mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-19 00:02:08 +08:00
Big UI : Cleanup
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user