diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 75b35d1ea0..023f771aae 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -61,7 +61,7 @@ enum MultiTouchAction Framework::Framework() : m_lastCompass(0.0) - , m_currentMode(location::MODE_UNKNOWN_POSITION) + , m_currentMode(location::PendingPosition) , m_isCurrentModeInitialized(false) , m_isChoosePositionMode(false) { @@ -97,13 +97,13 @@ void Framework::UpdateCompassSensor(int ind, float * arr) m_sensors[ind].Next(arr); } -void Framework::MyPositionModeChanged(location::EMyPositionMode mode) +void Framework::MyPositionModeChanged(location::EMyPositionMode mode, bool routingActive) { if (m_myPositionModeSignal != nullptr) - m_myPositionModeSignal(mode); + m_myPositionModeSignal(mode, routingActive); } -bool Framework::CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi) +bool Framework::CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi, bool firstLaunch) { m_contextFactory = make_unique_dp(new AndroidOGLContextFactory(env, jSurface)); AndroidOGLContextFactory const * factory = m_contextFactory->CastFactory(); @@ -117,11 +117,12 @@ bool Framework::CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi p.m_hasMyPositionState = m_isCurrentModeInitialized; p.m_initialMyPositionState = m_currentMode; p.m_isChoosePositionMode = m_isChoosePositionMode; + p.m_isFirstLaunch = firstLaunch; ASSERT(!m_guiPositions.empty(), ("GUI elements must be set-up before engine is created")); p.m_widgetsInitInfo = m_guiPositions; m_work.LoadBookmarks(); - m_work.SetMyPositionModeListener(bind(&Framework::MyPositionModeChanged, this, _1)); + m_work.SetMyPositionModeListener(bind(&Framework::MyPositionModeChanged, this, _1, _2)); m_work.CreateDrapeEngine(make_ref(m_contextFactory), move(p)); m_work.EnterForeground(); @@ -358,7 +359,7 @@ void Framework::SetMyPositionModeListener(location::TMyPositionModeChanged const location::EMyPositionMode Framework::GetMyPositionMode() const { if (!m_isCurrentModeInitialized) - return location::MODE_UNKNOWN_POSITION; + return location::PendingPosition; return m_currentMode; } diff --git a/android/jni/com/mapswithme/maps/Framework.hpp b/android/jni/com/mapswithme/maps/Framework.hpp index d1e9678b34..7cb9e93bf1 100644 --- a/android/jni/com/mapswithme/maps/Framework.hpp +++ b/android/jni/com/mapswithme/maps/Framework.hpp @@ -42,7 +42,7 @@ namespace android map m_guiPositions; - void MyPositionModeChanged(location::EMyPositionMode mode); + void MyPositionModeChanged(location::EMyPositionMode mode, bool routingActive); location::TMyPositionModeChanged m_myPositionModeSignal; location::EMyPositionMode m_currentMode; @@ -66,7 +66,7 @@ namespace android void Invalidate(); - bool CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi); + bool CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi, bool firstLaunch); void DeleteDrapeEngine(); bool IsDrapeEngineCreated(); diff --git a/android/jni/com/mapswithme/maps/LocationState.cpp b/android/jni/com/mapswithme/maps/LocationState.cpp index 2a10f51645..346f6f960d 100644 --- a/android/jni/com/mapswithme/maps/LocationState.cpp +++ b/android/jni/com/mapswithme/maps/LocationState.cpp @@ -18,18 +18,19 @@ extern "C" return g_framework->GetMyPositionMode(); } - void LocationStateModeChanged(location::EMyPositionMode mode, shared_ptr const & obj) + void LocationStateModeChanged(location::EMyPositionMode mode, bool routingActive, shared_ptr const & obj) { g_framework->SetMyPositionMode(mode); JNIEnv * env = jni::GetEnv(); - env->CallVoidMethod(*obj, jni::GetMethodID(env, *obj.get(), "onMyPositionModeChangedCallback", "(I)V"), static_cast(mode)); + env->CallVoidMethod(*obj, jni::GetMethodID(env, *obj.get(), "onMyPositionModeChangedCallback", "(IZ)V"), + static_cast(mode), static_cast(routingActive)); } JNIEXPORT void JNICALL Java_com_mapswithme_maps_LocationState_setMyPositionModeListener(JNIEnv * env, jobject thiz, jobject obj) { - g_framework->SetMyPositionModeListener(bind(&LocationStateModeChanged, _1, jni::make_global_ref(obj))); + g_framework->SetMyPositionModeListener(bind(&LocationStateModeChanged, _1, _2, jni::make_global_ref(obj))); } JNIEXPORT void JNICALL @@ -37,10 +38,4 @@ extern "C" { g_framework->SetMyPositionModeListener(location::TMyPositionModeChanged()); } - - JNIEXPORT void JNICALL - Java_com_mapswithme_maps_LocationState_invalidatePosition(JNIEnv * env, jobject thiz) - { - g_framework->NativeFramework()->InvalidateMyPosition(); - } } diff --git a/android/jni/com/mapswithme/maps/MapFragment.cpp b/android/jni/com/mapswithme/maps/MapFragment.cpp index 6a8b44a539..54c057c639 100644 --- a/android/jni/com/mapswithme/maps/MapFragment.cpp +++ b/android/jni/com/mapswithme/maps/MapFragment.cpp @@ -64,9 +64,9 @@ Java_com_mapswithme_maps_MapFragment_nativeShowMapForUrl(JNIEnv * env, jclass cl } JNIEXPORT jboolean JNICALL -Java_com_mapswithme_maps_MapFragment_nativeCreateEngine(JNIEnv * env, jclass clazz, jobject surface, jint density) +Java_com_mapswithme_maps_MapFragment_nativeCreateEngine(JNIEnv * env, jclass clazz, jobject surface, jint density, jboolean firstLaunch) { - return g_framework->CreateDrapeEngine(env, surface, density); + return g_framework->CreateDrapeEngine(env, surface, density, firstLaunch); } JNIEXPORT void JNICALL diff --git a/android/src/com/mapswithme/maps/LocationState.java b/android/src/com/mapswithme/maps/LocationState.java index 0ced79da5c..092ad52234 100644 --- a/android/src/com/mapswithme/maps/LocationState.java +++ b/android/src/com/mapswithme/maps/LocationState.java @@ -6,11 +6,11 @@ public enum LocationState /// These values should correspond to values of /// location::EMyPositionMode defined in platform/location.hpp - public static final int UNKNOWN_POSITION = 0; - public static final int PENDING_POSITION = 1; + public static final int PENDING_POSITION = 0; + public static final int NOT_FOLLOW_NO_POSITION = 1; public static final int NOT_FOLLOW = 2; public static final int FOLLOW = 3; - public static final int ROTATE_AND_FOLLOW = 4; + public static final int FOLLOW_AND_ROTATE = 4; public native void switchToNextMode(); @@ -19,8 +19,6 @@ public enum LocationState public native void setMyPositionModeListener(Object l); public native void removeMyPositionModeListener(); - public native void invalidatePosition(); - /** * Checks if location state on the map is active (so its not turned off or pending). */ diff --git a/android/src/com/mapswithme/maps/MapFragment.java b/android/src/com/mapswithme/maps/MapFragment.java index 87c06305a5..37fef4a102 100644 --- a/android/src/com/mapswithme/maps/MapFragment.java +++ b/android/src/com/mapswithme/maps/MapFragment.java @@ -152,7 +152,8 @@ public class MapFragment extends BaseMwmFragment getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics); final float exactDensityDpi = metrics.densityDpi; - mEngineCreated = nativeCreateEngine(surface, (int) exactDensityDpi); + boolean isFirstLaunch = false; //TODO(Android team): set correct value + mEngineCreated = nativeCreateEngine(surface, (int) exactDensityDpi, isFirstLaunch); if (!mEngineCreated) { reportUnsupported(); @@ -274,7 +275,7 @@ public class MapFragment extends BaseMwmFragment static native void nativeScaleMinus(); static native boolean nativeShowMapForUrl(String url); static native boolean nativeIsEngineCreated(); - private static native boolean nativeCreateEngine(Surface surface, int density); + private static native boolean nativeCreateEngine(Surface surface, int density, boolean firstLaunch); private static native void nativeDestroyEngine(); private static native void nativeAttachSurface(Surface surface); private static native void nativeDetachSurface(); diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java index e2ab631c44..127d73bc28 100644 --- a/android/src/com/mapswithme/maps/MwmActivity.java +++ b/android/src/com/mapswithme/maps/MwmActivity.java @@ -822,15 +822,12 @@ public class MwmActivity extends BaseMwmFragmentActivity // Callback from native location state mode element processing. @SuppressWarnings("unused") - public void onMyPositionModeChangedCallback(final int newMode) + public void onMyPositionModeChangedCallback(final int newMode, final boolean routingActive) { mLocationPredictor.myPositionModeChanged(newMode); mMainMenu.getMyPositionButton().update(newMode); switch (newMode) { - case LocationState.UNKNOWN_POSITION: - pauseLocation(); - break; case LocationState.PENDING_POSITION: resumeLocation(); break; @@ -843,7 +840,6 @@ public class MwmActivity extends BaseMwmFragmentActivity super.onResume(); LocationState.INSTANCE.setMyPositionModeListener(this); - invalidateLocationState(); mSearchController.refreshToolbar(); @@ -989,9 +985,6 @@ public class MwmActivity extends BaseMwmFragmentActivity switch (newMode) { - case LocationState.UNKNOWN_POSITION: - pauseLocation(); - break; case LocationState.PENDING_POSITION: resumeLocation(); break; @@ -1000,17 +993,6 @@ public class MwmActivity extends BaseMwmFragmentActivity } } - /** - * Invalidates location state in core. - * Updates location button accordingly. - */ - public void invalidateLocationState() - { - final int currentLocationMode = LocationState.INSTANCE.getLocationStateMode(); - refreshLocationState(currentLocationMode); - LocationState.INSTANCE.invalidatePosition(); - } - @Override protected void onStart() { diff --git a/android/src/com/mapswithme/maps/location/LocationPredictor.java b/android/src/com/mapswithme/maps/location/LocationPredictor.java index ebe416989c..f22ebb752b 100644 --- a/android/src/com/mapswithme/maps/location/LocationPredictor.java +++ b/android/src/com/mapswithme/maps/location/LocationPredictor.java @@ -52,7 +52,7 @@ public class LocationPredictor if (mode < LocationState.NOT_FOLLOW) mLastLocation = null; - mGeneratePredictions = (mode == LocationState.ROTATE_AND_FOLLOW); + mGeneratePredictions = (mode == LocationState.FOLLOW_AND_ROTATE); resetHandler(); } diff --git a/android/src/com/mapswithme/maps/routing/ResultCodesHelper.java b/android/src/com/mapswithme/maps/routing/ResultCodesHelper.java index 28d9c9ff6d..b5a3d67876 100644 --- a/android/src/com/mapswithme/maps/routing/ResultCodesHelper.java +++ b/android/src/com/mapswithme/maps/routing/ResultCodesHelper.java @@ -34,7 +34,7 @@ class ResultCodesHelper switch (errorCode) { case NO_POSITION: - if (LocationState.INSTANCE.getLocationStateMode() == LocationState.UNKNOWN_POSITION) + if (LocationState.INSTANCE.getLocationStateMode() == LocationState.NOT_FOLLOW_NO_POSITION) { titleRes = R.string.dialog_routing_location_turn_on; messages.add(resources.getString(R.string.dialog_routing_location_unknown_turn_on)); diff --git a/android/src/com/mapswithme/maps/widget/menu/MyPositionButton.java b/android/src/com/mapswithme/maps/widget/menu/MyPositionButton.java index d8745f598d..c0ad951343 100644 --- a/android/src/com/mapswithme/maps/widget/menu/MyPositionButton.java +++ b/android/src/com/mapswithme/maps/widget/menu/MyPositionButton.java @@ -37,10 +37,11 @@ public class MyPositionButton Drawable image; switch (state) { - case LocationState.UNKNOWN_POSITION: - image = Graphics.tint(mButton.getContext(), R.drawable.ic_follow, R.attr.iconTintLight); + case LocationState.PENDING_POSITION: + image = mButton.getResources().getDrawable(ThemeUtils.getResource(mButton.getContext(), R.attr.myPositionButtonAnimation)); break; + case LocationState.NOT_FOLLOW_NO_POSITION: case LocationState.NOT_FOLLOW: image = Graphics.tint(mButton.getContext(), R.drawable.ic_not_follow); break; @@ -49,14 +50,10 @@ public class MyPositionButton image = Graphics.tint(mButton.getContext(), R.drawable.ic_follow, R.attr.colorAccent); break; - case LocationState.ROTATE_AND_FOLLOW: + case LocationState.FOLLOW_AND_ROTATE: image = Graphics.tint(mButton.getContext(), R.drawable.ic_follow_and_rotate, R.attr.colorAccent); break; - case LocationState.PENDING_POSITION: - image = mButton.getResources().getDrawable(ThemeUtils.getResource(mButton.getContext(), R.attr.myPositionButtonAnimation)); - break; - default: throw new IllegalArgumentException("Invalid button state: " + state); } diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index b7da93ae90..9ee46fe45b 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -240,7 +240,7 @@ void BackendRenderer::AcceptMessage(ref_ptr message) case Message::InvalidateTextures: { m_texMng->Invalidate(VisualParams::Instance().GetResourcePostfix()); - RecacheMyPosition(); + RecacheMapShapes(); break; } case Message::CacheGpsTrackPoints: @@ -316,13 +316,13 @@ void BackendRenderer::InitGLDependentResource() m_texMng->Init(params); - RecacheMyPosition(); + RecacheMapShapes(); } -void BackendRenderer::RecacheMyPosition() +void BackendRenderer::RecacheMapShapes() { - auto msg = make_unique_dp(make_unique_dp(m_texMng), - make_unique_dp(m_texMng)); + auto msg = make_unique_dp(make_unique_dp(m_texMng), + make_unique_dp(m_texMng)); GLFunctions::glFlush(); m_commutator->PostMessage(ThreadsCommutator::RenderThread, move(msg), MessagePriority::High); diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp index bd46af90cd..3c92d9d5a5 100644 --- a/drape_frontend/backend_renderer.hpp +++ b/drape_frontend/backend_renderer.hpp @@ -59,9 +59,9 @@ protected: unique_ptr CreateRoutine() override; private: - void RecacheGui(gui::TWidgetsInitInfo const & initInfo, bool needResetOldGui); + void RecacheGui(gui::TWidgetsInitInfo const & initInfo, bool needResetOldGui); void RecacheChoosePositionMark(); - void RecacheMyPosition(); + void RecacheMapShapes(); void AcceptMessage(ref_ptr message) override; diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index d1aa53a883..51f2eda8ba 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -31,15 +31,15 @@ DrapeEngine::DrapeEngine(Params && params) location::EMyPositionMode mode = params.m_initialMyPositionMode.first; if (!params.m_initialMyPositionMode.second && !settings::Get(settings::kLocationStateMode, mode)) { - mode = location::MODE_UNKNOWN_POSITION; + mode = location::PendingPosition; } - else if (mode == location::MODE_ROTATE_AND_FOLLOW) + else if (mode == location::FollowAndRotate) { // If the screen rect setting in follow and rotate mode is missing or invalid, it could cause invalid animations, // so the follow and rotate mode should be discarded. m2::AnyRectD rect; if (!(settings::Get("ScreenClipRect", rect) && df::GetWorldRect().IsRectInside(rect.GetGlobalRect()))) - mode = location::MODE_FOLLOW; + mode = location::Follow; } FrontendRenderer::Params frParams(make_ref(m_threadCommutator), params.m_factory, @@ -47,9 +47,9 @@ DrapeEngine::DrapeEngine(Params && params) bind(&DrapeEngine::ModelViewChanged, this, _1), bind(&DrapeEngine::TapEvent, this, _1), bind(&DrapeEngine::UserPositionChanged, this, _1), - bind(&DrapeEngine::MyPositionModeChanged, this, _1), + bind(&DrapeEngine::MyPositionModeChanged, this, _1, _2), mode, make_ref(m_requestedTiles), params.m_allow3dBuildings, - params.m_blockTapEvents); + params.m_blockTapEvents, params.m_isFirstLaunch); m_frontend = make_unique_dp(frParams); @@ -217,13 +217,13 @@ void DrapeEngine::ModelViewChangedGuiThread(ScreenBase const & screen) p.second(screen); } -void DrapeEngine::MyPositionModeChanged(location::EMyPositionMode mode) +void DrapeEngine::MyPositionModeChanged(location::EMyPositionMode mode, bool routingActive) { settings::Set(settings::kLocationStateMode, mode); - GetPlatform().RunOnGuiThread([this, mode]() + GetPlatform().RunOnGuiThread([this, mode, routingActive]() { if (m_myPositionModeChanged != nullptr) - m_myPositionModeChanged(mode); + m_myPositionModeChanged(mode, routingActive); }); } @@ -266,10 +266,24 @@ void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable, c MessagePriority::High); } -void DrapeEngine::MyPositionNextMode(int preferredZoomLevel) +void DrapeEngine::SwitchMyPositionNextMode() { m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(ChangeMyPositionModeMessage::TYPE_NEXT, preferredZoomLevel), + make_unique_dp(ChangeMyPositionModeMessage::SwitchNextMode), + MessagePriority::High); +} + +void DrapeEngine::LoseLocation() +{ + m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, + make_unique_dp(ChangeMyPositionModeMessage::LoseLocation), + MessagePriority::High); +} + +void DrapeEngine::StopLocationFollow() +{ + m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, + make_unique_dp(ChangeMyPositionModeMessage::StopFollowing), MessagePriority::High); } @@ -281,27 +295,6 @@ void DrapeEngine::FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, MessagePriority::High); } -void DrapeEngine::CancelMyPosition() -{ - m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(ChangeMyPositionModeMessage::TYPE_CANCEL), - MessagePriority::High); -} - -void DrapeEngine::StopLocationFollow() -{ - m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(ChangeMyPositionModeMessage::TYPE_STOP_FOLLOW), - MessagePriority::High); -} - -void DrapeEngine::InvalidateMyPosition() -{ - m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(ChangeMyPositionModeMessage::TYPE_INVALIDATE), - MessagePriority::High); -} - void DrapeEngine::SetMyPositionModeListener(location::TMyPositionModeChanged const & fn) { m_myPositionModeChanged = fn; diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 5ae6e3a9f5..312f1b0c5c 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -42,7 +42,8 @@ public: pair const & initialMyPositionMode, bool allow3dBuildings, bool blockTapEvents, - bool showChoosePositionMark) + bool showChoosePositionMark, + bool firstLaunch) : m_factory(factory) , m_stringsBundle(stringBundle) , m_viewport(viewport) @@ -53,6 +54,7 @@ public: , m_allow3dBuildings(allow3dBuildings) , m_blockTapEvents(blockTapEvents) , m_showChoosePositionMark(showChoosePositionMark) + , m_isFirstLaunch(firstLaunch) {} ref_ptr m_factory; @@ -65,6 +67,7 @@ public: bool m_allow3dBuildings; bool m_blockTapEvents; bool m_showChoosePositionMark; + bool m_isFirstLaunch; }; DrapeEngine(Params && params); @@ -95,10 +98,9 @@ public: void SetCompassInfo(location::CompassInfo const & info); void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo); - void MyPositionNextMode(int preferredZoomLevel = -1); - void CancelMyPosition(); + void SwitchMyPositionNextMode(); + void LoseLocation(); void StopLocationFollow(); - void InvalidateMyPosition(); void SetMyPositionModeListener(location::TMyPositionModeChanged const & fn); using TTapEventInfoFn = FrontendRenderer::TTapEventInfoFn; @@ -137,7 +139,7 @@ private: void ModelViewChanged(ScreenBase const & screen); void ModelViewChangedGuiThread(ScreenBase const & screen); - void MyPositionModeChanged(location::EMyPositionMode mode); + void MyPositionModeChanged(location::EMyPositionMode mode, bool routingActive); void TapEvent(TapInfo const & tapInfo); void UserPositionChanged(m2::PointD const & position); diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index a6bfabb233..cef08c9fbf 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -138,7 +138,7 @@ FrontendRenderer::FrontendRenderer(Params const & params) ASSERT(m_tapEventInfoFn, ()); ASSERT(m_userPositionChangedFn, ()); - m_myPositionController.reset(new MyPositionController(params.m_initMyPositionMode)); + m_myPositionController.reset(new MyPositionController(params.m_initMyPositionMode, params.m_firstLaunch)); m_myPositionController->SetModeListener(params.m_myPositionModeCallback); StartThread(); @@ -356,9 +356,9 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) break; } - case Message::MyPositionShape: + case Message::MapShapes: { - ref_ptr msg = message; + ref_ptr msg = message; m_myPositionController->SetRenderShape(msg->AcceptShape()); m_selectionShape = msg->AcceptSelection(); } @@ -369,17 +369,14 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) ref_ptr msg = message; switch (msg->GetChangeType()) { - case ChangeMyPositionModeMessage::TYPE_NEXT: - m_myPositionController->NextMode(msg->GetPreferredZoomLevel()); + case ChangeMyPositionModeMessage::SwitchNextMode: + m_myPositionController->NextMode(); break; - case ChangeMyPositionModeMessage::TYPE_STOP_FOLLOW: + case ChangeMyPositionModeMessage::StopFollowing: m_myPositionController->StopLocationFollow(); break; - case ChangeMyPositionModeMessage::TYPE_INVALIDATE: - m_myPositionController->Invalidate(); - break; - case ChangeMyPositionModeMessage::TYPE_CANCEL: - m_myPositionController->TurnOff(); + case ChangeMyPositionModeMessage::LoseLocation: + m_myPositionController->LoseLocation(); break; default: ASSERT(false, ("Unknown change type:", static_cast(msg->GetChangeType()))); @@ -476,7 +473,6 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) MessagePriority::High); } - m_myPositionController->ActivateRouting(); if (m_pendingFollowRoute != nullptr) { FollowRoute(m_pendingFollowRoute->m_preferredZoomLevel, m_pendingFollowRoute->m_preferredZoomLevelIn3d, @@ -512,9 +508,9 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) { ref_ptr const msg = message; - // After night style switching and drape engine reinitialization FrontendRenderer + // After night style switching or drape engine reinitialization FrontendRenderer can // receive FollowRoute message before FlushRoute message, so we need to postpone its processing. - if (!m_myPositionController->IsInRouting()) + if (m_routeRenderer->GetRouteData() == nullptr) { m_pendingFollowRoute.reset( new FollowRouteData(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d(), @@ -709,17 +705,16 @@ unique_ptr FrontendRenderer::CreateRoutine() void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d, double rotationAngle, double angleFOV) { + if (m_enablePerspectiveInNavigation) { - bool immediatelyStart = !m_myPositionController->IsRotationActive(); - AddUserEvent(EnablePerspectiveEvent(rotationAngle, angleFOV, - true /* animated */, immediatelyStart)); + bool immediatelyStart = !m_myPositionController->IsRotationAvailable(); + AddUserEvent(EnablePerspectiveEvent(rotationAngle, angleFOV, true /* animated */, immediatelyStart)); } - m_myPositionController->NextMode(!m_enablePerspectiveInNavigation ? preferredZoomLevel - : preferredZoomLevelIn3d); + m_myPositionController->ActivateRouting(!m_enablePerspectiveInNavigation ? preferredZoomLevel + : preferredZoomLevelIn3d); m_overlayTree->SetFollowingMode(true); - } void FrontendRenderer::InvalidateRect(m2::RectD const & gRect) @@ -837,8 +832,7 @@ bool FrontendRenderer::CheckTileGenerations(TileKey const & tileKey) void FrontendRenderer::OnCompassTapped() { - if (!m_myPositionController->StopCompassFollow()) - m_userEventStream.AddEvent(RotateEvent(0.0)); + m_myPositionController->OnCompassTapped(); } FeatureID FrontendRenderer::GetVisiblePOI(m2::PointD const & pixelPoint) @@ -1438,7 +1432,8 @@ void FrontendRenderer::Routine::Do() m_renderer.PrepareScene(modelView); // Check for a frame is active. - bool isActiveFrame = modelViewChanged || viewportChanged; + bool isActiveFrame = modelViewChanged || viewportChanged || + m_renderer.m_myPositionController->IsWaitingForLocation(); isActiveFrame |= m_renderer.m_texMng->UpdateDynamicTextures(); m_renderer.RenderScene(modelView); @@ -1487,7 +1482,7 @@ void FrontendRenderer::Routine::Do() // Limit fps in following mode. double constexpr kFrameTime = 1.0 / 30.0; - if (isValidFrameTime && m_renderer.m_myPositionController->IsFollowingActive() && frameTime < kFrameTime) + if (isValidFrameTime && m_renderer.m_myPositionController->IsRouteFollowingActive() && frameTime < kFrameTime) { uint32_t const ms = static_cast((kFrameTime - frameTime) * 1000); this_thread::sleep_for(milliseconds(ms)); diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index 112ecdf8c0..aa8163733e 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -80,7 +80,8 @@ public: location::EMyPositionMode initMode, ref_ptr requestedTiles, bool allow3dBuildings, - bool blockTapEvents) + bool blockTapEvents, + bool firstLaunch) : BaseRenderer::Params(commutator, factory, texMng) , m_viewport(viewport) , m_modelViewChangedFn(modelViewChangedFn) @@ -91,6 +92,7 @@ public: , m_requestedTiles(requestedTiles) , m_allow3dBuildings(allow3dBuildings) , m_blockTapEvents(blockTapEvents) + , m_firstLaunch(firstLaunch) {} Viewport m_viewport; @@ -102,6 +104,7 @@ public: ref_ptr m_requestedTiles; bool m_allow3dBuildings; bool m_blockTapEvents; + bool m_firstLaunch; }; FrontendRenderer(Params const & params); diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index 33381d61df..17c55f394c 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -26,7 +26,7 @@ public: GuiLayerRecached, GuiRecache, GuiLayerLayout, - MyPositionShape, + MapShapes, ChangeMyPostitionMode, CompassInfo, GpsInfo, diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index b7753c32bd..521eb44bd9 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -343,15 +343,15 @@ private: bool const m_needBlock; }; -class MyPositionShapeMessage : public Message +class MapShapesMessage : public Message { public: - MyPositionShapeMessage(drape_ptr && shape, drape_ptr && selection) + MapShapesMessage(drape_ptr && shape, drape_ptr && selection) : m_shape(move(shape)) , m_selection(move(selection)) {} - Type GetType() const override { return Message::MyPositionShape; } + Type GetType() const override { return Message::MapShapes; } drape_ptr && AcceptShape() { return move(m_shape); } drape_ptr AcceptSelection() { return move(m_selection); } @@ -366,30 +366,20 @@ class ChangeMyPositionModeMessage : public Message public: enum EChangeType { - TYPE_NEXT, - TYPE_CANCEL, - TYPE_STOP_FOLLOW, - TYPE_INVALIDATE + SwitchNextMode, + LoseLocation, + StopFollowing }; explicit ChangeMyPositionModeMessage(EChangeType changeType) : m_changeType(changeType) - , m_preferredZoomLevel(-1) - {} - - explicit ChangeMyPositionModeMessage(EChangeType changeType, int zoomLevel) - : m_changeType(changeType) - , m_preferredZoomLevel(zoomLevel) {} EChangeType GetChangeType() const { return m_changeType; } Type GetType() const override { return Message::ChangeMyPostitionMode; } - int GetPreferredZoomLevel() const { return m_preferredZoomLevel; } - private: EChangeType const m_changeType; - int m_preferredZoomLevel; }; class CompassInfoMessage : public Message diff --git a/drape_frontend/my_position_controller.cpp b/drape_frontend/my_position_controller.cpp index d08f701e35..12c1c1aaa9 100644 --- a/drape_frontend/my_position_controller.cpp +++ b/drape_frontend/my_position_controller.cpp @@ -17,34 +17,29 @@ namespace df namespace { -int const POSITION_Y_OFFSET = 75; -int const POSITION_Y_OFFSET_3D = 80; -double const GPS_BEARING_LIFETIME_S = 5.0; -double const MIN_SPEED_THRESHOLD_MPS = 1.0; +int const kPositionOffsetY = 75; +int const kPositionOffsetYIn3D = 80; +double const kGpsBearingLifetimeSec = 5.0; +double const kMinSpeedThresholdMps = 1.0; -uint16_t SetModeBit(uint32_t mode, uint32_t bit) -{ - return mode | bit; -} +double const kMaxPendingLocationTimeSec = 15.0; -uint16_t ResetModeBit(uint32_t mode, uint32_t bit) +string LocationModeStatisticsName(location::EMyPositionMode mode) { - return mode & (~bit); -} - -location::EMyPositionMode ResetAllModeBits(uint32_t mode) -{ - return (location::EMyPositionMode)(mode & 0xF); -} - -uint16_t ChangeMode(uint32_t mode, location::EMyPositionMode newMode) -{ - return (mode & 0xF0) | newMode; -} - -bool TestModeBit(uint32_t mode, uint32_t bit) -{ - return (mode & bit) != 0; + switch (mode) + { + case location::PendingPosition: + return "@PendingPosition"; + case location::NotFollowNoPosition: + return "@NotFollowNoPosition"; + case location::NotFollow: + return "@NotFollow"; + case location::Follow: + return "@Follow"; + case location::FollowAndRotate: + return "@FollowAndRotate"; + } + return "@UnknownMode"; } } // namespace @@ -88,22 +83,29 @@ private: double m_rotateDuration; }; -MyPositionController::MyPositionController(location::EMyPositionMode initMode) - : m_modeInfo(location::MODE_PENDING_POSITION) - , m_afterPendingMode(location::MODE_FOLLOW) +MyPositionController::MyPositionController(location::EMyPositionMode initMode, bool isFirstLaunch) + : m_mode(initMode) + , m_isFirstLaunch(isFirstLaunch) + , m_isInRouting(false) + , m_needBlockAnimation(false) + , m_wasRotationInScaling(false) , m_errorRadius(0.0) , m_position(m2::PointD::Zero()) , m_drawDirection(0.0) + , m_oldPosition(m2::PointD::Zero()) + , m_oldDrawDirection(0.0) , m_lastGPSBearing(false) - , m_positionYOffset(POSITION_Y_OFFSET) + , m_positionYOffset(kPositionOffsetY) , m_isVisible(false) , m_isDirtyViewport(false) + , m_isPendingAnimation(false) , m_isPositionAssigned(false) + , m_isDirectionAssigned(false) { - if (initMode > location::MODE_UNKNOWN_POSITION) - m_afterPendingMode = initMode; - else - m_modeInfo = location::MODE_UNKNOWN_POSITION; + if (isFirstLaunch) + m_mode = location::NotFollowNoPosition; + else if (m_mode == location::NotFollowNoPosition) + m_mode = location::Follow; } MyPositionController::~MyPositionController() @@ -113,15 +115,15 @@ MyPositionController::~MyPositionController() void MyPositionController::OnNewPixelRect() { - Follow(); + UpdateViewport(); } void MyPositionController::UpdatePixelPosition(ScreenBase const & screen) { m_pixelRect = screen.isPerspective() ? screen.PixelRectIn3d() : screen.PixelRect(); - m_positionYOffset = screen.isPerspective() ? POSITION_Y_OFFSET_3D : POSITION_Y_OFFSET; - m_pixelPositionRaF = screen.P3dtoP(GetRaFPixelBinding()); - m_pixelPositionF = screen.P3dtoP(m_pixelRect.Center()); + m_positionYOffset = screen.isPerspective() ? kPositionOffsetYIn3D : kPositionOffsetY; + m_centerPixelPositionRouting = screen.P3dtoP(GetRoutingRotationPixelCenter()); + m_centerPixelPosition = screen.P3dtoP(m_pixelRect.Center()); } void MyPositionController::SetListener(ref_ptr listener) @@ -141,45 +143,56 @@ double MyPositionController::GetErrorRadius() const bool MyPositionController::IsModeChangeViewport() const { - return GetMode() >= location::MODE_FOLLOW; + return m_mode == location::Follow || m_mode == location::FollowAndRotate; } bool MyPositionController::IsModeHasPosition() const { - return GetMode() >= location::MODE_NOT_FOLLOW; + return m_mode != location::PendingPosition && m_mode != location::NotFollowNoPosition; } void MyPositionController::DragStarted() { - SetModeInfo(SetModeBit(m_modeInfo, BlockAnimation)); + m_needBlockAnimation = true; } void MyPositionController::DragEnded(m2::PointD const & distance) { float const kBindingDistance = 0.1; - SetModeInfo(ResetModeBit(m_modeInfo, BlockAnimation)); + m_needBlockAnimation = false; if (distance.Length() > kBindingDistance * min(m_pixelRect.SizeX(), m_pixelRect.SizeY())) StopLocationFollow(); - Follow(); + UpdateViewport(); } void MyPositionController::ScaleStarted() { - SetModeInfo(SetModeBit(m_modeInfo, BlockAnimation)); + m_needBlockAnimation = true; +} + +void MyPositionController::ScaleEnded() +{ + m_needBlockAnimation = false; + if (m_wasRotationInScaling) + { + m_wasRotationInScaling = false; + StopLocationFollow(); + } + + UpdateViewport(); } void MyPositionController::Rotated() { - location::EMyPositionMode mode = GetMode(); - if (mode == location::MODE_ROTATE_AND_FOLLOW) - SetModeInfo(SetModeBit(m_modeInfo, StopFollowOnActionEnd)); + if (m_mode == location::FollowAndRotate) + m_wasRotationInScaling = true; } void MyPositionController::CorrectScalePoint(m2::PointD & pt) const { if (IsModeChangeViewport()) - pt = GetCurrentPixelBinding(); + pt = GetRotationPixelCenter(); } void MyPositionController::CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const @@ -187,7 +200,7 @@ void MyPositionController::CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) if (IsModeChangeViewport()) { m2::PointD const oldPt1(pt1); - pt1 = GetCurrentPixelBinding(); + pt1 = GetRotationPixelCenter(); pt2 = pt2 - oldPt1 + pt1; } } @@ -198,199 +211,78 @@ void MyPositionController::CorrectGlobalScalePoint(m2::PointD & pt) const pt = m_position; } -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); } -void MyPositionController::NextMode(int preferredZoomLevel) +void MyPositionController::NextMode() { string const kAlohalyticsClickEvent = "$onClick"; - location::EMyPositionMode currentMode = GetMode(); - location::EMyPositionMode newMode = currentMode; - if (!IsInRouting()) + // Skip switching to next mode while we are waiting for position. + if (IsWaitingForLocation()) { - switch (currentMode) + alohalytics::LogEvent(kAlohalyticsClickEvent, + LocationModeStatisticsName(location::PendingPosition)); + return; + } + + alohalytics::LogEvent(kAlohalyticsClickEvent, LocationModeStatisticsName(m_mode)); + + // Start looking for location. + if (m_mode == location::NotFollowNoPosition) + { + m_pendingTimer.Reset(); + ChangeMode(location::PendingPosition); + return; + } + + // In routing not-follow -> follow-and-rotate, otherwise not-follow -> follow. + if (m_mode == location::NotFollow) + { + ChangeMode(m_isInRouting ? location::FollowAndRotate : location::Follow); + UpdateViewport(); + return; + } + + // From follow mode we transit to follow-and-rotate if compass is available or + // routing is enabled. + if (m_mode == location::Follow) + { + if (IsRotationAvailable() || m_isInRouting) { - case location::MODE_UNKNOWN_POSITION: - alohalytics::LogEvent(kAlohalyticsClickEvent, "@UnknownPosition"); - newMode = location::MODE_PENDING_POSITION; - break; - case location::MODE_PENDING_POSITION: - alohalytics::LogEvent(kAlohalyticsClickEvent, "@PendingPosition"); - newMode = location::MODE_UNKNOWN_POSITION; - m_afterPendingMode = location::MODE_FOLLOW; - break; - case location::MODE_NOT_FOLLOW: - alohalytics::LogEvent(kAlohalyticsClickEvent, "@NotFollow"); - newMode = location::MODE_FOLLOW; - break; - case location::MODE_FOLLOW: - alohalytics::LogEvent(kAlohalyticsClickEvent, "@Follow"); - if (IsRotationActive()) - newMode = location::MODE_ROTATE_AND_FOLLOW; - else - { - newMode = location::MODE_UNKNOWN_POSITION; - m_afterPendingMode = location::MODE_FOLLOW; - } - break; - case location::MODE_ROTATE_AND_FOLLOW: - alohalytics::LogEvent(kAlohalyticsClickEvent, "@RotateAndFollow"); - newMode = location::MODE_UNKNOWN_POSITION; - m_afterPendingMode = location::MODE_FOLLOW; - break; + ChangeMode(location::FollowAndRotate); + UpdateViewport(); } - } - else - { - newMode = IsRotationActive() ? location::MODE_ROTATE_AND_FOLLOW : location::MODE_FOLLOW; + return; } - SetModeInfo(ChangeMode(m_modeInfo, newMode), IsInRouting()); - Follow(preferredZoomLevel); -} - -void MyPositionController::TurnOff() -{ - StopLocationFollow(); - SetModeInfo(location::MODE_UNKNOWN_POSITION); - SetIsVisible(false); -} - -void MyPositionController::Invalidate() -{ - location::EMyPositionMode currentMode = GetMode(); - if (currentMode > location::MODE_PENDING_POSITION) + // From follow-and-rotate mode we can transit to follow mode if routing is disabled. + if (m_mode == location::FollowAndRotate) { - SetModeInfo(ChangeMode(m_modeInfo, location::MODE_UNKNOWN_POSITION)); - SetModeInfo(ChangeMode(m_modeInfo, location::MODE_PENDING_POSITION)); - m_afterPendingMode = currentMode; - SetIsVisible(true); - } - else if (currentMode == location::MODE_UNKNOWN_POSITION) - { - m_afterPendingMode = location::MODE_FOLLOW; - SetIsVisible(false); + if (!m_isInRouting) + { + ChangeMode(location::Follow); + UpdateViewport(); + } } } void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen) { - Assign(info, isNavigable, screen); + m2::PointD const oldPos = GetDrawablePosition(); + double const oldAzimut = GetDrawableAzimut(); - SetIsVisible(true); - - if (GetMode() == location::MODE_PENDING_POSITION) - { - SetModeInfo(ChangeMode(m_modeInfo, m_afterPendingMode)); - m_afterPendingMode = location::MODE_FOLLOW; - } -} - -void MyPositionController::OnCompassUpdate(location::CompassInfo const & info, - ScreenBase const & screen) -{ - Assign(info, screen); -} - -void MyPositionController::SetModeListener(location::TMyPositionModeChanged const & fn) -{ - m_modeChangeCallback = fn; - CallModeListener(m_modeInfo); -} - -void MyPositionController::Render(uint32_t renderMode, ScreenBase const & screen, ref_ptr mng, - dp::UniformValuesStorage const & commonUniforms) -{ - location::EMyPositionMode currentMode = GetMode(); - if (m_shape != nullptr && IsVisible() && currentMode > location::MODE_PENDING_POSITION) - { - if (m_isDirtyViewport && !TestModeBit(m_modeInfo, BlockAnimation)) - { - Follow(); - m_isDirtyViewport = false; - } - - if (!IsModeChangeViewport()) - m_isPendingAnimation = false; - - m_shape->SetPosition(GetDrawablePosition()); - m_shape->SetAzimuth(GetDrawableAzimut()); - m_shape->SetIsValidAzimuth(IsRotationActive()); - m_shape->SetAccuracy(m_errorRadius); - m_shape->SetRoutingMode(IsInRouting()); - - if ((renderMode & RenderAccuracy) != 0) - m_shape->RenderAccuracy(screen, mng, commonUniforms); - - if ((renderMode & RenderMyPosition) != 0) - m_shape->RenderMyPosition(screen, mng, commonUniforms); - } - - CheckAnimFinished(); -} - -bool MyPositionController::IsFollowingActive() const -{ - return IsInRouting() && GetMode() == location::MODE_ROTATE_AND_FOLLOW; -} - -void MyPositionController::AnimateStateTransition(location::EMyPositionMode oldMode, location::EMyPositionMode newMode) -{ - if (oldMode == location::MODE_PENDING_POSITION && newMode == location::MODE_FOLLOW) - { - ChangeModelView(m_position, -1); - } - else if (oldMode == location::MODE_ROTATE_AND_FOLLOW && - (newMode == location::MODE_FOLLOW || newMode == location::MODE_UNKNOWN_POSITION)) - { - ChangeModelView(m_position, 0.0, m_pixelPositionF, -1); - } -} - -bool MyPositionController::AlmostCurrentPosition(const m2::PointD & pos) const -{ - double const kPositionEqualityDelta = 1e-5; - - return pos.EqualDxDy(m_position, kPositionEqualityDelta); -} - -bool MyPositionController::AlmostCurrentAzimut(double azimut) const -{ - double const kDirectionEqualityDelta = 1e-5; - - return my::AlmostEqualAbs(azimut, m_drawDirection, kDirectionEqualityDelta); -} - -void MyPositionController::Assign(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen) -{ - m2::PointD oldPos = GetDrawablePosition(); - double oldAzimut = GetDrawableAzimut(); - - m2::RectD rect = MercatorBounds::MetresToXY(info.m_longitude, - info.m_latitude, + m2::RectD rect = MercatorBounds::MetresToXY(info.m_longitude, info.m_latitude, info.m_horizontalAccuracy); m_position = rect.Center(); - m_errorRadius = rect.SizeX() / 2; + m_errorRadius = rect.SizeX() * 0.5; bool const hasBearing = info.HasBearing(); if ((isNavigable && hasBearing) || - (!isNavigable && hasBearing && info.HasSpeed() && info.m_speed > MIN_SPEED_THRESHOLD_MPS)) + (!isNavigable && hasBearing && info.HasSpeed() && info.m_speed > kMinSpeedThresholdMps)) { SetDirection(my::DegToRad(info.m_bearing)); m_lastGPSBearing.Reset(); @@ -405,87 +297,161 @@ void MyPositionController::Assign(location::GpsInfo const & info, bool isNavigab m_isDirtyViewport = true; } + if (m_mode == location::PendingPosition || m_mode == location::NotFollowNoPosition) + { + ChangeMode(location::Follow); + if (!m_isFirstLaunch) + { + m2::PointD const size(m_errorRadius, m_errorRadius); + ChangeModelView(m2::RectD(m_position - size, m_position + size)); + } + else + { + ChangeModelView(m_position, -1); + } + } + else if (!m_isPositionAssigned) + { + ChangeMode(m_mode); + } + m_isPositionAssigned = true; + SetIsVisible(true); } -void MyPositionController::Assign(location::CompassInfo const & info, ScreenBase const & screen) +void MyPositionController::LoseLocation() { - double oldAzimut = GetDrawableAzimut(); + if (IsWaitingForLocation()) + ChangeMode(location::NotFollowNoPosition); - if ((IsInRouting() && GetMode() >= location::MODE_FOLLOW) || - (m_lastGPSBearing.ElapsedSeconds() < GPS_BEARING_LIFETIME_S)) - { + SetIsVisible(false); +} + +void MyPositionController::OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen) +{ + double const oldAzimut = GetDrawableAzimut(); + + if ((IsInRouting() && m_mode == location::FollowAndRotate) || + m_lastGPSBearing.ElapsedSeconds() < kGpsBearingLifetimeSec) return; - } SetDirection(info.m_bearing); - if (m_isPositionAssigned && !AlmostCurrentAzimut(oldAzimut) && GetMode() == location::MODE_ROTATE_AND_FOLLOW) + if (m_isPositionAssigned && !AlmostCurrentAzimut(oldAzimut) && m_mode == location::FollowAndRotate) { CreateAnim(GetDrawablePosition(), oldAzimut, screen); m_isDirtyViewport = true; } +} - m_isPositionAssigned = true; +void MyPositionController::SetModeListener(location::TMyPositionModeChanged const & fn) +{ + m_modeChangeCallback = fn; + + location::EMyPositionMode mode = m_mode; + if (m_isFirstLaunch) + mode = location::NotFollowNoPosition; + else if (!m_isPositionAssigned) + mode = location::PendingPosition; + + if (m_modeChangeCallback != nullptr) + m_modeChangeCallback(mode, m_isInRouting); +} + +void MyPositionController::Render(uint32_t renderMode, ScreenBase const & screen, + ref_ptr mng, + dp::UniformValuesStorage const & commonUniforms) +{ + if (IsWaitingForLocation()) + { + if (m_pendingTimer.ElapsedSeconds() >= kMaxPendingLocationTimeSec) + ChangeMode(location::NotFollowNoPosition); + } + + if (m_shape != nullptr && IsVisible() && IsModeHasPosition()) + { + if (m_isDirtyViewport && !m_needBlockAnimation) + { + UpdateViewport(); + m_isDirtyViewport = false; + } + + if (!IsModeChangeViewport()) + m_isPendingAnimation = false; + + m_shape->SetPosition(GetDrawablePosition()); + m_shape->SetAzimuth(GetDrawableAzimut()); + m_shape->SetIsValidAzimuth(IsRotationAvailable()); + m_shape->SetAccuracy(m_errorRadius); + m_shape->SetRoutingMode(IsInRouting()); + + if ((renderMode & RenderAccuracy) != 0) + m_shape->RenderAccuracy(screen, mng, commonUniforms); + + if ((renderMode & RenderMyPosition) != 0) + m_shape->RenderMyPosition(screen, mng, commonUniforms); + } + + CheckAnimFinished(); +} + +bool MyPositionController::IsRouteFollowingActive() const +{ + return IsInRouting() && m_mode == location::FollowAndRotate; +} + +bool MyPositionController::AlmostCurrentPosition(m2::PointD const & pos) const +{ + double const kPositionEqualityDelta = 1e-5; + return pos.EqualDxDy(m_position, kPositionEqualityDelta); +} + +bool MyPositionController::AlmostCurrentAzimut(double azimut) const +{ + double const kDirectionEqualityDelta = 1e-5; + return my::AlmostEqualAbs(azimut, m_drawDirection, kDirectionEqualityDelta); } void MyPositionController::SetDirection(double bearing) { m_drawDirection = bearing; - SetModeInfo(SetModeBit(m_modeInfo, KnownDirectionBit)); + m_isDirectionAssigned = true; } -void MyPositionController::SetModeInfo(uint32_t modeInfo, bool force) -{ - location::EMyPositionMode const newMode = ResetAllModeBits(modeInfo); - location::EMyPositionMode const oldMode = GetMode(); - m_modeInfo = modeInfo; - if (newMode != oldMode || force) - { - AnimateStateTransition(oldMode, newMode); - CallModeListener(newMode); - } -} - -location::EMyPositionMode MyPositionController::GetMode() const -{ - return ResetAllModeBits(m_modeInfo); -} - -void MyPositionController::CallModeListener(uint32_t mode) +void MyPositionController::ChangeMode(location::EMyPositionMode newMode) { + m_mode = newMode; if (m_modeChangeCallback != nullptr) - m_modeChangeCallback(ResetAllModeBits(mode)); + m_modeChangeCallback(m_mode, m_isInRouting); } -bool MyPositionController::IsInRouting() const +bool MyPositionController::IsWaitingForLocation() const { - return TestModeBit(m_modeInfo, RoutingSessionBit); -} + if (m_mode == location::NotFollowNoPosition) + return false; + + if (!m_isPositionAssigned) + return true; -bool MyPositionController::IsRotationActive() const -{ - return TestModeBit(m_modeInfo, KnownDirectionBit); + return m_mode == location::PendingPosition; } void MyPositionController::StopLocationFollow() { - location::EMyPositionMode currentMode = GetMode(); - if (currentMode > location::MODE_NOT_FOLLOW) - SetModeInfo(ChangeMode(m_modeInfo, location::MODE_NOT_FOLLOW)); - else if (currentMode == location::MODE_PENDING_POSITION) - m_afterPendingMode = location::MODE_NOT_FOLLOW; + if (m_mode == location::Follow || m_mode == location::FollowAndRotate) + ChangeMode(location::NotFollow); } -bool MyPositionController::StopCompassFollow() +void MyPositionController::OnCompassTapped() { - if (GetMode() != location::MODE_ROTATE_AND_FOLLOW) - return false; - - SetModeInfo(ChangeMode(m_modeInfo, location::MODE_FOLLOW)); - Follow(); - - return true; + alohalytics::LogEvent("$compassClicked", {{"mode", LocationModeStatisticsName(m_mode)}, + {"routing", strings::to_string(IsInRouting())}}); + ChangeModelView(0.0); + if (m_mode == location::FollowAndRotate) + { + ChangeMode(location::Follow); + UpdateViewport(); + } } void MyPositionController::ChangeModelView(m2::PointD const & center, int zoomLevel) @@ -507,43 +473,43 @@ void MyPositionController::ChangeModelView(m2::RectD const & rect) } void MyPositionController::ChangeModelView(m2::PointD const & userPos, double azimuth, - m2::PointD const & pxZero, int preferredZoomLevel) + m2::PointD const & pxZero, int zoomLevel) { if (m_listener) - m_listener->ChangeModelView(userPos, azimuth, pxZero, preferredZoomLevel); + m_listener->ChangeModelView(userPos, azimuth, pxZero, zoomLevel); } -void MyPositionController::Follow(int preferredZoomLevel) +void MyPositionController::UpdateViewport() { - location::EMyPositionMode currentMode = GetMode(); - if (currentMode == location::MODE_FOLLOW) - ChangeModelView(m_position, preferredZoomLevel); - else if (currentMode == location::MODE_ROTATE_AND_FOLLOW) - ChangeModelView(m_position, m_drawDirection, m_pixelPositionRaF, preferredZoomLevel); + if (IsWaitingForLocation()) + return; + + if (m_mode == location::Follow) + ChangeModelView(m_position, -1); + else if (m_mode == location::FollowAndRotate) + ChangeModelView(m_position, m_drawDirection, GetRotationPixelCenter(), -1); } -m2::PointD MyPositionController::GetRaFPixelBinding() const +m2::PointD MyPositionController::GetRotationPixelCenter() const +{ + if (m_mode == location::Follow) + return m_centerPixelPosition; + + if (m_mode == location::FollowAndRotate) + return m_isInRouting ? m_centerPixelPositionRouting : m_centerPixelPosition; + + return m2::PointD::Zero(); +} + +m2::PointD MyPositionController::GetRoutingRotationPixelCenter() const { return m2::PointD(m_pixelRect.Center().x, m_pixelRect.maxY() - m_positionYOffset * 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(); -} - m2::PointD MyPositionController::GetDrawablePosition() const { - if (m_anim && m_anim->IsMovingActive()) + if (m_anim != nullptr && m_anim->IsMovingActive()) return m_anim->GetCurrentPosition(); if (m_isPendingAnimation) @@ -554,7 +520,7 @@ m2::PointD MyPositionController::GetDrawablePosition() const double MyPositionController::GetDrawableAzimut() const { - if (m_anim && m_anim->IsRotatingActive()) + if (m_anim != nullptr && m_anim->IsRotatingActive()) return m_anim->GetCurrentAzimut(); if (m_isPendingAnimation) @@ -603,27 +569,34 @@ void MyPositionController::CreateAnim(m2::PointD const & oldPos, double oldAzimu } } -void MyPositionController::ActivateRouting() +void MyPositionController::ActivateRouting(int zoomLevel) { - if (!IsInRouting()) + if (!m_isInRouting) { - location::EMyPositionMode newMode = GetMode(); - if (IsModeHasPosition()) - newMode = location::MODE_NOT_FOLLOW; + m_isInRouting = true; - SetModeInfo(ChangeMode(SetModeBit(m_modeInfo, RoutingSessionBit), newMode)); + if (IsRotationAvailable()) + { + ChangeMode(location::FollowAndRotate); + ChangeModelView(m_position, m_drawDirection, GetRotationPixelCenter(), zoomLevel); + } + else + { + ChangeMode(location::Follow); + ChangeModelView(m_position, zoomLevel); + } } } void MyPositionController::DeactivateRouting() { - if (IsInRouting()) + if (m_isInRouting) { - SetModeInfo(ResetModeBit(m_modeInfo, RoutingSessionBit)); + m_isInRouting = false; - location::EMyPositionMode currentMode = GetMode(); - if (currentMode == location::MODE_ROTATE_AND_FOLLOW) - SetModeInfo(ChangeMode(m_modeInfo, location::MODE_FOLLOW)); + ChangeMode(location::Follow); + if (m_mode == location::FollowAndRotate) + ChangeModelView(m_position, 0.0, m_centerPixelPosition, -1); else ChangeModelView(0.0); } diff --git a/drape_frontend/my_position_controller.hpp b/drape_frontend/my_position_controller.hpp index 5f0768dd63..d77e7828b5 100644 --- a/drape_frontend/my_position_controller.hpp +++ b/drape_frontend/my_position_controller.hpp @@ -33,7 +33,7 @@ public: virtual void ChangeModelView(m2::RectD const & rect) = 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 preferredZoomLevel) = 0; + int zoomLevel) = 0; }; // Render bits @@ -43,7 +43,7 @@ public: RenderMyPosition = 0x2 }; - MyPositionController(location::EMyPositionMode initMode); + MyPositionController(location::EMyPositionMode initMode, bool isFirstLaunch); ~MyPositionController(); void OnNewPixelRect(); @@ -53,30 +53,32 @@ public: m2::PointD const & Position() const; double GetErrorRadius() const; - bool IsModeChangeViewport() const; bool IsModeHasPosition() const; void DragStarted(); void DragEnded(m2::PointD const & distance); - void AnimationStarted(ref_ptr anim); void ScaleStarted(); + void ScaleEnded(); + + void AnimationStarted(ref_ptr anim); + void Rotated(); + void CorrectScalePoint(m2::PointD & pt) const; void CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const; void CorrectGlobalScalePoint(m2::PointD & pt) const; - void ScaleEnded(); void SetRenderShape(drape_ptr && shape); - void ActivateRouting(); + void ActivateRouting(int zoomLevel); void DeactivateRouting(); void StopLocationFollow(); - bool StopCompassFollow(); - void NextMode(int preferredZoomLevel = -1); - void TurnOff(); - void Invalidate(); + void NextMode(); + void LoseLocation(); + + void OnCompassTapped(); void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen); void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen); @@ -86,33 +88,27 @@ public: void Render(uint32_t renderMode, ScreenBase const & screen, ref_ptr mng, dp::UniformValuesStorage const & commonUniforms); - bool IsFollowingActive() const; - bool IsRotationActive() const; - bool IsInRouting() const; + bool IsRotationAvailable() const { return m_isDirectionAssigned; } + bool IsInRouting() const { return m_isInRouting; } + bool IsRouteFollowingActive() const; + bool IsWaitingForLocation() const; private: - void AnimateStateTransition(location::EMyPositionMode oldMode, location::EMyPositionMode newMode); - - void Assign(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen); - void Assign(location::CompassInfo const & info, ScreenBase const & screen); + bool IsModeChangeViewport() const; + void ChangeMode(location::EMyPositionMode newMode); void SetDirection(double bearing); - void SetModeInfo(uint32_t modeInfo, bool force = false); - location::EMyPositionMode GetMode() const; - void CallModeListener(uint32_t mode); - bool IsVisible() const { return m_isVisible; } void SetIsVisible(bool isVisible) { m_isVisible = isVisible; } void ChangeModelView(m2::PointD const & center, int zoomLevel); void ChangeModelView(double azimuth); void ChangeModelView(m2::RectD const & rect); - void ChangeModelView(m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero, - int preferredZoomLevel); + void ChangeModelView(m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero, int zoomLevel); - void Follow(int preferredZoomLevel = -1); - m2::PointD GetRaFPixelBinding() const; - m2::PointD GetCurrentPixelBinding() const; + void UpdateViewport(); + m2::PointD GetRotationPixelCenter() const; + m2::PointD GetRoutingRotationPixelCenter() const; m2::PointD GetDrawablePosition() const; double GetDrawableAzimut() const; @@ -123,16 +119,13 @@ private: bool AlmostCurrentAzimut(double azimut) const; private: - // Mode bits - // { - static uint32_t const RoutingSessionBit = 0x40; - static uint32_t const KnownDirectionBit = 0x80; - static uint32_t const BlockAnimation = 0x100; - static uint32_t const StopFollowOnActionEnd = 0x200; - // } + location::EMyPositionMode m_mode; + bool m_isFirstLaunch; - uint32_t m_modeInfo; // combination of Mode enum and "Mode bits" - location::EMyPositionMode m_afterPendingMode; + bool m_isInRouting; + + bool m_needBlockAnimation; + bool m_wasRotationInScaling; location::TMyPositionModeChanged m_modeChangeCallback; drape_ptr m_shape; @@ -141,19 +134,20 @@ private: double m_errorRadius; // error radius in mercator m2::PointD m_position; // position in mercator double m_drawDirection; - my::HighResTimer m_lastGPSBearing; + m2::PointD m_oldPosition; // position in mercator + double m_oldDrawDirection; + + my::Timer m_lastGPSBearing; + my::Timer m_pendingTimer; m2::RectD m_pixelRect; - m2::PointD m_pixelPositionRaF; - m2::PointD m_pixelPositionF; + m2::PointD m_centerPixelPositionRouting; + m2::PointD m_centerPixelPosition; double m_positionYOffset; bool m_isVisible; bool m_isDirtyViewport; - bool m_isPendingAnimation = false; - - m2::PointD m_oldPosition; // position in mercator - double m_oldDrawDirection; + bool m_isPendingAnimation; class MyPositionAnim; mutable drape_ptr m_anim; @@ -162,6 +156,7 @@ private: TAnimationCreator m_animCreator; bool m_isPositionAssigned; + bool m_isDirectionAssigned; }; } diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm b/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm index 2426272771..914c35f05f 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm @@ -175,11 +175,11 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) [locBtn.imageView.layer removeAllAnimations]; switch (mode) { - case location::MODE_UNKNOWN_POSITION: - case location::MODE_NOT_FOLLOW: - case location::MODE_FOLLOW: + case location::NotFollow: + case location::NotFollowNoPosition: + case location::Follow: break; - case location::MODE_PENDING_POSITION: + case location::PendingPosition: { [locBtn setImage:[UIImage imageNamed:@"ic_menu_location_pending"] forState:UIControlStateNormal]; @@ -192,7 +192,7 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) [locBtn.imageView.layer addAnimation:rotation forKey:@"locationImage"]; break; } - case location::MODE_ROTATE_AND_FOLLOW: + case location::FollowAndRotate: { NSUInteger const morphImagesCount = 6; NSUInteger const endValue = morphImagesCount + 1; @@ -227,22 +227,19 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) MWMButton * locBtn = self.locationButton; switch (state) { - case location::MODE_PENDING_POSITION: + case location::PendingPosition: locBtn.coloring = MWMButtonColoringBlue; break; - case location::MODE_UNKNOWN_POSITION: - [locBtn setImage:[UIImage imageNamed:@"ic_menu_location_follow"] forState:UIControlStateNormal]; - locBtn.coloring = MWMButtonColoringGray; - break; - case location::MODE_NOT_FOLLOW: + case location::NotFollow: + case location::NotFollowNoPosition: [locBtn setImage:[UIImage imageNamed:@"ic_menu_location_get_position"] forState:UIControlStateNormal]; locBtn.coloring = MWMButtonColoringBlack; break; - case location::MODE_FOLLOW: + case location::Follow: [locBtn setImage:[UIImage imageNamed:@"ic_menu_location_follow"] forState:UIControlStateNormal]; locBtn.coloring = MWMButtonColoringBlue; break; - case location::MODE_ROTATE_AND_FOLLOW: + case location::FollowAndRotate: [locBtn setImage:[UIImage imageNamed:@"ic_menu_location_follow_and_rotate"] forState:UIControlStateNormal]; locBtn.coloring = MWMButtonColoringBlue; break; diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm index 07ff0dd398..c06bd67d39 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm @@ -558,7 +558,7 @@ extern NSString * const kAlohalyticsTapEventKey; { MWMAlertViewController * controller = [[MWMAlertViewController alloc] initWithViewController:self.ownerController]; LocationManager * manager = MapsAppDelegate.theApp.locationManager; - BOOL const needToRebuild = manager.lastLocationIsValid && !manager.isLocationModeUnknownOrPending && !isDestinationMyPosition; + BOOL const needToRebuild = manager.lastLocationIsValid && !manager.isLocationPendingOrNoPosition && !isDestinationMyPosition; m2::PointD const locationPoint = manager.lastLocation.mercator; [controller presentPoint2PointAlertWithOkBlock:^ { diff --git a/iphone/Maps/Classes/EAGLView.mm b/iphone/Maps/Classes/EAGLView.mm index 01cd45add5..fda5ee4783 100644 --- a/iphone/Maps/Classes/EAGLView.mm +++ b/iphone/Maps/Classes/EAGLView.mm @@ -6,6 +6,8 @@ #import "../Platform/opengl/iosOGLContextFactory.h" +#import "3party/Alohalytics/src/alohalytics_objc.h" + #include "Framework.h" #include "indexer/classificator_loader.hpp" @@ -92,11 +94,12 @@ double getExactDPI(double contentScaleFactor) LOG(LINFO, ("EAGLView createDrapeEngine Started")); if (MapsAppDelegate.theApp.isDaemonMode) return; - + Framework::DrapeCreationParams p; p.m_surfaceWidth = width; p.m_surfaceHeight = height; p.m_visualScale = dp::VisualScale(getExactDPI(self.contentScaleFactor)); + p.m_isFirstLaunch = [Alohalytics isFirstSession]; [self.widgetsManager setupWidgets:p]; GetFramework().CreateDrapeEngine(make_ref(m_factory), move(p)); diff --git a/iphone/Maps/Classes/LocationPredictor.mm b/iphone/Maps/Classes/LocationPredictor.mm index a7935ea4a6..13cdec8b11 100644 --- a/iphone/Maps/Classes/LocationPredictor.mm +++ b/iphone/Maps/Classes/LocationPredictor.mm @@ -38,8 +38,8 @@ namespace -(void)setMode:(location::EMyPositionMode)mode { - m_generatePredictions = (mode == location::MODE_ROTATE_AND_FOLLOW); - if (mode < location::MODE_NOT_FOLLOW) + m_generatePredictions = (mode == location::FollowAndRotate); + if (mode == location::PendingPosition || mode == location::NotFollowNoPosition) m_gpsInfoIsValid = false; [self resetTimer]; diff --git a/iphone/Maps/Classes/MWMBasePlacePageView.mm b/iphone/Maps/Classes/MWMBasePlacePageView.mm index ed28ba2572..d27764edb0 100644 --- a/iphone/Maps/Classes/MWMBasePlacePageView.mm +++ b/iphone/Maps/Classes/MWMBasePlacePageView.mm @@ -185,7 +185,7 @@ enum class AttributePosition BOOL const isMyPosition = entity.isMyPosition; self.addressLabel.text = entity.address; BOOL const isHeadingAvaible = [CLLocationManager headingAvailable]; - BOOL const noLocation = MapsAppDelegate.theApp.locationManager.isLocationModeUnknownOrPending; + BOOL const noLocation = MapsAppDelegate.theApp.locationManager.isLocationPendingOrNoPosition; self.distanceLabel.hidden = noLocation || isMyPosition; BOOL const hideDirection = noLocation || isMyPosition || !isHeadingAvaible; self.directionArrow.hidden = hideDirection; diff --git a/iphone/Maps/Classes/MWMPlacePageViewManager.mm b/iphone/Maps/Classes/MWMPlacePageViewManager.mm index a7d2450a68..72865727db 100644 --- a/iphone/Maps/Classes/MWMPlacePageViewManager.mm +++ b/iphone/Maps/Classes/MWMPlacePageViewManager.mm @@ -189,8 +189,8 @@ extern NSString * const kBookmarksChangedNotification; [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"ppRoute"]; LocationManager * lm = MapsAppDelegate.theApp.locationManager; - [self.delegate buildRouteFrom:lm.isLocationModeUnknownOrPending ? MWMRoutePoint::MWMRoutePointZero() - : MWMRoutePoint(lm.lastLocation.mercator) + [self.delegate buildRouteFrom:lm.isLocationPendingOrNoPosition ? MWMRoutePoint::MWMRoutePointZero() + : MWMRoutePoint(lm.lastLocation.mercator) to:self.target]; } diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm index 0350e23d40..43d405384b 100644 --- a/iphone/Maps/Classes/MapViewController.mm +++ b/iphone/Maps/Classes/MapViewController.mm @@ -519,7 +519,7 @@ NSString * const kReportSegue = @"Map2ReportSegue"; f.SetMapSelectionListeners([self](place_page::Info const & info) { [self onMapObjectSelected:info]; }, [self](bool switchFullScreen) { [self onMapObjectDeselected:switchFullScreen]; }); // TODO: Review and improve this code. - f.SetMyPositionModeListener([self](location::EMyPositionMode mode) + f.SetMyPositionModeListener([self](location::EMyPositionMode mode, bool routingActive) { // TODO: Two global listeners are subscribed to the same event from the core. // Probably it's better to subscribe only wnen needed and usubscribe in other cases. @@ -579,22 +579,19 @@ NSString * const kReportSegue = @"Map2ReportSegue"; switch (mode) { - case location::MODE_UNKNOWN_POSITION: - { - self.disableStandbyOnLocationStateMode = NO; - if (![Alohalytics isFirstSession]) - [[MapsAppDelegate theApp].locationManager stop:self]; - break; - } - case location::MODE_PENDING_POSITION: + case location::PendingPosition: self.disableStandbyOnLocationStateMode = NO; [[MapsAppDelegate theApp].locationManager start:self]; break; - case location::MODE_NOT_FOLLOW: + case location::NotFollowNoPosition: + //TODO(iOS team): show dialog if it is not first launch self.disableStandbyOnLocationStateMode = NO; break; - case location::MODE_FOLLOW: - case location::MODE_ROTATE_AND_FOLLOW: + case location::NotFollow: + self.disableStandbyOnLocationStateMode = NO; + break; + case location::Follow: + case location::FollowAndRotate: self.disableStandbyOnLocationStateMode = YES; break; } diff --git a/iphone/Maps/Classes/MapsAppDelegate.mm b/iphone/Maps/Classes/MapsAppDelegate.mm index 7de28586c1..075c769dd3 100644 --- a/iphone/Maps/Classes/MapsAppDelegate.mm +++ b/iphone/Maps/Classes/MapsAppDelegate.mm @@ -277,8 +277,6 @@ using namespace osm_auth_ios; [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:minimumBackgroundFetchIntervalInSeconds]; [self startAdServerForbiddenCheckTimer]; [self updateApplicationIconBadgeNumber]; - - GetFramework().InvalidateMyPosition(); } - (void)determineMapStyle diff --git a/iphone/Maps/Platform/LocationManager.h b/iphone/Maps/Platform/LocationManager.h index 62fe2d002d..e0ed79c8d9 100644 --- a/iphone/Maps/Platform/LocationManager.h +++ b/iphone/Maps/Platform/LocationManager.h @@ -31,7 +31,7 @@ - (NSString *)formattedSpeedAndAltitude:(BOOL &)hasSpeed; - (bool)lastLocationIsValid; -- (bool)isLocationModeUnknownOrPending; +- (bool)isLocationPendingOrNoPosition; - (BOOL)enabledOnMap; - (void)triggerCompass; diff --git a/iphone/Maps/Platform/LocationManager.mm b/iphone/Maps/Platform/LocationManager.mm index 3d324bfbbe..b6d0887d63 100644 --- a/iphone/Maps/Platform/LocationManager.mm +++ b/iphone/Maps/Platform/LocationManager.mm @@ -319,13 +319,13 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw return (([self lastLocation] != nil) && ([self.lastLocationTime timeIntervalSinceNow] > -300.0)); } -- (bool)isLocationModeUnknownOrPending +- (bool)isLocationPendingOrNoPosition { using location::EMyPositionMode; EMyPositionMode mode; if (!settings::Get(settings::kLocationStateMode, mode)) return true; - return mode == EMyPositionMode::MODE_PENDING_POSITION || mode == EMyPositionMode::MODE_UNKNOWN_POSITION; + return mode == EMyPositionMode::PendingPosition || mode == EMyPositionMode::NotFollowNoPosition; } - (BOOL)enabledOnMap diff --git a/map/framework.cpp b/map/framework.cpp index 1ab0a59053..7b8375179b 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -149,7 +149,7 @@ pair Framework::RegisterMap( void Framework::OnLocationError(TLocationError /*error*/) { - CallDrapeFunction(bind(&df::DrapeEngine::CancelMyPosition, _1)); + CallDrapeFunction(bind(&df::DrapeEngine::LoseLocation, _1)); } void Framework::OnLocationUpdate(GpsInfo const & info) @@ -203,14 +203,9 @@ void Framework::OnCompassUpdate(CompassInfo const & info) CallDrapeFunction(bind(&df::DrapeEngine::SetCompassInfo, _1, rInfo)); } -void Framework::SwitchMyPositionNextMode(int preferredZoomLevel) +void Framework::SwitchMyPositionNextMode() { - CallDrapeFunction(bind(&df::DrapeEngine::MyPositionNextMode, _1, preferredZoomLevel)); -} - -void Framework::InvalidateMyPosition() -{ - CallDrapeFunction(bind(&df::DrapeEngine::InvalidateMyPosition, _1)); + CallDrapeFunction(bind(&df::DrapeEngine::SwitchMyPositionNextMode, _1)); } void Framework::SetMyPositionModeListener(TMyPositionModeChanged && fn) @@ -1470,7 +1465,8 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, df::MapDataProvider(idReadFn, featureReadFn, isCountryLoadedByNameFn, updateCurrentCountryFn), params.m_visualScale, move(params.m_widgetsInitInfo), make_pair(params.m_initialMyPositionState, params.m_hasMyPositionState), - allow3dBuildings, params.m_isChoosePositionMode, params.m_isChoosePositionMode); + allow3dBuildings, params.m_isChoosePositionMode, + params.m_isChoosePositionMode, params.m_isFirstLaunch); m_drapeEngine = make_unique_dp(move(p)); AddViewportListener([this](ScreenBase const & screen) @@ -1484,7 +1480,6 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, OnSize(params.m_surfaceWidth, params.m_surfaceHeight); m_drapeEngine->SetMyPositionModeListener(m_myPositionListener); - m_drapeEngine->InvalidateMyPosition(); InvalidateUserMarks(); @@ -2134,6 +2129,7 @@ void Framework::BuildRoute(m2::PointD const & start, m2::PointD const & finish, double const kRouteScaleMultiplier = 1.5; InsertRoute(route); + StopLocationFollow(); m2::RectD routeRect = route.GetPoly().GetLimitRect(); routeRect.Scale(kRouteScaleMultiplier); ShowRect(routeRect, -1); diff --git a/map/framework.hpp b/map/framework.hpp index f7493dd473..c00ed341fe 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -309,8 +309,7 @@ public: void OnLocationError(location::TLocationError error); void OnLocationUpdate(location::GpsInfo const & info); void OnCompassUpdate(location::CompassInfo const & info); - void SwitchMyPositionNextMode(int preferredZoomLevel = -1); - void InvalidateMyPosition(); + void SwitchMyPositionNextMode(); /// Should be set before Drape initialization. Guarantees that fn is called in main thread context. void SetMyPositionModeListener(location::TMyPositionModeChanged && fn); @@ -327,9 +326,11 @@ public: gui::TWidgetsInitInfo m_widgetsInitInfo; bool m_hasMyPositionState = false; - location::EMyPositionMode m_initialMyPositionState = location::MODE_UNKNOWN_POSITION; + location::EMyPositionMode m_initialMyPositionState = location::PendingPosition; bool m_isChoosePositionMode = false; + + bool m_isFirstLaunch = false; }; void CreateDrapeEngine(ref_ptr contextFactory, DrapeCreationParams && params); diff --git a/platform/location.hpp b/platform/location.hpp index f068b213e7..38b5b4fe66 100644 --- a/platform/location.hpp +++ b/platform/location.hpp @@ -232,16 +232,15 @@ namespace location double GetDistanceFromBegin() const { return m_distanceFromBegin; } }; - // Do not change the order and values enum EMyPositionMode { - MODE_UNKNOWN_POSITION = 0x0, - MODE_PENDING_POSITION = 0x1, - MODE_NOT_FOLLOW = 0x2, - MODE_FOLLOW = 0x3, - MODE_ROTATE_AND_FOLLOW = 0x4, + PendingPosition = 0, + NotFollowNoPosition, + NotFollow, + Follow, + FollowAndRotate }; - using TMyPositionModeChanged = function; + using TMyPositionModeChanged = function; } // namespace location diff --git a/platform/settings.cpp b/platform/settings.cpp index 0cb17a4f3f..9feff99bc1 100644 --- a/platform/settings.cpp +++ b/platform/settings.cpp @@ -392,28 +392,28 @@ string ToString(location::EMyPositionMode const & v) { switch (v) { - case location::MODE_UNKNOWN_POSITION: return "Unknown"; - case location::MODE_PENDING_POSITION: return "Pending"; - case location::MODE_NOT_FOLLOW: return "NotFollow"; - case location::MODE_FOLLOW: return "Follow"; - case location::MODE_ROTATE_AND_FOLLOW: return "RotateAndFollow"; - default: return "Unknown"; + case location::PendingPosition: return "PendingPosition"; + case location::NotFollow: return "NotFollow"; + case location::NotFollowNoPosition: return "NotFollowNoPosition"; + case location::Follow: return "Follow"; + case location::FollowAndRotate: return "FollowAndRotate"; + default: return "Pending"; } } template <> bool FromString(string const & s, location::EMyPositionMode & v) { - if (s == "Unknown") - v = location::MODE_UNKNOWN_POSITION; - else if (s == "Pending") - v = location::MODE_PENDING_POSITION; + if (s == "PendingPosition") + v = location::PendingPosition; else if (s == "NotFollow") - v = location::MODE_NOT_FOLLOW; + v = location::NotFollow; + else if (s == "NotFollowNoPosition") + v = location::NotFollowNoPosition; else if (s == "Follow") - v = location::MODE_FOLLOW; - else if (s == "RotateAndFollow") - v = location::MODE_ROTATE_AND_FOLLOW; + v = location::Follow; + else if (s == "FollowAndRotate") + v = location::FollowAndRotate; else return false; diff --git a/qt/mainwindow.cpp b/qt/mainwindow.cpp index 02324bd151..8eb1b23eff 100644 --- a/qt/mainwindow.cpp +++ b/qt/mainwindow.cpp @@ -189,7 +189,7 @@ bool MainWindow::winEvent(MSG * msg, long * result) void MainWindow::LocationStateModeChanged(location::EMyPositionMode mode) { - if (mode == location::MODE_PENDING_POSITION) + if (mode == location::PendingPosition) { m_locationService->Start(); m_pMyPositionAction->setIcon(QIcon(":/navig64/location-search.png")); @@ -197,9 +197,6 @@ void MainWindow::LocationStateModeChanged(location::EMyPositionMode mode) return; } - if (mode == location::MODE_UNKNOWN_POSITION) - m_locationService->Stop(); - m_pMyPositionAction->setIcon(QIcon(":/navig64/location.png")); m_pMyPositionAction->setToolTip(tr("My Position")); } @@ -509,7 +506,7 @@ void MainWindow::OnUploadEditsMenuItem() void MainWindow::OnBeforeEngineCreation() { - m_pDrawWidget->GetFramework().SetMyPositionModeListener([this](location::EMyPositionMode mode) + m_pDrawWidget->GetFramework().SetMyPositionModeListener([this](location::EMyPositionMode mode, bool routingActive) { LocationStateModeChanged(mode); });