diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index cf12d836f9..4e11713605 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -258,25 +258,29 @@ void Framework::Touch(int action, Finger const & f1, Finger const & f2, uint8_t switch(eventType) { case MULTITOUCH_DOWN: - event.m_type = df::TouchEvent::TOUCH_DOWN; + event.SetTouchType(df::TouchEvent::TOUCH_DOWN); break; case MULTITOUCH_MOVE: - event.m_type = df::TouchEvent::TOUCH_MOVE; + event.SetTouchType(df::TouchEvent::TOUCH_MOVE); break; case MULTITOUCH_UP: - event.m_type = df::TouchEvent::TOUCH_UP; + event.SetTouchType(df::TouchEvent::TOUCH_UP); break; case MULTITOUCH_CANCEL: - event.m_type = df::TouchEvent::TOUCH_CANCEL; + event.SetTouchType(df::TouchEvent::TOUCH_CANCEL); break; default: return; } - event.m_touches[0].m_location = m2::PointD(f1.m_x, f1.m_y); - event.m_touches[0].m_id = f1.m_id; - event.m_touches[1].m_location = m2::PointD(f2.m_x, f2.m_y); - event.m_touches[1].m_id = f2.m_id; + df::Touch touch; + touch.m_location = m2::PointD(f1.m_x, f1.m_y); + touch.m_id = f1.m_id; + event.SetFirstTouch(touch); + + touch.m_location = m2::PointD(f2.m_x, f2.m_y); + touch.m_id = f2.m_id; + event.SetSecondTouch(touch); event.SetFirstMaskedPointer(maskedPointer); m_work.TouchEvent(event); diff --git a/drape_frontend/animation/parallel_animation.cpp b/drape_frontend/animation/parallel_animation.cpp index bee969b738..3445933a66 100644 --- a/drape_frontend/animation/parallel_animation.cpp +++ b/drape_frontend/animation/parallel_animation.cpp @@ -1,5 +1,7 @@ #include "parallel_animation.hpp" +#include "animation_system.hpp" + namespace df { @@ -7,6 +9,26 @@ ParallelAnimation::ParallelAnimation() : Animation(true /* couldBeInterrupted */, true /* couldBeBlended */) {} +string ParallelAnimation::GetCustomType() const +{ + return m_customType; +} + +void ParallelAnimation::SetCustomType(string const & type) +{ + m_customType = type; +} + +Animation::TAnimObjects const & ParallelAnimation::GetObjects() const +{ + return m_objects; +} + +bool ParallelAnimation::HasObject(TObject object) const +{ + return m_objects.find(object) != m_objects.end(); +} + Animation::TObjectProperties const & ParallelAnimation::GetProperties(TObject object) const { ASSERT(HasObject(object), ()); @@ -17,20 +39,70 @@ bool ParallelAnimation::HasProperty(TObject object, TProperty property) const { if (!HasObject(object)) return false; - TObjectProperties properties = GetProperties(object); + TObjectProperties const & properties = GetProperties(object); return properties.find(property) != properties.end(); } -void ParallelAnimation::AddAnimation(drape_ptr animation) +bool ParallelAnimation::HasTargetProperty(TObject object, TProperty property) const { - TAnimObjects const & objects = animation->GetObjects(); - m_objects.insert(objects.begin(), objects.end()); - for (auto const & object : objects) + ASSERT(!m_animations.empty(), ()); + for (auto const & anim : m_animations) { - TObjectProperties const & properties = animation->GetProperties(object); - m_properties[object].insert(properties.begin(), properties.end()); + if (anim->HasTargetProperty(object, property)) + return true; } - m_animations.push_back(move(animation)); + return false; +} + +void ParallelAnimation::SetMaxDuration(double maxDuration) +{ + for (auto const & anim : m_animations) + anim->SetMaxDuration(maxDuration); +} + +double ParallelAnimation::GetDuration() const +{ + double duration = 0.0; + for (auto const & anim : m_animations) + duration = max(duration, anim->GetDuration()); + return duration; +} + +bool ParallelAnimation::IsFinished() const +{ + return m_animations.empty(); +} + +bool ParallelAnimation::GetProperty(TObject object, TProperty property, PropertyValue & value) const +{ + ASSERT(!m_animations.empty(), ()); + for (auto const & anim : m_animations) + { + if (anim->HasProperty(object, property)) + return anim->GetProperty(object, property, value); + } + return false; +} + +bool ParallelAnimation::GetTargetProperty(TObject object, TProperty property, PropertyValue & value) const +{ + ASSERT(!m_animations.empty(), ()); + for (auto const & anim : m_animations) + { + if (anim->HasProperty(object, property)) + return anim->GetTargetProperty(object, property, value); + } + return false; +} + +void ParallelAnimation::AddAnimation(drape_ptr && animation) +{ + SetCouldBeInterrupted(CouldBeInterrupted() && animation->CouldBeInterrupted()); + SetCouldBeBlended(CouldBeBlended() && animation->CouldBeBlended()); + SetCouldBeRewinded(CouldBeRewinded() && animation->CouldBeRewinded()); + + m_animations.emplace_back(move(animation)); + ObtainObjectProperties(); } void ParallelAnimation::OnStart() @@ -54,7 +126,9 @@ void ParallelAnimation::Advance(double elapsedSeconds) if ((*iter)->IsFinished()) { (*iter)->OnFinish(); + AnimationSystem::Instance().SaveAnimationResult(*(*iter)); iter = m_animations.erase(iter); + ObtainObjectProperties(); } else { @@ -66,8 +140,33 @@ void ParallelAnimation::Advance(double elapsedSeconds) void ParallelAnimation::Finish() { for (auto & anim : m_animations) + { anim->Finish(); + AnimationSystem::Instance().SaveAnimationResult(*anim); + } + m_animations.clear(); + ObtainObjectProperties(); Animation::Finish(); } +void ParallelAnimation::ObtainObjectProperties() +{ + m_objects.clear(); + m_properties.clear(); + + if (m_animations.empty()) + return; + + for (auto const & anim : m_animations) + { + TAnimObjects const & objects = anim->GetObjects(); + m_objects.insert(objects.begin(), objects.end()); + for (auto const & object : objects) + { + TObjectProperties const & properties = anim->GetProperties(object); + m_properties[object].insert(properties.begin(), properties.end()); + } + } +} + } // namespace df diff --git a/drape_frontend/animation/parallel_animation.hpp b/drape_frontend/animation/parallel_animation.hpp index 524ceaf2b7..5fa9952660 100644 --- a/drape_frontend/animation/parallel_animation.hpp +++ b/drape_frontend/animation/parallel_animation.hpp @@ -14,31 +14,53 @@ public: Animation::Type GetType() const override { return Animation::Parallel; } - TAnimObjects const & GetObjects() const override - { - return m_objects; - } - - bool HasObject(TObject object) const override - { - return m_objects.find(object) != m_objects.end(); - } + TAnimObjects const & GetObjects() const override; + bool HasObject(TObject object) const override; TObjectProperties const & GetProperties(TObject object) const override; bool HasProperty(TObject object, TProperty property) const override; + bool HasTargetProperty(TObject object, TProperty property) const override; - void AddAnimation(drape_ptr animation); + string GetCustomType() const override; + void SetCustomType(string const & type); + + void AddAnimation(drape_ptr && animation); void OnStart() override; void OnFinish() override; + void SetMaxDuration(double maxDuration) override; + double GetDuration() const override; + bool IsFinished() const override; + void Advance(double elapsedSeconds) override; void Finish() override; + bool GetProperty(TObject object, TProperty property, PropertyValue & value) const override; + bool GetTargetProperty(TObject object, TProperty property, PropertyValue & value) const override; + + template T const * FindAnimation(Animation::Type type, char const * customType = nullptr) const + { + for (auto const & anim : m_animations) + { + if ((anim->GetType() == type) && + (customType == nullptr || anim->GetCustomType() == customType)) + { + ASSERT(dynamic_cast(anim.get()) != nullptr, ()); + return static_cast(anim.get()); + } + } + return nullptr; + } + private: + void ObtainObjectProperties(); + list> m_animations; TAnimObjects m_objects; map m_properties; + + string m_customType; }; } // namespace df diff --git a/drape_frontend/animation/sequence_animation.cpp b/drape_frontend/animation/sequence_animation.cpp index 13ed1ad7a1..4a2a121fa1 100644 --- a/drape_frontend/animation/sequence_animation.cpp +++ b/drape_frontend/animation/sequence_animation.cpp @@ -41,6 +41,8 @@ Animation::TObjectProperties const & SequenceAnimation::GetProperties(TObject ob bool SequenceAnimation::HasProperty(TObject object, TProperty property) const { + if (!HasObject(object)) + return false; ASSERT(!m_animations.empty(), ()); return m_animations.front()->HasProperty(object, property); } @@ -94,9 +96,9 @@ bool SequenceAnimation::GetTargetProperty(TObject object, TProperty property, Pr return false; } -void SequenceAnimation::AddAnimation(drape_ptr animation) +void SequenceAnimation::AddAnimation(drape_ptr && animation) { - m_animations.push_back(move(animation)); + m_animations.emplace_back(move(animation)); if (m_animations.size() == 1) ObtainObjectProperties(); } diff --git a/drape_frontend/animation/sequence_animation.hpp b/drape_frontend/animation/sequence_animation.hpp index 0cffac5c15..6fbd16c31a 100644 --- a/drape_frontend/animation/sequence_animation.hpp +++ b/drape_frontend/animation/sequence_animation.hpp @@ -30,7 +30,7 @@ public: bool GetProperty(TObject object, TProperty property, PropertyValue &value) const override; bool GetTargetProperty(TObject object, TProperty property, PropertyValue &value) const override; - void AddAnimation(drape_ptr animation); + void AddAnimation(drape_ptr && animation); void OnStart() override; void OnFinish() override; diff --git a/drape_frontend/animation_system.cpp b/drape_frontend/animation_system.cpp index b1acd5c1ff..2e06a55b0f 100644 --- a/drape_frontend/animation_system.cpp +++ b/drape_frontend/animation_system.cpp @@ -159,7 +159,7 @@ AnimationSystem & AnimationSystem::Instance() return animSystem; } -void AnimationSystem::CombineAnimation(drape_ptr animation) +void AnimationSystem::CombineAnimation(drape_ptr && animation) { #ifdef DEBUG_ANIMATIONS LOG(LINFO, ("Combine animation", animation->GetType())); @@ -233,7 +233,7 @@ void AnimationSystem::CombineAnimation(drape_ptr animation) PushAnimation(move(animation)); } -void AnimationSystem::PushAnimation(drape_ptr animation) +void AnimationSystem::PushAnimation(drape_ptr && animation) { #ifdef DEBUG_ANIMATIONS LOG(LINFO, ("Push animation", animation->GetType())); @@ -293,7 +293,7 @@ void AnimationSystem::FinishAnimations(function const { #ifdef DEBUG_ANIMATIONS LOG(LINFO, ("Finish animation", (*it)->GetType(), ", rewind:", rewind, - ", couldBeRewinded:", anim->CouldBeRewinded())); + ", couldBeRewinded:", (*it)->CouldBeRewinded())); changed = true; #endif it = lst.erase(it); diff --git a/drape_frontend/animation_system.hpp b/drape_frontend/animation_system.hpp index 72bd6c7f03..f163f09695 100644 --- a/drape_frontend/animation_system.hpp +++ b/drape_frontend/animation_system.hpp @@ -30,8 +30,8 @@ public: bool AnimationExists(Animation::TObject object) const; bool HasAnimations() const; - void CombineAnimation(drape_ptr animation); - void PushAnimation(drape_ptr animation); + void CombineAnimation(drape_ptr && animation); + void PushAnimation(drape_ptr && animation); void FinishAnimations(Animation::Type type, bool rewind, bool finishAll); void FinishAnimations(Animation::Type type, string const & customType, bool rewind, bool finishAll); diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index c3d8847e9b..9b2698c9b8 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -107,27 +107,27 @@ void DrapeEngine::Invalidate() void DrapeEngine::AddTouchEvent(TouchEvent const & event) { - AddUserEvent(event); + AddUserEvent(make_unique_dp(event)); } void DrapeEngine::Scale(double factor, m2::PointD const & pxPoint, bool isAnim) { - AddUserEvent(ScaleEvent(factor, pxPoint, isAnim)); + AddUserEvent(make_unique_dp(factor, pxPoint, isAnim)); } void DrapeEngine::SetModelViewCenter(m2::PointD const & centerPt, int zoom, bool isAnim) { - AddUserEvent(SetCenterEvent(centerPt, zoom, isAnim)); + AddUserEvent(make_unique_dp(centerPt, zoom, isAnim)); } void DrapeEngine::SetModelViewRect(m2::RectD const & rect, bool applyRotation, int zoom, bool isAnim) { - AddUserEvent(SetRectEvent(rect, applyRotation, zoom, isAnim)); + AddUserEvent(make_unique_dp(rect, applyRotation, zoom, isAnim)); } void DrapeEngine::SetModelViewAnyRect(m2::AnyRectD const & rect, bool isAnim) { - AddUserEvent(SetAnyRectEvent(rect, isAnim)); + AddUserEvent(make_unique_dp(rect, isAnim)); } void DrapeEngine::ClearUserMarksLayer(df::TileKey const & tileKey) @@ -194,9 +194,9 @@ void DrapeEngine::RecacheGui(bool needResetOldGui) MessagePriority::High); } -void DrapeEngine::AddUserEvent(UserEvent const & e) +void DrapeEngine::AddUserEvent(drape_ptr && e) { - m_frontend->AddUserEvent(e); + m_frontend->AddUserEvent(move(e)); } void DrapeEngine::ModelViewChanged(ScreenBase const & screen) @@ -228,7 +228,7 @@ void DrapeEngine::ResizeImpl(int w, int h) { gui::DrapeGui::Instance().SetSurfaceSize(m2::PointF(w, h)); m_viewport.SetViewport(0, 0, w, h); - AddUserEvent(ResizeEvent(w, h)); + AddUserEvent(make_unique_dp(w, h)); } void DrapeEngine::SetCompassInfo(location::CompassInfo const & info) diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index eede48e993..12c86481cc 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -157,7 +157,7 @@ public: TRequestSymbolsSizeCallback const & callback); private: - void AddUserEvent(UserEvent const & e); + void AddUserEvent(drape_ptr && e); void ModelViewChanged(ScreenBase const & screen); void MyPositionModeChanged(location::EMyPositionMode mode, bool routingActive); diff --git a/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp b/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp index 4858841d20..036019ea90 100644 --- a/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp +++ b/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp @@ -36,18 +36,17 @@ 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 /* anim */) override {} void OnTouchMapAction() override {} void OnAnimatedScaleEnded() override {} void AddUserEvent(df::TouchEvent const & event) { - m_stream.AddEvent(event); + m_stream.AddEvent(make_unique_dp(event)); } void SetRect(m2::RectD const & r) { - m_stream.AddEvent(df::SetRectEvent(r, false, -1, false /* isAnim */)); + m_stream.AddEvent(make_unique_dp(r, false, -1, false /* isAnim */)); } void AddExpectation(char const * action) @@ -82,14 +81,20 @@ int touchTimeStamp = 1; df::TouchEvent MakeTouchEvent(m2::PointD const & pt1, m2::PointD const & pt2, df::TouchEvent::ETouchType type) { df::TouchEvent e; - e.m_touches[0].m_location = pt1; - e.m_touches[0].m_id = 1; - e.m_touches[1].m_location = pt2; - e.m_touches[1].m_id = 2; - e.m_type = type; + df::Touch t1; + t1.m_location = pt1; + t1.m_id = 1; + e.SetFirstTouch(t1); + + df::Touch t2; + t2.m_location = pt2; + t2.m_id = 2; + e.SetSecondTouch(t2); + + e.SetTouchType(type); e.SetFirstMaskedPointer(0); e.SetSecondMaskedPointer(1); - e.m_timeStamp = touchTimeStamp++; + e.SetTimeStamp(touchTimeStamp++); return e; } @@ -97,11 +102,15 @@ df::TouchEvent MakeTouchEvent(m2::PointD const & pt1, m2::PointD const & pt2, df df::TouchEvent MakeTouchEvent(m2::PointD const & pt, df::TouchEvent::ETouchType type) { df::TouchEvent e; - e.m_touches[0].m_location = pt; - e.m_touches[0].m_id = 1; - e.m_type = type; + + df::Touch t1; + t1.m_location = pt; + t1.m_id = 1; + e.SetFirstTouch(t1); + + e.SetTouchType(type); e.SetFirstMaskedPointer(0); - e.m_timeStamp = touchTimeStamp++; + e.SetTimeStamp(touchTimeStamp++); return e; } diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 5939d93345..38d71b5e2e 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -627,7 +627,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) case Message::EnablePerspective: { - AddUserEvent(SetAutoPerspectiveEvent(true /* isAutoPerspective */)); + AddUserEvent(make_unique_dp(true /* isAutoPerspective */)); break; } @@ -640,7 +640,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) if (m_enablePerspectiveInNavigation == msg->AllowPerspective() && m_enablePerspectiveInNavigation != screen.isPerspective()) { - AddUserEvent(SetAutoPerspectiveEvent(m_enablePerspectiveInNavigation)); + AddUserEvent(make_unique_dp(m_enablePerspectiveInNavigation)); } #endif @@ -657,7 +657,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) m_myPositionController->EnablePerspectiveInRouting(m_enablePerspectiveInNavigation); if (m_myPositionController->IsInRouting()) { - AddUserEvent(SetAutoPerspectiveEvent(m_enablePerspectiveInNavigation)); + AddUserEvent(make_unique_dp(m_enablePerspectiveInNavigation)); } } break; @@ -722,7 +722,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) int zoom = kDoNotChangeZoom; if (m_currentZoomLevel < scales::GetAddNewPlaceScale()) zoom = scales::GetAddNewPlaceScale(); - AddUserEvent(SetCenterEvent(pt, zoom, true)); + AddUserEvent(make_unique_dp(pt, zoom, true)); } } break; @@ -759,7 +759,7 @@ void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLeve enableAutoZoom); if (m_enablePerspectiveInNavigation) - AddUserEvent(SetAutoPerspectiveEvent(true /* isAutoPerspective */)); + AddUserEvent(make_unique_dp(true /* isAutoPerspective */)); m_overlayTree->SetFollowingMode(true); } @@ -940,7 +940,7 @@ void FrontendRenderer::PullToBoundArea(bool randomPlace, bool applyZoom) int zoom = kDoNotChangeZoom; if (applyZoom && m_currentZoomLevel < scales::GetAddNewPlaceScale()) zoom = scales::GetAddNewPlaceScale(); - AddUserEvent(SetCenterEvent(dest, zoom, true)); + AddUserEvent(make_unique_dp(dest, zoom, true)); } } @@ -1254,7 +1254,7 @@ void FrontendRenderer::RefreshBgColor() void FrontendRenderer::DisablePerspective() { - AddUserEvent(SetAutoPerspectiveEvent(false /* isAutoPerspective */)); + AddUserEvent(make_unique_dp(false /* isAutoPerspective */)); } void FrontendRenderer::CheckIsometryMinScale(ScreenBase const & screen) @@ -1316,13 +1316,14 @@ void FrontendRenderer::OnForceTap(m2::PointD const & pt) void FrontendRenderer::OnDoubleTap(m2::PointD const & pt) { - m_userEventStream.AddEvent(ScaleEvent(2.0 /* scale factor */, pt, true /* animated */)); + m_userEventStream.AddEvent(make_unique_dp(2.0 /* scale factor */, pt, true /* animated */)); } void FrontendRenderer::OnTwoFingersTap() { ScreenBase const & screen = m_userEventStream.GetCurrentScreen(); - m_userEventStream.AddEvent(ScaleEvent(0.5 /* scale factor */, screen.PixelRect().Center(), true /* animated */)); + m_userEventStream.AddEvent(make_unique_dp(0.5 /* scale factor */, screen.PixelRect().Center(), + true /* animated */)); } bool FrontendRenderer::OnSingleTouchFiltrate(m2::PointD const & pt, TouchEvent::ETouchType type) @@ -1400,11 +1401,6 @@ void FrontendRenderer::OnAnimatedScaleEnded() PullToBoundArea(false /* randomPlace */, false /* applyZoom */); } -void FrontendRenderer::OnAnimationStarted(ref_ptr anim) -{ - m_myPositionController->AnimationStarted(anim); -} - void FrontendRenderer::OnTouchMapAction() { m_myPositionController->ResetRoutingNotFollowTimer(); @@ -1596,9 +1592,9 @@ void FrontendRenderer::ReleaseResources() m_contextFactory->getDrawContext()->doneCurrent(); } -void FrontendRenderer::AddUserEvent(UserEvent const & event) +void FrontendRenderer::AddUserEvent(drape_ptr && event) { - m_userEventStream.AddEvent(event); + m_userEventStream.AddEvent(move(event)); if (IsInInfinityWaiting()) CancelMessageWaiting(); } @@ -1608,30 +1604,32 @@ void FrontendRenderer::PositionChanged(m2::PointD const & position) m_userPositionChangedFn(position); } -void FrontendRenderer::ChangeModelView(m2::PointD const & center, int zoomLevel) +void FrontendRenderer::ChangeModelView(m2::PointD const & center, int zoomLevel, TAnimationCreator const & parallelAnimCreator) { - AddUserEvent(SetCenterEvent(center, zoomLevel, true)); + AddUserEvent(make_unique_dp(center, zoomLevel, true, parallelAnimCreator)); } -void FrontendRenderer::ChangeModelView(double azimuth) +void FrontendRenderer::ChangeModelView(double azimuth, TAnimationCreator const & parallelAnimCreator) { - AddUserEvent(RotateEvent(azimuth)); + AddUserEvent(make_unique_dp(azimuth, parallelAnimCreator)); } -void FrontendRenderer::ChangeModelView(m2::RectD const & rect) +void FrontendRenderer::ChangeModelView(m2::RectD const & rect, TAnimationCreator const & parallelAnimCreator) { - AddUserEvent(SetRectEvent(rect, true, kDoNotChangeZoom, true)); + AddUserEvent(make_unique_dp(rect, true, kDoNotChangeZoom, true, parallelAnimCreator)); } void FrontendRenderer::ChangeModelView(m2::PointD const & userPos, double azimuth, - m2::PointD const & pxZero, int preferredZoomLevel) + m2::PointD const & pxZero, int preferredZoomLevel, + TAnimationCreator const & parallelAnimCreator) { - AddUserEvent(FollowAndRotateEvent(userPos, pxZero, azimuth, preferredZoomLevel, true)); + AddUserEvent(make_unique_dp(userPos, pxZero, azimuth, preferredZoomLevel, true, parallelAnimCreator)); } -void FrontendRenderer::ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero) +void FrontendRenderer::ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero, + TAnimationCreator const & parallelAnimCreator) { - AddUserEvent(FollowAndRotateEvent(userPos, pxZero, azimuth, autoScale)); + AddUserEvent(make_unique_dp(userPos, pxZero, azimuth, autoScale, parallelAnimCreator)); } ScreenBase const & FrontendRenderer::ProcessEvents(bool & modelViewChanged, bool & viewportChanged) diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index ab99ec0954..2bb43a25be 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -136,16 +136,17 @@ public: void AfterDrawFrame(); #endif - void AddUserEvent(UserEvent const & event); + void AddUserEvent(drape_ptr && event); /// MyPositionController::Listener void PositionChanged(m2::PointD const & position) override; - void ChangeModelView(m2::PointD const & center, int zoomLevel) 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, int preferredZoomLevel) override; - void ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero) override; + void ChangeModelView(m2::PointD const & center, int zoomLevel, TAnimationCreator const & parallelAnimCreator) override; + void ChangeModelView(double azimuth, TAnimationCreator const & parallelAnimCreator) override; + void ChangeModelView(m2::RectD const & rect, TAnimationCreator const & parallelAnimCreator) override; + void ChangeModelView(m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero, + int preferredZoomLevel, TAnimationCreator const & parallelAnimCreator) override; + void ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero, + TAnimationCreator const & parallelAnimCreator) override; protected: void AcceptMessage(ref_ptr message) override; @@ -197,7 +198,6 @@ private: void CorrectGlobalScalePoint(m2::PointD & pt) const override; void OnScaleEnded() override; void OnAnimatedScaleEnded() override; - void OnAnimationStarted(ref_ptr anim) override; void OnTouchMapAction() override; class Routine : public threads::IRoutine diff --git a/drape_frontend/my_position_controller.cpp b/drape_frontend/my_position_controller.cpp index 5130a4a043..3d868a8efd 100644 --- a/drape_frontend/my_position_controller.cpp +++ b/drape_frontend/my_position_controller.cpp @@ -640,32 +640,37 @@ void MyPositionController::OnCompassTapped() void MyPositionController::ChangeModelView(m2::PointD const & center, int zoomLevel) { if (m_listener) - m_listener->ChangeModelView(center, zoomLevel); + m_listener->ChangeModelView(center, zoomLevel, m_animCreator); + m_animCreator = nullptr; } void MyPositionController::ChangeModelView(double azimuth) { if (m_listener) - m_listener->ChangeModelView(azimuth); + m_listener->ChangeModelView(azimuth, m_animCreator); + m_animCreator = nullptr; } void MyPositionController::ChangeModelView(m2::RectD const & rect) { if (m_listener) - m_listener->ChangeModelView(rect); + m_listener->ChangeModelView(rect, m_animCreator); + m_animCreator = nullptr; } void MyPositionController::ChangeModelView(m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero, int zoomLevel) { if (m_listener) - m_listener->ChangeModelView(userPos, azimuth, pxZero, zoomLevel); + m_listener->ChangeModelView(userPos, azimuth, pxZero, zoomLevel, m_animCreator); + m_animCreator = nullptr; } void MyPositionController::ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero) { if (m_listener) - m_listener->ChangeModelView(autoScale, userPos, azimuth, pxZero); + m_listener->ChangeModelView(autoScale, userPos, azimuth, pxZero, m_animCreator); + m_animCreator = nullptr; } void MyPositionController::UpdateViewport(int zoomLevel) @@ -697,11 +702,14 @@ m2::PointD MyPositionController::GetRoutingRotationPixelCenter() const m_pixelRect.maxY() - m_positionYOffset * VisualParams::Instance().GetVisualScale()); } -m2::PointD MyPositionController::GetDrawablePosition() const +m2::PointD MyPositionController::GetDrawablePosition() { m2::PointD position; if (AnimationSystem::Instance().GetArrowPosition(position)) + { + m_isPendingAnimation = false; return position; + } if (m_isPendingAnimation) return m_oldPosition; @@ -709,11 +717,14 @@ m2::PointD MyPositionController::GetDrawablePosition() const return m_position; } -double MyPositionController::GetDrawableAzimut() const +double MyPositionController::GetDrawableAzimut() { double angle; if (AnimationSystem::Instance().GetArrowAngle(angle)) + { + m_isPendingAnimation = false; return angle; + } if (m_isPendingAnimation) return m_oldDrawDirection; @@ -721,18 +732,6 @@ double MyPositionController::GetDrawableAzimut() const return m_drawDirection; } -void MyPositionController::AnimationStarted(ref_ptr anim) -{ - if (m_isPendingAnimation && m_animCreator != nullptr && anim != nullptr && - (anim->GetType() == Animation::MapFollow || - anim->GetType() == Animation::MapLinear)) - { - m_isPendingAnimation = false; - double const kDoNotChangeDuration = -1.0; - m_animCreator(anim->GetType() == Animation::MapFollow ? anim->GetDuration() : kDoNotChangeDuration); - } -} - void MyPositionController::CreateAnim(m2::PointD const & oldPos, double oldAzimut, ScreenBase const & screen) { double const moveDuration = PositionInterpolator::GetMoveDuration(oldPos, m_position, screen); @@ -741,10 +740,11 @@ void MyPositionController::CreateAnim(m2::PointD const & oldPos, double oldAzimu { if (IsModeChangeViewport()) { - m_animCreator = [this, oldPos, oldAzimut, moveDuration](double correctedDuration) + m_animCreator = [this, moveDuration](double correctedDuration) -> drape_ptr { - AnimationSystem::Instance().CombineAnimation(make_unique_dp(oldPos, m_position, - correctedDuration > 0.0 ? correctedDuration : moveDuration, oldAzimut, m_drawDirection)); + return make_unique_dp(GetDrawablePosition(), m_position, + correctedDuration > 0.0 ? correctedDuration : moveDuration, + GetDrawableAzimut(), m_drawDirection); }; m_oldPosition = oldPos; m_oldDrawDirection = oldAzimut; diff --git a/drape_frontend/my_position_controller.hpp b/drape_frontend/my_position_controller.hpp index 64350ae3e3..00bd0be3bc 100644 --- a/drape_frontend/my_position_controller.hpp +++ b/drape_frontend/my_position_controller.hpp @@ -15,7 +15,9 @@ namespace df { + class Animation; +using TAnimationCreator = function(double)>; class MyPositionController { @@ -26,16 +28,16 @@ public: virtual ~Listener() {} virtual void PositionChanged(m2::PointD const & position) = 0; /// Show map with center in "center" point and current zoom - virtual void ChangeModelView(m2::PointD const & center, int zoomLevel) = 0; + virtual void ChangeModelView(m2::PointD const & center, int zoomLevel, TAnimationCreator const & parallelAnimCreator) = 0; /// Change azimuth of current ModelView - virtual void ChangeModelView(double azimuth) = 0; + virtual void ChangeModelView(double azimuth, TAnimationCreator const & parallelAnimCreator) = 0; /// Somehow show map that "rect" will see - virtual void ChangeModelView(m2::RectD const & rect) = 0; + virtual void ChangeModelView(m2::RectD const & rect, TAnimationCreator const & parallelAnimCreator) = 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, - int zoomLevel) = 0; - virtual void ChangeModelView(double autoScale, - m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero) = 0; + int zoomLevel, TAnimationCreator const & parallelAnimCreator) = 0; + virtual void ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero, + TAnimationCreator const & parallelAnimCreator) = 0; }; MyPositionController(location::EMyPositionMode initMode, double timeInBackground, @@ -57,8 +59,6 @@ public: void ScaleStarted(); void ScaleEnded(); - void AnimationStarted(ref_ptr anim); - void Rotated(); void ResetRoutingNotFollowTimer(); @@ -98,7 +98,7 @@ public: bool IsWaitingForTimers() const; bool IsWaitingForLocation() const; - m2::PointD GetDrawablePosition() const; + m2::PointD GetDrawablePosition(); private: bool IsModeChangeViewport() const; @@ -121,7 +121,7 @@ private: m2::PointD GetRotationPixelCenter() const; m2::PointD GetRoutingRotationPixelCenter() const; - double GetDrawableAzimut() const; + double GetDrawableAzimut(); void CreateAnim(m2::PointD const & oldPos, double oldAzimut, ScreenBase const & screen); bool AlmostCurrentPosition(m2::PointD const & pos) const; @@ -167,7 +167,6 @@ private: bool m_isDirtyAutoZoom; bool m_isPendingAnimation; - using TAnimationCreator = function; TAnimationCreator m_animCreator; bool m_isPositionAssigned; diff --git a/drape_frontend/screen_animations.cpp b/drape_frontend/screen_animations.cpp index b896fa2445..fa8941afac 100644 --- a/drape_frontend/screen_animations.cpp +++ b/drape_frontend/screen_animations.cpp @@ -12,6 +12,8 @@ namespace df string const kPrettyMoveAnim = "PrettyMove"; string const kPrettyFollowAnim = "PrettyFollow"; +string const kParallelFollowAnim = "ParallelFollow"; +string const kParallelLinearAnim = "ParallelLinear"; drape_ptr GetPrettyMoveAnimation(ScreenBase const & startScreen, ScreenBase const & endScreen) { diff --git a/drape_frontend/screen_animations.hpp b/drape_frontend/screen_animations.hpp index ed81f3bd6f..e862eeaf12 100644 --- a/drape_frontend/screen_animations.hpp +++ b/drape_frontend/screen_animations.hpp @@ -9,6 +9,8 @@ namespace df extern string const kPrettyMoveAnim; extern string const kPrettyFollowAnim; +extern string const kParallelFollowAnim; +extern string const kParallelLinearAnim; class SequenceAnimation; class MapLinearAnimation; diff --git a/drape_frontend/user_event_stream.cpp b/drape_frontend/user_event_stream.cpp index 2402f6c540..c51a63338f 100644 --- a/drape_frontend/user_event_stream.cpp +++ b/drape_frontend/user_event_stream.cpp @@ -1,7 +1,8 @@ #include "drape_frontend/user_event_stream.hpp" +#include "drape_frontend/animation/follow_animation.hpp" #include "drape_frontend/animation/linear_animation.hpp" #include "drape_frontend/animation/scale_animation.hpp" -#include "drape_frontend/animation/follow_animation.hpp" +#include "drape_frontend/animation/parallel_animation.hpp" #include "drape_frontend/animation/sequence_animation.hpp" #include "drape_frontend/animation_constants.hpp" #include "drape_frontend/animation_system.hpp" @@ -35,6 +36,8 @@ uint64_t const kKineticDelayMs = 500; float const kForceTapThreshold = 0.75; +double const kDoNotChangeDuration = -1.0; + size_t GetValidTouchesCount(array const & touches) { size_t result = 0; @@ -70,6 +73,16 @@ char const * UserEventStream::END_DOUBLE_TAP_AND_HOLD = "EndDoubleTapAndHold"; uint8_t const TouchEvent::INVALID_MASKED_POINTER = 0xFF; +void TouchEvent::SetFirstTouch(const Touch & touch) +{ + m_touches[0] = touch; +} + +void TouchEvent::SetSecondTouch(const Touch & touch) +{ + m_touches[1] = touch; +} + void TouchEvent::PrepareTouches(array const & previousTouches) { if (GetValidTouchesCount(m_touches) == 2 && GetValidTouchesCount(previousTouches) > 0) @@ -129,17 +142,16 @@ UserEventStream::UserEventStream() { } -void UserEventStream::AddEvent(UserEvent const & event) +void UserEventStream::AddEvent(drape_ptr && event) { lock_guard guard(m_lock); UNUSED_VALUE(guard); - m_events.push_back(event); + m_events.emplace_back(move(event)); } ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool & viewportChanged) { - list events; - + TEventsList events; { lock_guard guard(m_lock); UNUSED_VALUE(guard); @@ -149,64 +161,77 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool m2::RectD const prevPixelRect = GetCurrentScreen().PixelRect(); m_modelViewChanged = !events.empty() || m_state == STATE_SCALE || m_state == STATE_DRAG; - for (UserEvent const & e : events) + for (auto const & e : events) { bool breakAnim = false; - switch (e.m_type) + switch (e->GetType()) { - case UserEvent::EVENT_SCALE: - breakAnim = SetScale(e.m_scaleEvent.m_pxPoint, e.m_scaleEvent.m_factor, e.m_scaleEvent.m_isAnim); - TouchCancel(m_touches); - break; - case UserEvent::EVENT_RESIZE: - m_navigator.OnSize(e.m_resize.m_width, e.m_resize.m_height); - breakAnim = true; - TouchCancel(m_touches); - if (m_state == STATE_DOUBLE_TAP_HOLD) - EndDoubleTapAndHold(m_touches[0]); - break; - case UserEvent::EVENT_SET_ANY_RECT: - breakAnim = SetRect(e.m_anyRect.m_rect, e.m_anyRect.m_isAnim); - TouchCancel(m_touches); - break; - case UserEvent::EVENT_SET_RECT: - breakAnim = SetRect(e.m_rectEvent.m_rect, e.m_rectEvent.m_zoom, e.m_rectEvent.m_applyRotation, e.m_rectEvent.m_isAnim); - TouchCancel(m_touches); - break; - case UserEvent::EVENT_SET_CENTER: - breakAnim = SetCenter(e.m_centerEvent.m_center, e.m_centerEvent.m_zoom, e.m_centerEvent.m_isAnim); - TouchCancel(m_touches); - break; - case UserEvent::EVENT_TOUCH: - breakAnim = ProcessTouch(e.m_touchEvent); - break; - case UserEvent::EVENT_ROTATE: + case UserEvent::EventType::Scale: { - ScreenBase const & screen = m_navigator.Screen(); - if (screen.isPerspective()) - { - m2::PointD pt = screen.PixelRectIn3d().Center(); - breakAnim = SetFollowAndRotate(screen.PtoG(screen.P3dtoP(pt)), pt, - e.m_rotate.m_targetAzimut, kDoNotChangeZoom, kDoNotAutoZoom, - true /* isAnim */, false /* isAutoScale */); - } - else - { - m2::AnyRectD dstRect = GetTargetRect(); - dstRect.SetAngle(e.m_rotate.m_targetAzimut); - breakAnim = SetRect(dstRect, true); - } + ref_ptr scaleEvent = make_ref(e); + breakAnim = OnSetScale(scaleEvent); + TouchCancel(m_touches); } break; - case UserEvent::EVENT_FOLLOW_AND_ROTATE: - breakAnim = SetFollowAndRotate(e.m_followAndRotate.m_userPos, e.m_followAndRotate.m_pixelZero, - e.m_followAndRotate.m_azimuth, e.m_followAndRotate.m_preferredZoomLevel, - e.m_followAndRotate.m_autoScale, - e.m_followAndRotate.m_isAnim, e.m_followAndRotate.m_isAutoScale); + case UserEvent::EventType::Resize: + { + ref_ptr resizeEvent = make_ref(e); + m_navigator.OnSize(resizeEvent->GetWidth(), resizeEvent->GetHeight()); + breakAnim = true; + TouchCancel(m_touches); + if (m_state == STATE_DOUBLE_TAP_HOLD) + EndDoubleTapAndHold(m_touches[0]); + } break; - case UserEvent::EVENT_AUTO_PERSPECTIVE: - SetAutoPerspective(e.m_autoPerspective.m_isAutoPerspective); + case UserEvent::EventType::SetAnyRect: + { + ref_ptr anyRectEvent = make_ref(e); + breakAnim = OnSetAnyRect(anyRectEvent); + TouchCancel(m_touches); + } + break; + case UserEvent::EventType::SetRect: + { + ref_ptr rectEvent = make_ref(e); + breakAnim = OnSetRect(rectEvent); + TouchCancel(m_touches); + } + break; + case UserEvent::EventType::SetCenter: + { + ref_ptr centerEvent = make_ref(e); + breakAnim = OnSetCenter(centerEvent); + TouchCancel(m_touches); + } + break; + case UserEvent::EventType::Touch: + { + ref_ptr touchEvent = make_ref(e); + breakAnim = ProcessTouch(*touchEvent.get()); + } + break; + case UserEvent::EventType::Rotate: + { + ref_ptr rotateEvent = make_ref(e); + breakAnim = OnRotate(rotateEvent); + } + break; + case UserEvent::EventType::FollowAndRotate: + { + ref_ptr followEvent = make_ref(e); + + breakAnim = SetFollowAndRotate(followEvent->GetUserPos(), followEvent->GetPixelZero(), + followEvent->GetAzimuth(), followEvent->GetPreferredZoomLelel(), + followEvent->GetAutoScale(), followEvent->IsAnim(), followEvent->IsAutoScale(), + followEvent->GetParallelAnimCreator()); + } + break; + case UserEvent::EventType::AutoPerspective: + { + ref_ptr perspectiveEvent = make_ref(e); + SetAutoPerspective(perspectiveEvent->IsAutoPerspective()); + } break; default: ASSERT(false, ()); @@ -256,15 +281,23 @@ ScreenBase const & UserEventStream::GetCurrentScreen() const return m_navigator.Screen(); } -bool UserEventStream::SetScale(m2::PointD const & pxScaleCenter, double factor, bool isAnim) +bool UserEventStream::OnSetScale(ref_ptr scaleEvent) { - m2::PointD scaleCenter = pxScaleCenter; + double factor = scaleEvent->GetFactor(); + + m2::PointD scaleCenter = scaleEvent->GetPxPoint(); if (m_listener) m_listener->CorrectScalePoint(scaleCenter); - if (isAnim) + if (scaleEvent->IsAnim()) { - auto const & followAnim = m_animationSystem.FindAnimation(Animation::MapFollow); + auto followAnim = m_animationSystem.FindAnimation(Animation::MapFollow); + if (followAnim == nullptr) + { + auto const parallelAnim = m_animationSystem.FindAnimation(Animation::Parallel, kParallelFollowAnim.c_str()); + if (parallelAnim != nullptr) + followAnim = parallelAnim->FindAnimation(Animation::MapFollow); + } if (followAnim != nullptr && followAnim->HasScale()) { // Scaling is not possible if current follow animation does pixel offset. @@ -273,6 +306,7 @@ bool UserEventStream::SetScale(m2::PointD const & pxScaleCenter, double factor, // Reset follow animation with scaling if we apply scale explicitly. ResetAnimations(Animation::MapFollow); + ResetAnimations(Animation::Parallel, kParallelFollowAnim); } m2::PointD glbScaleCenter = m_navigator.PtoG(m_navigator.P3dtoP(scaleCenter)); @@ -301,9 +335,24 @@ bool UserEventStream::SetScale(m2::PointD const & pxScaleCenter, double factor, return true; } -bool UserEventStream::SetCenter(m2::PointD const & center, int zoom, bool isAnim) +bool UserEventStream::OnSetAnyRect(ref_ptr anyRectEvent) { + return SetRect(anyRectEvent->GetRect(), anyRectEvent->IsAnim()); +} + +bool UserEventStream::OnSetRect(ref_ptr rectEvent) +{ + return SetRect(rectEvent->GetRect(), rectEvent->GetZoom(), rectEvent->GetApplyRotation(), rectEvent->IsAnim(), + rectEvent->GetParallelAnimCreator()); +} + +bool UserEventStream::OnSetCenter(ref_ptr centerEvent) +{ + m2::PointD const & center = centerEvent->GetCenter(); + double zoom = centerEvent->GetZoom(); + ScreenBase screen = GetCurrentScreen(); + if (zoom == kDoNotChangeZoom) { GetTargetScreen(screen); @@ -317,27 +366,47 @@ bool UserEventStream::SetCenter(m2::PointD const & center, int zoom, bool isAnim ShrinkAndScaleInto(screen, df::GetWorldRect()); - return SetScreen(screen, isAnim); + return SetScreen(screen, centerEvent->IsAnim(), centerEvent->GetParallelAnimCreator()); } -bool UserEventStream::SetRect(m2::RectD rect, int zoom, bool applyRotation, bool isAnim) +bool UserEventStream::OnRotate(ref_ptr rotateEvent) +{ + ScreenBase const & screen = m_navigator.Screen(); + if (screen.isPerspective()) + { + m2::PointD pt = screen.PixelRectIn3d().Center(); + return SetFollowAndRotate(screen.PtoG(screen.P3dtoP(pt)), pt, + rotateEvent->GetTargetAzimuth(), kDoNotChangeZoom, kDoNotAutoZoom, + true /* isAnim */, false /* isAutoScale */, + rotateEvent->GetParallelAnimCreator()); + } + + m2::AnyRectD dstRect = GetTargetRect(); + dstRect.SetAngle(rotateEvent->GetTargetAzimuth()); + return SetRect(dstRect, true, rotateEvent->GetParallelAnimCreator()); +} + +bool UserEventStream::SetRect(m2::RectD rect, int zoom, bool applyRotation, bool isAnim, TAnimationCreator parallelAnimCreator) { CheckMinGlobalRect(rect, kDefault3dScale); CheckMinMaxVisibleScale(rect, zoom, kDefault3dScale); m2::AnyRectD targetRect = applyRotation ? ToRotated(m_navigator, rect) : m2::AnyRectD(rect); - return SetRect(targetRect, isAnim); + return SetRect(targetRect, isAnim, parallelAnimCreator); } -bool UserEventStream::SetScreen(ScreenBase const & endScreen, bool isAnim) +bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim, TAnimationCreator parallelAnimCreator) +{ + ScreenBase tmp = GetCurrentScreen(); + tmp.SetFromRects(rect, tmp.PixelRectIn3d()); + tmp.MatchGandP3d(rect.GlobalCenter(), tmp.PixelRectIn3d().Center()); + + return SetScreen(tmp, isAnim, parallelAnimCreator); +} + +bool UserEventStream::SetScreen(ScreenBase const & endScreen, bool isAnim, TAnimationCreator parallelAnimCreator) { if (isAnim) { - auto onStartHandler = [this](ref_ptr animation) - { - if (m_listener) - m_listener->OnAnimationStarted(animation); - }; - ScreenBase const & screen = GetCurrentScreen(); drape_ptr anim = GetRectAnimation(screen, endScreen); @@ -352,8 +421,18 @@ bool UserEventStream::SetScreen(ScreenBase const & endScreen, bool isAnim) if (anim != nullptr) { - anim->SetOnStartAction(onStartHandler); - m_animationSystem.CombineAnimation(move(anim)); + if (parallelAnimCreator != nullptr) + { + drape_ptr parallelAnim = make_unique_dp(); + parallelAnim->SetCustomType(kParallelLinearAnim); + parallelAnim->AddAnimation(parallelAnimCreator(kDoNotChangeDuration)); + parallelAnim->AddAnimation(move(anim)); + m_animationSystem.CombineAnimation(move(parallelAnim)); + } + else + { + m_animationSystem.CombineAnimation(move(anim)); + } return false; } } @@ -363,15 +442,6 @@ bool UserEventStream::SetScreen(ScreenBase const & endScreen, bool isAnim) return true; } -bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim) -{ - ScreenBase tmp = GetCurrentScreen(); - tmp.SetFromRects(rect, tmp.PixelRectIn3d()); - tmp.MatchGandP3d(rect.GlobalCenter(), tmp.PixelRectIn3d().Center()); - - return SetScreen(tmp, isAnim); -} - bool UserEventStream::InterruptFollowAnimations(bool force) { Animation const * followAnim = m_animationSystem.FindAnimation(Animation::MapFollow); @@ -379,26 +449,25 @@ bool UserEventStream::InterruptFollowAnimations(bool force) if (followAnim == nullptr) followAnim = m_animationSystem.FindAnimation(Animation::Sequence, kPrettyFollowAnim.c_str()); + if (followAnim == nullptr) + followAnim = m_animationSystem.FindAnimation(Animation::Parallel, kParallelFollowAnim.c_str()); + + if (followAnim == nullptr) + followAnim = m_animationSystem.FindAnimation(Animation::Parallel, kParallelLinearAnim.c_str()); + if (followAnim != nullptr) { if (force || followAnim->CouldBeInterrupted()) - { - bool const isFollowAnim = followAnim->GetType() == Animation::MapFollow; - ResetAnimations(followAnim->GetType()); - if (isFollowAnim) - ResetAnimations(Animation::Arrow); - } + ResetAnimations(followAnim->GetType(), followAnim->GetCustomType()); else - { return false; - } } return true; } bool UserEventStream::SetFollowAndRotate(m2::PointD const & userPos, m2::PointD const & pixelPos, double azimuth, int preferredZoomLevel, double autoScale, - bool isAnim, bool isAutoScale) + bool isAnim, bool isAutoScale, TAnimationCreator parallelAnimCreator) { // Reset current follow-and-rotate animation if possible. if (isAnim && !InterruptFollowAnimations(false /* force */)) @@ -422,12 +491,6 @@ bool UserEventStream::SetFollowAndRotate(m2::PointD const & userPos, m2::PointD if (isAnim) { - auto onStartHandler = [this](ref_ptr animation) - { - if (m_listener) - m_listener->OnAnimationStarted(animation); - }; - drape_ptr anim; double const moveDuration = PositionInterpolator::GetMoveDuration(currentScreen.GetOrg(), screen.GetOrg(), currentScreen.PixelRectIn3d(), @@ -449,8 +512,18 @@ bool UserEventStream::SetFollowAndRotate(m2::PointD const & userPos, m2::PointD anim->SetCouldBeBlended(false); } - anim->SetOnStartAction(onStartHandler); - m_animationSystem.CombineAnimation(move(anim)); + if (parallelAnimCreator != nullptr) + { + drape_ptr parallelAnim = make_unique_dp(); + parallelAnim->SetCustomType(kParallelFollowAnim); + parallelAnim->AddAnimation(parallelAnimCreator(anim->GetType() == Animation::MapFollow ? anim->GetDuration() : kDoNotChangeDuration)); + parallelAnim->AddAnimation(move(anim)); + m_animationSystem.CombineAnimation(move(parallelAnim)); + } + else + { + m_animationSystem.CombineAnimation(move(anim)); + } return false; } @@ -515,25 +588,25 @@ m2::AnyRectD UserEventStream::GetTargetRect() bool UserEventStream::ProcessTouch(TouchEvent const & touch) { - ASSERT(touch.m_touches[0].m_id != -1, ()); + ASSERT(touch.GetFirstTouch().m_id != -1, ()); TouchEvent touchEvent = touch; touchEvent.PrepareTouches(m_touches); bool isMapTouch = false; - switch (touchEvent.m_type) + switch (touchEvent.GetTouchType()) { case TouchEvent::TOUCH_DOWN: - isMapTouch = TouchDown(touchEvent.m_touches); + isMapTouch = TouchDown(touchEvent.GetTouches()); break; case TouchEvent::TOUCH_MOVE: - isMapTouch = TouchMove(touchEvent.m_touches, touch.m_timeStamp); + isMapTouch = TouchMove(touchEvent.GetTouches(), touch.GetTimeStamp()); break; case TouchEvent::TOUCH_CANCEL: - isMapTouch = TouchCancel(touchEvent.m_touches); + isMapTouch = TouchCancel(touchEvent.GetTouches()); break; case TouchEvent::TOUCH_UP: - isMapTouch = TouchUp(touchEvent.m_touches); + isMapTouch = TouchUp(touchEvent.GetTouches()); break; default: ASSERT(false, ()); @@ -870,14 +943,7 @@ bool UserEventStream::EndDrag(Touch const & t, bool cancelled) { drape_ptr anim = m_scroller.CreateKineticAnimation(m_navigator.Screen()); if (anim != nullptr) - { - anim->SetOnStartAction([this](ref_ptr animation) - { - if (m_listener) - m_listener->OnAnimationStarted(animation); - }); m_animationSystem.CombineAnimation(move(anim)); - } m_scroller.CancelGrab(); return false; } diff --git a/drape_frontend/user_event_stream.hpp b/drape_frontend/user_event_stream.hpp index 9889d5ba7a..bfdb2304b8 100644 --- a/drape_frontend/user_event_stream.hpp +++ b/drape_frontend/user_event_stream.hpp @@ -23,6 +23,28 @@ namespace df int const kDoNotChangeZoom = -1; double const kDoNotAutoZoom = -1.0; +using TAnimationCreator = function(double)>; + +class UserEvent +{ +public: + enum class EventType + { + Touch, + Scale, + SetCenter, + SetRect, + SetAnyRect, + Resize, + Rotate, + FollowAndRotate, + AutoPerspective + }; + + virtual ~UserEvent() {} + virtual EventType GetType() const = 0; +}; + struct Touch { m2::PointF m_location = m2::PointF::Zero(); @@ -30,10 +52,9 @@ struct Touch float m_force = 0.0; // relative force of touch [0.0 - 1.0] }; -struct TouchEvent +class TouchEvent : public UserEvent { - static uint8_t const INVALID_MASKED_POINTER; - +public: TouchEvent() : m_type(TOUCH_CANCEL) , m_timeStamp(my::Timer::LocalTime()) @@ -49,9 +70,23 @@ struct TouchEvent TOUCH_CANCEL }; - ETouchType m_type; - array m_touches; // array of all touches - double m_timeStamp; // seconds + static uint8_t const INVALID_MASKED_POINTER; + + EventType GetType() const override { return UserEvent::EventType::Touch; } + + ETouchType GetTouchType() const { return m_type; } + void SetTouchType(ETouchType touchType) { m_type = touchType; } + + double GetTimeStamp() const { return m_timeStamp; } + void SetTimeStamp(double timeStamp) { m_timeStamp = timeStamp; } + + array const & GetTouches() const { return m_touches; } + + Touch const & GetFirstTouch() const { return m_touches[0]; } + Touch const & GetSecondTouch() const { return m_touches[1]; } + + void SetFirstTouch(Touch const & touch); + void SetSecondTouch(Touch const & touch); void PrepareTouches(array const & previousToches); @@ -70,11 +105,16 @@ struct TouchEvent private: void Swap(); + + ETouchType m_type; + array m_touches; // array of all touches + double m_timeStamp; // seconds uint16_t m_pointersMask; }; -struct ScaleEvent +class ScaleEvent : public UserEvent { +public: ScaleEvent(double factor, m2::PointD const & pxPoint, bool isAnim) : m_factor(factor) , m_pxPoint(pxPoint) @@ -82,56 +122,96 @@ struct ScaleEvent { } + EventType GetType() const override { return UserEvent::EventType::Scale; } + + double GetFactor() const { return m_factor; } + m2::PointD const & GetPxPoint() const { return m_pxPoint; } + bool IsAnim() const { return m_isAnim; } + +private: double m_factor; m2::PointD m_pxPoint; bool m_isAnim; }; -struct SetCenterEvent +class SetCenterEvent : public UserEvent { - SetCenterEvent(m2::PointD const & center, int zoom, bool isAnim) +public: + SetCenterEvent(m2::PointD const & center, int zoom, bool isAnim, + TAnimationCreator const & parallelAnimCreator = nullptr) : m_center(center) , m_zoom(zoom) , m_isAnim(isAnim) + , m_parallelAnimCreator(parallelAnimCreator) { } + EventType GetType() const override { return UserEvent::EventType::SetCenter; } + + m2::PointD const & GetCenter() const { return m_center; } + int GetZoom() const { return m_zoom; } + bool IsAnim() const { return m_isAnim; } + TAnimationCreator const & GetParallelAnimCreator() const { return m_parallelAnimCreator; } + +private: m2::PointD m_center; // center point in mercator int m_zoom; // if zoom == -1, then zoom level will'n change bool m_isAnim; + TAnimationCreator m_parallelAnimCreator; }; -struct SetRectEvent +class SetRectEvent : public UserEvent { - SetRectEvent(m2::RectD const & rect, bool rotate, int zoom, bool isAnim) +public: + SetRectEvent(m2::RectD const & rect, bool rotate, int zoom, bool isAnim, + TAnimationCreator const & parallelAnimCreator = nullptr) : m_rect(rect) , m_applyRotation(rotate) , m_zoom(zoom) , m_isAnim(isAnim) + , m_parallelAnimCreator(parallelAnimCreator) { } + EventType GetType() const override { return UserEvent::EventType::SetRect; } + + m2::RectD const & GetRect() const { return m_rect; } + bool GetApplyRotation() const { return m_applyRotation; } + int GetZoom() const { return m_zoom; } + bool IsAnim() const { return m_isAnim; } + TAnimationCreator const & GetParallelAnimCreator() const { return m_parallelAnimCreator; } + +private: m2::RectD m_rect; // destination mercator rect bool m_applyRotation; // if true, current rotation will be apply to m_rect int m_zoom; // if zoom == -1, then zoom level will'n change bool m_isAnim; + TAnimationCreator m_parallelAnimCreator; }; -struct SetAnyRectEvent +class SetAnyRectEvent : public UserEvent { +public: SetAnyRectEvent(m2::AnyRectD const & rect, bool isAnim) : m_rect(rect) , m_isAnim(isAnim) {} + EventType GetType() const override { return UserEvent::EventType::SetAnyRect; } + + m2::AnyRectD const & GetRect() const { return m_rect; } + bool IsAnim() const { return m_isAnim; } + +private: m2::AnyRectD m_rect; // destination mercator rect bool m_isAnim; }; -struct FollowAndRotateEvent +class FollowAndRotateEvent : public UserEvent { +public: FollowAndRotateEvent(m2::PointD const & userPos, m2::PointD const & pixelZero, - double azimuth, double autoScale) + double azimuth, double autoScale, TAnimationCreator const & parallelAnimCreator = nullptr) : m_userPos(userPos) , m_pixelZero(pixelZero) , m_azimuth(azimuth) @@ -139,11 +219,13 @@ struct FollowAndRotateEvent , m_autoScale(autoScale) , m_isAutoScale(true) , m_isAnim(true) + , m_parallelAnimCreator(parallelAnimCreator) { } FollowAndRotateEvent(m2::PointD const & userPos, m2::PointD const & pixelZero, - double azimuth, int preferredZoomLevel, bool isAnim) + double azimuth, int preferredZoomLevel, + bool isAnim, TAnimationCreator const & parallelAnimCreator = nullptr) : m_userPos(userPos) , m_pixelZero(pixelZero) , m_azimuth(azimuth) @@ -151,8 +233,21 @@ struct FollowAndRotateEvent , m_autoScale(kDoNotAutoZoom) , m_isAutoScale(false) , m_isAnim(isAnim) + , m_parallelAnimCreator(parallelAnimCreator) {} + EventType GetType() const override { return UserEvent::EventType::FollowAndRotate; } + + m2::PointD const & GetUserPos() const { return m_userPos; } + m2::PointD const & GetPixelZero() const { return m_pixelZero; } + double GetAzimuth() const { return m_azimuth; } + int GetPreferredZoomLelel() const { return m_preferredZoomLevel; } + double GetAutoScale() const { return m_autoScale; } + bool IsAutoScale() const { return m_isAutoScale; } + bool IsAnim() const { return m_isAnim; } + TAnimationCreator const & GetParallelAnimCreator() const { return m_parallelAnimCreator; } + +private: m2::PointD m_userPos; m2::PointD m_pixelZero; double m_azimuth; @@ -160,72 +255,57 @@ struct FollowAndRotateEvent double m_autoScale; bool m_isAutoScale; bool m_isAnim; + TAnimationCreator m_parallelAnimCreator; }; -struct SetAutoPerspectiveEvent +class SetAutoPerspectiveEvent : public UserEvent { +public: SetAutoPerspectiveEvent(bool isAutoPerspective) : m_isAutoPerspective(isAutoPerspective) {} + EventType GetType() const override { return UserEvent::EventType::AutoPerspective; } + + bool IsAutoPerspective() const { return m_isAutoPerspective; } + +private: bool m_isAutoPerspective; }; -struct RotateEvent +class RotateEvent : public UserEvent { - RotateEvent(double targetAzimut) : m_targetAzimut(targetAzimut) {} +public: + RotateEvent(double targetAzimut, TAnimationCreator const & parallelAnimCreator = nullptr) + : m_targetAzimut(targetAzimut) + , m_parallelAnimCreator(parallelAnimCreator) + {} + EventType GetType() const override { return UserEvent::EventType::Rotate; } + + double GetTargetAzimuth() const { return m_targetAzimut; } + TAnimationCreator const & GetParallelAnimCreator() const { return m_parallelAnimCreator; } + +private: double m_targetAzimut; + TAnimationCreator m_parallelAnimCreator; }; -struct ResizeEvent +class ResizeEvent : public UserEvent { +public: ResizeEvent(uint32_t w, uint32_t h) : m_width(w), m_height(h) {} + EventType GetType() const override { return UserEvent::EventType::Resize; } + + uint32_t GetWidth() const { return m_width; } + uint32_t GetHeight() const { return m_height; } + +private: uint32_t m_width; uint32_t m_height; }; -struct UserEvent -{ - enum EEventType - { - EVENT_TOUCH, - EVENT_SCALE, - EVENT_SET_CENTER, - EVENT_SET_RECT, - EVENT_SET_ANY_RECT, - EVENT_RESIZE, - EVENT_ROTATE, - EVENT_FOLLOW_AND_ROTATE, - EVENT_AUTO_PERSPECTIVE - }; - - UserEvent(TouchEvent const & e) : m_type(EVENT_TOUCH) { m_touchEvent = e; } - UserEvent(ScaleEvent const & e) : m_type(EVENT_SCALE) { m_scaleEvent = e; } - UserEvent(SetCenterEvent const & e) : m_type(EVENT_SET_CENTER) { m_centerEvent = e; } - UserEvent(SetRectEvent const & e) : m_type(EVENT_SET_RECT) { m_rectEvent = e; } - UserEvent(SetAnyRectEvent const & e) : m_type(EVENT_SET_ANY_RECT) { m_anyRect = e; } - UserEvent(ResizeEvent const & e) : m_type(EVENT_RESIZE) { m_resize = e; } - UserEvent(RotateEvent const & e) : m_type(EVENT_ROTATE) { m_rotate = e; } - UserEvent(FollowAndRotateEvent const & e) : m_type(EVENT_FOLLOW_AND_ROTATE) { m_followAndRotate = e; } - UserEvent(SetAutoPerspectiveEvent const & e) : m_type(EVENT_AUTO_PERSPECTIVE) { m_autoPerspective = e; } - - EEventType m_type; - union - { - TouchEvent m_touchEvent; - ScaleEvent m_scaleEvent; - SetCenterEvent m_centerEvent; - SetRectEvent m_rectEvent; - SetAnyRectEvent m_anyRect; - ResizeEvent m_resize; - RotateEvent m_rotate; - FollowAndRotateEvent m_followAndRotate; - SetAutoPerspectiveEvent m_autoPerspective; - }; -}; - class UserEventStream { public: @@ -250,13 +330,11 @@ public: virtual void OnScaleEnded() = 0; virtual void OnAnimatedScaleEnded() = 0; - virtual void OnAnimationStarted(ref_ptr anim) = 0; - virtual void OnTouchMapAction() = 0; }; UserEventStream(); - void AddEvent(UserEvent const & event); + void AddEvent(drape_ptr && event); ScreenBase const & ProcessEvents(bool & modelViewChanged, bool & viewportChanged); ScreenBase const & GetCurrentScreen() const; @@ -294,14 +372,22 @@ public: #endif private: - bool SetScale(m2::PointD const & pxScaleCenter, double factor, bool isAnim); - bool SetCenter(m2::PointD const & center, int zoom, bool isAnim); - bool SetRect(m2::RectD rect, int zoom, bool applyRotation, bool isAnim); - bool SetRect(m2::AnyRectD const & rect, bool isAnim); - bool SetScreen(ScreenBase const & screen, bool isAnim); + bool OnSetScale(ref_ptr scaleEvent); + bool OnSetAnyRect(ref_ptr anyRectEvent); + bool OnSetRect(ref_ptr rectEvent); + bool OnSetCenter(ref_ptr centerEvent); + bool OnRotate(ref_ptr rotateEvent); + + bool SetRect(m2::RectD rect, int zoom, bool applyRotation, bool isAnim, + TAnimationCreator parallelAnimCreator = nullptr); + bool SetRect(m2::AnyRectD const & rect, bool isAnim, TAnimationCreator parallelAnimCreator = nullptr); + + bool SetScreen(ScreenBase const & screen, bool isAnim, + TAnimationCreator parallelAnimCreator = nullptr); bool SetFollowAndRotate(m2::PointD const & userPos, m2::PointD const & pixelPos, double azimuth, int preferredZoomLevel, double autoScale, - bool isAnim, bool isAutoScale); + bool isAnim, bool isAutoScale, + TAnimationCreator parallelAnimCreator = nullptr); void SetAutoPerspective(bool isAutoPerspective); m2::AnyRectD GetCurrentRect() const; @@ -351,7 +437,8 @@ private: bool CheckDrag(array const & touches, double threshold) const; - list m_events; + using TEventsList = list>; + TEventsList m_events; mutable mutex m_lock; Navigator m_navigator; diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm index 0695b0e8fe..8318fa41a6 100644 --- a/iphone/Maps/Classes/MapViewController.mm +++ b/iphone/Maps/Classes/MapViewController.mm @@ -147,9 +147,9 @@ BOOL gIsFirstMyPositionMode = YES; { int64_t id = reinterpret_cast(touch); int8_t pointerIndex = df::TouchEvent::INVALID_MASKED_POINTER; - if (e.m_touches[0].m_id == id) + if (e.GetFirstTouch().m_id == id) pointerIndex = 0; - else if (e.m_touches[1].m_id == id) + else if (e.GetSecondTouch().m_id == id) pointerIndex = 1; if (e.GetFirstMaskedPointer() == df::TouchEvent::INVALID_MASKED_POINTER) @@ -172,19 +172,27 @@ BOOL gIsFirstMyPositionMode = YES; df::TouchEvent e; UITouch * touch = [allTouches objectAtIndex:0]; CGPoint const pt = [touch locationInView:v]; - e.m_type = type; - e.m_touches[0].m_id = reinterpret_cast(touch); - e.m_touches[0].m_location = m2::PointD(pt.x * scaleFactor, pt.y * scaleFactor); + + e.SetTouchType(type); + + df::Touch t0; + t0.m_location = m2::PointD(pt.x * scaleFactor, pt.y * scaleFactor); + t0.m_id = reinterpret_cast(touch); if ([self hasForceTouch]) - e.m_touches[0].m_force = touch.force / touch.maximumPossibleForce; + t0.m_force = touch.force / touch.maximumPossibleForce; + e.SetFirstTouch(t0); + if (allTouches.count > 1) { UITouch * touch = [allTouches objectAtIndex:1]; CGPoint const pt = [touch locationInView:v]; - e.m_touches[1].m_id = reinterpret_cast(touch); - e.m_touches[1].m_location = m2::PointD(pt.x * scaleFactor, pt.y * scaleFactor); + + df::Touch t1; + t1.m_location = m2::PointD(pt.x * scaleFactor, pt.y * scaleFactor); + t1.m_id = reinterpret_cast(touch); if ([self hasForceTouch]) - e.m_touches[1].m_force = touch.force / touch.maximumPossibleForce; + t1.m_force = touch.force / touch.maximumPossibleForce; + e.SetSecondTouch(t1); } NSArray * toggledTouches = [touches allObjects]; diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp index 16a8c45380..9c649fb0e5 100644 --- a/qt/draw_widget.cpp +++ b/qt/draw_widget.cpp @@ -425,10 +425,12 @@ void DrawWidget::keyPressEvent(QKeyEvent * e) e->key() == Qt::Key_Control) { df::TouchEvent event; - event.m_type = df::TouchEvent::TOUCH_DOWN; - event.m_touches[0].m_id = 0; - event.m_touches[0].m_location = m2::PointD(L2D(QCursor::pos().x()), L2D(QCursor::pos().y())); - event.m_touches[1] = GetSymmetrical(event.m_touches[0]); + event.SetTouchType(df::TouchEvent::TOUCH_DOWN); + df::Touch touch; + touch.m_id = 0; + touch.m_location = m2::PointD(L2D(QCursor::pos().x()), L2D(QCursor::pos().y())); + event.SetFirstTouch(touch); + event.SetSecondTouch(GetSymmetrical(touch)); m_framework->TouchEvent(event); } @@ -442,10 +444,12 @@ void DrawWidget::keyReleaseEvent(QKeyEvent * e) e->key() == Qt::Key_Control) { df::TouchEvent event; - event.m_type = df::TouchEvent::TOUCH_UP; - event.m_touches[0].m_id = 0; - event.m_touches[0].m_location = m2::PointD(L2D(QCursor::pos().x()), L2D(QCursor::pos().y())); - event.m_touches[1] = GetSymmetrical(event.m_touches[0]); + event.SetTouchType(df::TouchEvent::TOUCH_UP); + df::Touch touch; + touch.m_id = 0; + touch.m_location = m2::PointD(L2D(QCursor::pos().x()), L2D(QCursor::pos().y())); + event.SetFirstTouch(touch); + event.SetSecondTouch(GetSymmetrical(touch)); m_framework->TouchEvent(event); } @@ -645,10 +649,10 @@ df::Touch DrawWidget::GetSymmetrical(df::Touch const & touch) df::TouchEvent DrawWidget::GetTouchEvent(QMouseEvent * e, df::TouchEvent::ETouchType type) { df::TouchEvent event; - event.m_type = type; - event.m_touches[0] = GetTouch(e); + event.SetTouchType(type); + event.SetFirstTouch(GetTouch(e)); if (IsRotation(e)) - event.m_touches[1] = GetSymmetrical(event.m_touches[0]); + event.SetSecondTouch(GetSymmetrical(event.GetFirstTouch())); return event; }