mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-04 13:24:13 +08:00
big ui text size polish
This commit is contained in:
@@ -382,8 +382,9 @@ def point_hits(mouse_pos: MousePos, rect: rl.Rectangle, parent_rect: rl.Rectangl
|
||||
return hit.width > 0 and hit.height > 0 and rl.check_collision_point_rec(mouse_pos, hit)
|
||||
|
||||
|
||||
def wrap_text(font: rl.Font, text: str, max_width: float, font_size: float, max_lines: int = 2) -> list[str]:
|
||||
spacing = font_size * 0.15
|
||||
def wrap_text(font: rl.Font, text: str, max_width: float, font_size: float, max_lines: int = 2,
|
||||
*, spacing: float | None = None) -> list[str]:
|
||||
spacing = font_size * 0.15 if spacing is None else spacing
|
||||
words = text.split()
|
||||
lines: list[str] = []
|
||||
current = ""
|
||||
@@ -1434,11 +1435,23 @@ class BreadcrumbController:
|
||||
aether_end_scissor_mode()
|
||||
PANEL_HEADER_TITLE_Y: int = 34
|
||||
PANEL_HEADER_SUBTITLE_Y: int = 78
|
||||
PANEL_HEADER_TITLE_FONT_SIZE: int = 30
|
||||
PANEL_HEADER_SUBTITLE_FONT_SIZE: int = 26
|
||||
PANEL_HEADER_TITLE_FONT_SIZE: int = 44
|
||||
PANEL_HEADER_SUBTITLE_FONT_SIZE: int = 32
|
||||
PANEL_HEADER_TITLE_FONT: FontWeight = FontWeight.SEMI_BOLD
|
||||
PANEL_HEADER_SUBTITLE_FONT: FontWeight = FontWeight.NORMAL
|
||||
PANEL_HEADER_SUBTITLE_LINE_HEIGHT: float = 30.0 # subtitle_size(26) + interline_gap(4)
|
||||
SETTINGS_ROW_TITLE_FONT_SIZE: int = 40
|
||||
SETTINGS_ROW_SUBTITLE_FONT_SIZE: int = 28
|
||||
SETTINGS_ROW_VALUE_FONT_SIZE: int = 34
|
||||
|
||||
|
||||
def _settings_panel_header_layout(width: float, subtitle: str | None, title_size: int, subtitle_size: int,
|
||||
subtitle_weight: FontWeight = PANEL_HEADER_SUBTITLE_FONT,
|
||||
min_title_height: float = 0.0) -> tuple[float, list[str], float, float]:
|
||||
title_height = max(title_size * FONT_SCALE, min_title_height)
|
||||
line_height = subtitle_size * FONT_SCALE + SPACING.xs
|
||||
lines = wrap_text(gui_app.font(subtitle_weight), subtitle, width, subtitle_size, max_lines=4, spacing=0) if subtitle else []
|
||||
height = title_height + (SPACING.sm + len(lines) * line_height - SPACING.xs if lines else 0.0)
|
||||
return title_height, lines, line_height, height
|
||||
|
||||
|
||||
def draw_settings_panel_header(header_rect: rl.Rectangle, title: str, subtitle: str | None = None,
|
||||
@@ -1450,19 +1463,22 @@ def draw_settings_panel_header(header_rect: rl.Rectangle, title: str, subtitle:
|
||||
title_color: rl.Color = AetherListColors.HEADER,
|
||||
subtitle_color: rl.Color = AetherListColors.SUBTEXT,
|
||||
title_weight: FontWeight = PANEL_HEADER_TITLE_FONT,
|
||||
subtitle_weight: FontWeight = PANEL_HEADER_SUBTITLE_FONT):
|
||||
subtitle_weight: FontWeight = PANEL_HEADER_SUBTITLE_FONT,
|
||||
min_title_height: float = 0.0):
|
||||
if not title:
|
||||
return
|
||||
title_font = gui_app.font(title_weight)
|
||||
y = header_rect.y
|
||||
rl.draw_text_ex(title_font, title, rl.Vector2(header_rect.x, y), title_size, 0, title_color)
|
||||
y += title_size + 8
|
||||
if subtitle:
|
||||
title_height, desc_lines, line_height, _ = _settings_panel_header_layout(
|
||||
header_rect.width * max_subtitle_width, subtitle, title_size, subtitle_size, subtitle_weight, min_title_height,
|
||||
)
|
||||
y = header_rect.y + (title_height - title_size * FONT_SCALE) / 2
|
||||
draw_text_fit_common(title_font, title, rl.Vector2(header_rect.x, y), header_rect.width * max_title_width, title_size, color=title_color)
|
||||
y = header_rect.y + title_height + SPACING.sm
|
||||
if desc_lines:
|
||||
desc_font = gui_app.font(subtitle_weight)
|
||||
desc_lines = wrap_text(desc_font, subtitle, header_rect.width * max_subtitle_width, subtitle_size, max_lines=4)
|
||||
for line in desc_lines:
|
||||
rl.draw_text_ex(desc_font, line, rl.Vector2(header_rect.x, y), subtitle_size, 0, subtitle_color)
|
||||
y += subtitle_size + 4
|
||||
draw_text_fit_common(desc_font, line, rl.Vector2(header_rect.x, y), header_rect.width * max_subtitle_width, subtitle_size, color=subtitle_color)
|
||||
y += line_height
|
||||
|
||||
|
||||
|
||||
@@ -1590,7 +1606,6 @@ def draw_standard_toggle_row(
|
||||
pressed=pressed,
|
||||
is_last=is_last,
|
||||
show_chevron=False,
|
||||
title_size=36, subtitle_size=26,
|
||||
style=style,
|
||||
)
|
||||
|
||||
@@ -1783,7 +1798,7 @@ def draw_action_pill(
|
||||
draw_text_fit_common(
|
||||
gui_app.font(FontWeight.SEMI_BOLD),
|
||||
text,
|
||||
rl.Vector2(rect.x + 12, rect.y + (rect.height - font_size) / 2),
|
||||
rl.Vector2(rect.x + 12, rect.y + (rect.height - font_size * FONT_SCALE) / 2),
|
||||
max(1.0, rect.width - 24),
|
||||
font_size,
|
||||
align_center=True,
|
||||
@@ -2099,9 +2114,9 @@ def draw_settings_list_row(
|
||||
pressed: bool = False,
|
||||
is_last: bool = False,
|
||||
show_chevron: bool = True,
|
||||
title_size: int = 36,
|
||||
subtitle_size: int = 26,
|
||||
value_size: int = 28,
|
||||
title_size: int = SETTINGS_ROW_TITLE_FONT_SIZE,
|
||||
subtitle_size: int = SETTINGS_ROW_SUBTITLE_FONT_SIZE,
|
||||
value_size: int = SETTINGS_ROW_VALUE_FONT_SIZE,
|
||||
separator_inset: int = 24,
|
||||
title_color: rl.Color | None = None,
|
||||
subtitle_color: rl.Color | None = None,
|
||||
@@ -2139,9 +2154,9 @@ def draw_settings_list_row(
|
||||
text_width = max(100.0, text_right - text_left)
|
||||
|
||||
if subtitle:
|
||||
eff_title_size = min(36, title_size)
|
||||
eff_sub_size = min(26, subtitle_size)
|
||||
total_h = eff_title_size + eff_sub_size + 4
|
||||
eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size)
|
||||
eff_sub_size = min(SETTINGS_ROW_SUBTITLE_FONT_SIZE, subtitle_size)
|
||||
total_h = (eff_title_size + eff_sub_size) * FONT_SCALE + SPACING.xs
|
||||
start_y = draw_rect.y + (draw_rect.height - total_h) / 2
|
||||
|
||||
draw_text_fit_common(
|
||||
@@ -2152,13 +2167,13 @@ def draw_settings_list_row(
|
||||
)
|
||||
draw_text_fit_common(
|
||||
gui_app.font(FontWeight.NORMAL), subtitle,
|
||||
rl.Vector2(text_left, start_y + eff_title_size + 4),
|
||||
rl.Vector2(text_left, start_y + eff_title_size * FONT_SCALE + SPACING.xs),
|
||||
text_width, eff_sub_size,
|
||||
color=resolved_subtitle_color,
|
||||
)
|
||||
else:
|
||||
eff_title_size = min(36, title_size)
|
||||
title_y = draw_rect.y + (draw_rect.height - eff_title_size) / 2
|
||||
eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size)
|
||||
title_y = draw_rect.y + (draw_rect.height - eff_title_size * FONT_SCALE) / 2
|
||||
draw_text_fit_common(
|
||||
gui_app.font(FontWeight.SEMI_BOLD), title,
|
||||
rl.Vector2(text_left, title_y),
|
||||
@@ -2188,11 +2203,11 @@ def draw_settings_list_row(
|
||||
if value:
|
||||
if is_narrow and draw_rect.height >= 86 and not subtitle:
|
||||
# Adaptive Two-Line Stacked Layout: Title on top, Value spanning full width below
|
||||
eff_title_size = min(34, title_size)
|
||||
eff_value_size = min(28, value_size)
|
||||
eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size)
|
||||
eff_value_size = min(SETTINGS_ROW_VALUE_FONT_SIZE, value_size)
|
||||
available_w = max(100.0, draw_rect.width - 48 - (32 if show_chevron else 0))
|
||||
|
||||
total_h = eff_title_size + eff_value_size + 6
|
||||
total_h = (eff_title_size + eff_value_size) * FONT_SCALE + 6
|
||||
start_y = draw_rect.y + (draw_rect.height - total_h) / 2
|
||||
|
||||
draw_text_fit_common(
|
||||
@@ -2203,7 +2218,7 @@ def draw_settings_list_row(
|
||||
)
|
||||
draw_text_fit_common(
|
||||
gui_app.font(FontWeight.MEDIUM), value,
|
||||
rl.Vector2(text_left, start_y + eff_title_size + 6),
|
||||
rl.Vector2(text_left, start_y + eff_title_size * FONT_SCALE + 6),
|
||||
available_w, eff_value_size,
|
||||
color=resolved_subtitle_color if resolved_value_color == resolved_title_color else resolved_value_color,
|
||||
)
|
||||
@@ -2219,13 +2234,13 @@ def draw_settings_list_row(
|
||||
t_width = max(100.0, draw_rect.width - 48 - v_width - (32 if show_chevron else 0))
|
||||
v_right = chevron_rect.x - 16 if show_chevron else draw_rect.x + draw_rect.width - 24
|
||||
|
||||
eff_value_size = min(28, value_size) if is_narrow else min(32, value_size)
|
||||
value_y = draw_rect.y + (draw_rect.height - eff_value_size) / 2
|
||||
eff_value_size = min(SETTINGS_ROW_VALUE_FONT_SIZE, value_size)
|
||||
value_y = draw_rect.y + (draw_rect.height - eff_value_size * FONT_SCALE) / 2
|
||||
|
||||
if subtitle:
|
||||
eff_title_size = min(34, title_size)
|
||||
eff_sub_size = min(26, subtitle_size)
|
||||
total_h = eff_title_size + eff_sub_size + 4
|
||||
eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size)
|
||||
eff_sub_size = min(SETTINGS_ROW_SUBTITLE_FONT_SIZE, subtitle_size)
|
||||
total_h = (eff_title_size + eff_sub_size) * FONT_SCALE + SPACING.xs
|
||||
start_y = draw_rect.y + (draw_rect.height - total_h) / 2
|
||||
|
||||
draw_text_fit_common(
|
||||
@@ -2236,13 +2251,13 @@ def draw_settings_list_row(
|
||||
)
|
||||
draw_text_fit_common(
|
||||
gui_app.font(FontWeight.NORMAL), subtitle,
|
||||
rl.Vector2(text_left, start_y + eff_title_size + 4),
|
||||
rl.Vector2(text_left, start_y + eff_title_size * FONT_SCALE + SPACING.xs),
|
||||
t_width, eff_sub_size,
|
||||
color=resolved_subtitle_color,
|
||||
)
|
||||
else:
|
||||
eff_title_size = min(36, title_size) if is_narrow else title_size
|
||||
title_y = draw_rect.y + (draw_rect.height - eff_title_size) / 2
|
||||
eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size) if is_narrow else title_size
|
||||
title_y = draw_rect.y + (draw_rect.height - eff_title_size * FONT_SCALE) / 2
|
||||
|
||||
draw_text_fit_common(
|
||||
gui_app.font(FontWeight.SEMI_BOLD), title,
|
||||
@@ -2267,9 +2282,9 @@ def draw_settings_list_row(
|
||||
text_right = chevron_rect.x - 12 if show_chevron else draw_rect.x + draw_rect.width - 24
|
||||
text_width = max(100.0, text_right - text_left)
|
||||
if subtitle:
|
||||
eff_title_size = min(36, title_size)
|
||||
eff_sub_size = min(26, subtitle_size)
|
||||
total_h = eff_title_size + eff_sub_size + 4
|
||||
eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size)
|
||||
eff_sub_size = min(SETTINGS_ROW_SUBTITLE_FONT_SIZE, subtitle_size)
|
||||
total_h = (eff_title_size + eff_sub_size) * FONT_SCALE + SPACING.xs
|
||||
start_y = draw_rect.y + (draw_rect.height - total_h) / 2
|
||||
draw_text_fit_common(
|
||||
gui_app.font(FontWeight.SEMI_BOLD), title,
|
||||
@@ -2279,13 +2294,13 @@ def draw_settings_list_row(
|
||||
)
|
||||
draw_text_fit_common(
|
||||
gui_app.font(FontWeight.NORMAL), subtitle,
|
||||
rl.Vector2(text_left, start_y + eff_title_size + 4),
|
||||
rl.Vector2(text_left, start_y + eff_title_size * FONT_SCALE + SPACING.xs),
|
||||
text_width, eff_sub_size,
|
||||
color=resolved_subtitle_color,
|
||||
)
|
||||
else:
|
||||
eff_title_size = min(36, title_size)
|
||||
title_y = draw_rect.y + (draw_rect.height - eff_title_size) / 2
|
||||
eff_title_size = min(SETTINGS_ROW_TITLE_FONT_SIZE, title_size)
|
||||
title_y = draw_rect.y + (draw_rect.height - eff_title_size * FONT_SCALE) / 2
|
||||
draw_text_fit_common(
|
||||
gui_app.font(FontWeight.SEMI_BOLD), title,
|
||||
rl.Vector2(text_left, title_y),
|
||||
@@ -2950,11 +2965,11 @@ def draw_selection_list_row(
|
||||
subtitle_font = gui_app.font(FontWeight.NORMAL)
|
||||
|
||||
if subtitle:
|
||||
text_height = title_size + subtitle_size + 8
|
||||
text_height = (title_size + subtitle_size) * FONT_SCALE + 8
|
||||
title_y = info_rect.y + (info_rect.height - text_height) / 2
|
||||
subtitle_y = title_y + title_size + 8
|
||||
subtitle_y = title_y + title_size * FONT_SCALE + 8
|
||||
else:
|
||||
title_y = info_rect.y + (info_rect.height - title_size) / 2
|
||||
title_y = info_rect.y + (info_rect.height - title_size * FONT_SCALE) / 2
|
||||
subtitle_y = title_y
|
||||
|
||||
draw_text_fit_common(
|
||||
@@ -3112,7 +3127,7 @@ class AetherButton(Widget):
|
||||
draw_text_fit_common(
|
||||
gui_app.font(FontWeight.MEDIUM),
|
||||
self.text,
|
||||
rl.Vector2(rect.x + 18, rect.y + (rect.height - self._font_size) / 2),
|
||||
rl.Vector2(rect.x + 18, rect.y + (rect.height - self._font_size * FONT_SCALE) / 2),
|
||||
max(1.0, rect.width - 36),
|
||||
self._font_size,
|
||||
align_center=True,
|
||||
@@ -3265,7 +3280,7 @@ class AetherSettingsView(PanelManagerView):
|
||||
if self._parent_toggle:
|
||||
mid = f"parent_toggle:{self._parent_toggle.label}"
|
||||
rect = self._interactive_rects.get(mid)
|
||||
if rect and point_hits(mouse_pos, rect, None, pad_x=6, pad_y=6):
|
||||
if rect and point_hits(mouse_pos, rect, None, pad_x=0, pad_y=0):
|
||||
return mid
|
||||
return super()._target_at(mouse_pos)
|
||||
|
||||
@@ -3290,32 +3305,29 @@ class AetherSettingsView(PanelManagerView):
|
||||
elif row.type == "toggle" and row.set_state and row.get_state:
|
||||
row.set_state(not row.get_state())
|
||||
|
||||
def _header_text(self) -> tuple[str, str]:
|
||||
title, subtitle = self._header_title, self._header_subtitle
|
||||
if self._parent_toggle:
|
||||
title = title or self._parent_toggle.label
|
||||
subtitle = subtitle or self._parent_toggle.subtitle
|
||||
return tr(title), tr(subtitle) if subtitle else ""
|
||||
|
||||
def _header_text_width(self, width: float) -> float:
|
||||
right_inset = SPACING.xl
|
||||
if self._parent_toggle:
|
||||
right_inset = AETHER_LIST_METRICS.toggle_width + AETHER_LIST_METRICS.toggle_right_inset + SPACING.lg
|
||||
return max(100.0, width - SPACING.xl - right_inset)
|
||||
|
||||
def _compute_header_height(self, content_width: float) -> float:
|
||||
if not self._has_header:
|
||||
return 0.0
|
||||
if self._parent_toggle:
|
||||
h = max(float(AETHER_LIST_METRICS.toggle_height), 54.0) # toggle vs title(46px + 8px gap)
|
||||
subtitle_text = tr(self._parent_toggle.subtitle) if self._parent_toggle.subtitle else ""
|
||||
if self._header_subtitle:
|
||||
subtitle_text = tr(self._header_subtitle)
|
||||
if subtitle_text:
|
||||
toggle_take = AETHER_LIST_METRICS.toggle_width + AETHER_LIST_METRICS.toggle_right_inset + 16
|
||||
col_w = max(100.0, content_width + AETHER_LIST_METRICS.content_right_gutter - toggle_take)
|
||||
desc_font = gui_app.font(FontWeight.NORMAL)
|
||||
desc_lines = wrap_text(desc_font, subtitle_text, col_w, 29, max_lines=4)
|
||||
h += len(desc_lines) * PANEL_HEADER_SUBTITLE_LINE_HEIGHT + 12.0
|
||||
h += SECTION_GAP
|
||||
return h
|
||||
h = 54.0 # title (46px) + inner gap (8px)
|
||||
if self._header_subtitle:
|
||||
subtitle_text = tr(self._header_subtitle)
|
||||
if subtitle_text:
|
||||
desc_font = gui_app.font(FontWeight.NORMAL)
|
||||
col_w = (content_width - self.COLUMN_GAP) / 2 if self._uses_two_columns(content_width) else content_width
|
||||
desc_lines = wrap_text(desc_font, subtitle_text, col_w, 29, max_lines=4)
|
||||
h += len(desc_lines) * PANEL_HEADER_SUBTITLE_LINE_HEIGHT + 12.0
|
||||
h += SECTION_GAP
|
||||
return h
|
||||
_, subtitle = self._header_text()
|
||||
_, _, _, height = _settings_panel_header_layout(
|
||||
self._header_text_width(content_width + AETHER_LIST_METRICS.content_right_gutter), subtitle,
|
||||
PANEL_HEADER_TITLE_FONT_SIZE, PANEL_HEADER_SUBTITLE_FONT_SIZE,
|
||||
min_title_height=AETHER_LIST_METRICS.toggle_height if self._parent_toggle else 0.0,
|
||||
)
|
||||
return height + SECTION_GAP
|
||||
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
self.set_rect(rect)
|
||||
@@ -3357,25 +3369,18 @@ class AetherSettingsView(PanelManagerView):
|
||||
AetherListColors.PANEL_BG, fade_height=self._fade_height)
|
||||
|
||||
def _draw_header(self, rect: rl.Rectangle):
|
||||
title = tr(self._header_title) if self._header_title else ""
|
||||
subtitle = tr(self._header_subtitle) if self._header_subtitle else ""
|
||||
title, subtitle = self._header_text()
|
||||
text_rect = rl.Rectangle(rect.x + SPACING.xl, rect.y, self._header_text_width(rect.width), rect.height)
|
||||
draw_settings_panel_header(
|
||||
text_rect, title, subtitle, max_title_width=1.0, max_subtitle_width=1.0,
|
||||
min_title_height=AETHER_LIST_METRICS.toggle_height if self._parent_toggle else 0.0,
|
||||
)
|
||||
|
||||
if self._parent_toggle:
|
||||
toggle = self._parent_toggle
|
||||
|
||||
display_title = title if title else tr(toggle.label)
|
||||
subtitle_text = subtitle if subtitle else (tr(toggle.subtitle) if toggle.subtitle else "")
|
||||
|
||||
toggle_take = AETHER_LIST_METRICS.toggle_width + AETHER_LIST_METRICS.toggle_right_inset + 16
|
||||
text_rect = rl.Rectangle(rect.x, rect.y, max(100.0, rect.width - toggle_take), rect.height)
|
||||
draw_settings_panel_header(text_rect, display_title, subtitle_text, title_size=30, subtitle_size=26, max_subtitle_width=1.0)
|
||||
|
||||
toggle_id = f"parent_toggle:{toggle.label}"
|
||||
tw = AETHER_LIST_METRICS.toggle_width
|
||||
th = AETHER_LIST_METRICS.toggle_height
|
||||
ri = AETHER_LIST_METRICS.toggle_right_inset
|
||||
toggle_rect = rl.Rectangle(rect.x + rect.width - tw - ri, rect.y, tw, th)
|
||||
self._interactive_rects[toggle_id] = toggle_rect
|
||||
self._interactive_rects[toggle_id] = rl.Rectangle(rect.x, rect.y, rect.width, rect.height - SECTION_GAP)
|
||||
|
||||
toggle_value = toggle.get_state()
|
||||
|
||||
@@ -3388,8 +3393,6 @@ class AetherSettingsView(PanelManagerView):
|
||||
radius_px=100,
|
||||
bg_color=rl.Color(12, 10, 18, 255),
|
||||
)
|
||||
else:
|
||||
draw_settings_panel_header(rect, title, subtitle, title_size=30, subtitle_size=26)
|
||||
|
||||
def _active_sections(self) -> list[SettingSection]:
|
||||
if self._tab_defs and self._active_tab_key:
|
||||
@@ -3483,11 +3486,11 @@ class AetherSettingsView(PanelManagerView):
|
||||
group_h = max(section_h, right_h)
|
||||
|
||||
draw_section_header(
|
||||
rl.Rectangle(rect.x, y, col_w, SECTION_HEADER_HEIGHT),
|
||||
rl.Rectangle(rect.x + SPACING.xl, y, col_w - SPACING.xl * 2, SECTION_HEADER_HEIGHT),
|
||||
tr(section.title), style=self._panel_style,
|
||||
)
|
||||
draw_section_header(
|
||||
rl.Rectangle(rect.x + col_w + self.COLUMN_GAP, y, col_w, SECTION_HEADER_HEIGHT),
|
||||
rl.Rectangle(rect.x + col_w + self.COLUMN_GAP + SPACING.xl, y, col_w - SPACING.xl * 2, SECTION_HEADER_HEIGHT),
|
||||
tr(right_section.title), style=self._panel_style,
|
||||
)
|
||||
y += SECTION_HEADER_HEIGHT + SECTION_HEADER_GAP
|
||||
@@ -3514,7 +3517,7 @@ class AetherSettingsView(PanelManagerView):
|
||||
section: SettingSection, rows: list[SettingRow]) -> float:
|
||||
if section.title:
|
||||
draw_section_header(
|
||||
rl.Rectangle(x, y, width, SECTION_HEADER_HEIGHT),
|
||||
rl.Rectangle(x + SPACING.xl, y, width - SPACING.xl * 2, SECTION_HEADER_HEIGHT),
|
||||
tr(section.title),
|
||||
style=self._panel_style,
|
||||
)
|
||||
@@ -3555,7 +3558,6 @@ class AetherSettingsView(PanelManagerView):
|
||||
pressed=pressed,
|
||||
is_last=is_last,
|
||||
show_chevron=row.on_click is not None,
|
||||
title_size=36, subtitle_size=26, value_size=30,
|
||||
style=self._panel_style,
|
||||
)
|
||||
elif row.type == "action":
|
||||
@@ -3571,7 +3573,7 @@ class AetherSettingsView(PanelManagerView):
|
||||
pressed=pressed,
|
||||
is_last=is_last,
|
||||
action_pill=True,
|
||||
title_size=36, subtitle_size=26,
|
||||
title_size=SETTINGS_ROW_TITLE_FONT_SIZE, subtitle_size=SETTINGS_ROW_SUBTITLE_FONT_SIZE,
|
||||
action_pill_height=AETHER_LIST_METRICS.toggle_height, action_text_size=26,
|
||||
action_text_color=action_text_color,
|
||||
action_fill=action_fill,
|
||||
|
||||
@@ -26,7 +26,7 @@ from openpilot.starpilot.assets.model_manager import (
|
||||
set_model_profile,
|
||||
)
|
||||
from openpilot.starpilot.common.starpilot_variables import MODELS_PATH, update_starpilot_toggles
|
||||
from openpilot.system.ui.lib.application import FontWeight, MouseEvent, MousePos, gui_app
|
||||
from openpilot.system.ui.lib.application import FONT_SCALE, FontWeight, MouseEvent, MousePos, gui_app
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
from openpilot.system.ui.lib.scroll_panel2 import GuiScrollPanel2
|
||||
from openpilot.system.ui.widgets import DialogResult, Widget
|
||||
@@ -63,6 +63,9 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
|
||||
SECTION_HEADER_HEIGHT,
|
||||
SECTION_HEADER_GAP,
|
||||
ROW_HEIGHT,
|
||||
SETTINGS_ROW_TITLE_FONT_SIZE,
|
||||
SETTINGS_ROW_SUBTITLE_FONT_SIZE,
|
||||
SPACING,
|
||||
)
|
||||
ROW_RADIUS = AETHER_LIST_METRICS.row_radius
|
||||
ACTION_WIDTH = AETHER_LIST_METRICS.action_width
|
||||
@@ -74,10 +77,10 @@ TRANSITION_SECONDS = 0.24
|
||||
PANEL_STYLE = DEFAULT_PANEL_STYLE
|
||||
BANNER_HEIGHT = 128.0
|
||||
BANNER_GAP = 14.0
|
||||
HEADER_BUTTON_HEIGHT = 80.0
|
||||
HEADER_BUTTON_HEIGHT = float(ROW_HEIGHT)
|
||||
HEADER_BUTTON_GAP_Y = 14.0
|
||||
MANAGEMENT_STRIP_HEIGHT = 64.0
|
||||
MANAGEMENT_PILL_HEIGHT = 44.0
|
||||
MANAGEMENT_STRIP_HEIGHT = float(ROW_HEIGHT)
|
||||
MANAGEMENT_PILL_HEIGHT = float(AETHER_LIST_METRICS.toggle_height)
|
||||
EMPTY_STATE_HEIGHT = 240.0
|
||||
_SORT_MODES = ("alphabetical", "date", "date_oldest", "favorites", "community_picks")
|
||||
_SORT_LABELS = {
|
||||
@@ -136,6 +139,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
lambda: self._controller.cancel_active_download() if self._controller._is_download_active() else self._controller.download_all_missing(),
|
||||
enabled=lambda: self._controller.primary_header_button_state()[1],
|
||||
emphasized=True,
|
||||
font_size=SETTINGS_ROW_TITLE_FONT_SIZE,
|
||||
accent_color=rl.Color(139, 92, 246, 92),
|
||||
)
|
||||
)
|
||||
@@ -145,6 +149,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
self._controller.refresh_manifest,
|
||||
enabled=lambda: self._controller.secondary_header_button_state()[1],
|
||||
emphasized=False,
|
||||
font_size=SETTINGS_ROW_TITLE_FONT_SIZE,
|
||||
)
|
||||
)
|
||||
self._random_model_button = self._child(
|
||||
@@ -152,7 +157,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
lambda: self._controller.random_model_button_label(),
|
||||
self._controller.toggle_model_randomizer,
|
||||
emphasized=False,
|
||||
font_size=28,
|
||||
font_size=SETTINGS_ROW_TITLE_FONT_SIZE,
|
||||
)
|
||||
)
|
||||
self._primary_header_button.set_touch_valid_callback(lambda: self._scroll_panel.is_touch_valid())
|
||||
@@ -212,12 +217,11 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
for prefix in ("menu:", "action:", "row:"):
|
||||
for target_id, rect in self._interactive_rects.items():
|
||||
if target_id.startswith(prefix):
|
||||
pad_y = 6 if prefix == "menu:" else 0
|
||||
if point_hits(mouse_pos, rect, self._scroll_rect, pad_x=6, pad_y=pad_y):
|
||||
if point_hits(mouse_pos, rect, self._scroll_rect, pad_x=0, pad_y=0):
|
||||
return target_id
|
||||
for target_id, rect in self._interactive_rects.items():
|
||||
if target_id.startswith("sortopt:") or target_id.startswith("mgmt:"):
|
||||
if point_hits(mouse_pos, rect, self._shell_rect, pad_x=6, pad_y=6):
|
||||
if point_hits(mouse_pos, rect, self._shell_rect, pad_x=0, pad_y=0):
|
||||
return target_id
|
||||
return None
|
||||
|
||||
@@ -365,7 +369,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
pill_h = MANAGEMENT_PILL_HEIGHT
|
||||
pill_y = y + (MANAGEMENT_STRIP_HEIGHT - pill_h) / 2
|
||||
left = x + 16
|
||||
gap = 8.0
|
||||
gap = float(SPACING.lg)
|
||||
usable = width - 32.0
|
||||
|
||||
if randomizer_on:
|
||||
@@ -377,14 +381,14 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
draw_action_pill(bl_pill, bl_label,
|
||||
with_alpha(AetherListColors.PRIMARY, 18),
|
||||
with_alpha(AetherListColors.PRIMARY, 50),
|
||||
AetherListColors.HEADER, font_size=28, roundness=0.35)
|
||||
self._interactive_rects["mgmt:blacklist"] = bl_pill
|
||||
AetherListColors.HEADER, font_size=30, roundness=0.35)
|
||||
self._interactive_rects["mgmt:blacklist"] = rl.Rectangle(bl_pill.x, y, bl_w, MANAGEMENT_STRIP_HEIGHT)
|
||||
rt_pill = rl.Rectangle(left + bl_w + gap, pill_y, rt_w, pill_h)
|
||||
draw_action_pill(rt_pill, tr("Ratings"),
|
||||
with_alpha(AetherListColors.PRIMARY, 18),
|
||||
with_alpha(AetherListColors.PRIMARY, 50),
|
||||
AetherListColors.HEADER, font_size=28, roundness=0.35)
|
||||
self._interactive_rects["mgmt:ratings"] = rt_pill
|
||||
AetherListColors.HEADER, font_size=30, roundness=0.35)
|
||||
self._interactive_rects["mgmt:ratings"] = rl.Rectangle(rt_pill.x, y, rt_w, MANAGEMENT_STRIP_HEIGHT)
|
||||
return
|
||||
|
||||
sort_mode = self._controller._get_sort_mode()
|
||||
@@ -410,8 +414,8 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
else:
|
||||
fill = rl.Color(255, 255, 255, 8)
|
||||
border = with_alpha(AetherListColors.PRIMARY, 80) if is_active else rl.Color(255, 255, 255, 24)
|
||||
draw_action_pill(seg_rect, label, fill, border, AetherListColors.HEADER, font_size=28, roundness=0.3)
|
||||
self._interactive_rects[f"sortopt:{mode}"] = seg_rect
|
||||
draw_action_pill(seg_rect, label, fill, border, AetherListColors.HEADER, font_size=30, roundness=0.3)
|
||||
self._interactive_rects[f"sortopt:{mode}"] = rl.Rectangle(seg_x, y, seg_w, MANAGEMENT_STRIP_HEIGHT)
|
||||
|
||||
def _get_sections(self) -> list[tuple[str, list[ModelCatalogEntry]]]:
|
||||
sort_mode = self._controller._get_sort_mode()
|
||||
@@ -479,7 +483,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
)
|
||||
|
||||
def _draw_model_section(self, x: float, y: float, width: float, title: str, entries: list[ModelCatalogEntry]) -> float:
|
||||
draw_section_header(rl.Rectangle(x, y, width, SECTION_HEADER_HEIGHT), title, style=PANEL_STYLE)
|
||||
draw_section_header(rl.Rectangle(x + SPACING.xl, y, width - SPACING.xl * 2, SECTION_HEADER_HEIGHT), title, style=PANEL_STYLE)
|
||||
y += SECTION_HEADER_HEIGHT + SECTION_HEADER_GAP
|
||||
|
||||
group_rect = rl.Rectangle(x, y, width, len(entries) * ROW_HEIGHT)
|
||||
@@ -522,12 +526,16 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
separator_inset=22,
|
||||
)
|
||||
|
||||
action_rect = draw_action_rail(draw_rect, ACTION_WIDTH, current=current, alpha=alpha, fill=AetherListColors.ACTION_BG, separator=AetherListColors.ACTION_SEPARATOR, inset_y=18)
|
||||
action_width = ACTION_WIDTH * 2 + SPACING.lg if is_menu_open else ACTION_WIDTH
|
||||
action_rect = draw_action_rail(
|
||||
draw_rect, action_width, current=current, alpha=alpha,
|
||||
fill=AetherListColors.ACTION_BG, separator=AetherListColors.ACTION_SEPARATOR, inset_y=18,
|
||||
)
|
||||
|
||||
info_rect = rl.Rectangle(draw_rect.x + 24, draw_rect.y + 18, draw_rect.width - ACTION_WIDTH - 42, draw_rect.height - 36)
|
||||
info_rect = rl.Rectangle(draw_rect.x + 24, draw_rect.y + 18, draw_rect.width - action_width - 42, draw_rect.height - 36)
|
||||
row_touchable = entry.installed and not self._controller._params.get_bool("ModelRandomizer")
|
||||
if row_touchable:
|
||||
self._interactive_rects[f"row:{entry.key}"] = draw_rect
|
||||
self._interactive_rects[f"row:{entry.key}"] = rl.Rectangle(draw_rect.x, draw_rect.y, draw_rect.width - action_width, draw_rect.height)
|
||||
|
||||
self._draw_model_info(info_rect, entry, current)
|
||||
|
||||
@@ -538,7 +546,8 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
elif not removable:
|
||||
self._draw_protected_action(action_rect)
|
||||
else:
|
||||
self._interactive_rects[f"action:{entry.key}"] = action_rect
|
||||
if not is_menu_open:
|
||||
self._interactive_rects[f"action:{entry.key}"] = action_rect
|
||||
self._draw_menu_action(action_rect, is_menu_open, entry)
|
||||
else:
|
||||
self._interactive_rects[f"action:{entry.key}"] = action_rect
|
||||
@@ -548,20 +557,20 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
self._draw_download_action(action_rect)
|
||||
|
||||
def _draw_model_info(self, rect: rl.Rectangle, entry: ModelCatalogEntry, current: bool):
|
||||
title_size = 36
|
||||
meta_size = 26
|
||||
title_size = SETTINGS_ROW_TITLE_FONT_SIZE
|
||||
meta_size = SETTINGS_ROW_SUBTITLE_FONT_SIZE
|
||||
inter_gap = 6
|
||||
total_h = title_size + meta_size + inter_gap
|
||||
total_h = (title_size + meta_size) * FONT_SCALE + inter_gap
|
||||
start_y = rect.y + (rect.height - total_h) / 2
|
||||
|
||||
heart_offset = 0
|
||||
if entry.user_favorite:
|
||||
heart_color = rl.Color(210, 100, 130, 230)
|
||||
heart_center = rl.Vector2(rect.x + 14, start_y + title_size / 2)
|
||||
heart_center = rl.Vector2(rect.x + 14, start_y + title_size * FONT_SCALE / 2)
|
||||
draw_heart_icon(heart_center, heart_color)
|
||||
heart_offset = 36
|
||||
|
||||
title_rect = rl.Rectangle(rect.x + heart_offset, start_y, rect.width - heart_offset, title_size)
|
||||
title_rect = rl.Rectangle(rect.x + heart_offset, start_y, rect.width - heart_offset, title_size * FONT_SCALE)
|
||||
gui_label(title_rect, entry.name, title_size, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
|
||||
|
||||
meta_parts: list[str] = []
|
||||
@@ -585,7 +594,7 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
meta_parts.append(tr("Popular"))
|
||||
|
||||
if meta_parts:
|
||||
meta_rect = rl.Rectangle(rect.x, start_y + title_size + inter_gap, rect.width, meta_size)
|
||||
meta_rect = rl.Rectangle(rect.x, start_y + title_size * FONT_SCALE + inter_gap, rect.width, meta_size * FONT_SCALE)
|
||||
has_warning = entry.partial or entry.requires_external_gpu
|
||||
text_color = AetherListColors.WARNING if has_warning else AetherListColors.SUBTEXT
|
||||
gui_label(meta_rect, " • ".join(meta_parts), meta_size, text_color, FontWeight.NORMAL if not has_warning else FontWeight.MEDIUM)
|
||||
@@ -632,33 +641,31 @@ class DrivingModelManagerView(AetherInteractiveMixin, Widget):
|
||||
alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER,
|
||||
)
|
||||
else:
|
||||
btn_h = 48
|
||||
gap = 8
|
||||
total_h = btn_h * 2 + gap
|
||||
start_y = rect.y + (rect.height - total_h) / 2
|
||||
btn_w = rect.width - 28
|
||||
btn_h = AETHER_LIST_METRICS.header_button_height
|
||||
gap = SPACING.lg
|
||||
start_y = rect.y + (rect.height - btn_h) / 2
|
||||
btn_w = (rect.width - SPACING.md * 2 - gap) / 2
|
||||
|
||||
delete_rect = rl.Rectangle(rect.x + 14, start_y, btn_w, btn_h)
|
||||
fav_rect = rl.Rectangle(rect.x + 14, start_y + btn_h + gap, btn_w, btn_h)
|
||||
delete_rect = rl.Rectangle(rect.x + SPACING.md, start_y, btn_w, btn_h)
|
||||
fav_rect = rl.Rectangle(delete_rect.x + btn_w + gap, start_y, btn_w, btn_h)
|
||||
|
||||
self._interactive_rects[f"menu:{entry.key}:delete"] = delete_rect
|
||||
self._interactive_rects[f"menu:{entry.key}:favorite"] = fav_rect
|
||||
self._interactive_rects[f"menu:{entry.key}:delete"] = rl.Rectangle(delete_rect.x, rect.y, btn_w, rect.height)
|
||||
self._interactive_rects[f"menu:{entry.key}:favorite"] = rl.Rectangle(fav_rect.x, rect.y, btn_w, rect.height)
|
||||
|
||||
draw_action_pill(
|
||||
delete_rect,
|
||||
tr("Delete"),
|
||||
AetherListColors.DANGER_SOFT,
|
||||
rl.Color(AetherListColors.DANGER.r, AetherListColors.DANGER.g, AetherListColors.DANGER.b, min(AetherListColors.DANGER.a, 70)),
|
||||
AetherListColors.DANGER,
|
||||
font_size=24,
|
||||
AetherListColors.HEADER,
|
||||
font_size=32,
|
||||
)
|
||||
|
||||
is_fav = entry.user_favorite
|
||||
fav_fill = rl.Color(210, 100, 130, 44) if is_fav else rl.Color(PANEL_STYLE.accent.r, PANEL_STYLE.accent.g, PANEL_STYLE.accent.b, 26)
|
||||
fav_border = rl.Color((210 if is_fav else PANEL_STYLE.accent.r), (100 if is_fav else PANEL_STYLE.accent.g), (130 if is_fav else PANEL_STYLE.accent.b), min((255 if is_fav else PANEL_STYLE.accent.a), 70))
|
||||
fav_text_color = rl.Color(210, 100, 130, 255) if is_fav else PANEL_STYLE.accent
|
||||
fav_label = tr("Unfavorite") if is_fav else tr("Favorite")
|
||||
draw_action_pill(fav_rect, fav_label, fav_fill, fav_border, fav_text_color, font_size=24)
|
||||
draw_action_pill(fav_rect, fav_label, fav_fill, fav_border, AetherListColors.HEADER, font_size=32)
|
||||
|
||||
def _draw_current_action(self, rect: rl.Rectangle):
|
||||
chip_h = 52
|
||||
|
||||
@@ -204,8 +204,7 @@ class StarPilotLateralLayout(_SettingsPage):
|
||||
),
|
||||
SettingRow(
|
||||
"LaneChangeCloseGap", "toggle", tr_noop("Close Gap On Lane Change"),
|
||||
subtitle=tr_noop("Allows for a temporary shorter follow distance behind lead so that openpilot merges smoothly " +
|
||||
"out of current lane, it will allow car to accelerate as it changes lanes."),
|
||||
subtitle=tr_noop("Temporarily shorten the following gap and allow acceleration while changing lanes."),
|
||||
get_state=lambda: p.get_bool("LaneChangeCloseGap"),
|
||||
set_state=lambda s: p.put_bool("LaneChangeCloseGap", s),
|
||||
visible=lc_on,
|
||||
|
||||
Reference in New Issue
Block a user