Merge pull request #1231 from darina/arrow-position-fix

Fixed arrow position in follow and follow-and-rotate modes.
This commit is contained in:
Roman Kuznetsov 2016-01-06 11:43:25 +03:00
commit fcc93fb787
11 changed files with 88 additions and 34 deletions

View file

@ -0,0 +1,7 @@
#pragma once
namespace df
{
double const kMaxAnimationTimeSec = 1.5; // in seconds
} // namespace df

View file

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

View file

@ -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)
{

View file

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

View file

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

View file

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

View file

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

View file

@ -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()

View file

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

View file

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

View file

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