From 622720f730cc4777edc57d0d74f29c2deac6c355 Mon Sep 17 00:00:00 2001 From: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Date: Mon, 6 Jul 2026 02:04:28 -0400 Subject: [PATCH] BigUI WIP: Vehicle Panel Pass --- .../layouts/settings/starpilot/aethergrid.py | 44 ++++++++--- .../ui/layouts/settings/starpilot/vehicle.py | 79 ++++++++----------- 2 files changed, 63 insertions(+), 60 deletions(-) diff --git a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py index befc4b444..c478a4e0d 100644 --- a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py +++ b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py @@ -289,7 +289,7 @@ class AetherListMetrics: panel_padding_bottom: int = 22 header_height: int = 0 section_gap: int = 28 - section_header_height: int = 34 + section_header_height: int = 60 section_header_gap: int = 12 row_height: int = 122 utility_row_height: int = 88 @@ -312,7 +312,7 @@ class AetherListMetrics: utility_value_right: int = 270 utility_value_width: int = 220 utility_chevron_right: int = 62 - menu_button_font_size: int = 18 + menu_button_font_size: int = 32 menu_button_roundness: float = 0.35 menu_button_segments: int = 12 @@ -707,7 +707,7 @@ class PanelManagerView(AetherInteractiveMixin, Widget): def _compute_two_column_height(self, left_height: float) -> float: return max(self._scroll_rect.height if self._scroll_rect else 0.0, left_height) - def _draw_two_column_tile_grid(self, grid: TileGrid, x: float, y: float, column_width: float, matching_height: float, title: str | None = None, style: PanelStyle | None = None): + def _draw_two_column_tile_grid(self, grid: TileGrid, x: float, y: float, column_width: float, matching_height: float, title: str | None = None, subsection_title: str | None = None, style: PanelStyle | None = None): if style is None: style = self.PANEL_STYLE grid._columns = 2 @@ -720,7 +720,10 @@ class PanelManagerView(AetherInteractiveMixin, Widget): draw_h = max(0.0, matching_height) draw_list_group_shell(rl.Rectangle(x, draw_y, column_width, draw_h), style=style) - self._render_page_grid(grid, rl.Rectangle(x + 12, draw_y + 12, column_width - 24, max(0.0, draw_h - 24))) + inner_y = draw_y + if subsection_title: + inner_y = draw_subsection_header(x + 24, draw_y, column_width - 48, subsection_title) + self._render_page_grid(grid, rl.Rectangle(x + 12, inner_y + 12, column_width - 24, max(0.0, draw_h - (inner_y - draw_y) - 24))) # ── convenience builders ────────────────────────────────── @@ -1357,8 +1360,8 @@ def draw_status_badges( items: list[str], style: PanelStyle, *, - height: float = 28.0, - font_size: int = 17, + height: float = 44.0, + font_size: int = 28, gap: float = 8.0, padding_x: float = 18.0, text_color: rl.Color = AetherListColors.HEADER, @@ -1884,6 +1887,21 @@ GROUP_HEADER_GAP = 2.0 GROUP_HAIRLINE_COLOR = rl.Color(255, 255, 255, 10) GROUP_HEADER_COLOR = rl.Color(255, 255, 255, 90) +SUBSECTION_HEADER_HEIGHT = 36.0 +SUBSECTION_HEADER_GAP = 6.0 +SUBSECTION_HEADER_TOP_MARGIN = 8.0 +SUBSECTION_HEADER_FONT_SIZE = 24 +SUBSECTION_HEADER_COLOR = rl.Color(255, 255, 255, 200) +SUBSECTION_OVERHEAD = SUBSECTION_HEADER_TOP_MARGIN + SUBSECTION_HEADER_HEIGHT + SUBSECTION_HEADER_GAP + + +def draw_subsection_header(x: float, y: float, width: float, label: str) -> float: + header_y = y + SUBSECTION_HEADER_TOP_MARGIN + gui_label(rl.Rectangle(x, header_y, width, SUBSECTION_HEADER_HEIGHT), + label, SUBSECTION_HEADER_FONT_SIZE, SUBSECTION_HEADER_COLOR, FontWeight.MEDIUM) + return header_y + SUBSECTION_HEADER_HEIGHT + SUBSECTION_HEADER_GAP + + def draw_group_header(x: float, y: float, width: float, label: str) -> float: gui_label(rl.Rectangle(x, y, width, GROUP_HEADER_HEIGHT), label, 16, GROUP_HEADER_COLOR, FontWeight.MEDIUM) y += GROUP_HEADER_HEIGHT @@ -1896,8 +1914,8 @@ def draw_section_header( title: str = "", *, trailing_text: str = "", - title_size: int = 26, - trailing_size: int = 20, + title_size: int = 40, + trailing_size: int = 36, title_color: rl.Color | None = None, trailing_color: rl.Color | None = None, style: PanelStyle = DEFAULT_PANEL_STYLE, @@ -1989,9 +2007,9 @@ def draw_settings_list_row( pressed: bool = False, is_last: bool = False, show_chevron: bool = True, - title_size: int = 28, - subtitle_size: int = 20, - value_size: int = 24, + title_size: int = 34, + subtitle_size: int = 26, + value_size: int = 30, separator_inset: int = 22, title_color: rl.Color | None = None, subtitle_color: rl.Color | None = None, @@ -2036,7 +2054,7 @@ def draw_settings_list_row( if subtitle: draw_text_fit_common( gui_app.font(FontWeight.NORMAL), subtitle, - rl.Vector2(text_left, draw_rect.y + 54), + rl.Vector2(text_left, draw_rect.y + 64), text_width, subtitle_size, color=resolved_subtitle_color, ) @@ -2063,7 +2081,7 @@ def draw_settings_list_row( if value: value_left = draw_rect.x + draw_rect.width - AETHER_LIST_METRICS.utility_value_right value_right = chevron_rect.x - 16 if show_chevron else draw_rect.x + draw_rect.width - 24 - value_rect = rl.Rectangle(value_left, draw_rect.y + 20, max(48.0, value_right - value_left), 28) + value_rect = rl.Rectangle(value_left, draw_rect.y + 20, max(48.0, value_right - value_left), 34) gui_label( value_rect, value, diff --git a/selfdrive/ui/layouts/settings/starpilot/vehicle.py b/selfdrive/ui/layouts/settings/starpilot/vehicle.py index 3042f7e08..b9a7dada4 100644 --- a/selfdrive/ui/layouts/settings/starpilot/vehicle.py +++ b/selfdrive/ui/layouts/settings/starpilot/vehicle.py @@ -20,12 +20,11 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import ( PanelManagerView, SettingRow, TileGrid, - GROUP_HEADER_HEIGHT, - GROUP_HEADER_GAP, - draw_group_header, draw_list_group_shell, draw_section_header, draw_settings_list_row, + draw_subsection_header, + SUBSECTION_OVERHEAD, ) from openpilot.selfdrive.ui.lib.starpilot_state import starpilot_state from openpilot.selfdrive.ui.lib.fingerprint_catalog import ( @@ -66,9 +65,8 @@ def _lock_doors_timer_labels(): SECTION_GAP = 16 -SECTION_HEADER_HEIGHT = 30 +SECTION_HEADER_HEIGHT = 60 SECTION_HEADER_GAP = 8 -GROUP_OVERHEAD = GROUP_HEADER_HEIGHT + GROUP_HEADER_GAP ROW_HEIGHT = 86.0 PANEL_STYLE = DEFAULT_PANEL_STYLE @@ -79,7 +77,7 @@ class VehicleSettingsManagerView(PanelManagerView): outer_margin_y=14, panel_padding_top=16, panel_padding_bottom=14, - section_header_height=30, + section_header_height=60, section_header_gap=8, ) @@ -103,23 +101,9 @@ class VehicleSettingsManagerView(PanelManagerView): starpilot_state.update(force=True) self._rebuild_toggle_grid() - def _build_header_chips(self) -> list[str]: - cs = starpilot_state.car_state - chips = [] - if cs.canUsePedal: chips.append(tr("Pedal")) - if cs.hasSASCM: chips.append(tr("SASCM")) - if cs.canUseSDSU: chips.append(tr("SDSU")) - if cs.hasZSS: chips.append(tr("ZSS")) - if cs.hasRadar: chips.append(tr("Radar")) - if cs.hasOpenpilotLongitudinal: chips.append(tr("Long")) - if cs.hasBSM: chips.append(tr("BSM")) - if cs.hasSNG: chips.append(tr("SNG")) - return chips - def _build_identity_rows(self) -> list[SettingRow]: cs = starpilot_state.car_state fp = lambda: self._controller._params.get_bool("ForceFingerprint") - dl = "Enable Disable Fingerprinting to change." rows = [ SettingRow("ForceFingerprint", "toggle", tr_noop("Disable Fingerprinting"), subtitle=tr_noop("Manually select vehicle instead of auto-detecting."), @@ -128,11 +112,11 @@ class VehicleSettingsManagerView(PanelManagerView): SettingRow("CarMake", "value", tr_noop("Car Make"), get_value=self._controller._get_display_make, on_click=lambda: self._controller._on_select("CarMake"), - enabled=fp, disabled_label=dl), + enabled=fp), SettingRow("CarModel", "value", tr_noop("Car Model"), get_value=self._controller._get_display_model, on_click=lambda: self._controller._on_select("CarModel"), - enabled=fp, disabled_label=dl), + enabled=fp), ] if cs.isToyota: rows.append(SettingRow("LockDoorsTimer", "value", tr_noop("Lock Doors Timer"), @@ -184,15 +168,15 @@ class VehicleSettingsManagerView(PanelManagerView): value=value_text, enabled=enabled, hovered=hovered, pressed=pressed, is_last=is_last, show_chevron=row.on_click is not None, - title_size=34, subtitle_size=22, value_size=28, - style=PANEL_STYLE) + title_size=38, subtitle_size=26, value_size=32, + style=PANEL_STYLE) elif row.type == "toggle": toggle_value = row.get_state() if row.get_state else False draw_settings_list_row(rect, title=tr(row.title), subtitle=subtitle, toggle_value=toggle_value, enabled=enabled, hovered=hovered, pressed=pressed, is_last=is_last, show_chevron=False, - title_size=34, subtitle_size=22, + title_size=38, subtitle_size=26, style=PANEL_STYLE) def _draw_section(self, y: float, x: float, width: float, title: str, rows: list[SettingRow], row_height: float = ROW_HEIGHT) -> float: @@ -213,34 +197,35 @@ class VehicleSettingsManagerView(PanelManagerView): if self._uses_two_columns(width): col_w = self._column_width(width) rx = rect.x + col_w + self.COLUMN_GAP + content_y = y - draw_section_header(rl.Rectangle(rect.x, y, col_w, SECTION_HEADER_HEIGHT), - tr("Vehicle Identity"), style=PANEL_STYLE) - - caps = self._build_header_chips() - trailing = " " + tr("Vehicle Capabilities") + " " + " ".join(caps) if caps else "" - draw_section_header(rl.Rectangle(rx, y, col_w, SECTION_HEADER_HEIGHT), - tr("Features"), trailing_text=trailing, style=PANEL_STYLE) - - content_y = y + SECTION_HEADER_HEIGHT + SECTION_HEADER_GAP - + # LEFT COLUMN draw_list_group_shell(rl.Rectangle(rect.x, content_y, col_w, self._container_h), style=PANEL_STYLE) row_y = content_y + + # Vehicle Identity subsection header + row_y = draw_subsection_header(rect.x + 24, row_y, col_w - 48, tr("Vehicle Identity")) + + # All identity rows (Disable Fingerprinting, Car Make, Car Model, ...) for i, row in enumerate(identity_rows): + is_last = (i == len(identity_rows) - 1) and not steering_rows self._draw_row(rl.Rectangle(rect.x, row_y, col_w, self._left_row_height), - row, i == len(identity_rows) - 1 and not steering_rows) + row, is_last) row_y += self._left_row_height + # Steering Controls subsection header if steering_rows: - row_y = draw_group_header(rect.x + 24, row_y, col_w - 48, tr("STEERING CONTROLS")) + row_y = draw_subsection_header(rect.x + 24, row_y, col_w - 48, tr("Steering Controls")) for i, row in enumerate(steering_rows): self._draw_row(rl.Rectangle(rect.x, row_y, col_w, self._left_row_height), row, i == len(steering_rows) - 1) row_y += self._left_row_height + # RIGHT COLUMN — Feature subsection header inside tile group if self._toggle_grid.tiles: self._draw_two_column_tile_grid(self._toggle_grid, rx, content_y, col_w, - self._container_h, title=None, style=PANEL_STYLE) + self._container_h, title=None, + subsection_title=tr("Feature"), style=PANEL_STYLE) else: y = self._draw_section(y, rect.x, width, tr("Vehicle Identity"), identity_rows, self._left_row_height) y += SECTION_GAP @@ -274,24 +259,24 @@ class VehicleSettingsManagerView(PanelManagerView): tiles_h = self.measure_page_grid_height(self._toggle_grid, width - 24) if self._uses_two_columns(width): - left_content_natural = total_rows * ROW_HEIGHT + GROUP_OVERHEAD - header_h = SECTION_HEADER_HEIGHT + SECTION_HEADER_GAP + subsection_overhead = SUBSECTION_OVERHEAD + if steering_rows: + subsection_overhead += SUBSECTION_OVERHEAD - if self._scroll_rect: - available_content_h = self._scroll_rect.height - header_h - else: - available_content_h = max(left_content_natural, tiles_h) + left_content_natural = total_rows * ROW_HEIGHT + subsection_overhead + + available_content_h = self._scroll_rect.height if self._scroll_rect else max(left_content_natural, tiles_h) if left_content_natural > available_content_h and total_rows > 0: self._left_row_height = max(48.0, available_content_h / total_rows) else: self._left_row_height = ROW_HEIGHT - left_content_h = total_rows * self._left_row_height + GROUP_OVERHEAD + left_content_h = total_rows * self._left_row_height + subsection_overhead self._container_h = max(left_content_h, tiles_h) - total_h = self._compute_two_column_height(header_h + self._container_h) - self._container_h = total_h - header_h + total_h = self._compute_two_column_height(self._container_h) + self._container_h = total_h return total_h self._left_row_height = ROW_HEIGHT