Merge pull request #3408 from darina/smooth-arrow-animation

Smooth arrow animation
This commit is contained in:
Roman Kuznetsov 2016-06-01 17:29:47 +03:00
commit f4717cab34
7 changed files with 104 additions and 23 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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