Compare commits

..

2 Commits

Author SHA1 Message Date
Konstantin Pastbin
0a0bacc02d WIP try 184
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2026-01-03 23:42:51 +07:00
Vraj Shah
3cc7a92fc9 [android] Adjust map buttons margins in route building
Signed-off-by: Vraj Shah <vrajshah006@gmail.com>
2026-01-03 17:47:06 +07:00
46 changed files with 2503 additions and 2959 deletions

View File

@@ -9,8 +9,7 @@ import static app.organicmaps.leftbutton.LeftButtonsHolder.BUTTON_HELP_CODE;
import static app.organicmaps.leftbutton.LeftButtonsHolder.BUTTON_RECORD_TRACK_CODE;
import static app.organicmaps.leftbutton.LeftButtonsHolder.BUTTON_SETTINGS_CODE;
import static app.organicmaps.sdk.location.LocationState.FOLLOW;
import static app.organicmaps.sdk.location.LocationState.FOLLOW_AND_ROTATE_COMPASS;
import static app.organicmaps.sdk.location.LocationState.FOLLOW_AND_ROTATE_ROUTE;
import static app.organicmaps.sdk.location.LocationState.FOLLOW_AND_ROTATE;
import static app.organicmaps.sdk.location.LocationState.LOCATION_TAG;
import static app.organicmaps.sdk.util.PowerManagment.POWER_MANAGEMENT_TAG;
import static app.organicmaps.sdk.util.Utils.dimen;
@@ -1901,8 +1900,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
locationHelper.restartWithNewMode();
if ((newMode == FOLLOW || newMode == FOLLOW_AND_ROTATE_ROUTE || newMode == FOLLOW_AND_ROTATE_COMPASS)
&& !LocationUtils.checkFineLocationPermission(this))
if ((newMode == FOLLOW || newMode == FOLLOW_AND_ROTATE) && !LocationUtils.checkFineLocationPermission(this))
{
// Try to optimistically request FINE permission for FOLLOW and FOLLOW_AND_ROTATE modes.
Logger.i(LOCATION_TAG, "Requesting ACCESS_FINE_LOCATION permission for " + LocationState.nameOf(newMode));

View File

@@ -183,16 +183,11 @@ public final class UiHelpers
drawableRes = R.drawable.ic_follow;
tintColor = Colors.LOCATION_TINT;
}
case LocationState.FOLLOW_AND_ROTATE_COMPASS ->
case LocationState.FOLLOW_AND_ROTATE ->
{
drawableRes = R.drawable.ic_follow_and_rotate;
tintColor = Colors.LOCATION_TINT;
}
case LocationState.FOLLOW_AND_ROTATE_ROUTE ->
{
drawableRes = R.drawable.ic_follow_route;
tintColor = Colors.LOCATION_TINT;
}
default -> throw new IllegalArgumentException("Invalid button mode: " + locationMode);
}

View File

@@ -49,8 +49,8 @@ public class MyPositionButton
int colorAttr = R.attr.iconTint;
@DimenRes
int sizeDimen = R.dimen.map_button_icon_size;
if (mode == LocationState.FOLLOW || mode == LocationState.FOLLOW_AND_ROTATE_ROUTE
|| mode == LocationState.FOLLOW_AND_ROTATE_COMPASS || mode == LocationState.PENDING_POSITION)
if (mode == LocationState.FOLLOW || mode == LocationState.FOLLOW_AND_ROTATE
|| mode == LocationState.PENDING_POSITION)
{
colorAttr = com.google.android.material.R.attr.colorSecondary;
if (mode == LocationState.PENDING_POSITION)
@@ -69,8 +69,7 @@ public class MyPositionButton
case LocationState.NOT_FOLLOW_NO_POSITION -> R.drawable.ic_location_off;
case LocationState.NOT_FOLLOW -> R.drawable.ic_location_crosshair;
case LocationState.FOLLOW -> R.drawable.ic_follow;
case LocationState.FOLLOW_AND_ROTATE_COMPASS -> R.drawable.ic_follow_and_rotate;
case LocationState.FOLLOW_AND_ROTATE_ROUTE -> R.drawable.ic_follow_route;
case LocationState.FOLLOW_AND_ROTATE -> R.drawable.ic_follow_and_rotate;
default -> throw new IllegalArgumentException("Invalid button mode: " + mode);
};
image = ResourcesCompat.getDrawable(resources, drawableRes, context.getTheme());

View File

@@ -1,30 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:strokeColor="@android:color/white"
android:fillColor="@android:color/white"
android:pathData="M15.15 16.92l-7.04 2.8v0.4l2.63 1.07 0.98 2.67h0.39z"/>
<path
android:strokeColor="@android:color/white"
android:strokeWidth="2"
android:strokeLineJoin="miter"
android:pathData="m 16.25,15.95 c 2.29,-2.29 1.91,-3.87 -4.06,-3.87"/>
<path
android:strokeColor="@android:color/white"
android:strokeWidth="2"
android:strokeLineJoin="miter"
android:pathData="M8.98 7.43c-2.97 2.96-2.72 4.66 3.24 4.66"/>
<path
android:strokeColor="@android:color/white"
android:strokeWidth="2"
android:strokeLineJoin="miter"
android:pathData="M8.89 7.51l8.83-8.79"/>
<path
android:strokeColor="@android:color/white"
android:strokeWidth="2"
android:strokeLineJoin="miter"
android:pathData="M9.2 22.83c-0.64 0.57-2.9 2.5-3.56 3.13"/>
</vector>

View File

@@ -27,8 +27,6 @@ import app.organicmaps.sdk.util.NetworkPolicy;
import app.organicmaps.sdk.util.log.Logger;
import org.chromium.base.ObserverList;
import java.util.HashMap;
public class LocationHelper implements BaseLocationProvider.Listener
{
private static final long INTERVAL_MS = 500;
@@ -58,12 +56,6 @@ public class LocationHelper implements BaseLocationProvider.Listener
private Handler mHandler;
private Runnable mLocationTimeoutRunnable = this::notifyLocationUpdateTimeout;
private static final double INTERVAL_PROVIDER_DECISION = 3.0; // seconds
private final HashMap<String, Integer> mProviderLocationCounts = new HashMap<>();
private final HashMap<String, Float> mProviderAccuracyMeans = new HashMap<>();
private double mTimeAtLastProviderChange = Double.NaN;
private String mCurrentProvider = null;
@NonNull
private final GnssStatusCompat.Callback mGnssStatusCallback = new GnssStatusCompat.Callback() {
@Override
@@ -195,6 +187,7 @@ public class LocationHelper implements BaseLocationProvider.Listener
@Override
public void onLocationChanged(@NonNull Location location)
{
Logger.d(TAG, "provider = " + mLocationProvider.getClass().getSimpleName() + " location = " + location);
if (!isActive())
{
@@ -208,59 +201,21 @@ public class LocationHelper implements BaseLocationProvider.Listener
return;
}
updateProviderDecision(location);
if(mCurrentProvider != null && !mCurrentProvider.equals(location.getProvider())) {
Logger.d(TAG, "REJECTED: provider = " + mLocationProvider.getClass().getSimpleName() + " location = " + location);
if (mSavedLocation != null)
{
if (!LocationUtils.isLocationBetterThanLast(location, mSavedLocation))
{
Logger.d(TAG, "The new " + location + " is worse than the last " + mSavedLocation);
return;
}
}
Logger.d(TAG, "provider = " + mLocationProvider.getClass().getSimpleName() + " location = " + location);
mSavedLocation = location;
mMyPosition = null;
notifyLocationUpdated();
}
private void updateProviderDecision(Location location) {
if(Double.isNaN(mTimeAtLastProviderChange))
mTimeAtLastProviderChange = location.getElapsedRealtimeNanos() * 1.0E-9;
String provider = location.getProvider();
int count = mProviderLocationCounts.getOrDefault(provider, 0);
float average = mProviderAccuracyMeans.getOrDefault(provider, 0.0f);
float accuracy = location.getAccuracy();
float newAverage = (count * average + accuracy) / (count + 1);
mProviderLocationCounts.put(provider, count + 1);
mProviderAccuracyMeans.put(provider, newAverage);
double currentTime = location.getElapsedRealtimeNanos();
double timeDiff = (currentTime - mTimeAtLastProviderChange) * 1.0E-9;
if(timeDiff > INTERVAL_PROVIDER_DECISION) {
mCurrentProvider = getMinAccuracyProvider();
Logger.d(TAG, "Selected: " + mCurrentProvider + ", with acc. " + mProviderAccuracyMeans.get(mCurrentProvider));
mTimeAtLastProviderChange = currentTime;
mProviderLocationCounts.clear();
mProviderAccuracyMeans.clear();
}
}
private String getMinAccuracyProvider() {
String minAccuracyProvider = null;
float minAccuracy = Float.MAX_VALUE;
for(String p : mProviderAccuracyMeans.keySet()) {
float pAccuracy = mProviderAccuracyMeans.get(p);
if(pAccuracy < minAccuracy) {
minAccuracy = pAccuracy;
minAccuracyProvider = p;
}
}
return minAccuracyProvider;
}
// Used by GoogleFusedLocationProvider.
// Used by GoogleFusedLocationProvider.
@SuppressWarnings("unused")
@Override
@UiThread

View File

@@ -20,8 +20,7 @@ public final class LocationState
}
@Retention(RetentionPolicy.SOURCE)
@IntDef({PENDING_POSITION, NOT_FOLLOW_NO_POSITION, NOT_FOLLOW, FOLLOW, FOLLOW_AND_ROTATE_COMPASS,
FOLLOW_AND_ROTATE_ROUTE})
@IntDef({PENDING_POSITION, NOT_FOLLOW_NO_POSITION, NOT_FOLLOW, FOLLOW, FOLLOW_AND_ROTATE})
@interface Value
{}
@@ -30,8 +29,7 @@ public final class LocationState
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 FOLLOW_AND_ROTATE_COMPASS = 4;
public static final int FOLLOW_AND_ROTATE_ROUTE = 5;
public static final int FOLLOW_AND_ROTATE = 4;
// These constants should correspond to values defined in platform/location.hpp
// Leave 0-value as no any error.
@@ -71,8 +69,7 @@ public final class LocationState
case NOT_FOLLOW_NO_POSITION -> "NOT_FOLLOW_NO_POSITION";
case NOT_FOLLOW -> "NOT_FOLLOW";
case FOLLOW -> "FOLLOW";
case FOLLOW_AND_ROTATE_COMPASS -> "FOLLOW_AND_ROTATE_COMPASS";
case FOLLOW_AND_ROTATE_ROUTE -> "FOLLOW_AND_ROTATE_ROUTE";
case FOLLOW_AND_ROTATE -> "FOLLOW_AND_ROTATE";
default -> "Unknown: " + mode;
};
}

