mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 15:23:57 +08:00
Visuals: Turn signals on screen when blinker is used (#1291)
* get blinker state from car_state * Draw turn signals when blinker is active * reloacted and resized turning signals * add turn signal display setting * Lowered Blink Frequency * Moved x and y Offsets to drawing Function Co-authored-by: Nayan <nayan8teen@gmail.com> * Grouped Settings * Moved blinking Logic to pulseElement Function Co-authored-by: Nayan <nayan8teen@gmail.com> * Improved Blinker Size and Position * Get laneChangeBlocked Event from onroadEvents * Draw Blinker red if laneChangeBlocked event is set * Revert "Get laneChangeBlocked Event from onroadEvents" This reverts commit 4310931b6cd59aed22119c2b4b558f09d3ad9c90. * Get left and right Blindspot * Replaced laneChangeBlocked by Blindspot checks * slight optimization * more refinement --------- Co-authored-by: Nayan <nayan8teen@gmail.com> Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
This commit is contained in:
@@ -168,6 +168,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"ShowTurnSignals", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
{"TrueVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||
|
||||
|
||||
@@ -82,7 +82,14 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) {
|
||||
tr("When enabled, the speedometer on the onroad screen is not displayed."),
|
||||
"",
|
||||
false,
|
||||
}
|
||||
},
|
||||
{
|
||||
"ShowTurnSignals",
|
||||
tr("Display Turn Signals"),
|
||||
tr("When enabled, visual turn indicators are drawn on the HUD."),
|
||||
"",
|
||||
false,
|
||||
},
|
||||
};
|
||||
|
||||
// Add regular toggles first
|
||||
|
||||
@@ -122,6 +122,12 @@ void HudRendererSP::updateState(const UIState &s) {
|
||||
float v_ego = (v_ego_cluster_seen && !s.scene.trueVEgoUI) ? car_state.getVEgoCluster() : car_state.getVEgo();
|
||||
speed = std::max<float>(0.0f, v_ego * (is_metric ? MS_TO_KPH : MS_TO_MPH));
|
||||
hideVEgoUI = s.scene.hideVEgoUI;
|
||||
|
||||
leftBlinkerOn = car_state.getLeftBlinker();
|
||||
rightBlinkerOn = car_state.getRightBlinker();
|
||||
leftBlindspot = car_state.getLeftBlindspot();
|
||||
rightBlindspot = car_state.getRightBlindspot();
|
||||
showTurnSignals = s.scene.turn_signals;
|
||||
}
|
||||
|
||||
void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) {
|
||||
@@ -239,6 +245,11 @@ void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) {
|
||||
} else {
|
||||
e2eAlertFrame = 0;
|
||||
}
|
||||
|
||||
// Blinker
|
||||
if (showTurnSignals) {
|
||||
drawBlinker(p, surface_rect);
|
||||
}
|
||||
}
|
||||
|
||||
p.restore();
|
||||
@@ -752,3 +763,73 @@ void HudRendererSP::drawCurrentSpeedSP(QPainter &p, const QRect &surface_rect) {
|
||||
p.setFont(InterFont(66));
|
||||
HudRenderer::drawText(p, surface_rect.center().x(), 290, is_metric ? tr("km/h") : tr("mph"), 200);
|
||||
}
|
||||
|
||||
void HudRendererSP::drawBlinker(QPainter &p, const QRect &surface_rect) {
|
||||
if (!leftBlinkerOn && !rightBlinkerOn) {
|
||||
blinkerFrameCounter = 0;
|
||||
return;
|
||||
}
|
||||
++blinkerFrameCounter;
|
||||
|
||||
const int circleRadius = 44;
|
||||
const int arrowLength = 44;
|
||||
const int x_gap = 180;
|
||||
const int y_offset = 272;
|
||||
|
||||
const int centerX = surface_rect.center().x();
|
||||
const bool hazard = leftBlinkerOn && rightBlinkerOn;
|
||||
|
||||
const QPen bgBorder(Qt::white, 5);
|
||||
const QPen arrowPen(Qt::NoPen);
|
||||
|
||||
p.save();
|
||||
|
||||
auto drawArrow = [&](int cx, int cy, int dir, const QBrush &arrowBrush) {
|
||||
const int bodyLength = arrowLength / 2;
|
||||
const int bodyWidth = arrowLength / 2;
|
||||
const int headLength = arrowLength / 2;
|
||||
const int headWidth = arrowLength;
|
||||
|
||||
QPolygon arrow;
|
||||
arrow.reserve(7);
|
||||
arrow << QPoint(cx - dir * bodyLength, cy - bodyWidth / 2)
|
||||
<< QPoint(cx, cy - bodyWidth / 2)
|
||||
<< QPoint(cx, cy - headWidth / 2)
|
||||
<< QPoint(cx + dir * headLength, cy)
|
||||
<< QPoint(cx, cy + headWidth / 2)
|
||||
<< QPoint(cx, cy + bodyWidth / 2)
|
||||
<< QPoint(cx - dir * bodyLength, cy + bodyWidth / 2);
|
||||
|
||||
p.setPen(arrowPen);
|
||||
p.setBrush(arrowBrush);
|
||||
p.drawPolygon(arrow);
|
||||
};
|
||||
|
||||
auto drawCircle = [&](int cx, int cy, const QBrush &bgBrush) {
|
||||
p.setPen(bgBorder);
|
||||
p.setBrush(bgBrush);
|
||||
p.drawEllipse(QPoint(cx, cy), circleRadius, circleRadius);
|
||||
};
|
||||
|
||||
struct BlinkerSide { bool on; int dir; bool blocked; int cx; };
|
||||
const std::array<BlinkerSide, 2> sides = {{
|
||||
{leftBlinkerOn, -1, hazard ? true : (leftBlinkerOn && leftBlindspot), centerX - x_gap},
|
||||
{rightBlinkerOn, 1, hazard ? true : (rightBlinkerOn && rightBlindspot), centerX + x_gap},
|
||||
}};
|
||||
|
||||
for (const auto &s: sides) {
|
||||
if (!s.on) continue;
|
||||
|
||||
QColor bgColor = s.blocked ? QColor(135, 23, 23) : QColor(23, 134, 68);
|
||||
QColor arrowColor = s.blocked ? QColor(66, 12, 12) : QColor(12, 67, 34);
|
||||
if (pulseElement(blinkerFrameCounter)) arrowColor = Qt::white;
|
||||
|
||||
const QBrush bgBrush(bgColor);
|
||||
const QBrush arrowBrush(arrowColor);
|
||||
|
||||
drawCircle(s.cx, y_offset, bgBrush);
|
||||
drawArrow(s.cx, y_offset, s.dir, arrowBrush);
|
||||
}
|
||||
|
||||
p.restore();
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ private:
|
||||
void drawSetSpeedSP(QPainter &p, const QRect &surface_rect);
|
||||
void drawE2eAlert(QPainter &p, const QRect &surface_rect);
|
||||
void drawCurrentSpeedSP(QPainter &p, const QRect &surface_rect);
|
||||
void drawBlinker(QPainter &p, const QRect &surface_rect);
|
||||
|
||||
bool lead_status;
|
||||
float lead_d_rel;
|
||||
@@ -109,4 +110,10 @@ private:
|
||||
QString alert_text;
|
||||
QPixmap alert_img;
|
||||
bool hideVEgoUI;
|
||||
bool leftBlinkerOn;
|
||||
bool rightBlinkerOn;
|
||||
bool leftBlindspot;
|
||||
bool rightBlindspot;
|
||||
int blinkerFrameCounter;
|
||||
bool showTurnSignals;
|
||||
};
|
||||
|
||||
@@ -72,6 +72,8 @@ void ui_update_params_sp(UIStateSP *s) {
|
||||
s->scene.onroadScreenOffControl = params.getBool("OnroadScreenOffControl");
|
||||
s->scene.onroadScreenOffTimerParam = std::atoi(params.get("OnroadScreenOffTimer").c_str());
|
||||
s->reset_onroad_sleep_timer();
|
||||
|
||||
s->scene.turn_signals = params.getBool("ShowTurnSignals");
|
||||
}
|
||||
|
||||
void UIStateSP::reset_onroad_sleep_timer() {
|
||||
|
||||
@@ -17,4 +17,5 @@ typedef struct UISceneSP : UIScene {
|
||||
int onroadScreenOffTimerParam;
|
||||
bool trueVEgoUI;
|
||||
bool hideVEgoUI;
|
||||
bool turn_signals = false;
|
||||
} UISceneSP;
|
||||
|
||||
Reference in New Issue
Block a user