mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-12 19:33:48 +08:00
Merge branch 'upstream/openpilot/master' into sync-20250731
# Conflicts: # .github/workflows/selfdrive_tests.yaml # common/params.h # common/params_keys.h # common/params_pyx.pyx # docs/CARS.md # opendbc_repo # panda # selfdrive/car/tests/test_models.py # selfdrive/pandad/pandad.cc # selfdrive/pandad/pandad.h # selfdrive/selfdrived/selfdrived.py # selfdrive/ui/translations/main_ar.ts # selfdrive/ui/translations/main_de.ts # selfdrive/ui/translations/main_es.ts # selfdrive/ui/translations/main_fr.ts # selfdrive/ui/translations/main_ja.ts # selfdrive/ui/translations/main_ko.ts # selfdrive/ui/translations/main_pt-BR.ts # selfdrive/ui/translations/main_th.ts # selfdrive/ui/translations/main_tr.ts # selfdrive/ui/translations/main_zh-CHS.ts # selfdrive/ui/translations/main_zh-CHT.ts # system/athena/athenad.py # system/athena/manage_athenad.py # system/manager/manager.py # system/sentry.py # uv.lock Sync: `commaai/opendbc:master` into `sunnypilot/opendbc:master` Sync: `commaai/panda:master` into `sunnypilot/panda:master`
This commit is contained in:
@@ -8,3 +8,8 @@ Quick start:
|
||||
* set `SCALE=1.5` to scale the entire UI by 1.5x
|
||||
* https://www.raylib.com/cheatsheet/cheatsheet.html
|
||||
* https://electronstudio.github.io/raylib-python-cffi/README.html#quickstart
|
||||
|
||||
Style guide:
|
||||
* All graphical elements should subclass [`Widget`](/system/ui/widgets/__init__.py).
|
||||
* Prefer a stateful widget over a function for easy migration from QT
|
||||
* All internal class variables and functions should be prefixed with `_`
|
||||
|
||||
@@ -7,7 +7,7 @@ import threading
|
||||
from collections.abc import Callable
|
||||
from collections import deque
|
||||
from dataclasses import dataclass
|
||||
from enum import IntEnum
|
||||
from enum import StrEnum
|
||||
from typing import NamedTuple
|
||||
from importlib.resources import as_file, files
|
||||
from openpilot.common.swaglog import cloudlog
|
||||
@@ -33,16 +33,16 @@ ASSETS_DIR = files("openpilot.selfdrive").joinpath("assets")
|
||||
FONT_DIR = ASSETS_DIR.joinpath("fonts")
|
||||
|
||||
|
||||
class FontWeight(IntEnum):
|
||||
THIN = 0
|
||||
EXTRA_LIGHT = 1
|
||||
LIGHT = 2
|
||||
NORMAL = 3
|
||||
MEDIUM = 4
|
||||
SEMI_BOLD = 5
|
||||
BOLD = 6
|
||||
EXTRA_BOLD = 7
|
||||
BLACK = 8
|
||||
class FontWeight(StrEnum):
|
||||
THIN = "Inter-Thin.ttf"
|
||||
EXTRA_LIGHT = "Inter-ExtraLight.ttf"
|
||||
LIGHT = "Inter-Light.ttf"
|
||||
NORMAL = "Inter-Regular.ttf"
|
||||
MEDIUM = "Inter-Medium.ttf"
|
||||
SEMI_BOLD = "Inter-SemiBold.ttf"
|
||||
BOLD = "Inter-Bold.ttf"
|
||||
EXTRA_BOLD = "Inter-ExtraBold.ttf"
|
||||
BLACK = "Inter-Black.ttf"
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -312,34 +312,23 @@ class GuiApplication:
|
||||
return self._height
|
||||
|
||||
def _load_fonts(self):
|
||||
font_files = (
|
||||
"Inter-Thin.ttf",
|
||||
"Inter-ExtraLight.ttf",
|
||||
"Inter-Light.ttf",
|
||||
"Inter-Regular.ttf",
|
||||
"Inter-Medium.ttf",
|
||||
"Inter-SemiBold.ttf",
|
||||
"Inter-Bold.ttf",
|
||||
"Inter-ExtraBold.ttf",
|
||||
"Inter-Black.ttf",
|
||||
)
|
||||
|
||||
# Create a character set from our keyboard layouts
|
||||
from openpilot.system.ui.widgets.keyboard import KEYBOARD_LAYOUTS
|
||||
|
||||
all_chars = set()
|
||||
for layout in KEYBOARD_LAYOUTS.values():
|
||||
all_chars.update(key for row in layout for key in row)
|
||||
all_chars = "".join(all_chars)
|
||||
all_chars += "–✓°"
|
||||
all_chars += "–✓×°"
|
||||
|
||||
codepoint_count = rl.ffi.new("int *", 1)
|
||||
codepoints = rl.load_codepoints(all_chars, codepoint_count)
|
||||
|
||||
for index, font_file in enumerate(font_files):
|
||||
with as_file(FONT_DIR.joinpath(font_file)) as fspath:
|
||||
for font_weight_file in FontWeight:
|
||||
with as_file(FONT_DIR.joinpath(font_weight_file)) as fspath:
|
||||
font = rl.load_font_ex(fspath.as_posix(), 200, codepoints, codepoint_count[0])
|
||||
rl.set_texture_filter(font.texture, rl.TextureFilter.TEXTURE_FILTER_BILINEAR)
|
||||
self._fonts[index] = font
|
||||
self._fonts[font_weight_file] = font
|
||||
|
||||
rl.unload_codepoints(codepoints)
|
||||
rl.gui_set_font(self._fonts[FontWeight.NORMAL])
|
||||
|
||||
@@ -91,7 +91,7 @@ class WifiManager:
|
||||
# Set tethering ssid as "weedle" + first 4 characters of a dongle id
|
||||
self._tethering_ssid = "weedle"
|
||||
if Params is not None:
|
||||
dongle_id = Params().get("DongleId", encoding="utf-8")
|
||||
dongle_id = Params().get("DongleId")
|
||||
if dongle_id:
|
||||
self._tethering_ssid += "-" + dongle_id[:4]
|
||||
self.running: bool = True
|
||||
|
||||
+43
-29
@@ -1,18 +1,21 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import pyray as rl
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from enum import IntEnum
|
||||
|
||||
import pyray as rl
|
||||
|
||||
from openpilot.system.hardware import PC
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
from openpilot.system.ui.lib.button import gui_button, ButtonStyle
|
||||
from openpilot.system.ui.lib.label import gui_label, gui_text_box
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.button import Button, ButtonStyle
|
||||
from openpilot.system.ui.widgets.label import gui_label, gui_text_box
|
||||
|
||||
NVME = "/dev/nvme0n1"
|
||||
USERDATA = "/dev/disk/by-partlabel/userdata"
|
||||
TIMEOUT = 3*60
|
||||
|
||||
|
||||
class ResetMode(IntEnum):
|
||||
@@ -31,8 +34,16 @@ class ResetState(IntEnum):
|
||||
class Reset(Widget):
|
||||
def __init__(self, mode):
|
||||
super().__init__()
|
||||
self.mode = mode
|
||||
self.reset_state = ResetState.NONE
|
||||
self._mode = mode
|
||||
self._previous_reset_state = None
|
||||
self._reset_state = ResetState.NONE
|
||||
self._cancel_button = Button("Cancel", self._cancel_callback)
|
||||
self._confirm_button = Button("Confirm", self._confirm, button_style=ButtonStyle.PRIMARY)
|
||||
self._reboot_button = Button("Reboot", lambda: os.system("sudo reboot"))
|
||||
self._render_status = True
|
||||
|
||||
def _cancel_callback(self):
|
||||
self._render_status = False
|
||||
|
||||
def _do_erase(self):
|
||||
if PC:
|
||||
@@ -50,53 +61,56 @@ class Reset(Widget):
|
||||
if rm == 0 or fmt == 0:
|
||||
os.system("sudo reboot")
|
||||
else:
|
||||
self.reset_state = ResetState.FAILED
|
||||
self._reset_state = ResetState.FAILED
|
||||
|
||||
def start_reset(self):
|
||||
self.reset_state = ResetState.RESETTING
|
||||
self._reset_state = ResetState.RESETTING
|
||||
threading.Timer(0.1, self._do_erase).start()
|
||||
|
||||
def _update_state(self):
|
||||
if self._reset_state != self._previous_reset_state:
|
||||
self._previous_reset_state = self._reset_state
|
||||
self._timeout_st = time.monotonic()
|
||||
elif self._reset_state != ResetState.RESETTING and (time.monotonic() - self._timeout_st) > TIMEOUT:
|
||||
exit(0)
|
||||
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
label_rect = rl.Rectangle(rect.x + 140, rect.y, rect.width - 280, 100)
|
||||
gui_label(label_rect, "System Reset", 100, font_weight=FontWeight.BOLD)
|
||||
|
||||
text_rect = rl.Rectangle(rect.x + 140, rect.y + 140, rect.width - 280, rect.height - 90 - 100)
|
||||
gui_text_box(text_rect, self.get_body_text(), 90)
|
||||
gui_text_box(text_rect, self._get_body_text(), 90)
|
||||
|
||||
button_height = 160
|
||||
button_spacing = 50
|
||||
button_top = rect.y + rect.height - button_height
|
||||
button_width = (rect.width - button_spacing) / 2.0
|
||||
|
||||
if self.reset_state != ResetState.RESETTING:
|
||||
if self.mode == ResetMode.RECOVER or self.reset_state == ResetState.FAILED:
|
||||
if gui_button(rl.Rectangle(rect.x, button_top, button_width, button_height), "Reboot"):
|
||||
os.system("sudo reboot")
|
||||
elif self.mode == ResetMode.USER_RESET:
|
||||
if gui_button(rl.Rectangle(rect.x, button_top, button_width, button_height), "Cancel"):
|
||||
return False
|
||||
if self._reset_state != ResetState.RESETTING:
|
||||
if self._mode == ResetMode.RECOVER or self._reset_state == ResetState.FAILED:
|
||||
self._reboot_button.render(rl.Rectangle(rect.x, button_top, rect.width, button_height))
|
||||
elif self._mode == ResetMode.USER_RESET:
|
||||
self._cancel_button.render(rl.Rectangle(rect.x, button_top, button_width, button_height))
|
||||
|
||||
if self.reset_state != ResetState.FAILED:
|
||||
if gui_button(rl.Rectangle(rect.x + button_width + 50, button_top, button_width, button_height),
|
||||
"Confirm", button_style=ButtonStyle.PRIMARY):
|
||||
self.confirm()
|
||||
if self._reset_state != ResetState.FAILED:
|
||||
self._confirm_button.render(rl.Rectangle(rect.x + button_width + 50, button_top, button_width, button_height))
|
||||
|
||||
return True
|
||||
return self._render_status
|
||||
|
||||
def confirm(self):
|
||||
if self.reset_state == ResetState.CONFIRM:
|
||||
def _confirm(self):
|
||||
if self._reset_state == ResetState.CONFIRM:
|
||||
self.start_reset()
|
||||
else:
|
||||
self.reset_state = ResetState.CONFIRM
|
||||
self._reset_state = ResetState.CONFIRM
|
||||
|
||||
def get_body_text(self):
|
||||
if self.reset_state == ResetState.CONFIRM:
|
||||
def _get_body_text(self):
|
||||
if self._reset_state == ResetState.CONFIRM:
|
||||
return "Are you sure you want to reset your device?"
|
||||
if self.reset_state == ResetState.RESETTING:
|
||||
if self._reset_state == ResetState.RESETTING:
|
||||
return "Resetting device...\nThis may take up to a minute."
|
||||
if self.reset_state == ResetState.FAILED:
|
||||
if self._reset_state == ResetState.FAILED:
|
||||
return "Reset failed. Reboot to try again."
|
||||
if self.mode == ResetMode.RECOVER:
|
||||
if self._mode == ResetMode.RECOVER:
|
||||
return "Unable to mount data partition. Partition may be corrupted. Press confirm to erase and reset your device."
|
||||
return "System reset triggered. Press confirm to erase all content and settings. Press cancel to resume boot."
|
||||
|
||||
|
||||
+4
-4
@@ -10,11 +10,11 @@ import pyray as rl
|
||||
from cereal import log
|
||||
from openpilot.system.hardware import HARDWARE
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
from openpilot.system.ui.lib.button import gui_button, ButtonStyle
|
||||
from openpilot.system.ui.lib.label import gui_label, gui_text_box
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.widgets.network import WifiManagerUI, WifiManagerWrapper
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.button import gui_button, ButtonStyle
|
||||
from openpilot.system.ui.widgets.keyboard import Keyboard
|
||||
from openpilot.system.ui.widgets.label import gui_label, gui_text_box
|
||||
from openpilot.system.ui.widgets.network import WifiManagerUI, WifiManagerWrapper
|
||||
|
||||
NetworkType = log.DeviceState.NetworkType
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import sys
|
||||
|
||||
from openpilot.system.ui.lib.application import gui_app
|
||||
from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.text import wrap_text
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
|
||||
from openpilot.system.ui.sunnypilot.lib.application import gui_app_sp
|
||||
|
||||
|
||||
+4
-4
@@ -3,11 +3,11 @@ import re
|
||||
import sys
|
||||
import pyray as rl
|
||||
from openpilot.system.hardware import HARDWARE, PC
|
||||
from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||
from openpilot.system.ui.lib.button import gui_button, ButtonStyle
|
||||
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
|
||||
from openpilot.system.ui.lib.application import gui_app
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
|
||||
from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.button import gui_button, ButtonStyle
|
||||
|
||||
MARGIN = 50
|
||||
SPACING = 40
|
||||
|
||||
@@ -7,10 +7,10 @@ from enum import IntEnum
|
||||
|
||||
from openpilot.system.hardware import HARDWARE
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
from openpilot.system.ui.lib.button import gui_button, ButtonStyle
|
||||
from openpilot.system.ui.lib.label import gui_text_box, gui_label
|
||||
from openpilot.system.ui.lib.wifi_manager import WifiManagerWrapper
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.button import gui_button, ButtonStyle
|
||||
from openpilot.system.ui.widgets.label import gui_text_box, gui_label
|
||||
from openpilot.system.ui.widgets.network import WifiManagerUI
|
||||
|
||||
# Constants
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import pyray as rl
|
||||
from collections.abc import Callable
|
||||
from enum import IntEnum
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
|
||||
import pyray as rl
|
||||
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos
|
||||
from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
|
||||
|
||||
class ButtonStyle(IntEnum):
|
||||
@@ -54,6 +58,8 @@ BUTTON_PRESSED_BACKGROUND_COLORS = {
|
||||
_pressed_buttons: set[str] = set() # Track mouse press state globally
|
||||
|
||||
|
||||
# TODO: This should be a Widget class
|
||||
|
||||
def gui_button(
|
||||
rect: rl.Rectangle,
|
||||
text: str,
|
||||
@@ -146,3 +152,44 @@ def gui_button(
|
||||
rl.draw_text_ex(font, text, text_pos, font_size, 0, color)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class Button(Widget):
|
||||
def __init__(self,
|
||||
text: str,
|
||||
click_callback: Callable[[], None] = None,
|
||||
font_size: int = DEFAULT_BUTTON_FONT_SIZE,
|
||||
font_weight: FontWeight = FontWeight.MEDIUM,
|
||||
button_style: ButtonStyle = ButtonStyle.NORMAL,
|
||||
border_radius: int = 10,
|
||||
):
|
||||
|
||||
super().__init__()
|
||||
self._text = text
|
||||
self._click_callback = click_callback
|
||||
self._label_font = gui_app.font(FontWeight.SEMI_BOLD)
|
||||
self._button_style = button_style
|
||||
self._font_size = font_size
|
||||
self._border_radius = border_radius
|
||||
self._font_size = font_size
|
||||
self._text_color = BUTTON_TEXT_COLOR[button_style]
|
||||
self._text_size = measure_text_cached(gui_app.font(font_weight), text, font_size)
|
||||
|
||||
def _handle_mouse_release(self, mouse_pos: MousePos):
|
||||
if self._click_callback:
|
||||
print(f"Button clicked: {self._text}")
|
||||
self._click_callback()
|
||||
|
||||
def _get_background_color(self) -> rl.Color:
|
||||
if self._is_pressed:
|
||||
return BUTTON_PRESSED_BACKGROUND_COLORS[self._button_style]
|
||||
else:
|
||||
return BUTTON_BACKGROUND_COLORS[self._button_style]
|
||||
|
||||
def _render(self, _):
|
||||
roundness = self._border_radius / (min(self._rect.width, self._rect.height) / 2)
|
||||
rl.draw_rectangle_rounded(self._rect, roundness, 10, self._get_background_color())
|
||||
|
||||
text_pos = rl.Vector2(0, self._rect.y + (self._rect.height - self._text_size.y) // 2)
|
||||
text_pos.x = self._rect.x + (self._rect.width - self._text_size.x) // 2
|
||||
rl.draw_text_ex(self._label_font, self._text, text_pos, self._font_size, 0, self._text_color)
|
||||
@@ -1,8 +1,8 @@
|
||||
import pyray as rl
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
from openpilot.system.ui.lib.button import gui_button, ButtonStyle
|
||||
from openpilot.system.ui.lib.label import gui_text_box
|
||||
from openpilot.system.ui.lib.widget import DialogResult
|
||||
from openpilot.system.ui.widgets import DialogResult
|
||||
from openpilot.system.ui.widgets.button import gui_button, ButtonStyle
|
||||
from openpilot.system.ui.widgets.label import gui_text_box
|
||||
|
||||
DIALOG_WIDTH = 1520
|
||||
DIALOG_HEIGHT = 600
|
||||
|
||||
@@ -4,10 +4,10 @@ from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
from openpilot.system.ui.lib.wrap_text import wrap_text
|
||||
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
|
||||
from openpilot.system.ui.lib.widget import Widget, DialogResult
|
||||
from openpilot.system.ui.lib.button import gui_button, ButtonStyle
|
||||
from openpilot.system.ui.lib.wrap_text import wrap_text
|
||||
from openpilot.system.ui.widgets import Widget, DialogResult
|
||||
from openpilot.system.ui.widgets.button import gui_button, ButtonStyle
|
||||
|
||||
|
||||
class ElementType(Enum):
|
||||
|
||||
@@ -2,7 +2,7 @@ import pyray as rl
|
||||
import time
|
||||
from openpilot.system.ui.lib.application import gui_app
|
||||
from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
|
||||
PASSWORD_MASK_CHAR = "•"
|
||||
PASSWORD_MASK_DELAY = 1.5 # Seconds to show character before masking
|
||||
@@ -2,10 +2,10 @@ import time
|
||||
from typing import Literal
|
||||
import pyray as rl
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
from openpilot.system.ui.lib.button import ButtonStyle, gui_button
|
||||
from openpilot.system.ui.lib.inputbox import InputBox
|
||||
from openpilot.system.ui.lib.label import gui_label
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.button import ButtonStyle, gui_button
|
||||
from openpilot.system.ui.widgets.inputbox import InputBox
|
||||
from openpilot.system.ui.widgets.label import gui_label
|
||||
|
||||
KEY_FONT_SIZE = 96
|
||||
DOUBLE_CLICK_THRESHOLD = 0.5 # seconds
|
||||
|
||||
@@ -4,6 +4,8 @@ from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||
from openpilot.system.ui.lib.utils import GuiStyleContext
|
||||
|
||||
|
||||
# TODO: This should be a Widget class
|
||||
|
||||
def gui_label(
|
||||
rect: rl.Rectangle,
|
||||
text: str,
|
||||
@@ -5,9 +5,9 @@ from abc import ABC
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos
|
||||
from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||
from openpilot.system.ui.lib.wrap_text import wrap_text
|
||||
from openpilot.system.ui.lib.button import gui_button, ButtonStyle
|
||||
from openpilot.system.ui.lib.toggle import Toggle, WIDTH as TOGGLE_WIDTH, HEIGHT as TOGGLE_HEIGHT
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.button import gui_button, ButtonStyle
|
||||
from openpilot.system.ui.widgets.toggle import Toggle, WIDTH as TOGGLE_WIDTH, HEIGHT as TOGGLE_HEIGHT
|
||||
|
||||
ITEM_BASE_WIDTH = 600
|
||||
ITEM_BASE_HEIGHT = 170
|
||||
@@ -4,13 +4,13 @@ from typing import Literal
|
||||
|
||||
import pyray as rl
|
||||
from openpilot.system.ui.lib.application import gui_app
|
||||
from openpilot.system.ui.lib.button import ButtonStyle, gui_button
|
||||
from openpilot.system.ui.lib.label import gui_label
|
||||
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
|
||||
from openpilot.system.ui.lib.wifi_manager import NetworkInfo, WifiManagerCallbacks, WifiManagerWrapper, SecurityType
|
||||
from openpilot.system.ui.widgets.keyboard import Keyboard
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.button import ButtonStyle, gui_button
|
||||
from openpilot.system.ui.widgets.confirm_dialog import confirm_dialog
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.widgets.keyboard import Keyboard
|
||||
from openpilot.system.ui.widgets.label import gui_label
|
||||
|
||||
NM_DEVICE_STATE_NEED_AUTH = 60
|
||||
MIN_PASSWORD_LENGTH = 8
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import pyray as rl
|
||||
from openpilot.system.ui.lib.application import FontWeight
|
||||
from openpilot.system.ui.lib.button import gui_button, ButtonStyle, TextAlignment
|
||||
from openpilot.system.ui.lib.label import gui_label
|
||||
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.button import gui_button, ButtonStyle, TextAlignment
|
||||
from openpilot.system.ui.widgets.label import gui_label
|
||||
|
||||
# Constants
|
||||
MARGIN = 50
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import pyray as rl
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
|
||||
ITEM_SPACING = 40
|
||||
LINE_COLOR = rl.GRAY
|
||||
@@ -1,6 +1,6 @@
|
||||
import pyray as rl
|
||||
from openpilot.system.ui.lib.application import MousePos
|
||||
from openpilot.system.ui.lib.widget import Widget
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
|
||||
ON_COLOR = rl.Color(51, 171, 76, 255)
|
||||
OFF_COLOR = rl.Color(0x39, 0x39, 0x39, 255)
|
||||
Reference in New Issue
Block a user