BigUI WIP: More Tab Stuff

(cherry picked from commit 9ba41d1a4a46cb95c5ef07901593e72d3d00ad7a)
This commit is contained in:
firestarsdog
2026-04-07 01:13:27 -04:00
committed by firestar5683
parent 355fe2a273
commit 0b0fb3957a
11 changed files with 310 additions and 212 deletions
@@ -568,8 +568,8 @@ class RadioTileGroup(Widget):
self._option_targets.append(0.0)
for i in range(len(self._option_offsets)):
self._option_offsets[i] += (self._option_targets[i] - self._option_offsets[i]) * (1 - math.exp(-dt / PLATE_TAU))
padding = 20
option_w = 240 if len(self.options) <= 3 else 200
padding = 16
option_w = 240 if len(self.options) <= 3 else 188
total_width = len(self.options) * option_w + max(0, len(self.options) - 1) * padding
if self.title:
title_size = measure_text_cached(self._font_title, self.title, 40)
@@ -591,10 +591,17 @@ class RadioTileGroup(Widget):
rl.draw_rectangle_rounded(face_rect, TILE_RADIUS, 10, color)
rl.draw_rectangle_rounded(rl.Rectangle(face_rect.x + 1, face_rect.y + 1, face_rect.width - 2, face_rect.height - 2), TILE_RADIUS, 10, rl.Color(0, 0, 0, 80))
rl.draw_rectangle_rounded(rl.Rectangle(face_rect.x, face_rect.y, face_rect.width - 1.5, face_rect.height - 1.5), TILE_RADIUS, 10, rl.Color(255, 255, 255, 110))
ts = measure_text_cached(self._font, opt.upper(), 35)
font_size = 30
spacing = round(font_size * 0.08)
max_width = r.width - 28
ts = measure_text_cached(self._font, opt, font_size, spacing=spacing)
while font_size > 22 and ts.x > max_width:
font_size -= 1
spacing = round(font_size * 0.08)
ts = measure_text_cached(self._font, opt, font_size, spacing=spacing)
text_pos = rl.Vector2(face_x + (r.width - ts.x) / 2, face_y + (r.height - ts.y) / 2)
rl.draw_text_ex(self._font, opt.upper(), rl.Vector2(round(text_pos.x + 1), round(text_pos.y + 2)), 35, 0, rl.Color(0, 0, 0, 90))
rl.draw_text_ex(self._font, opt.upper(), rl.Vector2(round(text_pos.x), round(text_pos.y)), 35, 0, rl.WHITE)
rl.draw_text_ex(self._font, opt, rl.Vector2(round(text_pos.x + 1), round(text_pos.y + 2)), font_size, spacing, rl.Color(0, 0, 0, 90))
rl.draw_text_ex(self._font, opt, rl.Vector2(round(text_pos.x), round(text_pos.y)), font_size, spacing, rl.WHITE)
class TileGrid(Widget):
+13 -24
View File
@@ -30,7 +30,7 @@ class StarPilotDataLayout(StarPilotPanel):
self.CATEGORIES = [
{"title": tr_noop("Manage Backups"), "panel": "backups", "icon": "toggle_icons/icon_system.png", "color": "#D43D8A"},
{"title": tr_noop("Toggle Backups"), "panel": "toggle_backups", "icon": "toggle_icons/icon_system.png", "color": "#D43D8A"},
{"title": tr_noop("Manage Storage"), "panel": "storage", "icon": "toggle_icons/icon_system.png", "color": "#D43D8A"},
{"title": tr_noop("Driving Data Storage"), "type": "value", "get_value": self._get_storage, "on_click": lambda: None, "icon": "toggle_icons/icon_system.png", "color": "#D43D8A", "is_enabled": lambda: False},
{
"title": tr_noop("Delete Driving Data"),
"type": "hub",
@@ -50,7 +50,6 @@ class StarPilotDataLayout(StarPilotPanel):
self._sub_panels = {
"backups": StarPilotBackupsLayout(),
"toggle_backups": StarPilotToggleBackupsLayout(),
"storage": StarPilotStorageLayout(),
}
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
@@ -89,6 +88,18 @@ class StarPilotDataLayout(StarPilotPanel):
gui_app.set_modal_overlay(ConfirmDialog(tr("Delete all error logs?"), tr("Delete"), on_close=_do_delete))
def _get_storage(self):
paths = ["/data/media/0/osm/offline", "/data/media/0/realdata", "/data/backups"]
total = 0
for p in paths:
pp = Path(p)
if pp.exists():
total += sum(f.stat().st_size for f in pp.rglob('*') if f.is_file())
mb = total / (1024 * 1024)
if mb > 1024:
return f"{(mb / 1024):.2f} GB"
return f"{mb:.2f} MB"
class StarPilotBackupsLayout(StarPilotPanel):
def __init__(self):
@@ -231,25 +242,3 @@ class StarPilotToggleBackupsLayout(StarPilotPanel):
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr("Delete Toggle Backup"), backups, on_close=_on_select))
class StarPilotStorageLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
self.CATEGORIES = [
{"title": tr_noop("Driving Data"), "type": "value", "get_value": self._get_storage, "on_click": lambda: None, "color": "#D43D8A", "is_enabled": lambda: False},
]
self._rebuild_grid()
def _get_storage(self):
paths = ["/data/media/0/osm/offline", "/data/media/0/realdata", "/data/backups"]
total = 0
for p in paths:
pp = Path(p)
if pp.exists():
total += sum(f.stat().st_size for f in pp.rglob('*') if f.is_file())
mb = total / (1024 * 1024)
if mb > 1024:
return f"{(mb / 1024):.2f} GB"
return f"{mb:.2f} MB"
@@ -5,7 +5,8 @@ from openpilot.system.ui.lib.multilang import tr, tr_noop
from openpilot.system.ui.widgets import DialogResult
from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel, create_tile_panel
from openpilot.selfdrive.ui.layouts.settings.starpilot.tabbed_panel import TabSectionSpec, TabbedSectionHost
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import AetherSliderDialog
class StarPilotAdvancedLateralLayout(StarPilotPanel):
@@ -124,21 +125,41 @@ class StarPilotLateralQOLLayout(StarPilotPanel):
class StarPilotLateralLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._sub_panels = {
"advanced_lateral": StarPilotAdvancedLateralLayout(),
"always_on_lateral": StarPilotAlwaysOnLateralLayout(),
"lane_changes": StarPilotLaneChangesLayout(),
"lateral_tune": StarPilotLateralTuneLayout(),
"qol": StarPilotLateralQOLLayout(),
}
self.CATEGORIES = [
{"title": tr_noop("Advanced Lateral Tuning"), "panel": "advanced_lateral", "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497"},
steering_panel = create_tile_panel([
{"title": tr_noop("Always On Lateral"), "panel": "always_on_lateral", "icon": "toggle_icons/icon_always_on_lateral.png", "color": "#597497"},
{"title": tr_noop("Lane Changes"), "panel": "lane_changes", "icon": "toggle_icons/icon_lane.png", "color": "#597497"},
{"title": tr_noop("Lateral Tuning"), "panel": "lateral_tune", "icon": "toggle_icons/icon_lateral_tune.png", "color": "#597497"},
{"title": tr_noop("Quality of Life"), "panel": "qol", "icon": "toggle_icons/icon_quality_of_life.png", "color": "#597497"},
]
for name, panel in self._sub_panels.items():
if hasattr(panel, 'set_navigate_callback'): panel.set_navigate_callback(self._navigate_to)
if hasattr(panel, 'set_back_callback'): panel.set_back_callback(self._go_back)
self._rebuild_grid()
], {
"always_on_lateral": StarPilotAlwaysOnLateralLayout(),
"qol": StarPilotLateralQOLLayout(),
})
tune_panel = create_tile_panel([
{"title": tr_noop("Advanced Tuning"), "panel": "advanced_lateral", "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497"},
{"title": tr_noop("Lateral Tuning"), "panel": "lateral_tune", "icon": "toggle_icons/icon_lateral_tune.png", "color": "#597497"},
], {
"advanced_lateral": StarPilotAdvancedLateralLayout(),
"lateral_tune": StarPilotLateralTuneLayout(),
})
self._section_tabs = TabbedSectionHost([
TabSectionSpec("steering", "Steering", steering_panel),
TabSectionSpec("lane", "Lane", StarPilotLaneChangesLayout()),
TabSectionSpec("tune", "Tune", tune_panel),
])
def set_navigate_callback(self, callback):
self._section_tabs.set_navigate_callback(callback)
def set_back_callback(self, callback):
self._section_tabs.set_back_callback(callback)
def _render(self, rect):
self._section_tabs.render(rect)
def set_current_sub_panel(self, sub_panel: str):
self._section_tabs.set_current_sub_panel(sub_panel)
def show_event(self):
self._section_tabs.show_event()
def hide_event(self):
self._section_tabs.hide_event()
@@ -6,56 +6,68 @@ from openpilot.system.ui.widgets import DialogResult
from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
from openpilot.system.ui.widgets.input_dialog import InputDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel, create_tile_panel
from openpilot.selfdrive.ui.layouts.settings.starpilot.tabbed_panel import TabSectionSpec, TabbedSectionHost
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import AetherSliderDialog
class StarPilotLongitudinalLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._sub_panels = {
"advanced": StarPilotAdvancedLongitudinalLayout(),
"conditional": StarPilotConditionalExperimentalLayout(),
"curve": StarPilotCurveSpeedLayout(),
"personalities": StarPilotPersonalitiesLayout(),
tune_panel = create_tile_panel([
{"title": tr_noop("Longitudinal Tuning"), "panel": "tuning", "icon": "toggle_icons/icon_longitudinal_tune.png", "color": "#597497"},
{"title": tr_noop("Advanced Tuning"), "panel": "advanced", "icon": "toggle_icons/icon_advanced_longitudinal_tune.png", "color": "#597497"},
{"title": tr_noop("Driving Personalities"), "panel": "personalities", "icon": "toggle_icons/icon_personality.png", "color": "#597497"},
], {
"tuning": StarPilotLongitudinalTuneLayout(),
"qol": StarPilotLongitudinalQOLLayout(),
"slc": StarPilotSpeedLimitControllerLayout(),
"weather": StarPilotWeatherLayout(),
# Personality Sub-panels
"advanced": StarPilotAdvancedLongitudinalLayout(),
"personalities": StarPilotPersonalitiesLayout(),
"traffic_personality": StarPilotPersonalityProfileLayout("Traffic"),
"aggressive_personality": StarPilotPersonalityProfileLayout("Aggressive"),
"standard_personality": StarPilotPersonalityProfileLayout("Standard"),
"relaxed_personality": StarPilotPersonalityProfileLayout("Relaxed"),
# SLC Sub-panels
"slc_offsets": StarPilotSLCOffsetsLayout(),
"slc_qol": StarPilotSLCQOLLayout(),
"slc_visuals": StarPilotSLCVisualsLayout(),
# Weather Sub-panels
})
adaptive_panel = create_tile_panel([
{"title": tr_noop("Conditional Experimental"), "panel": "conditional", "icon": "toggle_icons/icon_conditional.png", "color": "#597497"},
{"title": tr_noop("Curve Speed"), "panel": "curve", "icon": "toggle_icons/icon_speed_map.png", "color": "#597497"},
{"title": tr_noop("Weather"), "panel": "weather", "icon": "toggle_icons/icon_rainbow.png", "color": "#597497"},
], {
"conditional": StarPilotConditionalExperimentalLayout(),
"curve": StarPilotCurveSpeedLayout(),
"weather": StarPilotWeatherLayout(),
"low_visibility": StarPilotWeatherBase("LowVisibility"),
"rain": StarPilotWeatherBase("Rain"),
"rainstorm": StarPilotWeatherBase("RainStorm"),
"snow": StarPilotWeatherBase("Snow"),
}
})
self.CATEGORIES = [
{"title": tr_noop("Advanced Longitudinal Tuning"), "panel": "advanced", "icon": "toggle_icons/icon_advanced_longitudinal_tune.png", "color": "#597497"},
{"title": tr_noop("Conditional Experimental Mode"), "panel": "conditional", "icon": "toggle_icons/icon_conditional.png", "color": "#597497"},
{"title": tr_noop("Curve Speed Controller"), "panel": "curve", "icon": "toggle_icons/icon_speed_map.png", "color": "#597497"},
{"title": tr_noop("Driving Personalities"), "panel": "personalities", "icon": "toggle_icons/icon_personality.png", "color": "#597497"},
{"title": tr_noop("Longitudinal Tuning"), "panel": "tuning", "icon": "toggle_icons/icon_longitudinal_tune.png", "color": "#597497"},
{"title": tr_noop("Quality of Life"), "panel": "qol", "icon": "toggle_icons/icon_quality_of_life.png", "color": "#597497"},
{"title": tr_noop("Speed Limit Controller"), "panel": "slc", "icon": "toggle_icons/icon_speed_limit.png", "color": "#597497"},
{"title": tr_noop("Weather"), "panel": "weather", "icon": "toggle_icons/icon_rainbow.png", "color": "#597497"},
]
for name, panel in self._sub_panels.items():
if hasattr(panel, 'set_navigate_callback'):
panel.set_navigate_callback(self._navigate_to)
if hasattr(panel, 'set_back_callback'):
panel.set_back_callback(self._go_back)
self._section_tabs = TabbedSectionHost([
TabSectionSpec("tune", "Tune", tune_panel),
TabSectionSpec("adaptive", "Adaptive", adaptive_panel),
TabSectionSpec("limits", "Limits", StarPilotSpeedLimitControllerLayout()),
TabSectionSpec("daily", "Daily", StarPilotLongitudinalQOLLayout()),
])
self._rebuild_grid()
def set_navigate_callback(self, callback):
self._section_tabs.set_navigate_callback(callback)
def set_back_callback(self, callback):
self._section_tabs.set_back_callback(callback)
def _render(self, rect):
self._section_tabs.render(rect)
def set_current_sub_panel(self, sub_panel: str):
self._section_tabs.set_current_sub_panel(sub_panel)
def show_event(self):
self._section_tabs.show_event()
def hide_event(self):
self._section_tabs.hide_event()
class StarPilotAdvancedLongitudinalLayout(StarPilotPanel):
def __init__(self):
@@ -165,15 +177,6 @@ class StarPilotConditionalExperimentalLayout(StarPilotPanel):
"icon": "toggle_icons/icon_conditional.png",
"color": "#597497",
},
{
"title": tr_noop("Conditional Experimental"),
"type": "toggle",
"get_state": lambda: self._params.get_bool("ConditionalExperimental"),
"set_state": lambda s: self._params.put_bool("ConditionalExperimental", s),
"icon": "toggle_icons/icon_conditional.png",
"color": "#597497",
"visible": lambda: self._params.get_bool("ConditionalExperimental"),
},
{
"title": tr_noop("Below Speed"),
"type": "value",
@@ -302,16 +305,6 @@ class StarPilotCurveSpeedLayout(StarPilotPanel):
"icon": "toggle_icons/icon_speed_map.png",
"color": "#597497",
},
{
"title": tr_noop("Curve Speed Controller"),
"desc": tr_noop("Automatically slow down for upcoming curves using data learned from your driving style."),
"type": "toggle",
"get_state": lambda: self._params.get_bool("CurveSpeedController"),
"set_state": lambda s: self._params.put_bool("CurveSpeedController", s),
"icon": "toggle_icons/icon_speed_map.png",
"color": "#597497",
"visible": lambda: self._params.get_bool("CurveSpeedController"),
},
{
"title": tr_noop("Status Widget"),
"desc": tr_noop("Show the Curve Speed Controller ambient effect on the driving screen."),
@@ -677,6 +670,11 @@ class StarPilotLongitudinalQOLLayout(StarPilotPanel):
class StarPilotSpeedLimitControllerLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._sub_panels = {
"slc_offsets": StarPilotSLCOffsetsLayout(),
"slc_qol": StarPilotSLCQOLLayout(),
"slc_visuals": StarPilotSLCVisualsLayout(),
}
self.CATEGORIES = [
{
"title": tr_noop("Speed Limit Controller"),
@@ -712,6 +710,13 @@ class StarPilotSpeedLimitControllerLayout(StarPilotPanel):
"color": "#597497",
},
]
for panel in self._sub_panels.values():
if hasattr(panel, 'set_navigate_callback'):
panel.set_navigate_callback(self._navigate_to)
if hasattr(panel, 'set_back_callback'):
panel.set_back_callback(self._go_back)
self._rebuild_grid()
def _get_priority_value(self):
@@ -110,6 +110,9 @@ class StarPilotLayout(Widget):
StarPilotPanelType.LATERAL,
StarPilotPanelType.NAVIGATION,
StarPilotPanelType.MAPS,
StarPilotPanelType.VISUALS,
StarPilotPanelType.THEMES,
StarPilotPanelType.VEHICLE,
)
self._main_grid = TileGrid(columns=None, padding=20)
@@ -162,7 +165,11 @@ class StarPilotLayout(Widget):
self._depth_callback(depth)
def _push_sub_panel(self, sub_panel_name: str):
self._panel_stack.append((self._current_panel, sub_panel_name))
if sub_panel_name:
self._panel_stack.append((self._current_panel, sub_panel_name))
else:
while self._panel_stack and self._panel_stack[-1][0] == self._current_panel:
self._panel_stack.pop()
self._update_sub_panel_visibility()
self._update_depth()
@@ -8,6 +8,7 @@ import pyray as rl
from openpilot.common.params import Params
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.widgets import Widget
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid
class StarPilotPanelType(IntEnum):
@@ -121,3 +122,19 @@ class StarPilotPanel(Widget):
self._sub_panels[self._current_sub_panel].show_event()
elif self._scroller:
self._scroller.show_event()
def create_tile_panel(categories: list[dict], sub_panels: dict[str, Widget] | None = None) -> StarPilotPanel:
panel = StarPilotPanel()
panel.CATEGORIES = categories
panel._sub_panels = sub_panels or {}
panel._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
for name, child in panel._sub_panels.items():
if hasattr(child, 'set_navigate_callback'):
child.set_navigate_callback(panel._navigate_to)
if hasattr(child, 'set_back_callback'):
child.set_back_callback(panel._go_back)
panel._rebuild_grid()
return panel
@@ -58,7 +58,13 @@ class StarPilotSoundsLayout(StarPilotPanel):
def _on_section_change(self, index: int):
if 0 <= index < len(self._section_names):
self._set_active_section(self._section_names[index])
previous_panel = self._sub_panels[self._active_section]
if hasattr(previous_panel, 'set_current_sub_panel'):
previous_panel.set_current_sub_panel("")
self._current_sub_panel = ""
self._set_active_section(self._section_names[index], "")
if self._navigate_callback:
self._navigate_callback("")
def _set_active_section(self, section_name: str, child_panel: str = ""):
if section_name not in self._sub_panels:
@@ -38,7 +38,13 @@ class StarPilotSystemLayout(StarPilotPanel):
def _on_section_change(self, index: int):
if 0 <= index < len(self._section_names):
self._set_active_section(self._section_names[index])
previous_panel = self._sub_panels[self._active_section]
if hasattr(previous_panel, 'set_current_sub_panel'):
previous_panel.set_current_sub_panel("")
self._current_sub_panel = ""
self._set_active_section(self._section_names[index], "")
if self._navigate_callback:
self._navigate_callback("")
def _set_active_section(self, section_name: str, child_panel: str = ""):
if section_name not in self._sub_panels:
@@ -0,0 +1,119 @@
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
import pyray as rl
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.widgets import Widget
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import RadioTileGroup
@dataclass(frozen=True)
class TabSectionSpec:
key: str
label: str
panel: Widget
class TabbedSectionHost(Widget):
def __init__(self, sections: list[TabSectionSpec]):
super().__init__()
if not sections:
raise ValueError("TabbedSectionHost requires at least one section")
self._sections = {spec.key: spec.panel for spec in sections}
self._section_order = [spec.key for spec in sections]
self._active_section = self._section_order[0]
self._navigate_callback: Callable | None = None
self._back_callback: Callable | None = None
self._current_sub_panel = ""
self._tab_height = 110
self._panel_top = 140
self._section_tabs = RadioTileGroup("", [tr(spec.label) for spec in sections], 0, self._on_tab_change)
for key, panel in self._sections.items():
if hasattr(panel, "set_navigate_callback"):
panel.set_navigate_callback(lambda sub_panel, section_key=key: self._on_child_navigate(section_key, sub_panel))
if hasattr(panel, "set_back_callback"):
panel.set_back_callback(self._go_back)
def set_navigate_callback(self, callback: Callable):
self._navigate_callback = callback
def set_back_callback(self, callback: Callable):
self._back_callback = callback
def set_current_sub_panel(self, sub_panel: str):
self._current_sub_panel = sub_panel
if not sub_panel:
panel = self._sections[self._active_section]
if hasattr(panel, "set_current_sub_panel"):
panel.set_current_sub_panel("")
return
if ":" in sub_panel:
section_key, child_panel = sub_panel.split(":", 1)
self._activate_section(section_key, child_panel)
elif sub_panel in self._sections:
self._activate_section(sub_panel)
else:
panel = self._sections[self._active_section]
if hasattr(panel, "set_current_sub_panel"):
panel.set_current_sub_panel(sub_panel)
def _on_tab_change(self, index: int):
if 0 <= index < len(self._section_order):
self._current_sub_panel = ""
self._activate_section(self._section_order[index], "")
if self._navigate_callback:
self._navigate_callback("")
def _activate_section(self, section_key: str, child_panel: str = ""):
if section_key not in self._sections:
return
previous = self._active_section
if section_key != previous:
previous_panel = self._sections[previous]
if hasattr(previous_panel, "set_current_sub_panel"):
previous_panel.set_current_sub_panel("")
self._sections[previous].hide_event()
self._active_section = section_key
self._sections[section_key].show_event()
self._section_tabs.set_index(self._section_order.index(section_key))
panel = self._sections[section_key]
if hasattr(panel, "set_current_sub_panel"):
panel.set_current_sub_panel(child_panel)
def _on_child_navigate(self, section_key: str, sub_panel: str):
self._current_sub_panel = f"{section_key}:{sub_panel}" if sub_panel else section_key
if self._navigate_callback:
self._navigate_callback(self._current_sub_panel)
def _go_back(self):
self._current_sub_panel = ""
panel = self._sections[self._active_section]
if hasattr(panel, "set_current_sub_panel"):
panel.set_current_sub_panel("")
if self._back_callback:
self._back_callback()
def _render(self, rect: rl.Rectangle):
tab_rect = rl.Rectangle(rect.x, rect.y, rect.width, self._tab_height)
panel_rect = rl.Rectangle(rect.x, rect.y + self._panel_top, rect.width, rect.height - self._panel_top)
self._section_tabs.render(tab_rect)
self._sections[self._active_section].render(panel_rect)
def show_event(self):
super().show_event()
self._section_tabs.show_event()
self._sections[self._active_section].show_event()
def hide_event(self):
super().hide_event()
self._section_tabs.hide_event()
self._sections[self._active_section].hide_event()
@@ -105,6 +105,7 @@ class StarPilotThemesLayout(StarPilotPanel):
"icon": "toggle_icons/icon_frog.png",
"color": "#542A71",
"desc": tr_noop("Customize the overall look and feel."),
"visible": lambda: self._params.get_bool("CustomThemes"),
},
{
"title": tr_noop("Holiday Themes"),
@@ -179,13 +180,6 @@ class StarPilotPersonalizeLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self.CATEGORIES = [
{
"title": tr_noop("Custom Themes"),
"type": "toggle",
"get_state": lambda: self._params.get_bool("CustomThemes"),
"set_state": lambda s: self._params.put_bool("CustomThemes", s),
"color": "#542A71",
},
{
"title": tr_noop("Boot Logo"),
"type": "value",
@@ -4,108 +4,44 @@ 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.selection_dialog import SelectionDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel, create_tile_panel
from openpilot.selfdrive.ui.layouts.settings.starpilot.tabbed_panel import TabSectionSpec, TabbedSectionHost
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid, ToggleTile, AetherSliderDialog
class StarPilotThemesLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._sub_panels = {
"personalize": StarPilotPersonalizeLayout(),
}
self.CATEGORIES = [
{"title": tr_noop("Personalize openpilot"), "panel": "personalize", "icon": "toggle_icons/icon_frog.png", "color": "#8B5CF6"},
{
"title": tr_noop("Holiday Themes"),
"type": "toggle",
"get_state": lambda: self._params.get_bool("HolidayThemes"),
"set_state": lambda s: self._params.put_bool("HolidayThemes", s),
"icon": "toggle_icons/icon_calendar.png",
"color": "#8B5CF6",
},
{
"title": tr_noop("Rainbow Path"),
"type": "toggle",
"get_state": lambda: self._params.get_bool("RainbowPath"),
"set_state": lambda s: self._params.put_bool("RainbowPath", s),
"icon": "toggle_icons/icon_rainbow.png",
"color": "#8B5CF6",
},
{
"title": tr_noop("Random Events"),
"type": "toggle",
"get_state": lambda: self._params.get_bool("RandomEvents"),
"set_state": lambda s: self._params.put_bool("RandomEvents", s),
"icon": "toggle_icons/icon_random.png",
"color": "#8B5CF6",
},
{
"title": tr_noop("Random Themes"),
"type": "toggle",
"get_state": lambda: self._params.get_bool("RandomThemes"),
"set_state": lambda s: self._params.put_bool("RandomThemes", s),
"icon": "toggle_icons/icon_random_themes.png",
"color": "#8B5CF6",
},
]
for name, panel in self._sub_panels.items():
if hasattr(panel, 'set_navigate_callback'):
panel.set_navigate_callback(self._navigate_to)
if hasattr(panel, 'set_back_callback'):
panel.set_back_callback(self._go_back)
self._rebuild_grid()
class StarPilotPersonalizeLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self.CATEGORIES = [
{"title": tr_noop("Boot Logo"), "type": "hub", "on_click": lambda: self._show_theme_selector("BootLogo"), "color": "#8B5CF6"},
{"title": tr_noop("Color Scheme"), "type": "hub", "on_click": lambda: self._show_theme_selector("ColorScheme"), "color": "#8B5CF6"},
{"title": tr_noop("Distance Icons"), "type": "hub", "on_click": lambda: self._show_theme_selector("DistanceIconPack"), "color": "#8B5CF6"},
{"title": tr_noop("Icon Pack"), "type": "hub", "on_click": lambda: self._show_theme_selector("IconPack"), "color": "#8B5CF6"},
{"title": tr_noop("Turn Signals"), "type": "hub", "on_click": lambda: self._show_theme_selector("SignalAnimation"), "color": "#8B5CF6"},
{"title": tr_noop("Sound Pack"), "type": "hub", "on_click": lambda: self._show_theme_selector("SoundPack"), "color": "#8B5CF6"},
{"title": tr_noop("Steering Wheel"), "type": "hub", "on_click": lambda: self._show_theme_selector("WheelIcon"), "color": "#8B5CF6"},
]
self._rebuild_grid()
def _show_theme_selector(self, key):
themes = ["Stock", "Frog", "Cyberpunk", "Minimal"]
current = self._params.get(key, encoding='utf-8') or "Stock"
def on_select(res, val):
if res == DialogResult.CONFIRM:
self._params.put(key, val)
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr(key), themes, current, on_close=on_select))
class StarPilotVisualsLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._sub_panels = {
"advanced": StarPilotAdvancedVisualsLayout(),
"widgets": StarPilotVisualWidgetsLayout(),
"model": StarPilotModelUILayout(),
"navigation": StarPilotNavigationVisualsLayout(),
"qol": StarPilotVisualQOLLayout(),
}
self.CATEGORIES = [
display_panel = create_tile_panel([
{"title": tr_noop("Advanced UI Controls"), "panel": "advanced", "icon": "toggle_icons/icon_advanced_device.png", "color": "#8B5CF6"},
{"title": tr_noop("Driving Screen Widgets"), "panel": "widgets", "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6"},
{"title": tr_noop("Model UI"), "panel": "model", "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6"},
{"title": tr_noop("Navigation Widgets"), "panel": "navigation", "icon": "toggle_icons/icon_map.png", "color": "#8B5CF6"},
{"title": tr_noop("Quality of Life"), "panel": "qol", "icon": "toggle_icons/icon_quality_of_life.png", "color": "#8B5CF6"},
]
for name, panel in self._sub_panels.items():
if hasattr(panel, 'set_navigate_callback'):
panel.set_navigate_callback(self._navigate_to)
if hasattr(panel, 'set_back_callback'):
panel.set_back_callback(self._go_back)
self._rebuild_grid()
], {
"advanced": StarPilotAdvancedVisualsLayout(),
"qol": StarPilotVisualQOLLayout(),
})
self._section_tabs = TabbedSectionHost([
TabSectionSpec("display", "Display", display_panel),
TabSectionSpec("widgets", "Widgets", StarPilotVisualWidgetsLayout()),
TabSectionSpec("model", "Model", StarPilotModelUILayout()),
TabSectionSpec("navigation", "Nav", StarPilotNavigationVisualsLayout()),
])
def set_navigate_callback(self, callback):
self._section_tabs.set_navigate_callback(callback)
def set_back_callback(self, callback):
self._section_tabs.set_back_callback(callback)
def _render(self, rect):
self._section_tabs.render(rect)
def set_current_sub_panel(self, sub_panel: str):
self._section_tabs.set_current_sub_panel(sub_panel)
def show_event(self):
self._section_tabs.show_event()
def hide_event(self):
self._section_tabs.hide_event()
class StarPilotAdvancedVisualsLayout(StarPilotPanel):
@@ -558,15 +494,6 @@ class StarPilotNavigationVisualsLayout(StarPilotPanel):
"color": "#8B5CF6",
"visible": lambda: self._params.get_bool("NavigationUI"),
},
{
"title": tr_noop("Mapbox Limits"),
"type": "toggle",
"get_state": lambda: self._params.get_bool("SLCMapboxFiller"),
"set_state": lambda s: self._params.put_bool("SLCMapboxFiller", s),
"icon": "toggle_icons/icon_speed_limit.png",
"color": "#8B5CF6",
"visible": lambda: self._params.get_bool("NavigationUI") and self._params.get_bool("ShowSpeedLimits"),
},
{
"title": tr_noop("Vienna Signs"),
"type": "toggle",