diff --git a/drape_frontend/animation_system.cpp b/drape_frontend/animation_system.cpp index 49fd982f19..4a7444fe5c 100644 --- a/drape_frontend/animation_system.cpp +++ b/drape_frontend/animation_system.cpp @@ -235,8 +235,8 @@ ScaleInterpolator::ScaleInterpolator(double delay, double startScale, double end // static double ScaleInterpolator::GetScaleDuration(double startScale, double endScale) { - // Resize 2.0 times should be done for 0.3 seconds. - double constexpr kPixelSpeed = 2.0 / 0.3; + // Resize 2.0 times should be done for 0.2 seconds. + double constexpr kPixelSpeed = 2.0 / 0.2; if (startScale > endScale) swap(startScale, endScale); diff --git a/drape_frontend/animation_system.hpp b/drape_frontend/animation_system.hpp index 00796f3f2e..3503bdd3ca 100644 --- a/drape_frontend/animation_system.hpp +++ b/drape_frontend/animation_system.hpp @@ -140,6 +140,9 @@ public: void SetInterruptedOnCombine(bool enable) { m_interruptedOnCombine = enable; } bool GetInterruptedOnCombine() const { return m_interruptedOnCombine; } + void SetCouldBeInterrupted(bool enable) { m_couldBeInterrupted = enable; } + void SetCouldBeBlended(bool enable) { m_couldBeBlended = enable; } + protected: TAction m_onStartAction; TAction m_onFinishAction; diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index ac074b0adc..3ad6ecaa57 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -383,7 +383,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) switch (msg->GetChangeType()) { case ChangeMyPositionModeMessage::SwitchNextMode: - m_myPositionController->NextMode(); + m_myPositionController->NextMode(m_userEventStream.GetCurrentScreen()); break; case ChangeMyPositionModeMessage::StopFollowing: m_myPositionController->StopLocationFollow(); diff --git a/drape_frontend/my_position_controller.cpp b/drape_frontend/my_position_controller.cpp index 259ff04dd9..fea72a4bd3 100644 --- a/drape_frontend/my_position_controller.cpp +++ b/drape_frontend/my_position_controller.cpp @@ -5,6 +5,8 @@ #include "drape_frontend/animation/base_interpolator.hpp" #include "drape_frontend/animation/interpolations.hpp" +#include "indexer/scales.hpp" + #include "geometry/mercator.hpp" #include "base/math.hpp" @@ -28,6 +30,9 @@ double const kMaxNotFollowRoutingTimeSec = 10.0; double const kMaxUpdateLocationInvervalSec = 30.0; double const kMaxWaitStartLocationSec = 5.0; +int const kZoomThreshold = 10; +int const kMaxScaleZoomLevel = 16; + int const kDoNotChangeZoom = -1; string LocationModeStatisticsName(location::EMyPositionMode mode) @@ -48,6 +53,19 @@ string LocationModeStatisticsName(location::EMyPositionMode mode) return "@UnknownMode"; } +int GetZoomLevel(ScreenBase const & screen) +{ + return my::clamp(fabs(log(screen.GetScale()) / log(2.0)), 1, scales::GetUpperStyleScale()); +} + +int GetZoomLevel(ScreenBase const & screen, m2::PointD const & position, double errorRadius) +{ + ScreenBase s = screen; + m2::PointD const size(errorRadius, errorRadius); + s.SetFromRect(m2::AnyRectD(position, screen.GetAngle(), m2::RectD(position - size, position + size))); + return GetZoomLevel(s); +} + } // namespace class MyPositionController::MyPositionAnim : public BaseInterpolator @@ -125,7 +143,7 @@ MyPositionController::~MyPositionController() void MyPositionController::OnNewPixelRect() { - UpdateViewport(); + UpdateViewport(kDoNotChangeZoom); } void MyPositionController::UpdatePixelPosition(ScreenBase const & screen) @@ -173,7 +191,7 @@ void MyPositionController::DragEnded(m2::PointD const & distance) if (distance.Length() > kBindingDistance * min(m_pixelRect.SizeX(), m_pixelRect.SizeY())) StopLocationFollow(); - UpdateViewport(); + UpdateViewport(kDoNotChangeZoom); } void MyPositionController::ScaleStarted() @@ -190,7 +208,7 @@ void MyPositionController::ScaleEnded() StopLocationFollow(); } - UpdateViewport(); + UpdateViewport(kDoNotChangeZoom); } void MyPositionController::Rotated() @@ -226,7 +244,7 @@ void MyPositionController::SetRenderShape(drape_ptr && shape) m_shape = move(shape); } -void MyPositionController::NextMode() +void MyPositionController::NextMode(ScreenBase const & screen) { string const kAlohalyticsClickEvent = "$onClick"; @@ -248,11 +266,17 @@ void MyPositionController::NextMode() return; } + // Calculate preferred zoom level. + int const currentZoom = GetZoomLevel(screen); + int preferredZoomLevel = kDoNotChangeZoom; + if (currentZoom < kZoomThreshold) + preferredZoomLevel = min(GetZoomLevel(screen, m_position, m_errorRadius), kMaxScaleZoomLevel); + // In routing not-follow -> follow-and-rotate, otherwise not-follow -> follow. if (m_mode == location::NotFollow) { ChangeMode(m_isInRouting ? location::FollowAndRotate : location::Follow); - UpdateViewport(); + UpdateViewport(preferredZoomLevel); return; } @@ -263,7 +287,7 @@ void MyPositionController::NextMode() if (IsRotationAvailable() || m_isInRouting) { ChangeMode(location::FollowAndRotate); - UpdateViewport(); + UpdateViewport(preferredZoomLevel); } return; } @@ -274,7 +298,7 @@ void MyPositionController::NextMode() if (!m_isInRouting) { ChangeMode(location::Follow); - UpdateViewport(); + ChangeModelView(m_position, 0.0, m_centerPixelPosition, preferredZoomLevel); } } } @@ -314,8 +338,15 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool ChangeMode(location::Follow); if (!m_isFirstLaunch) { - m2::PointD const size(m_errorRadius, m_errorRadius); - ChangeModelView(m2::RectD(m_position - size, m_position + size)); + if (GetZoomLevel(screen, m_position, m_errorRadius) <= kMaxScaleZoomLevel) + { + m2::PointD const size(m_errorRadius, m_errorRadius); + ChangeModelView(m2::RectD(m_position - size, m_position + size)); + } + else + { + ChangeModelView(m_position, kMaxScaleZoomLevel); + } } else { @@ -411,14 +442,14 @@ void MyPositionController::Render(uint32_t renderMode, ScreenBase const & screen m_routingNotFollowTimer.ElapsedSeconds() >= kMaxNotFollowRoutingTimeSec) { ChangeMode(location::FollowAndRotate); - UpdateViewport(); + UpdateViewport(kDoNotChangeZoom); } if (m_shape != nullptr && IsVisible() && IsModeHasPosition()) { if (m_isDirtyViewport && !m_needBlockAnimation) { - UpdateViewport(); + UpdateViewport(kDoNotChangeZoom); m_isDirtyViewport = false; } @@ -504,7 +535,7 @@ void MyPositionController::SetTimeInBackground(double time) if (time >= kMaxTimeInBackgroundSec && m_mode == location::NotFollow) { ChangeMode(location::Follow); - UpdateViewport(); + UpdateViewport(kDoNotChangeZoom); } } @@ -516,7 +547,7 @@ void MyPositionController::OnCompassTapped() if (m_mode == location::FollowAndRotate) { ChangeMode(location::Follow); - UpdateViewport(); + UpdateViewport(kDoNotChangeZoom); } } @@ -545,16 +576,16 @@ void MyPositionController::ChangeModelView(m2::PointD const & userPos, double az m_listener->ChangeModelView(userPos, azimuth, pxZero, zoomLevel); } -void MyPositionController::UpdateViewport() +void MyPositionController::UpdateViewport(int zoomLevel) { if (IsWaitingForLocation()) return; if (m_mode == location::Follow) - ChangeModelView(m_position, kDoNotChangeZoom); + ChangeModelView(m_position, zoomLevel); else if (m_mode == location::FollowAndRotate) ChangeModelView(m_position, m_drawDirection, - m_isInRouting ? m_centerPixelPositionRouting : m_centerPixelPosition, kDoNotChangeZoom); + m_isInRouting ? m_centerPixelPositionRouting : m_centerPixelPosition, zoomLevel); } m2::PointD MyPositionController::GetRotationPixelCenter() const diff --git a/drape_frontend/my_position_controller.hpp b/drape_frontend/my_position_controller.hpp index 788f2616c7..75cc83d95d 100644 --- a/drape_frontend/my_position_controller.hpp +++ b/drape_frontend/my_position_controller.hpp @@ -75,7 +75,7 @@ public: void DeactivateRouting(); void StopLocationFollow(); - void NextMode(); + void NextMode(ScreenBase const & screen); void LoseLocation(); void SetTimeInBackground(double time); @@ -113,7 +113,7 @@ private: void ChangeModelView(m2::RectD const & rect); void ChangeModelView(m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero, int zoomLevel); - void UpdateViewport(); + void UpdateViewport(int zoomLevel); m2::PointD GetRotationPixelCenter() const; m2::PointD GetRoutingRotationPixelCenter() const; diff --git a/drape_frontend/user_event_stream.cpp b/drape_frontend/user_event_stream.cpp index 6090979530..d2fd119901 100644 --- a/drape_frontend/user_event_stream.cpp +++ b/drape_frontend/user_event_stream.cpp @@ -570,6 +570,11 @@ bool UserEventStream::SetFollowAndRotate(m2::PointD const & userPos, m2::PointD auto anim = make_unique_dp(userPos, startScale, targetScale, screen.GlobalRect().Angle().val(), -azimuth, screen.GtoP(userPos), pixelPos, screen.PixelRect()); + if (preferredZoomLevel != kDoNotChangeZoom) + { + anim->SetCouldBeInterrupted(false); + anim->SetCouldBeBlended(false); + } anim->SetMaxDuration(kMaxAnimationTimeSec); anim->SetOnStartAction(onStartHandler); m_animationSystem.CombineAnimation(move(anim));