View File

@@ -81,6 +81,20 @@ public class LocationUtils
return location.getAccuracy() > 0.0f;
}
public static boolean isLocationBetterThanLast(@NonNull Location newLocation, @NonNull Location lastLocation)
{
if (newLocation.getElapsedRealtimeNanos() < lastLocation.getElapsedRealtimeNanos())
return false;
// As described in isAccuracySatisfied, GPS may have zero accuracy "for some reasons".
if (isFromGpsProvider(lastLocation) && lastLocation.getAccuracy() == 0.0f)
return true;
double speed = Math.max(DEFAULT_SPEED_MPS, (newLocation.getSpeed() + lastLocation.getSpeed()) / 2.0);
double lastAccuracy = lastLocation.getAccuracy() + speed * LocationUtils.getTimeDiff(lastLocation, newLocation);
return newLocation.getAccuracy() < lastAccuracy;
}
public static boolean areLocationServicesTurnedOn(@NonNull Context context)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)

File diff suppressed because it is too large Load Diff

View File

@@ -1674,57 +1674,57 @@ CoMaps 的地理位置数据共享应该是启用的。</p>
<dd lang="en">
<p>Default battery optimization settings on Samsung, Huawei, Google, Xiaomi, OnePlus, Meizu, Asus, Wiko, Lenovo, Oppo, Vivo, Realme, Sony, Motorola, HTC and other devices may stop or kill CoMaps app in the background.</p>
<p>This is especially true for versions Android 11 and higher</p>
<p>The exact steps on how to make CoMaps (and other apps) work in the background are listed here: <a href="https://dontkillmyapp.com/">https://dontkillmyapp.com/</a></p>
<p>The exact steps on how to make CoMaps (and other apps) work in the background are listed here: https://dontkillmyapp.com/</p>
</dd>
<dd lang="ru">
<p>Настройки оптимизации батареи по умолчанию на устройствах Samsung, Huawei, Google, Xiaomi, OnePlus, Meizu, Asus, Wiko, Lenovo, Oppo, Vivo, Realme, Sony, Motorola, HTC и других могут остановить или закрыть приложение CoMaps в фоновом режиме.</p>
<p>Это особенно актуально для версий Android 11 и выше.</p>
<p>На этом сайте описано, как настроить работу в фоновом режиме для CoMaps и других приложений: <a href="https://dontkillmyapp.com/">https://dontkillmyapp.com/</a></p>
<p>На этом сайте описано, как настроить работу в фоновом режиме для CoMaps и других приложений: https://dontkillmyapp.com/</p>
</dd><dd lang="de">
<p>Die Standardeinstellungen zur Akkuoptimierung auf Samsung, Huawei, Google, Xiaomi, OnePlus, Meizu, Asus, Wiko, Lenovo, Oppo, Vivo, Realme, Sony, Motorola, HTC und anderen Geräten können die CoMaps-App im Hintergrund stoppen oder beenden.</p>
<p>Dies gilt insbesondere für Versionen Android 11 und höher</p>
<p>Die genauen Schritte, wie man CoMaps (und andere Apps) im Hintergrund zum Laufen bringt, sind hier aufgeführt: <a href="https://dontkillmyapp.com/">https://dontkillmyapp.com/</a></p>
<p>Die genauen Schritte, wie man CoMaps (und andere Apps) im Hintergrund zum Laufen bringt, sind hier aufgeführt: https://dontkillmyapp.com/</p>
</dd><dd lang="es">
<p>La configuración predeterminada de optimización de la batería en Samsung, Huawei, Google, Xiaomi, OnePlus, Meizu, Asus, Wiko, Lenovo, Oppo, Vivo, Realme, Sony, Motorola, HTC y otros dispositivos puede detener o cerrar la aplicación CoMaps en segundo plano.</p>
<p>Esto es especialmente cierto para las versiones de Android 11 y superior</p>
<p>Los pasos exactos sobre cómo hacer que CoMaps (y otras aplicaciones) funcionen en segundo plano se enumeran aquí (en inglés): <a href="https://dontkillmyapp.com/">https://dontkillmyapp.com/</a></p>
<p>Los pasos exactos sobre cómo hacer que CoMaps (y otras aplicaciones) funcionen en segundo plano se enumeran aquí (en inglés): https://dontkillmyapp.com/</p>
</dd><dd lang="fr">
<p>Les paramètres d'optimisation de la batterie par défaut sur Samsung, Huawei, Google, Xiaomi, OnePlus, Meizu, Asus, Wiko, Lenovo, Oppo, Vivo, Realme, Sony, Motorola, HTC et d'autres appareils peuvent arrêter ou tuer l'application CoMaps en arrière-plan.</p>
<p>Cela est particulièrement vrai pour les versions Android 11 et supérieures</p>
<p>Les étapes exactes pour faire fonctionner CoMaps (et d'autres applications) en arrière-plan sont listées ici : <a href="https://dontkillmyapp.com/">https://dontkillmyapp.com/</a></p>
<p>Les étapes exactes pour faire fonctionner CoMaps (et d'autres applications) en arrière-plan sont listées ici : https://dontkillmyapp.com/</p>
</dd><dd lang="pl">
<p>Domyślne ustawienia optymalizacji baterii na urządzeniach Samsung, Huawei, Google, Xiaomi, OnePlus, Meizu, Asus, Wiko, Lenovo, Oppo, Vivo, Realme, Sony, Motorola, HTC i innych, mogą zatrzymać aplikację CoMaps działającą w tle.</p>
<p>Dotyczy to szczególnie wersji Android 11 i wyższych</p>
<p>Dokładne kroki, jak sprawić, by CoMaps (i inne aplikacje) działały w tle, są wymienione tutaj: <a href="https://dontkillmyapp.com/">https://dontkillmyapp.com/</a></p>
<p>Dokładne kroki, jak sprawić, by CoMaps (i inne aplikacje) działały w tle, są wymienione tutaj: https://dontkillmyapp.com/</p>
</dd><dd lang="pt">
<p>As definições predefinidas de otimização da bateria na Samsung, Huawei, Google, Xiaomi, OnePlus, Meizu, Asus, Wiko, Lenovo, Oppo, Vivo, Realme, Sony, Motorola, HTC e outros dispositivos podem parar ou encerrar a aplicação CoMaps em segundo plano.</p>
<p>Isso é especialmente verdadeiro para as versões Android 11 e superior</p>
<p>Os passos exatos sobre como fazer com que o CoMaps (e outras aplicações) funcionem em segundo plano estão listados aqui: <a href="https://dontkillmyapp.com/">https://dontkillmyapp.com/</a></p>
<p>Os passos exatos sobre como fazer com que o CoMaps (e outras aplicações) funcionem em segundo plano estão listados aqui: https://dontkillmyapp.com/</p>
</dd><dd lang="pt-BR">
<p>As configurações padrão de otimização da bateria na Samsung, Huawei, Google, Xiaomi, OnePlus, Meizu, Asus, Wiko, Lenovo, Oppo, Vivo, Realme, Sony, Motorola, HTC e outros dispositivos podem interromper ou fechar o aplicativo CoMaps em segundo plano.</p>
<p>Isso é especialmente verdadeiro para as versões Android 11 e superiores</p>
<p>O passo-a-passo sobre como fazer o CoMaps (e outros aplicativos) funcionar em segundo plano pode ser encontrado aqui: <a href="https://dontkillmyapp.com/">https://dontkillmyapp.com/</a></p>
<p>O passo-a-passo sobre como fazer o CoMaps (e outros aplicativos) funcionar em segundo plano pode ser encontrado aqui: https://dontkillmyapp.com/</p>
</dd><dd lang="tr">
<p>Samsung, Huawei, Google, Xiaomi, OnePlus, Meizu, Asus, Wiko, Lenovo, Oppo, Vivo, Realme, Sony, Motorola, HTC ve diğer cihazlardaki varsayılan pil optimizasyon ayarları arka planda CoMaps uygulamasını durdurabilir veya öldürebilir.</p>
<p>Bu özellikle Android 11 ve üstü sürümler için geçerlidir</p>
<p>CoMaps'ın (ve diğer uygulamaların) arka planda nasıl çalışacağına ilişkin tam adımlar burada listelenmiştir: <a href="https://dontkillmyapp.com/">https://dontkillmyapp.com/</a></p>
<p>CoMaps'ın (ve diğer uygulamaların) arka planda nasıl çalışacağına ilişkin tam adımlar burada listelenmiştir: https://dontkillmyapp.com/</p>
</dd><dd lang="uk">
<p>Стандартні налаштування оптимізації роботи акумулятора на пристроях Samsung, Huawei, Google, Xiaomi, OnePlus, Meizu, Asus, Wiko, Lenovo, Oppo, Vivo, Realme, Sony, Motorola, HTC та інших пристроях можуть зупиняти або закривати додаток CoMaps у фоновому режимі.</p>
<p>Особливо це стосується версій Android 11 і вище</p>
<p>На цьому сайті описано, як налаштувати роботу у фоновому режимі для CoMaps та інших додатків: <a href="https://dontkillmyapp.com/">https://dontkillmyapp.com/</a></p>
<p>На цьому сайті описано, як налаштувати роботу у фоновому режимі для CoMaps та інших додатків: https://dontkillmyapp.com/</p>
</dd><dd lang="zh">
<p>三星、华为、谷歌、小米、OnePlus、美图、华硕、Wiko、联想、Oppo、Vivo、Realme、索尼、摩托罗拉、HTC 和其他设备上的默认电池优化设置可能会在后台停止或杀死CoMaps应用程序。</p>
<p>对于 Android 11 及更高版本来说尤其如此</p>
<p>如何让CoMaps和其他应用程序在后台工作的具体步骤在此列出<a href="https://dontkillmyapp.com/">https://dontkillmyapp.com/</a></p>
<p>如何让CoMaps和其他应用程序在后台工作的具体步骤在此列出https://dontkillmyapp.com/</p>
</dd>
</dl>

View File

@@ -1,108 +0,0 @@
{
"make_a_slight_right_turn":"லேசாக வலதுபுறம் திரும்புங்கள்.",
"make_a_slight_right_turn_street":"NULL",
"make_a_slight_right_turn_street_verb":"NULL",
"make_a_right_turn":"வலதுபுறமாக திரும்புங்கள்.",
"make_a_right_turn_street":"NULL",
"make_a_sharp_right_turn":"கூர்மையாக வலதுபுறம் திரும்புங்கள்.",
"make_a_sharp_right_turn_street":"NULL",
"enter_the_roundabout":"ரவுண்டபௌட்டை நுழையுங்கள்.",
"enter_the_roundabout_street":"NULL",
"enter_the_roundabout_street_verb":"NULL",
"leave_the_roundabout":"ரவுண்டபௌட்டை வெளியேறுங்கள்.",
"leave_the_roundabout_street":"NULL",
"leave_the_roundabout_street_verb":"NULL",
"make_a_slight_left_turn":"லேசாக இடதுபுறம் திரும்புங்கள்.",
"make_a_slight_left_turn_street":"NULL",
"make_a_slight_left_turn_street_verb":"NULL",
"make_a_left_turn":"இடதுபுறமாக திரும்புங்கள்.",
"make_a_left_turn_street":"NULL",
"make_a_sharp_left_turn":"கூர்மையாக இடதுபுறம் திரும்புங்கள்.",
"make_a_sharp_left_turn_street":"NULL",
"make_a_u_turn":"U-வழியில் திரும்புங்கள்.",
"make_a_u_turn_street":"NULL",
"make_a_u_turn_street_verb":"NULL",
"go_straight":"நேரா போங்க.",
"exit":"வெளியேறுங்கள்.",
"onto":"நோக்கி",
"take_exit_number":"வெளியேறும் வழி எடுங்கள்",
"take_exit_number_street_verb":"NULL",
"route_recalculating":"வழி மறுபடி கணிக்கிறது",
"destination":"நீங்கள் வருவீர்கள்.",
"you_have_reached_the_destination":"நீங்கள் வந்துவிட்டீர்கள்..",
"in_50_meters":"ஐம்பது மீட்டரில்",
"in_100_meters":"நூறு மீட்டரில்",
"in_200_meters":"இருநூறு மீட்டரில்",
"in_250_meters":"இருநூற்று ஐம்பது மீட்டரில்",
"in_300_meters":"முன்னூறு மீட்டரில்",
"in_400_meters":"நானூறு மீட்டரில்",
"in_500_meters":"ஐநூறு மீட்டரில்",
"in_600_meters":"அறுநூறு மீட்டரில்",
"in_700_meters":"எழுநூறு மீட்டரில்",
"in_750_meters":"எழுநூறு ஐம்பது மீட்டரில்",
"in_800_meters":"எண்ணூறு மீட்டரில்",
"in_900_meters":"தொள்ளாயிரம் மீட்டரில்",
"in_1_kilometer":"ஒரு கிலோமீட்டரில்",
"in_1_5_kilometers":"ஒன்றரை கிலோமீட்டரில்",
"in_2_kilometers":"இரண்டு கிலோமீட்டரில்",
"in_2_5_kilometers":"இரண்டரை கிலோமீட்டரில்",
"in_3_kilometers":"மூன்று கிலோமீட்டரில்",
"then":"அடுத்தது",
"dist_direction_onto_street":"%1$s %4$s %3$s %5$s %2$s",
"take_the_1_exit":"ஒன்றாம் வெளியேறும் வழி எடுங்கள்.",
"take_the_1_exit_street":"NULL",
"take_the_1_exit_street_verb":"NULL",
"take_the_2_exit":"இரண்டாம் வெளியேறும் வழி எடுங்கள்.",
"take_the_2_exit_street":"NULL",
"take_the_2_exit_street_verb":"NULL",
"take_the_3_exit":"மூன்றாம் வெளியேறும் வழி எடுங்கள்.",
"take_the_3_exit_street":"NULL",
"take_the_3_exit_street_verb":"NULL",
"take_the_4_exit":"நான்காவது வெளியேறும் வழி எடுங்கள்.",
"take_the_4_exit_street":"NULL",
"take_the_4_exit_street_verb":"NULL",
"take_the_5_exit":"ஐந்தாவது வெளியேறும் வழி எடுங்கள்.",
"take_the_5_exit_street":"NULL",
"take_the_5_exit_street_verb":"NULL",
"take_the_6_exit":"ஆறாவது வெளியேறும் வழி எடுங்கள்.",
"take_the_6_exit_street":"NULL",
"take_the_6_exit_street_verb":"NULL",
"take_the_7_exit":"ஏழாவது வெளியேறும் வழி எடுங்கள்.",
"take_the_7_exit_street":"NULL",
"take_the_7_exit_street_verb":"NULL",
"take_the_8_exit":"எட்டாவது வெளியேறும் வழி எடுங்கள்.",
"take_the_8_exit_street":"NULL",
"take_the_8_exit_street_verb":"NULL",
"take_the_9_exit":"ஒன்பதாவது வெளியேறும் வழி எடுங்கள்.",
"take_the_9_exit_street":"NULL",
"take_the_9_exit_street_verb":"NULL",
"take_the_10_exit":"பத்தாவது வெளியேறும் வழி எடுங்கள்.",
"take_the_10_exit_street":"NULL",
"take_the_10_exit_street_verb":"NULL",
"take_the_11_exit":"பதினொன்றாவது வெளியேறும் வழி எடுங்கள்.",
"take_the_11_exit_street":"NULL",
"take_the_11_exit_street_verb":"NULL",
"in_50_feet":"ஐம்பது அடியில்",
"in_100_feet":"நூறு அடியில்",
"in_200_feet":"இருநூறு அடியில்",
"in_300_feet":"முன்னூறு அடியில்",
"in_400_feet":"நானூறு அடியில்",
"in_500_feet":"ஐநூறு அடியில்",
"in_600_feet":"அறுநூறு அடியில்",
"in_700_feet":"எழுநூறு அடியில்",
"in_800_feet":"எண்ணூறு அடியில்",
"in_900_feet":"தொள்ளாயிரம் அடியில்",
"in_1000_feet":"ஆயிரம் அடியில்",
"in_1500_feet":"ஆயிரம் ஐநூறு அடியில்",
"in_2000_feet":"இரண்டு ஆயிரம் அடியில்",
"in_2500_feet":"இரண்டு ஆயிரம் ஐநூறு அடியில்",
"in_3000_feet":"மூன்று ஆயிரம் அடியில்",
"in_3500_feet":"மூன்று ஆயிரம் ஐநூறு அடியில்",
"in_4000_feet":"நான்கு ஆயிரம் அடியில்",
"in_4500_feet":"நான்கு ஆயிரம் ஐநூறு அடியில்",
"in_5000_feet":"ஐந்து ஆயிரம் அடியில்",
"in_1_mile":"ஒன்று மைலில்",
"in_1_5_miles":"ஒன்றரை மைலில்",
"in_2_miles":"இரண்டு மைலில்",
"unknown_camera":"கேமரா முன்னால் இருக்கிறது"
}

View File

@@ -239,7 +239,7 @@ final class CarPlayService: NSObject {
MapTemplateBuilder.configureBaseUI(mapTemplate: mapTemplate)
if currentPositionMode == .pendingPosition {
mapTemplate.leadingNavigationBarButtons = []
} else if currentPositionMode == .follow || currentPositionMode == .followAndRotateCompass || currentPositionMode == .followAndRotateRoute {
} else if currentPositionMode == .follow || currentPositionMode == .followAndRotate {
MapTemplateBuilder.setupDestinationButton(mapTemplate: mapTemplate)
} else {
MapTemplateBuilder.setupRecenterButton(mapTemplate: mapTemplate)
@@ -623,32 +623,22 @@ extension CarPlayService: CarPlayRouterListener {
extension CarPlayService: LocationModeListener {
func processMyPositionStateModeEvent(_ mode: MWMMyPositionMode) {
currentPositionMode = mode
// make sure we have a rootMapTemplate
guard let rootMapTemplate = rootMapTemplate else {
return
}
// exit if we're navigating
guard let info = rootMapTemplate.userInfo as? MapInfo,
info.type == CPConstants.TemplateType.main else {
MapTemplateBuilder.updateMyPositionModeButton(mapTemplate: rootMapTemplate, newMode: mode)
guard let rootMapTemplate = rootMapTemplate,
let info = rootMapTemplate.userInfo as? MapInfo,
info.type == CPConstants.TemplateType.main else {
return
}
switch mode {
case .follow, .followAndRotateCompass, .followAndRotateRoute:
case .follow, .followAndRotate:
if !rootMapTemplate.isPanningInterfaceVisible {
MapTemplateBuilder.setupDestinationButton(mapTemplate: rootMapTemplate)
MapTemplateBuilder.updateMyPositionModeButton(mapTemplate: rootMapTemplate, newMode: mode)
}
case .notFollow:
if !rootMapTemplate.isPanningInterfaceVisible {
MapTemplateBuilder.setupRecenterButton(mapTemplate: rootMapTemplate)
MapTemplateBuilder.updateMyPositionModeButton(mapTemplate: rootMapTemplate, newMode: mode)
}
case .pendingPosition, .notFollowNoPosition:
rootMapTemplate.leadingNavigationBarButtons = []
MapTemplateBuilder.updateMyPositionModeButton(mapTemplate: rootMapTemplate, newMode: mode)
}
}
}

View File

@@ -5,7 +5,6 @@ final class MapTemplateBuilder {
case startPanning
case zoomIn
case zoomOut
case myPositionMode
}
enum BarButtonType {
case dismissPaning
@@ -29,7 +28,7 @@ final class MapTemplateBuilder {
configureBaseUI(mapTemplate: mapTemplate)
if positionMode == .pendingPosition {
mapTemplate.leadingNavigationBarButtons = []
} else if positionMode == .follow || positionMode == .followAndRotateCompass || positionMode == .followAndRotateRoute {
} else if positionMode == .follow || positionMode == .followAndRotate {
setupDestinationButton(mapTemplate: mapTemplate)
} else {
setupRecenterButton(mapTemplate: mapTemplate)
@@ -70,10 +69,7 @@ final class MapTemplateBuilder {
let zoomOutButton = buildMapButton(type: .zoomOut) { _ in
FrameworkHelper.zoomMap(.out)
}
let myPositionModeButton = buildMapButton(type: .myPositionMode) { _ in
FrameworkHelper.switchMyPositionMode()
}
mapTemplate.mapButtons = [myPositionModeButton, panningButton, zoomInButton, zoomOutButton]
mapTemplate.mapButtons = [panningButton, zoomInButton, zoomOutButton]
let settingsButton = buildBarButton(type: .settings) { _ in
let gridTemplate = SettingsTemplateBuilder.buildGridTemplate()
@@ -103,10 +99,7 @@ final class MapTemplateBuilder {
let panningButton = buildMapButton(type: .startPanning) { _ in
mapTemplate.showPanningInterface(animated: true)
}
let myPositionModeButton = buildMapButton(type: .myPositionMode) { _ in
FrameworkHelper.switchMyPositionMode()
}
mapTemplate.mapButtons = [myPositionModeButton, panningButton]
mapTemplate.mapButtons = [panningButton]
setupMuteAndRedirectButtons(template: mapTemplate)
let endButton = buildBarButton(type: .endRoute) { _ in
CarPlayService.shared.cancelCurrentTrip()
@@ -124,28 +117,6 @@ final class MapTemplateBuilder {
mapTemplate.leadingNavigationBarButtons = [destinationButton]
}
class func updateMyPositionModeButton(mapTemplate: CPMapTemplate, newMode: MWMMyPositionMode) {
let button = CPMapButton(handler: { _ in
FrameworkHelper.switchMyPositionMode()
})
switch newMode {
case .pendingPosition:
button.image = UIImage(systemName: "location.fill")
case .notFollowNoPosition:
button.image = UIImage(systemName: "location")
case .notFollow:
button.image = UIImage(systemName: "location")
case .follow:
button.image = UIImage(systemName: "location.fill")
case .followAndRotate:
button.image = UIImage(systemName: "location.north.line.fill")
}
if mapTemplate.mapButtons.count > 0 {
mapTemplate.mapButtons[0] = button
}
}
class func setupRecenterButton(mapTemplate: CPMapTemplate) {
let recenterButton = buildBarButton(type: .recenter) { _ in
FrameworkHelper.switchMyPositionMode()
@@ -195,8 +166,6 @@ final class MapTemplateBuilder {
button.image = UIImage(systemName: "plus")
case .zoomOut:
button.image = UIImage(systemName: "minus")
case .myPositionMode:
button.image = UIImage(systemName: "location")
}
// Remove code below once Apple has fixed its issue with the button background
if #unavailable(iOS 26) {
@@ -207,8 +176,6 @@ final class MapTemplateBuilder {
button.focusedImage = UIImage(systemName: "plus.circle.fill")
case .zoomOut:
button.focusedImage = UIImage(systemName: "minus.circle.fill")
case .myPositionMode:
button.image = UIImage(systemName: "location.fill")
}
}
return button

View File

@@ -91,8 +91,7 @@ NSString * const kUDDidShowLongTapToShowSideButtonsToast = @"kUDDidShowLongTapTo
case MWMMyPositionModeNotFollow:
case MWMMyPositionModeNotFollowNoPosition: [locBtn setStyleNameAndApply: @"ButtonGetPosition"]; break;
case MWMMyPositionModeFollow: [locBtn setStyleNameAndApply: @"ButtonFollow"]; break;
case MWMMyPositionModeFollowAndRotateCompass: [locBtn setStyleNameAndApply: @"ButtonFollowAndRotateCompass"]; break;
case MWMMyPositionModeFollowAndRotateRoute: [locBtn setStyleNameAndApply: @"ButtonFollowAndRotateRoute"]; break;
case MWMMyPositionModeFollowAndRotate: [locBtn setStyleNameAndApply: @"ButtonFollowAndRotate"]; break;
}
}

View File

@@ -632,8 +632,7 @@ NSString *const kAboutSegue = @"Map2About";
case MWMMyPositionModeNotFollow:
break;
case MWMMyPositionModeFollow:
case MWMMyPositionModeFollowAndRotateCompass:
case MWMMyPositionModeFollowAndRotateRoute:
case MWMMyPositionModeFollowAndRotate:
self.disableStandbyOnLocationStateMode = YES;
break;
}

View File

@@ -32,8 +32,7 @@ static inline MWMMyPositionMode mwmMyPositionMode(location::EMyPositionMode mode
case location::EMyPositionMode::NotFollowNoPosition: return MWMMyPositionModeNotFollowNoPosition;
case location::EMyPositionMode::NotFollow: return MWMMyPositionModeNotFollow;
case location::EMyPositionMode::Follow: return MWMMyPositionModeFollow;
case location::EMyPositionMode::FollowAndRotateCompass: return MWMMyPositionModeFollowAndRotateCompass;
case location::EMyPositionMode::FollowAndRotateRoute: return MWMMyPositionModeFollowAndRotateRoute;
case location::EMyPositionMode::FollowAndRotate: return MWMMyPositionModeFollowAndRotate;
}
}
} // namespace location_helpers

View File

@@ -50,8 +50,7 @@ std::string DebugPrint(MWMMyPositionMode mode) {
case MWMMyPositionModeNotFollowNoPosition: return "MWMMyPositionModeNotFollowNoPosition";
case MWMMyPositionModeNotFollow: return "MWMMyPositionModeNotFollow";
case MWMMyPositionModeFollow: return "MWMMyPositionModeFollow";
case MWMMyPositionModeFollowAndRotateCompass: return "MWMMyPositionModeFollowAndRotateCompass";
case MWMMyPositionModeFollowAndRotateRoute: return "MWMMyPositionModeFollowAndRotateRoute";
case MWMMyPositionModeFollowAndRotate: return "MWMMyPositionModeFollowAndRotate";
}
CHECK(false, ("Unsupported value", static_cast<int>(mode)));
}
@@ -368,8 +367,7 @@ void setShowLocationAlert(BOOL needShow) {
case MWMMyPositionModeNotFollowNoPosition:
case MWMMyPositionModeNotFollow: manager.geoMode = GeoMode::NotInPosition; break;
case MWMMyPositionModeFollow: manager.geoMode = GeoMode::InPosition; break;
case MWMMyPositionModeFollowAndRotateCompass:
case MWMMyPositionModeFollowAndRotateRoute: manager.geoMode = GeoMode::FollowAndRotate; break;
case MWMMyPositionModeFollowAndRotate: manager.geoMode = GeoMode::FollowAndRotate; break;
}
}
}

View File

@@ -30,7 +30,7 @@ NSUInteger constexpr kMaxPredictionCount = 20;
- (void)setMyPositionMode:(MWMMyPositionMode)mode
{
self.isLastPositionModeValid = (mode == MWMMyPositionModeFollowAndRotateCompass);
self.isLastPositionModeValid = (mode == MWMMyPositionModeFollowAndRotate);
[self restart];
}

View File

@@ -3,6 +3,5 @@ typedef NS_CLOSED_ENUM(NSUInteger, MWMMyPositionMode) {
MWMMyPositionModeNotFollowNoPosition,
MWMMyPositionModeNotFollow,
MWMMyPositionModeFollow,
MWMMyPositionModeFollowAndRotateCompass,
MWMMyPositionModeFollowAndRotateRoute
MWMMyPositionModeFollowAndRotate
};

View File

@@ -41,14 +41,13 @@ final class ThemeManager: NSObject {
}
}(actualTheme)
let isCarPlayActive = CarPlayService.shared.isCarplayActivated
if !isCarPlayActive, Settings.mapAppearance == .light {
if Settings.mapAppearance == .light {
if actualTheme == .vehicleDay || actualTheme == .vehicleNight {
FrameworkHelper.setTheme(.vehicleDay)
} else {
FrameworkHelper.setTheme(.day)
}
} else if !isCarPlayActive, Settings.mapAppearance == .dark {
} else if Settings.mapAppearance == .dark {
if actualTheme == .vehicleDay || actualTheme == .vehicleNight {
FrameworkHelper.setTheme(.vehicleNight)
} else {

View File

@@ -7,8 +7,7 @@ enum MapStyleSheet: String, CaseIterable {
case mapButtonPending = "ButtonPending"
case mapButtonGetPosition = "ButtonGetPosition"
case mapButtonFollow = "ButtonFollow"
case mapButtonFollowAndRotateCompass = "ButtonFollowAndRotateCompass"
case mapButtonFollowAndRotateRoute = "ButtonFollowAndRotateRoute"
case mapButtonFollowAndRotate = "ButtonFollowAndRotate"
case mapButtonMapBookmarks = "ButtonMapBookmarks"
case mapPromoDiscoveryButton = "PromoDiscroveryButton"
case mapButtonBookmarksBack = "ButtonBookmarksBack"
@@ -68,14 +67,10 @@ extension MapStyleSheet: IStyleSheet {
return .add { s in
s.mwmImage = "btn_follow"
}
case .mapButtonFollowAndRotateCompass:
case .mapButtonFollowAndRotate:
return .add { s in
s.mwmImage = "btn_follow_and_rotate"
}
case .mapButtonFollowAndRotateRoute:
return .add { s in
s.mwmImage = "btn_follow_route"
}
case .mapButtonMapBookmarks:
return .add { s in
s.mwmImage = "ic_routing_bookmark"

View File

@@ -1,6 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
"version" : 1,
"author" : "xcode"
}
}
}

View File

@@ -1,21 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "btn_follow_route_dark.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,21 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "btn_follow_route_highlighted_dark.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,21 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "btn_follow_route_highlighted_light.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,21 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "btn_follow_route_light.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -186,7 +186,7 @@ import AVFoundation
return mapAppearance
}
return .light
return .auto
}
set {
UserDefaults.standard.set(newValue.rawValue, forKey: userDefaultsKeyMapAppearance)

View File

@@ -9,7 +9,6 @@
#include "drape/support_manager.hpp"
#include "platform/settings.hpp"
#include "routing/base/followed_polyline.hpp"
#include <unordered_map>
@@ -41,7 +40,7 @@ DrapeEngine::DrapeEngine(Params && params)
using namespace location;
EMyPositionMode mode = PendingPosition;
if (settings::Get(kLocationStateMode, mode) && mode == FollowAndRotateCompass)
if (settings::Get(kLocationStateMode, mode) && mode == 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.
@@ -442,12 +441,13 @@ void DrapeEngine::SetCompassInfo(location::CompassInfo const & info)
MessagePriority::Normal);
}
void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, df::NavigationContext const & navigationContext,
void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
location::RouteMatchingInfo const & routeInfo)
{
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<GpsInfoMessage>(info, navigationContext, routeInfo),
MessagePriority::Normal);
m_threadCommutator->PostMessage(
ThreadsCommutator::RenderThread,
make_unique_dp<GpsInfoMessage>(info, isNavigable, distToNextTurn, speedLimit, routeInfo),
MessagePriority::Normal);
}
void DrapeEngine::SwitchMyPositionNextMode()
@@ -474,13 +474,12 @@ void DrapeEngine::StopLocationFollow()
MessagePriority::Normal);
}
void DrapeEngine::FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, bool enableAutoZoom, bool isArrowGlued,
bool allowRouteRotation)
void DrapeEngine::FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, bool enableAutoZoom, bool isArrowGlued)
{
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<FollowRouteMessage>(preferredZoomLevel, preferredZoomLevel3d,
enableAutoZoom, isArrowGlued, allowRouteRotation),
MessagePriority::Normal);
m_threadCommutator->PostMessage(
ThreadsCommutator::RenderThread,
make_unique_dp<FollowRouteMessage>(preferredZoomLevel, preferredZoomLevel3d, enableAutoZoom, isArrowGlued),
MessagePriority::Normal);
}
void DrapeEngine::SetModelViewListener(ModelViewChangedHandler && fn)

