From 4c2e61330abe680138e35e9882dfc2d6fc2b42d4 Mon Sep 17 00:00:00 2001 From: ExMix Date: Mon, 3 Aug 2015 17:13:44 +0300 Subject: [PATCH] animation for my position mark moving and rotating --- drape_frontend/apply_feature_functors.cpp | 6 +- drape_frontend/frontend_renderer.cpp | 5 +- drape_frontend/my_position_controller.cpp | 105 ++++++++++++++++++++-- drape_frontend/my_position_controller.hpp | 17 +++- 4 files changed, 117 insertions(+), 16 deletions(-) diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp index 48c5f6c405..fd5f05e4ba 100644 --- a/drape_frontend/apply_feature_functors.cpp +++ b/drape_frontend/apply_feature_functors.cpp @@ -128,8 +128,6 @@ void Extract(::LineDefProto const * lineRule, ASSERT(false, ()); } - params.m_cap = dp::ButtCap; - switch (lineRule->join()) { case ::NOJOIN : params.m_join = dp::MiterJoin; @@ -436,6 +434,10 @@ void ApplyLineFeature::ProcessRule(Stylist::TRuleWrapper const & rule) Extract(pLineRule, params); params.m_depth = depth; params.m_baseGtoPScale = m_currentScaleGtoP; + + if (m_simplify) + params.m_cap = dp::ButtCap; + m_insertShape(make_unique_dp(m_spline, params)); } } diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 50fed991cd..4abcc84b86 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -257,14 +257,15 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) case Message::CompassInfo: { ref_ptr msg = message; - m_myPositionController->OnCompassUpdate(msg->GetInfo()); + m_myPositionController->OnCompassUpdate(msg->GetInfo(), m_userEventStream.GetCurrentScreen()); break; } case Message::GpsInfo: { ref_ptr msg = message; - m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable()); + m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), + m_userEventStream.GetCurrentScreen()); location::RouteMatchingInfo const & info = msg->GetRouteInfo(); if (info.HasDistanceFromBegin()) diff --git a/drape_frontend/my_position_controller.cpp b/drape_frontend/my_position_controller.cpp index 7e63706693..9bec0d6577 100644 --- a/drape_frontend/my_position_controller.cpp +++ b/drape_frontend/my_position_controller.cpp @@ -1,5 +1,8 @@ #include "my_position_controller.hpp" #include "visual_params.hpp" +#include "animation/base_interpolator.hpp" +#include "animation/interpolations.hpp" +#include "animation/model_view_animation.hpp" #include "indexer/mercator.hpp" @@ -42,6 +45,41 @@ bool TestModeBit(uint32_t mode, uint32_t bit) } // namespace +class MyPositionController::MyPositionAnim : public BaseInterpolator +{ + using TBase = BaseInterpolator; +public: + MyPositionAnim(m2::PointD const & startPt, m2::PointD const & endPt, double moveDuration, + double startAzimut, double endAzimut, double rotationDuration) + : TBase(max(moveDuration, rotationDuration)) + , m_startPt(startPt) + , m_endPt(endPt) + , m_moveDuration(moveDuration) + , m_angleInterpolator(startAzimut, endAzimut) + , m_rotateDuration(rotationDuration) + { + } + + m2::PointD GetCurrentPosition() const + { + return InterpolatePoint(m_startPt, m_endPt, + my::clamp(GetElapsedTime() / m_moveDuration, 0.0, 1.0)); + } + + double GetCurrentAzimut() const + { + return m_angleInterpolator.Interpolate(my::clamp(GetElapsedTime() / m_rotateDuration, 0.0, 1.0)); + } + +private: + m2::PointD m_startPt; + m2::PointD m_endPt; + double m_moveDuration; + + InerpolateAngle m_angleInterpolator; + double m_rotateDuration; +}; + MyPositionController::MyPositionController(location::EMyPositionMode initMode) : m_modeInfo(location::MODE_PENDING_POSITION) , m_afterPendingMode(location::MODE_FOLLOW) @@ -58,6 +96,11 @@ MyPositionController::MyPositionController(location::EMyPositionMode initMode) m_modeInfo = location::MODE_UNKNOWN_POSITION; } +MyPositionController::~MyPositionController() +{ + m_anim.reset(); +} + void MyPositionController::SetPixelRect(m2::RectD const & pixelRect) { m_pixelRect = pixelRect; @@ -225,9 +268,10 @@ void MyPositionController::Invalidate() } } -void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable) +void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, + ScreenBase const & screen) { - Assign(info, isNavigable); + Assign(info, isNavigable, screen); SetIsVisible(true); @@ -238,9 +282,10 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool } } -void MyPositionController::OnCompassUpdate(location::CompassInfo const & info) +void MyPositionController::OnCompassUpdate(location::CompassInfo const & info, + ScreenBase const & screen) { - Assign(info); + Assign(info, screen); } void MyPositionController::SetModeListener(location::TMyPositionModeChanged const & fn) @@ -261,8 +306,8 @@ void MyPositionController::Render(uint32_t renderMode, ScreenBase const & screen m_isDirtyViewport = false; } - m_shape->SetPosition(m_position); - m_shape->SetAzimuth(m_drawDirection); + m_shape->SetPosition(GetDrawablePosition()); + m_shape->SetAzimuth(GetDrawableAzimut()); m_shape->SetIsValidAzimuth(IsRotationActive()); m_shape->SetAccuracy(m_errorRadius); m_shape->SetRoutingMode(IsInRouting()); @@ -273,6 +318,8 @@ void MyPositionController::Render(uint32_t renderMode, ScreenBase const & screen if ((renderMode & RenderMyPosition) != 0) m_shape->RenderMyPosition(screen, mng, commonUniforms); } + + CheckAnimFinished(); } void MyPositionController::AnimateStateTransition(location::EMyPositionMode oldMode, location::EMyPositionMode newMode) @@ -296,8 +343,11 @@ void MyPositionController::AnimateStateTransition(location::EMyPositionMode oldM } } -void MyPositionController::Assign(location::GpsInfo const & info, bool isNavigable) +void MyPositionController::Assign(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen) { + m2::PointD oldPos = GetDrawablePosition(); + double oldAzimut = GetDrawableAzimut(); + m2::RectD rect = MercatorBounds::MetresToXY(info.m_longitude, info.m_latitude, info.m_horizontalAccuracy); @@ -315,11 +365,16 @@ void MyPositionController::Assign(location::GpsInfo const & info, bool isNavigab if (m_listener) m_listener->PositionChanged(Position()); + CreateAnim(oldPos, oldAzimut, screen); + m_isDirtyViewport = true; } -void MyPositionController::Assign(location::CompassInfo const & info) +void MyPositionController::Assign(location::CompassInfo const & info, ScreenBase const & screen) { + m2::PointD oldPos = GetDrawablePosition(); + double oldAzimut = GetDrawableAzimut(); + if ((IsInRouting() && GetMode() >= location::MODE_FOLLOW) || (m_lastGPSBearing.ElapsedSeconds() < GPS_BEARING_LIFETIME_S)) { @@ -327,6 +382,8 @@ void MyPositionController::Assign(location::CompassInfo const & info) } SetDirection(info.m_bearing); + CreateAnim(oldPos, oldAzimut, screen); + m_isDirtyViewport = true; } @@ -440,6 +497,38 @@ m2::PointD MyPositionController::GetCurrentPixelBinding() const return m2::PointD::Zero(); } +m2::PointD MyPositionController::GetDrawablePosition() const +{ + if (m_anim) + return m_anim->GetCurrentPosition(); + + return Position(); +} + +double MyPositionController::GetDrawableAzimut() const +{ + if (m_anim) + return m_anim->GetCurrentAzimut(); + + return m_drawDirection; +} + +void MyPositionController::CheckAnimFinished() const +{ + if (m_anim && m_anim->IsFinished()) + m_anim.reset(); +} + +void MyPositionController::CreateAnim(m2::PointD const & oldPos, double oldAzimut, ScreenBase const & screen) +{ + double moveDuration = ModelViewAnimation::GetMoveDuration(oldPos, m_position, screen); + double rotateDuration = ModelViewAnimation::GetRotateDuration(oldAzimut, m_drawDirection); + double maxDuration = max(moveDuration, rotateDuration); + double MAX_MY_POSITION_DURATION = 2.0; // in seconds + if (maxDuration > 0.0 && maxDuration < MAX_MY_POSITION_DURATION) + m_anim.reset(new MyPositionAnim(oldPos, m_position, moveDuration, oldAzimut, m_drawDirection, rotateDuration)); +} + void MyPositionController::ActivateRouting() { if (!IsInRouting()) diff --git a/drape_frontend/my_position_controller.hpp b/drape_frontend/my_position_controller.hpp index 82ec056197..28feda0a78 100644 --- a/drape_frontend/my_position_controller.hpp +++ b/drape_frontend/my_position_controller.hpp @@ -40,6 +40,7 @@ public: }; MyPositionController(location::EMyPositionMode initMode); + ~MyPositionController(); void SetPixelRect(m2::RectD const & pixelRect); void SetListener(ref_ptr listener); @@ -72,8 +73,8 @@ public: void TurnOff(); void Invalidate(); - void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable); - void OnCompassUpdate(location::CompassInfo const & info); + void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen); + void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen); void SetModeListener(location::TMyPositionModeChanged const & fn); @@ -83,8 +84,8 @@ public: private: void AnimateStateTransition(location::EMyPositionMode oldMode, location::EMyPositionMode newMode); - void Assign(location::GpsInfo const & info, bool isNavigable); - void Assign(location::CompassInfo const & info); + void Assign(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen); + void Assign(location::CompassInfo const & info, ScreenBase const & screen); void SetDirection(double bearing); void SetModeInfo(uint32_t modeInfo, bool force = false); @@ -106,6 +107,11 @@ private: m2::PointD GetRaFPixelBinding() const; m2::PointD GetCurrentPixelBinding() const; + m2::PointD GetDrawablePosition() const; + double GetDrawableAzimut() const; + void CheckAnimFinished() const; + void CreateAnim(m2::PointD const & oldPos, double oldAzimut, ScreenBase const & screen); + private: // Mode bits // { @@ -132,6 +138,9 @@ private: bool m_isVisible; bool m_isDirtyViewport; + + class MyPositionAnim; + mutable drape_ptr m_anim; }; }