forked from organicmaps/organicmaps
Merge pull request #3408 from darina/smooth-arrow-animation
Smooth arrow animation
This commit is contained in:
commit
f4717cab34
7 changed files with 104 additions and 23 deletions
|
@ -83,7 +83,7 @@ double MapFollowAnimation::GetDuration() const
|
|||
|
||||
double MapFollowAnimation::CalculateDuration() const
|
||||
{
|
||||
return max(max(m_angleInterpolator.GetDuration(),
|
||||
return max(max(m_pixelPosInterpolator.GetDuration(),
|
||||
m_angleInterpolator.GetDuration()), m_scaleInterpolator.GetDuration());
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,9 @@ PositionInterpolator::PositionInterpolator(double duration, double delay,
|
|||
, m_startPosition(startPosition)
|
||||
, m_endPosition(endPosition)
|
||||
, m_position(startPosition)
|
||||
{}
|
||||
{
|
||||
SetActive(m_startPosition != m_endPosition);
|
||||
}
|
||||
|
||||
PositionInterpolator::PositionInterpolator(m2::PointD const & startPosition,
|
||||
m2::PointD const & endPosition,
|
||||
|
@ -112,18 +114,18 @@ PositionInterpolator::PositionInterpolator(double delay, m2::PointD const & star
|
|||
SetActive(m_startPosition != m_endPosition);
|
||||
}
|
||||
|
||||
PositionInterpolator::PositionInterpolator(m2::PointD const & startPosition,
|
||||
m2::PointD const & endPosition,
|
||||
PositionInterpolator::PositionInterpolator(m2::PointD const & startPxPosition,
|
||||
m2::PointD const & endPxPosition,
|
||||
m2::RectD const & pixelRect)
|
||||
: PositionInterpolator(0.0 /* delay */, startPosition, endPosition, pixelRect)
|
||||
: PositionInterpolator(0.0 /* delay */, startPxPosition, endPxPosition, pixelRect)
|
||||
{}
|
||||
|
||||
PositionInterpolator::PositionInterpolator(double delay, m2::PointD const & startPosition,
|
||||
m2::PointD const & endPosition, m2::RectD const & pixelRect)
|
||||
: Interpolator(PositionInterpolator::GetPixelMoveDuration(startPosition, endPosition, pixelRect), delay)
|
||||
, m_startPosition(startPosition)
|
||||
, m_endPosition(endPosition)
|
||||
, m_position(startPosition)
|
||||
PositionInterpolator::PositionInterpolator(double delay, m2::PointD const & startPxPosition,
|
||||
m2::PointD const & endPxPosition, m2::RectD const & pixelRect)
|
||||
: Interpolator(PositionInterpolator::GetPixelMoveDuration(startPxPosition, endPxPosition, pixelRect), delay)
|
||||
, m_startPosition(startPxPosition)
|
||||
, m_endPosition(endPxPosition)
|
||||
, m_position(startPxPosition)
|
||||
{
|
||||
SetActive(m_startPosition != m_endPosition);
|
||||
}
|
||||
|
@ -135,7 +137,7 @@ double PositionInterpolator::GetMoveDuration(m2::PointD const & startPosition,
|
|||
{
|
||||
return GetPixelMoveDuration(convertor.GtoP(startPosition),
|
||||
convertor.GtoP(endPosition),
|
||||
convertor.PixelRectIn3d());
|
||||
convertor.PixelRect());
|
||||
}
|
||||
|
||||
double PositionInterpolator::GetPixelMoveDuration(m2::PointD const & startPosition,
|
||||
|
|
|
@ -48,11 +48,11 @@ public:
|
|||
PositionInterpolator(double delay, m2::PointD const & startPosition,
|
||||
m2::PointD const & endPosition,
|
||||
ScreenBase const & convertor);
|
||||
PositionInterpolator(m2::PointD const & startPosition,
|
||||
m2::PointD const & endPosition,
|
||||
PositionInterpolator(m2::PointD const & startPxPosition,
|
||||
m2::PointD const & endPxPosition,
|
||||
m2::RectD const & pixelRect);
|
||||
PositionInterpolator(double delay, m2::PointD const & startPosition,
|
||||
m2::PointD const & endPosition,
|
||||
PositionInterpolator(double delay, m2::PointD const & startPxPosition,
|
||||
m2::PointD const & endPxPosition,
|
||||
m2::RectD const & pixelRect);
|
||||
|
||||
static double GetMoveDuration(m2::PointD const & startPosition,
|
||||
|
|
|
@ -138,7 +138,7 @@ bool AnimationSystem::SwitchPerspective(Animation::SwitchPerspectiveParams & par
|
|||
bool AnimationSystem::GetArrowPosition(m2::PointD & position)
|
||||
{
|
||||
Animation::PropertyValue value;
|
||||
if (GetProperty(Animation::Arrow, Animation::Position, value))
|
||||
if (GetProperty(Animation::MyPositionArrow, Animation::Position, value))
|
||||
{
|
||||
position = value.m_valuePointD;
|
||||
return true;
|
||||
|
@ -149,7 +149,7 @@ bool AnimationSystem::GetArrowPosition(m2::PointD & position)
|
|||
bool AnimationSystem::GetArrowAngle(double & angle)
|
||||
{
|
||||
Animation::PropertyValue value;
|
||||
if (GetProperty(Animation::Arrow, Animation::Angle, value))
|
||||
if (GetProperty(Animation::MyPositionArrow, Animation::Angle, value))
|
||||
{
|
||||
angle = value.m_valueD;
|
||||
return true;
|
||||
|
@ -188,6 +188,9 @@ AnimationSystem & AnimationSystem::Instance()
|
|||
|
||||
void AnimationSystem::CombineAnimation(drape_ptr<Animation> animation)
|
||||
{
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
LOG(LINFO, ("Combine animation", animation->GetType()));
|
||||
#endif
|
||||
TAnimationList interruptedAnimations;
|
||||
bool startImmediately = true;
|
||||
for (auto & pList : m_animationChain)
|
||||
|
@ -200,6 +203,9 @@ void AnimationSystem::CombineAnimation(drape_ptr<Animation> animation)
|
|||
auto & anim = *it;
|
||||
if (anim->GetInterruptedOnCombine())
|
||||
{
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
LOG(LINFO, ("Interrupted on combine", anim->GetType()));
|
||||
#endif
|
||||
interruptedAnimations.splice(interruptedAnimations.end(), lst, it++);
|
||||
}
|
||||
else if (!anim->CouldBeBlendedWith(*animation))
|
||||
|
@ -209,6 +215,9 @@ void AnimationSystem::CombineAnimation(drape_ptr<Animation> animation)
|
|||
couldBeBlended = false;
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
LOG(LINFO, ("Couldn't be blended, interrupted", anim->GetType()));
|
||||
#endif
|
||||
interruptedAnimations.splice(interruptedAnimations.end(), lst, it++);
|
||||
}
|
||||
else
|
||||
|
@ -225,13 +234,23 @@ void AnimationSystem::CombineAnimation(drape_ptr<Animation> animation)
|
|||
|
||||
if (couldBeBlended)
|
||||
{
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
LOG(LINFO, ("Animation blended"));
|
||||
#endif
|
||||
lst.emplace_back(move(animation));
|
||||
if (startImmediately)
|
||||
lst.back()->OnStart();
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
Print();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else if (m_animationChain.size() > 1 && animation->CouldBeInterrupted())
|
||||
{
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
LOG(LINFO, ("Animation rejected"));
|
||||
Print();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -243,6 +262,10 @@ void AnimationSystem::CombineAnimation(drape_ptr<Animation> animation)
|
|||
|
||||
void AnimationSystem::PushAnimation(drape_ptr<Animation> animation)
|
||||
{
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
LOG(LINFO, ("Push animation", animation->GetType()));
|
||||
#endif
|
||||
|
||||
shared_ptr<TAnimationList> pList(new TAnimationList());
|
||||
pList->emplace_back(move(animation));
|
||||
|
||||
|
@ -250,6 +273,10 @@ void AnimationSystem::PushAnimation(drape_ptr<Animation> animation)
|
|||
m_animationChain.push_back(pList);
|
||||
if (startImmediately)
|
||||
pList->front()->OnStart();
|
||||
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
Print();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AnimationSystem::FinishAnimations(function<bool(shared_ptr<Animation> const &)> const & predicate,
|
||||
|
@ -258,15 +285,27 @@ void AnimationSystem::FinishAnimations(function<bool(shared_ptr<Animation> const
|
|||
if (m_animationChain.empty())
|
||||
return;
|
||||
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
bool changed = false;
|
||||
#endif
|
||||
|
||||
TAnimationList & frontList = *(m_animationChain.front());
|
||||
TAnimationList finishAnimations;
|
||||
for (auto it = frontList.begin(); it != frontList.end();)
|
||||
{
|
||||
auto & anim = *it;
|
||||
if (predicate(anim))
|
||||
{
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
LOG(LINFO, ("Finish animation", anim->GetType(), ", rewind:", rewind));
|
||||
changed = true;
|
||||
#endif
|
||||
finishAnimations.splice(finishAnimations.end(), frontList, it++);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
if (finishAll)
|
||||
|
@ -277,9 +316,17 @@ void AnimationSystem::FinishAnimations(function<bool(shared_ptr<Animation> const
|
|||
for (auto it = lst.begin(); it != lst.end();)
|
||||
{
|
||||
if (predicate(*it))
|
||||
{
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
LOG(LINFO, ("Finish animation", (*it)->GetType(), ", rewind:", rewind));
|
||||
changed = true;
|
||||
#endif
|
||||
it = lst.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -291,6 +338,11 @@ void AnimationSystem::FinishAnimations(function<bool(shared_ptr<Animation> const
|
|||
SaveAnimationResult(*anim);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
if (changed)
|
||||
Print();
|
||||
#endif
|
||||
|
||||
if (frontList.empty())
|
||||
StartNextAnimations();
|
||||
}
|
||||
|
@ -336,6 +388,26 @@ void AnimationSystem::Advance(double elapsedSeconds)
|
|||
StartNextAnimations();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
void AnimationSystem::Print()
|
||||
{
|
||||
LOG(LINFO, ("-----------------------Animation chain begin-----------------------"));
|
||||
for (size_t i = 0, sz = m_animationChain.size(); i < sz; ++i)
|
||||
{
|
||||
auto & lst = *m_animationChain[i];
|
||||
if (i > 0 && i < sz - 1)
|
||||
LOG(LINFO, ("- - - - - - - - - - - - Next parallel block - - - - - - - - - - - -"));
|
||||
for (auto it = lst.begin(); it != lst.end(); ++it)
|
||||
{
|
||||
auto & anim = *it;
|
||||
LOG(LINFO, ("Type:", anim->GetType()));
|
||||
}
|
||||
|
||||
}
|
||||
LOG(LINFO, ("========================Animation chain end========================"));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool AnimationSystem::GetProperty(Animation::TObject object, Animation::TProperty property,
|
||||
Animation::PropertyValue & value) const
|
||||
{
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "std/shared_ptr.hpp"
|
||||
#include "std/string.hpp"
|
||||
|
||||
//#define DEBUG_ANIMATIONS
|
||||
|
||||
namespace df
|
||||
{
|
||||
|
||||
|
@ -91,6 +93,10 @@ private:
|
|||
void FinishAnimations(function<bool(shared_ptr<Animation> const &)> const & predicate,
|
||||
bool rewind, bool finishAll);
|
||||
|
||||
#ifdef DEBUG_ANIMATIONS
|
||||
void Print();
|
||||
#endif
|
||||
|
||||
using TAnimationList = list<shared_ptr<Animation>>;
|
||||
using TAnimationChain = deque<shared_ptr<TAnimationList>>;
|
||||
using TPropertyCache = map<pair<Animation::TObject, Animation::TProperty>, Animation::PropertyValue>;
|
||||
|
|
|
@ -618,7 +618,8 @@ void MyPositionController::AnimationStarted(ref_ptr<Animation> anim)
|
|||
anim->GetType() == Animation::MapLinear))
|
||||
{
|
||||
m_isPendingAnimation = false;
|
||||
m_animCreator();
|
||||
double const kDoNotChangeDuration = -1.0;
|
||||
m_animCreator(anim->GetType() == Animation::MapFollow ? anim->GetDuration() : kDoNotChangeDuration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -630,10 +631,10 @@ void MyPositionController::CreateAnim(m2::PointD const & oldPos, double oldAzimu
|
|||
{
|
||||
if (IsModeChangeViewport())
|
||||
{
|
||||
m_animCreator = [this, oldPos, oldAzimut, moveDuration]()
|
||||
m_animCreator = [this, oldPos, oldAzimut, moveDuration](double correctedDuration)
|
||||
{
|
||||
AnimationSystem::Instance().CombineAnimation(make_unique_dp<ArrowAnimation>(oldPos, m_position, moveDuration,
|
||||
oldAzimut, m_drawDirection));
|
||||
AnimationSystem::Instance().CombineAnimation(make_unique_dp<ArrowAnimation>(oldPos, m_position,
|
||||
correctedDuration > 0.0 ? correctedDuration : moveDuration, oldAzimut, m_drawDirection));
|
||||
};
|
||||
m_oldPosition = oldPos;
|
||||
m_oldDrawDirection = oldAzimut;
|
||||
|
|
|
@ -161,7 +161,7 @@ private:
|
|||
bool m_isDirtyViewport;
|
||||
bool m_isPendingAnimation;
|
||||
|
||||
using TAnimationCreator = function<void()>;
|
||||
using TAnimationCreator = function<void(double)>;
|
||||
TAnimationCreator m_animCreator;
|
||||
|
||||
bool m_isPositionAssigned;
|
||||
|
|
Loading…
Add table
Reference in a new issue