firehose fixups

pull/36306/head
Shane Smiskol 5 days ago
parent efda5b4f3b
commit 3e82b47c9c
  1. 65
      selfdrive/ui/layouts/settings/firehose.py
  2. 4
      system/ui/lib/scroll_panel.py

@ -7,7 +7,8 @@ from openpilot.common.params import Params
from openpilot.common.swaglog import cloudlog from openpilot.common.swaglog import cloudlog
from openpilot.selfdrive.ui.ui_state import ui_state from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.athena.registration import UNREGISTERED_DONGLE_ID from openpilot.system.athena.registration import UNREGISTERED_DONGLE_ID
from openpilot.system.ui.lib.application import gui_app, FontWeight from openpilot.system.ui.lib.application import gui_app, FontWeight, FONT_SCALE
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
from openpilot.system.ui.lib.wrap_text import wrap_text from openpilot.system.ui.lib.wrap_text import wrap_text
from openpilot.system.ui.widgets import Widget from openpilot.system.ui.widgets import Widget
@ -43,6 +44,7 @@ class FirehoseLayout(Widget):
self.params = Params() self.params = Params()
self.segment_count = self._get_segment_count() self.segment_count = self._get_segment_count()
self.scroll_panel = GuiScrollPanel() self.scroll_panel = GuiScrollPanel()
self._content_height = 0
self.running = True self.running = True
self.update_thread = threading.Thread(target=self._update_loop, daemon=True) self.update_thread = threading.Thread(target=self._update_loop, daemon=True)
@ -69,55 +71,25 @@ class FirehoseLayout(Widget):
def _render(self, rect: rl.Rectangle): def _render(self, rect: rl.Rectangle):
# Calculate content dimensions # Calculate content dimensions
content_width = rect.width - 80 content_rect = rl.Rectangle(rect.x, rect.y, rect.width, self._content_height)
content_height = self._calculate_content_height(int(content_width))
content_rect = rl.Rectangle(rect.x, rect.y, rect.width, content_height)
# Handle scrolling and render with clipping # Handle scrolling and render with clipping
scroll_offset = self.scroll_panel.update(rect, content_rect) scroll_offset = self.scroll_panel.update(rect, content_rect)
rl.begin_scissor_mode(int(rect.x), int(rect.y), int(rect.width), int(rect.height)) rl.begin_scissor_mode(int(rect.x), int(rect.y), int(rect.width), int(rect.height))
self._render_content(rect, scroll_offset) self._content_height = self._render_content(rect, scroll_offset)
rl.end_scissor_mode() rl.end_scissor_mode()
def _calculate_content_height(self, content_width: int) -> int: def _render_content(self, rect: rl.Rectangle, scroll_offset: float) -> int:
height = 80 # Top margin
# Title
height += 100 + 40
# Description
desc_font = gui_app.font(FontWeight.NORMAL)
desc_lines = wrap_text(desc_font, DESCRIPTION, 45, content_width)
height += len(desc_lines) * 45 + 40
# Status section
height += 32 # Separator
status_text, _ = self._get_status()
status_lines = wrap_text(gui_app.font(FontWeight.BOLD), status_text, 60, content_width)
height += len(status_lines) * 60 + 20
# Contribution count (if available)
if self.segment_count > 0:
contrib_text = f"{self.segment_count} segment(s) of your driving is in the training dataset so far."
contrib_lines = wrap_text(gui_app.font(FontWeight.BOLD), contrib_text, 52, content_width)
height += len(contrib_lines) * 52 + 20
# Instructions section
height += 32 # Separator
inst_lines = wrap_text(gui_app.font(FontWeight.NORMAL), INSTRUCTIONS, 40, content_width)
height += len(inst_lines) * 40 + 40 # Bottom margin
return height
def _render_content(self, rect: rl.Rectangle, scroll_offset: float):
x = int(rect.x + 40) x = int(rect.x + 40)
y = int(rect.y + 40 + scroll_offset) y = int(rect.y + 40 + scroll_offset)
w = int(rect.width - 80) w = int(rect.width - 80)
# Title # Title (centered)
title_font = gui_app.font(FontWeight.MEDIUM) title_font = gui_app.font(FontWeight.MEDIUM)
rl.draw_text_ex(title_font, TITLE, rl.Vector2(x, y), 100, 0, rl.WHITE) text_width = measure_text_cached(title_font, TITLE, 100).x
y += 140 title_x = rect.x + (rect.width - text_width) / 2
rl.draw_text_ex(title_font, TITLE, rl.Vector2(title_x, y), 100, 0, rl.WHITE)
y += 200
# Description # Description
y = self._draw_wrapped_text(x, y, w, DESCRIPTION, gui_app.font(FontWeight.NORMAL), 45, rl.WHITE) y = self._draw_wrapped_text(x, y, w, DESCRIPTION, gui_app.font(FontWeight.NORMAL), 45, rl.WHITE)
@ -143,14 +115,17 @@ class FirehoseLayout(Widget):
y += 30 y += 30
# Instructions # Instructions
self._draw_wrapped_text(x, y, w, INSTRUCTIONS, gui_app.font(FontWeight.NORMAL), 40, self.LIGHT_GRAY) y = self._draw_wrapped_text(x, y, w, INSTRUCTIONS, gui_app.font(FontWeight.NORMAL), 40, self.LIGHT_GRAY)
# bottom margin + remove effect of scroll offset
return y - self.scroll_panel.offset + 40
def _draw_wrapped_text(self, x, y, width, text, font, size, color): def _draw_wrapped_text(self, x, y, width, text, font, font_size, color):
wrapped = wrap_text(font, text, size, width) wrapped = wrap_text(font, text, font_size, width)
for line in wrapped: for line in wrapped:
rl.draw_text_ex(font, line, rl.Vector2(x, y), size, 0, color) rl.draw_text_ex(font, line, rl.Vector2(x, y), font_size, 0, color)
y += size y += font_size * FONT_SCALE
return y return round(y)
def _get_status(self) -> tuple[str, rl.Color]: def _get_status(self) -> tuple[str, rl.Color]:
network_type = ui_state.sm["deviceState"].networkType network_type = ui_state.sm["deviceState"].networkType

@ -128,3 +128,7 @@ class GuiScrollPanel:
self._offset_filter_y.x = position self._offset_filter_y.x = position
self._velocity_filter_y.x = 0.0 self._velocity_filter_y.x = 0.0
self._scroll_state = ScrollState.IDLE self._scroll_state = ScrollState.IDLE
@property
def offset(self) -> float:
return float(self._offset_filter_y.x)

Loading…
Cancel
Save