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 float TWISTEFFECT_ANIMATION_MAX_TIME = 60.0f; ///< Animation time (every time finishes, checks if it needs to go again)
27 const float TWISTEFFECT_DEFAULT_DROPOFF = 0.7f; ///< Default drop off amount
28 const float TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_X = 720.0f; ///< Default drop off distance
29 const float TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_Y = 1280.0f; ///< Default drop off distance
31 // Hop Easing equation.
32 // Starts with a -ve cosine ranging from 0 to pi.
34 // Then finishes with a -ve cosine ranging from pi to 0
35 // 0......(RISE).....PI (SUSTAIN) PI.....(FALL)......0
36 // xxxxxxxxxxxxxxxxxxxxx
45 const float HOP_RISE(0.25f);
46 const float HOP_FALL(0.5f);
47 const float DELAY(0.5f);
49 float HopEasing(float progress)
51 // progress from 0.0 - HOP_RISE (go from 0.0 to 1.0)
52 if(progress < HOP_RISE)
54 return 0.5f - cosf(progress/HOP_RISE * Math::PI) * 0.5f;
57 progress += HOP_FALL - 1.0f;
59 // progress from 0.0 - HOP_FALL (go from 1.0 to 0.0)
62 return 0.5f + cosf(progress/HOP_FALL * Math::PI) * 0.5f;
65 // progress at plateau.
70 * Gets a property index. If the property doesn't already exist, then
71 * it will create the property.
72 * @param[in] handle The handle that owns or will own the property
73 * @param[in] name The name for this property
74 * @param[in] propertyValue The initial value for this property
75 * @return The property index for this property is returned.
77 Property::Index SafeRegisterProperty( Handle& handle, const std::string& name, Property::Value propertyValue )
79 Property::Index index = handle.GetPropertyIndex( name );
81 if(index == Property::INVALID_INDEX)
83 index = handle.RegisterProperty( name, propertyValue );
90 * Re-scales input value x from x0 - x1, to linearly map
91 * over the values y0 - y1. Values outside of this range
92 * will also conform to the trend (gradient) set.
93 * @param[in] x input X value
94 * @param[in] x0 input minimum bound
95 * @param[in] x1 input maximum bound
96 * @param[in] y0 output minimum bound
97 * @param[in] y1 output maximum bound
98 * @return The result of the mapping is returned.
100 float Rescale(float x, float x0, float x1, float y0, float y1)
102 return y0 + (y1 - y0) * (x - x0) / (x1-x0);
106 * Returns the value of x chasing target.
107 * returns a value of x which is closer to target.
108 * but limited by maxDelta. #
113 * result is 30.0f (x is 20.0f units closer to target)
114 * However, if x is already within maxDelta units
115 * of target, x will equal target.
120 * result is 50.0f (x was already within 20.0f units of target)
122 float Chase( float x, float target, float maxDelta )
124 float delta = target - x;
128 x = std::min( x + maxDelta, target );
132 x = std::max( x - maxDelta, target );
138 // constraints ////////////////////////////////////////////////////////////////
141 * ScrollTwistRotationConstraint
143 * Rotate constraint adjusts the angle of the Actors
144 * based on actor's world-position relative to the middle of the screen.
145 * When at middle of screen Angles on X and Y Axes is 0.
146 * When one screen away from the middle Angle is 90 degrees (pi/2)
148 struct ScrollDropoffTwistRotationConstraint
151 * Constraint constructor
152 * @param[in] angleSwing The amount the Actor should revolve in radians
153 * for a given page worth of distance.
155 ScrollDropoffTwistRotationConstraint(const Vector2& angleSwing, const Vector2& dropOff, const Vector2& distance, AlphaFunction function)
156 : mAngleSwing(angleSwing),
158 mDropOffDistance(distance),
159 mDropOffFunction(function)
164 * @param[in] current The current orientation of this Actor
165 * @param[in] actorPositionProperty The actor's world-position property
166 * @param[in] scrollOvershootXProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_X_PROPERTY_NAME)
167 * @param[in] scrollOvershootYProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_Y_PROPERTY_NAME)
168 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
169 * @return The new orientation of this Actor.
171 Quaternion operator()(const Quaternion& current,
172 const PropertyInput& actorPositionProperty,
173 const PropertyInput& scrollablePositionProperty,
174 const PropertyInput& scrollOvershootXProperty,
175 const PropertyInput& scrollOvershootYProperty,
176 const PropertyInput& pageSizeProperty,
177 const PropertyInput& activateProperty)
179 const Vector3& position = actorPositionProperty.GetVector3();
180 const Vector3& parentPosition = scrollablePositionProperty.GetVector3();
181 const Vector3& pageSize = pageSizeProperty.GetVector3();
182 const Vector2 overshoot(scrollOvershootXProperty.GetFloat(), scrollOvershootYProperty.GetFloat());
184 if(fabsf(overshoot.x) < Math::MACHINE_EPSILON_0 && fabsf(overshoot.y) < Math::MACHINE_EPSILON_0)
189 const float& activate = activateProperty.GetFloat();
191 if(activate < Math::MACHINE_EPSILON_0)
196 // get distance from centre of scrollable container
197 Vector2 distance = position.GetVectorXY() - parentPosition.GetVectorXY();
199 if( overshoot.x > 0.0f )
201 distance.x += pageSize.x * 0.5f;
205 distance.x -= pageSize.x * 0.5f;
207 distance.x = Clamp(fabsf(distance.x), 0.0f, mDropOffDistance.x);
209 if( overshoot.y > 0.0f )
211 distance.y += pageSize.y * 0.5f;
215 distance.y -= pageSize.y * 0.5f;
217 distance.y = Clamp(fabsf(distance.y), 0.0f, mDropOffDistance.y);
219 Vector2 angleMod = distance / mDropOffDistance;
222 angleMod.x = mDropOffFunction(angleMod.x);
223 angleMod.y = mDropOffFunction(angleMod.y);
225 angleMod = Vector2::ONE - (angleMod * mDropOff);
227 Vector2 angle = angleMod * mAngleSwing * overshoot;
229 Quaternion rotation = Quaternion(angle.x, Vector3::YAXIS) *
230 Quaternion(-angle.y, Vector3::XAXIS) *
236 const Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
237 const Vector2 mDropOff;
238 const Vector2 mDropOffDistance;
239 AlphaFunction mDropOffFunction;
243 * ScrollTwistRotationConstraint
245 * Rotate constraint adjusts the angle of the Actors
246 * based on actor's world-position relative to the middle of the screen.
247 * When at middle of screen Angles on X and Y Axes is 0.
248 * When one screen away from the middle Angle is 90 degrees (pi/2)
250 struct ScrollTwistRotationConstraint
253 * Constraint constructor
254 * @param[in] angleSwing The amount the Actor should revolve in radians
255 * for a given page worth of distance.
257 ScrollTwistRotationConstraint(const Vector2& angleSwing)
258 : mAngleSwing(angleSwing)
263 * @param[in] current The current orientation of this Actor
264 * @param[in] actorPositionProperty The actor's world-position property
265 * @param[in] scrollOvershootXProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_X_PROPERTY_NAME)
266 * @param[in] scrollOvershootYProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_Y_PROPERTY_NAME)
267 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
268 * @return The new orientation of this Actor.
270 Quaternion operator()(const Quaternion& current,
271 const PropertyInput& scrollOvershootXProperty,
272 const PropertyInput& scrollOvershootYProperty,
273 const PropertyInput& activateProperty)
275 const Vector2 overshoot(scrollOvershootXProperty.GetFloat(), scrollOvershootYProperty.GetFloat());
277 if(fabsf(overshoot.x) < Math::MACHINE_EPSILON_0 && fabsf(overshoot.y) < Math::MACHINE_EPSILON_0)
282 const float& activate = activateProperty.GetFloat();
284 if(activate < Math::MACHINE_EPSILON_0)
289 Quaternion rotation = Quaternion(overshoot.x * mAngleSwing.x, Vector3::YAXIS) *
290 Quaternion(-overshoot.y * mAngleSwing.y, Vector3::XAXIS) *
296 const Vector2 mAngleSwing;
300 * ScrollTwistPositionConstraint
302 * Position constraint adjusts the position of the Actors
303 * based on their parent page's position relative to the middle of the screen.
304 * When at middle of the screen the position is not altered.
305 * When one screen away from middle the position is rotated about it's origin + mAnchor
307 struct ScrollTwistPositionConstraint
310 * Constraint constructor
312 ScrollTwistPositionConstraint(float delayMin, float delayMax)
313 : mDelayMin(delayMin),
315 mCurrentDelayFactor(0.0f)
320 * @param[in] current The current position
321 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
322 * @param[in] effectReferenceProperty The point in the scroll-view where the user touched the screen
323 * @param[in] effectTimeProperty The current timer. Starting from 0.0 when scroll animation/dragging
324 * commences. Ensures that constraint is applied and processed every frame (to achieve the delay effect)
325 * @param[in] sizeProperty The size of the ScrollView.
326 * @return The new position of this Actor.
328 Vector3 operator()(const Vector3& current,
329 const PropertyInput& pagePositionProperty,
330 const PropertyInput& scrollPositionProperty,
331 const PropertyInput& effectReferenceProperty,
332 const PropertyInput& effectTimeProperty,
333 const PropertyInput& sizeProperty,
334 const PropertyInput& activateProperty)
336 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
337 const float& activate = activateProperty.GetFloat();
339 if(activate < Math::MACHINE_EPSILON_0)
341 mScrollPosition = scrollPosition;
342 return current + mScrollPosition;
344 const Vector3& pagePosition = pagePositionProperty.GetVector3();
345 const Vector3& referencePoint = effectReferenceProperty.GetVector3();
346 // Determine the relative position of the actor from the scrolling reference point.
347 // (the further away from the refernce, the longer the delay should be)
348 Vector3 relativePosition = pagePosition + current - referencePoint;
349 float f = relativePosition.x;
351 // f represents this absolute distance. Get as a relative distance and inverse exponential
352 // (as delay equation is has an exponential effect i.e. the closer delayFactor to 1.0f,
353 // the longer the delay would appear exponentially)
354 f = fabsf(f / sizeProperty.GetVector3().width);
355 f = std::min(f, 1.0f);
356 f = 1.0f - (1.0f - f) * (1.0f - f);
357 // at center delay factor is mDelayMin, at maximum (1.0) it is mDelayMax
358 f = Rescale(f, 0.0f, 1.0f, mDelayMin, mDelayMax);
360 // Will take 0.25s for current delay factor to equal target delay factor
361 // This prevents users quickly dragging from different points and noticing a jerk.
362 mCurrentDelayFactor = Chase( mCurrentDelayFactor, f, 4.0f/60.0f );
363 float delay = activate * mCurrentDelayFactor;
364 mScrollPosition = mScrollPosition * delay + scrollPosition * (1.0f-delay);
366 return current + mScrollPosition;
371 Vector3 mScrollPosition; ///< The current scroll position
374 float mCurrentDelayFactor;
379 * ScrollTwistScaleConstraint
381 * Scale constraint adjusts the scale of the Actors
382 * based on a supplied depth property value.
384 struct ScrollTwistScaleConstraint
387 * Constraint constructor
389 ScrollTwistScaleConstraint(float scaleAmount)
390 : mScaleAmount(scaleAmount)
395 * @param[in] current The current position
396 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
397 * @return The new position of this Actor.
399 Vector3 operator()(const Vector3& current,
400 const PropertyInput& depthProperty)
402 float depth = depthProperty.GetFloat();
404 return current * (1.0f - depth * mScaleAmount); // contract by mScaleAmount of original size.
412 } // unnamed namespace
423 ScrollViewTwistEffect::ScrollViewTwistEffect()
424 : mFlags(DefaultFlags),
425 mPropertyTime(Property::INVALID_INDEX),
427 mAdditionalEffects(false),
428 mPropertyReference(Property::INVALID_INDEX),
429 mPropertyActivate(Property::INVALID_INDEX),
430 mMinimumDistanceForShrink(Toolkit::ScrollViewTwistEffect::DEFAULT_MINIMUM_DISTANCE_FOR_SHRINK),
431 mMaxSwingAngle(Math::PI_2, Math::PI_2),
432 mDropOff(TWISTEFFECT_DEFAULT_DROPOFF, TWISTEFFECT_DEFAULT_DROPOFF),
433 mDropOffDistance(TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_X, TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_Y),
434 mDropOffFunction(NULL)
438 ScrollViewTwistEffect::~ScrollViewTwistEffect()
443 float ScrollViewTwistEffect::GetMinimumDistanceForShrink() const
445 return mMinimumDistanceForShrink;
448 void ScrollViewTwistEffect::SetMinimumDistanceForShrink(float distance)
450 mMinimumDistanceForShrink = distance;
453 void ScrollViewTwistEffect::EnableEffect(bool enableFlag)
455 mEnableEffect = enableFlag;
458 void ScrollViewTwistEffect::ApplyToActor(Actor child,
459 bool additionalEffects,
460 const Vector2& angleSwing,
465 mMaxSwingAngle = angleSwing;
466 mAdditionalEffects = additionalEffects;
467 mScaleFactor = scaleAmount;
468 mDelayMin = delayMin;
469 mDelayMax = delayMax;
470 if(mFlags & FlagDefaultDropOff)
472 Vector3 size = GetScrollView().GetCurrentSize();
473 // size may still be 0 if the effect is applied before scroll view hits the stage
474 if(size.x > Math::MACHINE_EPSILON_1)
476 mDropOffDistance.x = size.x;
478 if(size.y > Math::MACHINE_EPSILON_1)
480 mDropOffDistance.y = size.y;
483 if(scaleAmount > Math::MACHINE_EPSILON_0)
489 mFlags = mFlags & ~FlagScale;
491 if(mMaxSwingAngle.LengthSquared() > Math::MACHINE_EPSILON_0)
497 mFlags = mFlags & ~FlagTwist;
502 void ScrollViewTwistEffect::Apply(Actor child)
504 // Apply constraints to these actors //
505 Constraint constraint;
507 Toolkit::ScrollView scrollView = GetScrollView();
509 if( mFlags & FlagScale )
511 constraint = Constraint::New<Vector3>( Actor::SCALE,
512 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewTwistEffect::EFFECT_DEPTH ) ),
513 ScrollTwistScaleConstraint(mScaleFactor) );
514 constraint.SetRemoveAction( Constraint::Discard );
515 child.ApplyConstraint( constraint );
518 constraint = Constraint::New<Vector3>( Actor::POSITION,
519 ParentSource(Actor::POSITION),
520 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
521 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewTwistEffect::EFFECT_REFERENCE ) ),
522 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewTwistEffect::EFFECT_TIME ) ),
523 Source(scrollView, Actor::SIZE),
524 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewTwistEffect::EFFECT_ACTIVATE) ),
525 ScrollTwistPositionConstraint(mDelayMin, mDelayMax) );
526 constraint.SetRemoveAction( Constraint::Discard );
527 child.ApplyConstraint( constraint );
529 // use actor position to affect rotation
530 if(mFlags & FlagTwist)
532 if(mFlags & FlagDropOff)
534 constraint = Constraint::New<Quaternion>( Actor::ROTATION,
535 LocalSource(Actor::WORLD_POSITION),
536 Source(scrollView, Actor::WORLD_POSITION ),
537 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME ) ),
538 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME ) ),
539 Source(scrollView, Actor::SIZE ),
540 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewTwistEffect::EFFECT_ACTIVATE) ),
541 ScrollDropoffTwistRotationConstraint(mMaxSwingAngle, mDropOff, mDropOffDistance, mDropOffFunction) );
545 constraint = Constraint::New<Quaternion>( Actor::ROTATION,
546 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME ) ),
547 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME ) ),
548 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewTwistEffect::EFFECT_ACTIVATE) ),
549 ScrollTwistRotationConstraint(mMaxSwingAngle) );
551 constraint.SetRemoveAction( Constraint::Discard );
552 child.ApplyConstraint( constraint );
556 void ScrollViewTwistEffect::SetSwingDropOff(const Vector2& dropOff, const Vector2& distance, AlphaFunction function)
558 if( mDropOffDistance.LengthSquared() > Math::MACHINE_EPSILON_1 && mDropOff.LengthSquared() > Math::MACHINE_EPSILON_1 )
560 mFlags |= FlagDropOff;
562 mDropOffDistance = distance;
563 mDropOffFunction = function;
567 mFlags = mFlags & ~FlagDropOff;
569 // can no longer use default dop off
570 mFlags = mFlags & ~FlagDefaultDropOff;
573 void ScrollViewTwistEffect::OnAttach(Toolkit::ScrollView& scrollView)
575 // Create effect-time property if not already created.
576 if(mPropertyTime == Property::INVALID_INDEX)
578 mPropertyTime = SafeRegisterProperty( scrollView, Toolkit::ScrollViewTwistEffect::EFFECT_TIME, 0.0f );
579 mPropertyReference = SafeRegisterProperty( scrollView, Toolkit::ScrollViewTwistEffect::EFFECT_REFERENCE, Vector3::ZERO );
580 mPropertyDepth = SafeRegisterProperty( scrollView, Toolkit::ScrollViewTwistEffect::EFFECT_DEPTH, 0.0f);
581 mPropertyActivate = SafeRegisterProperty(scrollView,Toolkit::ScrollViewTwistEffect::EFFECT_ACTIVATE,1.0f);
584 // Connect to the scroll view signals
585 scrollView.ScrollStartedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollStart);
586 scrollView.SnapStartedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollSnap);
587 scrollView.ScrollUpdatedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollUpdate);
588 scrollView.ScrollCompletedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollComplete);
590 AttachActor(scrollView);
593 void ScrollViewTwistEffect::OnDetach(Toolkit::ScrollView& scrollView)
595 scrollView.ScrollStartedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollStart);
596 scrollView.SnapStartedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollSnap);
597 scrollView.ScrollUpdatedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollUpdate);
598 scrollView.ScrollCompletedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollComplete);
602 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
608 void ScrollViewTwistEffect::AttachActor(Actor actor)
613 void ScrollViewTwistEffect::DetachActor(Actor actor)
615 // TODO: remove the specific constraint defined in AttachActor (and possibly
616 // unregister property) - neither functionality exists in Dali.
619 void ScrollViewTwistEffect::ContinueAnimation(float endTime)
621 // continue animating
624 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
628 Actor scrollView = GetScrollView();
630 mAnimation = Animation::New(TWISTEFFECT_ANIMATION_MAX_TIME);
631 mAnimation.AnimateTo( Property(scrollView, mPropertyTime), endTime, AlphaFunctions::Linear );
632 mAnimation.FinishedSignal().Connect(this, &ScrollViewTwistEffect::OnAnimationFinished);
636 void ScrollViewTwistEffect::OnScrollStart( const Vector3& position )
638 if(mActivateAnimation)
640 // if the animation after Scroll complete not terminate before another scroll action, stop the animation before start again
641 mActivateAnimation.Stop();
642 mActivateAnimation.Clear();
643 mActivateAnimation = NULL;
646 GetScrollView().SetProperty(mPropertyTime, 0.0f);
649 GetScrollView().SetProperty(mPropertyActivate, 1.0f);
653 GetScrollView().SetProperty(mPropertyActivate, 0.0f);
655 GetScrollView().SetProperty(mPropertyReference, position);
657 ContinueAnimation(TWISTEFFECT_ANIMATION_MAX_TIME);
660 void ScrollViewTwistEffect::OnScrollUpdate( const Vector3& position )
665 void ScrollViewTwistEffect::OnScrollComplete( const Vector3& position )
669 OnActivateAnimationFinished(mAnimation);
672 Actor scrollView = GetScrollView();
673 scrollView.SetProperty(mPropertyActivate, 1.0f);
674 mActivateAnimation = Animation::New(DELAY);
675 mActivateAnimation.AnimateTo( Property(scrollView, mPropertyActivate), 0.0f, AlphaFunctions::Linear);
676 mActivateAnimation.FinishedSignal().Connect(this, &ScrollViewTwistEffect::OnActivateAnimationFinished);
677 mActivateAnimation.Play();
680 void ScrollViewTwistEffect::OnScrollSnap( const Toolkit::ScrollView::SnapEvent& event )
682 // If a Flicking snap is occuring and the distance is more than mMinimumDistanceForShrink
683 // then animate depth effect i.e. shrink actors and then bring back in to regular size.
684 // NOTE: ScrollView Snap returns a value opposite of GetCurrentScrollPosition
685 // i.e. if you've "scrolled 100 pixels right" (so content on screen has shifted 100 pixels left)
686 // then GetCurrentScrollPosition returns a positive value (100.0f, 0.0f) (position of where you're
687 // look, not where content has been moved to).
688 // event.position returns a negative value (-100.0f, 0.0f)
689 // Would be a good idea to change SnapEvent in the API so it reflects GetCurrentScrollPosition.
690 // TODO: Change scroll-view API, check if anything uses SnapEvent and change them correspondingly
691 Vector3 targetScrollPosition(-event.position);
693 Vector3 delta = targetScrollPosition - GetScrollView().GetCurrentScrollPosition();
695 if(event.type==Flick && delta.Length() > mMinimumDistanceForShrink)
697 Actor scrollView = GetScrollView();
699 Animation animation = Animation::New(event.duration);
700 animation.AnimateTo( Property(scrollView, mPropertyDepth), 1.0f, HopEasing);
705 void ScrollViewTwistEffect::OnAnimationFinished( Animation& animation )
707 // still unstable, so continue animating.
708 // TODO: Requires an instability check to ensure time animation finishes when delay is
709 // less noticeable. i.e. all present scrollPositions are approx the same as mScrollPosition in constraints.
710 // best solution for this is to switch to a single history vector of scroll position, and compare if
711 // position has not deviated >= 0.5 pixel for the past 1 second.
712 float endTime = GetScrollView().GetProperty<float>(mPropertyTime) + TWISTEFFECT_ANIMATION_MAX_TIME;
713 ContinueAnimation(endTime);
716 void ScrollViewTwistEffect::OnActivateAnimationFinished( Animation& animation )
720 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
727 } // namespace Internal
729 } // namespace Toolkit