|
|
|
@ -56,11 +56,11 @@ bool car_space_to_full_frame(const UIState *s, float in_x, float in_y, float in_ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void ui_draw_text(NVGcontext *vg, float x, float y, const char* string, float size, NVGcolor color, int font){ |
|
|
|
|
nvgFontFaceId(vg, font); |
|
|
|
|
nvgFontSize(vg, size); |
|
|
|
|
nvgFillColor(vg, color); |
|
|
|
|
nvgText(vg, x, y, string, NULL); |
|
|
|
|
static void ui_draw_text(const UIState *s, float x, float y, const char* string, float size, NVGcolor color, const char *font_name){ |
|
|
|
|
nvgFontFace(s->vg, font_name); |
|
|
|
|
nvgFontSize(s->vg, size); |
|
|
|
|
nvgFillColor(s->vg, color); |
|
|
|
|
nvgText(s->vg, x, y, string, NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void draw_chevron(UIState *s, float x_in, float y_in, float sz, |
|
|
|
@ -94,19 +94,19 @@ static void draw_chevron(UIState *s, float x_in, float y_in, float sz, |
|
|
|
|
nvgFill(s->vg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ui_draw_circle_image(NVGcontext *vg, int x, int y, int size, int image, NVGcolor color, float img_alpha, int img_y = 0) { |
|
|
|
|
static void ui_draw_circle_image(const UIState *s, int x, int y, int size, const char *image, NVGcolor color, float img_alpha, int img_y = 0) { |
|
|
|
|
const int img_size = size * 1.5; |
|
|
|
|
nvgBeginPath(vg); |
|
|
|
|
nvgCircle(vg, x, y + (bdr_s * 1.5), size); |
|
|
|
|
nvgFillColor(vg, color); |
|
|
|
|
nvgFill(vg); |
|
|
|
|
ui_draw_image(vg, {x - (img_size / 2), img_y ? img_y : y - (size / 4), img_size, img_size}, image, img_alpha); |
|
|
|
|
nvgBeginPath(s->vg); |
|
|
|
|
nvgCircle(s->vg, x, y + (bdr_s * 1.5), size); |
|
|
|
|
nvgFillColor(s->vg, color); |
|
|
|
|
nvgFill(s->vg); |
|
|
|
|
ui_draw_image(s, {x - (img_size / 2), img_y ? img_y : y - (size / 4), img_size, img_size}, image, img_alpha); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ui_draw_circle_image(NVGcontext *vg, int x, int y, int size, int image, bool active) { |
|
|
|
|
static void ui_draw_circle_image(const UIState *s, int x, int y, int size, const char *image, bool active) { |
|
|
|
|
float bg_alpha = active ? 0.3f : 0.1f; |
|
|
|
|
float img_alpha = active ? 1.0f : 0.15f; |
|
|
|
|
ui_draw_circle_image(vg, x, y, size, image, nvgRGBA(0, 0, 0, (255 * bg_alpha)), img_alpha); |
|
|
|
|
ui_draw_circle_image(s, x, y, size, image, nvgRGBA(0, 0, 0, (255 * bg_alpha)), img_alpha); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void draw_lead(UIState *s, const cereal::RadarState::LeadData::Reader &lead){ |
|
|
|
@ -225,12 +225,12 @@ static void ui_draw_vision_maxspeed(UIState *s) { |
|
|
|
|
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->vg, rect.centerX(), 148, "MAX", 26 * 2.5, COLOR_WHITE_ALPHA(is_cruise_set ? 200 : 100), s->font_sans_regular); |
|
|
|
|
ui_draw_text(s, rect.centerX(), 148, "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->vg, rect.centerX(), 242, maxspeed_str.c_str(), 48 * 2.5, COLOR_WHITE, s->font_sans_bold); |
|
|
|
|
ui_draw_text(s, rect.centerX(), 242, maxspeed_str.c_str(), 48 * 2.5, COLOR_WHITE, "sans-bold"); |
|
|
|
|
} else { |
|
|
|
|
ui_draw_text(s->vg, rect.centerX(), 242, "N/A", 42 * 2.5, COLOR_WHITE_ALPHA(100), s->font_sans_semibold); |
|
|
|
|
ui_draw_text(s, rect.centerX(), 242, "N/A", 42 * 2.5, COLOR_WHITE_ALPHA(100), "sans-semibold"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -238,8 +238,8 @@ static void ui_draw_vision_speed(UIState *s) { |
|
|
|
|
const float speed = std::max(0.0, s->scene.controls_state.getVEgo() * (s->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->vg, s->scene.viz_rect.centerX(), 240, speed_str.c_str(), 96 * 2.5, COLOR_WHITE, s->font_sans_bold); |
|
|
|
|
ui_draw_text(s->vg, s->scene.viz_rect.centerX(), 320, s->is_metric ? "km/h" : "mph", 36 * 2.5, COLOR_WHITE_ALPHA(200), s->font_sans_regular); |
|
|
|
|
ui_draw_text(s, s->scene.viz_rect.centerX(), 240, speed_str.c_str(), 96 * 2.5, COLOR_WHITE, "sans-bold"); |
|
|
|
|
ui_draw_text(s, s->scene.viz_rect.centerX(), 320, s->is_metric ? "km/h" : "mph", 36 * 2.5, COLOR_WHITE_ALPHA(200), "sans-regular"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ui_draw_vision_event(UIState *s) { |
|
|
|
@ -250,7 +250,7 @@ static void ui_draw_vision_event(UIState *s) { |
|
|
|
|
// draw winding road sign
|
|
|
|
|
const int img_turn_size = 160*1.5; |
|
|
|
|
const Rect rect = {viz_event_x - (img_turn_size / 4), viz_event_y + bdr_s - 25, img_turn_size, img_turn_size}; |
|
|
|
|
ui_draw_image(s->vg, rect, s->img_turn, 1.0f); |
|
|
|
|
ui_draw_image(s, rect, "trafficSign_turn", 1.0f); |
|
|
|
|
} else if (s->scene.controls_state.getEngageable()) { |
|
|
|
|
// draw steering wheel
|
|
|
|
|
const int bg_wheel_size = 96; |
|
|
|
@ -258,7 +258,7 @@ static void ui_draw_vision_event(UIState *s) { |
|
|
|
|
const int bg_wheel_y = viz_event_y + (bg_wheel_size/2); |
|
|
|
|
const NVGcolor color = bg_colors[s->status]; |
|
|
|
|
|
|
|
|
|
ui_draw_circle_image(s->vg, bg_wheel_x, bg_wheel_y, bg_wheel_size, s->img_wheel, color, 1.0f, bg_wheel_y - 25); |
|
|
|
|
ui_draw_circle_image(s, bg_wheel_x, bg_wheel_y, bg_wheel_size, "wheel", color, 1.0f, bg_wheel_y - 25); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -266,7 +266,7 @@ static void ui_draw_vision_face(UIState *s) { |
|
|
|
|
const int face_size = 96; |
|
|
|
|
const int face_x = (s->scene.viz_rect.x + face_size + (bdr_s * 2)); |
|
|
|
|
const int face_y = (s->scene.viz_rect.bottom() - footer_h + ((footer_h - face_size) / 2)); |
|
|
|
|
ui_draw_circle_image(s->vg, face_x, face_y, face_size, s->img_face, s->scene.dmonitoring_state.getFaceDetected()); |
|
|
|
|
ui_draw_circle_image(s, face_x, face_y, face_size, "driver_face", s->scene.dmonitoring_state.getFaceDetected()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ui_draw_driver_view(UIState *s) { |
|
|
|
@ -307,7 +307,7 @@ static void ui_draw_driver_view(UIState *s) { |
|
|
|
|
const int face_size = 85; |
|
|
|
|
const int icon_x = is_rhd ? rect.right() - face_size - bdr_s * 2 : rect.x + face_size + bdr_s * 2; |
|
|
|
|
const int icon_y = rect.bottom() - face_size - bdr_s * 2.5; |
|
|
|
|
ui_draw_circle_image(s->vg, icon_x, icon_y, face_size, s->img_face, face_detected); |
|
|
|
|
ui_draw_circle_image(s, icon_x, icon_y, face_size, "driver_face", face_detected); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ui_draw_vision_header(UIState *s) { |
|
|
|
@ -356,17 +356,17 @@ static void ui_draw_vision_alert(UIState *s) { |
|
|
|
|
nvgTextAlign(s->vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE); |
|
|
|
|
|
|
|
|
|
if (scene->alert_size == cereal::ControlsState::AlertSize::SMALL) { |
|
|
|
|
ui_draw_text(s->vg, rect.centerX(), rect.centerY() + 15, scene->alert_text1.c_str(), 40*2.5, COLOR_WHITE, s->font_sans_semibold); |
|
|
|
|
ui_draw_text(s, rect.centerX(), rect.centerY() + 15, scene->alert_text1.c_str(), 40*2.5, COLOR_WHITE, "sans-semibold"); |
|
|
|
|
} else if (scene->alert_size == cereal::ControlsState::AlertSize::MID) { |
|
|
|
|
ui_draw_text(s->vg, rect.centerX(), rect.centerY() - 45, scene->alert_text1.c_str(), 48*2.5, COLOR_WHITE, s->font_sans_bold); |
|
|
|
|
ui_draw_text(s->vg, rect.centerX(), rect.centerY() + 75, scene->alert_text2.c_str(), 36*2.5, COLOR_WHITE, s->font_sans_regular); |
|
|
|
|
ui_draw_text(s, rect.centerX(), rect.centerY() - 45, scene->alert_text1.c_str(), 48*2.5, COLOR_WHITE, "sans-bold"); |
|
|
|
|
ui_draw_text(s, rect.centerX(), rect.centerY() + 75, scene->alert_text2.c_str(), 36*2.5, COLOR_WHITE, "sans-regular"); |
|
|
|
|
} else if (scene->alert_size == cereal::ControlsState::AlertSize::FULL) { |
|
|
|
|
nvgFontSize(s->vg, (longAlert1?72:96)*2.5); |
|
|
|
|
nvgFontFaceId(s->vg, s->font_sans_bold); |
|
|
|
|
nvgFontFace(s->vg, "sans-bold"); |
|
|
|
|
nvgTextAlign(s->vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE); |
|
|
|
|
nvgTextBox(s->vg, rect.x, rect.y+(longAlert1?360:420), rect.w-60, scene->alert_text1.c_str(), NULL); |
|
|
|
|
nvgFontSize(s->vg, 48*2.5); |
|
|
|
|
nvgFontFaceId(s->vg, s->font_sans_regular); |
|
|
|
|
nvgFontFace(s->vg, "sans-regular"); |
|
|
|
|
nvgTextAlign(s->vg, NVG_ALIGN_CENTER | NVG_ALIGN_BOTTOM); |
|
|
|
|
nvgTextBox(s->vg, rect.x, rect.h-(longAlert1?300:360), rect.w-60, scene->alert_text2.c_str(), NULL); |
|
|
|
|
} |
|
|
|
@ -443,12 +443,12 @@ void ui_draw(UIState *s) { |
|
|
|
|
glDisable(GL_BLEND); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ui_draw_image(NVGcontext *vg, const Rect &r, int image, float alpha){ |
|
|
|
|
nvgBeginPath(vg); |
|
|
|
|
NVGpaint imgPaint = nvgImagePattern(vg, r.x, r.y, r.w, r.h, 0, image, alpha); |
|
|
|
|
nvgRect(vg, r.x, r.y, r.w, r.h); |
|
|
|
|
nvgFillPaint(vg, imgPaint); |
|
|
|
|
nvgFill(vg); |
|
|
|
|
void ui_draw_image(const UIState *s, const Rect &r, const char *name, float alpha){ |
|
|
|
|
nvgBeginPath(s->vg); |
|
|
|
|
NVGpaint imgPaint = nvgImagePattern(s->vg, r.x, r.y, r.w, r.h, 0, s->images.at(name), alpha); |
|
|
|
|
nvgRect(s->vg, r.x, r.y, r.w, r.h); |
|
|
|
|
nvgFillPaint(s->vg, imgPaint); |
|
|
|
|
nvgFill(s->vg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ui_draw_rect(NVGcontext *vg, const Rect &r, NVGcolor color, int width, float radius) { |
|
|
|
@ -525,36 +525,38 @@ void ui_nvg_init(UIState *s) { |
|
|
|
|
#else |
|
|
|
|
s->vg = nvgCreate(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
assert(s->vg); |
|
|
|
|
|
|
|
|
|
s->font_sans_regular = nvgCreateFont(s->vg, "sans-regular", "../assets/fonts/opensans_regular.ttf"); |
|
|
|
|
assert(s->font_sans_regular >= 0); |
|
|
|
|
s->font_sans_semibold = nvgCreateFont(s->vg, "sans-semibold", "../assets/fonts/opensans_semibold.ttf"); |
|
|
|
|
assert(s->font_sans_semibold >= 0); |
|
|
|
|
s->font_sans_bold = nvgCreateFont(s->vg, "sans-bold", "../assets/fonts/opensans_bold.ttf"); |
|
|
|
|
assert(s->font_sans_bold >= 0); |
|
|
|
|
|
|
|
|
|
s->img_wheel = nvgCreateImage(s->vg, "../assets/img_chffr_wheel.png", 1); |
|
|
|
|
assert(s->img_wheel != 0); |
|
|
|
|
s->img_turn = nvgCreateImage(s->vg, "../assets/img_trafficSign_turn.png", 1); |
|
|
|
|
assert(s->img_turn != 0); |
|
|
|
|
s->img_face = nvgCreateImage(s->vg, "../assets/img_driver_face.png", 1); |
|
|
|
|
assert(s->img_face != 0); |
|
|
|
|
s->img_button_settings = nvgCreateImage(s->vg, "../assets/images/button_settings.png", 1); |
|
|
|
|
assert(s->img_button_settings != 0); |
|
|
|
|
s->img_button_home = nvgCreateImage(s->vg, "../assets/images/button_home.png", 1); |
|
|
|
|
assert(s->img_button_home != 0); |
|
|
|
|
s->img_battery = nvgCreateImage(s->vg, "../assets/images/battery.png", 1); |
|
|
|
|
assert(s->img_battery != 0); |
|
|
|
|
s->img_battery_charging = nvgCreateImage(s->vg, "../assets/images/battery_charging.png", 1); |
|
|
|
|
assert(s->img_battery_charging != 0); |
|
|
|
|
|
|
|
|
|
for(int i=0;i<=5;++i) { |
|
|
|
|
char network_asset[32]; |
|
|
|
|
snprintf(network_asset, sizeof(network_asset), "../assets/images/network_%d.png", i); |
|
|
|
|
s->img_network[i] = nvgCreateImage(s->vg, network_asset, 1); |
|
|
|
|
assert(s->img_network[i] != 0); |
|
|
|
|
// init fonts
|
|
|
|
|
std::pair<const char *, const char *> fonts[] = { |
|
|
|
|
{"sans-regular", "../assets/fonts/opensans_regular.ttf"}, |
|
|
|
|
{"sans-semibold", "../assets/fonts/opensans_semibold.ttf"}, |
|
|
|
|
{"sans-bold", "../assets/fonts/opensans_bold.ttf"}, |
|
|
|
|
}; |
|
|
|
|
for (auto [name, file] : fonts) { |
|
|
|
|
int font_id = nvgCreateFont(s->vg, name, file); |
|
|
|
|
assert(font_id >= 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// init images
|
|
|
|
|
std::vector<std::pair<const char *, const char *>> images = { |
|
|
|
|
{"wheel", "../assets/img_chffr_wheel.png"}, |
|
|
|
|
{"trafficSign_turn", "../assets/img_trafficSign_turn.png"}, |
|
|
|
|
{"driver_face", "../assets/img_driver_face.png"}, |
|
|
|
|
{"button_settings", "../assets/images/button_settings.png"}, |
|
|
|
|
{"button_home", "../assets/images/button_home.png"}, |
|
|
|
|
{"battery", "../assets/images/battery.png"}, |
|
|
|
|
{"battery_charging", "../assets/images/battery_charging.png"}, |
|
|
|
|
{"network_0", "../assets/images/network_0.png"}, |
|
|
|
|
{"network_1", "../assets/images/network_1.png"}, |
|
|
|
|
{"network_2", "../assets/images/network_2.png"}, |
|
|
|
|
{"network_3", "../assets/images/network_3.png"}, |
|
|
|
|
{"network_4", "../assets/images/network_4.png"}, |
|
|
|
|
{"network_5", "../assets/images/network_5.png"}, |
|
|
|
|
}; |
|
|
|
|
for (auto [name, file] : images) { |
|
|
|
|
s->images[name] = nvgCreateImage(s->vg, file, 1); |
|
|
|
|
assert(s->images[name] != 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// init gl
|
|
|
|
|