From 0857acfc502e10d8b7af5cfda5a75e803090dea7 Mon Sep 17 00:00:00 2001 From: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Date: Fri, 2 Oct 2026 14:24:05 -0400 Subject: [PATCH] big ui text size polish --- .../layouts/settings/starpilot/aethergrid.py | 184 +++++++++--------- .../settings/starpilot/driving_model.py | 85 ++++---- .../ui/layouts/settings/starpilot/lateral.py | 3 +- 3 files changed, 140 insertions(+), 132 deletions(-) diff --git a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py index 21c23a4660..c166a4e020 100644 --- a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py +++ b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py @@ -382,8 +382,9 @@ def point_hits(mouse_pos: MousePos, rect: rl.Rectangle, parent_rect: rl.Rectangl return hit.width > 0 and hit.height > 0 and rl.check_collision_point_rec(mouse_pos, hit) -def wrap_text(font: rl.Font, text: str, max_width: float, font_size: float, max_lines: int = 2) -> list[str]: - spacing = font_size * 0.15 +def wrap_text(font: rl.Font, text: str, max_width: float, font_size: float, max_lines: int = 2, + *, spacing: float | None = None) -> list[str]: + spacing = font_size * 0.15 if spacing is None else spacing words = text.split() lines: list[str] = [] current = "" @@ -1434,11 +1435,23 @@ class BreadcrumbController: aether_end_scissor_mode() PANEL_HEADER_TITLE_Y: int = 34 PANEL_HEADER_SUBTITLE_Y: int = 78 -PANEL_HEADER_TITLE_FONT_SIZE: int = 30 -PANEL_HEADER_SUBTITLE_FONT_SIZE: int = 26 +PANEL_HEADER_TITLE_FONT_SIZE: int = 44 +PANEL_HEADER_SUBTITLE_FONT_SIZE: int = 32 PANEL_HEADER_TITLE_FONT: FontWeight = FontWeight.SEMI_BOLD PANEL_HEADER_SUBTITLE_FONT: FontWeight = FontWeight.NORMAL -PANEL_HEADER_SUBTITLE_LINE_HEIGHT: float = 30.0 # subtitle_size(26) + interline_gap(4) +SETTINGS_ROW_TITLE_FONT_SIZE: int = 40 +SETTINGS_ROW_SUBTITLE_FONT_SIZE: int = 28 +SETTINGS_ROW_VALUE_FONT_SIZE: int = 34 + + +def _settings_panel_header_layout(width: float, subtitle: str | None, title_size: int, subtitle_size: int, + subtitle_weight: FontWeight = PANEL_HEADER_SUBTITLE_FONT, + min_title_height: float = 0.0) -> tuple[float, list[str], float, float]: + title_height = max(title_size * FONT_SCALE, min_title_height) + line_height = subtitle_size * FONT_SCALE + SPACING.xs + lines = wrap_text(gui_app.font(subtitle_weight), subtitle, width, subtitle_size, max_lines=4, spacing=0) if subtitle else [] + height = title_height + (SPACING.sm + len(lines) * line_height - SPACING.xs if lines else 0.0) + return title_height, lines, line_height, height def draw_settings_panel_header(header_rect: rl.Rectangle, title: str, subtitle: str | None = None, @@ -1450,19 +1463,22 @@ def draw_settings_panel_header(header_rect: rl.Rectangle, title: str, subtitle: title_color: rl.Color = AetherListColors.HEADER, subtitle_color: rl.Color = AetherListColors.SUBTEXT, title_weight: FontWeight = PANEL_HEADER_TITLE_FONT, - subtitle_weight: FontWeight = PANEL_HEADER_SUBTITLE_FONT): + subtitle_weight: FontWeight = PANEL_HEADER_SUBTITLE_FONT, + min_title_height: float = 0.0): if not title: return title_font = gui_app.font(title_weight) - y = header_rect.y - rl.draw_text_ex(title_font, title, rl.Vector2(header_rect.x, y), title_size, 0, title_color) - y += title_size + 8 - if subtitle: + title_height, desc_lines, line_height, _ = _settings_panel_header_layout( + header_rect.width * max_subtitle_width, subtitle, title_size, subtitle_size, subtitle_weight, min_title_height, + ) + y = header_rect.y + (title_height - title_size * FONT_SCALE) / 2 + draw_text_fit_common(title_font, title, rl.Vector2(header_rect.x, y), header_rect.width * max_title_width, title_size, color=title_color) + y = header_rect.y + title_height + SPACING.sm + if desc_lines: desc_font = gui_app.font(subtitle_weight) - desc_lines = wrap_text(desc_font, subtitle, header_rect.width * max_subtitle_width, subtitle_size, max_lines=4) for line in desc_lines: - rl.draw_text_ex(desc_font, line, rl.Vector2(header_rect.x, y), subtitle_size, 0, subtitle_color) - y += subtitle_size + 4 + draw_text_fit_common(desc_font, line, rl.Vector2(header_rect.x, y), header_rect.width * max_subtitle_width, subtitle_size, color=subtitle_color) + y += line_height @@ -1590,7 +1606,6 @@ def draw_standard_toggle_row( pressed=pressed, is_last=is_last, show_chevron=False, - title_size=36, subtitle_size=26, style=style, ) @@ -1783,7 +1798,7 @@ def draw_action_pill( draw_text_fit_common( gui_app.font(FontWeight.SEMI_BOLD), text, - rl.Vector2(rect.x + 12, rect.y + (rect.height - font_size) / 2), + rl.Vector2(rect.x + 12, rect.y + (rect.height - font_size * FONT_SCALE) / 2), max(1.0, rect.width - 24), font_size, align_center=True, @@ -2099,9 +2114,9 @@ def draw_settings_list_row( pressed: bool = False, is_last: bool = False, show_chevron: bool = True, - title_size: int = 36, - subtitle_size: int = 26, - value_size: int = 28, + title_size: int = SETTINGS_ROW_TITLE_FONT_SIZE, + subtitle_size: int = SETTINGS_ROW_SUBTITLE_FONT_SIZE, + value_size: int = SETTINGS_ROW_VALUE_FONT_SIZE, separator_inset: int = 24, title_color: rl.Color | None = None, subtitle_color: rl.Color | None = None, @@ -2139,9 +2154,9 @@ def draw_settings_list_row( text_width = max(100.0, text_right - text_left) if subtitle: - eff_title_size = min(36, title_size) - eff_sub_size = min(26, subtitle_size) - total_h = eff_title_size + eff_sub_size + 4 + eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size) + eff_sub_size = min(SETTINGS_ROW_SUBTITLE_FONT_SIZE, subtitle_size) + total_h = (eff_title_size + eff_sub_size) * FONT_SCALE + SPACING.xs start_y = draw_rect.y + (draw_rect.height - total_h) / 2 draw_text_fit_common( @@ -2152,13 +2167,13 @@ def draw_settings_list_row( ) draw_text_fit_common( gui_app.font(FontWeight.NORMAL), subtitle, - rl.Vector2(text_left, start_y + eff_title_size + 4), + rl.Vector2(text_left, start_y + eff_title_size * FONT_SCALE + SPACING.xs), text_width, eff_sub_size, color=resolved_subtitle_color, ) else: - eff_title_size = min(36, title_size) - title_y = draw_rect.y + (draw_rect.height - eff_title_size) / 2 + eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size) + title_y = draw_rect.y + (draw_rect.height - eff_title_size * FONT_SCALE) / 2 draw_text_fit_common( gui_app.font(FontWeight.SEMI_BOLD), title, rl.Vector2(text_left, title_y), @@ -2188,11 +2203,11 @@ def draw_settings_list_row( if value: if is_narrow and draw_rect.height >= 86 and not subtitle: # Adaptive Two-Line Stacked Layout: Title on top, Value spanning full width below - eff_title_size = min(34, title_size) - eff_value_size = min(28, value_size) + eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size) + eff_value_size = min(SETTINGS_ROW_VALUE_FONT_SIZE, value_size) available_w = max(100.0, draw_rect.width - 48 - (32 if show_chevron else 0)) - total_h = eff_title_size + eff_value_size + 6 + total_h = (eff_title_size + eff_value_size) * FONT_SCALE + 6 start_y = draw_rect.y + (draw_rect.height - total_h) / 2 draw_text_fit_common( @@ -2203,7 +2218,7 @@ def draw_settings_list_row( ) draw_text_fit_common( gui_app.font(FontWeight.MEDIUM), value, - rl.Vector2(text_left, start_y + eff_title_size + 6), + rl.Vector2(text_left, start_y + eff_title_size * FONT_SCALE + 6), available_w, eff_value_size, color=resolved_subtitle_color if resolved_value_color == resolved_title_color else resolved_value_color, ) @@ -2219,13 +2234,13 @@ def draw_settings_list_row( t_width = max(100.0, draw_rect.width - 48 - v_width - (32 if show_chevron else 0)) v_right = chevron_rect.x - 16 if show_chevron else draw_rect.x + draw_rect.width - 24 - eff_value_size = min(28, value_size) if is_narrow else min(32, value_size) - value_y = draw_rect.y + (draw_rect.height - eff_value_size) / 2 + eff_value_size = min(SETTINGS_ROW_VALUE_FONT_SIZE, value_size) + value_y = draw_rect.y + (draw_rect.height - eff_value_size * FONT_SCALE) / 2 if subtitle: - eff_title_size = min(34, title_size) - eff_sub_size = min(26, subtitle_size) - total_h = eff_title_size + eff_sub_size + 4 + eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size) + eff_sub_size = min(SETTINGS_ROW_SUBTITLE_FONT_SIZE, subtitle_size) + total_h = (eff_title_size + eff_sub_size) * FONT_SCALE + SPACING.xs start_y = draw_rect.y + (draw_rect.height - total_h) / 2 draw_text_fit_common( @@ -2236,13 +2251,13 @@ def draw_settings_list_row( ) draw_text_fit_common( gui_app.font(FontWeight.NORMAL), subtitle, - rl.Vector2(text_left, start_y + eff_title_size + 4), + rl.Vector2(text_left, start_y + eff_title_size * FONT_SCALE + SPACING.xs), t_width, eff_sub_size, color=resolved_subtitle_color, ) else: - eff_title_size = min(36, title_size) if is_narrow else title_size - title_y = draw_rect.y + (draw_rect.height - eff_title_size) / 2 + eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size) if is_narrow else title_size + title_y = draw_rect.y + (draw_rect.height - eff_title_size * FONT_SCALE) / 2 draw_text_fit_common( gui_app.font(FontWeight.SEMI_BOLD), title, @@ -2267,9 +2282,9 @@ def draw_settings_list_row( text_right = chevron_rect.x - 12 if show_chevron else draw_rect.x + draw_rect.width - 24 text_width = max(100.0, text_right - text_left) if subtitle: - eff_title_size = min(36, title_size) - eff_sub_size = min(26, subtitle_size) - total_h = eff_title_size + eff_sub_size + 4 + eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size) + eff_sub_size = min(SETTINGS_ROW_SUBTITLE_FONT_SIZE, subtitle_size) + total_h = (eff_title_size + eff_sub_size) * FONT_SCALE + SPACING.xs start_y = draw_rect.y + (draw_rect.height - total_h) / 2 draw_text_fit_common( gui_app.font(FontWeight.SEMI_BOLD), title, @@ -2279,13 +2294,13 @@ def draw_settings_list_row( ) draw_text_fit_common( gui_app.font(FontWeight.NORMAL), subtitle, - rl.Vector2(text_left, start_y + eff_title_size + 4), + rl.Vector2(text_left, start_y + eff_title_size * FONT_SCALE + SPACING.xs), text_width, eff_sub_size, color=resolved_subtitle_color, ) else: - eff_title_size = min(36, title_size) - title_y = draw_rect.y + (draw_rect.height - eff_title_size) / 2 + eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size) + title_y = draw_rect.y + (draw_rect.height - eff_title_size * FONT_SCALE) / 2 draw_text_fit_common( gui_app.font(FontWeight.SEMI_BOLD), title, rl.Vector2(text_left, title_y), @@ -2950,11 +2965,11 @@ def draw_selection_list_row( subtitle_font = gui_app.font(FontWeight.NORMAL) if subtitle: - text_height = title_size + subtitle_size + 8 + text_height = (title_size + subtitle_size) * FONT_SCALE + 8 title_y = info_rect.y + (info_rect.height - text_height) / 2 - subtitle_y = title_y + title_size + 8 + subtitle_y = title_y + title_size * FONT_SCALE + 8 else: - title_y = info_rect.y + (info_rect.height - title_size) / 2 + title_y = info_rect.y + (info_rect.height - title_size * FONT_SCALE) / 2 subtitle_y = title_y draw_text_fit_common( @@ -3112,7 +3127,7 @@ class AetherButton(Widget): draw_text_fit_common( gui_app.font(FontWeight.MEDIUM), self.text, - rl.Vector2(rect.x + 18, rect.y + (rect.height - self._font_size) / 2), + rl.Vector2(rect.x + 18, rect.y + (rect.height - self._font_size * FONT_SCALE) / 2), max(1.0, rect.width - 36), self._font_size, align_center=True, @@ -3265,7 +3280,7 @@ class AetherSettingsView(PanelManagerView): if self._parent_toggle: mid = f"parent_toggle:{self._parent_toggle.label}" rect = self._interactive_rects.get(mid) - if rect and point_hits(mouse_pos, rect, None, pad_x=6, pad_y=6): + if rect and point_hits(mouse_pos, rect, None, pad_x=0, pad_y=0): return mid return super()._target_at(mouse_pos) @@ -3290,32 +3305,29 @@ class AetherSettingsView(PanelManagerView): elif row.type == "toggle" and row.set_state and row.get_state: row.set_state(not row.get_state()) + def _header_text(self) -> tuple[str, str]: + title, subtitle = self._header_title, self._header_subtitle + if self._parent_toggle: + title = title or self._parent_toggle.label + subtitle = subtitle or self._parent_toggle.subtitle + return tr(title), tr(subtitle) if subtitle else "" + + def _header_text_width(self, width: float) -> float: + right_inset = SPACING.xl + if self._parent_toggle: + right_inset = AETHER_LIST_METRICS.toggle_width + AETHER_LIST_METRICS.toggle_right_inset + SPACING.lg + return max(100.0, width - SPACING.xl - right_inset) + def _compute_header_height(self, content_width: float) -> float: if not self._has_header: return 0.0 - if self._parent_toggle: - h = max(float(AETHER_LIST_METRICS.toggle_height), 54.0) # toggle vs title(46px + 8px gap) - subtitle_text = tr(self._parent_toggle.subtitle) if self._parent_toggle.subtitle else "" - if self._header_subtitle: - subtitle_text = tr(self._header_subtitle) - if subtitle_text: - toggle_take = AETHER_LIST_METRICS.toggle_width + AETHER_LIST_METRICS.toggle_right_inset + 16 - col_w = max(100.0, content_width + AETHER_LIST_METRICS.content_right_gutter - toggle_take) - desc_font = gui_app.font(FontWeight.NORMAL) - desc_lines = wrap_text(desc_font, subtitle_text, col_w, 29, max_lines=4) - h += len(desc_lines) * PANEL_HEADER_SUBTITLE_LINE_HEIGHT + 12.0 - h += SECTION_GAP - return h - h = 54.0 # title (46px) + inner gap (8px) - if self._header_subtitle: - subtitle_text = tr(self._header_subtitle) - if subtitle_text: - desc_font = gui_app.font(FontWeight.NORMAL) - col_w = (content_width - self.COLUMN_GAP) / 2 if self._uses_two_columns(content_width) else content_width - desc_lines = wrap_text(desc_font, subtitle_text, col_w, 29, max_lines=4) - h += len(desc_lines) * PANEL_HEADER_SUBTITLE_LINE_HEIGHT + 12.0 - h += SECTION_GAP - return h + _, subtitle = self._header_text() + _, _, _, height = _settings_panel_header_layout( + self._header_text_width(content_width + AETHER_LIST_METRICS.content_right_gutter), subtitle, + PANEL_HEADER_TITLE_FONT_SIZE, PANEL_HEADER_SUBTITLE_FONT_SIZE, + min_title_height=AETHER_LIST_METRICS.toggle_height if self._parent_toggle else 0.0, + ) + return height + SECTION_GAP def _render(self, rect: rl.Rectangle): self.set_rect(rect) @@ -3357,25 +3369,18 @@ class AetherSettingsView(PanelManagerView): AetherListColors.PANEL_BG, fade_height=self._fade_height) def _draw_header(self, rect: rl.Rectangle): - title = tr(self._header_title) if self._header_title else "" - subtitle = tr(self._header_subtitle) if self._header_subtitle else "" + title, subtitle = self._header_text() + text_rect = rl.Rectangle(rect.x + SPACING.xl, rect.y, self._header_text_width(rect.width), rect.height) + draw_settings_panel_header( + text_rect, title, subtitle, max_title_width=1.0, max_subtitle_width=1.0, + min_title_height=AETHER_LIST_METRICS.toggle_height if self._parent_toggle else 0.0, + ) if self._parent_toggle: toggle = self._parent_toggle - - display_title = title if title else tr(toggle.label) - subtitle_text = subtitle if subtitle else (tr(toggle.subtitle) if toggle.subtitle else "") - - toggle_take = AETHER_LIST_METRICS.toggle_width + AETHER_LIST_METRICS.toggle_right_inset + 16 - text_rect = rl.Rectangle(rect.x, rect.y, max(100.0, rect.width - toggle_take), rect.height) - draw_settings_panel_header(text_rect, display_title, subtitle_text, title_size=30, subtitle_size=26, max_subtitle_width=1.0) - toggle_id = f"parent_toggle:{toggle.label}" - tw = AETHER_LIST_METRICS.toggle_width th = AETHER_LIST_METRICS.toggle_height - ri = AETHER_LIST_METRICS.toggle_right_inset - toggle_rect = rl.Rectangle(rect.x + rect.width - tw - ri, rect.y, tw, th) - self._interactive_rects[toggle_id] = toggle_rect + self._interactive_rects[toggle_id] = rl.Rectangle(rect.x, rect.y, rect.width, rect.height - SECTION_GAP) toggle_value = toggle.get_state() @@ -3388,8 +3393,6 @@ class AetherSettingsView(PanelManagerView): radius_px=100, bg_color=rl.Color(12, 10, 18, 255), ) - else: - draw_settings_panel_header(rect, title, subtitle, title_size=30, subtitle_size=26) def _active_sections(self) -> list[SettingSection]: if self._tab_defs and self._active_tab_key: @@ -3483,11 +3486,11 @@ class AetherSettingsView(PanelManagerView): group_h = max(section_h, right_h) draw_section_header( - rl.Rectangle(rect.x, y, col_w, SECTION_HEADER_HEIGHT), + rl.Rectangle(rect.x + SPACING.xl, y, col_w - SPACING.xl * 2, SECTION_HEADER_HEIGHT), tr(section.title), style=self._panel_style, ) draw_section_header( - rl.Rectangle(rect.x + col_w + self.COLUMN_GAP, y, col_w, SECTION_HEADER_HEIGHT), + rl.Rectangle(rect.x + col_w + self.COLUMN_GAP + SPACING.xl, y, col_w - SPACING.xl * 2, SECTION_HEADER_HEIGHT), tr(right_section.title), style=self._panel_style, ) y += SECTION_HEADER_HEIGHT + SECTION_HEADER_GAP @@ -3514,7 +3517,7 @@ class AetherSettingsView(PanelManagerView): section: SettingSection, rows: list[SettingRow]) -> float: if section.title: draw_section_header( - rl.Rectangle(x, y, width, SECTION_HEADER_HEIGHT), + rl.Rectangle(x + SPACING.xl, y, width - SPACING.xl * 2, SECTION_HEADER_HEIGHT), tr(section.title), style=self._panel_style, ) @@ -3555,7 +3558,6 @@ class AetherSettingsView(PanelManagerView): pressed=pressed, is_last=is_last, show_chevron=row.on_click is not None, - title_size=36, subtitle_size=26, value_size=30, style=self._panel_style, ) elif row.type == "action": @@ -3571,7 +3573,7 @@ class AetherSettingsView(PanelManagerView): pressed=pressed, is_last=is_last, action_pill=True, - title_size=36, subtitle_size=26, + title_size=SETTINGS_ROW_TITLE_FONT_SIZE, subtitle_size=SETTINGS_ROW_SUBTITLE_FONT_SIZE, action_pill_height=AETHER_LIST_METRICS.toggle_height, action_text_size=26, action_text_color=action_text_color, action_fill=action_fill, diff --git a/selfdrive/ui/layouts/settings/starpilot/driving_model.py b/selfdrive/ui/layouts/settings/starpilot/driving_model.py index eb9e0e1c13..ebea4d6ac7 100644 --- a/selfdrive/ui/layouts/settings/starpilot/driving_model.py +++ b/selfdrive/ui/layouts/settings/starpilot/driving_model.py @@ -26,7 +26,7 @@ from openpilot.starpilot.assets.model_manager import ( set_model_profile, ) from openpilot.starpilot.common.starpilot_variables import MODELS_PATH, update_starpilot_toggles -from openpilot.system.ui.lib.application import FontWeight, MouseEvent, MousePos, gui_app +from openpilot.system.ui.lib.application import FONT_SCALE, FontWeight, MouseEvent, MousePos, gui_app from openpilot.system.ui.lib.multilang import tr from openpilot.system.ui.lib.scroll_panel2 import GuiScrollPanel2 from openpilot.system.ui.widgets import DialogResult, Widget @@ -63,6 +63,9 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import ( SECTION_HEADER_HEIGHT, SECTION_HEADER_GAP, ROW_HEIGHT, + SETTINGS_ROW_TITLE_FONT_SIZE, + SETTINGS_ROW_SUBTITLE_FONT_SIZE, + SPACING, ) ROW_RADIUS = AETHER_LIST_METRICS.row_radius ACTION_WIDTH = AETHER_LIST_METRICS.action_width @@ -74,10 +77,10 @@ TRANSITION_SECONDS = 0.24 PANEL_STYLE = DEFAULT_PANEL_STYLE BANNER_HEIGHT = 128.0 BANNER_GAP = 14.0 -HEADER_BUTTON_HEIGHT = 80.0 +HEADER_BUTTON_HEIGHT = float(ROW_HEIGHT) HEADER_BUTTON_GAP_Y = 14.0 -MANAGEMENT_STRIP_HEIGHT = 64.0 -MANAGEMENT_PILL_HEIGHT = 44.0 +MANAGEMENT_STRIP_HEIGHT = float(ROW_HEIGHT) +MANAGEMENT_PILL_HEIGHT = float(AETHER_LIST_METRICS.toggle_height) EMPTY_STATE_HEIGHT = 240.0 _SORT_MODES = ("alphabetical", "date", "date_oldest", "favorites", "community_picks") _SORT_LABELS = { @@ -136,6 +139,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): lambda: self._controller.cancel_active_download() if self._controller._is_download_active() else self._controller.download_all_missing(), enabled=lambda: self._controller.primary_header_button_state()[1], emphasized=True, + font_size=SETTINGS_ROW_TITLE_FONT_SIZE, accent_color=rl.Color(139, 92, 246, 92), ) ) @@ -145,6 +149,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): self._controller.refresh_manifest, enabled=lambda: self._controller.secondary_header_button_state()[1], emphasized=False, + font_size=SETTINGS_ROW_TITLE_FONT_SIZE, ) ) self._random_model_button = self._child( @@ -152,7 +157,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): lambda: self._controller.random_model_button_label(), self._controller.toggle_model_randomizer, emphasized=False, - font_size=28, + font_size=SETTINGS_ROW_TITLE_FONT_SIZE, ) ) self._primary_header_button.set_touch_valid_callback(lambda: self._scroll_panel.is_touch_valid()) @@ -212,12 +217,11 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): for prefix in ("menu:", "action:", "row:"): for target_id, rect in self._interactive_rects.items(): if target_id.startswith(prefix): - pad_y = 6 if prefix == "menu:" else 0 - if point_hits(mouse_pos, rect, self._scroll_rect, pad_x=6, pad_y=pad_y): + if point_hits(mouse_pos, rect, self._scroll_rect, pad_x=0, pad_y=0): return target_id for target_id, rect in self._interactive_rects.items(): if target_id.startswith("sortopt:") or target_id.startswith("mgmt:"): - if point_hits(mouse_pos, rect, self._shell_rect, pad_x=6, pad_y=6): + if point_hits(mouse_pos, rect, self._shell_rect, pad_x=0, pad_y=0): return target_id return None @@ -365,7 +369,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): pill_h = MANAGEMENT_PILL_HEIGHT pill_y = y + (MANAGEMENT_STRIP_HEIGHT - pill_h) / 2 left = x + 16 - gap = 8.0 + gap = float(SPACING.lg) usable = width - 32.0 if randomizer_on: @@ -377,14 +381,14 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): draw_action_pill(bl_pill, bl_label, with_alpha(AetherListColors.PRIMARY, 18), with_alpha(AetherListColors.PRIMARY, 50), - AetherListColors.HEADER, font_size=28, roundness=0.35) - self._interactive_rects["mgmt:blacklist"] = bl_pill + AetherListColors.HEADER, font_size=30, roundness=0.35) + self._interactive_rects["mgmt:blacklist"] = rl.Rectangle(bl_pill.x, y, bl_w, MANAGEMENT_STRIP_HEIGHT) rt_pill = rl.Rectangle(left + bl_w + gap, pill_y, rt_w, pill_h) draw_action_pill(rt_pill, tr("Ratings"), with_alpha(AetherListColors.PRIMARY, 18), with_alpha(AetherListColors.PRIMARY, 50), - AetherListColors.HEADER, font_size=28, roundness=0.35) - self._interactive_rects["mgmt:ratings"] = rt_pill + AetherListColors.HEADER, font_size=30, roundness=0.35) + self._interactive_rects["mgmt:ratings"] = rl.Rectangle(rt_pill.x, y, rt_w, MANAGEMENT_STRIP_HEIGHT) return sort_mode = self._controller._get_sort_mode() @@ -410,8 +414,8 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): else: fill = rl.Color(255, 255, 255, 8) border = with_alpha(AetherListColors.PRIMARY, 80) if is_active else rl.Color(255, 255, 255, 24) - draw_action_pill(seg_rect, label, fill, border, AetherListColors.HEADER, font_size=28, roundness=0.3) - self._interactive_rects[f"sortopt:{mode}"] = seg_rect + draw_action_pill(seg_rect, label, fill, border, AetherListColors.HEADER, font_size=30, roundness=0.3) + self._interactive_rects[f"sortopt:{mode}"] = rl.Rectangle(seg_x, y, seg_w, MANAGEMENT_STRIP_HEIGHT) def _get_sections(self) -> list[tuple[str, list[ModelCatalogEntry]]]: sort_mode = self._controller._get_sort_mode() @@ -479,7 +483,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): ) def _draw_model_section(self, x: float, y: float, width: float, title: str, entries: list[ModelCatalogEntry]) -> float: - draw_section_header(rl.Rectangle(x, y, width, SECTION_HEADER_HEIGHT), title, style=PANEL_STYLE) + draw_section_header(rl.Rectangle(x + SPACING.xl, y, width - SPACING.xl * 2, SECTION_HEADER_HEIGHT), title, style=PANEL_STYLE) y += SECTION_HEADER_HEIGHT + SECTION_HEADER_GAP group_rect = rl.Rectangle(x, y, width, len(entries) * ROW_HEIGHT) @@ -522,12 +526,16 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): separator_inset=22, ) - action_rect = draw_action_rail(draw_rect, ACTION_WIDTH, current=current, alpha=alpha, fill=AetherListColors.ACTION_BG, separator=AetherListColors.ACTION_SEPARATOR, inset_y=18) + action_width = ACTION_WIDTH * 2 + SPACING.lg if is_menu_open else ACTION_WIDTH + action_rect = draw_action_rail( + draw_rect, action_width, current=current, alpha=alpha, + fill=AetherListColors.ACTION_BG, separator=AetherListColors.ACTION_SEPARATOR, inset_y=18, + ) - info_rect = rl.Rectangle(draw_rect.x + 24, draw_rect.y + 18, draw_rect.width - ACTION_WIDTH - 42, draw_rect.height - 36) + info_rect = rl.Rectangle(draw_rect.x + 24, draw_rect.y + 18, draw_rect.width - action_width - 42, draw_rect.height - 36) row_touchable = entry.installed and not self._controller._params.get_bool("ModelRandomizer") if row_touchable: - self._interactive_rects[f"row:{entry.key}"] = draw_rect + self._interactive_rects[f"row:{entry.key}"] = rl.Rectangle(draw_rect.x, draw_rect.y, draw_rect.width - action_width, draw_rect.height) self._draw_model_info(info_rect, entry, current) @@ -538,7 +546,8 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): elif not removable: self._draw_protected_action(action_rect) else: - self._interactive_rects[f"action:{entry.key}"] = action_rect + if not is_menu_open: + self._interactive_rects[f"action:{entry.key}"] = action_rect self._draw_menu_action(action_rect, is_menu_open, entry) else: self._interactive_rects[f"action:{entry.key}"] = action_rect @@ -548,20 +557,20 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): self._draw_download_action(action_rect) def _draw_model_info(self, rect: rl.Rectangle, entry: ModelCatalogEntry, current: bool): - title_size = 36 - meta_size = 26 + title_size = SETTINGS_ROW_TITLE_FONT_SIZE + meta_size = SETTINGS_ROW_SUBTITLE_FONT_SIZE inter_gap = 6 - total_h = title_size + meta_size + inter_gap + total_h = (title_size + meta_size) * FONT_SCALE + inter_gap start_y = rect.y + (rect.height - total_h) / 2 heart_offset = 0 if entry.user_favorite: heart_color = rl.Color(210, 100, 130, 230) - heart_center = rl.Vector2(rect.x + 14, start_y + title_size / 2) + heart_center = rl.Vector2(rect.x + 14, start_y + title_size * FONT_SCALE / 2) draw_heart_icon(heart_center, heart_color) heart_offset = 36 - title_rect = rl.Rectangle(rect.x + heart_offset, start_y, rect.width - heart_offset, title_size) + title_rect = rl.Rectangle(rect.x + heart_offset, start_y, rect.width - heart_offset, title_size * FONT_SCALE) gui_label(title_rect, entry.name, title_size, AetherListColors.HEADER, FontWeight.SEMI_BOLD) meta_parts: list[str] = [] @@ -585,7 +594,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): meta_parts.append(tr("Popular")) if meta_parts: - meta_rect = rl.Rectangle(rect.x, start_y + title_size + inter_gap, rect.width, meta_size) + meta_rect = rl.Rectangle(rect.x, start_y + title_size * FONT_SCALE + inter_gap, rect.width, meta_size * FONT_SCALE) has_warning = entry.partial or entry.requires_external_gpu text_color = AetherListColors.WARNING if has_warning else AetherListColors.SUBTEXT gui_label(meta_rect, " • ".join(meta_parts), meta_size, text_color, FontWeight.NORMAL if not has_warning else FontWeight.MEDIUM) @@ -632,33 +641,31 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget): alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER, ) else: - btn_h = 48 - gap = 8 - total_h = btn_h * 2 + gap - start_y = rect.y + (rect.height - total_h) / 2 - btn_w = rect.width - 28 + btn_h = AETHER_LIST_METRICS.header_button_height + gap = SPACING.lg + start_y = rect.y + (rect.height - btn_h) / 2 + btn_w = (rect.width - SPACING.md * 2 - gap) / 2 - delete_rect = rl.Rectangle(rect.x + 14, start_y, btn_w, btn_h) - fav_rect = rl.Rectangle(rect.x + 14, start_y + btn_h + gap, btn_w, btn_h) + delete_rect = rl.Rectangle(rect.x + SPACING.md, start_y, btn_w, btn_h) + fav_rect = rl.Rectangle(delete_rect.x + btn_w + gap, start_y, btn_w, btn_h) - self._interactive_rects[f"menu:{entry.key}:delete"] = delete_rect - self._interactive_rects[f"menu:{entry.key}:favorite"] = fav_rect + self._interactive_rects[f"menu:{entry.key}:delete"] = rl.Rectangle(delete_rect.x, rect.y, btn_w, rect.height) + self._interactive_rects[f"menu:{entry.key}:favorite"] = rl.Rectangle(fav_rect.x, rect.y, btn_w, rect.height) draw_action_pill( delete_rect, tr("Delete"), AetherListColors.DANGER_SOFT, rl.Color(AetherListColors.DANGER.r, AetherListColors.DANGER.g, AetherListColors.DANGER.b, min(AetherListColors.DANGER.a, 70)), - AetherListColors.DANGER, - font_size=24, + AetherListColors.HEADER, + font_size=32, ) is_fav = entry.user_favorite fav_fill = rl.Color(210, 100, 130, 44) if is_fav else rl.Color(PANEL_STYLE.accent.r, PANEL_STYLE.accent.g, PANEL_STYLE.accent.b, 26) fav_border = rl.Color((210 if is_fav else PANEL_STYLE.accent.r), (100 if is_fav else PANEL_STYLE.accent.g), (130 if is_fav else PANEL_STYLE.accent.b), min((255 if is_fav else PANEL_STYLE.accent.a), 70)) - fav_text_color = rl.Color(210, 100, 130, 255) if is_fav else PANEL_STYLE.accent fav_label = tr("Unfavorite") if is_fav else tr("Favorite") - draw_action_pill(fav_rect, fav_label, fav_fill, fav_border, fav_text_color, font_size=24) + draw_action_pill(fav_rect, fav_label, fav_fill, fav_border, AetherListColors.HEADER, font_size=32) def _draw_current_action(self, rect: rl.Rectangle): chip_h = 52 diff --git a/selfdrive/ui/layouts/settings/starpilot/lateral.py b/selfdrive/ui/layouts/settings/starpilot/lateral.py index 03032e41e7..e7e57dbd12 100644 --- a/selfdrive/ui/layouts/settings/starpilot/lateral.py +++ b/selfdrive/ui/layouts/settings/starpilot/lateral.py @@ -204,8 +204,7 @@ class StarPilotLateralLayout(_SettingsPage): ), SettingRow( "LaneChangeCloseGap", "toggle", tr_noop("Close Gap On Lane Change"), - subtitle=tr_noop("Allows for a temporary shorter follow distance behind lead so that openpilot merges smoothly " + - "out of current lane, it will allow car to accelerate as it changes lanes."), + subtitle=tr_noop("Temporarily shorten the following gap and allow acceleration while changing lanes."), get_state=lambda: p.get_bool("LaneChangeCloseGap"), set_state=lambda s: p.put_bool("LaneChangeCloseGap", s), visible=lc_on,