diff --git a/drape_frontend/animation/model_view_animation.cpp b/drape_frontend/animation/model_view_animation.cpp index 0b40eb48fd..e0bfd59fdd 100644 --- a/drape_frontend/animation/model_view_animation.cpp +++ b/drape_frontend/animation/model_view_animation.cpp @@ -8,8 +8,7 @@ namespace double GetMoveDuration(m2::PointD const & startPx, m2::PointD const & endPt, int minDisplaySize) { - double const length = (endPt - startPx).Length(); - return (length / minDisplaySize); + return max(0.5, min(0.5, 0.5 * startPx.Length(endPt) / 50.0)); } double GetRotateDuration(double const & startAngle, double const & endAngle) diff --git a/drape_frontend/animation/opacity_animation.cpp b/drape_frontend/animation/opacity_animation.cpp index bb61ac70f7..b875ab9af9 100644 --- a/drape_frontend/animation/opacity_animation.cpp +++ b/drape_frontend/animation/opacity_animation.cpp @@ -6,9 +6,9 @@ namespace df OpacityAnimation::OpacityAnimation(double duration, double startOpacity, double endOpacity) : BaseInterpolator(duration) - , m_opacity(startOpacity) , m_startOpacity(startOpacity) , m_endOpacity(endOpacity) + , m_opacity(startOpacity) { } 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 c747ba46d5..4242907fe8 100644 --- a/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp +++ b/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp @@ -12,22 +12,27 @@ namespace { -class UserEventStreamTest +class UserEventStreamTest : df::UserEventStream::Listener { public: UserEventStreamTest(bool filtrateTouches) : m_stream([](m2::PointD const &) { return true; }) + , m_filtrate(filtrateTouches) { - auto const tapDetectedFn = [](m2::PointD const &, bool isLong) {}; - auto const filtrateFn = [&filtrateTouches](m2::PointD const &, df::TouchEvent::ETouchType) - { - return filtrateTouches; - }; - - m_stream.SetTapListener(tapDetectedFn, filtrateFn); m_stream.SetTestBridge(bind(&UserEventStreamTest::TestBridge, this, _1)); } + void OnTap(const m2::PointD & pt, bool isLong) override {} + bool OnSingleTouchFiltrate(m2::PointD const & pt, df::TouchEvent::ETouchType type) override { return m_filtrate; } + void OnDragStarted() override {} + void OnDragEnded(m2::PointD const & /*distance*/) override {} + void OnRotated() override {} + + void OnScaleStarted() override {} + void CorrectScalePoint(m2::PointD & pt) const override {} + void CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const override {} + void OnScaleEnded() override {} + void AddUserEvent(df::TouchEvent const & event) { m_stream.AddEvent(event); @@ -62,6 +67,7 @@ private: private: df::UserEventStream m_stream; list m_expectation; + bool m_filtrate; }; df::TouchEvent MakeTouchEvent(m2::PointD const & pt1, m2::PointD const & pt2, df::TouchEvent::ETouchType type) diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 5275aecf75..8800f1e34b 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -445,12 +445,12 @@ void FrontendRenderer::ResolveZoomLevel(const ScreenBase & screen) m_currentZoomLevel = (zoomLevel <= upperScale ? zoomLevel : upperScale); } -void FrontendRenderer::TapDetected(m2::PointD const & pt, bool isLongTap) +void FrontendRenderer::OnTap(m2::PointD const & pt, bool isLongTap) { LOG(LINFO, ("Tap detected. Is long = ", isLongTap)); } -bool FrontendRenderer::SingleTouchFiltration(m2::PointD const & pt, TouchEvent::ETouchType type) +bool FrontendRenderer::OnSingleTouchFiltrate(m2::PointD const & pt, TouchEvent::ETouchType type) { float const rectHalfSize = 5 * df::VisualParams::Instance().GetVisualScale(); m2::RectD r(-rectHalfSize, -rectHalfSize, rectHalfSize, rectHalfSize); @@ -460,15 +460,12 @@ bool FrontendRenderer::SingleTouchFiltration(m2::PointD const & pt, TouchEvent:: { case TouchEvent::ETouchType::TOUCH_DOWN: return m_guiRenderer->OnTouchDown(r); - case TouchEvent::ETouchType::TOUCH_UP: m_guiRenderer->OnTouchUp(r); return false; - case TouchEvent::ETouchType::TOUCH_CANCEL: m_guiRenderer->OnTouchCancel(r); return false; - case TouchEvent::ETouchType::TOUCH_MOVE: return false; } @@ -476,6 +473,41 @@ bool FrontendRenderer::SingleTouchFiltration(m2::PointD const & pt, TouchEvent:: return false; } +void FrontendRenderer::OnDragStarted() +{ + m_myPositionController->DragStarted(); +} + +void FrontendRenderer::OnDragEnded(m2::PointD const & distance) +{ + m_myPositionController->DragEnded(distance); +} + +void FrontendRenderer::OnScaleStarted() +{ + m_myPositionController->ScaleStarted(); +} + +void FrontendRenderer::OnRotated() +{ + m_myPositionController->Rotated(); +} + +void FrontendRenderer::CorrectScalePoint(m2::PointD & pt) const +{ + m_myPositionController->CorrectScalePoint(pt); +} + +void FrontendRenderer::CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const +{ + m_myPositionController->CorrectScalePoint(pt1, pt2); +} + +void FrontendRenderer::OnScaleEnded() +{ + m_myPositionController->ScaleEnded(); +} + void FrontendRenderer::ResolveTileKeys(ScreenBase const & screen, TTilesCollection & tiles) { // equal for x and y @@ -513,15 +545,13 @@ void FrontendRenderer::Routine::Do() { gui::DrapeGui::Instance().ConnectOnCompassTappedHandler(bind(&FrontendRenderer::OnCompassTapped, &m_renderer)); m_renderer.m_myPositionController->SetListener(ref_ptr(&m_renderer)); + m_renderer.m_userEventStream.SetListener(ref_ptr(&m_renderer)); m_renderer.m_tileTree->SetHandlers(bind(&FrontendRenderer::OnAddRenderGroup, &m_renderer, _1, _2, _3), bind(&FrontendRenderer::OnDeferRenderGroup, &m_renderer, _1, _2, _3), bind(&FrontendRenderer::OnActivateTile, &m_renderer, _1), bind(&FrontendRenderer::OnRemoveTile, &m_renderer, _1)); - m_renderer.m_userEventStream.SetTapListener(bind(&FrontendRenderer::TapDetected, &m_renderer, _1, _2), - bind(&FrontendRenderer::SingleTouchFiltration, &m_renderer, _1, _2)); - dp::OGLContext * context = m_renderer.m_contextFactory->getDrawContext(); context->makeCurrent(); GLFunctions::Init(); @@ -634,7 +664,7 @@ void FrontendRenderer::ChangeModelView(m2::PointD const & userPos, double azimut viewVector.Normalize(); AddUserEvent(SetAnyRectEvent(m2::AnyRectD(userPos + (viewVector * offset), -azimuth, - screen.GlobalRect().GetLocalRect()), true /* animate */)); + m_userEventStream.GetTargetRect().GetLocalRect()), true /* animate */)); } ScreenBase const & FrontendRenderer::UpdateScene(bool & modelViewChanged) diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index bb08d165ae..04eac88b46 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -41,6 +41,7 @@ namespace df class FrontendRenderer : public BaseRenderer , public MyPositionController::Listener + , public UserEventStream::Listener { public: using TModelViewChanged = function; @@ -112,8 +113,16 @@ private: int GetCurrentZoomLevel() const; void ResolveZoomLevel(ScreenBase const & screen); - void TapDetected(const m2::PointD & pt, bool isLongTap); - bool SingleTouchFiltration(m2::PointD const & pt, TouchEvent::ETouchType type); + void OnTap(m2::PointD const & pt, bool isLong) override; + bool OnSingleTouchFiltrate(m2::PointD const & pt, TouchEvent::ETouchType type) override; + void OnDragStarted() override; + void OnDragEnded(m2::PointD const & distance) override; + + void OnScaleStarted() override; + void OnRotated() override; + void CorrectScalePoint(m2::PointD & pt) const override; + void CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const override; + void OnScaleEnded() override; private: class Routine : public threads::IRoutine diff --git a/drape_frontend/my_position.cpp b/drape_frontend/my_position.cpp index f4508e5b3a..f1eb1e60b5 100644 --- a/drape_frontend/my_position.cpp +++ b/drape_frontend/my_position.cpp @@ -92,6 +92,7 @@ void MyPosition::Render(ScreenBase const & screen, dp::UniformValuesStorage accuracyUniforms = uniforms; accuracyUniforms.SetFloatValue("u_position", m_position.x, m_position.y, dp::depth::POSITION_ACCURACY); accuracyUniforms.SetFloatValue("u_accuracy", pixelAccuracy); + accuracyUniforms.SetFloatValue("u_opacity", 1.0); RenderPart(mng, accuracyUniforms, MY_POSITION_ACCURACY); } @@ -99,6 +100,7 @@ void MyPosition::Render(ScreenBase const & screen, dp::UniformValuesStorage arrowUniforms = uniforms; arrowUniforms.SetFloatValue("u_position", m_position.x, m_position.y, dp::depth::MY_POSITION_MARK); arrowUniforms.SetFloatValue("u_azimut", -(m_azimuth + screen.GetAngle())); + arrowUniforms.SetFloatValue("u_opacity", 1.0); RenderPart(mng, arrowUniforms, (m_showAzimuth == true) ? MY_POSITION_ARROW : MY_POSITION_POINT); } } diff --git a/drape_frontend/my_position_controller.cpp b/drape_frontend/my_position_controller.cpp index d023f5f731..55cd0ad3e4 100644 --- a/drape_frontend/my_position_controller.cpp +++ b/drape_frontend/my_position_controller.cpp @@ -15,27 +15,27 @@ int const POSITION_Y_OFFSET = 120; double const GPS_BEARING_LIFETIME_S = 5.0; double const MIN_SPEED_THRESHOLD_MPS = 1.0; -uint16_t SetModeBit(uint16_t mode, uint16_t bit) +uint16_t SetModeBit(uint32_t mode, uint32_t bit) { return mode | bit; } -//uint16_t ResetModeBit(uint16_t mode, uint16_t bit) -//{ -// return mode & (~bit); -//} +uint16_t ResetModeBit(uint32_t mode, uint32_t bit) +{ + return mode & (~bit); +} -location::EMyPositionMode ResetAllModeBits(uint16_t mode) +location::EMyPositionMode ResetAllModeBits(uint32_t mode) { return (location::EMyPositionMode)(mode & 0xF); } -uint16_t ChangeMode(uint16_t mode, location::EMyPositionMode newMode) +uint16_t ChangeMode(uint32_t mode, location::EMyPositionMode newMode) { return (mode & 0xF0) | newMode; } -bool TestModeBit(uint16_t mode, uint16_t bit) +bool TestModeBit(uint32_t mode, uint32_t bit) { return (mode & bit) != 0; } @@ -89,6 +89,59 @@ bool MyPositionController::IsModeHasPosition() const return GetMode() >= location::MODE_NOT_FOLLOW; } +void MyPositionController::DragStarted() +{ + SetModeInfo(SetModeBit(m_modeInfo, BlockAnimation)); +} + +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(); + + Follow(); +} + +void MyPositionController::ScaleStarted() +{ + SetModeInfo(SetModeBit(m_modeInfo, BlockAnimation)); +} + +void MyPositionController::Rotated() +{ + location::EMyPositionMode mode = GetMode(); + if (mode == location::MODE_ROTATE_AND_FOLLOW) + SetModeInfo(SetModeBit(m_modeInfo, StopFollowOnActionEnd)); +} + +void MyPositionController::CorrectScalePoint(m2::PointD & pt) const +{ + if (IsModeChangeViewport()) + pt = GetCurrentPixelBinding(); +} + +void MyPositionController::CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const +{ + if (IsModeChangeViewport()) + { + m2::PointD const ptDiff = GetCurrentPixelBinding() - (pt1 + (pt2 - pt1) * 0.5); + pt1 += ptDiff; + pt2 += ptDiff; + } +} + +void MyPositionController::ScaleEnded() +{ + SetModeInfo(ResetModeBit(m_modeInfo, BlockAnimation)); + if (TestModeBit(m_modeInfo, StopFollowOnActionEnd)) + { + SetModeInfo(ResetModeBit(m_modeInfo, StopFollowOnActionEnd)); + StopLocationFollow(); + } + Follow(); +} + void MyPositionController::SetRenderShape(drape_ptr && shape) { m_shape = move(shape); @@ -145,6 +198,7 @@ void MyPositionController::NextMode() } SetModeInfo(ChangeMode(m_modeInfo, newMode)); + Follow(); } void MyPositionController::TurnOff() @@ -201,7 +255,7 @@ void MyPositionController::Render(ScreenBase const & screen, ref_ptr location::MODE_PENDING_POSITION) { - if (m_isDirtyViewport) + if (m_isDirtyViewport && !TestModeBit(m_modeInfo, BlockAnimation)) { Follow(); m_isDirtyViewport = false; @@ -273,7 +327,7 @@ void MyPositionController::SetDirection(double bearing) SetModeInfo(SetModeBit(m_modeInfo, KnownDirectionBit)); } -void MyPositionController::SetModeInfo(uint16_t modeInfo, bool force) +void MyPositionController::SetModeInfo(uint32_t modeInfo, bool force) { location::EMyPositionMode const newMode = ResetAllModeBits(modeInfo); location::EMyPositionMode const oldMode = GetMode(); @@ -290,7 +344,7 @@ location::EMyPositionMode MyPositionController::GetMode() const return ResetAllModeBits(m_modeInfo); } -void MyPositionController::CallModeListener(uint16_t mode) +void MyPositionController::CallModeListener(uint32_t mode) { if (m_modeChangeCallback != nullptr) m_modeChangeCallback(ResetAllModeBits(mode)); @@ -321,6 +375,7 @@ void MyPositionController::StopCompassFollow() return; SetModeInfo(ChangeMode(m_modeInfo, location::MODE_FOLLOW)); + Follow(); } void MyPositionController::ChangeModelView(m2::PointD const & center) @@ -352,15 +407,28 @@ void MyPositionController::Follow() { location::EMyPositionMode currentMode = GetMode(); if (currentMode == location::MODE_FOLLOW) - { ChangeModelView(m_position); - } else if (currentMode == location::MODE_ROTATE_AND_FOLLOW) - { - m2::PointD pxZero(m_pixelRect.Center().x, - m_pixelRect.maxY() - POSITION_Y_OFFSET * VisualParams::Instance().GetVisualScale()); - ChangeModelView(m_position, m_drawDirection, pxZero); - } + ChangeModelView(m_position, m_drawDirection, GetRaFPixelBinding()); +} + +m2::PointD MyPositionController::GetRaFPixelBinding() const +{ + return m2::PointD (m_pixelRect.Center().x, + m_pixelRect.maxY() - POSITION_Y_OFFSET * VisualParams::Instance().GetVisualScale()); +} + +m2::PointD MyPositionController::GetCurrentPixelBinding() const +{ + location::EMyPositionMode mode = GetMode(); + if (mode == location::MODE_FOLLOW) + return m_pixelRect.Center(); + else if (mode == location::MODE_ROTATE_AND_FOLLOW) + return GetRaFPixelBinding(); + else + ASSERT(false, ()); + + return m2::PointD::Zero(); } } diff --git a/drape_frontend/my_position_controller.hpp b/drape_frontend/my_position_controller.hpp index cfc3909e8a..3d74f78a4e 100644 --- a/drape_frontend/my_position_controller.hpp +++ b/drape_frontend/my_position_controller.hpp @@ -42,6 +42,15 @@ public: bool IsModeChangeViewport() const; bool IsModeHasPosition() const; + void DragStarted(); + void DragEnded(m2::PointD const & distance); + + void ScaleStarted(); + void Rotated(); + void CorrectScalePoint(m2::PointD & pt) const; + void CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const; + void ScaleEnded(); + void SetRenderShape(drape_ptr && shape); void SetFixedZoom(); @@ -67,9 +76,9 @@ private: void Assign(location::CompassInfo const & info); void SetDirection(double bearing); - void SetModeInfo(uint16_t modeInfo, bool force = false); + void SetModeInfo(uint32_t modeInfo, bool force = false); location::EMyPositionMode GetMode() const; - void CallModeListener(uint16_t mode); + void CallModeListener(uint32_t mode); bool IsInRouting() const; bool IsRotationActive() const; @@ -83,16 +92,20 @@ private: void ChangeModelView(m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero); void Follow(); + m2::PointD GetRaFPixelBinding() const; + m2::PointD GetCurrentPixelBinding() const; private: // Mode bits // { - static uint16_t const FixedZoomBit = 0x20; - static uint16_t const RoutingSessionBit = 0x40; - static uint16_t const KnownDirectionBit = 0x80; + static uint32_t const FixedZoomBit = 0x20; + static uint32_t const RoutingSessionBit = 0x40; + static uint32_t const KnownDirectionBit = 0x80; + static uint32_t const BlockAnimation = 0x100; + static uint32_t const StopFollowOnActionEnd = 0x200; // } - uint16_t m_modeInfo; // combination of Mode enum and "Mode bits" + uint32_t m_modeInfo; // combination of Mode enum and "Mode bits" location::EMyPositionMode m_afterPendingMode; location::TMyPositionModeChanged m_modeChangeCallback; diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index ddb7455bf3..1573ee426a 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -100,6 +100,11 @@ bool RenderGroupComparator::operator()(drape_ptr const & l, drape_p if (rPendingOnDelete == lPendingOnDelete) { + dp::GLState::DepthLayer lDepth = lState.GetDepthLayer(); + dp::GLState::DepthLayer rDepth = rState.GetDepthLayer(); + if (lDepth != rDepth) + return lDepth < rDepth; + if (my::AlmostEqual(l->GetOpacity(), r->GetOpacity())) return lState < rState; else diff --git a/drape_frontend/user_event_stream.cpp b/drape_frontend/user_event_stream.cpp index 947d5fc8d4..eb0289cb74 100644 --- a/drape_frontend/user_event_stream.cpp +++ b/drape_frontend/user_event_stream.cpp @@ -39,6 +39,8 @@ char const * UserEventStream::CANCEL_FILTER = "CancelFilter"; UserEventStream::UserEventStream(TIsCountryLoaded const & fn) : m_isCountryLoaded(fn) , m_state(STATE_EMPTY) + , m_validTouchesCount(0) + , m_startDragOrg(m2::PointD::Zero()) { } @@ -69,7 +71,7 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChange, bool & switch (e.m_type) { case UserEvent::EVENT_SCALE: - breakAnim = Scale(e.m_scaleEvent.m_pxPoint, e.m_scaleEvent.m_factor, e.m_scaleEvent.m_isAnim); + 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: @@ -129,24 +131,22 @@ ScreenBase const & UserEventStream::GetCurrentScreen() const return m_navigator.Screen(); } -void UserEventStream::SetTapListener(TTapDetectedFn const & tapCallback, TSingleTouchFilterFn const & filterFn) +bool UserEventStream::SetScale(m2::PointD const & pxScaleCenter, double factor, bool isAnim) { - m_tapDetectedFn = tapCallback; - m_filterFn = filterFn; -} + m2::PointD scaleCenter = pxScaleCenter; + if (m_listener) + m_listener->CorrectScalePoint(scaleCenter); -bool UserEventStream::Scale(m2::PointD const & pxScaleCenter, double factor, bool isAnim) -{ if (isAnim) { - m2::PointD glbCenter = m_navigator.PtoG(pxScaleCenter); + m2::PointD glbCenter = m_navigator.PtoG(scaleCenter); m2::AnyRectD rect = GetTargetRect(); m2::RectD sizeRect = rect.GetLocalRect(); sizeRect.Scale(1.0 / factor); return SetRect(m2::AnyRectD(glbCenter, rect.Angle(), sizeRect), true); } - m_navigator.Scale(pxScaleCenter, factor); + m_navigator.Scale(scaleCenter, factor); return true; } @@ -396,6 +396,9 @@ void UserEventStream::BeginDrag(Touch const & t) TEST_CALL(BEGIN_DRAG); ASSERT(m_state == STATE_EMPTY, ()); m_state = STATE_DRAG; + m_startDragOrg = m_navigator.Screen().GetOrg(); + if (m_listener) + m_listener->OnDragStarted(); m_navigator.StartDrag(t.m_location); } @@ -411,6 +414,10 @@ void UserEventStream::EndDrag(Touch const & t) TEST_CALL(END_DRAG); ASSERT(m_state == STATE_DRAG, ()); m_state = STATE_EMPTY; + if (m_listener) + m_listener->OnDragEnded(m_navigator.GtoP(m_navigator.Screen().GetOrg()) - m_navigator.GtoP(m_startDragOrg)); + + m_startDragOrg = m2::PointD::Zero(); m_navigator.StopDrag(t.m_location); } @@ -419,14 +426,35 @@ void UserEventStream::BeginScale(Touch const & t1, Touch const & t2) TEST_CALL(BEGIN_SCALE); ASSERT(m_state == STATE_EMPTY, ()); m_state = STATE_SCALE; - m_navigator.StartScale(t1.m_location, t2.m_location); + m2::PointD touch1 = t1.m_location; + m2::PointD touch2 = t2.m_location; + + if (m_listener) + { + m_listener->OnScaleStarted(); + m_listener->CorrectScalePoint(touch1, touch2); + } + + m_navigator.StartScale(touch1, touch2); } void UserEventStream::Scale(Touch const & t1, Touch const & t2) { TEST_CALL(SCALE); ASSERT(m_state == STATE_SCALE, ()); - m_navigator.DoScale(t1.m_location, t2.m_location); + + m2::PointD touch1 = t1.m_location; + m2::PointD touch2 = t2.m_location; + + if (m_listener) + { + if (m_navigator.IsRotatingDuringScale()) + m_listener->OnRotated(); + + m_listener->CorrectScalePoint(touch1, touch2); + } + + m_navigator.DoScale(touch1, touch2); } void UserEventStream::EndScale(const Touch & t1, const Touch & t2) @@ -434,7 +462,17 @@ void UserEventStream::EndScale(const Touch & t1, const Touch & t2) TEST_CALL(END_SCALE); ASSERT(m_state == STATE_SCALE, ()); m_state = STATE_EMPTY; - m_navigator.StopScale(t1.m_location, t2.m_location); + + m2::PointD touch1 = t1.m_location; + m2::PointD touch2 = t2.m_location; + + if (m_listener) + { + m_listener->CorrectScalePoint(touch1, touch2); + m_listener->OnScaleEnded(); + } + + m_navigator.StopScale(touch1, touch2); } void UserEventStream::BeginTapDetector() @@ -452,7 +490,8 @@ void UserEventStream::DetectLongTap(Touch const & touch) { TEST_CALL(LONG_TAP_DETECTED); m_state = STATE_EMPTY; - m_tapDetectedFn(touch.m_location, true); + if (m_listener) + m_listener->OnTap(touch.m_location, true); } } @@ -461,7 +500,8 @@ void UserEventStream::EndTapDetector(Touch const & touch) TEST_CALL(SHORT_TAP_DETECTED); ASSERT(m_state == STATE_TAP_DETECTION, ()); m_state = STATE_EMPTY; - m_tapDetectedFn(touch.m_location, false); + if (m_listener) + m_listener->OnTap(touch.m_location, false); } void UserEventStream::CancelTapDetector() @@ -475,7 +515,7 @@ bool UserEventStream::TryBeginFilter(Touch const & t) { TEST_CALL(TRY_FILTER); ASSERT(m_state == STATE_EMPTY, ()); - if (m_filterFn(t.m_location, TouchEvent::TOUCH_DOWN)) + if (m_listener && m_listener->OnSingleTouchFiltrate(t.m_location, TouchEvent::TOUCH_DOWN)) { m_state = STATE_FILTER; return true; @@ -489,7 +529,8 @@ void UserEventStream::EndFilter(const Touch & t) TEST_CALL(END_FILTER); ASSERT(m_state == STATE_FILTER, ()); m_state = STATE_EMPTY; - m_filterFn(t.m_location, TouchEvent::TOUCH_UP); + if (m_listener) + m_listener->OnSingleTouchFiltrate(t.m_location, TouchEvent::TOUCH_UP); } void UserEventStream::CancelFilter(Touch const & t) @@ -497,7 +538,8 @@ void UserEventStream::CancelFilter(Touch const & t) TEST_CALL(CANCEL_FILTER); ASSERT(m_state == STATE_FILTER, ()); m_state = STATE_EMPTY; - m_filterFn(t.m_location, TouchEvent::TOUCH_CANCEL); + if (m_listener) + m_listener->OnSingleTouchFiltrate(t.m_location, TouchEvent::TOUCH_CANCEL); } } diff --git a/drape_frontend/user_event_stream.hpp b/drape_frontend/user_event_stream.hpp index 0603721858..7b8025f58f 100644 --- a/drape_frontend/user_event_stream.hpp +++ b/drape_frontend/user_event_stream.hpp @@ -3,6 +3,8 @@ #include "drape_frontend/navigator.hpp" #include "drape_frontend/animation/model_view_animation.hpp" +#include "drape/pointers.hpp" + #include "geometry/point2d.hpp" #include "geometry/rect2d.hpp" #include "geometry/any_rect2d.hpp" @@ -150,14 +152,29 @@ struct UserEvent class UserEventStream { public: + class Listener + { + public: + virtual void OnTap(m2::PointD const & pt, bool isLong) = 0; + virtual bool OnSingleTouchFiltrate(m2::PointD const & pt, TouchEvent::ETouchType type) = 0; + virtual void OnDragStarted() = 0; + virtual void OnDragEnded(m2::PointD const & distance) = 0; + + virtual void OnScaleStarted() = 0; + virtual void OnRotated() = 0; + virtual void CorrectScalePoint(m2::PointD & pt) const = 0; + virtual void CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const = 0; + virtual void OnScaleEnded() = 0; + }; + UserEventStream(TIsCountryLoaded const & fn); void AddEvent(UserEvent const & event); ScreenBase const & ProcessEvents(bool & modelViewChange, bool & viewportChanged); ScreenBase const & GetCurrentScreen() const; - using TTapDetectedFn = function; - using TSingleTouchFilterFn = function; - void SetTapListener(TTapDetectedFn const & tapCallback, TSingleTouchFilterFn const & filterFn); + m2::AnyRectD GetTargetRect() const; + + void SetListener(ref_ptr listener) { m_listener = listener; } #ifdef DEBUG static char const * BEGIN_DRAG; @@ -179,13 +196,12 @@ public: #endif private: - bool Scale(m2::PointD const & pxScaleCenter, double factor, bool isAnim); + 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); m2::AnyRectD GetCurrentRect() const; - m2::AnyRectD GetTargetRect() const; bool ProcessTouch(TouchEvent const & touch); @@ -215,8 +231,6 @@ private: private: TIsCountryLoaded m_isCountryLoaded; - TTapDetectedFn m_tapDetectedFn; - TSingleTouchFilterFn m_filterFn; list m_events; mutable mutex m_lock; @@ -236,10 +250,12 @@ private: size_t m_validTouchesCount; unique_ptr m_animation; + ref_ptr m_listener; #ifdef DEBUG TTestBridge m_testFn; #endif + m2::PointD m_startDragOrg; }; }