raylib ui: common state update function (#35546)

* add _update_state

* nonlya

* visible already does this for us!

* do hud renderer and exp button

* temp

* this really needs some type of timer like QT

* this really needs some type of timer like QT

* todo

* use in model renderer

* Revert "use in model renderer"

This reverts commit d35f774155.

* no passing rect

* cl

* unused now
pull/35143/head^2
Shane Smiskol 5 days ago committed by GitHub
parent f275d6d892
commit 25e123a23a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      selfdrive/ui/layouts/home.py
  2. 4
      selfdrive/ui/layouts/sidebar.py
  3. 19
      selfdrive/ui/onroad/driver_state.py
  4. 5
      selfdrive/ui/onroad/exp_button.py
  5. 8
      selfdrive/ui/onroad/hud_renderer.py
  6. 5
      system/ui/lib/widget.py

@ -193,6 +193,7 @@ class HomeLayout(Widget):
self._setup_widget.render(setup_rect)
def _refresh(self):
# TODO: implement _update_state with a timer
self.update_available = self.update_alert.refresh()
self.alert_count = self.offroad_alert.refresh()
self._update_state_priority(self.update_available, self.alert_count > 0)

@ -86,8 +86,6 @@ class Sidebar(Widget):
self._on_flag_click = on_flag
def _render(self, rect: rl.Rectangle):
self.update_state()
# Background
rl.draw_rectangle_rec(rect, Colors.SIDEBAR_BG)
@ -95,7 +93,7 @@ class Sidebar(Widget):
self._draw_network_indicator(rect)
self._draw_metrics(rect)
def update_state(self):
def _update_state(self):
sm = ui_state.sm
if not sm.updated['deviceState']:
return

@ -50,7 +50,6 @@ class DriverStateRenderer(Widget):
self.is_active = False
self.is_rhd = False
self.dm_fade_state = 0.0
self.state_updated = False
self.driver_pose_vals = np.zeros(3, dtype=np.float32)
self.driver_pose_diff = np.zeros(3, dtype=np.float32)
self.driver_pose_sins = np.zeros(3, dtype=np.float32)
@ -79,10 +78,6 @@ class DriverStateRenderer(Widget):
ui_state.sm.seen['driverMonitoringState']))
def _render(self, rect):
self._update_state(ui_state.sm, rect)
if not self.state_updated:
return
# Set opacity based on active state
opacity = 0.65 if self.is_active else 0.2
@ -107,8 +102,9 @@ class DriverStateRenderer(Widget):
if self.v_arc_data:
rl.draw_spline_linear(self.v_arc_lines, len(self.v_arc_lines), self.v_arc_data.thickness, self.arc_color)
def _update_state(self, sm, rect):
def _update_state(self):
"""Update the driver monitoring state based on model data"""
sm = ui_state.sm
if not sm.updated["driverMonitoringState"]:
return
@ -158,16 +154,15 @@ class DriverStateRenderer(Widget):
self.face_keypoints_transformed = self.face_kpts_draw[:, :2] * kp_depth[:, None]
# Pre-calculate all drawing elements
self._pre_calculate_drawing_elements(rect)
self.state_updated = True
self._pre_calculate_drawing_elements()
def _pre_calculate_drawing_elements(self, rect):
def _pre_calculate_drawing_elements(self):
"""Pre-calculate all drawing elements based on the current rectangle"""
# Calculate icon position (bottom-left or bottom-right)
width, height = rect.width, rect.height
width, height = self._rect.width, self._rect.height
offset = UI_BORDER_SIZE + BTN_SIZE // 2
self.position_x = rect.x + (width - offset if self.is_rhd else offset)
self.position_y = rect.y + height - offset
self.position_x = self._rect.x + (width - offset if self.is_rhd else offset)
self.position_y = self._rect.y + height - offset
# Pre-calculate the face lines positions
positioned_keypoints = self.face_keypoints_transformed + np.array([self.position_x, self.position_y])

@ -1,6 +1,5 @@
import time
import pyray as rl
from cereal.messaging import SubMaster
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.widget import Widget
@ -28,8 +27,8 @@ class ExpButton(Widget):
def set_rect(self, rect: rl.Rectangle) -> None:
self._rect.x, self._rect.y = rect.x, rect.y
def update_state(self, sm: SubMaster) -> None:
selfdrive_state = sm["selfdriveState"]
def _update_state(self) -> None:
selfdrive_state = ui_state.sm["selfdriveState"]
self._experimental_mode = selfdrive_state.experimentalMode
self._engageable = selfdrive_state.engageable or selfdrive_state.enabled

@ -1,6 +1,5 @@
import pyray as rl
from dataclasses import dataclass
from cereal.messaging import SubMaster
from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus
from openpilot.selfdrive.ui.onroad.exp_button import ExpButton
from openpilot.system.ui.lib.application import gui_app, FontWeight
@ -72,8 +71,9 @@ class HudRenderer(Widget):
self._exp_button = ExpButton(UI_CONFIG.button_size, UI_CONFIG.wheel_icon_size)
def _update_state(self, sm: SubMaster) -> None:
def _update_state(self) -> None:
"""Update HUD state based on car state and controls state."""
sm = ui_state.sm
if sm.recv_frame["carState"] < ui_state.started_frame:
self.is_cruise_set = False
self.set_speed = SET_SPEED_NA
@ -99,12 +99,8 @@ class HudRenderer(Widget):
speed_conversion = CV.MS_TO_KPH if ui_state.is_metric else CV.MS_TO_MPH
self.speed = max(0.0, v_ego * speed_conversion)
self._exp_button.update_state(sm)
def _render(self, rect: rl.Rectangle) -> None:
"""Render HUD elements to the screen."""
self._update_state(ui_state.sm)
# Draw the header background
rl.draw_rectangle_gradient_v(
int(rect.x),

@ -34,6 +34,8 @@ class Widget(abc.ABC):
if rect is not None:
self.set_rect(rect)
self._update_state()
if not self.is_visible:
return None
@ -56,6 +58,9 @@ class Widget(abc.ABC):
def _render(self, rect: rl.Rectangle) -> bool | int | None:
"""Render the widget within the given rectangle."""
def _update_state(self):
"""Optionally update the widget's non-layout state. This is called before rendering."""
def _update_layout_rects(self) -> None:
"""Optionally update any layout rects on Widget rect change."""

Loading…
Cancel
Save