mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 05:23:41 +08:00
a82935f326
Integrate onroad views, configurable widgets, local settings, steering-profile contracts, Bluetooth and Android Auto with their device and runtime services. Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> Co-authored-by: Daniel Koepping <elkoled@gmail.com> Co-authored-by: Danny <dannyirwin31@yahoo.com> Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com> Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com> Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com> Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu> Co-authored-by: Shane Smiskol <shane@smiskol.com> Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com> Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Co-authored-by: stef <19478336+stefpi@users.noreply.github.com> Co-authored-by: whoisdomi <dcantu83@gmail.com> Co-authored-by: Intelli <contact@intelli.software> Co-authored-by: pharmacomaniac <blittle65@gmail.com> Co-authored-by: prabhaavp <prabhaav@msu.edu>
96 lines
3.0 KiB
Python
96 lines
3.0 KiB
Python
"""Supplied toggle values and request-only interaction for the offline shell."""
|
|
|
|
from collections.abc import Callable
|
|
from dataclasses import dataclass
|
|
from enum import StrEnum
|
|
|
|
|
|
class ToggleKey(StrEnum):
|
|
ENABLED = "enabled"
|
|
EXPERIMENTAL = "experimental"
|
|
SAFE_MODE = "safe_mode"
|
|
DISENGAGE_ACCELERATOR = "disengage_accelerator"
|
|
LANE_DEPARTURE = "lane_departure"
|
|
ALWAYS_ON_DM = "always_on_dm"
|
|
RIGHT_HAND_DRIVING = "right_hand_driving"
|
|
RECORD_FRONT = "record_front"
|
|
RECORD_AUDIO = "record_audio"
|
|
METRIC = "metric"
|
|
|
|
|
|
class Personality(StrEnum):
|
|
AGGRESSIVE = "aggressive"
|
|
STANDARD = "standard"
|
|
RELAXED = "relaxed"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class TogglesState:
|
|
enabled: bool = True
|
|
experimental: bool = False
|
|
safe_mode: bool = False
|
|
disengage_accelerator: bool = False
|
|
lane_departure: bool = False
|
|
always_on_dm: bool = False
|
|
right_hand_driving: bool = False
|
|
record_front: bool = False
|
|
record_audio: bool = False
|
|
metric: bool = False
|
|
personality: Personality = Personality.STANDARD
|
|
scroll_y: float = 0.0
|
|
unavailable: frozenset[ToggleKey] = frozenset()
|
|
|
|
def __post_init__(self) -> None:
|
|
if not 0 <= self.scroll_y <= 1000:
|
|
raise ValueError("Toggle scroll position must stay within the content")
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ToggleRequest:
|
|
key: ToggleKey | None = None
|
|
value: bool | None = None
|
|
personality: Personality | None = None
|
|
|
|
|
|
class TogglesInput:
|
|
def __init__(self, emit: Callable[[ToggleRequest], None]):
|
|
self.emit = emit
|
|
self._pressed: tuple[float, float, ToggleRequest, float] | None = None
|
|
|
|
def _target(self, x: float, y: float, state: TogglesState) -> ToggleRequest | None:
|
|
if not 500 <= x < 2160 or not 50 <= y < 1030:
|
|
return None
|
|
row = int((y - 50 + state.scroll_y) // 171)
|
|
rows = (ToggleKey.ENABLED, ToggleKey.EXPERIMENTAL, ToggleKey.SAFE_MODE,
|
|
ToggleKey.DISENGAGE_ACCELERATOR, None, ToggleKey.LANE_DEPARTURE,
|
|
ToggleKey.ALWAYS_ON_DM, ToggleKey.RIGHT_HAND_DRIVING, ToggleKey.RECORD_FRONT,
|
|
ToggleKey.RECORD_AUDIO, ToggleKey.METRIC)
|
|
if 0 <= row < len(rows) and rows[row] is not None and x >= 1790:
|
|
key = rows[row]
|
|
if key in state.unavailable:
|
|
return None
|
|
return ToggleRequest(key=key, value=not getattr(state, key.value))
|
|
if row == 4 and 1300 <= x < 2110:
|
|
index = min(2, int((x - 1300) // 270))
|
|
return ToggleRequest(personality=tuple(Personality)[index])
|
|
return None
|
|
|
|
def press(self, x: float, y: float, state: TogglesState) -> None:
|
|
target = self._target(x, y, state)
|
|
self._pressed = (x, y, target, state.scroll_y) if target else None
|
|
|
|
def move(self, x: float, y: float, state: TogglesState) -> None:
|
|
if self._pressed:
|
|
_, _, target, scroll_y = self._pressed
|
|
if state.scroll_y != scroll_y or self._target(x, y, state) != target:
|
|
self.cancel()
|
|
|
|
def release(self, x: float, y: float, state: TogglesState) -> None:
|
|
self.move(x, y, state)
|
|
if self._pressed:
|
|
self.emit(self._pressed[2])
|
|
self.cancel()
|
|
|
|
def cancel(self) -> None:
|
|
self._pressed = None
|