forked from organicmaps/organicmaps
Merge pull request #1231 from darina/arrow-position-fix
Fixed arrow position in follow and follow-and-rotate modes.
This commit is contained in:
commit
fcc93fb787
11 changed files with 88 additions and 34 deletions
7
drape_frontend/animation_constants.hpp
Normal file
7
drape_frontend/animation_constants.hpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
namespace df
|
||||
{
|
||||
double const kMaxAnimationTimeSec = 1.5; // in seconds
|
||||
|
||||
} // namespace df
|
|
@ -113,6 +113,7 @@ HEADERS += \
|
|||
gui/ruler_helper.hpp \
|
||||
gui/shape.hpp \
|
||||
gui/skin.hpp \
|
||||
animation_constants.hpp \
|
||||
apply_feature_functors.hpp \
|
||||
area_shape.hpp \
|
||||
arrow3d.hpp \
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
void CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const override {}
|
||||
void CorrectGlobalScalePoint(m2::PointD & pt) const override {}
|
||||
void OnScaleEnded() override {}
|
||||
void OnAnimationStarted(ref_ptr<df::BaseModelViewAnimation> /* anim */) override {}
|
||||
|
||||
void AddUserEvent(df::TouchEvent const & event)
|
||||
{
|
||||
|
|
|
@ -1107,6 +1107,11 @@ void FrontendRenderer::OnScaleEnded()
|
|||
m_myPositionController->ScaleEnded();
|
||||
}
|
||||
|
||||
void FrontendRenderer::OnAnimationStarted(ref_ptr<BaseModelViewAnimation> anim)
|
||||
{
|
||||
m_myPositionController->AnimationStarted(anim);
|
||||
}
|
||||
|
||||
void FrontendRenderer::ResolveTileKeys(ScreenBase const & screen, TTilesCollection & tiles)
|
||||
{
|
||||
m2::RectD const & clipRect = screen.ClipRect();
|
||||
|
|
|
@ -172,6 +172,7 @@ private:
|
|||
void CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const override;
|
||||
void CorrectGlobalScalePoint(m2::PointD & pt) const override;
|
||||
void OnScaleEnded() override;
|
||||
void OnAnimationStarted(ref_ptr<BaseModelViewAnimation> anim) override;
|
||||
|
||||
class Routine : public threads::IRoutine
|
||||
{
|
||||
|
|
|
@ -116,11 +116,11 @@ void KineticScroller::CancelGrab()
|
|||
m_direction = m2::PointD::Zero();
|
||||
}
|
||||
|
||||
unique_ptr<BaseModelViewAnimation> KineticScroller::CreateKineticAnimation(ScreenBase const & modelView)
|
||||
drape_ptr<BaseModelViewAnimation> KineticScroller::CreateKineticAnimation(ScreenBase const & modelView)
|
||||
{
|
||||
static double kVelocityThreshold = kKineticThreshold * VisualParams::Instance().GetVisualScale();
|
||||
if (m_direction.Length() < kVelocityThreshold)
|
||||
return unique_ptr<BaseModelViewAnimation>();
|
||||
return drape_ptr<BaseModelViewAnimation>();
|
||||
|
||||
// Before we start animation we have to convert length(m_direction) from pixel space to mercator space.
|
||||
m2::PointD center = m_lastRect.GlobalCenter();
|
||||
|
@ -129,9 +129,9 @@ unique_ptr<BaseModelViewAnimation> KineticScroller::CreateKineticAnimation(Scree
|
|||
m2::PointD const glbDirection = m_direction.Normalize() * glbLength;
|
||||
m2::PointD const targetCenter = center + glbDirection;
|
||||
if (!df::GetWorldRect().IsPointInside(targetCenter))
|
||||
return unique_ptr<BaseModelViewAnimation>();
|
||||
return drape_ptr<BaseModelViewAnimation>();
|
||||
|
||||
return unique_ptr<BaseModelViewAnimation>(new KineticScrollAnimation(m_lastRect, glbDirection, kKineticDuration));
|
||||
return make_unique_dp<KineticScrollAnimation>(m_lastRect, glbDirection, kKineticDuration);
|
||||
}
|
||||
|
||||
} // namespace df
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "animation/model_view_animation.hpp"
|
||||
|
||||
#include "drape/pointers.hpp"
|
||||
|
||||
#include "geometry/any_rect2d.hpp"
|
||||
|
||||
namespace df
|
||||
|
@ -16,7 +18,7 @@ public:
|
|||
bool IsActive() const;
|
||||
void GrabViewRect(ScreenBase const & modelView, double timeStamp);
|
||||
void CancelGrab();
|
||||
unique_ptr<BaseModelViewAnimation> CreateKineticAnimation(ScreenBase const & modelView);
|
||||
drape_ptr<BaseModelViewAnimation> CreateKineticAnimation(ScreenBase const & modelView);
|
||||
|
||||
private:
|
||||
double m_lastTimestamp;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "my_position_controller.hpp"
|
||||
#include "animation_constants.hpp"
|
||||
#include "visual_params.hpp"
|
||||
#include "animation/base_interpolator.hpp"
|
||||
#include "animation/interpolations.hpp"
|
||||
|
@ -97,7 +98,6 @@ MyPositionController::MyPositionController(location::EMyPositionMode initMode)
|
|||
, m_positionYOffset(POSITION_Y_OFFSET)
|
||||
, m_isVisible(false)
|
||||
, m_isDirtyViewport(false)
|
||||
, m_needAnimation(false)
|
||||
{
|
||||
if (initMode > location::MODE_UNKNOWN_POSITION)
|
||||
m_afterPendingMode = initMode;
|
||||
|
@ -157,8 +157,6 @@ void MyPositionController::DragEnded(m2::PointD const & distance)
|
|||
SetModeInfo(ResetModeBit(m_modeInfo, BlockAnimation));
|
||||
if (distance.Length() > 0.2 * min(m_pixelRect.SizeX(), m_pixelRect.SizeY()))
|
||||
StopLocationFollow();
|
||||
else if (IsModeChangeViewport())
|
||||
m_needAnimation = true;
|
||||
|
||||
Follow();
|
||||
}
|
||||
|
@ -205,10 +203,7 @@ void MyPositionController::ScaleEnded()
|
|||
SetModeInfo(ResetModeBit(m_modeInfo, StopFollowOnActionEnd));
|
||||
StopLocationFollow();
|
||||
}
|
||||
else if (IsModeChangeViewport())
|
||||
{
|
||||
m_needAnimation = true;
|
||||
}
|
||||
|
||||
Follow();
|
||||
}
|
||||
|
||||
|
@ -333,14 +328,10 @@ void MyPositionController::Render(uint32_t renderMode, ScreenBase const & screen
|
|||
m_isDirtyViewport = false;
|
||||
}
|
||||
|
||||
bool const fixedPixelPos = IsModeChangeViewport() && !TestModeBit(m_modeInfo, BlockAnimation) &&
|
||||
!m_needAnimation && !(m_anim != nullptr && m_anim->IsMovingActive());
|
||||
|
||||
if (fixedPixelPos)
|
||||
m_shape->SetPosition(screen.PtoG(screen.P3dtoP(GetCurrentPixelBinding())));
|
||||
else
|
||||
m_shape->SetPosition(GetDrawablePosition());
|
||||
if (!IsModeChangeViewport())
|
||||
m_isPendingAnimation = false;
|
||||
|
||||
m_shape->SetPosition(GetDrawablePosition());
|
||||
m_shape->SetAzimuth(GetDrawableAzimut());
|
||||
m_shape->SetIsValidAzimuth(IsRotationActive());
|
||||
m_shape->SetAccuracy(m_errorRadius);
|
||||
|
@ -417,11 +408,7 @@ void MyPositionController::Assign(location::GpsInfo const & info, bool isNavigab
|
|||
|
||||
if (!AlmostCurrentPosition(oldPos) || !AlmostCurrentAzimut(oldAzimut))
|
||||
{
|
||||
if (m_needAnimation || !IsModeChangeViewport())
|
||||
{
|
||||
CreateAnim(oldPos, oldAzimut, screen);
|
||||
m_needAnimation = false;
|
||||
}
|
||||
CreateAnim(oldPos, oldAzimut, screen);
|
||||
m_isDirtyViewport = true;
|
||||
}
|
||||
}
|
||||
|
@ -561,7 +548,10 @@ m2::PointD MyPositionController::GetDrawablePosition() const
|
|||
if (m_anim && m_anim->IsMovingActive())
|
||||
return m_anim->GetCurrentPosition();
|
||||
|
||||
return Position();
|
||||
if (m_isPendingAnimation)
|
||||
return m_oldPosition;
|
||||
|
||||
return m_position;
|
||||
}
|
||||
|
||||
double MyPositionController::GetDrawableAzimut() const
|
||||
|
@ -569,6 +559,9 @@ double MyPositionController::GetDrawableAzimut() const
|
|||
if (m_anim && m_anim->IsRotatingActive())
|
||||
return m_anim->GetCurrentAzimut();
|
||||
|
||||
if (m_isPendingAnimation)
|
||||
return m_oldDrawDirection;
|
||||
|
||||
return m_drawDirection;
|
||||
}
|
||||
|
||||
|
@ -578,14 +571,39 @@ void MyPositionController::CheckAnimFinished() const
|
|||
m_anim.reset();
|
||||
}
|
||||
|
||||
void MyPositionController::AnimationStarted(ref_ptr<BaseModelViewAnimation> anim)
|
||||
{
|
||||
if (m_isPendingAnimation && m_animCreator != nullptr && anim != nullptr &&
|
||||
(anim->GetType() == ModelViewAnimationType::FollowAndRotate ||
|
||||
anim->GetType() == ModelViewAnimationType::Default))
|
||||
{
|
||||
m_isPendingAnimation = false;
|
||||
m_animCreator();
|
||||
}
|
||||
}
|
||||
|
||||
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 kMaxMyPositionDuration = 2.0; // in seconds
|
||||
if (maxDuration > 0.0 && maxDuration < kMaxMyPositionDuration)
|
||||
m_anim.reset(new MyPositionAnim(oldPos, m_position, moveDuration, oldAzimut, m_drawDirection, rotateDuration));
|
||||
if (maxDuration > 0.0 && maxDuration < kMaxAnimationTimeSec)
|
||||
{
|
||||
if (IsModeChangeViewport())
|
||||
{
|
||||
m_animCreator = [this, oldPos, moveDuration, oldAzimut, rotateDuration]()
|
||||
{
|
||||
m_anim = make_unique_dp<MyPositionAnim>(oldPos, m_position, moveDuration, oldAzimut, m_drawDirection, rotateDuration);
|
||||
};
|
||||
m_oldPosition = oldPos;
|
||||
m_oldDrawDirection = oldAzimut;
|
||||
m_isPendingAnimation = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_anim = make_unique_dp<MyPositionAnim>(oldPos, m_position, moveDuration, oldAzimut, m_drawDirection, rotateDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MyPositionController::ActivateRouting()
|
||||
|
|
|
@ -11,8 +11,11 @@
|
|||
|
||||
#include "base/timer.hpp"
|
||||
|
||||
#include "std/function.hpp"
|
||||
|
||||
namespace df
|
||||
{
|
||||
class BaseModelViewAnimation;
|
||||
|
||||
class MyPositionController
|
||||
{
|
||||
|
@ -56,6 +59,7 @@ public:
|
|||
void DragStarted();
|
||||
void DragEnded(m2::PointD const & distance);
|
||||
|
||||
void AnimationStarted(ref_ptr<BaseModelViewAnimation> anim);
|
||||
void ScaleStarted();
|
||||
void Rotated();
|
||||
void CorrectScalePoint(m2::PointD & pt) const;
|
||||
|
@ -137,8 +141,8 @@ private:
|
|||
drape_ptr<MyPosition> m_shape;
|
||||
ref_ptr<Listener> m_listener;
|
||||
|
||||
double m_errorRadius; //< error radius in mercator
|
||||
m2::PointD m_position; //< position in mercator
|
||||
double m_errorRadius; // error radius in mercator
|
||||
m2::PointD m_position; // position in mercator
|
||||
double m_drawDirection;
|
||||
my::HighResTimer m_lastGPSBearing;
|
||||
|
||||
|
@ -148,10 +152,16 @@ private:
|
|||
|
||||
bool m_isVisible;
|
||||
bool m_isDirtyViewport;
|
||||
bool m_needAnimation;
|
||||
bool m_isPendingAnimation = false;
|
||||
|
||||
m2::PointD m_oldPosition; // position in mercator
|
||||
double m_oldDrawDirection;
|
||||
|
||||
class MyPositionAnim;
|
||||
mutable drape_ptr<MyPositionAnim> m_anim;
|
||||
|
||||
using TAnimationCreator = function<void()>;
|
||||
TAnimationCreator m_animCreator;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "drape_frontend/user_event_stream.hpp"
|
||||
#include "drape_frontend/animation_constants.hpp"
|
||||
#include "drape_frontend/visual_params.hpp"
|
||||
|
||||
#include "indexer/scales.hpp"
|
||||
|
@ -24,8 +25,6 @@ uint64_t const kDoubleTapPauseMs = 250;
|
|||
uint64_t const kLongTouchMs = 1000;
|
||||
uint64_t const kKineticDelayMs = 500;
|
||||
|
||||
double const kMaxAnimationTimeSec = 1.5; // in seconds
|
||||
|
||||
float const kForceTapThreshold = 0.75;
|
||||
|
||||
size_t GetValidTouchesCount(array<Touch, 2> const & touches)
|
||||
|
@ -319,6 +318,8 @@ bool UserEventStream::SetScale(m2::PointD const & pxScaleCenter, double factor,
|
|||
{
|
||||
m_animation.reset(new ScaleAnimation(startRect, endRect, aDuration, mDuration,
|
||||
sDuration, glbScaleCenter, offset));
|
||||
if (m_listener)
|
||||
m_listener->OnAnimationStarted(make_ref(m_animation));
|
||||
};
|
||||
|
||||
ScreenBase screen = GetCurrentScreen();
|
||||
|
@ -429,6 +430,8 @@ bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim)
|
|||
double aDuration, double mDuration, double sDuration)
|
||||
{
|
||||
m_animation.reset(new ModelViewAnimation(startRect, endRect, aDuration, mDuration, sDuration));
|
||||
if (m_listener)
|
||||
m_listener->OnAnimationStarted(make_ref(m_animation));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -494,6 +497,8 @@ bool UserEventStream::SetFollowAndRotate(m2::PointD const & userPos, m2::PointD
|
|||
{
|
||||
m_animation.reset(new FollowAndRotateAnimation(startRect, targetLocalRect, userPos,
|
||||
screen.GtoP(userPos), pixelPos, azimuth, duration));
|
||||
if (m_listener)
|
||||
m_listener->OnAnimationStarted(make_ref(m_animation));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -850,6 +855,8 @@ bool UserEventStream::EndDrag(Touch const & t, bool cancelled)
|
|||
if (m_kineticTimer.TimeElapsedAs<milliseconds>().count() >= kKineticDelayMs)
|
||||
{
|
||||
m_animation = m_scroller.CreateKineticAnimation(m_navigator.Screen());
|
||||
if (m_listener)
|
||||
m_listener->OnAnimationStarted(make_ref(m_animation));
|
||||
m_scroller.CancelGrab();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -256,6 +256,8 @@ public:
|
|||
virtual void CorrectGlobalScalePoint(m2::PointD & pt) const = 0;
|
||||
virtual void CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const = 0;
|
||||
virtual void OnScaleEnded() = 0;
|
||||
|
||||
virtual void OnAnimationStarted(ref_ptr<BaseModelViewAnimation> anim) = 0;
|
||||
};
|
||||
|
||||
UserEventStream(TIsCountryLoaded const & fn);
|
||||
|
@ -363,7 +365,7 @@ private:
|
|||
|
||||
array<Touch, 2> m_touches;
|
||||
|
||||
unique_ptr<BaseModelViewAnimation> m_animation;
|
||||
drape_ptr<BaseModelViewAnimation> m_animation;
|
||||
|
||||
unique_ptr<PerspectiveAnimation> m_perspectiveAnimation;
|
||||
unique_ptr<UserEvent> m_pendingEvent;
|
||||
|
|
Loading…
Add table
Reference in a new issue