diff --git a/selfdrive/ui/onroad/starpilot/aethergauge.py b/selfdrive/ui/onroad/starpilot/aethergauge.py index bb1bfaf3c..af34d720c 100644 --- a/selfdrive/ui/onroad/starpilot/aethergauge.py +++ b/selfdrive/ui/onroad/starpilot/aethergauge.py @@ -29,8 +29,8 @@ PERSPECTIVE_EXPONENT = 1.8 ROAD_HEIGHT = 80.0 * SCALE ROAD_SEGMENTS = 24 -ROAD_W_BOTTOM = 22.0 * SCALE -ROAD_W_TOP = 14.0 * SCALE +ROAD_W_BOTTOM = 32.0 * SCALE +ROAD_W_TOP = 18.0 * SCALE ROAD_THICKNESS = 4.0 * SCALE ROAD_HALF_SIZE = 40.0 * SCALE ROAD_EDGE_INSET = 2.0 * SCALE @@ -530,8 +530,8 @@ class AetherGauge: t_lead = max(0.15, min(0.85, t_lead)) car_scale = 0.45 + (1.0 - t_lead) * 0.55 - W = 30.0 * SCALE * car_scale - H = 18.0 * SCALE * car_scale + W = 38.0 * SCALE * car_scale + H = 22.0 * SCALE * car_scale is_stopped = data.indicator_extra == "stopped" is_slower = data.indicator_extra == "slower" @@ -543,30 +543,31 @@ class AetherGauge: else: border_color = _fade(data.color, alpha) - # Car body: cabin and main body + # Car body: cabin and main body with high-contrast outlines for rect_args, corner_r, fill in [ ((cx_lead - W * 0.3, cy_lead - H, W * 0.6, H * 0.45), 0.5, _fade(rl.Color(15, 15, 15, 240), alpha)), ((cx_lead - W / 2, cy_lead - H * 0.65, W, H * 0.55), 0.3, _fade(rl.Color(20, 20, 20, 240), alpha)), ]: r = rl.Rectangle(*rect_args) rl.draw_rectangle_rounded(r, corner_r, 4, fill) - rl.draw_rectangle_rounded_lines_ex(r, corner_r, 4, 1.5, border_color) + rl.draw_rectangle_rounded_lines_ex(r, corner_r, 4, 2.0, border_color) - # Tail lights with glow - tl_w = W * 0.15 - tl_h = H * 0.12 + # Tail lights with radial bloom + tl_w = max(4.0, W * 0.16) + tl_h = max(2.5, H * 0.14) tl_y = int(cy_lead - H * 0.55) glow_y = int(cy_lead - H * 0.5) for tl_x, glow_x in [(int(cx_lead - W * 0.45), int(cx_lead - W * 0.38)), (int(cx_lead + W * 0.3), int(cx_lead + W * 0.38))]: if is_stopped: pulse = _pulse(2.5) - r_glow = int(W * 0.08 * (1.0 + 0.4 * pulse)) + r_glow = int(W * 0.10 * (1.0 + 0.4 * pulse)) + rl.draw_circle(glow_x, glow_y, r_glow + 4, _fade(rl.Color(255, 30, 60, int(60 + 40 * pulse)), alpha)) rl.draw_circle(glow_x, glow_y, r_glow, _fade(rl.Color(255, 30, 60, int(150 + 105 * pulse)), alpha)) c_tl = _fade(rl.Color(255, 220, 220, 255), alpha) elif is_slower: pulse = _pulse(1.2) - r_glow = int(W * 0.06 * (1.0 + 0.2 * pulse)) + r_glow = int(W * 0.08 * (1.0 + 0.2 * pulse)) rl.draw_circle(glow_x, glow_y, r_glow, _fade(rl.Color(255, 140, 30, int(100 + 80 * pulse)), alpha)) c_tl = _fade(rl.Color(255, 160, 60, int(180 + 75 * pulse)), alpha) else: @@ -594,8 +595,8 @@ class AetherGauge: road_h = self._current_road_h cy_t = bottom - t * road_h - chevron_w = 12.0 * SCALE - t * 5.0 * SCALE - chevron_thick = max(1.5 * SCALE, 3.5 * SCALE - t * 1.5 * SCALE) + chevron_w = 14.0 * SCALE - t * 5.0 * SCALE + chevron_thick = max(2.0 * SCALE, 4.0 * SCALE - t * 1.5 * SCALE) lx = cx_t - chevron_w rx = cx_t + chevron_w @@ -636,9 +637,9 @@ class AetherGauge: dir_right_x = -dir_up_y dir_right_y = dir_up_x - chevron_w = max(2.0 * SCALE, 14.0 * SCALE - t * 6.0 * SCALE) + chevron_w = max(3.0 * SCALE, 18.0 * SCALE - t * 7.0 * SCALE) chevron_h = chevron_w * 0.6 - chevron_thick = max(2.0 * SCALE, 4.0 * SCALE - t * 2.0 * SCALE) + chevron_thick = max(2.5 * SCALE, 4.5 * SCALE - t * 2.0 * SCALE) lx = cx_t - dir_right_x * chevron_w + dir_up_x * chevron_h ly = cy_t - dir_right_y * chevron_w + dir_up_y * chevron_h @@ -659,29 +660,29 @@ class AetherGauge: t_light, cx_light, cy_road = _road_xy(distance, icx, icy + ROAD_HALF_SIZE, data, self._current_road_h) s_light = 1.0 - t_light - scale_light = 0.6 + (s_light ** 2.0) * 1.4 - cy_light = cy_road - 35.0 * SCALE * s_light - width = 11.0 * SCALE * scale_light - height = 27.0 * SCALE * scale_light + scale_light = 0.65 + (s_light ** 2.0) * 1.35 + cy_light = cy_road - 38.0 * SCALE * s_light + width = 15.0 * SCALE * scale_light + height = 36.0 * SCALE * scale_light - rl.draw_rectangle_rounded(rl.Rectangle(cx_light - width/2, cy_light - height/2 + 1.5, width, height), 0.2, 4, _fade(rl.Color(0, 0, 0, 120), alpha)) + rl.draw_rectangle_rounded(rl.Rectangle(cx_light - width/2, cy_light - height/2 + 1.5, width, height), 0.25, 4, _fade(rl.Color(0, 0, 0, 120), alpha)) rect_housing = rl.Rectangle(cx_light - width/2, cy_light - height/2, width, height) - rl.draw_rectangle_rounded(rect_housing, 0.2, 4, _fade(rl.Color(22, 22, 22, 255), alpha)) - rl.draw_rectangle_rounded_lines_ex(rect_housing, 0.2, 4, 1.0, _fade(rl.Color(80, 80, 80, 255), alpha)) + rl.draw_rectangle_rounded(rect_housing, 0.25, 4, _fade(rl.Color(22, 22, 22, 255), alpha)) + rl.draw_rectangle_rounded_lines_ex(rect_housing, 0.25, 4, 1.5, _fade(rl.Color(100, 100, 100, 255), alpha)) - r_bulb = 2.2 * SCALE * scale_light + r_bulb = 3.2 * SCALE * scale_light active_light = data.indicator_extra if data.indicator_extra in ("red", "yellow", "green") else "red" bulbs = [ - (cy_light - 7.5 * SCALE * scale_light, "red", rl.Color(255, 30, 60, 255), rl.Color(50, 10, 15, 255)), + (cy_light - 10.0 * SCALE * scale_light, "red", rl.Color(255, 30, 60, 255), rl.Color(50, 10, 15, 255)), (cy_light, "yellow", rl.Color(255, 200, 0, 255), rl.Color(50, 40, 0, 255)), - (cy_light + 7.5 * SCALE * scale_light, "green", rl.Color(0, 255, 100, 255), rl.Color(0, 40, 15, 255)), + (cy_light + 10.0 * SCALE * scale_light, "green", rl.Color(0, 255, 100, 255), rl.Color(0, 40, 15, 255)), ] for y, name, active_c, inactive_c in bulbs: if name == "red" and active_light == "red": glow_pulse = _pulse(1.5) - rl.draw_circle_v(rl.Vector2(cx_light, y), r_bulb + 3.0 * SCALE * glow_pulse, _fade(rl.Color(255, 30, 60, 45), alpha)) - rl.draw_circle_v(rl.Vector2(cx_light, y), r_bulb + 6.0 * SCALE * glow_pulse, _fade(rl.Color(255, 30, 60, 15), alpha)) + rl.draw_circle_v(rl.Vector2(cx_light, y), r_bulb + 8.0 * SCALE * glow_pulse, _fade(rl.Color(255, 30, 60, 25), alpha)) + rl.draw_circle_v(rl.Vector2(cx_light, y), r_bulb + 4.0 * SCALE * glow_pulse, _fade(rl.Color(255, 30, 60, 60), alpha)) c = _fade(active_c if active_light == name else inactive_c, alpha) rl.draw_circle_v(rl.Vector2(cx_light, y), r_bulb, c) @@ -696,16 +697,16 @@ class AetherGauge: cy_road = bottom - t_stop_gauge * road_h y_sign = cy_road - 25.0 * SCALE * smoothed_s - r_min = 6.0 * SCALE - r_max = 20.0 * SCALE + r_min = 12.0 * SCALE + r_max = 28.0 * SCALE r_sign = r_min + (smoothed_s ** 2.0) * (r_max - r_min) - shadow_alpha = int(min(120, r_sign * 12)) + shadow_alpha = int(min(140, r_sign * 10)) rl.draw_poly(rl.Vector2(cx_stop, y_sign + 2.0), 8, r_sign, 22.5, _fade(rl.Color(0, 0, 0, shadow_alpha), alpha)) rl.draw_poly(rl.Vector2(cx_stop, y_sign), 8, r_sign, 22.5, _fade(COLOR_FORCE_STOP, alpha)) - outline_t = max(0.8, min(1.5, r_sign * 0.07)) - outline_a = int(max(0, min(200, (r_sign - 5.0) * 20))) + outline_t = max(1.5, min(2.5, r_sign * 0.08)) + outline_a = int(max(0, min(220, (r_sign - 5.0) * 20))) if outline_a > 20: for i in range(8): a1 = math.radians(22.5 + i * 45.0) @@ -714,9 +715,9 @@ class AetherGauge: p2 = rl.Vector2(cx_stop + r_sign * math.cos(a2), y_sign + r_sign * math.sin(a2)) rl.draw_line_ex(p1, p2, outline_t, _fade(_with_alpha(COLOR_STOP_SIGN_OUTLINE, outline_a), alpha)) - if r_sign < 8.0 * SCALE: + if r_sign < 10.0 * SCALE: return - stop_font_size = max(10, int(r_sign * 0.7)) + stop_font_size = max(14, int(r_sign * 0.7)) stop_txt_size = measure_text_cached(font_bold, "STOP", stop_font_size) rl.draw_text_ex(font_bold, "STOP", rl.Vector2(cx_stop - stop_txt_size.x / 2, y_sign - stop_txt_size.y / 2), stop_font_size, 0, _fade(rl.WHITE, alpha)) @@ -725,30 +726,30 @@ class AetherGauge: return if data.is_numeric: - val_size = measure_text_cached(font_bold, data.text, int(48 * SCALE)) - val_pos = rl.Vector2(int(cx - val_size.x / 2), int(bottom + 12 * SCALE)) - _draw_text_with_shadow(font_bold, data.text, val_pos, int(48 * SCALE), data.color, alpha) + val_size = measure_text_cached(font_bold, data.text, int(50 * SCALE)) + val_pos = rl.Vector2(int(cx - val_size.x / 2), int(bottom + 6 * SCALE)) + _draw_text_with_shadow(font_bold, data.text, val_pos, int(50 * SCALE), data.color, alpha) - accent_y = int(bottom + 12 * SCALE + val_size.y + 2 * SCALE) - accent_w = int(val_size.x + 12 * SCALE) + accent_y = int(val_pos.y + val_size.y + 2 * SCALE) + accent_w = int(val_size.x + 16 * SCALE) accent_x = int(cx - accent_w / 2) rl.draw_line_ex( rl.Vector2(accent_x, accent_y), rl.Vector2(accent_x + accent_w, accent_y), 2.0 * SCALE, - _fade(_with_alpha(data.color, 150), alpha), + _fade(_with_alpha(data.color, 160), alpha), ) if data.reduction_text: - red_size = measure_text_cached(font_medium, data.reduction_text, int(20 * SCALE)) - red_pos = rl.Vector2(int(cx + val_size.x / 2 + 8 * SCALE), int(bottom + 12 * SCALE + val_size.y / 2 - red_size.y / 2)) - _draw_text_with_shadow(font_medium, data.reduction_text, red_pos, int(20 * SCALE), COLOR_REDUCTION, alpha) + red_size = measure_text_cached(font_medium, data.reduction_text, int(22 * SCALE)) + red_pos = rl.Vector2(int(cx + val_size.x / 2 + 6 * SCALE), int(val_pos.y + val_size.y / 2 - red_size.y / 2)) + _draw_text_with_shadow(font_medium, data.reduction_text, red_pos, int(22 * SCALE), COLOR_REDUCTION, alpha) if data.unit: - unit_size = measure_text_cached(font_medium, data.unit, int(18 * SCALE)) - unit_pos = rl.Vector2(int(cx - unit_size.x / 2), int(bottom + 12 * SCALE + val_size.y + 4 * SCALE)) - _draw_text_with_shadow(font_medium, data.unit, unit_pos, int(18 * SCALE), rl.Color(255, 255, 255, 160), alpha) + unit_size = measure_text_cached(font_medium, data.unit, int(20 * SCALE)) + unit_pos = rl.Vector2(int(cx - unit_size.x / 2), int(accent_y + 3 * SCALE)) + _draw_text_with_shadow(font_medium, data.unit, unit_pos, int(20 * SCALE), rl.Color(255, 255, 255, 180), alpha) else: - val_size = measure_text_cached(font_bold, data.text, int(24 * SCALE)) - val_pos = rl.Vector2(int(cx - val_size.x / 2), int(bottom + 16 * SCALE)) - _draw_text_with_shadow(font_bold, data.text, val_pos, int(24 * SCALE), data.color, alpha) + val_size = measure_text_cached(font_bold, data.text, int(32 * SCALE)) + val_pos = rl.Vector2(int(cx - val_size.x / 2), int(bottom + 10 * SCALE)) + _draw_text_with_shadow(font_bold, data.text, val_pos, int(32 * SCALE), data.color, alpha) diff --git a/selfdrive/ui/onroad/starpilot/widgets/aethergauge.py b/selfdrive/ui/onroad/starpilot/widgets/aethergauge.py index 352c9cb8b..168d5874c 100644 --- a/selfdrive/ui/onroad/starpilot/widgets/aethergauge.py +++ b/selfdrive/ui/onroad/starpilot/widgets/aethergauge.py @@ -2,7 +2,7 @@ import pyray as rl from openpilot.common.filter_simple import FirstOrderFilter from openpilot.system.ui.lib.application import gui_app, FontWeight from openpilot.selfdrive.ui.onroad.starpilot.widgets.base import LayoutWidget -from openpilot.selfdrive.ui.onroad.starpilot.aethergauge import AetherGauge +from openpilot.selfdrive.ui.onroad.starpilot.aethergauge import AetherGauge, _fade class AetherGaugeWidget(LayoutWidget): def __init__(self, hud_renderer): @@ -18,17 +18,18 @@ class AetherGaugeWidget(LayoutWidget): return self._aethergauge.has_active_source() def get_size(self) -> tuple[float, float]: - # Width 180, height 250 covers the road visual and the mini text cradle - return 180.0, 250.0 + # Width 172 aligns with SetSpeedWidget; height 260 covers the road visual and text cradle + return 172.0, 260.0 def _render(self, rect: rl.Rectangle) -> None: target = 1.0 if self._aethergauge.has_active_source() else 0.0 alpha = self._alpha_filter.update(target) if alpha < 0.02: return + cx = rect.x + rect.width / 2 - # Set the road bottom to rect.y + 130, leaving 120px for the text cradle underneath - bottom = rect.y + 130 + # Set the road bottom to rect.y + 145, leaving 115px for the text cradle underneath + bottom = rect.y + 145.0 self._aethergauge.render( rect, self._font_bold, self._font_medium, current_speed=self.hud_renderer.speed,