forked from organicmaps/organicmaps
[drape] my position produce viewport animations
This commit is contained in:
parent
bd638377b9
commit
6257016d0e
6 changed files with 137 additions and 33 deletions
|
@ -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<MyPositionController::Listener>(&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;
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace df
|
|||
{
|
||||
|
||||
class FrontendRenderer : public BaseRenderer
|
||||
, public MyPositionController::Listener
|
||||
{
|
||||
public:
|
||||
using TModelViewChanged = function<void (ScreenBase const & screen)>;
|
||||
|
@ -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> message);
|
||||
unique_ptr<threads::IRoutine> CreateRoutine() override;
|
||||
|
|
|
@ -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<MyPositionController::Listener> 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<dp::GpuProgramManager> 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<dp::GpuProg
|
|||
|
||||
void MyPositionController::AnimateStateTransition(location::EMyPositionMode oldMode, location::EMyPositionMode newMode)
|
||||
{
|
||||
//TODO UVR (rakhuba) restore viewport animation logic
|
||||
}
|
||||
|
||||
void MyPositionController::AnimateFollow()
|
||||
{
|
||||
//TODO UVR (rakhuba) restore viewport animation logic
|
||||
if (oldMode == location::MODE_PENDING_POSITION && newMode == location::MODE_FOLLOW)
|
||||
{
|
||||
if (!TestModeBit(m_modeInfo, FixedZoomBit))
|
||||
{
|
||||
m2::PointD const size(m_errorRadius, m_errorRadius);
|
||||
ChangeModelView(m2::RectD(m_position - size, m_position + size));
|
||||
}
|
||||
}
|
||||
else if (oldMode == location::MODE_ROTATE_AND_FOLLOW && newMode == location::MODE_UNKNOWN_POSITION)
|
||||
{
|
||||
ChangeModelView(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
void MyPositionController::Assign(location::GpsInfo const & info, bool isNavigable)
|
||||
|
@ -224,18 +250,20 @@ void MyPositionController::Assign(location::GpsInfo const & info, bool isNavigab
|
|||
SetDirection(my::DegToRad(info.m_bearing));
|
||||
m_lastGPSBearing.Reset();
|
||||
}
|
||||
|
||||
m_isDirtyViewport = true;
|
||||
}
|
||||
|
||||
bool MyPositionController::Assign(location::CompassInfo const & info)
|
||||
void MyPositionController::Assign(location::CompassInfo const & info)
|
||||
{
|
||||
if ((IsInRouting() && GetMode() >= 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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> 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<MyPosition> m_shape;
|
||||
ref_ptr<Listener> 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue