Big UI : Cleanup

This commit is contained in:
firestarsdog
2026-07-16 18:57:57 -04:00
parent c6708e716f
commit 33d7e977b4
9 changed files with 187 additions and 333 deletions
@@ -1033,6 +1033,71 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
self._on_page_changed()
# ═══════════════════════════════════════════════════════════════
# AdjustorTogglesPanelView — shared adjustor+toggle-grid base
# ═══════════════════════════════════════════════════════════════
class AdjustorTogglesPanelView(PanelManagerView):
"""PanelManagerView with AetherAdjustorRow sliders + paginated toggles.
Subclasses must set ``self._adjustor_rows``, ``self._toggle_grid``,
and call ``super().__init__()``. May override ``_get_active_elements()``
to control which children receive mouse events.
"""
@property
def vertical_scrolling_disabled(self) -> bool:
return True
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._pressed_target: str | None = None
self._adjustor_rows: dict[str, AetherAdjustorRow] = {}
self._can_click = True
self._active_adjustor_key = None
def _set_active_adjustor(self, key: str, active: bool):
if active:
if self._active_adjustor_key and self._active_adjustor_key != key:
old = self._adjustor_rows.get(self._active_adjustor_key)
if old:
old.reset_interaction()
self._active_adjustor_key = key
elif self._active_adjustor_key == key:
self._active_adjustor_key = None
def show_event(self):
super().show_event()
self._pressed_target = None
self._can_click = True
def hide_event(self):
super().hide_event()
self._pressed_target = None
self._can_click = True
def _get_active_elements(self):
elems = list(self._adjustor_rows.values())
if hasattr(self, '_toggle_grid'):
elems.append(self._toggle_grid)
return elems
def _handle_mouse_press(self, mouse_pos):
super()._handle_mouse_press(mouse_pos)
for el in self._get_active_elements():
el._handle_mouse_press(mouse_pos)
def _handle_mouse_release(self, mouse_pos):
for el in self._get_active_elements():
el._handle_mouse_release(mouse_pos)
super()._handle_mouse_release(mouse_pos)
def _handle_mouse_event(self, mouse_event):
super()._handle_mouse_event(mouse_event)
for el in self._get_active_elements():
el._handle_mouse_event(mouse_event)
class BreadcrumbController:
EXPAND_DURATION: float = 2.5
@@ -3380,10 +3445,66 @@ class AetherSettingsView(PanelManagerView):
action_text_color=action_text_color,
action_fill=action_fill,
action_border=action_border,
row_separator=self._panel_style.divider_color,
row_separator=self._panel_style.divider_color,
)
# ═══════════════════════════════════════════════════════════════
# CardHubManagerView — shared HubTile card-grid landing page
# ═══════════════════════════════════════════════════════════════
class CardHubManagerView(AetherSettingsView):
"""AetherSettingsView that renders a TileGrid of HubTile navigation cards.
Subclasses override ``_build_cards()`` to return a list of card dicts
with keys ``title``, ``desc``, ``icon``, ``on_click``.
"""
@property
def vertical_scrolling_disabled(self) -> bool:
return True
def __init__(self, controller, sections, *, columns=3, padding=SPACING.tile_gap, **kwargs):
super().__init__(controller, sections, **kwargs)
self._grid = TileGrid(columns=columns, padding=padding)
self._grid.set_touch_valid_callback(lambda: self._scroll_panel.is_touch_valid())
self._child(self._grid)
self._init_cards()
def _init_cards(self):
self._grid.clear()
for d in self._build_cards():
self._grid.add_tile(HubTile(
title=d["title"], desc=d["desc"], icon_key=d["icon"],
on_click=d["on_click"],
))
def _build_cards(self) -> list[dict]:
raise NotImplementedError
def _render(self, rect: rl.Rectangle):
self.set_rect(rect)
self._interactive_rects.clear()
mx = float(self._metrics.outer_margin_x)
my = float(self._metrics.outer_margin_y)
grid_x = rect.x + mx
grid_y = rect.y + my
grid_w = rect.width - mx * 2
grid_h = rect.y + rect.height - grid_y - my
self._scroll_rect = rl.Rectangle(grid_x, grid_y, grid_w, grid_h)
self._content_height = grid_h
self._scroll_panel.set_enabled(self.is_visible)
self._scroll_offset = self._scroll_panel.update(
self._scroll_rect, self._scroll_rect.height)
self._scroll_offset = 0.0
self._draw_scroll_content(self._scroll_rect, self._scroll_rect.width)
def _draw_scroll_content(self, rect: rl.Rectangle, width: float):
y = rect.y + self._scroll_offset
self._grid.set_parent_rect(self._scroll_rect)
self._grid.render(rl.Rectangle(rect.x, y, width, rect.height))
def draw_back_button(pill_rect: rl.Rectangle, center_y: float, pressed: bool, hovered: bool) -> rl.Rectangle:
back_size = 48
back_x = pill_rect.x + 12
@@ -1,15 +1,13 @@
from __future__ import annotations
import re
import math
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.multilang import tr, tr_noop
from openpilot.system.ui.widgets import DialogResult
from openpilot.system.ui.widgets.option_dialog import MultiOptionDialog
from openpilot.selfdrive.ui.lib.starpilot_state import starpilot_state
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import _SettingsPage
import pyray as rl
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
AetherSliderDialog,
DEFAULT_PANEL_STYLE,
@@ -17,10 +15,7 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
SettingRow,
SettingSection,
AetherSettingsView,
TileGrid,
HubTile,
draw_list_group_shell,
AetherListColors,
CardHubManagerView,
)
from openpilot.selfdrive.ui.layouts.settings.starpilot.simple_download_manager import SimpleDownloadManager
from openpilot.starpilot.common.starpilot_variables import THEME_SAVE_PATH
@@ -85,114 +80,53 @@ def _theme_display_name(value: str) -> str:
return display
# ═══════════════════════════════════════════════════════════════
# Unified Appearance panel
# AppearanceManagerView — 6-card category hub
# ═══════════════════════════════════════════════════════════════
class AppearanceManagerView(AetherSettingsView):
@property
def vertical_scrolling_disabled(self) -> bool:
return True
class AppearanceManagerView(CardHubManagerView):
def __init__(self, controller, sections, **kwargs):
super().__init__(controller, sections, **kwargs)
self._main_grid = TileGrid(columns=3, padding=12)
self._main_grid.set_touch_valid_callback(lambda: self._scroll_panel.is_touch_valid())
self._child(self._main_grid)
self._init_toggles()
def _init_toggles(self):
hero_data = [
def _build_cards(self):
return [
{
"title": tr("Model & Path Visualization"),
"desc": tr("Customize dynamic lane paths, road edges, and colors."),
"icon": "steering",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("model")
"on_click": lambda: self._controller._navigate_to("model"),
},
{
"title": tr("Driving Widgets & HUD"),
"desc": tr("Configure compass, dynamic pedals, signals, and screen borders."),
"icon": "display",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("hud")
"on_click": lambda: self._controller._navigate_to("hud"),
},
{
"title": tr("Screen Declutter & Visibility"),
"desc": tr("Toggle speed limits, alert banners, and driver monitoring icon."),
"icon": "system",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("declutter")
"on_click": lambda: self._controller._navigate_to("declutter"),
},
]
standard_data = [
{
"title": tr("Navigation & Mapping"),
"desc": tr("Configure road names, Vienna signs, and offroad routes."),
"icon": "navigate",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("nav")
"on_click": lambda: self._controller._navigate_to("nav"),
},
{
"title": tr("Camera & System Startup"),
"desc": tr("Manage driver monitoring cameras, boot logos, and startup sounds."),
"icon": "vehicle",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("system")
"on_click": lambda: self._controller._navigate_to("system"),
},
{
"title": tr("Advanced Metrics"),
"desc": tr("Adjust radar plots, lead vehicle info, and stop sign metrics."),
"icon": "sound",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("dev")
"on_click": lambda: self._controller._navigate_to("dev"),
},
]
all_data = hero_data + standard_data
self._main_grid.clear()
for d in all_data:
self._main_grid.add_tile(
HubTile(
title=d["title"],
desc=d["desc"],
icon_key=d["icon"],
on_click=d["on_click"],
bg_color=d["color"],
)
)
def _render(self, rect: rl.Rectangle):
self.set_rect(rect)
self._interactive_rects.clear()
margin_x = 10.0
margin_y = 10.0
grid_x = rect.x + margin_x
grid_y = rect.y + margin_y
grid_w = rect.width - margin_x * 2
grid_h = rect.y + rect.height - grid_y - margin_y
self._scroll_rect = rl.Rectangle(grid_x, grid_y, grid_w, grid_h)
self._content_height = grid_h
self._scroll_panel.set_enabled(self.is_visible)
self._scroll_offset = self._scroll_panel.update(
self._scroll_rect, self._scroll_rect.height
)
if self.vertical_scrolling_disabled:
self._scroll_offset = 0.0
self._draw_scroll_content(self._scroll_rect, self._scroll_rect.width)
def _draw_scroll_content(self, rect: rl.Rectangle, width: float):
y = rect.y + self._scroll_offset
self._main_grid.set_parent_rect(self._scroll_rect)
self._main_grid.render(rl.Rectangle(rect.x, y, width, rect.height))
class StarPilotAppearanceLayout(_SettingsPage):
def __init__(self):
@@ -393,10 +327,6 @@ class StarPilotAppearanceLayout(_SettingsPage):
# ═══ 3. Screen Declutter & Visibility ═══
self._declutter_rows = [
SettingRow("AdvancedCustomUI", "toggle", tr_noop("Advanced UI Controls"),
subtitle=tr_noop("Fine-tune which elements appear on screen."),
get_state=lambda: self._params.get_bool("AdvancedCustomUI"),
set_state=lambda s: self._params.put_bool("AdvancedCustomUI", s)),
SettingRow("HideSpeed", "toggle", tr_noop("Hide Speed"),
subtitle="",
get_state=lambda: self._params.get_bool("HideSpeed"),
@@ -583,6 +513,8 @@ class StarPilotAppearanceLayout(_SettingsPage):
"Display the driving model path, lanes, and road edges.")
pt_hud = self._make_parent("CustomUI", "Driving Screen Widgets",
"Show interactive indicators on the driving screen.")
pt_declutter = self._make_parent("AdvancedCustomUI", "Advanced UI Controls",
"Fine-tune which elements appear on screen.")
# Register subpanels for Level 2 slide transitions
self._sub_panels["model"] = AetherSettingsView(
@@ -606,6 +538,7 @@ class StarPilotAppearanceLayout(_SettingsPage):
[SettingSection(title="", rows=self._declutter_rows)],
header_title=tr_noop("Screen Declutter & Visibility"),
header_subtitle=tr_noop("Toggle speed limits, alert banners, and driver monitoring icon."),
parent_toggle=pt_declutter,
panel_style=PANEL_STYLE,
)
self._sub_panels["nav"] = AetherSettingsView(
@@ -1,7 +1,5 @@
from __future__ import annotations
import pyray as rl
from openpilot.system.hardware import HARDWARE
from openpilot.selfdrive.ui.lib.starpilot_state import starpilot_state
from openpilot.system.ui.lib.application import gui_app, FontWeight
@@ -12,11 +10,10 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import _SettingsPag
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
DEFAULT_PANEL_STYLE,
AetherSettingsView,
CardHubManagerView,
ParentToggle,
SettingRow,
SettingSection,
TileGrid,
HubTile,
AetherSliderDialog,
)
@@ -47,88 +44,35 @@ def _sync_parent(params, parent_key, child_keys):
# ═══════════════════════════════════════════════════════════════
# SteeringManagerView — clean 3-card category hub
# SteeringManagerView — 3-card category hub
# ═══════════════════════════════════════════════════════════════
class SteeringManagerView(AetherSettingsView):
@property
def vertical_scrolling_disabled(self) -> bool:
return True
class SteeringManagerView(CardHubManagerView):
def __init__(self, controller, **kwargs):
super().__init__(controller, [], panel_style=PANEL_STYLE, **kwargs)
self._grid = TileGrid(columns=3, padding=12)
self._grid.set_touch_valid_callback(lambda: self._scroll_panel.is_touch_valid())
self._child(self._grid)
self._init_toggles()
super().__init__(controller, [], **kwargs)
def _init_toggles(self):
cards = [
def _build_cards(self):
return [
{
"title": tr("Steering Behavior"),
"desc": tr("Configure Always On Lateral (AOL), pause speed thresholds, and turn signal behaviors."),
"icon": "steering",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("behavior")
"on_click": lambda: self._controller._navigate_to("behavior"),
},
{
"title": tr("Lane Changes"),
"desc": tr("Configure automatic lane changes, speed/width thresholds, and smoothing parameters."),
"icon": "road",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("lane_changes")
"on_click": lambda: self._controller._navigate_to("lane_changes"),
},
{
"title": tr("Advanced Lateral Tuning"),
"desc": tr("Adjust actuator delay, steer ratio, Kp, friction, and neural network feedforward controllers."),
"icon": "system",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("advanced")
"on_click": lambda: self._controller._navigate_to("advanced"),
},
]
self._grid.clear()
for d in cards:
self._grid.add_tile(
HubTile(
title=d["title"],
desc=d["desc"],
icon_key=d["icon"],
on_click=d["on_click"],
bg_color=d["color"],
)
)
def _render(self, rect: rl.Rectangle):
self.set_rect(rect)
self._interactive_rects.clear()
margin_x = 10.0
margin_y = 10.0
grid_x = rect.x + margin_x
grid_y = rect.y + margin_y
grid_w = rect.width - margin_x * 2
grid_h = rect.y + rect.height - grid_y - margin_y
self._scroll_rect = rl.Rectangle(grid_x, grid_y, grid_w, grid_h)
self._content_height = grid_h
self._scroll_panel.set_enabled(self.is_visible)
self._scroll_offset = self._scroll_panel.update(
self._scroll_rect, self._scroll_rect.height
)
if self.vertical_scrolling_disabled:
self._scroll_offset = 0.0
self._draw_scroll_content(self._scroll_rect, self._scroll_rect.width)
def _draw_scroll_content(self, rect: rl.Rectangle, width: float):
y = rect.y + self._scroll_offset
self._grid.set_parent_rect(self._scroll_rect)
self._grid.render(rl.Rectangle(rect.x, y, width, rect.height))
# ═══════════════════════════════════════════════════════════════
# StarPilotLateralLayout — controller
@@ -18,6 +18,7 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import _SettingsPag
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
AETHER_LIST_METRICS,
COMPACT_PANEL_METRICS,
AdjustorTogglesPanelView,
AetherAdjustorRow,
AetherSegmentedControl,
AetherSliderDialog,
@@ -27,12 +28,14 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
SettingRow,
SettingSection,
AetherSettingsView,
CardHubManagerView,
TileGrid,
HubTile,
TOGGLE_MIN_HEIGHT,
TOGGLE_ROW_HEIGHT,
RowToggleTile,
ToggleTile,
SPACING,
draw_section_header,
draw_list_group_shell,
SECTION_GAP,
@@ -88,7 +91,7 @@ class AdaptiveSpeedView(Widget):
super().__init__()
self._header_title = tr_noop("Adaptive Speed Controls")
self._controller = controller
self._grid = TileGrid(columns=2, padding=12)
self._grid = TileGrid(columns=2, padding=SPACING.tile_gap)
self._child(self._grid)
self._grid.add_tile(HubTile(
@@ -96,7 +99,6 @@ class AdaptiveSpeedView(Widget):
desc=tr("Configure automated switching between Experimental and Chill Modes based on set conditions."),
icon_key="steering",
on_click=lambda: controller._navigate_to("ce"),
bg_color="#8B5CF6",
))
self._grid.add_tile(HubTile(
@@ -104,130 +106,68 @@ class AdaptiveSpeedView(Widget):
desc=tr("Configure speed control on curves and reset collected calibration data."),
icon_key="navigate",
on_click=lambda: controller._navigate_to("csc"),
bg_color="#8B5CF6",
))
def _render(self, rect: rl.Rectangle):
margin_x = 10.0
margin_y = 10.0
grid_x = rect.x + margin_x
grid_y = rect.y + margin_y
grid_w = rect.width - margin_x * 2
grid_h = rect.y + rect.height - grid_y - margin_y
mx = float(AETHER_LIST_METRICS.outer_margin_x)
my = float(AETHER_LIST_METRICS.outer_margin_y)
grid_x = rect.x + mx
grid_y = rect.y + my
grid_w = rect.width - mx * 2
grid_h = rect.y + rect.height - grid_y - my
self._grid.render(rl.Rectangle(grid_x, grid_y, grid_w, grid_h))
# ═══════════════════════════════════════════════════════════════
# LongitudinalManagerView — main category grid
# LongitudinalManagerView — 6-card category hub
# ═══════════════════════════════════════════════════════════════
class LongitudinalManagerView(AetherSettingsView):
@property
def vertical_scrolling_disabled(self) -> bool:
return True
class LongitudinalManagerView(CardHubManagerView):
def __init__(self, controller, sections, **kwargs):
super().__init__(controller, sections, **kwargs)
self._main_grid = TileGrid(columns=3, padding=12)
self._main_grid.set_touch_valid_callback(lambda: self._scroll_panel.is_touch_valid())
self._child(self._main_grid)
self._init_toggles()
def _init_toggles(self):
hero_data = [
def _build_cards(self):
return [
{
"title": tr("Longitudinal Tuning"),
"desc": tr("Configure acceleration profiles, lane changes, and route speed control."),
"icon": "steering",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("tune")
"on_click": lambda: self._controller._navigate_to("tune"),
},
{
"title": tr("Advanced Actuators"),
"desc": tr("Adjust actuator delay, EV/Truck tuning, and launch/stop speeds/rates."),
"icon": "vehicle",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("advanced")
"on_click": lambda: self._controller._navigate_to("advanced"),
},
{
"title": tr("Speed Limit Controller"),
"desc": tr("Manage auto speed matching, confirmation, offsets, and source priority."),
"icon": "navigate",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("slc")
"on_click": lambda: self._controller._navigate_to("slc"),
},
]
standard_data = [
{
"title": tr("Adaptive Speed Controls"),
"desc": tr("Configure Curve Speed Controller and Conditional Experimental Mode triggers."),
"icon": "display",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("adaptive_speed")
"on_click": lambda: self._controller._navigate_to("adaptive_speed"),
},
{
"title": tr("Driving Personalities"),
"desc": tr("Customize follow distance and jerk/response metrics for each personality profile."),
"icon": "system",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("personality")
"on_click": lambda: self._controller._navigate_to("personality"),
},
{
"title": tr("Quality of Life"),
"desc": tr("Configure cruise intervals, standstill behaviors, gear mapping, and weather presets."),
"icon": "sound",
"color": "#8B5CF6",
"on_click": lambda: self._controller._navigate_to("daily")
"on_click": lambda: self._controller._navigate_to("daily"),
},
]
all_data = hero_data + standard_data
self._main_grid.clear()
for d in all_data:
self._main_grid.add_tile(
HubTile(
title=d["title"],
desc=d["desc"],
icon_key=d["icon"],
on_click=d["on_click"],
bg_color=d["color"],
)
)
def _render(self, rect: rl.Rectangle):
self.set_rect(rect)
self._interactive_rects.clear()
margin_x = 10.0
margin_y = 10.0
grid_x = rect.x + margin_x
grid_y = rect.y + margin_y
grid_w = rect.width - margin_x * 2
grid_h = rect.y + rect.height - grid_y - margin_y
self._scroll_rect = rl.Rectangle(grid_x, grid_y, grid_w, grid_h)
self._content_height = grid_h
self._scroll_panel.set_enabled(self.is_visible)
self._scroll_offset = self._scroll_panel.update(
self._scroll_rect, self._scroll_rect.height
)
if self.vertical_scrolling_disabled:
self._scroll_offset = 0.0
self._draw_scroll_content(self._scroll_rect, self._scroll_rect.width)
def _draw_scroll_content(self, rect: rl.Rectangle, width: float):
y = rect.y + self._scroll_offset
self._main_grid.set_parent_rect(self._scroll_rect)
self._main_grid.render(rl.Rectangle(rect.x, y, width, rect.height))
class ConditionalDriveModeView(PanelManagerView):
class ConditionalDriveModeView(AdjustorTogglesPanelView):
METRICS = COMPACT_PANEL_METRICS
TAB_HEIGHT = 98
TAB_BOTTOM_GAP = 26
@@ -240,18 +180,10 @@ class ConditionalDriveModeView(PanelManagerView):
super().__init__()
self._header_title = tr("Conditional Drive Mode")
self._controller = controller
self._pressed_target: str | None = None
self._adjustor_rows: dict[str, AetherAdjustorRow] = {}
self._can_click = True
self._active_adjustor_key = None
self._init_segmented_control()
self._init_adjustors()
self._init_toggles()
self._forward_touch_valid()
def _forward_touch_valid(self):
pass
def _init_segmented_control(self):
self._drive_mode_control = self._child(
@@ -343,16 +275,6 @@ class ConditionalDriveModeView(PanelManagerView):
return cls(**kwargs)
def _set_active_adjustor(self, key: str, active: bool):
if active:
if self._active_adjustor_key and self._active_adjustor_key != key:
old = self._adjustor_rows.get(self._active_adjustor_key)
if old:
old.reset_interaction()
self._active_adjustor_key = key
elif self._active_adjustor_key == key:
self._active_adjustor_key = None
def _init_adjustors(self):
speed_unit = self._controller._speed_unit()
is_metric = self._controller._is_metric()
@@ -417,16 +339,6 @@ class ConditionalDriveModeView(PanelManagerView):
unit=spec["unit"], labels=spec["labels"], color=PANEL_STYLE.accent
))
def show_event(self):
super().show_event()
self._pressed_target = None
self._can_click = True
def hide_event(self):
super().hide_event()
self._pressed_target = None
self._can_click = True
def _draw_header(self, rect: rl.Rectangle):
pass
@@ -539,30 +451,13 @@ class ConditionalDriveModeView(PanelManagerView):
def _get_active_elements(self):
mode = self._get_drive_mode_index()
elems = [self._drive_mode_control]
if mode == 1:
return [self._adjustor_rows[k] for k in self._cem_keys] + [self._toggle_grid]
elems += [self._adjustor_rows[k] for k in self._cem_keys]
elif mode == 2:
return [self._adjustor_rows[k] for k in self._ccm_keys] + [self._toggle_grid]
return []
def _handle_mouse_press(self, mouse_pos: MousePos):
super()._handle_mouse_press(mouse_pos)
for el in self._get_active_elements():
el._handle_mouse_press(mouse_pos)
self._drive_mode_control._handle_mouse_press(mouse_pos)
def _handle_mouse_release(self, mouse_pos: MousePos):
for el in self._get_active_elements():
el._handle_mouse_release(mouse_pos)
self._drive_mode_control._handle_mouse_release(mouse_pos)
super()._handle_mouse_release(mouse_pos)
def _handle_mouse_event(self, mouse_event: MouseEvent):
super()._handle_mouse_event(mouse_event)
for el in self._get_active_elements():
el._handle_mouse_event(mouse_event)
self._drive_mode_control._handle_mouse_event(mouse_event)
elems += [self._adjustor_rows[k] for k in self._ccm_keys]
elems.append(self._toggle_grid)
return elems
# ═══════════════════════════════════════════════════════════════
@@ -17,7 +17,7 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.system_settings import St
from openpilot.selfdrive.ui.layouts.settings.starpilot.appearance import StarPilotAppearanceLayout
from openpilot.selfdrive.ui.layouts.settings.starpilot.vehicle import StarPilotVehicleSettingsLayout
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid, HubTile, SPACING, BreadcrumbController, AETHER_LIST_METRICS, draw_rounded_fill, draw_rounded_stroke, AetherTransitionManager
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid, HubTile, SPACING, BreadcrumbController, AETHER_LIST_METRICS, AetherListColors, draw_rounded_fill, draw_rounded_stroke, AetherTransitionManager
class StarPilotLayout(Widget):
CATEGORIES = [
@@ -284,18 +284,21 @@ class StarPilotLayout(Widget):
# 0. Draw top bar with HubTile-style purple glow
glass_rect = rl.Rectangle(shell_x, rect.y + 2, shell_w, TOP_BAR_HEIGHT - 4)
GLOW = AetherListColors.PRIMARY
BAR_FILL = rl.Color(12, 10, 18, 255)
# 0a. Purple glow rings — 4 concentric, fading outward (HubTile parity)
for i in range(4, 0, -1):
off = i * 2.5
gr = rl.Rectangle(glass_rect.x - off, glass_rect.y - off, glass_rect.width + off * 2, glass_rect.height + off * 2)
a = int(25 * (1.0 - i / 5))
draw_rounded_fill(gr, rl.Color(139, 92, 246, max(0, min(255, a))), radius_px=34)
draw_rounded_fill(gr, rl.Color(GLOW.r, GLOW.g, GLOW.b, max(0, min(255, a))), radius_px=34)
# 0b. Dark fill — strict parity with HubTile _HUD_BG_ON
draw_rounded_fill(glass_rect, rl.Color(12, 10, 18, 255), radius_px=34)
draw_rounded_fill(glass_rect, BAR_FILL, radius_px=34)
# 0c. Full bright purple border — strict parity
draw_rounded_stroke(glass_rect, rl.Color(139, 92, 246, 255), radius_px=34)
draw_rounded_stroke(glass_rect, GLOW, radius_px=34)
# 1. Draw breadcrumbs in top bar
crumb_rect = rl.Rectangle(glass_rect.x, glass_rect.y, glass_rect.width, glass_rect.height)
@@ -11,7 +11,7 @@ from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.widgets import DialogResult, Widget
from openpilot.system.ui.widgets.option_dialog import MultiOptionDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid, HubTile, ToggleTile, ValueTile, SliderTile, SPACING, AetherSliderDialog, AetherTransitionManager
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid, HubTile, ToggleTile, ValueTile, SliderTile, SPACING, AetherSliderDialog, AetherTransitionManager, AetherListColors
from openpilot.selfdrive.ui.layouts.settings.starpilot.sectioned_panel import SectionedTileLayout, TileSection
import time
@@ -92,11 +92,8 @@ class StarPilotPanelType(IntEnum):
LATERAL = 4
MAPS = 5
DEVICE = 6
UTILITIES = 7
VISUALS = 8
THEMES = 9
VEHICLE = 10
WHEEL = 11
SYSTEM = 12
@@ -349,7 +346,7 @@ class _SettingsPage(StarPilotPanel):
shared slider and selector dialog helpers.
"""
SLIDER_COLOR = "#8B5CF6"
SLIDER_COLOR = AetherListColors.PRIMARY
def __init__(self):
super().__init__()
@@ -17,6 +17,7 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import _SettingsPag
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
AETHER_LIST_METRICS,
COMPACT_PANEL_METRICS,
AdjustorTogglesPanelView,
AetherAdjustorRow,
AetherListColors,
PanelManagerView,
@@ -44,7 +45,7 @@ SOUNDS_PANEL_METRICS = replace(
class SoundsManagerView(PanelManagerView):
class SoundsManagerView(AdjustorTogglesPanelView):
METRICS = SOUNDS_PANEL_METRICS
@property
@@ -54,9 +55,6 @@ class SoundsManagerView(PanelManagerView):
def __init__(self, controller: StarPilotSoundsLayout):
super().__init__()
self._controller = controller
self._pressed_target: str | None = None
self._adjustor_rows: dict[str, AetherAdjustorRow] = {}
self._can_click = True
self._reset_rect = rl.Rectangle(0, 0, 0, 0)
self._tile_grid_h = 0.0
@@ -93,16 +91,6 @@ class SoundsManagerView(PanelManagerView):
page_size = self._compute_page_size(TOGGLE_ROW_HEIGHT)
self._set_toggle_pages([toggle_defs[i:i+page_size] for i in range(0, len(toggle_defs), page_size)])
def _set_active_adjustor(self, key: str, active: bool):
if active:
if self._active_adjustor_key and self._active_adjustor_key != key:
old = self._adjustor_rows.get(self._active_adjustor_key)
if old:
old.reset_interaction()
self._active_adjustor_key = key
elif self._active_adjustor_key == key:
self._active_adjustor_key = None
def _init_adjustors(self):
for key in self._controller.VOLUME_KEYS:
info = self._controller.VOLUME_INFO[key]
@@ -199,24 +187,6 @@ class SoundsManagerView(PanelManagerView):
)
)
def _handle_mouse_press(self, mouse_pos: MousePos):
super()._handle_mouse_press(mouse_pos)
for adjustor in self._adjustor_rows.values():
adjustor._handle_mouse_press(mouse_pos)
self._toggle_grid._handle_mouse_press(mouse_pos)
def _handle_mouse_release(self, mouse_pos: MousePos):
for adjustor in self._adjustor_rows.values():
adjustor._handle_mouse_release(mouse_pos)
self._toggle_grid._handle_mouse_release(mouse_pos)
super()._handle_mouse_release(mouse_pos)
def _handle_mouse_event(self, mouse_event: MouseEvent):
super()._handle_mouse_event(mouse_event)
for adjustor in self._adjustor_rows.values():
adjustor._handle_mouse_event(mouse_event)
self._toggle_grid._handle_mouse_event(mouse_event)
def _target_at(self, mouse_pos: MousePos) -> str | None:
if point_hits(mouse_pos, self._reset_rect, None, pad_x=6, pad_y=0):
return "action:restore_defaults"
@@ -226,16 +196,6 @@ class SoundsManagerView(PanelManagerView):
if target == "action:restore_defaults":
self._controller._restore_defaults()
def show_event(self):
super().show_event()
self._pressed_target = None
self._can_click = True
def hide_event(self):
super().hide_event()
self._pressed_target = None
self._can_click = True
def _measure_content_height(self, content_width: float) -> float:
col_width = (content_width - SECTION_GAP) / 2
@@ -93,7 +93,7 @@ REPORT_CATEGORIES = [
]
FADE_HEIGHT = AETHER_LIST_METRICS.fade_height
PANEL_STYLE = DEFAULT_PANEL_STYLE
SYSTEM_PANEL_METRICS = AETHER_LIST_METRICS
@@ -15,6 +15,7 @@ from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog, alert_dial
from openpilot.system.ui.widgets.option_dialog import MultiOptionDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import _SettingsPage
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
AETHER_LIST_METRICS,
AetherSliderDialog,
COMPACT_PANEL_METRICS,
DEFAULT_PANEL_STYLE,
@@ -73,7 +74,7 @@ def _lock_doors_timer_labels():
return labels
SECTION_GAP = 28
SECTION_GAP = AETHER_LIST_METRICS.section_gap
ROW_HEIGHT = 125.0
PANEL_STYLE = DEFAULT_PANEL_STYLE
@@ -275,7 +276,7 @@ class VehicleSettingsManagerView(PanelManagerView):
row_y += self._left_row_height
if steering_rows:
row_y = draw_group_header(rect.x + 24, row_y, col_w - 48, tr("STEERING CONTROLS"))
row_y = draw_group_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)