# include <stdio.h>
# include <string.h>
# include <math.h>
# include <map>
# include "paint.hpp"
# include "sidebar.hpp"
static void ui_draw_sidebar_background ( UIState * s ) {
# ifdef QCOM
const NVGcolor color = COLOR_BLACK_ALPHA ( 85 ) ;
# else
const NVGcolor color = nvgRGBA ( 0x39 , 0x39 , 0x39 , 0xff ) ;
# endif
ui_draw_rect ( s - > vg , 0 , 0 , sbr_w , s - > fb_h , color ) ;
}
static void ui_draw_sidebar_settings_button ( UIState * s ) {
const float alpha = s - > active_app = = cereal : : UiLayoutState : : App : : SETTINGS ? 1.0f : 0.65f ;
ui_draw_image ( s - > vg , settings_btn , s - > img_button_settings , alpha ) ;
}
static void ui_draw_sidebar_home_button ( UIState * s ) {
const float alpha = s - > active_app = = cereal : : UiLayoutState : : App : : HOME ? 1.0f : 0.65f ; ;
ui_draw_image ( s - > vg , home_btn , s - > img_button_home , alpha ) ;
}
static void ui_draw_sidebar_network_strength ( UIState * s ) {
static std : : map < cereal : : ThermalData : : NetworkStrength , int > network_strength_map = {
{ cereal : : ThermalData : : NetworkStrength : : UNKNOWN , 1 } ,
{ cereal : : ThermalData : : NetworkStrength : : POOR , 2 } ,
{ cereal : : ThermalData : : NetworkStrength : : MODERATE , 3 } ,
{ cereal : : ThermalData : : NetworkStrength : : GOOD , 4 } ,
{ cereal : : ThermalData : : NetworkStrength : : GREAT , 5 } } ;
const Rect rect = { 58 , 196 , 176 , 27 } ;
const int img_idx = s - > scene . thermal . getNetworkType ( ) = = cereal : : ThermalData : : NetworkType : : NONE ? 0 : network_strength_map [ s - > scene . thermal . getNetworkStrength ( ) ] ;
ui_draw_image ( s - > vg , rect , s - > img_network [ img_idx ] , 1.0f ) ;
}
static void ui_draw_sidebar_battery_icon ( UIState * s ) {
int battery_img = s - > scene . thermal . getBatteryStatus ( ) = = " Charging " ? s - > img_battery_charging : s - > img_battery ;
const Rect rect = { 160 , 255 , 76 , 36 } ;
ui_draw_rect ( s - > vg , rect . x + 6 , rect . y + 5 ,
( ( rect . w - 19 ) * ( s - > scene . thermal . getBatteryPercent ( ) * 0.01 ) ) , rect . h - 11 , COLOR_WHITE ) ;
ui_draw_image ( s - > vg , rect , battery_img , 1.0f ) ;
}
static void ui_draw_sidebar_network_type ( UIState * s ) {
static std : : map < cereal : : ThermalData : : NetworkType , const char * > network_type_map = {
{ cereal : : ThermalData : : NetworkType : : NONE , " -- " } ,
{ cereal : : ThermalData : : NetworkType : : WIFI , " WiFi " } ,
{ cereal : : ThermalData : : NetworkType : : CELL2_G , " 2G " } ,
{ cereal : : ThermalData : : NetworkType : : CELL3_G , " 3G " } ,
{ cereal : : ThermalData : : NetworkType : : CELL4_G , " 4G " } ,
{ cereal : : ThermalData : : NetworkType : : CELL5_G , " 5G " } } ;
const int network_x = 50 ;
const int network_y = 273 ;
const int network_w = 100 ;
const char * network_type = network_type_map [ s - > scene . thermal . getNetworkType ( ) ] ;
nvgFillColor ( s - > vg , COLOR_WHITE ) ;
nvgFontSize ( s - > vg , 48 ) ;
nvgFontFaceId ( s - > vg , s - > font_sans_regular ) ;
nvgTextAlign ( s - > vg , NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE ) ;
nvgTextBox ( s - > vg , network_x , network_y , network_w , network_type ? network_type : " -- " , NULL ) ;
}
static void ui_draw_sidebar_metric ( UIState * s , const char * label_str , const char * value_str , const int severity , const int y_offset , const char * message_str ) {
const int metric_x = 30 ;
const int metric_y = 338 + y_offset ;
const int metric_w = 240 ;
const int metric_h = message_str ? strchr ( message_str , ' \n ' ) ? 124 : 100 : 148 ;
NVGcolor status_color ;
if ( severity = = 0 ) {
status_color = COLOR_WHITE ;
} else if ( severity = = 1 ) {
status_color = COLOR_YELLOW ;
} else if ( severity > 1 ) {
status_color = COLOR_RED ;
}
ui_draw_rect ( s - > vg , metric_x , metric_y , metric_w , metric_h ,
severity > 0 ? COLOR_WHITE : COLOR_WHITE_ALPHA ( 85 ) , 20 , 2 ) ;
nvgBeginPath ( s - > vg ) ;
nvgRoundedRectVarying ( s - > vg , metric_x + 6 , metric_y + 6 , 18 , metric_h - 12 , 25 , 0 , 0 , 25 ) ;
nvgFillColor ( s - > vg , status_color ) ;
nvgFill ( s - > vg ) ;
if ( ! message_str ) {
nvgFillColor ( s - > vg , COLOR_WHITE ) ;
nvgFontSize ( s - > vg , 78 ) ;
nvgFontFaceId ( s - > vg , s - > font_sans_bold ) ;
nvgTextAlign ( s - > vg , NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE ) ;
nvgTextBox ( s - > vg , metric_x + 50 , metric_y + 50 , metric_w - 60 , value_str , NULL ) ;
nvgFillColor ( s - > vg , COLOR_WHITE ) ;
nvgFontSize ( s - > vg , 48 ) ;
nvgFontFaceId ( s - > vg , s - > font_sans_regular ) ;
nvgTextAlign ( s - > vg , NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE ) ;
nvgTextBox ( s - > vg , metric_x + 50 , metric_y + 50 + 66 , metric_w - 60 , label_str , NULL ) ;
} else {
nvgFillColor ( s - > vg , COLOR_WHITE ) ;
nvgFontSize ( s - > vg , 48 ) ;
nvgFontFaceId ( s - > vg , s - > font_sans_bold ) ;
nvgTextAlign ( s - > vg , NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE ) ;
nvgTextBox ( s - > vg , metric_x + 35 , metric_y + ( strchr ( message_str , ' \n ' ) ? 40 : 50 ) , metric_w - 50 , message_str , NULL ) ;
}
}
static void ui_draw_sidebar_temp_metric ( UIState * s ) {
static std : : map < cereal : : ThermalData : : ThermalStatus , const int > temp_severity_map = {
{ cereal : : ThermalData : : ThermalStatus : : GREEN , 0 } ,
{ cereal : : ThermalData : : ThermalStatus : : YELLOW , 1 } ,
{ cereal : : ThermalData : : ThermalStatus : : RED , 2 } ,
{ cereal : : ThermalData : : ThermalStatus : : DANGER , 3 } } ;
std : : string temp_val = std : : to_string ( ( int ) s - > scene . thermal . getAmbient ( ) ) + " °C " ;
ui_draw_sidebar_metric ( s , " TEMP " , temp_val . c_str ( ) , temp_severity_map [ s - > scene . thermal . getThermalStatus ( ) ] , 0 , NULL ) ;
}
static void ui_draw_sidebar_panda_metric ( UIState * s ) {
const int panda_y_offset = 32 + 148 ;
int panda_severity = 0 ;
std : : string panda_message = " VEHICLE \n ONLINE " ;
if ( s - > scene . hwType = = cereal : : HealthData : : HwType : : UNKNOWN ) {
panda_severity = 2 ;
panda_message = " NO \n VEHICLE " ;
} else if ( s - > started ) {
if ( s - > scene . satelliteCount < 6 ) {
panda_severity = 1 ;
panda_message = " VEHICLE \n NO GPS " ;
} else {
panda_severity = 0 ;
panda_message = " VEHICLE \n GOOD GPS " ;
}
}
ui_draw_sidebar_metric ( s , NULL , NULL , panda_severity , panda_y_offset , panda_message . c_str ( ) ) ;
}
static void ui_draw_sidebar_connectivity ( UIState * s ) {
static std : : map < NetStatus , std : : pair < const char * , int > > connectivity_map = {
{ NET_ERROR , { " CONNECT \n ERROR " , 2 } } ,
{ NET_CONNECTED , { " CONNECT \n ONLINE " , 0 } } ,
{ NET_DISCONNECTED , { " CONNECT \n OFFLINE " , 1 } } ,
} ;
auto net_params = connectivity_map [ s - > scene . athenaStatus ] ;
ui_draw_sidebar_metric ( s , NULL , NULL , net_params . second , 180 + 158 , net_params . first ) ;
}
void ui_draw_sidebar ( UIState * s ) {
if ( s - > scene . sidebar_collapsed ) {
return ;
}
ui_draw_sidebar_background ( s ) ;
ui_draw_sidebar_settings_button ( s ) ;
ui_draw_sidebar_home_button ( s ) ;
ui_draw_sidebar_network_strength ( s ) ;
ui_draw_sidebar_battery_icon ( s ) ;
ui_draw_sidebar_network_type ( s ) ;
ui_draw_sidebar_temp_metric ( s ) ;
ui_draw_sidebar_panda_metric ( s ) ;
ui_draw_sidebar_connectivity ( s ) ;
}