From 51382176734b63d947269e24971f748c614ee312 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Thu, 12 Jun 2025 14:11:11 -0700 Subject: [PATCH] raylib ui: store rects (#35538) * simple version * use it * use it in one place --- selfdrive/ui/layouts/main.py | 4 +--- selfdrive/ui/onroad/exp_button.py | 6 ++++-- selfdrive/ui/onroad/model_renderer.py | 2 -- selfdrive/ui/ui.py | 3 ++- system/ui/lib/toggle.py | 5 +++-- system/ui/lib/widget.py | 15 +++++++++++---- 6 files changed, 21 insertions(+), 14 deletions(-) diff --git a/selfdrive/ui/layouts/main.py b/selfdrive/ui/layouts/main.py index 113c2f33c..099444b9a 100644 --- a/selfdrive/ui/layouts/main.py +++ b/selfdrive/ui/layouts/main.py @@ -21,7 +21,6 @@ class MainLayout(Widget): self._sidebar_visible = True self._current_mode = MainState.HOME self._prev_onroad = False - self._window_rect = None # Initialize layouts self._layouts = {MainState.HOME: HomeLayout(), MainState.SETTINGS: SettingsLayout(), MainState.ONROAD: AugmentedRoadView()} @@ -45,7 +44,6 @@ class MainLayout(Widget): self._layouts[MainState.ONROAD].set_callbacks(on_click=self._on_onroad_clicked) def _update_layout_rects(self, rect): - self._window_rect = rect self._sidebar_rect = rl.Rectangle(rect.x, rect.y, SIDEBAR_WIDTH, rect.height) x_offset = SIDEBAR_WIDTH if self._sidebar_visible else 0 @@ -85,5 +83,5 @@ class MainLayout(Widget): if self._sidebar_visible: self._sidebar.render(self._sidebar_rect) - content_rect = self._content_rect if self._sidebar_visible else self._window_rect + content_rect = self._content_rect if self._sidebar_visible else self._rect self._layouts[self._current_mode].render(content_rect) diff --git a/selfdrive/ui/onroad/exp_button.py b/selfdrive/ui/onroad/exp_button.py index cabfe2a24..6ca1b4ca8 100644 --- a/selfdrive/ui/onroad/exp_button.py +++ b/selfdrive/ui/onroad/exp_button.py @@ -23,7 +23,10 @@ class ExpButton(Widget): self._black_bg: rl.Color = rl.Color(0, 0, 0, 166) self._txt_wheel: rl.Texture = gui_app.texture('icons/chffr_wheel.png', icon_size, icon_size) self._txt_exp: rl.Texture = gui_app.texture('icons/experimental.png', icon_size, icon_size) - self._rect: rl.Rectangle = rl.Rectangle(0, 0, button_size, button_size) + self._rect = rl.Rectangle(0, 0, button_size, button_size) + + 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"] @@ -44,7 +47,6 @@ class ExpButton(Widget): return False def _render(self, rect: rl.Rectangle) -> None: - self._rect.x, self._rect.y = rect.x, rect.y center_x = int(self._rect.x + self._rect.width // 2) center_y = int(self._rect.y + self._rect.height // 2) diff --git a/selfdrive/ui/onroad/model_renderer.py b/selfdrive/ui/onroad/model_renderer.py index 853bfa506..ab2b7aaef 100644 --- a/selfdrive/ui/onroad/model_renderer.py +++ b/selfdrive/ui/onroad/model_renderer.py @@ -66,7 +66,6 @@ class ModelRenderer(Widget): self._car_space_transform = np.zeros((3, 3), dtype=np.float32) self._transform_dirty = True self._clip_region = None - self._rect = None self._exp_gradient = { 'start': (0.0, 1.0), # Bottom of path @@ -93,7 +92,6 @@ class ModelRenderer(Widget): return # Set up clipping region - self._rect = rect self._clip_region = rl.Rectangle( rect.x - CLIP_MARGIN, rect.y - CLIP_MARGIN, rect.width + 2 * CLIP_MARGIN, rect.height + 2 * CLIP_MARGIN ) diff --git a/selfdrive/ui/ui.py b/selfdrive/ui/ui.py index b37fe62cb..bb2b431e0 100755 --- a/selfdrive/ui/ui.py +++ b/selfdrive/ui/ui.py @@ -9,12 +9,13 @@ from openpilot.selfdrive.ui.ui_state import ui_state def main(): gui_app.init_window("UI") main_layout = MainLayout() + main_layout.set_rect(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) for _ in gui_app.render(): ui_state.update() # TODO handle brigntness and awake state here - main_layout.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) + main_layout.render() kick_watchdog() diff --git a/system/ui/lib/toggle.py b/system/ui/lib/toggle.py index 4c08da50d..ab651479a 100644 --- a/system/ui/lib/toggle.py +++ b/system/ui/lib/toggle.py @@ -17,10 +17,12 @@ class Toggle(Widget): super().__init__() self._state = initial_state self._enabled = True - self._rect = rl.Rectangle(0, 0, WIDTH, HEIGHT) self._progress = 1.0 if initial_state else 0.0 self._target = self._progress + def set_rect(self, rect: rl.Rectangle): + self._rect = rl.Rectangle(rect.x, rect.y, WIDTH, HEIGHT) + def handle_input(self): if not self._enabled: return 0 @@ -52,7 +54,6 @@ class Toggle(Widget): self._progress = max(0.0, min(1.0, self._progress)) def _render(self, rect: rl.Rectangle): - self._rect.x, self._rect.y = rect.x, rect.y self.update() if self._enabled: diff --git a/system/ui/lib/widget.py b/system/ui/lib/widget.py index 1335eae41..6c274124f 100644 --- a/system/ui/lib/widget.py +++ b/system/ui/lib/widget.py @@ -11,19 +11,26 @@ class DialogResult(IntEnum): class Widget(abc.ABC): def __init__(self): + self._rect: rl.Rectangle = rl.Rectangle(0, 0, 0, 0) self._is_pressed = False - def render(self, rect: rl.Rectangle) -> bool | int | None: - ret = self._render(rect) + def set_rect(self, rect: rl.Rectangle) -> None: + self._rect = rect + + def render(self, rect: rl.Rectangle = None) -> bool | int | None: + if rect is not None: + self.set_rect(rect) + + ret = self._render(self._rect) # Keep track of whether mouse down started within the widget's rectangle mouse_pos = rl.get_mouse_position() if rl.is_mouse_button_pressed(rl.MouseButton.MOUSE_BUTTON_LEFT): - if rl.check_collision_point_rec(mouse_pos, rect): + if rl.check_collision_point_rec(mouse_pos, self._rect): self._is_pressed = True if rl.is_mouse_button_released(rl.MouseButton.MOUSE_BUTTON_LEFT): - if self._is_pressed and rl.check_collision_point_rec(mouse_pos, rect): + if self._is_pressed and rl.check_collision_point_rec(mouse_pos, self._rect): self._handle_mouse_release(mouse_pos) self._is_pressed = False