From c0e17f6df571c57bbeca807281ac78ef45edfdf4 Mon Sep 17 00:00:00 2001 From: Daria Volvenkova Date: Fri, 22 Apr 2016 02:22:41 +0300 Subject: [PATCH] Kinetic scroll. --- drape_frontend/animation_system.cpp | 12 ++++ drape_frontend/animation_system.h | 4 +- drape_frontend/kinetic_scroller.cpp | 87 +++++++++++++++++++++------- drape_frontend/kinetic_scroller.hpp | 4 +- drape_frontend/user_event_stream.cpp | 10 +++- drape_frontend/user_event_stream.hpp | 2 +- 6 files changed, 91 insertions(+), 28 deletions(-) diff --git a/drape_frontend/animation_system.cpp b/drape_frontend/animation_system.cpp index 9dbd213eac..b6a38dc75b 100644 --- a/drape_frontend/animation_system.cpp +++ b/drape_frontend/animation_system.cpp @@ -813,6 +813,18 @@ void SequenceAnimation::Advance(double elapsedSeconds) } } +void SequenceAnimation::Finish() +{ + for (auto & anim : m_animations) + { + anim->Finish(); + AnimationSystem::Instance().SaveAnimationResult(*anim); + } + m_animations.clear(); + ObtainObjectProperties(); + Animation::Finish(); +} + void SequenceAnimation::ObtainObjectProperties() { m_objects.clear(); diff --git a/drape_frontend/animation_system.h b/drape_frontend/animation_system.h index 2865a2030e..2a72cf6830 100644 --- a/drape_frontend/animation_system.h +++ b/drape_frontend/animation_system.h @@ -24,7 +24,8 @@ public: MapScale, MapFollow, MapPerspective, - Arrow + Arrow, + KineticScroll }; enum Object @@ -460,6 +461,7 @@ public: void OnFinish() override; void Advance(double elapsedSeconds) override; + void Finish() override; private: void ObtainObjectProperties(); diff --git a/drape_frontend/kinetic_scroller.cpp b/drape_frontend/kinetic_scroller.cpp index 745c30dc6a..7d3b1484c7 100644 --- a/drape_frontend/kinetic_scroller.cpp +++ b/drape_frontend/kinetic_scroller.cpp @@ -25,39 +25,84 @@ double CalculateKineticMaxSpeed(ScreenBase const & modelView) return (kKineticMaxSpeedStart * lerpCoef + kKineticMaxSpeedEnd * (1.0 - lerpCoef)) * VisualParams::Instance().GetVisualScale(); } -class KineticScrollAnimation : public BaseModelViewAnimation +class KineticScrollAnimation : public Animation { public: // startRect - mercator visible on screen rect in moment when user release fingers. // direction - mercator space direction of moving. length(direction) - mercator distance on wich map will be offset. - KineticScrollAnimation(m2::AnyRectD const & startRect, m2::PointD const & direction, double duration) - : BaseModelViewAnimation(duration) - , m_targetCenter(startRect.GlobalCenter() + direction) - , m_angle(startRect.Angle()) - , m_localRect(startRect.GetLocalRect()) + KineticScrollAnimation(m2::PointD const & startPos, m2::PointD const & direction, double duration) + : Animation(true /* couldBeInterrupted */, true /* couldBeMixed */) + , m_endPos(startPos + direction) , m_direction(direction) + , m_duration(duration) + , m_elapsedTime(0.0) { + m_objects.insert(Animation::MapPlane); + m_properties.insert(Animation::Position); } - ModelViewAnimationType GetType() const override { return ModelViewAnimationType::KineticScroll; } + Animation::Type GetType() const override { return Animation::KineticScroll; } - m2::AnyRectD GetCurrentRect(ScreenBase const & screen) const override + TAnimObjects const & GetObjects() const override { + return m_objects; + } + + bool HasObject(TObject object) const override + { + return m_objects.find(object) != m_objects.end(); + } + + TObjectProperties const & GetProperties(TObject object) const override + { + ASSERT(HasObject(object), ()); + return m_properties; + } + + bool HasProperty(TObject object, TProperty property) const override + { + return HasObject(object) && m_properties.find(property) != m_properties.end(); + } + + void SetMaxDuration(double maxDuration) override + { + if (m_duration > maxDuration) + m_duration = maxDuration; + } + + double GetDuration() const override { return m_duration; } + bool IsFinished() const override { return m_elapsedTime >= m_duration; } + + void Advance(double elapsedSeconds) override + { + m_elapsedTime += elapsedSeconds; + } + void Finish() override { + m_elapsedTime = m_duration; + Animation::Finish(); + } + + bool GetProperty(TObject object, TProperty property, PropertyValue & value) const override + { + ASSERT(HasProperty(object, property), ()); // Current position = target position - amplutide * e ^ (elapsed / duration). // We calculate current position not based on start position, but based on target position. - return m2::AnyRectD(m_targetCenter - m_direction * exp(-kKineticFadeoff * GetT()), m_angle, m_localRect); - } - - m2::AnyRectD GetTargetRect(ScreenBase const & screen) const override - { - return GetCurrentRect(screen); + value.m_valuePointD = m_endPos - m_direction * exp(-kKineticFadeoff * GetT()); + return true; } private: - m2::PointD m_targetCenter; - ang::AngleD m_angle; - m2::RectD m_localRect; + double GetT() const + { + return IsFinished() ? 1.0 : m_elapsedTime / m_duration; + } + + m2::PointD m_endPos; m2::PointD m_direction; + double m_duration; + double m_elapsedTime; + TAnimObjects m_objects; + TObjectProperties m_properties; }; KineticScroller::KineticScroller() @@ -116,11 +161,11 @@ void KineticScroller::CancelGrab() m_direction = m2::PointD::Zero(); } -drape_ptr KineticScroller::CreateKineticAnimation(ScreenBase const & modelView) +drape_ptr KineticScroller::CreateKineticAnimation(ScreenBase const & modelView) { static double kVelocityThreshold = kKineticThreshold * VisualParams::Instance().GetVisualScale(); if (m_direction.Length() < kVelocityThreshold) - return drape_ptr(); + return drape_ptr(); // Before we start animation we have to convert length(m_direction) from pixel space to mercator space. m2::PointD center = m_lastRect.GlobalCenter(); @@ -129,9 +174,9 @@ drape_ptr KineticScroller::CreateKineticAnimation(Screen m2::PointD const glbDirection = m_direction.Normalize() * glbLength; m2::PointD const targetCenter = center + glbDirection; if (!df::GetWorldRect().IsPointInside(targetCenter)) - return drape_ptr(); + return drape_ptr(); - return make_unique_dp(m_lastRect, glbDirection, kKineticDuration); + return make_unique_dp(center, glbDirection, kKineticDuration); } } // namespace df diff --git a/drape_frontend/kinetic_scroller.hpp b/drape_frontend/kinetic_scroller.hpp index 2d9de55aed..6353158f1f 100644 --- a/drape_frontend/kinetic_scroller.hpp +++ b/drape_frontend/kinetic_scroller.hpp @@ -1,6 +1,6 @@ #pragma once -#include "animation/model_view_animation.hpp" +#include "animation_system.h" #include "drape/pointers.hpp" @@ -18,7 +18,7 @@ public: bool IsActive() const; void GrabViewRect(ScreenBase const & modelView, double timeStamp); void CancelGrab(); - drape_ptr CreateKineticAnimation(ScreenBase const & modelView); + drape_ptr CreateKineticAnimation(ScreenBase const & modelView); private: double m_lastTimestamp; diff --git a/drape_frontend/user_event_stream.cpp b/drape_frontend/user_event_stream.cpp index a4aeea8aa1..077b3434cc 100644 --- a/drape_frontend/user_event_stream.cpp +++ b/drape_frontend/user_event_stream.cpp @@ -953,9 +953,13 @@ bool UserEventStream::EndDrag(Touch const & t, bool cancelled) if (m_kineticScrollEnabled && m_kineticTimer.TimeElapsedAs().count() >= kKineticDelayMs) { - m_animation = m_scroller.CreateKineticAnimation(m_navigator.Screen()); - if (m_listener) - m_listener->OnAnimationStarted(make_ref(m_animation)); + drape_ptr anim = m_scroller.CreateKineticAnimation(m_navigator.Screen()); + if (anim != nullptr) + { + AnimationSystem::Instance().AddAnimation(move(anim), true /* force */); + if (m_listener) + m_listener->OnAnimationStarted(nullptr); + } m_scroller.CancelGrab(); return false; } diff --git a/drape_frontend/user_event_stream.hpp b/drape_frontend/user_event_stream.hpp index 8c849595d6..fc26f7d080 100644 --- a/drape_frontend/user_event_stream.hpp +++ b/drape_frontend/user_event_stream.hpp @@ -376,7 +376,7 @@ private: drape_ptr m_animation; - bool m_perspectiveAnimation; + bool m_perspectiveAnimation = false; unique_ptr m_pendingEvent; double m_discardedFOV = 0.0; double m_discardedAngle = 0.0;