View File

@@ -1,7 +1,5 @@
#pragma once
#include "drape_frontend/my_position_controller.hpp"
#include "routing/base/followed_polyline.hpp"
#include "traffic/traffic_info.hpp"
#include "drape_frontend/backend_renderer.hpp"
@@ -156,7 +154,7 @@ public:
void UpdateMapStyle();
void SetCompassInfo(location::CompassInfo const & info);
void SetGpsInfo(location::GpsInfo const & info, df::NavigationContext const & navigationContext,
void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
location::RouteMatchingInfo const & routeInfo);
void SwitchMyPositionNextMode();
void LoseLocation();
@@ -173,8 +171,7 @@ public:
dp::DrapeID AddSubroute(SubrouteConstPtr subroute);
void RemoveSubroute(dp::DrapeID subrouteId, bool deactivateFollowing);
void FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, bool enableAutoZoom, bool isArrowGlued,
bool allowRouteRotation);
void FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, bool enableAutoZoom, bool isArrowGlued);
void DeactivateRouteFollowing();
void SetSubrouteVisibility(dp::DrapeID subrouteId, bool isVisible);
dp::DrapeID AddRoutePreviewSegment(m2::PointD const & startPt, m2::PointD const & finishPt);

View File

@@ -438,8 +438,8 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
#endif
ref_ptr<GpsInfoMessage> msg = message;
m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->GetNavigationContext(),
m_userEventStream.GetCurrentScreen());
m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), msg->GetDistanceToNextTurn(),
msg->GetSpeedLimit(), m_userEventStream.GetCurrentScreen());
location::RouteMatchingInfo const & info = msg->GetRouteInfo();
if (info.HasDistanceFromBegin())
@@ -512,8 +512,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
if (m_pendingFollowRoute != nullptr)
{
FollowRoute(m_pendingFollowRoute->m_preferredZoomLevel, m_pendingFollowRoute->m_preferredZoomLevelIn3d,
m_pendingFollowRoute->m_enableAutoZoom, m_pendingFollowRoute->m_isArrowGlued,
m_pendingFollowRoute->m_allowRouteRotation);
m_pendingFollowRoute->m_enableAutoZoom, m_pendingFollowRoute->m_isArrowGlued);
m_pendingFollowRoute.reset();
}
break;
@@ -585,14 +584,13 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
// receive FollowRoute message before FlushSubroute message, so we need to postpone its processing.
if (m_routeRenderer->GetSubroutes().empty())
{
m_pendingFollowRoute =
std::make_unique<FollowRouteData>(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d(),
msg->EnableAutoZoom(), msg->IsArrowGlued(), msg->AllowRouteRotation());
m_pendingFollowRoute = std::make_unique<FollowRouteData>(
msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d(), msg->EnableAutoZoom(), msg->IsArrowGlued());
}
else
{
FollowRoute(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d(), msg->EnableAutoZoom(),
msg->IsArrowGlued(), msg->AllowRouteRotation());
msg->IsArrowGlued());
}
break;
}
@@ -1059,11 +1057,10 @@ void FrontendRenderer::UpdateContextDependentResources()
}
void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom,
bool isArrowGlued, bool allowRouteRotation)
bool isArrowGlued)
{
m_myPositionController->ActivateRouting(
!m_enablePerspectiveInNavigation ? preferredZoomLevel : preferredZoomLevelIn3d, enableAutoZoom, isArrowGlued,
allowRouteRotation);
!m_enablePerspectiveInNavigation ? preferredZoomLevel : preferredZoomLevelIn3d, enableAutoZoom, isArrowGlued);
if (m_enablePerspectiveInNavigation)
AddUserEvent(make_unique_dp<SetAutoPerspectiveEvent>(true /* isAutoPerspective */));

