[drape] my position produce viewport animations

This commit is contained in:
ExMix 2015-05-22 10:38:51 +03:00 committed by r.kuznetsov
parent bd638377b9
commit 6257016d0e
6 changed files with 137 additions and 33 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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;
};
}

View file

@ -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;

View file

@ -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));
}