WIP BigUI: Fixes + Model Manager Stuff

This commit is contained in:
firestarsdog
2026-04-12 01:11:17 -04:00
parent 8ead3db292
commit b0ebc18285
16 changed files with 1215 additions and 426 deletions
+3 -1
View File
@@ -37,12 +37,14 @@ class MainLayout(Widget):
# Set callbacks
self._setup_callbacks()
gui_app.push_widget(self)
# Skip onboarding on desktop; keep normal flow on device.
self._onboarding_window = None
if not PC:
self._onboarding_window = OnboardingWindow()
if not self._onboarding_window.completed:
gui_app.set_modal_overlay(self._onboarding_window)
gui_app.push_widget(self._onboarding_window)
def _render(self, _):
self._handle_onroad_transition()
@@ -6,6 +6,7 @@ from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.system.ui.widgets import Widget, DialogResult
from openpilot.selfdrive.ui.layouts.settings.starpilot.asset_loader import starpilot_texture
GEOMETRY_OFFSET = 10
@@ -207,7 +208,7 @@ class HubTile(AetherTile):
self.title = title
self.desc = desc
if icon_path:
if starpilot_icon: self._icon = gui_app.starpilot_texture(icon_path, 100, 100)
if starpilot_icon: self._icon = starpilot_texture(icon_path, 100, 100)
else: self._icon = gui_app.texture(icon_path, 100, 100)
else: self._icon = None
self._font_title = gui_app.font(FontWeight.BOLD)
@@ -254,7 +255,7 @@ class ToggleTile(AetherTile):
self.get_state = get_state
self.set_state = set_state
self.set_enabled(is_enabled or True)
self._icon = gui_app.starpilot_texture(icon_path, 80, 80) if icon_path else None
self._icon = starpilot_texture(icon_path, 80, 80) if icon_path else None
self._font = gui_app.font(FontWeight.BOLD)
self._font_desc = gui_app.font(FontWeight.NORMAL)
self._active_color = self.surface_color
@@ -302,7 +303,7 @@ class ValueTile(AetherTile):
self.desc = desc
self.get_value = get_value
self._enabled = is_enabled or (lambda: True)
self._icon = gui_app.starpilot_texture(icon_path, 80, 80) if icon_path else None
self._icon = starpilot_texture(icon_path, 80, 80) if icon_path else None
self._font = gui_app.font(FontWeight.BOLD)
self._font_desc = gui_app.font(FontWeight.NORMAL)
self._active_color = self.surface_color
@@ -505,13 +506,13 @@ class AetherSliderDialog(Widget):
if self._is_pressed_ok:
self._ok_target = 0.0
if rl.check_collision_point_rec(mouse_pos, self._ok_rect):
gui_app.set_modal_overlay(None)
gui_app.pop_widget()
self._user_callback(DialogResult.CONFIRM, self._current_val)
self._is_pressed_ok = False
if self._is_pressed_cancel:
self._cancel_target = 0.0
if rl.check_collision_point_rec(mouse_pos, self._cancel_rect):
gui_app.set_modal_overlay(None)
gui_app.pop_widget()
self._user_callback(DialogResult.CANCEL, self._current_val)
self._is_pressed_cancel = False
@@ -0,0 +1,31 @@
from __future__ import annotations
from importlib.resources import as_file, files
import pyray as rl
from openpilot.system.ui.lib.application import gui_app
def starpilot_texture(asset_path: str, width: int | None = None, height: int | None = None,
alpha_premultiply: bool = False, keep_aspect_ratio: bool = True) -> rl.Texture:
if width is not None:
width = round(width)
if height is not None:
height = round(height)
cache_key = f"starpilot_{asset_path}_{width}_{height}_{alpha_premultiply}_{keep_aspect_ratio}"
if cache_key in gui_app._textures:
return gui_app._textures[cache_key]
starpilot_assets = files("openpilot.starpilot").joinpath("assets")
with as_file(starpilot_assets.joinpath(asset_path)) as fspath:
image_obj = gui_app._load_image_from_path(fspath.as_posix(), width, height, alpha_premultiply, keep_aspect_ratio)
texture_obj = gui_app._load_texture_from_image(image_obj)
if gui_app._scale != 1.0 and width is not None and height is not None:
texture_obj.width = width
texture_obj.height = height
gui_app._textures[cache_key] = texture_obj
return texture_obj
+34 -20
View File
@@ -10,8 +10,8 @@ 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.confirm_dialog import ConfirmDialog, alert_dialog
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
from openpilot.system.ui.widgets.input_dialog import InputDialog
from openpilot.system.ui.widgets.keyboard import Keyboard
from openpilot.system.ui.widgets.option_dialog import MultiOptionDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid
@@ -27,6 +27,7 @@ LEGACY_STARPILOT_PARAM_RENAMES = {
class StarPilotDataLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._keyboard = Keyboard(min_text_size=0)
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"},
@@ -134,44 +135,51 @@ class StarPilotBackupsLayout(StarPilotPanel):
threading.Thread(target=_task, daemon=True).start()
gui_app.set_modal_overlay(InputDialog(tr("Name your backup"), "", on_close=on_name))
self._keyboard.reset(min_text_size=0)
self._keyboard.set_title(tr("Name your backup"), "")
self._keyboard.set_text("")
self._keyboard.set_callback(lambda result: on_name(result, self._keyboard.text))
gui_app.push_widget(self._keyboard)
def _on_restore_backup(self):
backups = self._get_backups()
if not backups:
gui_app.set_modal_overlay(alert_dialog(tr("No backups found.")))
return
dialog = MultiOptionDialog(tr("Select Backup"), backups)
def _on_select(res, val):
if res == DialogResult.CONFIRM:
def _on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
gui_app.set_modal_overlay(alert_dialog(tr("Restoring... device will reboot.")))
def _task():
subprocess.run(["rm", "-rf", "/data/openpilot/*"])
subprocess.run(["tar", "--use-compress-program=zstd", "-xf", f"/data/backups/{val}", "-C", "/"])
subprocess.run(["tar", "--use-compress-program=zstd", "-xf", f"/data/backups/{dialog.selection}", "-C", "/"])
os.system("reboot")
threading.Thread(target=_task, daemon=True).start()
gui_app.set_modal_overlay(SelectionDialog(tr("Select Backup"), backups, on_close=_on_select))
gui_app.set_modal_overlay(dialog, callback=_on_select)
def _on_delete_backup(self):
backups = self._get_backups()
if not backups:
gui_app.set_modal_overlay(alert_dialog(tr("No backups found.")))
return
dialog = MultiOptionDialog(tr("Delete Backup"), backups)
def _on_select(res, val):
if res == DialogResult.CONFIRM:
os.remove(f"/data/backups/{val}")
def _on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
os.remove(f"/data/backups/{dialog.selection}")
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr("Delete Backup"), backups, on_close=_on_select))
gui_app.set_modal_overlay(dialog, callback=_on_select)
class StarPilotToggleBackupsLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._keyboard = Keyboard(min_text_size=0)
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
self.CATEGORIES = [
{"title": tr_noop("Create Toggle Backup"), "type": "hub", "on_click": self._on_create, "color": "#D43D8A"},
@@ -199,20 +207,25 @@ class StarPilotToggleBackupsLayout(StarPilotPanel):
gui_app.set_modal_overlay(alert_dialog(tr("Toggle backup created.")))
self._rebuild_grid()
gui_app.set_modal_overlay(InputDialog(tr("Name your toggle backup"), "", on_close=on_name))
self._keyboard.reset(min_text_size=0)
self._keyboard.set_title(tr("Name your toggle backup"), "")
self._keyboard.set_text("")
self._keyboard.set_callback(lambda result: on_name(result, self._keyboard.text))
gui_app.push_widget(self._keyboard)
def _on_restore(self):
backups = self._get_backups()
if not backups:
gui_app.set_modal_overlay(alert_dialog(tr("No toggle backups found.")))
return
dialog = MultiOptionDialog(tr("Select Toggle Backup"), backups)
def _on_select(res, val):
if res == DialogResult.CONFIRM:
def _on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
def on_confirm(r2):
if r2 == DialogResult.CONFIRM:
src = Path(f"/data/toggle_backups/{val}")
src = Path(f"/data/toggle_backups/{dialog.selection}")
params_dir = Path("/data/params/d")
for old_key, new_key in LEGACY_STARPILOT_PARAM_RENAMES.items():
if (src / old_key).exists():
@@ -228,17 +241,18 @@ class StarPilotToggleBackupsLayout(StarPilotPanel):
gui_app.set_modal_overlay(ConfirmDialog(tr("This will overwrite your current toggles."), tr("Restore"), on_close=on_confirm))
gui_app.set_modal_overlay(SelectionDialog(tr("Select Toggle Backup"), backups, on_close=_on_select))
gui_app.set_modal_overlay(dialog, callback=_on_select)
def _on_delete(self):
backups = self._get_backups()
if not backups:
gui_app.set_modal_overlay(alert_dialog(tr("No toggle backups found.")))
return
dialog = MultiOptionDialog(tr("Delete Toggle Backup"), backups)
def _on_select(res, val):
if res == DialogResult.CONFIRM:
shutil.rmtree(f"/data/toggle_backups/{val}", ignore_errors=True)
def _on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
shutil.rmtree(f"/data/toggle_backups/{dialog.selection}", ignore_errors=True)
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr("Delete Toggle Backup"), backups, on_close=_on_select))
gui_app.set_modal_overlay(dialog, callback=_on_select)
@@ -7,7 +7,6 @@ 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.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.aethergrid import AetherSliderDialog, TileGrid
File diff suppressed because it is too large Load Diff
@@ -4,8 +4,8 @@ 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.confirm_dialog import ConfirmDialog
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
from openpilot.system.ui.widgets.input_dialog import InputDialog
from openpilot.system.ui.widgets.keyboard import Keyboard
from openpilot.system.ui.widgets.option_dialog import MultiOptionDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel, create_master_toggle_panel, 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
@@ -653,13 +653,14 @@ class StarPilotLongitudinalTuneLayout(StarPilotPanel):
option_labels = [tr(option_label) for _, option_label in options]
label_to_value = {tr(option_label): option_value for option_value, option_label in options}
default_option = next((tr(option_label) for option_value, option_label in options if option_value == current_value), option_labels[0])
dialog = MultiOptionDialog(tr(title), option_labels, default_option)
def on_select(res, val):
if res == DialogResult.CONFIRM:
self._params.put_int(key, label_to_value[val])
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
self._params.put_int(key, label_to_value[dialog.selection])
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr(title), option_labels, default_option, on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
def _show_int_selector(self, key, min_v, max_v, unit=""):
def on_close(res, val):
@@ -847,45 +848,42 @@ class StarPilotSpeedLimitControllerLayout(StarPilotPanel):
current_primary = self._params.get("SLCPriority1", encoding='utf-8') or "Map Data"
current_secondary = self._params.get("SLCPriority2", encoding='utf-8') or "None"
def on_secondary_select(primary, res, val):
if res == DialogResult.CONFIRM:
def on_secondary_select(primary, dialog, res):
if res == DialogResult.CONFIRM and dialog.selection:
self._params.put("SLCPriority1", primary)
self._params.put("SLCPriority2", val)
self._params.put("SLCPriority2", dialog.selection)
self._rebuild_grid()
def show_secondary_dialog(primary):
secondary_options = ["None"] + [option for option in ("Dashboard", "Map Data", "Vision") if option != primary]
selected_secondary = current_secondary if current_secondary in secondary_options else "None"
gui_app.set_modal_overlay(
SelectionDialog(
tr("SLC Secondary Priority"),
secondary_options,
selected_secondary,
on_close=lambda res, val: on_secondary_select(primary, res, val),
)
)
secondary_dialog = MultiOptionDialog(tr("SLC Secondary Priority"), secondary_options, selected_secondary)
gui_app.set_modal_overlay(secondary_dialog, callback=lambda res: on_secondary_select(primary, secondary_dialog, res))
def on_primary_select(res, val):
if res != DialogResult.CONFIRM:
primary_dialog = MultiOptionDialog(tr("SLC Primary Priority"), primary_options, current_primary)
def on_primary_select(res):
if res != DialogResult.CONFIRM or not primary_dialog.selection:
return
if val in ("Highest", "Lowest"):
self._params.put("SLCPriority1", val)
if primary_dialog.selection in ("Highest", "Lowest"):
self._params.put("SLCPriority1", primary_dialog.selection)
self._params.put("SLCPriority2", "None")
self._rebuild_grid()
return
show_secondary_dialog(val)
show_secondary_dialog(primary_dialog.selection)
gui_app.set_modal_overlay(
SelectionDialog(tr("SLC Primary Priority"), primary_options, current_primary, on_close=on_primary_select)
)
gui_app.set_modal_overlay(primary_dialog, callback=on_primary_select)
def _show_selection(self, key, options):
def on_select(res, val):
if res == DialogResult.CONFIRM:
self._params.put(key, val)
current = self._params.get(key, encoding='utf-8') or "None"
dialog = MultiOptionDialog(tr(key), options, current)
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
self._params.put(key, dialog.selection)
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr(key), options, self._params.get(key, encoding='utf-8') or "None", on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
class StarPilotSLCOffsetsLayout(StarPilotPanel):
@@ -1006,6 +1004,7 @@ class StarPilotSLCVisualsLayout(StarPilotPanel):
class StarPilotWeatherLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._keyboard = Keyboard(min_text_size=1)
self.CATEGORIES = [
{"title": tr_noop("Low Visibility"), "panel": "low_visibility", "icon": "toggle_icons/icon_rainbow.png", "color": "#597497"},
{"title": tr_noop("Rain"), "panel": "rain", "icon": "toggle_icons/icon_rainbow.png", "color": "#597497"},
@@ -1022,18 +1021,23 @@ class StarPilotWeatherLayout(StarPilotPanel):
def _set_weather_key(self):
options = ["ADD", "REMOVE"]
dialog = MultiOptionDialog(tr("Weather API Key"), options, "ADD")
def on_select(res, val):
if res == DialogResult.CONFIRM:
if val == "ADD":
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
if dialog.selection == "ADD":
def on_key(res, text):
if res == DialogResult.CONFIRM:
self._params.put("WeatherAPIKey", text)
self._rebuild_grid()
gui_app.set_modal_overlay(InputDialog(tr("Weather API Key"), on_close=on_key))
elif val == "REMOVE":
self._keyboard.reset(min_text_size=1)
self._keyboard.set_title(tr("Weather API Key"), "")
self._keyboard.set_text("")
self._keyboard.set_callback(lambda result: on_key(result, self._keyboard.text))
gui_app.push_widget(self._keyboard)
elif dialog.selection == "REMOVE":
def on_confirm(res):
if res == DialogResult.CONFIRM:
@@ -1042,7 +1046,7 @@ class StarPilotWeatherLayout(StarPilotPanel):
gui_app.set_modal_overlay(ConfirmDialog(tr("Remove API Key?"), tr("Confirm"), on_close=on_confirm))
gui_app.set_modal_overlay(SelectionDialog(tr("Weather API Key"), options, "ADD", on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
class StarPilotWeatherBase(StarPilotPanel):
@@ -6,7 +6,7 @@ from pathlib import Path
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.system.ui.widgets.option_dialog import MultiOptionDialog
from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog, alert_dialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
from openpilot.starpilot.common.maps_catalog import (
@@ -117,13 +117,14 @@ class StarPilotMapsLayout(StarPilotPanel):
def _on_schedule(self):
options = list(MAP_SCHEDULE_LABELS.values())
current = schedule_label(self._params.get("PreferredSchedule"))
dialog = MultiOptionDialog(tr("Auto Update Schedule"), options, current)
def on_select(res, val):
if res == DialogResult.CONFIRM:
self._params.put("PreferredSchedule", schedule_param_value(val))
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
self._params.put("PreferredSchedule", schedule_param_value(dialog.selection))
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr("Auto Update Schedule"), options, current, on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
def _on_download(self):
current_selected = self._params.get("MapsSelected", encoding="utf-8") or ""
@@ -2,15 +2,15 @@ from __future__ import annotations
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.system.ui.widgets.confirm_dialog import ConfirmDialog, alert_dialog
from openpilot.system.ui.widgets.input_dialog import InputDialog
from openpilot.system.ui.widgets.keyboard import Keyboard
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
class StarPilotNavigationLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._keyboard = Keyboard(min_text_size=1)
self._sub_panels = {
"mapbox": StarPilotMapboxLayout(),
}
@@ -60,7 +60,11 @@ class StarPilotNavigationLayout(StarPilotPanel):
if res == DialogResult.CONFIRM and text:
self._params.put("SearchAddress", text)
gui_app.set_modal_overlay(InputDialog(tr("Search Destination"), "", on_close=on_close))
self._keyboard.reset(min_text_size=1)
self._keyboard.set_title(tr("Search Destination"), "")
self._keyboard.set_text("")
self._keyboard.set_callback(lambda result: on_close(result, self._keyboard.text))
gui_app.push_widget(self._keyboard)
def _on_home(self):
current = self._params.get("HomeAddress", encoding='utf-8') or ""
@@ -70,7 +74,11 @@ class StarPilotNavigationLayout(StarPilotPanel):
self._params.put("HomeAddress", text)
self._rebuild_grid()
gui_app.set_modal_overlay(InputDialog(tr("Home Address"), current, on_close=on_close))
self._keyboard.reset(min_text_size=0)
self._keyboard.set_title(tr("Home Address"), "")
self._keyboard.set_text(current)
self._keyboard.set_callback(lambda result: on_close(result, self._keyboard.text))
gui_app.push_widget(self._keyboard)
def _on_work(self):
current = self._params.get("WorkAddress", encoding='utf-8') or ""
@@ -80,12 +88,17 @@ class StarPilotNavigationLayout(StarPilotPanel):
self._params.put("WorkAddress", text)
self._rebuild_grid()
gui_app.set_modal_overlay(InputDialog(tr("Work Address"), current, on_close=on_close))
self._keyboard.reset(min_text_size=0)
self._keyboard.set_title(tr("Work Address"), "")
self._keyboard.set_text(current)
self._keyboard.set_callback(lambda result: on_close(result, self._keyboard.text))
gui_app.push_widget(self._keyboard)
class StarPilotMapboxLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._keyboard = Keyboard(min_text_size=1)
self.CATEGORIES = [
{
"title": tr_noop("Public Mapbox Key"),
@@ -131,4 +144,8 @@ class StarPilotMapboxLayout(StarPilotPanel):
self._params.put(key, text)
self._rebuild_grid()
gui_app.set_modal_overlay(InputDialog(tr(f"Enter {key.replace('Mapbox', 'Mapbox ')}"), "", on_close=on_close))
self._keyboard.reset(min_text_size=1)
self._keyboard.set_title(tr(f"Enter {key.replace('Mapbox', 'Mapbox ')}"), "")
self._keyboard.set_text("")
self._keyboard.set_callback(lambda result: on_close(result, self._keyboard.text))
gui_app.push_widget(self._keyboard)
@@ -7,7 +7,7 @@ from openpilot.system.hardware.hw import Paths
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.system.ui.widgets.option_dialog import MultiOptionDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
if HARDWARE.get_device_type() == "pc":
@@ -161,19 +161,21 @@ class StarPilotThemesLayout(StarPilotPanel):
else:
current = "Clear"
def on_select(res, val):
if res == DialogResult.CONFIRM:
if val == "Stock":
dialog = MultiOptionDialog(tr("Startup Alert"), options, current)
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
if dialog.selection == "Stock":
self._params.put("StartupMessageTop", "Be ready to take over at any time")
self._params.put("StartupMessageBottom", "Always keep hands on wheel and eyes on road")
elif val == "StarPilot":
elif dialog.selection == "StarPilot":
self._params.put("StartupMessageTop", "Hop in and buckle up!")
self._params.put("StartupMessageBottom", "Human-tested, frog-approved")
else:
self._params.remove("StartupMessageTop")
self._params.remove("StartupMessageBottom")
gui_app.set_modal_overlay(SelectionDialog(tr("Startup Alert"), options, current, on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
class StarPilotPersonalizeLayout(StarPilotPanel):
@@ -317,12 +319,14 @@ class StarPilotPersonalizeLayout(StarPilotPanel):
if not themes:
return
def on_select(res, val):
if res == DialogResult.CONFIRM:
selected_slug = option_map.get(val)
dialog = MultiOptionDialog(tr(key), themes, current)
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
selected_slug = option_map.get(dialog.selection)
if selected_slug is None:
return
self._params.put(key, selected_slug)
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr(key), themes, current, on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
@@ -5,8 +5,8 @@ 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.confirm_dialog import ConfirmDialog, alert_dialog
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
from openpilot.system.ui.widgets.input_dialog import InputDialog
from openpilot.system.ui.widgets.keyboard import Keyboard
from openpilot.system.ui.widgets.option_dialog import MultiOptionDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid
@@ -39,6 +39,7 @@ REPORT_CATEGORIES = [
class StarPilotUtilitiesLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._keyboard = Keyboard(min_text_size=1)
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
self.CATEGORIES = [
{
@@ -79,13 +80,15 @@ class StarPilotUtilitiesLayout(StarPilotPanel):
def _on_force_drive_state(self):
options = [tr("Offroad"), tr("Onroad"), tr("Default")]
current = self._get_force_drive_state()
dialog = MultiOptionDialog(tr("Force Drive State"), options, current)
def on_select(res, val):
if res == DialogResult.CONFIRM:
if val == tr("Offroad"):
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
if dialog.selection == tr("Offroad"):
self._params.put_bool("ForceOffroad", True)
self._params.put_bool("ForceOnroad", False)
elif val == tr("Onroad"):
elif dialog.selection == tr("Onroad"):
self._params.put_bool("ForceOnroad", True)
self._params.put_bool("ForceOffroad", False)
else:
@@ -93,25 +96,30 @@ class StarPilotUtilitiesLayout(StarPilotPanel):
self._params.put_bool("ForceOnroad", False)
self._rebuild_grid()
current = self._get_force_drive_state()
gui_app.set_modal_overlay(SelectionDialog(tr("Force Drive State"), options, current, on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
def _on_report_issue(self):
def on_category(res, val):
if res != DialogResult.CONFIRM:
dialog = MultiOptionDialog(tr("Select Issue"), REPORT_CATEGORIES)
def on_category(res):
if res != DialogResult.CONFIRM or not dialog.selection:
return
discord_user = self._params.get("DiscordUsername", encoding='utf-8') or ""
def on_discord(res2, username):
if res2 == DialogResult.CONFIRM and username:
self._params.put("DiscordUsername", username)
report = json.dumps({"DiscordUser": username, "Issue": val})
report = json.dumps({"DiscordUser": username, "Issue": dialog.selection})
self._params_memory.put("IssueReported", report)
gui_app.set_modal_overlay(alert_dialog(tr("Issue reported. Thank you!")))
gui_app.set_modal_overlay(InputDialog(tr("Discord Username"), discord_user or "", on_close=on_discord))
self._keyboard.reset(min_text_size=1)
self._keyboard.set_title(tr("Discord Username"), "")
self._keyboard.set_text(discord_user or "")
self._keyboard.set_callback(lambda result: on_discord(result, self._keyboard.text))
gui_app.push_widget(self._keyboard)
gui_app.set_modal_overlay(SelectionDialog(tr("Select Issue"), REPORT_CATEGORIES, on_close=on_category))
gui_app.set_modal_overlay(dialog, callback=on_category)
def _on_reset_defaults(self):
def _do_reset(res):
@@ -5,7 +5,7 @@ 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.confirm_dialog import ConfirmDialog
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
from openpilot.system.ui.widgets.option_dialog import MultiOptionDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import AetherSliderDialog, TileGrid, HubTile, ToggleTile, ValueTile
from openpilot.selfdrive.ui.lib.starpilot_state import starpilot_state
@@ -170,19 +170,22 @@ class StarPilotVehicleSettingsLayout(StarPilotPanel):
gui_app.set_modal_overlay(ConfirmDialog(tr("No fingerprint list available."), tr("OK"), on_close=lambda r: None))
return
def on_select(res, val):
if res == DialogResult.CONFIRM:
self._params.put("CarMake", val)
current_make = self._params.get("CarMake", encoding='utf-8') or ""
default_make = current_make if current_make in makes else makes[0]
dialog = MultiOptionDialog(tr("Select Make"), makes, default_make)
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
self._params.put("CarMake", dialog.selection)
current_model = self._params.get("CarModel", encoding='utf-8') or ""
available_models = {option.value for option in self._models_by_make.get(val, ())}
available_models = {option.value for option in self._models_by_make.get(dialog.selection, ())}
if current_model not in available_models:
self._params.remove("CarModel")
self._params.remove("CarModelName")
self._rebuild_grid()
current_make = self._params.get("CarMake", encoding='utf-8') or ""
default_make = current_make if current_make in makes else makes[0]
gui_app.set_modal_overlay(SelectionDialog(tr("Select Make"), makes, default_make, on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
def _on_select_model(self):
make = self._params.get("CarMake", encoding='utf-8') or ""
@@ -203,15 +206,17 @@ class StarPilotVehicleSettingsLayout(StarPilotPanel):
if default_option is None:
default_option = next((option.option_label for option in model_options if option.value == current_model), option_labels[0])
def on_select(res, val):
if res == DialogResult.CONFIRM:
selected_option = selected_by_label[val]
dialog = MultiOptionDialog(tr("Select Model"), option_labels, default_option)
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
selected_option = selected_by_label[dialog.selection]
self._params.put("CarModel", selected_option.value)
self._params.put("CarModelName", selected_option.label)
self._params.put("CarMake", make)
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr("Select Model"), option_labels, default_option, on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
def _on_disable_long(self, state):
if state:
@@ -3,7 +3,7 @@ from openpilot.selfdrive.ui.lib.starpilot_state import starpilot_state
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.system.ui.widgets.option_dialog import MultiOptionDialog
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
@@ -453,15 +453,17 @@ class StarPilotModelUILayout(StarPilotPanel):
presets = ["Stock", "#FFFFFF", "#178644", "#3B82F6", "#E63956", "#8B5CF6", "#F59E0B"]
current = self._params.get(key, encoding='utf-8') or "Stock"
def on_select(res, val):
if res == DialogResult.CONFIRM:
if val == "Stock":
dialog = MultiOptionDialog(tr(key), presets, current)
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
if dialog.selection == "Stock":
self._params.remove(key)
else:
self._params.put(key, val)
self._params.put(key, dialog.selection)
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr(key), presets, current, on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
class StarPilotNavigationVisualsLayout(StarPilotPanel):
@@ -554,10 +556,12 @@ class StarPilotVisualQOLLayout(StarPilotPanel):
def _show_camera_view_selector(self):
current = self._params.get_int("CameraView")
def on_select(res, val):
if res == DialogResult.CONFIRM:
idx = self.CAMERA_VIEWS.index(val)
dialog = MultiOptionDialog(tr("Camera View"), self.CAMERA_VIEWS, self.CAMERA_VIEWS[current])
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
idx = self.CAMERA_VIEWS.index(dialog.selection)
self._params.put_int("CameraView", idx)
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr("Camera View"), self.CAMERA_VIEWS, self.CAMERA_VIEWS[current], on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
@@ -3,7 +3,7 @@ from openpilot.selfdrive.ui.lib.starpilot_state import starpilot_state
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.system.ui.widgets.option_dialog import MultiOptionDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
ACTION_OPTIONS = [
@@ -107,14 +107,15 @@ class StarPilotWheelLayout(StarPilotPanel):
current = self._get_action_name(key)
if current not in actions:
current = actions[0]
dialog = MultiOptionDialog(tr(key), actions, current)
def on_select(res, val):
if res == DialogResult.CONFIRM:
self._params.put_int(key, ACTION_IDS.get(val, 0))
def on_select(res):
if res == DialogResult.CONFIRM and dialog.selection:
self._params.put_int(key, ACTION_IDS.get(dialog.selection, 0))
self._params_memory.put_bool("StarPilotTogglesUpdated", True)
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr(key), actions, current, on_close=on_select))
gui_app.set_modal_overlay(dialog, callback=on_select)
def _rebuild_grid(self):
if not self.CATEGORIES:
@@ -2,7 +2,7 @@ import pyray as rl
from cereal import log
from openpilot.common.params import Params
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.application import gui_app
from openpilot.selfdrive.ui.layouts.settings.starpilot.asset_loader import starpilot_texture
from openpilot.system.ui.widgets import Widget
BTN_SIZE = 192
@@ -20,10 +20,10 @@ class PersonalityButton(Widget):
# 0=traffic, 1=aggressive, 2=standard, 3=relaxed
self._icons = [
gui_app.starpilot_texture("stock_theme/distance_icons/traffic.png", ICON_SIZE, ICON_SIZE),
gui_app.starpilot_texture("stock_theme/distance_icons/aggressive.png", ICON_SIZE, ICON_SIZE),
gui_app.starpilot_texture("stock_theme/distance_icons/standard.png", ICON_SIZE, ICON_SIZE),
gui_app.starpilot_texture("stock_theme/distance_icons/relaxed.png", ICON_SIZE, ICON_SIZE),
starpilot_texture("stock_theme/distance_icons/traffic.png", ICON_SIZE, ICON_SIZE),
starpilot_texture("stock_theme/distance_icons/aggressive.png", ICON_SIZE, ICON_SIZE),
starpilot_texture("stock_theme/distance_icons/standard.png", ICON_SIZE, ICON_SIZE),
starpilot_texture("stock_theme/distance_icons/relaxed.png", ICON_SIZE, ICON_SIZE),
]
self._rect = rl.Rectangle(0, 0, BTN_SIZE, BTN_SIZE)
+9
View File
@@ -8,6 +8,7 @@ from openpilot.system.ui.lib.application import gui_app, MouseEvent
from openpilot.system.hardware import TICI
from collections import deque
MOUSE_WHEEL_SCROLL_SPEED = 50
MIN_VELOCITY = 10 # px/s, changes from auto scroll to steady state
MIN_VELOCITY_FOR_CLICKING = 2 * 60 # px/s, accepts clicks while auto scrolling below this velocity
MIN_DRAG_PIXELS = 12
@@ -73,6 +74,14 @@ class GuiScrollPanel2:
self._handle_mouse_event(mouse_event, bounds, bounds_size, content_size)
self._previous_mouse_event = mouse_event
wheel_move = rl.get_mouse_wheel_move()
if wheel_move != 0 and self.enabled and rl.check_collision_point_rec(rl.get_mouse_position(), bounds):
scroll_delta = wheel_move * MOUSE_WHEEL_SCROLL_SPEED
if self._horizontal:
self._offset.x += scroll_delta
else:
self._offset.y += scroll_delta
self._update_state(bounds_size, content_size)
if DEBUG: