Qt: draw border in OnroadWindow (#21594)

* draw border in OnroadAlerts

* non transparent

* no scissor

* set video_rect to the full size

* fix header gradient

* Revert "fix header gradient"

This reverts commit f5565c19d5cabda22fe6b60af23dc26727ecd5bc.

* Revert "set video_rect to the full size"

This reverts commit c012db105a8cabd140971208431d83ae3592b70e.

* fix scissor

* fix header gradient

* set scissor box to video_rect when draw lines

* move up eta

* init alert_size to NONE

* remove glScissor

* cleanup

* rename draw_video_frame to draw_vision_frame

* remove space

* add comment

* move border to OnroadWindow

* cleanup signals

* fw declare MapWindow

* fix build err

* remove viz_rect

* fix build err

* continue

* cleanup

* text rect:no border

* use signals

* remove space

cleanup

* merge master

* fix map eta

* get bgColor from alerts

* update alerts in OnroadWindow

* add function clearAlert

* repaint border

* init bg color to STATUS_DISENGAGED

* no black frame

* cleanup

Co-authored-by: Willem Melching <willem.melching@gmail.com>
Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
pull/21704/head
Dean Lee 4 years ago committed by GitHub
parent ff573e8c4a
commit f0389f7e2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 76
      selfdrive/ui/paint.cc
  2. 2
      selfdrive/ui/qt/home.cc
  3. 4
      selfdrive/ui/qt/maps/map.cc
  4. 94
      selfdrive/ui/qt/onroad.cc
  5. 20
      selfdrive/ui/qt/onroad.h
  6. 1
      selfdrive/ui/ui.h

@ -85,8 +85,8 @@ static void draw_lead(UIState *s, const cereal::RadarState::LeadData::Reader &le
}
float sz = std::clamp((25 * 30) / (d_rel / 3 + 30), 15.0f, 30.0f) * 2.35;
x = std::clamp(x, 0.f, s->viz_rect.right() - sz / 2);
y = std::fmin(s->viz_rect.bottom() - sz * .6, y);
x = std::clamp(x, 0.f, s->fb_w - sz / 2);
y = std::fmin(s->fb_h - sz * .6, y);
draw_chevron(s, x, y, sz, nvgRGBA(201, 34, 49, fillAlpha), COLOR_YELLOW);
}
@ -108,7 +108,7 @@ static void ui_draw_line(UIState *s, const line_vertices_data &vd, NVGcolor *col
nvgFill(s->vg);
}
static void draw_frame(UIState *s) {
static void draw_vision_frame(UIState *s) {
glBindVertexArray(s->frame_vao);
mat4 *out_mat = &s->rear_frame_mat;
glActiveTexture(GL_TEXTURE0);
@ -160,8 +160,7 @@ static void ui_draw_vision_lane_lines(UIState *s) {
// Draw all world space objects.
static void ui_draw_world(UIState *s) {
// Don't draw on top of sidebar
nvgScissor(s->vg, s->viz_rect.x, s->viz_rect.y, s->viz_rect.w, s->viz_rect.h);
nvgScissor(s->vg, 0, 0, s->fb_w, s->fb_h);
// Draw lane edges and vision/mpc tracks
ui_draw_vision_lane_lines(s);
@ -187,17 +186,17 @@ static void ui_draw_vision_maxspeed(UIState *s) {
const bool is_cruise_set = maxspeed != 0 && maxspeed != SET_SPEED_NA;
if (is_cruise_set && !s->scene.is_metric) { maxspeed *= 0.6225; }
const Rect rect = {s->viz_rect.x + (bdr_s * 2), int(s->viz_rect.y + (bdr_s * 1.5)), 184, 202};
const Rect rect = {bdr_s * 2, int(bdr_s * 1.5), 184, 202};
ui_fill_rect(s->vg, rect, COLOR_BLACK_ALPHA(100), 30.);
ui_draw_rect(s->vg, rect, COLOR_WHITE_ALPHA(100), 10, 20.);
nvgTextAlign(s->vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
ui_draw_text(s, rect.centerX(), 148, "MAX", 26 * 2.5, COLOR_WHITE_ALPHA(is_cruise_set ? 200 : 100), "sans-regular");
ui_draw_text(s, rect.centerX(), 118, "MAX", 26 * 2.5, COLOR_WHITE_ALPHA(is_cruise_set ? 200 : 100), "sans-regular");
if (is_cruise_set) {
const std::string maxspeed_str = std::to_string((int)std::nearbyint(maxspeed));
ui_draw_text(s, rect.centerX(), 242, maxspeed_str.c_str(), 48 * 2.5, COLOR_WHITE, "sans-bold");
ui_draw_text(s, rect.centerX(), 212, maxspeed_str.c_str(), 48 * 2.5, COLOR_WHITE, "sans-bold");
} else {
ui_draw_text(s, rect.centerX(), 242, "N/A", 42 * 2.5, COLOR_WHITE_ALPHA(100), "sans-semibold");
ui_draw_text(s, rect.centerX(), 212, "N/A", 42 * 2.5, COLOR_WHITE_ALPHA(100), "sans-semibold");
}
}
@ -205,16 +204,16 @@ static void ui_draw_vision_speed(UIState *s) {
const float speed = std::max(0.0, (*s->sm)["carState"].getCarState().getVEgo() * (s->scene.is_metric ? 3.6 : 2.2369363));
const std::string speed_str = std::to_string((int)std::nearbyint(speed));
nvgTextAlign(s->vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
ui_draw_text(s, s->viz_rect.centerX(), 240, speed_str.c_str(), 96 * 2.5, COLOR_WHITE, "sans-bold");
ui_draw_text(s, s->viz_rect.centerX(), 320, s->scene.is_metric ? "km/h" : "mph", 36 * 2.5, COLOR_WHITE_ALPHA(200), "sans-regular");
ui_draw_text(s, s->fb_w/2, 210, speed_str.c_str(), 96 * 2.5, COLOR_WHITE, "sans-bold");
ui_draw_text(s, s->fb_w/2, 290, s->scene.is_metric ? "km/h" : "mph", 36 * 2.5, COLOR_WHITE_ALPHA(200), "sans-regular");
}
static void ui_draw_vision_event(UIState *s) {
if (s->scene.engageable) {
// draw steering wheel
const int radius = 96;
const int center_x = s->viz_rect.right() - radius - bdr_s * 2;
const int center_y = s->viz_rect.y + radius + (bdr_s * 1.5);
const int center_x = s->fb_w - radius - bdr_s * 2;
const int center_y = radius + (bdr_s * 1.5);
const QColor &color = bg_colors[s->status];
NVGcolor nvg_color = nvgRGBA(color.red(), color.green(), color.blue(), color.alpha());
ui_draw_circle_image(s, center_x, center_y, radius, "wheel", nvg_color, 1.0f);
@ -223,35 +222,20 @@ static void ui_draw_vision_event(UIState *s) {
static void ui_draw_vision_face(UIState *s) {
const int radius = 96;
const int center_x = s->viz_rect.x + radius + (bdr_s * 2);
const int center_y = s->viz_rect.bottom() - footer_h / 2;
const int center_x = radius + (bdr_s * 2);
const int center_y = s->fb_h - footer_h / 2;
ui_draw_circle_image(s, center_x, center_y, radius, "driver_face", s->scene.dm_active);
}
static void ui_draw_vision_header(UIState *s) {
NVGpaint gradient = nvgLinearGradient(s->vg, s->viz_rect.x,
s->viz_rect.y+(header_h-(header_h/2.5)),
s->viz_rect.x, s->viz_rect.y+header_h,
NVGpaint gradient = nvgLinearGradient(s->vg, 0, header_h - (header_h / 2.5), 0, header_h,
nvgRGBAf(0, 0, 0, 0.45), nvgRGBAf(0, 0, 0, 0));
ui_fill_rect(s->vg, {s->viz_rect.x, s->viz_rect.y, s->viz_rect.w, header_h}, gradient);
ui_fill_rect(s->vg, {0, 0, s->fb_w , header_h}, gradient);
ui_draw_vision_maxspeed(s);
ui_draw_vision_speed(s);
ui_draw_vision_event(s);
}
static void ui_draw_vision_frame(UIState *s) {
// Draw video frames
glEnable(GL_SCISSOR_TEST);
glViewport(s->video_rect.x, s->video_rect.y, s->video_rect.w, s->video_rect.h);
glScissor(s->viz_rect.x, s->viz_rect.y, s->viz_rect.w, s->viz_rect.h);
draw_frame(s);
glDisable(GL_SCISSOR_TEST);
glViewport(0, 0, s->fb_w, s->fb_h);
}
static void ui_draw_vision(UIState *s) {
const UIScene *scene = &s->scene;
// Draw augmented elements
@ -265,33 +249,20 @@ static void ui_draw_vision(UIState *s) {
}
}
static void ui_draw_background(UIState *s) {
const QColor &color = bg_colors[s->status];
glClearColor(color.redF(), color.greenF(), color.blueF(), 1.0);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
}
void ui_draw(UIState *s, int w, int h) {
s->viz_rect = Rect{bdr_s, bdr_s, w - 2 * bdr_s, h - 2 * bdr_s};
const bool draw_vision = s->scene.started && s->vipc_client->connected;
// GL drawing functions
ui_draw_background(s);
glViewport(0, 0, s->fb_w, s->fb_h);
if (draw_vision) {
ui_draw_vision_frame(s);
draw_vision_frame(s);
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glViewport(0, 0, s->fb_w, s->fb_h);
// NVG drawing functions - should be no GL inside NVG frame
nvgBeginFrame(s->vg, s->fb_w, s->fb_h, 1.0f);
if (draw_vision) {
ui_draw_vision(s);
}
nvgEndFrame(s->vg);
glDisable(GL_BLEND);
}
@ -446,13 +417,12 @@ void ui_resize(UIState *s, int width, int height) {
zoom *= 0.5;
}
s->video_rect = Rect{bdr_s, bdr_s, s->fb_w - 2 * bdr_s, s->fb_h - 2 * bdr_s};
float zx = zoom * 2 * intrinsic_matrix.v[2] / s->video_rect.w;
float zy = zoom * 2 * intrinsic_matrix.v[5] / s->video_rect.h;
float zx = zoom * 2 * intrinsic_matrix.v[2] / width;
float zy = zoom * 2 * intrinsic_matrix.v[5] / height;
const mat4 frame_transform = {{
zx, 0.0, 0.0, 0.0,
0.0, zy, 0.0, -y_offset / s->video_rect.h * 2,
0.0, zy, 0.0, -y_offset / height * 2,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
}};
@ -461,11 +431,9 @@ void ui_resize(UIState *s, int width, int height) {
// Apply transformation such that video pixel coordinates match video
// 1) Put (0, 0) in the middle of the video
nvgTranslate(s->vg, s->video_rect.x + s->video_rect.w / 2, s->video_rect.y + s->video_rect.h / 2 + y_offset);
nvgTranslate(s->vg, width / 2, height / 2 + y_offset);
// 2) Apply same scaling as video
nvgScale(s->vg, zoom, zoom);
// 3) Put (0, 0) in top left corner of video
nvgTranslate(s->vg, -intrinsic_matrix.v[2], -intrinsic_matrix.v[5]);

@ -31,7 +31,7 @@ HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) {
onroad = new OnroadWindow(this);
slayout->addWidget(onroad);
QObject::connect(this, &HomeWindow::update, onroad, &OnroadWindow::update);
QObject::connect(this, &HomeWindow::update, onroad, &OnroadWindow::updateStateSignal);
QObject::connect(this, &HomeWindow::offroadTransitionSignal, onroad, &OnroadWindow::offroadTransitionSignal);
driver_view = new DriverViewWindow(this);

@ -46,7 +46,7 @@ MapWindow::MapWindow(const QMapboxGLSettings &settings) :
const int h = 120;
map_eta->setFixedHeight(h);
map_eta->move(25, 1080 - h);
map_eta->move(25, 1080 - h - bdr_s*2);
map_eta->setVisible(false);
// Routing
@ -807,5 +807,5 @@ void MapETA::updateETA(float s, float s_typical, float d) {
setMask(mask);
// Center
move(static_cast<QWidget*>(parent())->width() / 2 - width() / 2, 1080 - height());
move(static_cast<QWidget*>(parent())->width() / 2 - width() / 2, 1080 - height() - bdr_s*2);
}

@ -7,18 +7,20 @@
#include "selfdrive/common/timing.h"
#include "selfdrive/ui/paint.h"
#include "selfdrive/ui/qt/util.h"
#ifdef ENABLE_MAPS
#include "selfdrive/ui/qt/maps/map.h"
#endif
OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) {
main_layout = new QStackedLayout(this);
main_layout->setStackingMode(QStackedLayout::StackAll);
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setMargin(bdr_s);
QStackedLayout *stacked_layout = new QStackedLayout;
stacked_layout->setStackingMode(QStackedLayout::StackAll);
main_layout->addLayout(stacked_layout);
// old UI on bottom
nvg = new NvgWindow(this);
QObject::connect(this, &OnroadWindow::update, nvg, &NvgWindow::update);
QObject::connect(this, &OnroadWindow::updateStateSignal, nvg, &NvgWindow::updateState);
QWidget * split_wrapper = new QWidget;
split = new QHBoxLayout(split_wrapper);
@ -26,21 +28,46 @@ OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) {
split->setSpacing(0);
split->addWidget(nvg);
main_layout->addWidget(split_wrapper);
stacked_layout->addWidget(split_wrapper);
alerts = new OnroadAlerts(this);
alerts->setAttribute(Qt::WA_TransparentForMouseEvents, true);
QObject::connect(this, &OnroadWindow::update, alerts, &OnroadAlerts::updateState);
QObject::connect(this, &OnroadWindow::offroadTransitionSignal, alerts, &OnroadAlerts::offroadTransition);
QObject::connect(this, &OnroadWindow::offroadTransitionSignal, this, &OnroadWindow::offroadTransition);
main_layout->addWidget(alerts);
stacked_layout->addWidget(alerts);
// setup stacking order
alerts->raise();
setAttribute(Qt::WA_OpaquePaintEvent);
QObject::connect(this, &OnroadWindow::updateStateSignal, this, &OnroadWindow::updateState);
QObject::connect(this, &OnroadWindow::offroadTransitionSignal, this, &OnroadWindow::offroadTransition);
}
void OnroadWindow::updateState(const UIState &s) {
SubMaster &sm = *(s.sm);
QColor bgColor = bg_colors[s.status];
if (sm.updated("controlsState")) {
const cereal::ControlsState::Reader &cs = sm["controlsState"].getControlsState();
alerts->updateAlert({QString::fromStdString(cs.getAlertText1()),
QString::fromStdString(cs.getAlertText2()),
QString::fromStdString(cs.getAlertType()),
cs.getAlertSize(), cs.getAlertSound()}, bgColor);
} else if ((sm.frame - s.scene.started_frame) > 5 * UI_FREQ) {
// Handle controls timeout
if (sm.rcv_frame("controlsState") < s.scene.started_frame) {
// car is started, but controlsState hasn't been seen at all
alerts->updateAlert(CONTROLS_WAITING_ALERT, bgColor);
} else if ((nanos_since_boot() - sm.rcv_time("controlsState")) / 1e9 > CONTROLS_TIMEOUT) {
// car is started, but controls is lagging or died
bgColor = bg_colors[STATUS_ALERT];
alerts->updateAlert(CONTROLS_UNRESPONSIVE_ALERT, bgColor);
}
}
if (bg != bgColor) {
// repaint border
bg = bgColor;
update();
}
}
void OnroadWindow::offroadTransition(bool offroad) {
#ifdef ENABLE_MAPS
@ -57,50 +84,25 @@ void OnroadWindow::offroadTransition(bool offroad) {
MapWindow * m = new MapWindow(settings);
QObject::connect(this, &OnroadWindow::offroadTransitionSignal, m, &MapWindow::offroadTransition);
split->addWidget(m);
map = m;
}
}
#endif
}
// ***** onroad widgets *****
void OnroadAlerts::updateState(const UIState &s) {
SubMaster &sm = *(s.sm);
if (sm["deviceState"].getDeviceState().getStarted()) {
if (sm.updated("controlsState")) {
const cereal::ControlsState::Reader &cs = sm["controlsState"].getControlsState();
updateAlert({QString::fromStdString(cs.getAlertText1()),
QString::fromStdString(cs.getAlertText2()),
QString::fromStdString(cs.getAlertType()),
cs.getAlertSize(), cs.getAlertSound()});
} else if ((sm.frame - s.scene.started_frame) > 10 * UI_FREQ) {
// Handle controls timeout
if (sm.rcv_frame("controlsState") < s.scene.started_frame) {
// car is started, but controlsState hasn't been seen at all
updateAlert(CONTROLS_WAITING_ALERT);
} else if ((nanos_since_boot() - sm.rcv_time("controlsState")) / 1e9 > CONTROLS_TIMEOUT) {
// car is started, but controls is lagging or died
updateAlert(CONTROLS_UNRESPONSIVE_ALERT);
// TODO: clean this up once Qt handles the border
QUIState::ui_state.status = STATUS_ALERT;
}
}
alerts->updateAlert({}, bg);
}
bg = bg_colors[s.status];
void OnroadWindow::paintEvent(QPaintEvent *event) {
QPainter p(this);
p.fillRect(rect(), QColor(bg.red(), bg.green(), bg.blue(), 255));
}
void OnroadAlerts::offroadTransition(bool offroad) {
updateAlert({});
}
// ***** onroad widgets *****
void OnroadAlerts::updateAlert(Alert a) {
if (!alert.equal(a)) {
void OnroadAlerts::updateAlert(const Alert &a, const QColor &color) {
if (!alert.equal(a) || color != bg) {
alert = a;
bg = color;
update();
}
}
@ -135,9 +137,6 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) {
p.fillRect(r, g);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
// remove bottom border
r = QRect(0, height() - h, width(), h - 30);
// text
const QPoint c = r.center();
p.setPen(QColor(0xff, 0xff, 0xff));
@ -180,11 +179,14 @@ void NvgWindow::initializeGL() {
prev_draw_t = millis_since_boot();
}
void NvgWindow::update(const UIState &s) {
void NvgWindow::updateState(const UIState &s) {
// Connecting to visionIPC requires opengl to be current
if (s.vipc_client->connected) {
makeCurrent();
}
if (isVisible() != s.vipc_client->connected) {
setVisible(s.vipc_client->connected);
}
repaint();
}

@ -17,20 +17,15 @@ class OnroadAlerts : public QWidget {
Q_OBJECT
public:
OnroadAlerts(QWidget *parent = 0) {};
OnroadAlerts(QWidget *parent = 0) : QWidget(parent) {};
void updateAlert(const Alert &a, const QColor &color);
protected:
void paintEvent(QPaintEvent*) override;
private:
QColor bg;
Alert alert;
void updateAlert(Alert a);
public slots:
void updateState(const UIState &s);
void offroadTransition(bool offroad);
Alert alert = {};
};
// container window for the NVG UI
@ -51,7 +46,7 @@ private:
double prev_draw_t = 0;
public slots:
void update(const UIState &s);
void updateState(const UIState &s);
};
// container for all onroad widgets
@ -63,15 +58,18 @@ public:
QWidget *map = nullptr;
private:
void paintEvent(QPaintEvent *event);
OnroadAlerts *alerts;
NvgWindow *nvg;
QStackedLayout *main_layout;
QColor bg = bg_colors[STATUS_DISENGAGED];
QHBoxLayout* split;
signals:
void update(const UIState &s);
void updateStateSignal(const UIState &s);
void offroadTransitionSignal(bool offroad);
private slots:
void offroadTransition(bool offroad);
void updateState(const UIState &s);
};

@ -151,7 +151,6 @@ typedef struct UIState {
bool awake;
Rect video_rect, viz_rect;
float car_space_transform[6];
bool wide_camera;
} UIState;

Loading…
Cancel
Save