forked from organicmaps/organicmaps
Redone my position
This commit is contained in:
parent
047ebf3c4a
commit
c1d1942f4d
35 changed files with 467 additions and 554 deletions
|
@ -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<dp::ThreadSafeFactory>(new AndroidOGLContextFactory(env, jSurface));
|
||||
AndroidOGLContextFactory const * factory = m_contextFactory->CastFactory<AndroidOGLContextFactory>();
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace android
|
|||
|
||||
map<gui::EWidget, gui::Position> 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();
|
||||
|
||||
|
|
|
@ -18,18 +18,19 @@ extern "C"
|
|||
return g_framework->GetMyPositionMode();
|
||||
}
|
||||
|
||||
void LocationStateModeChanged(location::EMyPositionMode mode, shared_ptr<jobject> const & obj)
|
||||
void LocationStateModeChanged(location::EMyPositionMode mode, bool routingActive, shared_ptr<jobject> const & obj)
|
||||
{
|
||||
g_framework->SetMyPositionMode(mode);
|
||||
|
||||
JNIEnv * env = jni::GetEnv();
|
||||
env->CallVoidMethod(*obj, jni::GetMethodID(env, *obj.get(), "onMyPositionModeChangedCallback", "(I)V"), static_cast<jint>(mode));
|
||||
env->CallVoidMethod(*obj, jni::GetMethodID(env, *obj.get(), "onMyPositionModeChangedCallback", "(IZ)V"),
|
||||
static_cast<jint>(mode), static_cast<jboolean>(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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
*/
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -240,7 +240,7 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> 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<MyPositionShapeMessage>(make_unique_dp<MyPosition>(m_texMng),
|
||||
make_unique_dp<SelectionShape>(m_texMng));
|
||||
auto msg = make_unique_dp<MapShapesMessage>(make_unique_dp<MyPosition>(m_texMng),
|
||||
make_unique_dp<SelectionShape>(m_texMng));
|
||||
|
||||
GLFunctions::glFlush();
|
||||
m_commutator->PostMessage(ThreadsCommutator::RenderThread, move(msg), MessagePriority::High);
|
||||
|
|
|
@ -59,9 +59,9 @@ protected:
|
|||
unique_ptr<threads::IRoutine> 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> message) override;
|
||||
|
||||
|
|
|
@ -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<FrontendRenderer>(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>(ChangeMyPositionModeMessage::TYPE_NEXT, preferredZoomLevel),
|
||||
make_unique_dp<ChangeMyPositionModeMessage>(ChangeMyPositionModeMessage::SwitchNextMode),
|
||||
MessagePriority::High);
|
||||
}
|
||||
|
||||
void DrapeEngine::LoseLocation()
|
||||
{
|
||||
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
|
||||
make_unique_dp<ChangeMyPositionModeMessage>(ChangeMyPositionModeMessage::LoseLocation),
|
||||
MessagePriority::High);
|
||||
}
|
||||
|
||||
void DrapeEngine::StopLocationFollow()
|
||||
{
|
||||
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
|
||||
make_unique_dp<ChangeMyPositionModeMessage>(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>(ChangeMyPositionModeMessage::TYPE_CANCEL),
|
||||
MessagePriority::High);
|
||||
}
|
||||
|
||||
void DrapeEngine::StopLocationFollow()
|
||||
{
|
||||
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
|
||||
make_unique_dp<ChangeMyPositionModeMessage>(ChangeMyPositionModeMessage::TYPE_STOP_FOLLOW),
|
||||
MessagePriority::High);
|
||||
}
|
||||
|
||||
void DrapeEngine::InvalidateMyPosition()
|
||||
{
|
||||
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
|
||||
make_unique_dp<ChangeMyPositionModeMessage>(ChangeMyPositionModeMessage::TYPE_INVALIDATE),
|
||||
MessagePriority::High);
|
||||
}
|
||||
|
||||
void DrapeEngine::SetMyPositionModeListener(location::TMyPositionModeChanged const & fn)
|
||||
{
|
||||
m_myPositionModeChanged = fn;
|
||||
|
|
|
@ -42,7 +42,8 @@ public:
|
|||
pair<location::EMyPositionMode, bool> 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<dp::OGLContextFactory> 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);
|
||||
|
||||
|
|
|
@ -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> message)
|
|||
break;
|
||||
}
|
||||
|
||||
case Message::MyPositionShape:
|
||||
case Message::MapShapes:
|
||||
{
|
||||
ref_ptr<MyPositionShapeMessage> msg = message;
|
||||
ref_ptr<MapShapesMessage> msg = message;
|
||||
m_myPositionController->SetRenderShape(msg->AcceptShape());
|
||||
m_selectionShape = msg->AcceptSelection();
|
||||
}
|
||||
|
@ -369,17 +369,14 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
|
|||
ref_ptr<ChangeMyPositionModeMessage> 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<int>(msg->GetChangeType())));
|
||||
|
@ -476,7 +473,6 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> 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> message)
|
|||
{
|
||||
ref_ptr<FollowRouteMessage> 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<threads::IRoutine> 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<uint32_t>((kFrameTime - frameTime) * 1000);
|
||||
this_thread::sleep_for(milliseconds(ms));
|
||||
|
|
|
@ -80,7 +80,8 @@ public:
|
|||
location::EMyPositionMode initMode,
|
||||
ref_ptr<RequestedTiles> 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<RequestedTiles> m_requestedTiles;
|
||||
bool m_allow3dBuildings;
|
||||
bool m_blockTapEvents;
|
||||
bool m_firstLaunch;
|
||||
};
|
||||
|
||||
FrontendRenderer(Params const & params);
|
||||
|
|
|
@ -26,7 +26,7 @@ public:
|
|||
GuiLayerRecached,
|
||||
GuiRecache,
|
||||
GuiLayerLayout,
|
||||
MyPositionShape,
|
||||
MapShapes,
|
||||
ChangeMyPostitionMode,
|
||||
CompassInfo,
|
||||
GpsInfo,
|
||||
|
|
|
@ -343,15 +343,15 @@ private:
|
|||
bool const m_needBlock;
|
||||
};
|
||||
|
||||
class MyPositionShapeMessage : public Message
|
||||
class MapShapesMessage : public Message
|
||||
{
|
||||
public:
|
||||
MyPositionShapeMessage(drape_ptr<MyPosition> && shape, drape_ptr<SelectionShape> && selection)
|
||||
MapShapesMessage(drape_ptr<MyPosition> && shape, drape_ptr<SelectionShape> && 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<MyPosition> && AcceptShape() { return move(m_shape); }
|
||||
drape_ptr<SelectionShape> 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
|
||||
|
|
|
@ -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<MyPositionController::Listener> 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<MyPosition> && 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<dp::GpuProgramManager> 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<dp::GpuProgramManager> 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);
|
||||
}
|
||||
|
|
|
@ -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<BaseModelViewAnimation> anim);
|
||||
void ScaleStarted();
|
||||
void ScaleEnded();
|
||||
|
||||
void AnimationStarted(ref_ptr<BaseModelViewAnimation> 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<MyPosition> && 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<dp::GpuProgramManager> 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<MyPosition> 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<MyPositionAnim> m_anim;
|
||||
|
@ -162,6 +156,7 @@ private:
|
|||
TAnimationCreator m_animCreator;
|
||||
|
||||
bool m_isPositionAssigned;
|
||||
bool m_isDirectionAssigned;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:^
|
||||
{
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -277,8 +277,6 @@ using namespace osm_auth_ios;
|
|||
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:minimumBackgroundFetchIntervalInSeconds];
|
||||
[self startAdServerForbiddenCheckTimer];
|
||||
[self updateApplicationIconBadgeNumber];
|
||||
|
||||
GetFramework().InvalidateMyPosition();
|
||||
}
|
||||
|
||||
- (void)determineMapStyle
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
- (NSString *)formattedSpeedAndAltitude:(BOOL &)hasSpeed;
|
||||
|
||||
- (bool)lastLocationIsValid;
|
||||
- (bool)isLocationModeUnknownOrPending;
|
||||
- (bool)isLocationPendingOrNoPosition;
|
||||
- (BOOL)enabledOnMap;
|
||||
- (void)triggerCompass;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -149,7 +149,7 @@ pair<MwmSet::MwmId, MwmSet::RegResult> 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<dp::OGLContextFactory> 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<df::DrapeEngine>(move(p));
|
||||
AddViewportListener([this](ScreenBase const & screen)
|
||||
|
@ -1484,7 +1480,6 @@ void Framework::CreateDrapeEngine(ref_ptr<dp::OGLContextFactory> 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);
|
||||
|
|
|
@ -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<dp::OGLContextFactory> contextFactory, DrapeCreationParams && params);
|
||||
|
|
|
@ -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<void (location::EMyPositionMode)>;
|
||||
using TMyPositionModeChanged = function<void (location::EMyPositionMode, bool)>;
|
||||
|
||||
} // namespace location
|
||||
|
|
|
@ -392,28 +392,28 @@ string ToString<location::EMyPositionMode>(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<location::EMyPositionMode>(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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue