mirror of
https://github.com/MoreTore/openpilot.git
synced 2026-08-05 00:05:59 +08:00
ui/map: move MapInstructions & MapETA to separate files (#28976)
This commit is contained in:
@@ -29,7 +29,8 @@ widgets_src = ["ui.cc", "qt/widgets/input.cc", "qt/widgets/drive_stats.cc", "qt/
|
||||
qt_env['CPPDEFINES'] = []
|
||||
if maps:
|
||||
base_libs += ['qmapboxgl']
|
||||
widgets_src += ["qt/maps/map_helpers.cc", "qt/maps/map_settings.cc", "qt/maps/map.cc", "qt/maps/map_panel.cc"]
|
||||
widgets_src += ["qt/maps/map_helpers.cc", "qt/maps/map_settings.cc", "qt/maps/map.cc", "qt/maps/map_panel.cc",
|
||||
"qt/maps/map_eta.cc", "qt/maps/map_instructions.cc"]
|
||||
qt_env['CPPDEFINES'] += ["ENABLE_MAPS"]
|
||||
|
||||
widgets = qt_env.Library("qt_widgets", widgets_src, LIBS=base_libs)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <eigen3/Eigen/Dense>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
|
||||
#include "common/transformations/coordinates.hpp"
|
||||
#include "selfdrive/ui/qt/maps/map_helpers.h"
|
||||
@@ -12,7 +11,6 @@
|
||||
|
||||
|
||||
const int PAN_TIMEOUT = 100;
|
||||
const float MANEUVER_TRANSITION_THRESHOLD = 10;
|
||||
|
||||
const float MAX_ZOOM = 17;
|
||||
const float MIN_ZOOM = 14;
|
||||
@@ -20,8 +18,6 @@ const float MAX_PITCH = 50;
|
||||
const float MIN_PITCH = 0;
|
||||
const float MAP_SCALE = 2;
|
||||
|
||||
const QString ICON_SUFFIX = ".png";
|
||||
|
||||
MapWindow::MapWindow(const QMapboxGLSettings &settings) : m_settings(settings), velocity_filter(0, 10, 0.05) {
|
||||
QObject::connect(uiState(), &UIState::uiUpdate, this, &MapWindow::updateState);
|
||||
|
||||
@@ -428,186 +424,3 @@ void MapWindow::updateDestinationMarker() {
|
||||
m_map->setPaintProperty("pinLayer", "icon-opacity", 1);
|
||||
}
|
||||
}
|
||||
|
||||
MapInstructions::MapInstructions(QWidget *parent) : QWidget(parent) {
|
||||
is_rhd = Params().getBool("IsRhdDetected");
|
||||
QHBoxLayout *main_layout = new QHBoxLayout(this);
|
||||
main_layout->setContentsMargins(11, 50, 11, 11);
|
||||
main_layout->addWidget(icon_01 = new QLabel, 0, Qt::AlignTop);
|
||||
|
||||
QWidget *right_container = new QWidget(this);
|
||||
right_container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
QVBoxLayout *layout = new QVBoxLayout(right_container);
|
||||
|
||||
layout->addWidget(distance = new QLabel);
|
||||
distance->setStyleSheet(R"(font-size: 90px;)");
|
||||
|
||||
layout->addWidget(primary = new QLabel);
|
||||
primary->setStyleSheet(R"(font-size: 60px;)");
|
||||
primary->setWordWrap(true);
|
||||
|
||||
layout->addWidget(secondary = new QLabel);
|
||||
secondary->setStyleSheet(R"(font-size: 50px;)");
|
||||
secondary->setWordWrap(true);
|
||||
|
||||
layout->addLayout(lane_layout = new QHBoxLayout);
|
||||
main_layout->addWidget(right_container);
|
||||
|
||||
setStyleSheet("color:white");
|
||||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Background, QColor(0, 0, 0, 150));
|
||||
setAutoFillBackground(true);
|
||||
setPalette(pal);
|
||||
|
||||
buildPixmapCache();
|
||||
}
|
||||
|
||||
void MapInstructions::buildPixmapCache() {
|
||||
QDir dir("../assets/navigation");
|
||||
for (QString fn : dir.entryList({"*" + ICON_SUFFIX}, QDir::Files)) {
|
||||
QPixmap pm(dir.filePath(fn));
|
||||
QString key = fn.left(fn.size() - ICON_SUFFIX.length());
|
||||
pm = pm.scaledToWidth(200, Qt::SmoothTransformation);
|
||||
|
||||
// Maneuver icons
|
||||
pixmap_cache[key] = pm;
|
||||
// lane direction icons
|
||||
if (key.contains("turn_")) {
|
||||
pixmap_cache["lane_" + key] = pm.scaled({125, 125}, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
// for rhd, reflect direction and then flip
|
||||
if (key.contains("_left")) {
|
||||
pixmap_cache["rhd_" + key.replace("_left", "_right")] = pm.transformed(QTransform().scale(-1, 1));
|
||||
} else if (key.contains("_right")) {
|
||||
pixmap_cache["rhd_" + key.replace("_right", "_left")] = pm.transformed(QTransform().scale(-1, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString MapInstructions::getDistance(float d) {
|
||||
d = std::max(d, 0.0f);
|
||||
if (uiState()->scene.is_metric) {
|
||||
return (d > 500) ? QString::number(d / 1000, 'f', 1) + tr(" km")
|
||||
: QString::number(50 * int(d / 50)) + tr(" m");
|
||||
} else {
|
||||
float feet = d * METER_TO_FOOT;
|
||||
return (feet > 500) ? QString::number(d * METER_TO_MILE, 'f', 1) + tr(" mi")
|
||||
: QString::number(50 * int(feet / 50)) + tr(" ft");
|
||||
}
|
||||
}
|
||||
|
||||
void MapInstructions::updateInstructions(cereal::NavInstruction::Reader instruction) {
|
||||
setUpdatesEnabled(false);
|
||||
|
||||
// Show instruction text
|
||||
QString primary_str = QString::fromStdString(instruction.getManeuverPrimaryText());
|
||||
QString secondary_str = QString::fromStdString(instruction.getManeuverSecondaryText());
|
||||
|
||||
primary->setText(primary_str);
|
||||
secondary->setVisible(secondary_str.length() > 0);
|
||||
secondary->setText(secondary_str);
|
||||
distance->setText(getDistance(instruction.getManeuverDistance()));
|
||||
|
||||
// Show arrow with direction
|
||||
QString type = QString::fromStdString(instruction.getManeuverType());
|
||||
QString modifier = QString::fromStdString(instruction.getManeuverModifier());
|
||||
if (!type.isEmpty()) {
|
||||
QString fn = "direction_" + type;
|
||||
if (!modifier.isEmpty()) {
|
||||
fn += "_" + modifier;
|
||||
}
|
||||
fn = fn.replace(' ', '_');
|
||||
bool rhd = is_rhd && (fn.contains("_left") || fn.contains("_right"));
|
||||
icon_01->setPixmap(pixmap_cache[!rhd ? fn : "rhd_" + fn]);
|
||||
icon_01->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
icon_01->setVisible(true);
|
||||
}
|
||||
|
||||
// Show lanes
|
||||
auto lanes = instruction.getLanes();
|
||||
for (int i = 0; i < lanes.size(); ++i) {
|
||||
bool active = lanes[i].getActive();
|
||||
|
||||
// TODO: only use active direction if active
|
||||
bool left = false, straight = false, right = false;
|
||||
for (auto const &direction: lanes[i].getDirections()) {
|
||||
left |= direction == cereal::NavInstruction::Direction::LEFT;
|
||||
right |= direction == cereal::NavInstruction::Direction::RIGHT;
|
||||
straight |= direction == cereal::NavInstruction::Direction::STRAIGHT;
|
||||
}
|
||||
|
||||
// TODO: Make more images based on active direction and combined directions
|
||||
QString fn = "lane_direction_";
|
||||
if (left) {
|
||||
fn += "turn_left";
|
||||
} else if (right) {
|
||||
fn += "turn_right";
|
||||
} else if (straight) {
|
||||
fn += "turn_straight";
|
||||
}
|
||||
|
||||
if (!active) {
|
||||
fn += "_inactive";
|
||||
}
|
||||
|
||||
QLabel *label = (i < lane_labels.size()) ? lane_labels[i] : lane_labels.emplace_back(new QLabel);
|
||||
if (!label->parentWidget()) {
|
||||
lane_layout->addWidget(label);
|
||||
}
|
||||
label->setPixmap(pixmap_cache[fn]);
|
||||
label->setVisible(true);
|
||||
}
|
||||
|
||||
for (int i = lanes.size(); i < lane_labels.size(); ++i) {
|
||||
lane_labels[i]->setVisible(false);
|
||||
}
|
||||
|
||||
setUpdatesEnabled(true);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
MapETA::MapETA(QWidget *parent) : QWidget(parent) {
|
||||
setVisible(false);
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
eta_doc.setUndoRedoEnabled(false);
|
||||
eta_doc.setDefaultStyleSheet("body {font-family:Inter;font-size:60px;color:white;} b{font-size:70px;font-weight:600}");
|
||||
}
|
||||
|
||||
void MapETA::paintEvent(QPaintEvent *event) {
|
||||
if (!eta_doc.isEmpty()) {
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(QColor(0, 0, 0, 150));
|
||||
QSizeF txt_size = eta_doc.size();
|
||||
p.drawRoundedRect((width() - txt_size.width()) / 2 - UI_BORDER_SIZE, 0, txt_size.width() + UI_BORDER_SIZE * 2, height() + 25, 25, 25);
|
||||
p.translate((width() - txt_size.width()) / 2, (height() - txt_size.height()) / 2);
|
||||
eta_doc.drawContents(&p);
|
||||
}
|
||||
}
|
||||
|
||||
void MapETA::updateETA(float s, float s_typical, float d) {
|
||||
// ETA
|
||||
auto eta_t = QDateTime::currentDateTime().addSecs(s).time();
|
||||
auto eta = format_24h ? std::array{eta_t.toString("HH:mm"), tr("eta")}
|
||||
: std::array{eta_t.toString("h:mm a").split(' ')[0], eta_t.toString("a")};
|
||||
|
||||
// Remaining time
|
||||
auto remaining = s < 3600 ? std::array{QString::number(int(s / 60)), tr("min")}
|
||||
: std::array{QString("%1:%2").arg((int)s / 3600).arg(((int)s % 3600) / 60, 2, 10, QLatin1Char('0')), tr("hr")};
|
||||
QString color = "#25DA6E";
|
||||
if (s / s_typical > 1.5) color = "#DA3025";
|
||||
else if (s / s_typical > 1.2) color = "#DAA725";
|
||||
|
||||
// Distance
|
||||
float num = uiState()->scene.is_metric ? (d / 1000.0) : (d * METER_TO_MILE);
|
||||
auto distance = std::array{QString::number(num, 'f', num < 100 ? 1 : 0),
|
||||
uiState()->scene.is_metric ? tr("km") : tr("mi")};
|
||||
|
||||
eta_doc.setHtml(QString(R"(<body><b>%1</b>%2 <span style="color:%3"><b>%4</b>%5</span> <b>%6</b>%7</body>)")
|
||||
.arg(eta[0], eta[1], color, remaining[0], remaining[1], distance[0], distance[1]));
|
||||
|
||||
setVisible(d >= MANEUVER_TRANSITION_THRESHOLD);
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#include <QGeoCoordinate>
|
||||
#include <QGestureEvent>
|
||||
#include <QHash>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QMap>
|
||||
#include <QMapboxGL>
|
||||
@@ -15,7 +13,6 @@
|
||||
#include <QPushButton>
|
||||
#include <QScopedPointer>
|
||||
#include <QString>
|
||||
#include <QTextDocument>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWheelEvent>
|
||||
|
||||
@@ -23,42 +20,8 @@
|
||||
#include "common/params.h"
|
||||
#include "common/util.h"
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
class MapInstructions : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QLabel *distance;
|
||||
QLabel *primary;
|
||||
QLabel *secondary;
|
||||
QLabel *icon_01;
|
||||
QHBoxLayout *lane_layout;
|
||||
bool is_rhd = false;
|
||||
std::vector<QLabel *> lane_labels;
|
||||
QHash<QString, QPixmap> pixmap_cache;
|
||||
|
||||
public:
|
||||
MapInstructions(QWidget * parent=nullptr);
|
||||
void buildPixmapCache();
|
||||
QString getDistance(float d);
|
||||
void updateInstructions(cereal::NavInstruction::Reader instruction);
|
||||
};
|
||||
|
||||
class MapETA : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MapETA(QWidget * parent=nullptr);
|
||||
void updateETA(float seconds, float seconds_typical, float distance);
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void showEvent(QShowEvent *event) override { format_24h = param.getBool("NavSettingTime24h"); }
|
||||
|
||||
bool format_24h = false;
|
||||
QTextDocument eta_doc;
|
||||
Params param;
|
||||
};
|
||||
#include "selfdrive/ui/qt/maps/map_eta.h"
|
||||
#include "selfdrive/ui/qt/maps/map_instructions.h"
|
||||
|
||||
class MapWindow : public QOpenGLWidget {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "selfdrive/ui/qt/maps/map_eta.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QPainter>
|
||||
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
const float MANEUVER_TRANSITION_THRESHOLD = 10;
|
||||
|
||||
MapETA::MapETA(QWidget *parent) : QWidget(parent) {
|
||||
setVisible(false);
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
eta_doc.setUndoRedoEnabled(false);
|
||||
eta_doc.setDefaultStyleSheet("body {font-family:Inter;font-size:60px;color:white;} b{font-size:70px;font-weight:600}");
|
||||
}
|
||||
|
||||
void MapETA::paintEvent(QPaintEvent *event) {
|
||||
if (!eta_doc.isEmpty()) {
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(QColor(0, 0, 0, 150));
|
||||
QSizeF txt_size = eta_doc.size();
|
||||
p.drawRoundedRect((width() - txt_size.width()) / 2 - UI_BORDER_SIZE, 0, txt_size.width() + UI_BORDER_SIZE * 2, height() + 25, 25, 25);
|
||||
p.translate((width() - txt_size.width()) / 2, (height() - txt_size.height()) / 2);
|
||||
eta_doc.drawContents(&p);
|
||||
}
|
||||
}
|
||||
|
||||
void MapETA::updateETA(float s, float s_typical, float d) {
|
||||
// ETA
|
||||
auto eta_t = QDateTime::currentDateTime().addSecs(s).time();
|
||||
auto eta = format_24h ? std::array{eta_t.toString("HH:mm"), tr("eta")}
|
||||
: std::array{eta_t.toString("h:mm a").split(' ')[0], eta_t.toString("a")};
|
||||
|
||||
// Remaining time
|
||||
auto remaining = s < 3600 ? std::array{QString::number(int(s / 60)), tr("min")}
|
||||
: std::array{QString("%1:%2").arg((int)s / 3600).arg(((int)s % 3600) / 60, 2, 10, QLatin1Char('0')), tr("hr")};
|
||||
QString color = "#25DA6E";
|
||||
if (s / s_typical > 1.5)
|
||||
color = "#DA3025";
|
||||
else if (s / s_typical > 1.2)
|
||||
color = "#DAA725";
|
||||
|
||||
// Distance
|
||||
float num = uiState()->scene.is_metric ? (d / 1000.0) : (d * METER_TO_MILE);
|
||||
auto distance = std::array{QString::number(num, 'f', num < 100 ? 1 : 0),
|
||||
uiState()->scene.is_metric ? tr("km") : tr("mi")};
|
||||
|
||||
eta_doc.setHtml(QString(R"(<body><b>%1</b>%2 <span style="color:%3"><b>%4</b>%5</span> <b>%6</b>%7</body>)")
|
||||
.arg(eta[0], eta[1], color, remaining[0], remaining[1], distance[0], distance[1]));
|
||||
|
||||
setVisible(d >= MANEUVER_TRANSITION_THRESHOLD);
|
||||
update();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <QPaintEvent>
|
||||
#include <QTextDocument>
|
||||
#include <QWidget>
|
||||
|
||||
#include "common/params.h"
|
||||
|
||||
class MapETA : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MapETA(QWidget * parent=nullptr);
|
||||
void updateETA(float seconds, float seconds_typical, float distance);
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void showEvent(QShowEvent *event) override { format_24h = param.getBool("NavSettingTime24h"); }
|
||||
|
||||
bool format_24h = false;
|
||||
QTextDocument eta_doc;
|
||||
Params param;
|
||||
};
|
||||
@@ -0,0 +1,146 @@
|
||||
#include "selfdrive/ui/qt/maps/map_instructions.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
const QString ICON_SUFFIX = ".png";
|
||||
|
||||
MapInstructions::MapInstructions(QWidget *parent) : QWidget(parent) {
|
||||
is_rhd = Params().getBool("IsRhdDetected");
|
||||
QHBoxLayout *main_layout = new QHBoxLayout(this);
|
||||
main_layout->setContentsMargins(11, 50, 11, 11);
|
||||
main_layout->addWidget(icon_01 = new QLabel, 0, Qt::AlignTop);
|
||||
|
||||
QWidget *right_container = new QWidget(this);
|
||||
right_container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
QVBoxLayout *layout = new QVBoxLayout(right_container);
|
||||
|
||||
layout->addWidget(distance = new QLabel);
|
||||
distance->setStyleSheet(R"(font-size: 90px;)");
|
||||
|
||||
layout->addWidget(primary = new QLabel);
|
||||
primary->setStyleSheet(R"(font-size: 60px;)");
|
||||
primary->setWordWrap(true);
|
||||
|
||||
layout->addWidget(secondary = new QLabel);
|
||||
secondary->setStyleSheet(R"(font-size: 50px;)");
|
||||
secondary->setWordWrap(true);
|
||||
|
||||
layout->addLayout(lane_layout = new QHBoxLayout);
|
||||
main_layout->addWidget(right_container);
|
||||
|
||||
setStyleSheet("color:white");
|
||||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Background, QColor(0, 0, 0, 150));
|
||||
setAutoFillBackground(true);
|
||||
setPalette(pal);
|
||||
|
||||
buildPixmapCache();
|
||||
}
|
||||
|
||||
void MapInstructions::buildPixmapCache() {
|
||||
QDir dir("../assets/navigation");
|
||||
for (QString fn : dir.entryList({"*" + ICON_SUFFIX}, QDir::Files)) {
|
||||
QPixmap pm(dir.filePath(fn));
|
||||
QString key = fn.left(fn.size() - ICON_SUFFIX.length());
|
||||
pm = pm.scaledToWidth(200, Qt::SmoothTransformation);
|
||||
|
||||
// Maneuver icons
|
||||
pixmap_cache[key] = pm;
|
||||
// lane direction icons
|
||||
if (key.contains("turn_")) {
|
||||
pixmap_cache["lane_" + key] = pm.scaled({125, 125}, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
// for rhd, reflect direction and then flip
|
||||
if (key.contains("_left")) {
|
||||
pixmap_cache["rhd_" + key.replace("_left", "_right")] = pm.transformed(QTransform().scale(-1, 1));
|
||||
} else if (key.contains("_right")) {
|
||||
pixmap_cache["rhd_" + key.replace("_right", "_left")] = pm.transformed(QTransform().scale(-1, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString MapInstructions::getDistance(float d) {
|
||||
d = std::max(d, 0.0f);
|
||||
if (uiState()->scene.is_metric) {
|
||||
return (d > 500) ? QString::number(d / 1000, 'f', 1) + tr(" km")
|
||||
: QString::number(50 * int(d / 50)) + tr(" m");
|
||||
} else {
|
||||
float feet = d * METER_TO_FOOT;
|
||||
return (feet > 500) ? QString::number(d * METER_TO_MILE, 'f', 1) + tr(" mi")
|
||||
: QString::number(50 * int(feet / 50)) + tr(" ft");
|
||||
}
|
||||
}
|
||||
|
||||
void MapInstructions::updateInstructions(cereal::NavInstruction::Reader instruction) {
|
||||
setUpdatesEnabled(false);
|
||||
|
||||
// Show instruction text
|
||||
QString primary_str = QString::fromStdString(instruction.getManeuverPrimaryText());
|
||||
QString secondary_str = QString::fromStdString(instruction.getManeuverSecondaryText());
|
||||
|
||||
primary->setText(primary_str);
|
||||
secondary->setVisible(secondary_str.length() > 0);
|
||||
secondary->setText(secondary_str);
|
||||
distance->setText(getDistance(instruction.getManeuverDistance()));
|
||||
|
||||
// Show arrow with direction
|
||||
QString type = QString::fromStdString(instruction.getManeuverType());
|
||||
QString modifier = QString::fromStdString(instruction.getManeuverModifier());
|
||||
if (!type.isEmpty()) {
|
||||
QString fn = "direction_" + type;
|
||||
if (!modifier.isEmpty()) {
|
||||
fn += "_" + modifier;
|
||||
}
|
||||
fn = fn.replace(' ', '_');
|
||||
bool rhd = is_rhd && (fn.contains("_left") || fn.contains("_right"));
|
||||
icon_01->setPixmap(pixmap_cache[!rhd ? fn : "rhd_" + fn]);
|
||||
icon_01->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
icon_01->setVisible(true);
|
||||
}
|
||||
|
||||
// Show lanes
|
||||
auto lanes = instruction.getLanes();
|
||||
for (int i = 0; i < lanes.size(); ++i) {
|
||||
bool active = lanes[i].getActive();
|
||||
|
||||
// TODO: only use active direction if active
|
||||
bool left = false, straight = false, right = false;
|
||||
for (auto const &direction : lanes[i].getDirections()) {
|
||||
left |= direction == cereal::NavInstruction::Direction::LEFT;
|
||||
right |= direction == cereal::NavInstruction::Direction::RIGHT;
|
||||
straight |= direction == cereal::NavInstruction::Direction::STRAIGHT;
|
||||
}
|
||||
|
||||
// TODO: Make more images based on active direction and combined directions
|
||||
QString fn = "lane_direction_";
|
||||
if (left) {
|
||||
fn += "turn_left";
|
||||
} else if (right) {
|
||||
fn += "turn_right";
|
||||
} else if (straight) {
|
||||
fn += "turn_straight";
|
||||
}
|
||||
|
||||
if (!active) {
|
||||
fn += "_inactive";
|
||||
}
|
||||
|
||||
QLabel *label = (i < lane_labels.size()) ? lane_labels[i] : lane_labels.emplace_back(new QLabel);
|
||||
if (!label->parentWidget()) {
|
||||
lane_layout->addWidget(label);
|
||||
}
|
||||
label->setPixmap(pixmap_cache[fn]);
|
||||
label->setVisible(true);
|
||||
}
|
||||
|
||||
for (int i = lanes.size(); i < lane_labels.size(); ++i) {
|
||||
lane_labels[i]->setVisible(false);
|
||||
}
|
||||
|
||||
setUpdatesEnabled(true);
|
||||
setVisible(true);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <QHash>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
|
||||
#include "cereal/gen/cpp/log.capnp.h"
|
||||
|
||||
class MapInstructions : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QLabel *distance;
|
||||
QLabel *primary;
|
||||
QLabel *secondary;
|
||||
QLabel *icon_01;
|
||||
QHBoxLayout *lane_layout;
|
||||
bool is_rhd = false;
|
||||
std::vector<QLabel *> lane_labels;
|
||||
QHash<QString, QPixmap> pixmap_cache;
|
||||
|
||||
public:
|
||||
MapInstructions(QWidget * parent=nullptr);
|
||||
void buildPixmapCache();
|
||||
QString getDistance(float d);
|
||||
void updateInstructions(cereal::NavInstruction::Reader instruction);
|
||||
};
|
||||
Reference in New Issue
Block a user