diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index c058fce057..eb2faf734d 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -496,6 +496,7 @@ FrontendRenderer::Routine::Routine(FrontendRenderer & renderer) : m_renderer(ren void FrontendRenderer::Routine::Do() { gui::DrapeGui::Instance().ConnectOnCompassTappedHandler(bind(&FrontendRenderer::OnCompassTapped, &m_renderer)); + m_renderer.m_myPositionController->SetListener(ref_ptr(&m_renderer)); m_renderer.m_tileTree->SetHandlers(bind(&FrontendRenderer::OnAddRenderGroup, &m_renderer, _1, _2, _3), bind(&FrontendRenderer::OnDeferRenderGroup, &m_renderer, _1, _2, _3), @@ -592,6 +593,32 @@ void FrontendRenderer::AddUserEvent(UserEvent const & event) CancelMessageWaiting(); } +void FrontendRenderer::ChangeModelView(m2::PointD const & center) +{ + AddUserEvent(SetCenterEvent(center, -1, true)); +} + +void FrontendRenderer::ChangeModelView(double azimuth) +{ + AddUserEvent(RotateEvent(azimuth)); +} + +void FrontendRenderer::ChangeModelView(m2::RectD const & rect) +{ + AddUserEvent(SetRectEvent(rect, true, scales::GetUpperComfortScale(), true)); +} + +void FrontendRenderer::ChangeModelView(m2::PointD const & userPos, double azimuth, + m2::PointD const & pxZero, ScreenBase const & screen) +{ + double offset = (screen.PtoG(screen.PixelRect().Center()) - screen.PtoG(pxZero)).Length(); + m2::PointD viewVector = userPos.Move(1.0, -azimuth + math::pi2) - userPos; + viewVector.Normalize(); + + AddUserEvent(SetAnyRectEvent(m2::AnyRectD(userPos + (viewVector * offset), -azimuth, + screen.GlobalRect().GetLocalRect()), true /* animate */)); +} + ScreenBase const & FrontendRenderer::UpdateScene(bool & modelViewChanged) { bool viewportChanged; diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index cda4e49c25..3f31fe81a3 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -40,6 +40,7 @@ namespace df { class FrontendRenderer : public BaseRenderer + , public MyPositionController::Listener { public: using TModelViewChanged = function; @@ -88,6 +89,13 @@ public: void AddUserEvent(UserEvent const & event); + /// MyPositionController::Listener + void ChangeModelView(m2::PointD const & center) override; + void ChangeModelView(double azimuth) override; + void ChangeModelView(m2::RectD const & rect) override; + void ChangeModelView(m2::PointD const & userPos, double azimuth, + m2::PointD const & pxZero, ScreenBase const & screen) override; + protected: virtual void AcceptMessage(ref_ptr message); unique_ptr CreateRoutine() override; diff --git a/drape_frontend/my_position_controller.cpp b/drape_frontend/my_position_controller.cpp index 30d5b0f054..330afef9d4 100644 --- a/drape_frontend/my_position_controller.cpp +++ b/drape_frontend/my_position_controller.cpp @@ -1,4 +1,5 @@ #include "my_position_controller.hpp" +#include "visual_params.hpp" #include "indexer/mercator.hpp" @@ -10,6 +11,7 @@ namespace df namespace { +int const POSITION_Y_OFFSET = 120; double const GPS_BEARING_LIFETIME_S = 5.0; double const MIN_SPEED_THRESHOLD_MPS = 1.0; @@ -48,6 +50,7 @@ MyPositionController::MyPositionController(location::EMyPositionMode initMode) , m_drawDirection(0.0) , m_lastGPSBearing(false) , m_isVisible(false) + , m_isDirtyViewport(false) { if (initMode > location::MODE_UNKNOWN_POSITION) m_afterPendingMode = initMode; @@ -55,6 +58,11 @@ MyPositionController::MyPositionController(location::EMyPositionMode initMode) m_modeInfo = location::MODE_UNKNOWN_POSITION; } +void MyPositionController::SetListener(ref_ptr listener) +{ + m_listener = listener; +} + m2::PointD const & MyPositionController::Position() const { return m_position; @@ -168,16 +176,11 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool SetModeInfo(ChangeMode(m_modeInfo, m_afterPendingMode)); m_afterPendingMode = location::MODE_FOLLOW; } - else - { - AnimateFollow(); - } } void MyPositionController::OnCompassUpdate(location::CompassInfo const & info) { - if (Assign(info)) - AnimateFollow(); + Assign(info); } void MyPositionController::SetModeListener(location::TMyPositionModeChanged const & fn) @@ -189,8 +192,25 @@ void MyPositionController::SetModeListener(location::TMyPositionModeChanged cons void MyPositionController::Render(ScreenBase const & screen, ref_ptr mng, dp::UniformValuesStorage const & commonUniforms) { - if (m_shape != nullptr && IsVisible() && GetMode() > location::MODE_PENDING_POSITION) + location::EMyPositionMode currentMode = GetMode(); + if (m_shape != nullptr && IsVisible() && currentMode > location::MODE_PENDING_POSITION) { + if (m_isDirtyViewport) + { + if (currentMode == location::MODE_FOLLOW) + { + ChangeModelView(m_position); + } + else if (currentMode == location::MODE_ROTATE_AND_FOLLOW) + { + m2::RectD const & pixelRect = screen.PixelRect(); + m2::PointD pxZero(pixelRect.Center().x, + pixelRect.maxY() - POSITION_Y_OFFSET * VisualParams::Instance().GetVisualScale()); + ChangeModelView(m_position, m_drawDirection, pxZero, screen); + } + m_isDirtyViewport = false; + } + m_shape->SetPosition(m_position); m_shape->SetAzimuth(m_drawDirection); m_shape->SetIsValidAzimuth(IsRotationActive()); @@ -201,12 +221,18 @@ void MyPositionController::Render(ScreenBase const & screen, ref_ptr= location::MODE_FOLLOW) || (m_lastGPSBearing.ElapsedSeconds() < GPS_BEARING_LIFETIME_S)) { - return false; + return; } SetDirection(info.m_bearing); - return true; + m_isDirtyViewport = true; } void MyPositionController::SetDirection(double bearing) @@ -281,15 +309,9 @@ void MyPositionController::StopLocationFollow() { location::EMyPositionMode currentMode = GetMode(); if (currentMode > location::MODE_NOT_FOLLOW) - { - StopAllAnimations(); SetModeInfo(ChangeMode(m_modeInfo, location::MODE_NOT_FOLLOW)); - } else if (currentMode == location::MODE_PENDING_POSITION) - { - StopAllAnimations(); m_afterPendingMode = location::MODE_NOT_FOLLOW; - } } void MyPositionController::StopCompassFollow() @@ -297,13 +319,32 @@ void MyPositionController::StopCompassFollow() if (GetMode() != location::MODE_ROTATE_AND_FOLLOW) return; - StopAllAnimations(); SetModeInfo(ChangeMode(m_modeInfo, location::MODE_FOLLOW)); } -void MyPositionController::StopAllAnimations() +void MyPositionController::ChangeModelView(m2::PointD const & center) { - // TODO + if (m_listener) + m_listener->ChangeModelView(center); +} + +void MyPositionController::ChangeModelView(double azimuth) +{ + if (m_listener) + m_listener->ChangeModelView(azimuth); +} + +void MyPositionController::ChangeModelView(m2::RectD const & rect) +{ + if (m_listener) + m_listener->ChangeModelView(rect); +} + +void MyPositionController::ChangeModelView(m2::PointD const & userPos, double azimuth, + m2::PointD const & pxZero, ScreenBase const & screen) +{ + if (m_listener) + m_listener->ChangeModelView(userPos, azimuth, pxZero, screen); } } diff --git a/drape_frontend/my_position_controller.hpp b/drape_frontend/my_position_controller.hpp index 08d3d7dc60..369fdd24fe 100644 --- a/drape_frontend/my_position_controller.hpp +++ b/drape_frontend/my_position_controller.hpp @@ -17,8 +17,25 @@ namespace df class MyPositionController { public: + class Listener + { + public: + virtual ~Listener() {} + /// Show map with center in "center" point and current zoom + virtual void ChangeModelView(m2::PointD const & center) = 0; + /// Change azimuth of current ModelView + virtual void ChangeModelView(double azimuth) = 0; + /// Somehow show map that "rect" will see + virtual void ChangeModelView(m2::RectD const & rect) = 0; + /// Show map where "usePos" (mercator) placed in "pxZero" on screen and map rotated around "userPos" + virtual void ChangeModelView(m2::PointD const & userPos, double azimuth, + m2::PointD const & pxZero, ScreenBase const & screen) = 0; + }; + MyPositionController(location::EMyPositionMode initMode); + void SetListener(ref_ptr listener); + m2::PointD const & Position() const; double GetErrorRadius() const; @@ -43,10 +60,9 @@ public: private: void AnimateStateTransition(location::EMyPositionMode oldMode, location::EMyPositionMode newMode); - void AnimateFollow(); void Assign(location::GpsInfo const & info, bool isNavigable); - bool Assign(location::CompassInfo const & info); + void Assign(location::CompassInfo const & info); void SetDirection(double bearing); void SetModeInfo(uint16_t modeInfo, bool force = false); @@ -58,11 +74,16 @@ private: void StopLocationFollow(); void StopCompassFollow(); - void StopAllAnimations(); bool IsVisible() const { return m_isVisible; } void SetIsVisible(bool isVisible) { m_isVisible = isVisible; } + void ChangeModelView(m2::PointD const & center); + void ChangeModelView(double azimuth); + void ChangeModelView(m2::RectD const & rect); + void ChangeModelView(m2::PointD const & userPos, double azimuth, + m2::PointD const & pxZero, ScreenBase const & screen); + private: // Mode bits // { @@ -76,6 +97,7 @@ private: location::TMyPositionModeChanged m_modeChangeCallback; drape_ptr m_shape; + ref_ptr m_listener; double m_errorRadius; //< error radius in mercator m2::PointD m_position; //< position in mercator @@ -83,6 +105,7 @@ private: my::HighResTimer m_lastGPSBearing; bool m_isVisible; + bool m_isDirtyViewport; }; } diff --git a/drape_frontend/user_event_stream.cpp b/drape_frontend/user_event_stream.cpp index 0575453d7e..f36d89dece 100644 --- a/drape_frontend/user_event_stream.cpp +++ b/drape_frontend/user_event_stream.cpp @@ -147,8 +147,13 @@ bool UserEventStream::Scale(m2::PointD const & pxScaleCenter, double factor, boo bool UserEventStream::SetCenter(m2::PointD const & center, int zoom, bool isAnim) { - m2::RectD rect = df::GetRectForDrawScale(zoom, center); - return SetRect(rect, zoom, true, isAnim); + if (zoom == -1) + { + m2::AnyRectD r = GetTargetRect(); + return SetRect(m2::AnyRectD(center, r.Angle(), r.GetLocalRect()), isAnim); + } + + return SetRect(df::GetRectForDrawScale(zoom, center), zoom, true, isAnim); } bool UserEventStream::SetRect(m2::RectD rect, int zoom, bool applyRotation, bool isAnim) @@ -163,7 +168,7 @@ bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim) { if (isAnim) { - m2::AnyRectD startRect = m_navigator.Screen().GlobalRect(); + m2::AnyRectD startRect = GetCurrentRect(); double const duration = ModelViewAnimation::GetDuration(startRect, rect, m_navigator.Screen()); m_animation.reset(new ModelViewAnimation(startRect, rect, duration)); return false; diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp index 6bda769ba8..7ef1e42419 100644 --- a/qt/draw_widget.cpp +++ b/qt/draw_widget.cpp @@ -219,14 +219,14 @@ bool IsLocationEmulation(QMouseEvent * e) void DrawWidget::mouseMoveEvent(QMouseEvent * e) { TBase::mouseMoveEvent(e); - if (IsLeftButton(e)) + if (IsLeftButton(e) && !IsLocationEmulation(e)) m_framework->TouchEvent(GetTouchEvent(e, df::TouchEvent::TOUCH_MOVE)); } void DrawWidget::mouseReleaseEvent(QMouseEvent * e) { TBase::mouseReleaseEvent(e); - if (IsLeftButton(e)) + if (IsLeftButton(e) && !IsLocationEmulation(e)) m_framework->TouchEvent(GetTouchEvent(e, df::TouchEvent::TOUCH_UP)); }