ui: resizable on PC by mouse drag

pull/22831/head
kernyan 4 years ago
parent 53e095343d
commit 56aa8254a2
  1. 2
      selfdrive/hardware/hw.h
  2. 62
      selfdrive/ui/paint.cc
  3. 6
      selfdrive/ui/qt/offroad/driverview.cc
  4. 85
      selfdrive/ui/qt/onroad.cc
  5. 9
      selfdrive/ui/qt/qt_window.cc
  6. 4
      selfdrive/ui/qt/sidebar.cc
  7. 26
      selfdrive/ui/qt/util.cc
  8. 2
      selfdrive/ui/qt/util.h

@ -13,7 +13,7 @@
class HardwarePC : public HardwareNone {
public:
static std::string get_os_version() { return "openpilot for PC"; }
static bool PC() { return true; }
static constexpr bool PC() { return true; }
static bool TICI() { return util::getenv("TICI", 0) == 1; }
};
#define Hardware HardwarePC

@ -151,72 +151,86 @@ static void ui_draw_world(UIState *s) {
nvgResetScissor(s->vg);
}
static void ui_draw_vision_maxspeed(UIState *s) {
static void ui_draw_vision_maxspeed(UIState *s, const float ratio) {
const int SET_SPEED_NA = 255;
float maxspeed = (*s->sm)["controlsState"].getControlsState().getVCruise();
const bool is_cruise_set = maxspeed != 0 && maxspeed != SET_SPEED_NA;
if (is_cruise_set && !s->scene.is_metric) { maxspeed *= KM_TO_MILE; }
const Rect rect = {bdr_s * 2, int(bdr_s * 1.5), 184, 202};
const Rect rect = {int(bdr_s * 2 * ratio), int(bdr_s * 1.5 * ratio),
int(184 * ratio), int(202 * ratio)};
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(), 118, "MAX", 26 * 2.5, COLOR_WHITE_ALPHA(is_cruise_set ? 200 : 100), "sans-regular");
ui_draw_text(s, rect.centerX(), 118 * ratio, "MAX",
26 * 2.5 * ratio, 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(), 212, maxspeed_str.c_str(), 48 * 2.5, COLOR_WHITE, "sans-bold");
ui_draw_text(s, rect.centerX(), 212 * ratio, maxspeed_str.c_str(),
48 * 2.5 * ratio, COLOR_WHITE, "sans-bold");
} else {
ui_draw_text(s, rect.centerX(), 212, "N/A", 42 * 2.5, COLOR_WHITE_ALPHA(100), "sans-semibold");
ui_draw_text(s, rect.centerX(), 212 * ratio, "N/A",
42 * 2.5 * ratio, COLOR_WHITE_ALPHA(100), "sans-semibold");
}
}
static void ui_draw_vision_speed(UIState *s) {
static void ui_draw_vision_speed(UIState *s, const float ratio) {
const float speed = std::max(0.0, (*s->sm)["carState"].getCarState().getVEgo() * (s->scene.is_metric ? MS_TO_KPH : MS_TO_MPH));
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->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");
ui_draw_text(s, s->fb_w/2, 210 * ratio, speed_str.c_str(),
96 * 2.5 * ratio, COLOR_WHITE, "sans-bold");
ui_draw_text(s, s->fb_w/2, 290 * ratio, s->scene.is_metric ? "km/h" : "mph",
36 * 2.5 * ratio, COLOR_WHITE_ALPHA(200), "sans-regular");
}
static void ui_draw_vision_event(UIState *s) {
static void ui_draw_vision_event(UIState *s, const float ratio) {
if (s->scene.engageable) {
// draw steering wheel
const int radius = 96;
const int center_x = s->fb_w - radius - bdr_s * 2;
const int center_y = radius + (bdr_s * 1.5);
const int radius = 96 * ratio;
const int center_x = s->fb_w - radius - (bdr_s * ratio* 2);
const int center_y = radius + (bdr_s * ratio * 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);
}
}
static void ui_draw_vision_face(UIState *s) {
const int radius = 96;
const int center_x = radius + (bdr_s * 2);
const int center_y = s->fb_h - footer_h / 2;
static void ui_draw_vision_face(UIState *s, const float ratio) {
const int radius = 96 * ratio;
const int center_x = radius + (bdr_s * ratio * 2);
const int center_y = s->fb_h - (footer_h * ratio / 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) {
static void ui_draw_vision_header(UIState *s, const float ratio) {
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, {0, 0, s->fb_w , header_h}, gradient);
ui_draw_vision_maxspeed(s);
ui_draw_vision_speed(s);
ui_draw_vision_event(s);
ui_draw_vision_maxspeed(s, ratio);
ui_draw_vision_speed(s, ratio);
ui_draw_vision_event(s, ratio);
}
static void ui_draw_vision(UIState *s) {
static void ui_draw_vision(UIState *s, const float ratio) {
const UIScene *scene = &s->scene;
// Draw augmented elements
if (scene->world_objects_visible) {
ui_draw_world(s);
}
// Set Speed, Current Speed, Status/Events
ui_draw_vision_header(s);
ui_draw_vision_header(s, ratio);
if ((*s->sm)["controlsState"].getControlsState().getAlertSize() == cereal::ControlsState::AlertSize::NONE) {
ui_draw_vision_face(s);
ui_draw_vision_face(s, ratio);
}
}
inline float resize_ratio(int w, int h) {
if constexpr (Hardware::PC()) {
return std::min<int>(w, h) / 1080.0; // 1080 is min of default 1920 x 1080
} else {
return 1.0;
}
}
@ -228,7 +242,7 @@ void ui_draw(UIState *s, int w, int h) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
nvgBeginFrame(s->vg, s->fb_w, s->fb_h, 1.0f);
ui_draw_vision(s);
ui_draw_vision(s, resize_ratio(w, h));
nvgEndFrame(s->vg);
glDisable(GL_BLEND);
}

@ -52,8 +52,10 @@ void DriverViewScene::paintEvent(QPaintEvent* event) {
if (!frame_updated) {
p.setPen(Qt::white);
p.setRenderHint(QPainter::TextAntialiasing);
configFont(p, "Inter", 100, "Bold");
p.drawText(geometry(), Qt::AlignCenter, "camera starting");
const QRect r(geometry());
const QString text("camera starting");
configFont(p, r, "Inter", 100, "Bold", text);
p.drawText(geometry(), Qt::AlignCenter, text);
return;
}

@ -122,18 +122,60 @@ void OnroadAlerts::updateAlert(const Alert &a, const QColor &color) {
}
}
struct Rects
{
int x, y, w, h; // bounding box for total text area
int x1, y1, w1, h1; // bounding box for alert text 1
int x2, y2, w2, h2; // bounding box for alert text 2
Rects()
{
memset(this, 0, sizeof(Rects));
}
};
template<typename T>
void getRects(T t, Rects &r, Alert alert) {
// returns bounding boxes for text area, alert1, alert2
// w - width, h - height, windows starting position x, y
const int heightMax = 1080; // adjust to change text box scale
const int width = t->width();
const int height = t->height();
switch (alert.size) {
case cereal::ControlsState::AlertSize::SMALL:
r.h = height * (271.0 / heightMax);
break;
case cereal::ControlsState::AlertSize::MID:
r.h = height * (420.0 / heightMax);
break;
case cereal::ControlsState::AlertSize::FULL:
r.h = height;
break;
case cereal::ControlsState::AlertSize::NONE:
break;
}
r.w = width;
r.w1 = r.w;
r.w2 = r.w1;
r.h1 = r.h / 2.0;
r.h2 = r.h1;
r.y = height - r.h;
r.y1 = r.y;
r.y2 = r.y1 + r.h1;
}
void OnroadAlerts::paintEvent(QPaintEvent *event) {
if (alert.size == cereal::ControlsState::AlertSize::NONE) {
return;
}
static std::map<cereal::ControlsState::AlertSize, const int> alert_sizes = {
{cereal::ControlsState::AlertSize::SMALL, 271},
{cereal::ControlsState::AlertSize::MID, 420},
{cereal::ControlsState::AlertSize::FULL, height()},
};
int h = alert_sizes[alert.size];
QRect r = QRect(0, height() - h, width(), h);
Rects R;
getRects(this, R, alert);
QRect r = QRect(R.x, R.y, R.w, R.h);
QPainter p(this);
// draw background + gradient
@ -153,23 +195,28 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) {
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
// text
const QPoint c = r.center();
p.setPen(QColor(0xff, 0xff, 0xff));
p.setRenderHint(QPainter::TextAntialiasing);
const QRect a1 = QRect(R.x1, R.y1, R.w1, R.h1);
const QRect a2 = QRect(R.x2, R.y2, R.w2, R.h2);
const int textBoxFlag = Qt::AlignCenter;
if (alert.size == cereal::ControlsState::AlertSize::SMALL) {
configFont(p, "Open Sans", 74, "SemiBold");
p.drawText(r, Qt::AlignCenter, alert.text1);
configFont(p, r, "Open Sans", 74, "SemiBold", alert.text1);
p.drawText(r, textBoxFlag, alert.text1);
} else if (alert.size == cereal::ControlsState::AlertSize::MID) {
configFont(p, "Open Sans", 88, "Bold");
p.drawText(QRect(0, c.y() - 125, width(), 150), Qt::AlignHCenter | Qt::AlignTop, alert.text1);
configFont(p, "Open Sans", 66, "Regular");
p.drawText(QRect(0, c.y() + 21, width(), 90), Qt::AlignHCenter, alert.text2);
configFont(p, a1, "Open Sans", 88, "Bold", alert.text1);
p.drawText(a1, textBoxFlag, alert.text1);
configFont(p, a2, "Open Sans", 66, "Regular", alert.text2);
p.drawText(a2, textBoxFlag, alert.text2);
} else if (alert.size == cereal::ControlsState::AlertSize::FULL) {
bool l = alert.text1.length() > 15;
configFont(p, "Open Sans", l ? 132 : 177, "Bold");
p.drawText(QRect(0, r.y() + (l ? 240 : 270), width(), 600), Qt::AlignHCenter | Qt::TextWordWrap, alert.text1);
configFont(p, "Open Sans", 88, "Regular");
p.drawText(QRect(0, r.height() - (l ? 361 : 420), width(), 300), Qt::AlignHCenter | Qt::TextWordWrap, alert.text2);
configFont(p, a1, "Open Sans", l ? 132 : 177, "Bold", alert.text1);
p.drawText(a1, textBoxFlag, alert.text1);
configFont(p, a2, "Open Sans", 88, "Regular", alert.text2);
p.drawText(a2, textBoxFlag, alert.text2);
}
}

@ -3,9 +3,14 @@
void setMainWindow(QWidget *w) {
const bool wide = (QGuiApplication::primaryScreen()->size().width() >= WIDE_WIDTH) ^
(getenv("INVERT_WIDTH") != NULL);
const float scale = util::getenv("SCALE", 1.0f);
if constexpr (Hardware::PC()) {
w->setMinimumSize(QSize(640, 480));
w->setMaximumSize(QSize(WIDE_WIDTH, 1080));
w->resize(QSize(1920, 1080));
} else {
w->setFixedSize(QSize(wide ? WIDE_WIDTH : 1920, 1080));
}
w->setFixedSize(QSize(wide ? WIDE_WIDTH : 1920, 1080) * scale);
w->show();
#ifdef QCOM2

@ -20,8 +20,8 @@ void Sidebar::drawMetric(QPainter &p, const QString &label, QColor c, int y) {
p.drawRoundedRect(rect, 20, 20);
p.setPen(QColor(0xff, 0xff, 0xff));
configFont(p, "Open Sans", 35, "Bold");
const QRect r = QRect(rect.x() + 30, rect.y(), rect.width() - 40, rect.height());
configFont(p, r, "Open Sans", 35, "Bold", label);
p.drawText(r, Qt::AlignCenter, label);
}
@ -99,9 +99,9 @@ void Sidebar::paintEvent(QPaintEvent *event) {
x += 37;
}
configFont(p, "Open Sans", 35, "Regular");
p.setPen(QColor(0xff, 0xff, 0xff));
const QRect r = QRect(50, 247, 100, 50);
configFont(p, r, "Open Sans", 35, "Regular", net_type);
p.drawText(r, Qt::AlignCenter, net_type);
// metrics

@ -33,6 +33,32 @@ void configFont(QPainter &p, const QString &family, int size, const QString &sty
p.setFont(f);
}
void configFont(QPainter &p, const QRect &r, const QString &family, int size,
const QString &style, const QString &text) {
if constexpr (Hardware::PC()) {
int szTemp = 1;
QFont f(family);
f.setStyleName(style);
while (true) {
f.setPixelSize(szTemp);
QRect rTemp = QFontMetrics(f).boundingRect(r, Qt::AlignCenter, text);
if (rTemp.height() < r.height() &&
rTemp.width() < r.width() &&
szTemp <= size) {
++szTemp;
} else {
p.setFont(f);
return;
}
}
} else {
QFont f(family);
f.setPixelSize(size);
f.setStyleName(style);
p.setFont(f);
}
}
void clearLayout(QLayout* layout) {
while (QLayoutItem* item = layout->takeAt(0)) {
if (QWidget* widget = item->widget()) {

@ -13,6 +13,8 @@ QString getBrand();
QString getBrandVersion();
std::optional<QString> getDongleId();
void configFont(QPainter &p, const QString &family, int size, const QString &style);
void configFont(QPainter &p, const QRect &r, const QString &family, int size,
const QString &style, const QString &text);
void clearLayout(QLayout* layout);
void setQtSurfaceFormat();
QString timeAgo(const QDateTime &date);

Loading…
Cancel
Save