From 8412a44ed713f225f6b0c5f94594d15807e5e3ab Mon Sep 17 00:00:00 2001 From: Daria Volvenkova Date: Thu, 21 Apr 2016 02:39:00 +0300 Subject: [PATCH] Perspective animation. --- drape_frontend/animation_system.cpp | 225 ++++++++++++++++++++++++--- drape_frontend/animation_system.h | 89 +++++++++-- drape_frontend/frontend_renderer.cpp | 5 +- drape_frontend/user_event_stream.cpp | 128 +++++++-------- drape_frontend/user_event_stream.hpp | 8 +- 5 files changed, 348 insertions(+), 107 deletions(-) diff --git a/drape_frontend/animation_system.cpp b/drape_frontend/animation_system.cpp index 747806cfb7..f52e753446 100644 --- a/drape_frontend/animation_system.cpp +++ b/drape_frontend/animation_system.cpp @@ -3,9 +3,6 @@ #include "base/logging.hpp" -#include "boost/variant/variant.hpp" -#include "boost/variant/get.hpp" - namespace df { @@ -75,6 +72,11 @@ void Interpolator::Advance(double elapsedSeconds) m_elapsedTime += elapsedSeconds; } +void Interpolator::Finish() +{ + m_elapsedTime = m_duration + m_delay + 1.0; +} + void Interpolator::SetMaxDuration(double maxDuration) { m_duration = min(m_duration, maxDuration); @@ -172,6 +174,12 @@ void PositionInterpolator::Advance(double elapsedSeconds) m_position = InterpolatePoint(m_startPosition, m_endPosition, GetT()); } +void PositionInterpolator::Finish() +{ + TBase::Finish(); + m_position = m_endPosition; +} + // static double AngleInterpolator::GetRotateDuration(double startAngle, double endAngle) { @@ -199,6 +207,12 @@ void AngleInterpolator::Advance(double elapsedSeconds) m_angle = InterpolateDouble(m_startAngle, m_endAngle, GetT()); } +void AngleInterpolator::Finish() +{ + TBase::Finish(); + m_angle = m_endAngle; +} + // static double ScaleInterpolator::GetScaleDuration(double startScale, double endScale) { @@ -230,6 +244,12 @@ void ScaleInterpolator::Advance(double elapsedSeconds) m_scale = InterpolateDouble(m_startScale, m_endScale, GetT()); } +void ScaleInterpolator::Finish() +{ + TBase::Finish(); + m_scale = m_endScale; +} + MapLinearAnimation::MapLinearAnimation(m2::PointD const & startPos, m2::PointD const & endPos, double startAngle, double endAngle, double startScale, double endScale, ScreenBase const & convertor) @@ -296,6 +316,17 @@ void MapLinearAnimation::Advance(double elapsedSeconds) m_positionInterpolator->Advance(elapsedSeconds); } +void MapLinearAnimation::Finish() +{ + if (m_angleInterpolator != nullptr) + m_angleInterpolator->Finish(); + if (m_scaleInterpolator != nullptr) + m_scaleInterpolator->Finish(); + if (m_positionInterpolator != nullptr) + m_positionInterpolator->Finish(); + Animation::Finish(); +} + void MapLinearAnimation::SetMaxDuration(double maxDuration) { if (m_angleInterpolator != nullptr) @@ -325,7 +356,7 @@ bool MapLinearAnimation::IsFinished() const && (m_positionInterpolator == nullptr || m_positionInterpolator->IsFinished())); } -Animation::TPropValue MapLinearAnimation::GetProperty(TObject object, TProperty property) const +Animation::PropertyValue MapLinearAnimation::GetProperty(TObject object, TProperty property) const { ASSERT(object == Animation::MapPlane, ()); @@ -381,6 +412,12 @@ void MapScaleAnimation::Advance(double elapsedSeconds) m_scaleInterpolator->Advance(elapsedSeconds); } +void MapScaleAnimation::Finish() +{ + m_scaleInterpolator->Finish(); + Animation::Finish(); +} + void MapScaleAnimation::SetMaxDuration(double maxDuration) { m_scaleInterpolator->SetMaxDuration(maxDuration); @@ -396,7 +433,7 @@ bool MapScaleAnimation::IsFinished() const return m_scaleInterpolator->IsFinished(); } -Animation::TPropValue MapScaleAnimation::GetProperty(TObject object, TProperty property) const +Animation::PropertyValue MapScaleAnimation::GetProperty(TObject object, TProperty property) const { if (property == Animation::Position) @@ -453,6 +490,14 @@ void MapFollowAnimation::Advance(double elapsedSeconds) m_pixelPosInterpolator->Advance(elapsedSeconds); } +void MapFollowAnimation::Finish() +{ + m_angleInterpolator->Finish(); + m_scaleInterpolator->Finish(); + m_pixelPosInterpolator->Finish(); + Animation::Finish(); +} + void MapFollowAnimation::SetMaxDuration(double maxDuration) { m_angleInterpolator->SetMaxDuration(maxDuration); @@ -479,7 +524,7 @@ bool MapFollowAnimation::IsFinished() const && (m_scaleInterpolator == nullptr || m_scaleInterpolator->IsFinished())); } -Animation::TPropValue MapFollowAnimation::GetProperty(TObject object, TProperty property) const +Animation::PropertyValue MapFollowAnimation::GetProperty(TObject object, TProperty property) const { if (property == Animation::Position) @@ -503,6 +548,66 @@ Animation::TPropValue MapFollowAnimation::GetProperty(TObject object, TProperty return 0.0; } +PerspectiveSwitchAnimation::PerspectiveSwitchAnimation(double startAngle, double endAngle) + : Animation(false, false) +{ + m_angleInterpolator = make_unique_dp(startAngle, endAngle); + m_objects.insert(Animation::MapPlane); + m_properties.insert(Animation::AnglePerspective); +} + +Animation::TObjectProperties const & PerspectiveSwitchAnimation::GetProperties(TObject object) const +{ + ASSERT(object == Animation::MapPlane, ()); + return m_properties; +} + +bool PerspectiveSwitchAnimation::HasProperty(TObject object, TProperty property) const +{ + return HasObject(object) && m_properties.find(property) != m_properties.end(); +} + +void PerspectiveSwitchAnimation::Advance(double elapsedSeconds) +{ + m_angleInterpolator->Advance(elapsedSeconds); +} + +void PerspectiveSwitchAnimation::Finish() +{ + m_angleInterpolator->Finish(); + Animation::Finish(); +} + +void PerspectiveSwitchAnimation::SetMaxDuration(double maxDuration) +{ + m_angleInterpolator->SetMaxDuration(maxDuration); +} + +double PerspectiveSwitchAnimation::GetDuration() const +{ + return m_angleInterpolator->GetDuration(); +} + +bool PerspectiveSwitchAnimation::IsFinished() const +{ + return m_angleInterpolator->IsFinished(); +} + +Animation::PropertyValue PerspectiveSwitchAnimation::GetProperty(TObject object, TProperty property) const +{ + ASSERT(object == Animation::MapPlane, ()); + + switch (property) + { + case Animation::AnglePerspective: + return m_angleInterpolator->GetAngle(); + break; + default: + ASSERT(!"Wrong property", ()); + } + + return 0.0; +} Animation::TObjectProperties const & ParallelAnimation::GetProperties(TObject object) const { @@ -557,6 +662,13 @@ void ParallelAnimation::Advance(double elapsedSeconds) } } +void ParallelAnimation::Finish() +{ + for (auto & anim : m_animations) + anim->Finish(); + Animation::Finish(); +} + Animation::TAnimObjects const & SequenceAnimation::GetObjects() const { ASSERT(!m_animations.empty(), ()); @@ -615,16 +727,19 @@ AnimationSystem::AnimationSystem() } -m2::AnyRectD AnimationSystem::GetRect(ScreenBase const & currentScreen) +double AnimationSystem::GetPerspectiveAngle(double currentAngle) +{ + return GetProperty(Animation::MapPlane, Animation::AnglePerspective, currentAngle).m_valueD; +} + +m2::AnyRectD AnimationSystem::GetRect(ScreenBase const & currentScreen, bool & viewportChanged) { const Animation::TObject obj = Animation::MapPlane; + viewportChanged |= m_lastScreen != nullptr && (m_lastScreen->isPerspective() != currentScreen.isPerspective()); m_lastScreen = make_unique_dp(currentScreen); - double scale = boost::get( - GetProperty(obj, Animation::Scale, currentScreen.GetScale())); - double angle = boost::get( - GetProperty(obj, Animation::Angle, currentScreen.GetAngle())); - m2::PointD pos = boost::get( - GetProperty(obj, Animation::Position, currentScreen.GlobalRect().GlobalZero())); + double scale = GetProperty(obj, Animation::Scale, currentScreen.GetScale()).m_valueD; + double angle = GetProperty(obj, Animation::Angle, currentScreen.GetAngle()).m_valueD; + m2::PointD pos = GetProperty(obj, Animation::Position, currentScreen.GlobalRect().GlobalZero()).m_valuePointD; m2::RectD rect = currentScreen.PixelRect(); rect.Offset(-rect.Center()); rect.Scale(scale); @@ -633,12 +748,13 @@ m2::AnyRectD AnimationSystem::GetRect(ScreenBase const & currentScreen) bool AnimationSystem::AnimationExists(Animation::TObject object) const { - if (m_animationChain.empty()) - return false; - for (auto const & anim : m_animationChain.front()) + if (!m_animationChain.empty()) { - if (anim->HasObject(object)) - return true; + for (auto const & anim : m_animationChain.front()) + { + if (anim->HasObject(object)) + return true; + } } for (auto it = m_propertyCache.begin(); it != m_propertyCache.end(); ++it) { @@ -692,12 +808,65 @@ void AnimationSystem::AddAnimation(drape_ptr && animation, bool force void AnimationSystem::PushAnimation(drape_ptr && animation) { - animation->OnStart(); + if (m_animationChain.empty()) + animation->OnStart(); + TAnimationList list; list.emplace_back(move(animation)); + m_animationChain.emplace_back(move(list)); } +void AnimationSystem::FinishAnimations(Animation::Type type, bool rewind) +{ + if (m_animationChain.empty()) + return; + + TAnimationList & frontList = m_animationChain.front(); + for (auto it = frontList.begin(); it != frontList.end();) + { + auto & anim = *it; + if (anim->GetType() == type) + { + if (rewind) + anim->Finish(); + SaveAnimationResult(*anim); + it = frontList.erase(it); + } + else + { + ++it; + } + } + if (frontList.empty()) + StartNextAnimations(); +} + +void AnimationSystem::FinishObjectAnimations(Animation::TObject object, bool rewind) +{ + if (m_animationChain.empty()) + return; + + TAnimationList & frontList = m_animationChain.front(); + for (auto it = frontList.begin(); it != frontList.end();) + { + auto & anim = *it; + if (anim->HasObject(object)) + { + if (rewind) + anim->Finish(); + SaveAnimationResult(*anim); + it = frontList.erase(it); + } + else + { + ++it; + } + } + if (frontList.empty()) + StartNextAnimations(); +} + void AnimationSystem::Advance(double elapsedSeconds) { if (m_animationChain.empty()) @@ -719,9 +888,11 @@ void AnimationSystem::Advance(double elapsedSeconds) ++it; } } + if (frontList.empty()) + StartNextAnimations(); } -Animation::TPropValue AnimationSystem::GetProperty(Animation::TObject object, Animation::TProperty property, Animation::TPropValue current) const +Animation::PropertyValue AnimationSystem::GetProperty(Animation::TObject object, Animation::TProperty property, Animation::PropertyValue current) const { if (!m_animationChain.empty()) { @@ -734,7 +905,7 @@ Animation::TPropValue AnimationSystem::GetProperty(Animation::TObject object, An auto it = m_propertyCache.find(make_pair(object, property)); if (it != m_propertyCache.end()) { - Animation::TPropValue value(it->second); + Animation::PropertyValue value(it->second); m_propertyCache.erase(it); return value; } @@ -752,4 +923,16 @@ void AnimationSystem::SaveAnimationResult(Animation const & animation) } } +void AnimationSystem::StartNextAnimations() +{ + m_animationChain.pop_front(); + if (m_animationChain.empty()) + return; + for (auto & anim : m_animationChain.front()) + { + // TODO: use propertyCache to load start values to the next animations + anim->OnStart(); + } +} + } // namespace df diff --git a/drape_frontend/animation_system.h b/drape_frontend/animation_system.h index c3b6238794..9f03206ebb 100644 --- a/drape_frontend/animation_system.h +++ b/drape_frontend/animation_system.h @@ -10,8 +10,6 @@ #include "std/deque.hpp" #include "std/noncopyable.hpp" -#include "boost/variant/variant_fwd.hpp" - namespace df { @@ -40,22 +38,53 @@ public: { Position, Scale, - Angle + Angle, + AnglePerspective + }; + + enum PropertyValueType + { + ValueD, + ValuePointD + }; + + struct PropertyValue + { + PropertyValue() + { + } + + PropertyValue(double value) + : m_type(ValueD), + m_valueD(value) + {} + + PropertyValue(m2::PointD value) + : m_type(ValuePointD), + m_valuePointD(value) + {} + + PropertyValueType m_type; + union + { + m2::PointD m_valuePointD; + double m_valueD; + }; }; using TObject = uint32_t; using TProperty = uint32_t; - using TPropValue = boost::variant; using TAnimObjects = set; using TObjectProperties = set; + using TAction = function; Animation(bool couldBeInterrupted, bool couldBeMixed) : m_couldBeInterrupted(couldBeInterrupted) , m_couldBeMixed(couldBeMixed) {} - virtual void OnStart() {} - virtual void OnFinish() {} + virtual void OnStart() {if (m_onStartAction != nullptr) m_onStartAction(*this);} + virtual void OnFinish() {if (m_onFinishAction != nullptr) m_onFinishAction(*this);} virtual void Interrupt() {} virtual Type GetType() const = 0; @@ -70,8 +99,13 @@ public: virtual bool IsFinished() const = 0; virtual void Advance(double elapsedSeconds) = 0; + virtual void Finish() { OnFinish(); } - virtual TPropValue GetProperty(TObject object, TProperty property) const = 0; + virtual PropertyValue GetProperty(TObject object, TProperty property) const = 0; + + void SetOnStartAction(TAction const & action) { m_onStartAction = action; } + void SetOnFinishAction(TAction const & action) { m_onFinishAction = action; } + void SetOnInterruptAction(TAction const & action) { m_onInterruptAction = action; } bool CouldBeInterrupted() const { return m_couldBeInterrupted; } bool CouldBeMixed() const { return m_couldBeMixed; } @@ -79,6 +113,9 @@ public: bool CouldBeMixedWith(Animation const & animation); protected: + TAction m_onStartAction; + TAction m_onFinishAction; + TAction m_onInterruptAction; bool m_couldBeInterrupted; bool m_couldBeMixed; }; @@ -91,6 +128,7 @@ public: bool IsFinished() const; virtual void Advance(double elapsedSeconds); + virtual void Finish(); void SetMaxDuration(double maxDuration); void SetMinDuration(double minDuration); double GetDuration() const; @@ -121,6 +159,7 @@ public: static double GetPixelMoveDuration(m2::PointD const & startPosition, m2::PointD const & endPosition, m2::RectD const & pixelRect); void Advance(double elapsedSeconds) override; + void Finish() override; virtual m2::PointD GetPosition() const { return m_position; } private: @@ -140,6 +179,7 @@ public: static double GetScaleDuration(double startScale, double endScale); void Advance(double elapsedSeconds) override; + void Finish() override; virtual double GetScale() const { return m_scale; } private: @@ -159,6 +199,7 @@ public: static double GetRotateDuration(double startAngle, double endAngle); void Advance(double elapsedSeconds) override; + void Finish() override; virtual double GetAngle() const { return m_angle; } private: @@ -195,6 +236,7 @@ public: bool HasProperty(TObject object, TProperty property) const override; void Advance(double elapsedSeconds) override; + void Finish() override; private: drape_ptr m_positionInterpolator; @@ -205,9 +247,8 @@ private: class PerspectiveSwitchAnimation : public Animation { - PerspectiveSwitchAnimation() - : Animation(false, false) - {} +public: + PerspectiveSwitchAnimation(double startAngle, double endAngle); Animation::Type GetType() const override { return Animation::MapPerspective; } @@ -223,6 +264,13 @@ class PerspectiveSwitchAnimation : public Animation bool HasProperty(TObject object, TProperty property) const override; void Advance(double elapsedSeconds) override; + void Finish() override; + + void SetMaxDuration(double maxDuration) override; + double GetDuration() const override; + bool IsFinished() const override; + + PropertyValue GetProperty(TObject object, TProperty property) const override; private: drape_ptr m_angleInterpolator; @@ -256,12 +304,13 @@ public: bool HasProperty(TObject object, TProperty property) const override; void Advance(double elapsedSeconds) override; + void Finish() override; void SetMaxDuration(double maxDuration) override; double GetDuration() const override; bool IsFinished() const override; - TPropValue GetProperty(TObject object, TProperty property) const override; + PropertyValue GetProperty(TObject object, TProperty property) const override; private: drape_ptr m_angleInterpolator; @@ -291,12 +340,13 @@ public: bool HasProperty(TObject object, TProperty property) const override; void Advance(double elapsedSeconds) override; + void Finish() override; void SetMaxDuration(double maxDuration) override; double GetDuration() const override; bool IsFinished() const override; - TPropValue GetProperty(TObject object, TProperty property) const override; + PropertyValue GetProperty(TObject object, TProperty property) const override; private: drape_ptr m_scaleInterpolator; @@ -329,12 +379,13 @@ public: bool HasProperty(TObject object, TProperty property) const override; void Advance(double elapsedSeconds) override; + void Finish() override; void SetMaxDuration(double maxDuration) override; double GetDuration() const override; bool IsFinished() const override; - TPropValue GetProperty(TObject object, TProperty property) const override; + PropertyValue GetProperty(TObject object, TProperty property) const override; private: drape_ptr m_scaleInterpolator; @@ -388,6 +439,7 @@ public: void OnFinish() override; void Advance(double elapsedSeconds) override; + void Finish() override; private: list> m_animations; @@ -400,27 +452,32 @@ class AnimationSystem : private noncopyable public: static AnimationSystem & Instance(); - m2::AnyRectD GetRect(ScreenBase const & currentScreen); + m2::AnyRectD GetRect(ScreenBase const & currentScreen, bool & viewportChanged); + double GetPerspectiveAngle(double currentAngle); bool AnimationExists(Animation::TObject object) const; void AddAnimation(drape_ptr && animation, bool force); void PushAnimation(drape_ptr && animation); + void FinishAnimations(Animation::Type type, bool rewind); + void FinishObjectAnimations(Animation::TObject object, bool rewind); + void Advance(double elapsedSeconds); ScreenBase const & GetLastScreen() { return *m_lastScreen.get(); } private: - Animation::TPropValue GetProperty(Animation::TObject object, Animation::TProperty property, Animation::TPropValue current) const; + Animation::PropertyValue GetProperty(Animation::TObject object, Animation::TProperty property, Animation::PropertyValue current) const; void SaveAnimationResult(Animation const & animation); + void StartNextAnimations(); AnimationSystem(); private: using TAnimationList = list>; using TAnimationChain = deque; - using TPropertyCache = map, Animation::TPropValue>; + using TPropertyCache = map, Animation::PropertyValue>; TAnimationChain m_animationChain; mutable TPropertyCache m_propertyCache; diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index a8acdd8f2a..d5c54218c6 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -747,14 +747,15 @@ void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLeve double rotationAngle, double angleFOV) { + m_myPositionController->ActivateRouting(!m_enablePerspectiveInNavigation ? preferredZoomLevel + : preferredZoomLevelIn3d); + if (m_enablePerspectiveInNavigation) { bool immediatelyStart = !m_myPositionController->IsRotationAvailable(); AddUserEvent(EnablePerspectiveEvent(rotationAngle, angleFOV, true /* animated */, immediatelyStart)); } - m_myPositionController->ActivateRouting(!m_enablePerspectiveInNavigation ? preferredZoomLevel - : preferredZoomLevelIn3d); m_overlayTree->SetFollowingMode(true); } diff --git a/drape_frontend/user_event_stream.cpp b/drape_frontend/user_event_stream.cpp index b797bcb385..43491875ce 100644 --- a/drape_frontend/user_event_stream.cpp +++ b/drape_frontend/user_event_stream.cpp @@ -145,7 +145,7 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChange, bool & modelViewChange = !events.empty() || m_state == STATE_SCALE || m_state == STATE_DRAG; for (UserEvent const & e : events) { - if (m_perspectiveAnimation != nullptr && FilterEventWhile3dAnimation(e.m_type)) + if (m_perspectiveAnimation && FilterEventWhile3dAnimation(e.m_type)) continue; bool breakAnim = false; @@ -167,7 +167,7 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChange, bool & TouchCancel(m_touches); break; case UserEvent::EVENT_SET_RECT: - if (m_perspectiveAnimation != nullptr) + if (m_perspectiveAnimation) { m_pendingEvent.reset(new UserEvent(e.m_rectEvent)); break; @@ -199,26 +199,20 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChange, bool & } break; case UserEvent::EVENT_FOLLOW_AND_ROTATE: - m_pendingPerspective = false; breakAnim = SetFollowAndRotate(e.m_followAndRotate.m_userPos, e.m_followAndRotate.m_pixelZero, e.m_followAndRotate.m_azimuth, e.m_followAndRotate.m_preferredZoomLevel, e.m_followAndRotate.m_isAnim); TouchCancel(m_touches); break; case UserEvent::EVENT_ENABLE_PERSPECTIVE: - if (!e.m_enable3dMode.m_immediatelyStart) - { - m_pendingPerspective = true; - m_pendingEvent.reset(new UserEvent(e.m_enable3dMode)); - } - else - SetEnable3dMode(e.m_enable3dMode.m_rotationAngle, e.m_enable3dMode.m_angleFOV, - e.m_enable3dMode.m_isAnim, viewportChanged); + SetEnable3dMode(e.m_enable3dMode.m_rotationAngle, e.m_enable3dMode.m_angleFOV, + e.m_enable3dMode.m_isAnim, e.m_enable3dMode.m_immediatelyStart, + viewportChanged); m_discardedFOV = m_discardedAngle = 0.0; break; case UserEvent::EVENT_DISABLE_PERSPECTIVE: if (m_navigator.Screen().isPerspective()) - SetDisable3dModeAnimation(); + SetDisable3dModeAnimation(viewportChanged); m_discardedFOV = m_discardedAngle = 0.0; break; case UserEvent::EVENT_SWITCH_VIEW_MODE: @@ -226,11 +220,12 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChange, bool & { m_discardedFOV = m_navigator.Screen().GetAngleFOV(); m_discardedAngle = m_navigator.Screen().GetRotationAngle(); - SetDisable3dModeAnimation(); + SetDisable3dModeAnimation(viewportChanged); } else if (m_discardedFOV > 0.0) { - SetEnable3dMode(m_discardedAngle, m_discardedFOV, true /* isAnim */, viewportChanged); + SetEnable3dMode(m_discardedAngle, m_discardedFOV, true /* isAnim */, true /* immediatelyStart */, + viewportChanged); m_discardedFOV = m_discardedAngle = 0.0; } break; @@ -256,44 +251,17 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChange, bool & } if (AnimationSystem::Instance().AnimationExists(Animation::MapPlane)) { - m2::AnyRectD const rect = AnimationSystem::Instance().GetRect(GetCurrentScreen()); + m2::AnyRectD const rect = AnimationSystem::Instance().GetRect(GetCurrentScreen(), viewportChanged); m_navigator.SetFromRect(rect); - modelViewChange = true; - } - if (m_pendingEvent != nullptr && - m_pendingEvent->m_type == UserEvent::EVENT_ENABLE_PERSPECTIVE && - !m_pendingPerspective && m_animation == nullptr) - { - SetEnable3dMode(m_pendingEvent->m_enable3dMode.m_rotationAngle, - m_pendingEvent->m_enable3dMode.m_angleFOV, - m_pendingEvent->m_enable3dMode.m_isAnim, - viewportChanged); - modelViewChange = true; - m_pendingEvent.reset(); - } - - if (m_perspectiveAnimation != nullptr) - { - double const angle = m_perspectiveAnimation->GetRotationAngle(); - m_navigator.SetRotationIn3dMode(angle); - modelViewChange = true; - TouchCancel(m_touches); - - if (m_perspectiveAnimation->IsFinished()) + ScreenBase const & screen = GetCurrentScreen(); + if (screen.isPerspective()) { - if (angle == 0.0) - { - m_navigator.Disable3dMode(); - viewportChanged = true; - - if (m_pendingEvent != nullptr && m_pendingEvent->m_type == UserEvent::EVENT_SET_RECT) - SetRect(m_pendingEvent->m_rectEvent.m_rect, m_pendingEvent->m_rectEvent.m_zoom, - m_pendingEvent->m_rectEvent.m_applyRotation, m_pendingEvent->m_rectEvent.m_isAnim); - } - m_pendingEvent.reset(); - m_perspectiveAnimation.reset(); + double const angle = AnimationSystem::Instance().GetPerspectiveAngle(screen.GetRotationAngle()); + m_navigator.SetRotationIn3dMode(angle); + //TouchCancel(m_touches); } + modelViewChange = true; } if (GetValidTouchesCount(m_touches) == 1) @@ -555,32 +523,64 @@ bool UserEventStream::FilterEventWhile3dAnimation(UserEvent::EEventType type) co type != UserEvent::EVENT_SET_RECT; } -void UserEventStream::SetEnable3dMode(double maxRotationAngle, double angleFOV, bool isAnim, bool & viewportChanged) +void UserEventStream::SetEnable3dMode(double maxRotationAngle, double angleFOV, + bool isAnim, bool immediatelyStart, + bool & viewportChanged) { - bool const finishAnimation = m_animation != nullptr && m_animation->GetType() == ModelViewAnimationType::Default; - ResetCurrentAnimation(finishAnimation); + AnimationSystem::Instance().FinishAnimations(Animation::MapLinear, true /* rewind */); + + m_navigator.SetFromRect(AnimationSystem::Instance().GetRect(GetCurrentScreen(), viewportChanged)); double const startAngle = isAnim ? 0.0 : maxRotationAngle; - if (isAnim) + double const endAngle = maxRotationAngle; + if (isAnim || !immediatelyStart) { - double const endAngle = maxRotationAngle; - double const rotateDuration = PerspectiveAnimation::GetRotateDuration(startAngle, endAngle); - m_perspectiveAnimation.reset( - new PerspectiveAnimation(rotateDuration, 0.0 /* delay */, startAngle, endAngle)); + drape_ptr anim = make_unique_dp(startAngle, endAngle); + anim->SetOnStartAction([this, startAngle, endAngle, angleFOV](Animation const &) + { + m_perspectiveAnimation = true; + m_navigator.Enable3dMode(startAngle, endAngle, angleFOV); + }); + anim->SetOnFinishAction([this](Animation const &) + { + m_perspectiveAnimation = false; + }); + if (immediatelyStart) + { + //AnimationSystem::Instance().FinishObjectAnimations(Animation::MapPlane, false /* rewind */); + AnimationSystem::Instance().AddAnimation(move(anim), true /* force */); + } + else + AnimationSystem::Instance().PushAnimation(move(anim)); } - m_navigator.Enable3dMode(startAngle, maxRotationAngle, angleFOV); - viewportChanged = true; } -void UserEventStream::SetDisable3dModeAnimation() +void UserEventStream::SetDisable3dModeAnimation(bool & viewportChanged) { - bool const finishAnimation = m_animation != nullptr && m_animation->GetType() == ModelViewAnimationType::Default; - ResetCurrentAnimation(finishAnimation); + AnimationSystem::Instance().FinishAnimations(Animation::MapLinear, true /* rewind */); + //AnimationSystem::Instance().FinishObjectAnimations(Animation::MapPlane, false /* rewind */); + m_navigator.SetFromRect(AnimationSystem::Instance().GetRect(GetCurrentScreen(), viewportChanged)); double const startAngle = m_navigator.Screen().GetRotationAngle(); double const endAngle = 0.0; - double const rotateDuration = PerspectiveAnimation::GetRotateDuration(startAngle, endAngle); - m_perspectiveAnimation.reset(new PerspectiveAnimation(rotateDuration, 0.0 /* delay */, startAngle, endAngle)); + + drape_ptr anim = make_unique_dp(startAngle, endAngle); + anim->SetOnStartAction([this](Animation const &) + { + m_perspectiveAnimation = true; + }); + anim->SetOnFinishAction([this](Animation const &) + { + m_perspectiveAnimation = false; + m_navigator.Disable3dMode(); + if (m_pendingEvent != nullptr && m_pendingEvent->m_type == UserEvent::EVENT_SET_RECT) + { + SetRect(m_pendingEvent->m_rectEvent.m_rect, m_pendingEvent->m_rectEvent.m_zoom, + m_pendingEvent->m_rectEvent.m_applyRotation, m_pendingEvent->m_rectEvent.m_isAnim); + m_pendingEvent.reset(); + } + }); + AnimationSystem::Instance().AddAnimation(move(anim), true /* force */); } void UserEventStream::ResetCurrentAnimation(bool finishAnimation) @@ -1160,7 +1160,7 @@ bool UserEventStream::IsWaitingForActionCompletion() const bool UserEventStream::IsInPerspectiveAnimation() const { - return m_perspectiveAnimation != nullptr; + return m_perspectiveAnimation; } void UserEventStream::SetKineticScrollEnabled(bool enabled) diff --git a/drape_frontend/user_event_stream.hpp b/drape_frontend/user_event_stream.hpp index e248910851..c589860f3a 100644 --- a/drape_frontend/user_event_stream.hpp +++ b/drape_frontend/user_event_stream.hpp @@ -310,8 +310,9 @@ private: double azimuth, int preferredZoomLevel, bool isAnim); bool FilterEventWhile3dAnimation(UserEvent::EEventType type) const; - void SetEnable3dMode(double maxRotationAngle, double angleFOV, bool isAnim, bool & viewportChanged); - void SetDisable3dModeAnimation(); + void SetEnable3dMode(double maxRotationAngle, double angleFOV, + bool isAnim, bool immediatelyStart, bool & viewportChanged); + void SetDisable3dModeAnimation(bool & viewportChanged); m2::AnyRectD GetCurrentRect() const; @@ -376,8 +377,7 @@ private: drape_ptr m_animation; - unique_ptr m_perspectiveAnimation; - bool m_pendingPerspective = false; + bool m_perspectiveAnimation; unique_ptr m_pendingEvent; double m_discardedFOV = 0.0; double m_discardedAngle = 0.0;