mirror of
https://github.com/infiniteCable2/openpilot.git
synced 2026-07-26 03:42:05 +08:00
ui: refactor hud updating and rendering into HudRenderer class (#33458)
refactor hud updating and rendering into DriverMonitorRenderer class
This commit is contained in:
@@ -31,7 +31,7 @@ qt_src = ["main.cc", "ui.cc", "qt/sidebar.cc", "qt/body.cc",
|
||||
"qt/offroad/software_settings.cc", "qt/offroad/onboarding.cc",
|
||||
"qt/offroad/driverview.cc", "qt/offroad/experimental_mode.cc",
|
||||
"qt/onroad/onroad_home.cc", "qt/onroad/annotated_camera.cc",
|
||||
"qt/onroad/buttons.cc", "qt/onroad/alerts.cc", "qt/onroad/driver_monitoring.cc"]
|
||||
"qt/onroad/buttons.cc", "qt/onroad/alerts.cc", "qt/onroad/driver_monitoring.cc", "qt/onroad/hud.cc"]
|
||||
|
||||
# build translation files
|
||||
with open(File("translations/languages.json").abspath) as f:
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <cmath>
|
||||
|
||||
#include "common/swaglog.h"
|
||||
#include "selfdrive/ui/qt/onroad/buttons.h"
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
// Window that shows camera view and variety of info drawn on top
|
||||
@@ -23,98 +22,11 @@ AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget *par
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::updateState(const UIState &s) {
|
||||
const int SET_SPEED_NA = 255;
|
||||
const SubMaster &sm = *(s.sm);
|
||||
|
||||
const bool cs_alive = sm.alive("carState");
|
||||
const auto cs = sm["controlsState"].getControlsState();
|
||||
const auto car_state = sm["carState"].getCarState();
|
||||
|
||||
is_metric = s.scene.is_metric;
|
||||
|
||||
// Handle older routes where vCruise was in controlsState
|
||||
float v_cruise = car_state.getVCruiseCluster() == 0.0 ? cs.getVCruiseDEPRECATED() : car_state.getVCruiseCluster();
|
||||
setSpeed = cs_alive ? v_cruise : SET_SPEED_NA;
|
||||
is_cruise_set = setSpeed > 0 && (int)setSpeed != SET_SPEED_NA;
|
||||
if (is_cruise_set && !is_metric) {
|
||||
setSpeed *= KM_TO_MILE;
|
||||
}
|
||||
|
||||
// Handle older routes where vEgoCluster is not set
|
||||
v_ego_cluster_seen = v_ego_cluster_seen || car_state.getVEgoCluster() != 0.0;
|
||||
float v_ego = v_ego_cluster_seen ? car_state.getVEgoCluster() : car_state.getVEgo();
|
||||
speed = cs_alive ? std::max<float>(0.0, v_ego) : 0.0;
|
||||
speed *= is_metric ? MS_TO_KPH : MS_TO_MPH;
|
||||
|
||||
speedUnit = is_metric ? tr("km/h") : tr("mph");
|
||||
status = s.status;
|
||||
|
||||
// update engageability/experimental mode button
|
||||
experimental_btn->updateState(s);
|
||||
|
||||
// update DM icon
|
||||
dmon.updateState(s);
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::drawHud(QPainter &p) {
|
||||
p.save();
|
||||
|
||||
// Header gradient
|
||||
QLinearGradient bg(0, UI_HEADER_HEIGHT - (UI_HEADER_HEIGHT / 2.5), 0, UI_HEADER_HEIGHT);
|
||||
bg.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.45));
|
||||
bg.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0));
|
||||
p.fillRect(0, 0, width(), UI_HEADER_HEIGHT, bg);
|
||||
|
||||
QString speedStr = QString::number(std::nearbyint(speed));
|
||||
QString setSpeedStr = is_cruise_set ? QString::number(std::nearbyint(setSpeed)) : "–";
|
||||
|
||||
// Draw outer box + border to contain set speed
|
||||
const QSize default_size = {172, 204};
|
||||
QSize set_speed_size = default_size;
|
||||
if (is_metric) set_speed_size.rwidth() = 200;
|
||||
|
||||
QRect set_speed_rect(QPoint(60 + (default_size.width() - set_speed_size.width()) / 2, 45), set_speed_size);
|
||||
p.setPen(QPen(whiteColor(75), 6));
|
||||
p.setBrush(blackColor(166));
|
||||
p.drawRoundedRect(set_speed_rect, 32, 32);
|
||||
|
||||
// Draw MAX
|
||||
QColor max_color = QColor(0x80, 0xd8, 0xa6, 0xff);
|
||||
QColor set_speed_color = whiteColor();
|
||||
if (is_cruise_set) {
|
||||
if (status == STATUS_DISENGAGED) {
|
||||
max_color = whiteColor();
|
||||
} else if (status == STATUS_OVERRIDE) {
|
||||
max_color = QColor(0x91, 0x9b, 0x95, 0xff);
|
||||
}
|
||||
} else {
|
||||
max_color = QColor(0xa6, 0xa6, 0xa6, 0xff);
|
||||
set_speed_color = QColor(0x72, 0x72, 0x72, 0xff);
|
||||
}
|
||||
p.setFont(InterFont(40, QFont::DemiBold));
|
||||
p.setPen(max_color);
|
||||
p.drawText(set_speed_rect.adjusted(0, 27, 0, 0), Qt::AlignTop | Qt::AlignHCenter, tr("MAX"));
|
||||
p.setFont(InterFont(90, QFont::Bold));
|
||||
p.setPen(set_speed_color);
|
||||
p.drawText(set_speed_rect.adjusted(0, 77, 0, 0), Qt::AlignTop | Qt::AlignHCenter, setSpeedStr);
|
||||
|
||||
// current speed
|
||||
p.setFont(InterFont(176, QFont::Bold));
|
||||
drawText(p, rect().center().x(), 210, speedStr);
|
||||
p.setFont(InterFont(66));
|
||||
drawText(p, rect().center().x(), 290, speedUnit, 200);
|
||||
|
||||
p.restore();
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::drawText(QPainter &p, int x, int y, const QString &text, int alpha) {
|
||||
QRect real_rect = p.fontMetrics().boundingRect(text);
|
||||
real_rect.moveCenter({x, y - real_rect.height() / 2});
|
||||
|
||||
p.setPen(QColor(0xff, 0xff, 0xff, alpha));
|
||||
p.drawText(real_rect.x(), real_rect.bottom(), text);
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::initializeGL() {
|
||||
CameraWidget::initializeGL();
|
||||
qInfo() << "OpenGL version:" << QString((const char*)glGetString(GL_VERSION));
|
||||
@@ -333,8 +245,8 @@ void AnnotatedCameraWidget::paintGL() {
|
||||
}
|
||||
|
||||
dmon.draw(painter, rect());
|
||||
|
||||
drawHud(painter);
|
||||
hud.updateState(*s);
|
||||
hud.draw(painter, rect());
|
||||
|
||||
double cur_draw_t = millis_since_boot();
|
||||
double dt = cur_draw_t - prev_draw_t;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <memory>
|
||||
|
||||
#include "selfdrive/ui/qt/onroad/hud.h"
|
||||
#include "selfdrive/ui/qt/onroad/buttons.h"
|
||||
#include "selfdrive/ui/qt/onroad/driver_monitoring.h"
|
||||
#include "selfdrive/ui/qt/widgets/cameraview.h"
|
||||
@@ -15,18 +15,10 @@ public:
|
||||
void updateState(const UIState &s);
|
||||
|
||||
private:
|
||||
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);
|
||||
|
||||
QVBoxLayout *main_layout;
|
||||
ExperimentalButton *experimental_btn;
|
||||
DriverMonitorRenderer dmon;
|
||||
float speed;
|
||||
QString speedUnit;
|
||||
float setSpeed;
|
||||
bool is_cruise_set = false;
|
||||
bool is_metric = false;
|
||||
bool v_ego_cluster_seen = false;
|
||||
int status = STATUS_DISENGAGED;
|
||||
HudRenderer hud;
|
||||
std::unique_ptr<PubMaster> pm;
|
||||
|
||||
int skip_frame_count = 0;
|
||||
@@ -39,10 +31,7 @@ protected:
|
||||
mat4 calcFrameMatrix() override;
|
||||
void drawLaneLines(QPainter &painter, const UIState *s);
|
||||
void drawLead(QPainter &painter, const cereal::RadarState::LeadData::Reader &lead_data, const QPointF &vd);
|
||||
void drawHud(QPainter &p);
|
||||
inline QColor redColor(int alpha = 255) { return QColor(201, 34, 49, alpha); }
|
||||
inline QColor whiteColor(int alpha = 255) { return QColor(255, 255, 255, alpha); }
|
||||
inline QColor blackColor(int alpha = 255) { return QColor(0, 0, 0, alpha); }
|
||||
|
||||
double prev_draw_t = 0;
|
||||
FirstOrderFilter fps_filter;
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
#include "selfdrive/ui/qt/onroad/hud.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
constexpr int SET_SPEED_NA = 255;
|
||||
|
||||
HudRenderer::HudRenderer() {}
|
||||
|
||||
void HudRenderer::updateState(const UIState &s) {
|
||||
is_metric = s.scene.is_metric;
|
||||
status = s.status;
|
||||
|
||||
const SubMaster &sm = *(s.sm);
|
||||
if (!sm.alive("carState")) {
|
||||
is_cruise_set = false;
|
||||
set_speed = SET_SPEED_NA;
|
||||
speed = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &controls_state = sm["controlsState"].getControlsState();
|
||||
const auto &car_state = sm["carState"].getCarState();
|
||||
|
||||
// Handle older routes where vCruiseCluster is not set
|
||||
set_speed = car_state.getVCruiseCluster() == 0.0 ? controls_state.getVCruiseDEPRECATED() : car_state.getVCruiseCluster();
|
||||
is_cruise_set = set_speed > 0 && set_speed != SET_SPEED_NA;
|
||||
|
||||
if (is_cruise_set && !is_metric) {
|
||||
set_speed *= KM_TO_MILE;
|
||||
}
|
||||
|
||||
// Handle older routes where vEgoCluster is not set
|
||||
v_ego_cluster_seen = v_ego_cluster_seen || car_state.getVEgoCluster() != 0.0;
|
||||
float v_ego = v_ego_cluster_seen ? car_state.getVEgoCluster() : car_state.getVEgo();
|
||||
speed = std::max<float>(0.0f, v_ego * (is_metric ? MS_TO_KPH : MS_TO_MPH));
|
||||
}
|
||||
|
||||
void HudRenderer::draw(QPainter &p, const QRect &surface_rect) {
|
||||
p.save();
|
||||
|
||||
// Draw header gradient
|
||||
QLinearGradient bg(0, UI_HEADER_HEIGHT - (UI_HEADER_HEIGHT / 2.5), 0, UI_HEADER_HEIGHT);
|
||||
bg.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.45));
|
||||
bg.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0));
|
||||
p.fillRect(0, 0, surface_rect.width(), UI_HEADER_HEIGHT, bg);
|
||||
|
||||
|
||||
drawSetSpeed(p, surface_rect);
|
||||
drawCurrentSpeed(p, surface_rect);
|
||||
|
||||
p.restore();
|
||||
}
|
||||
|
||||
void HudRenderer::drawSetSpeed(QPainter &p, const QRect &surface_rect) {
|
||||
// Draw outer box + border to contain set speed
|
||||
const QSize default_size = {172, 204};
|
||||
QSize set_speed_size = is_metric ? QSize(200, 204) : default_size;
|
||||
QRect set_speed_rect(QPoint(60 + (default_size.width() - set_speed_size.width()) / 2, 45), set_speed_size);
|
||||
|
||||
// Draw set speed box
|
||||
p.setPen(QPen(QColor(255, 255, 255, 75), 6));
|
||||
p.setBrush(QColor(0, 0, 0, 166));
|
||||
p.drawRoundedRect(set_speed_rect, 32, 32);
|
||||
|
||||
// Colors based on status
|
||||
QColor max_color = QColor(0xa6, 0xa6, 0xa6, 0xff);
|
||||
QColor set_speed_color = QColor(0x72, 0x72, 0x72, 0xff);
|
||||
if (is_cruise_set) {
|
||||
if (status == STATUS_DISENGAGED) {
|
||||
max_color = QColor(255, 255, 255);
|
||||
} else if (status == STATUS_OVERRIDE) {
|
||||
max_color = QColor(0x91, 0x9b, 0x95, 0xff);
|
||||
} else {
|
||||
max_color = QColor(0x80, 0xd8, 0xa6, 0xff);
|
||||
set_speed_color = QColor(255, 255, 255);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw "MAX" text
|
||||
p.setFont(InterFont(40, QFont::DemiBold));
|
||||
p.setPen(max_color);
|
||||
p.drawText(set_speed_rect.adjusted(0, 27, 0, 0), Qt::AlignTop | Qt::AlignHCenter, tr("MAX"));
|
||||
|
||||
// Draw set speed
|
||||
QString setSpeedStr = is_cruise_set ? QString::number(std::nearbyint(set_speed)) : "–";
|
||||
p.setFont(InterFont(90, QFont::Bold));
|
||||
p.setPen(set_speed_color);
|
||||
p.drawText(set_speed_rect.adjusted(0, 77, 0, 0), Qt::AlignTop | Qt::AlignHCenter, setSpeedStr);
|
||||
}
|
||||
|
||||
void HudRenderer::drawCurrentSpeed(QPainter &p, const QRect &surface_rect) {
|
||||
QString speedStr = QString::number(std::nearbyint(speed));
|
||||
|
||||
p.setFont(InterFont(176, QFont::Bold));
|
||||
drawText(p, surface_rect.center().x(), 210, speedStr);
|
||||
|
||||
p.setFont(InterFont(66));
|
||||
drawText(p, surface_rect.center().x(), 290, is_metric ? tr("km/h") : tr("mph"), 200);
|
||||
}
|
||||
|
||||
void HudRenderer::drawText(QPainter &p, int x, int y, const QString &text, int alpha) {
|
||||
QRect real_rect = p.fontMetrics().boundingRect(text);
|
||||
real_rect.moveCenter({x, y - real_rect.height() / 2});
|
||||
|
||||
p.setPen(QColor(0xff, 0xff, 0xff, alpha));
|
||||
p.drawText(real_rect.x(), real_rect.bottom(), text);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <QPainter>
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
class HudRenderer : public QObject {
|
||||
public:
|
||||
HudRenderer();
|
||||
void updateState(const UIState &s);
|
||||
void draw(QPainter &p, const QRect &surface_rect);
|
||||
|
||||
private:
|
||||
void drawSetSpeed(QPainter &p, const QRect &surface_rect);
|
||||
void drawCurrentSpeed(QPainter &p, const QRect &surface_rect);
|
||||
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);
|
||||
|
||||
float speed = 0;
|
||||
float set_speed = 0;
|
||||
bool is_cruise_set = false;
|
||||
bool is_metric = false;
|
||||
bool v_ego_cluster_seen = false;
|
||||
int status = STATUS_DISENGAGED;
|
||||
};
|
||||
@@ -87,21 +87,6 @@
|
||||
<translation>من أجل "%1"</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnnotatedCameraWidget</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>كم/س</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>ميل/س</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConfirmationDialog</name>
|
||||
<message>
|
||||
@@ -289,6 +274,21 @@
|
||||
<translation>تشغيل وضع الراحة</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HudRenderer</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>كم/س</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>ميل/س</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputDialog</name>
|
||||
<message>
|
||||
|
||||
@@ -87,21 +87,6 @@
|
||||
<translation type="unfinished">für "%1"</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnnotatedCameraWidget</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConfirmationDialog</name>
|
||||
<message>
|
||||
@@ -289,6 +274,21 @@
|
||||
<translation>ENTSPANNTER MODUS AN</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HudRenderer</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputDialog</name>
|
||||
<message>
|
||||
|
||||
@@ -87,21 +87,6 @@
|
||||
<translation>para "%1"</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnnotatedCameraWidget</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConfirmationDialog</name>
|
||||
<message>
|
||||
@@ -289,6 +274,21 @@
|
||||
<translation>MODO CHILL</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HudRenderer</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputDialog</name>
|
||||
<message>
|
||||
|
||||
@@ -87,21 +87,6 @@
|
||||
<translation>pour "%1"</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnnotatedCameraWidget</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mi/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConfirmationDialog</name>
|
||||
<message>
|
||||
@@ -289,6 +274,21 @@
|
||||
<translation>MODE DÉTENTE ACTIVÉ</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HudRenderer</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mi/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputDialog</name>
|
||||
<message>
|
||||
|
||||
@@ -87,21 +87,6 @@
|
||||
<translation type="unfinished">ネットワーク名:%1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnnotatedCameraWidget</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>最高速度</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConfirmationDialog</name>
|
||||
<message>
|
||||
@@ -289,6 +274,21 @@
|
||||
<translation>チルモード</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HudRenderer</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>最高速度</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputDialog</name>
|
||||
<message>
|
||||
|
||||
@@ -87,21 +87,6 @@
|
||||
<translation>"%1"에 접속하려면 비밀번호가 필요합니다</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnnotatedCameraWidget</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConfirmationDialog</name>
|
||||
<message>
|
||||
@@ -289,6 +274,21 @@
|
||||
<translation>안정 모드 사용</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HudRenderer</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputDialog</name>
|
||||
<message>
|
||||
|
||||
@@ -87,21 +87,6 @@
|
||||
<translation>para "%1"</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnnotatedCameraWidget</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>LIMITE</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConfirmationDialog</name>
|
||||
<message>
|
||||
@@ -289,6 +274,21 @@
|
||||
<translation>MODO CHILL ON</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HudRenderer</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>LIMITE</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputDialog</name>
|
||||
<message>
|
||||
|
||||
@@ -87,21 +87,6 @@
|
||||
<translation>สำหรับ "%1"</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnnotatedCameraWidget</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>กม./ชม.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>ไมล์/ชม.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>สูงสุด</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConfirmationDialog</name>
|
||||
<message>
|
||||
@@ -289,6 +274,21 @@
|
||||
<translation>คุณกำลังใช้โหมดชิล</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HudRenderer</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>กม./ชม.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>ไมล์/ชม.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>สูงสุด</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputDialog</name>
|
||||
<message>
|
||||
|
||||
@@ -87,21 +87,6 @@
|
||||
<translation type="unfinished">için "%1"</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnnotatedCameraWidget</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation type="unfinished">km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation type="unfinished">mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation type="unfinished">MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConfirmationDialog</name>
|
||||
<message>
|
||||
@@ -289,6 +274,21 @@
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HudRenderer</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>MAX</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputDialog</name>
|
||||
<message>
|
||||
|
||||
@@ -87,21 +87,6 @@
|
||||
<translation>网络名称:"%1"</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnnotatedCameraWidget</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>最高定速</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConfirmationDialog</name>
|
||||
<message>
|
||||
@@ -289,6 +274,21 @@
|
||||
<translation>轻松模式运行</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HudRenderer</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>最高定速</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputDialog</name>
|
||||
<message>
|
||||
|
||||
@@ -87,21 +87,6 @@
|
||||
<translation>給 "%1"</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AnnotatedCameraWidget</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>最高</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConfirmationDialog</name>
|
||||
<message>
|
||||
@@ -289,6 +274,21 @@
|
||||
<translation>輕鬆模式 ON</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HudRenderer</name>
|
||||
<message>
|
||||
<source>km/h</source>
|
||||
<translation>km/h</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>mph</source>
|
||||
<translation>mph</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MAX</source>
|
||||
<translation>最高</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputDialog</name>
|
||||
<message>
|
||||
|
||||
Reference in New Issue
Block a user