View File

@@ -261,8 +261,7 @@ private:
using TRenderGroupRemovePredicate = std::function<bool(drape_ptr<RenderGroup> const &)>;
void RemoveRenderGroupsLater(TRenderGroupRemovePredicate const & predicate);
void FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom, bool isArrowGlued,
bool allowRouteRotation);
void FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom, bool isArrowGlued);
bool CheckRouteRecaching(ref_ptr<BaseSubrouteData> subrouteData);
@@ -373,20 +372,17 @@ private:
struct FollowRouteData
{
FollowRouteData(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom, bool isArrowGlued,
bool allowRouteRotation)
FollowRouteData(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom, bool isArrowGlued)
: m_preferredZoomLevel(preferredZoomLevel)
, m_preferredZoomLevelIn3d(preferredZoomLevelIn3d)
, m_enableAutoZoom(enableAutoZoom)
, m_isArrowGlued(isArrowGlued)
, m_allowRouteRotation(allowRouteRotation)
{}
int m_preferredZoomLevel;
int m_preferredZoomLevelIn3d;
bool m_enableAutoZoom;
bool m_isArrowGlued;
bool m_allowRouteRotation;
};
std::unique_ptr<FollowRouteData> m_pendingFollowRoute;

View File

@@ -10,7 +10,6 @@
#include "drape_frontend/gui/skin.hpp"
#include "drape_frontend/message.hpp"
#include "drape_frontend/my_position.hpp"
#include "drape_frontend/my_position_controller.hpp"
#include "drape_frontend/overlay_batcher.hpp"
#include "drape_frontend/postprocess_renderer.hpp"
#include "drape_frontend/render_node.hpp"
@@ -30,7 +29,6 @@
#include "geometry/rect2d.hpp"
#include "geometry/triangle2d.hpp"
#include "routing/base/followed_polyline.hpp"
#include <condition_variable>
#include <functional>
@@ -477,22 +475,28 @@ private:
class GpsInfoMessage : public Message
{
public:
GpsInfoMessage(location::GpsInfo const & info, df::NavigationContext const & navigationContext,
GpsInfoMessage(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
location::RouteMatchingInfo const & routeInfo)
: m_info(info)
, m_navigationContext(navigationContext)
, m_isNavigable(isNavigable)
, m_distToNextTurn(distToNextTurn)
, m_speedLimit(speedLimit)
, m_routeInfo(routeInfo)
{}
Type GetType() const override { return Type::GpsInfo; }
location::GpsInfo const & GetInfo() const { return m_info; }
df::NavigationContext const & GetNavigationContext() const { return m_navigationContext; }
bool IsNavigable() const { return m_isNavigable; }
double const & GetSpeedLimit() const { return m_speedLimit; }
double const & GetDistanceToNextTurn() const { return m_distToNextTurn; }
location::RouteMatchingInfo const & GetRouteInfo() const { return m_routeInfo; }
private:
location::GpsInfo const m_info;
df::NavigationContext const m_navigationContext;
bool const m_isNavigable;
double const m_distToNextTurn;
double const m_speedLimit;
location::RouteMatchingInfo const m_routeInfo;
};
@@ -736,13 +740,11 @@ public:
class FollowRouteMessage : public Message
{
public:
FollowRouteMessage(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom, bool isArrowGlued,
bool allowRouteRotation)
FollowRouteMessage(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom, bool isArrowGlued)
: m_preferredZoomLevel(preferredZoomLevel)
, m_preferredZoomLevelIn3d(preferredZoomLevelIn3d)
, m_enableAutoZoom(enableAutoZoom)
, m_isArrowGlued(isArrowGlued)
, m_allowRouteRotation(allowRouteRotation)
{}
Type GetType() const override { return Type::FollowRoute; }
@@ -751,14 +753,12 @@ public:
int GetPreferredZoomLevelIn3d() const { return m_preferredZoomLevelIn3d; }
bool EnableAutoZoom() const { return m_enableAutoZoom; }
bool IsArrowGlued() const { return m_isArrowGlued; }
bool AllowRouteRotation() const { return m_allowRouteRotation; }
private:
int const m_preferredZoomLevel;
int const m_preferredZoomLevelIn3d;
bool const m_enableAutoZoom;
bool const m_isArrowGlued;
bool const m_allowRouteRotation;
};
class SwitchMapStyleMessage : public BaseBlockingMessage

View File

@@ -9,11 +9,9 @@
#include "geometry/mercator.hpp"
#include "platform/location.hpp"
#include "platform/measurement_utils.hpp"
#include "base/math.hpp"
#include "routing/base/followed_polyline.hpp"
#include <algorithm>
#include <array>
@@ -33,9 +31,6 @@ double constexpr kMaxTimeInBackgroundSec = 60.0 * 60 * 30; // 30 hours before s
double constexpr kMaxNotFollowRoutingTimeSec = 20.0;
double constexpr kMaxUpdateLocationInvervalSec = 30.0;
double constexpr kMaxBlockAutoZoomTimeSec = 10.0;
double constexpr kDefaultSpeedLimitKmpH = 50.0;
double constexpr kLookaheadTimeSpeedRatio = 0.3;
double constexpr kMaxLookaheadTimeSec = 25.0;
int constexpr kZoomThreshold = 10;
int constexpr kMaxScaleZoomLevel = 16;
@@ -71,6 +66,7 @@ double CalculateZoomByMaxSpeed(double speedMpS, bool isPerspectiveAllowed)
std::array<TSpeedScale, 2> const & scales = isPerspectiveAllowed ? scales3d : scales2d;
double constexpr kDefaultSpeedLimitKmpH = 50.0;
double const speedKmpH = speedMpS > 0 ? measurement_utils::MpsToKmph(speedMpS) : kDefaultSpeedLimitKmpH;
size_t i = 0;
@@ -147,7 +143,7 @@ void ResetNotification(uint64_t & notifyId)
bool IsModeChangeViewport(location::EMyPositionMode mode)
{
return mode == location::Follow || mode == location::FollowAndRotateCompass || mode == location::FollowAndRotateRoute;
return mode == location::Follow || mode == location::FollowAndRotate;
}
} // namespace
@@ -161,11 +157,9 @@ MyPositionController::MyPositionController(Params && params, ref_ptr<DrapeNotifi
, m_errorRadius(0.0)
, m_horizontalAccuracy(0.0)
, m_position(m2::PointD::Zero())
, m_direction(0.0)
, m_routeDirection(0.0)
, m_arrowDirection(0.0)
, m_drawDirection(0.0)
, m_oldPosition(m2::PointD::Zero())
, m_oldArrowDirection(0.0)
, m_oldDrawDirection(0.0)
, m_enablePerspectiveInRouting(false)
, m_enableAutoZoomInRouting(params.m_isAutozoomEnabled)
, m_autoScale2d(GetScreenScale(kDefaultAutoZoom))
@@ -177,8 +171,7 @@ MyPositionController::MyPositionController(Params && params, ref_ptr<DrapeNotifi
, m_isDirtyAutoZoom(false)
, m_isPendingAnimation(false)
, m_isPositionAssigned(false)
, m_isArrowDirectionAssigned(false)
, m_isRouteDirectionAssigned(false)
, m_isDirectionAssigned(false)
, m_isCompassAvailable(false)
, m_positionIsObsolete(false)
, m_needBlockAutoZoom(false)
@@ -297,7 +290,7 @@ void MyPositionController::ScaleEnded()
void MyPositionController::Rotated()
{
if (m_mode == location::FollowAndRotateCompass)
if (m_mode == location::FollowAndRotate)
m_wasRotationInScaling = true;
}
@@ -405,32 +398,25 @@ void MyPositionController::NextMode(ScreenBase const & screen)
// In routing not-follow -> follow-and-rotate, otherwise not-follow -> follow.
if (m_mode == location::NotFollow)
{
ChangeMode(m_isInRouting ? location::FollowAndRotateCompass : location::Follow);
ChangeMode(m_isInRouting ? location::FollowAndRotate : location::Follow);
UpdateViewport(preferredZoomLevel);
return;
}
// From follow mode we transit to follow-and-rotate-compass, if in routing
// From follow mode we transit to follow-and-rotate if compass is available or
// routing is enabled.
if (m_mode == location::Follow)
{
if (IsArrowRotationAvailable() || m_isInRouting)
if (IsRotationAvailable() || m_isInRouting)
{
ChangeMode(location::FollowAndRotateCompass);
ChangeMode(location::FollowAndRotate);
UpdateViewport(preferredZoomLevel);
}
return;
}
// From -rotate-compass mode we transit to -rotate-route mode, if allowed
if (m_mode == location::FollowAndRotateCompass && IsRouteRotationAvailable() && m_allowRouteRotationInRouting)
{
ChangeMode(location::FollowAndRotateRoute);
UpdateViewport(preferredZoomLevel);
return;
}
// From -rotate-route mode, or from -rotate-compass if -rotate-route is not allowed, we return to follow mode
if (m_mode == location::FollowAndRotateRoute || m_mode == location::FollowAndRotateCompass)
// From follow-and-rotate mode we can transit to follow mode.
if (m_mode == location::FollowAndRotate)
{
if (m_isInRouting && screen.isPerspective())
preferredZoomLevel = static_cast<int>(GetZoomLevel(ScreenBase::GetStartPerspectiveScale() * 1.1));
@@ -439,8 +425,8 @@ void MyPositionController::NextMode(ScreenBase const & screen)
}
}
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info,
df::NavigationContext const & navigationContext, ScreenBase const & screen)
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn,
double speedLimit, ScreenBase const & screen)
{
m2::PointD const oldPos = GetDrawablePosition();
double const oldAzimut = GetDrawableAzimut();
@@ -452,62 +438,33 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info,
m_errorRadius = rect.SizeX() * 0.5;
m_horizontalAccuracy = info.m_horizontalAccuracy;
if (navigationContext.m_distanceToNextTurn >= 0.0 || navigationContext.m_speedLimit >= 0.0)
if (distanceToNextTurn >= 0.0 || speedLimit >= 0.0)
{
double const mercatorPerMeter = m_errorRadius / info.m_horizontalAccuracy;
m_autoScale2d =
mercatorPerMeter * CalculateAutoZoom(navigationContext.m_speedLimit, navigationContext.m_distanceToNextTurn,
false /* isPerspectiveAllowed */);
mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, false /* isPerspectiveAllowed */);
m_autoScale3d =
mercatorPerMeter * CalculateAutoZoom(navigationContext.m_speedLimit, navigationContext.m_distanceToNextTurn,
true /* isPerspectiveAllowed */);
mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, true /* isPerspectiveAllowed */);
}
else
{
m_autoScale2d = m_autoScale3d = kUnknownAutoZoom;
}
// Sets arrow direction based on GPS if:
// Sets direction based on GPS if:
// 1. Compass is not available.
// 2. Direction must be glued to the route during routing (route-corrected angle is set only in
// OnLocationUpdate(): in OnCompassUpdate() the angle always has the original value.
// 3. Device is moving faster then pedestrian.
bool const isMovingFast = info.HasSpeed() && info.m_speed > kMinSpeedThresholdMps;
bool const glueArrowInRouting = navigationContext.m_isNavigable && m_isArrowGluedInRouting;
// Calculate the route direction by looking ahead a distance in the route
// depending on the current speed
if (glueArrowInRouting && navigationContext.m_followedPolyline != nullptr)
{
double const speed =
(navigationContext.m_speedLimit > 0 ? measurement_utils::MpsToKmph(navigationContext.m_speedLimit)
: kDefaultSpeedLimitKmpH);
double const lookaheadTimeSec = std::min(speed * kLookaheadTimeSpeedRatio, kMaxLookaheadTimeSec);
double const lookaheadDistance = std::min(speed * lookaheadTimeSec, navigationContext.m_distanceToNextTurn);
auto const & iter = navigationContext.m_followedPolyline->GetCurrentIter();
m2::PointD const point = navigationContext.m_followedPolyline->GetLookaheadPoint(lookaheadDistance);
auto angle = math::RadToDeg(ang::AngleTo(iter.m_pt, point));
if (std::isnan(angle) || std::isinf(angle))
{
// fallback in case the current route becomes invalid for any reason
SetRouteDirection(info.m_bearing);
}
else
{
SetRouteDirection(math::DegToRad(location::AngleToBearing(angle)));
}
}
bool const glueArrowInRouting = isNavigable && m_isArrowGluedInRouting;
if ((!m_isCompassAvailable || glueArrowInRouting || isMovingFast) && info.HasBearing())
{
SetArrowDirection(math::DegToRad(info.m_bearing));
SetDirection(math::DegToRad(info.m_bearing));
m_lastGPSBearingTimer.Reset();
}
m_direction = m_mode == location::FollowAndRotateRoute ? m_routeDirection : m_arrowDirection;
if (m_isPositionAssigned && (!AlmostCurrentPosition(oldPos) || !AlmostCurrentAzimut(oldAzimut)))
{
CreateAnim(oldPos, oldAzimut, screen);
@@ -530,9 +487,9 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info,
{
ChangeModelView(m_position, kDoNotChangeZoom);
}
else if (m_mode == location::FollowAndRotateCompass || m_mode == location::FollowAndRotateRoute)
else if (m_mode == location::FollowAndRotate)
{
ChangeModelView(m_position, m_direction,
ChangeModelView(m_position, m_drawDirection,
m_isInRouting ? GetRoutingRotationPixelCenter() : m_visiblePixelRect.Center(),
kDoNotChangeZoom);
}
@@ -542,7 +499,7 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info,
{
if (m_isInRouting)
{
ChangeMode(location::FollowAndRotateCompass);
ChangeMode(location::FollowAndRotate);
UpdateViewport(kMaxScaleZoomLevel);
}
else
@@ -568,7 +525,7 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info,
{
if (m_isInRouting)
{
ChangeMode(location::FollowAndRotateCompass);
ChangeMode(location::FollowAndRotate);
UpdateViewport(kMaxScaleZoomLevel);
}
else
@@ -595,8 +552,7 @@ void MyPositionController::LoseLocation()
{
if (m_mode == location::NotFollowNoPosition)
return;
else if (m_mode == location::Follow || m_mode == location::FollowAndRotateCompass ||
m_mode == location::FollowAndRotateRoute)
else if (m_mode == location::Follow || m_mode == location::FollowAndRotate)
ChangeMode(location::PendingPosition);
else
ChangeMode(location::NotFollowNoPosition);
@@ -614,11 +570,10 @@ void MyPositionController::OnCompassUpdate(location::CompassInfo const & info, S
if ((IsInRouting() && m_isArrowGluedInRouting) || existsFreshGpsBearing)
return;
SetArrowDirection(info.m_bearing);
SetDirection(info.m_bearing);
if (m_isPositionAssigned && !AlmostCurrentAzimut(oldAzimut) && m_mode == location::FollowAndRotateCompass)
if (m_isPositionAssigned && !AlmostCurrentAzimut(oldAzimut) && m_mode == location::FollowAndRotate)
{
m_direction = info.m_bearing;
CreateAnim(GetDrawablePosition(), oldAzimut, screen);
m_isDirtyViewport = true;
}
@@ -627,10 +582,10 @@ void MyPositionController::OnCompassUpdate(location::CompassInfo const & info, S
bool MyPositionController::UpdateViewportWithAutoZoom()
{
double const autoScale = m_enablePerspectiveInRouting ? m_autoScale3d : m_autoScale2d;
if (autoScale > 0.0 && (m_mode == location::FollowAndRotateCompass || m_mode == location::FollowAndRotateRoute) &&
m_isInRouting && m_enableAutoZoomInRouting && !m_needBlockAutoZoom)
if (autoScale > 0.0 && m_mode == location::FollowAndRotate && m_isInRouting && m_enableAutoZoomInRouting &&
!m_needBlockAutoZoom)
{
ChangeModelView(autoScale, m_position, m_direction, GetRoutingRotationPixelCenter());
ChangeModelView(autoScale, m_position, m_drawDirection, GetRoutingRotationPixelCenter());
return true;
}
return false;
@@ -662,7 +617,7 @@ void MyPositionController::Render(ref_ptr<dp::GraphicsContext> context, ref_ptr<
m_shape->SetPositionObsolete(m_positionIsObsolete);
m_shape->SetPosition(m2::PointF(GetDrawablePosition()));
m_shape->SetAzimuth(static_cast<float>(GetDrawableAzimut()));
m_shape->SetIsValidAzimuth(IsArrowRotationAvailable());
m_shape->SetIsValidAzimuth(IsRotationAvailable());
m_shape->SetAccuracy(static_cast<float>(m_errorRadius));
m_shape->SetRoutingMode(IsInRouting());
@@ -676,7 +631,7 @@ void MyPositionController::Render(ref_ptr<dp::GraphicsContext> context, ref_ptr<
bool MyPositionController::IsRouteFollowingActive() const
{
return IsInRouting() && m_mode == location::FollowAndRotateCompass;
return IsInRouting() && m_mode == location::FollowAndRotate;
}
bool MyPositionController::AlmostCurrentPosition(m2::PointD const & pos) const
@@ -688,25 +643,18 @@ bool MyPositionController::AlmostCurrentPosition(m2::PointD const & pos) const
bool MyPositionController::AlmostCurrentAzimut(double azimut) const
{
double constexpr kDirectionEqualityDelta = 1e-3;
return AlmostEqualAbs(azimut, m_direction, kDirectionEqualityDelta);
return AlmostEqualAbs(azimut, m_drawDirection, kDirectionEqualityDelta);
}
void MyPositionController::SetRouteDirection(double bearing)
void MyPositionController::SetDirection(double bearing)
{
m_routeDirection = bearing;
m_isRouteDirectionAssigned = true;
}
void MyPositionController::SetArrowDirection(double bearing)
{
m_arrowDirection = bearing;
m_isArrowDirectionAssigned = true;
m_drawDirection = bearing;
m_isDirectionAssigned = true;
}
void MyPositionController::ChangeMode(location::EMyPositionMode newMode)
{
if (m_isInRouting && (m_mode != newMode) &&
(newMode == location::FollowAndRotateCompass || newMode == location::FollowAndRotateRoute))
if (m_isInRouting && (m_mode != newMode) && (newMode == location::FollowAndRotate))
ResetBlockAutoZoomTimer();
m_mode = newMode;
@@ -727,8 +675,7 @@ bool MyPositionController::IsWaitingForLocation() const
void MyPositionController::StopLocationFollow()
{
if (m_mode == location::Follow || m_mode == location::FollowAndRotateCompass ||
m_mode == location::FollowAndRotateRoute)
if (m_mode == location::Follow || m_mode == location::FollowAndRotate)
ChangeMode(location::NotFollow);
m_desiredInitMode = location::NotFollow;
@@ -743,7 +690,7 @@ void MyPositionController::OnEnterForeground(double backgroundTime)
// When location was active during previous session the app will try to follow the user.
if (m_mode == location::NotFollow)
{
ChangeMode(m_isInRouting ? location::FollowAndRotateCompass : location::Follow);
ChangeMode(m_isInRouting ? location::FollowAndRotate : location::Follow);
UpdateViewport(kDoNotChangeZoom);
}
@@ -759,7 +706,7 @@ void MyPositionController::OnEnterBackground() {}
void MyPositionController::OnCompassTapped()
{
if (m_mode == location::FollowAndRotateCompass)
if (m_mode == location::FollowAndRotate)
{
ChangeMode(location::Follow);
ChangeModelView(m_position, 0.0, m_visiblePixelRect.Center(), kDoNotChangeZoom);
@@ -816,9 +763,9 @@ void MyPositionController::UpdateViewport(int zoomLevel)
{
ChangeModelView(m_position, zoomLevel);
}
else if (m_mode == location::FollowAndRotateCompass || m_mode == location::FollowAndRotateRoute)
else if (m_mode == location::FollowAndRotate)
{
ChangeModelView(m_position, m_direction,
ChangeModelView(m_position, m_drawDirection,
m_isInRouting ? GetRoutingRotationPixelCenter() : m_visiblePixelRect.Center(), zoomLevel);
}
}
@@ -828,7 +775,7 @@ m2::PointD MyPositionController::GetRotationPixelCenter() const
if (m_mode == location::Follow)
return m_visiblePixelRect.Center();
if (m_mode == location::FollowAndRotateCompass || m_mode == location::FollowAndRotateRoute)
if (m_mode == location::FollowAndRotate)
return m_isInRouting ? GetRoutingRotationPixelCenter() : m_visiblePixelRect.Center();
return m2::PointD::Zero();
@@ -870,15 +817,15 @@ double MyPositionController::GetDrawableAzimut()
}
if (m_isPendingAnimation)
return m_oldArrowDirection;
return m_oldDrawDirection;
return m_arrowDirection;
return m_drawDirection;
}
void MyPositionController::CreateAnim(m2::PointD const & oldPos, double oldAzimut, ScreenBase const & screen)
{
double const moveDuration = PositionInterpolator::GetMoveDuration(oldPos, m_position, screen);
double const rotateDuration = AngleInterpolator::GetRotateDuration(oldAzimut, m_arrowDirection);
double const rotateDuration = AngleInterpolator::GetRotateDuration(oldAzimut, m_drawDirection);
if (df::IsAnimationAllowed(std::max(moveDuration, rotateDuration), screen))
{
if (IsModeChangeViewport())
@@ -887,7 +834,7 @@ void MyPositionController::CreateAnim(m2::PointD const & oldPos, double oldAzimu
{
drape_ptr<Animation> anim = make_unique_dp<ArrowAnimation>(
GetDrawablePosition(), m_position, syncAnim == nullptr ? moveDuration : syncAnim->GetDuration(),
GetDrawableAzimut(), m_arrowDirection);
GetDrawableAzimut(), m_drawDirection);
if (syncAnim != nullptr)
{
anim->SetMaxDuration(syncAnim->GetMaxDuration());
@@ -896,13 +843,13 @@ void MyPositionController::CreateAnim(m2::PointD const & oldPos, double oldAzimu
return anim;
};
m_oldPosition = oldPos;
m_oldArrowDirection = oldAzimut;
m_oldDrawDirection = oldAzimut;
m_isPendingAnimation = true;
}
else
{
AnimationSystem::Instance().CombineAnimation(
make_unique_dp<ArrowAnimation>(oldPos, m_position, moveDuration, oldAzimut, m_arrowDirection));
make_unique_dp<ArrowAnimation>(oldPos, m_position, moveDuration, oldAzimut, m_drawDirection));
}
}
}
@@ -921,18 +868,16 @@ void MyPositionController::EnableAutoZoomInRouting(bool enableAutoZoom)
}
}
void MyPositionController::ActivateRouting(int zoomLevel, bool enableAutoZoom, bool isArrowGlued,
bool allowRouteRotation)
void MyPositionController::ActivateRouting(int zoomLevel, bool enableAutoZoom, bool isArrowGlued)
{
if (!m_isInRouting)
{
m_isInRouting = true;
m_isArrowGluedInRouting = isArrowGlued;
m_enableAutoZoomInRouting = enableAutoZoom;
m_allowRouteRotationInRouting = allowRouteRotation;
ChangeMode(location::FollowAndRotateCompass);
ChangeModelView(m_position, m_isRouteDirectionAssigned ? m_routeDirection : 0.0, GetRoutingRotationPixelCenter(),
ChangeMode(location::FollowAndRotate);
ChangeModelView(m_position, m_isDirectionAssigned ? m_drawDirection : 0.0, GetRoutingRotationPixelCenter(),
zoomLevel, [this](ref_ptr<Animation> anim) { UpdateViewport(kDoNotChangeZoom); });
ResetRoutingNotFollowTimer();
}
@@ -944,10 +889,8 @@ void MyPositionController::DeactivateRouting()
{
m_isInRouting = false;
m_isArrowGluedInRouting = false;
m_allowRouteRotationInRouting = false;
m_isArrowDirectionAssigned = m_isCompassAvailable && m_isArrowDirectionAssigned;
m_isRouteDirectionAssigned = false;
m_isDirectionAssigned = m_isCompassAvailable && m_isDirectionAssigned;
ChangeMode(location::Follow);
ChangeModelView(m_position, 0.0, m_visiblePixelRect.Center(), kDoNotChangeZoom);
@@ -976,7 +919,7 @@ void MyPositionController::CheckNotFollowRouting()
CHECK_ON_TIMEOUT(m_routingNotFollowNotifyId, kMaxNotFollowRoutingTimeSec, CheckNotFollowRouting);
if (m_routingNotFollowTimer.ElapsedSeconds() >= kMaxNotFollowRoutingTimeSec)
{
ChangeMode(location::FollowAndRotateCompass);
ChangeMode(location::FollowAndRotate);
UpdateViewport(kDoNotChangeZoom);
}
}

View File

@@ -7,7 +7,6 @@
#include "drape/pointers.hpp"
#include "routing/base/followed_polyline.hpp"
#include "shaders/program_manager.hpp"
#include "platform/location.hpp"
@@ -25,24 +24,6 @@ using TAnimationCreator = std::function<drape_ptr<Animation>(ref_ptr<Animation>)
class DrapeNotifier;
struct NavigationContext
{
bool m_isNavigable = false;
double m_distanceToNextTurn = 0.0;
double m_speedLimit = 0.0;
routing::FollowedPolyline const * m_followedPolyline = nullptr;
NavigationContext() = default;
NavigationContext(bool navigable, double distanceToTurn, double speedLimit,
routing::FollowedPolyline const & followedPolyline)
: m_isNavigable(navigable)
, m_distanceToNextTurn(distanceToTurn)
, m_speedLimit(speedLimit)
, m_followedPolyline(&followedPolyline)
{}
};
class MyPositionController
{
public:
@@ -121,7 +102,7 @@ public:
drape_ptr<MyPosition> && shape, Arrow3d::PreloadedData && preloadedData);
void ResetRenderShape();
void ActivateRouting(int zoomLevel, bool enableAutoZoom, bool isArrowGlued, bool allowRouteRotation);
void ActivateRouting(int zoomLevel, bool enableAutoZoom, bool isArrowGlued);
void DeactivateRouting();
void EnablePerspectiveInRouting(bool enablePerspective);
@@ -136,15 +117,14 @@ public:
void OnEnterBackground();
void OnCompassTapped();
void OnLocationUpdate(location::GpsInfo const & info, df::NavigationContext const & navigationContext,
void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn, double speedLimit,
ScreenBase const & screen);
void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen);
void Render(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng, ScreenBase const & screen,
int zoomLevel, FrameValues const & frameValues);
bool IsArrowRotationAvailable() const { return m_isArrowDirectionAssigned; }
bool IsRouteRotationAvailable() const { return m_isRouteDirectionAssigned; }
bool IsRotationAvailable() const { return m_isDirectionAssigned; }
bool IsInRouting() const { return m_isInRouting; }
bool IsRouteFollowingActive() const;
bool IsModeChangeViewport() const;
@@ -155,8 +135,7 @@ public:
private:
void ChangeMode(location::EMyPositionMode newMode);
void SetRouteDirection(double bearing);
void SetArrowDirection(double bearing);
void SetDirection(double bearing);
void ChangeModelView(m2::PointD const & center, int zoomLevel);
void ChangeModelView(double azimuth);
@@ -199,15 +178,12 @@ private:
double m_errorRadius; // error radius in mercator.
double m_horizontalAccuracy;
m2::PointD m_position; // position in mercator.
double m_direction;
double m_routeDirection;
double m_arrowDirection;
double m_drawDirection;
m2::PointD m_oldPosition; // position in mercator.
double m_oldArrowDirection;
double m_oldDrawDirection;
bool m_enablePerspectiveInRouting;
bool m_enableAutoZoomInRouting;
bool m_allowRouteRotationInRouting;
double m_autoScale2d;
double m_autoScale3d;
@@ -229,8 +205,7 @@ private:
TAnimationCreator m_animCreator;
bool m_isPositionAssigned;
bool m_isArrowDirectionAssigned;
bool m_isRouteDirectionAssigned;
bool m_isDirectionAssigned;
bool m_isCompassAvailable;
bool m_positionIsObsolete;

View File

@@ -31,8 +31,8 @@ namespace df
{
namespace
{
uint64_t constexpr kDoubleTapPauseMs = 200;
uint64_t constexpr kLongTouchMs = 700;
uint64_t constexpr kDoubleTapPauseMs = 250;
uint64_t constexpr kLongTouchMs = 500;
uint64_t constexpr kKineticDelayMs = 500;
float constexpr kForceTapThreshold = 0.75;

View File

@@ -58,15 +58,15 @@ public:
// Should match codes in the array below.
static int8_t constexpr kEnglishCode = 1;
static int8_t constexpr kUnsupportedLocaleCode = -1;
static int8_t constexpr kSimplifiedChineseCode = 45;
static int8_t constexpr kTraditionalChineseCode = 46;
static int8_t constexpr kSimplifiedChineseCode = 44;
static int8_t constexpr kTraditionalChineseCode = 45;
// *NOTE* These constants should be updated when adding new
// translation to categories.txt. When editing, keep in mind to check
// CategoriesHolder::MapLocaleToInteger() and
// CategoriesHolder::MapIntegerToLocale() as their implementations
// strongly depend on the contents of the variable.
// TODO: Refactor for more flexibility and to avoid breaking rules in two methods mentioned above.
static std::array<CategoriesHolder::Mapping, 46> constexpr kLocaleMapping = {{
static std::array<CategoriesHolder::Mapping, 45> constexpr kLocaleMapping = {{
{"en", kEnglishCode},
{"en-AU", 2},
{"en-GB", 3},
@@ -93,24 +93,23 @@ public:
{"it", 24},
{"ja", 25},
{"ko", 26},
{"lt", 27},
{"lv", 28},
{"mr", 29},
{"nb", 30},
{"nl", 31},
{"pl", 32},
{"pt", 33},
{"pt-BR", 34},
{"ro", 35},
{"ru", 36},
{"sk", 37},
{"sr", 38},
{"sv", 39},
{"sw", 40},
{"th", 41},
{"tr", 42},
{"uk", 43},
{"vi", 44},
{"lv", 27},
{"mr", 28},
{"nb", 29},
{"nl", 30},
{"pl", 31},
{"pt", 32},
{"pt-BR", 33},
{"ro", 34},
{"ru", 35},
{"sk", 36},
{"sr", 37},
{"sv", 38},
{"sw", 39},
{"th", 40},
{"tr", 41},
{"uk", 42},
{"vi", 43},
{"zh-Hans", kSimplifiedChineseCode},
{"zh-Hant", kTraditionalChineseCode},
}};

View File

@@ -7,7 +7,6 @@
#include "ge0/url_generator.hpp"
#include "platform/location.hpp"
#include "routing/route.hpp"
#include "routing/speed_camera_prohibition.hpp"
@@ -1454,7 +1453,7 @@ void Framework::CreateDrapeEngine(ref_ptr<dp::GraphicsContextFactory> contextFac
GetPlatform().RunTask(Platform::Thread::Gui, [this, mode, routingActive]()
{
// Deactivate selection (and hide place page) if we return to routing in F&R mode.
if (routingActive && (mode == location::FollowAndRotateCompass || mode == location::FollowAndRotateRoute))
if (routingActive && mode == location::FollowAndRotate)
DeactivateMapSelection();
if (m_myPositionListener != nullptr)
@@ -3209,7 +3208,6 @@ void Framework::ReadFeatures(function<void(FeatureType &)> const & reader, vecto
void Framework::OnRouteFollow(routing::RouterType type)
{
bool const isPedestrianRoute = type == RouterType::Pedestrian;
bool const allowRouteRotation = type == RouterType::Vehicle;
bool const enableAutoZoom = isPedestrianRoute ? false : LoadAutoZoom();
int const scale = isPedestrianRoute ? scales::GetPedestrianNavigationScale() : scales::GetNavigationScale();
int scale3d = isPedestrianRoute ? scales::GetPedestrianNavigation3dScale() : scales::GetNavigation3dScale();
@@ -3225,7 +3223,7 @@ void Framework::OnRouteFollow(routing::RouterType type)
// TODO. We need to sync two enums VehicleType and RouterType to be able to pass
// GetRoutingSettings(type).m_matchRoute to the FollowRoute() instead of |isPedestrianRoute|.
// |isArrowGlued| parameter fully corresponds to |m_matchRoute| in RoutingSettings.
m_drapeEngine->FollowRoute(scale, scale3d, enableAutoZoom, !isPedestrianRoute /* isArrowGlued */, allowRouteRotation);
m_drapeEngine->FollowRoute(scale, scale3d, enableAutoZoom, !isPedestrianRoute /* isArrowGlued */);
}
// RoutingManager::Delegate

View File

@@ -1,12 +1,9 @@
#include "routing_manager.hpp"
#include "drape_frontend/my_position_controller.hpp"
#include "geometry/angles.hpp"
#include "map/chart_generator.hpp"
#include "map/routing_mark.hpp"
#include "routing/absent_regions_finder.hpp"
#include "routing/base/followed_polyline.hpp"
#include "routing/checkpoint_predictor.hpp"
#include "routing/index_router.hpp"
#include "routing/route.hpp"
@@ -1173,9 +1170,9 @@ void RoutingManager::SetDrapeEngine(ref_ptr<df::DrapeEngine> engine, bool is3dAl
if (m_gpsInfoCache != nullptr)
{
auto routeMatchingInfo = GetRouteMatchingInfo(*m_gpsInfoCache);
df::NavigationContext navigationContext(m_routingSession.IsNavigable(), m_routingSession.GetDistanceToNextTurn(),
m_routingSession.GetCurrentSpeedLimit(), GetRoutePolyline());
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, *m_gpsInfoCache, navigationContext, routeMatchingInfo);
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, *m_gpsInfoCache, m_routingSession.IsNavigable(),
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
routeMatchingInfo);
m_gpsInfoCache.reset();
}
@@ -1519,9 +1516,9 @@ void RoutingManager::OnExtrapolatedLocationUpdate(location::GpsInfo const & info
m_gpsInfoCache = make_unique<location::GpsInfo>(gpsInfo);
auto routeMatchingInfo = GetRouteMatchingInfo(gpsInfo);
df::NavigationContext navigationContext(m_routingSession.IsNavigable(), m_routingSession.GetDistanceToNextTurn(),
m_routingSession.GetCurrentSpeedLimit(), GetRoutePolyline());
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, navigationContext, routeMatchingInfo);
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, m_routingSession.IsNavigable(),
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
routeMatchingInfo);
}
void RoutingManager::DeleteSavedRoutePoints()

View File

@@ -27,7 +27,7 @@ namespace routing::turns::sound
* - All other variants default to `zh-Hans` (Simplified Chinese).
*
*/
std::array<std::pair<std::string_view, std::string_view>, 43> constexpr kLanguageList = {{
std::array<std::pair<std::string_view, std::string_view>, 42> constexpr kLanguageList = {{
{"en", "English"},
{"id", "Bahasa Indonesia"},
{"ca", "Català"},
@@ -82,6 +82,5 @@ std::array<std::pair<std::string_view, std::string_view>, 43> constexpr kLanguag
#endif
{"ja", "日本語"},
{"ko", "한국어"},
{"ta", "தமிழ்"},
}};
} // namespace routing::turns::sound

View File

@@ -139,8 +139,7 @@ enum EMyPositionMode
NotFollowNoPosition,
NotFollow,
Follow,
FollowAndRotateCompass,
FollowAndRotateRoute
FollowAndRotate
};
using TMyPositionModeChanged = std::function<void(location::EMyPositionMode, bool)>;

View File

@@ -308,8 +308,7 @@ string ToString<location::EMyPositionMode>(location::EMyPositionMode const & v)
case location::NotFollow: return "NotFollow";
case location::NotFollowNoPosition: return "NotFollowNoPosition";
case location::Follow: return "Follow";
case location::FollowAndRotateCompass: return "FollowAndRotateCompass";
case location::FollowAndRotateRoute: return "FollowAndRotateRoute";
case location::FollowAndRotate: return "FollowAndRotate";
default: return "Pending";
}
}
@@ -325,10 +324,8 @@ bool FromString<location::EMyPositionMode>(string const & s, location::EMyPositi
v = location::NotFollowNoPosition;
else if (s == "Follow")
v = location::Follow;
else if (s == "FollowAndRotateCompass")
v = location::FollowAndRotateCompass;
else if (s == "FollowAndRotateRoute")
v = location::FollowAndRotateRoute;
else if (s == "FollowAndRotate")
v = location::FollowAndRotate;
else
return false;

View File

@@ -237,34 +237,4 @@ Iter FollowedPolyline::GetClosestMatchingProjectionInInterval(m2::RectD const &
return nearestIter;
}
m2::PointD FollowedPolyline::GetLookaheadPoint(double lookaheadDistanceM) const
{
if (!IsValid())
return m2::PointD();
size_t segmentIdx = m_current.m_ind;
m2::PointD prev = m_current.m_pt;
size_t const maxSegmentIdx = m_poly.GetSize() - 1;
double remaining = lookaheadDistanceM;
while (segmentIdx < maxSegmentIdx)
{
m2::PointD const & next = m_poly.GetPoint(segmentIdx + 1);
double segLen = mercator::DistanceOnEarth(prev, next);
if (remaining <= segLen)
{
double t = remaining / segLen;
return prev + (next - prev) * t;
}
remaining -= segLen;
prev = next;
segmentIdx += 1;
}
return m_poly.GetPoint(segmentIdx);
}
} // namespace routing

View File

@@ -125,9 +125,6 @@ public:
bool IsFakeSegment(size_t index) const;
/// \brief Obtain a point |lookaheadDistanceM| meters along the current route
m2::PointD GetLookaheadPoint(double lookaheadDistanceM) const;
private:
/// \returns iterator to the best projection of center of |posRect| to the |m_poly|.
/// If there's a good projection of center of |posRect| to two closest segments of |m_poly|