@ -174,17 +174,24 @@ void NvgWindow::updateState(const UIState &s) {
const SubMaster & sm = * ( s . sm ) ;
const auto cs = sm [ " controlsState " ] . getControlsState ( ) ;
float max speed = cs . getVCruise ( ) ;
bool cruise_set = max speed > 0 & & ( int ) max speed ! = SET_SPEED_NA ;
float set_ speed = cs . getVCruise ( ) ;
bool cruise_set = set_ speed > 0 & & ( int ) set_ speed ! = SET_SPEED_NA ;
if ( cruise_set & & ! s . scene . is_metric ) {
max speed * = KM_TO_MILE ;
set_ speed * = KM_TO_MILE ;
}
QString maxspeed_str = cruise_set ? QString : : number ( std : : nearbyint ( maxspeed ) ) : " N/A " ;
float cur_speed = std : : max ( 0.0 , sm [ " carState " ] . getCarState ( ) . getVEgo ( ) * ( s . scene . is_metric ? MS_TO_KPH : MS_TO_MPH ) ) ;
auto speed_limit_sign = sm [ " navInstruction " ] . getNavInstruction ( ) . getSpeedLimitSign ( ) ;
float speed_limit = sm [ " navInstruction " ] . getValid ( ) ? sm [ " navInstruction " ] . getNavInstruction ( ) . getSpeedLimit ( ) : 0.0 ;
speed_limit * = ( s . scene . is_metric ? MS_TO_KPH : MS_TO_MPH ) ;
setProperty ( " speedLimit " , speed_limit ) ;
setProperty ( " has_us_speed_limit " , speed_limit > 1 & & speed_limit_sign = = cereal : : NavInstruction : : SpeedLimitSign : : MUTCD ) ;
setProperty ( " has_eu_speed_limit " , speed_limit > 1 & & speed_limit_sign = = cereal : : NavInstruction : : SpeedLimitSign : : VIENNA ) ;
setProperty ( " is_cruise_set " , cruise_set ) ;
setProperty ( " speed " , QString : : number ( std : : nearbyint ( cur_speed ) ) ) ;
setProperty ( " maxSpeed " , maxspeed_str ) ;
setProperty ( " speed " , cur_speed ) ;
setProperty ( " setSpeed " , set_speed ) ;
setProperty ( " speedUnit " , s . scene . is_metric ? " km/h " : " mph " ) ;
setProperty ( " hideDM " , cs . getAlertSize ( ) ! = cereal : : ControlsState : : AlertSize : : NONE ) ;
setProperty ( " status " , s . status ) ;
@ -205,26 +212,139 @@ void NvgWindow::drawHud(QPainter &p) {
bg . setColorAt ( 1 , QColor : : fromRgbF ( 0 , 0 , 0 , 0 ) ) ;
p . fillRect ( 0 , 0 , width ( ) , header_h , bg ) ;
// max speed
QRect rc ( bdr_s * 2 , bdr_s * 1.5 , 184 , 202 ) ;
p . setPen ( QPen ( QColor ( 0xff , 0xff , 0xff , 100 ) , 10 ) ) ;
p . setBrush ( QColor ( 0 , 0 , 0 , 100 ) ) ;
p . drawRoundedRect ( rc , 20 , 20 ) ;
p . setPen ( Qt : : NoPen ) ;
QString speedLimitStr = QString : : number ( std : : nearbyint ( speedLimit ) ) ;
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 and speed limit
int default_rect_width = 172 ;
int rect_width = default_rect_width ;
if ( has_us_speed_limit & & speedLimitStr . size ( ) > = 3 ) rect_width = 223 ;
else if ( has_eu_speed_limit ) rect_width = 200 ;
int rect_height = 204 ;
if ( has_us_speed_limit ) rect_height = 402 ;
else if ( has_eu_speed_limit ) rect_height = 392 ;
configFont ( p , " Open Sans " , 48 , " Regular " ) ;
drawText ( p , rc . center ( ) . x ( ) , 118 , " MAX " , is_cruise_set ? 200 : 100 ) ;
int top_radius = 32 ;
int bottom_radius = has_eu_speed_limit ? 100 : 32 ;
QRect set_speed_rect ( 60 + default_rect_width / 2 - rect_width / 2 , 45 , rect_width , rect_height ) ;
p . setPen ( QPen ( QColor ( 255 , 255 , 255 , 75 ) , 6 ) ) ;
p . setBrush ( QColor ( 0 , 0 , 0 , 166 ) ) ;
drawRoundedRect ( p , set_speed_rect , top_radius , top_radius , bottom_radius , bottom_radius ) ;
// Draw set speed
if ( is_cruise_set ) {
configFont ( p , " Open Sans " , 88 , " Bold " ) ;
drawText ( p , rc . center ( ) . x ( ) , 212 , maxSpeed , 255 ) ;
if ( speedLimit > 0 & & status ! = STATUS_DISENGAGED & & status ! = STATUS_OVERRIDE ) {
p . setPen ( interpColor (
setSpeed ,
{ speedLimit + 5 , speedLimit + 15 , speedLimit + 25 } ,
{ QColor ( 0xff , 0xff , 0xff , 0xff ) , QColor ( 0xff , 0x95 , 0x00 , 0xff ) , QColor ( 0xff , 0x00 , 0x00 , 0xff ) }
) ) ;
} else {
p . setPen ( QColor ( 0xff , 0xff , 0xff , 0xff ) ) ;
}
} else {
p . setPen ( QColor ( 0x72 , 0x72 , 0x72 , 0xff ) ) ;
}
configFont ( p , " Open Sans " , 90 , " Bold " ) ;
QRect speed_rect = getTextRect ( p , Qt : : AlignCenter , setSpeedStr ) ;
speed_rect . moveCenter ( { set_speed_rect . center ( ) . x ( ) , 0 } ) ;
speed_rect . moveTop ( set_speed_rect . top ( ) + 8 ) ;
p . drawText ( speed_rect , Qt : : AlignCenter , setSpeedStr ) ;
// Draw MAX
if ( is_cruise_set ) {
if ( status = = STATUS_DISENGAGED ) {
p . setPen ( QColor ( 0xff , 0xff , 0xff , 0xff ) ) ;
} else if ( status = = STATUS_OVERRIDE ) {
p . setPen ( QColor ( 0x91 , 0x9b , 0x95 , 0xff ) ) ;
} else if ( speedLimit > 0 ) {
p . setPen ( interpColor (
setSpeed ,
{ speedLimit + 5 , speedLimit + 15 , speedLimit + 25 } ,
{ QColor ( 0x80 , 0xd8 , 0xa6 , 0xff ) , QColor ( 0xff , 0xe4 , 0xbf , 0xff ) , QColor ( 0xff , 0xbf , 0xbf , 0xff ) }
) ) ;
} else {
configFont ( p , " Open Sans " , 80 , " SemiBold " ) ;
drawText ( p , rc . center ( ) . x ( ) , 212 , maxSpeed , 100 ) ;
p . setPen ( QColor ( 0x80 , 0xd8 , 0xa6 , 0xff ) ) ;
}
} else {
p . setPen ( QColor ( 0xa6 , 0xa6 , 0xa6 , 0xff ) ) ;
}
configFont ( p , " Open Sans " , 40 , " SemiBold " ) ;
QRect max_rect = getTextRect ( p , Qt : : AlignCenter , " MAX " ) ;
max_rect . moveCenter ( { set_speed_rect . center ( ) . x ( ) , 0 } ) ;
max_rect . moveTop ( set_speed_rect . top ( ) + 123 ) ;
p . drawText ( max_rect , Qt : : AlignCenter , " MAX " ) ;
// US/Canada (MUTCD style) sign
if ( has_us_speed_limit ) {
const int border_width = 6 ;
const int sign_width = ( speedLimitStr . size ( ) > = 3 ) ? 199 : 148 ;
const int sign_height = 186 ;
// White outer square
QRect sign_rect_outer ( set_speed_rect . left ( ) + 12 , set_speed_rect . bottom ( ) - 11 - sign_height , sign_width , sign_height ) ;
p . setPen ( Qt : : NoPen ) ;
p . setBrush ( QColor ( 255 , 255 , 255 , 255 ) ) ;
p . drawRoundedRect ( sign_rect_outer , 24 , 24 ) ;
// Smaller white square with black border
QRect sign_rect ( sign_rect_outer . left ( ) + 1.5 * border_width , sign_rect_outer . top ( ) + 1.5 * border_width , sign_width - 3 * border_width , sign_height - 3 * border_width ) ;
p . setPen ( QPen ( QColor ( 0 , 0 , 0 , 255 ) , border_width ) ) ;
p . setBrush ( QColor ( 255 , 255 , 255 , 255 ) ) ;
p . drawRoundedRect ( sign_rect , 16 , 16 ) ;
// "SPEED"
configFont ( p , " Open Sans " , 28 , " SemiBold " ) ;
QRect text_speed_rect = getTextRect ( p , Qt : : AlignCenter , " SPEED " ) ;
text_speed_rect . moveCenter ( { sign_rect . center ( ) . x ( ) , 0 } ) ;
text_speed_rect . moveTop ( sign_rect_outer . top ( ) + 20 ) ;
p . drawText ( text_speed_rect , Qt : : AlignCenter , " SPEED " ) ;
// "LIMIT"
QRect text_limit_rect = getTextRect ( p , Qt : : AlignCenter , " LIMIT " ) ;
text_limit_rect . moveCenter ( { sign_rect . center ( ) . x ( ) , 0 } ) ;
text_limit_rect . moveTop ( sign_rect_outer . top ( ) + 48 ) ;
p . drawText ( text_limit_rect , Qt : : AlignCenter , " LIMIT " ) ;
// Speed limit value
configFont ( p , " Open Sans " , 70 , " Bold " ) ;
QRect speed_limit_rect = getTextRect ( p , Qt : : AlignCenter , speedLimitStr ) ;
speed_limit_rect . moveCenter ( { sign_rect . center ( ) . x ( ) , 0 } ) ;
speed_limit_rect . moveTop ( sign_rect . top ( ) + 70 ) ;
p . drawText ( speed_limit_rect , Qt : : AlignCenter , speedLimitStr ) ;
}
// EU (Vienna style) sign
if ( has_eu_speed_limit ) {
int outer_radius = 176 / 2 ;
int inner_radius_1 = outer_radius - 6 ; // White outer border
int inner_radius_2 = inner_radius_1 - 20 ; // Red circle
// Draw white circle with red border
QPoint center ( set_speed_rect . center ( ) . x ( ) + 1 , set_speed_rect . top ( ) + 204 + outer_radius ) ;
p . setPen ( Qt : : NoPen ) ;
p . setBrush ( QColor ( 255 , 255 , 255 , 255 ) ) ;
p . drawEllipse ( center , outer_radius , outer_radius ) ;
p . setBrush ( QColor ( 255 , 0 , 0 , 255 ) ) ;
p . drawEllipse ( center , inner_radius_1 , inner_radius_1 ) ;
p . setBrush ( QColor ( 255 , 255 , 255 , 255 ) ) ;
p . drawEllipse ( center , inner_radius_2 , inner_radius_2 ) ;
// Speed limit value
int font_size = ( speedLimitStr . size ( ) > = 3 ) ? 62 : 70 ;
configFont ( p , " Open Sans " , font_size , " Bold " ) ;
QRect speed_limit_rect = getTextRect ( p , Qt : : AlignCenter , speedLimitStr ) ;
speed_limit_rect . moveCenter ( center ) ;
p . setPen ( QColor ( 0 , 0 , 0 , 255 ) ) ;
p . drawText ( speed_limit_rect , Qt : : AlignCenter , speedLimitStr ) ;
}
// current speed
configFont ( p , " Open Sans " , 176 , " Bold " ) ;
drawText ( p , rect ( ) . center ( ) . x ( ) , 210 , speed ) ;
drawText ( p , rect ( ) . center ( ) . x ( ) , 210 , speedStr ) ;
configFont ( p , " Open Sans " , 66 , " Regular " ) ;
drawText ( p , rect ( ) . center ( ) . x ( ) , 290 , speedUnit , 200 ) ;
@ -243,9 +363,7 @@ void NvgWindow::drawHud(QPainter &p) {
}
void NvgWindow : : drawText ( QPainter & p , int x , int y , const QString & text , int alpha ) {
QFontMetrics fm ( p . font ( ) ) ;
QRect init_rect = fm . boundingRect ( text ) ;
QRect real_rect = fm . boundingRect ( init_rect , 0 , text ) ;
QRect real_rect = getTextRect ( p , 0 , text ) ;
real_rect . moveCenter ( { x , y - real_rect . height ( ) / 2 } ) ;
p . setPen ( QColor ( 0xff , 0xff , 0xff , alpha ) ) ;