BigUI WIP: Lil scrolling cleanup

This commit is contained in:
firestarsdog
2026-06-16 03:42:22 -04:00
parent 624f51aef4
commit da305d9da3
5 changed files with 97 additions and 59 deletions
@@ -507,6 +507,10 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
def _draw_scroll_content(self, scroll_rect: rl.Rectangle, content_width: float) -> None:
"""Override to render visible content rows inside the scissor region."""
@property
def vertical_scrolling_disabled(self) -> bool:
return False
# ── render pipeline ───────────────────────────────────────
def _render(self, rect: rl.Rectangle) -> None:
@@ -521,8 +525,15 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
self._content_height = self._measure_content_height(content_width)
self._scroll_panel.set_enabled(self.is_visible)
scroll_disabled = self.vertical_scrolling_disabled
effective_height = scroll_rect.height if scroll_disabled else self._content_height
self._scroll_offset = self._scroll_panel.update(
scroll_rect, max(self._content_height, scroll_rect.height))
scroll_rect, max(effective_height, scroll_rect.height))
if scroll_disabled:
self._scroll_offset = 0.0
rl.begin_scissor_mode(
int(scroll_rect.x), int(scroll_rect.y),
@@ -530,12 +541,12 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
self._draw_scroll_content(scroll_rect, content_width)
rl.end_scissor_mode()
if self._content_height > scroll_rect.height:
if self._content_height > scroll_rect.height and not scroll_disabled:
self._scrollbar.render(scroll_rect, self._content_height, self._scroll_offset)
draw_list_scroll_fades(scroll_rect, self._content_height, self._scroll_offset,
AetherListColors.PANEL_BG)
self._draw_page_dots(frame.scroll)
if not scroll_disabled:
draw_list_scroll_fades(scroll_rect, self._content_height, self._scroll_offset,
AetherListColors.PANEL_BG)
# ── shared layout helpers ─────────────────────────────────
@@ -613,6 +624,12 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
def _has_pagination(self) -> bool:
return self._page_count > 1
def measure_page_grid_height(self, grid: TileGrid, width: float) -> float:
h = grid.measure_height(width)
if self._has_pagination:
h += 32
return h
def register_page_grid(self, grid: TileGrid) -> None:
self._page_grid = grid
if grid not in self._children:
@@ -671,59 +688,61 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
self._page_anim_from = from_offset
def _render_page_grid(self, grid: TileGrid, rect: rl.Rectangle, clip_rect: rl.Rectangle | None = None) -> None:
pagination_padding = 32.0 if self._has_pagination else 0.0
if clip_rect is None:
clip_rect = rl.Rectangle(rect.x - self.GRID_PADDING, rect.y - self.GRID_PADDING,
rect.width + self.GRID_PADDING * 2, rect.height + self.GRID_PADDING * 2)
self._page_clip_rect = clip_rect
grid_rect = rl.Rectangle(rect.x, rect.y, rect.width, max(0.0, rect.height - pagination_padding))
# active drag
if self._page_drag_active:
drag_off = self._page_drag_offset
self._page_scissor_push(clip_rect)
grid.render(rl.Rectangle(rect.x + drag_off, rect.y, rect.width, rect.height))
grid.render(rl.Rectangle(grid_rect.x + drag_off, grid_rect.y, grid_rect.width, grid_rect.height))
self._page_scissor_pop()
return
# no animation
if not self._page_animating:
elif not self._page_animating:
# no animation
grid.set_parent_rect(self._scroll_rect)
grid.render(rect)
return
# animation
elapsed = time.monotonic() - self._page_anim_start
duration = self.PAGE_ANIM_DURATION if self._page_anim_committed else self.PAGE_SNAP_DURATION
if elapsed >= duration:
self._page_animating = False
self._page_anim_prev_tiles.clear()
grid.set_parent_rect(self._scroll_rect)
grid.render(rect)
return
t = elapsed / duration
t = 1.0 - (1.0 - t) ** 3
if self._page_anim_committed:
direction = 1 if self._page_anim_from < 0 else -1
old_target = -direction * rect.width
prev_offset = self._page_anim_from + (old_target - self._page_anim_from) * t
cur_offset = direction * rect.width + (0.0 - direction * rect.width) * t
self._page_scissor_push(clip_rect)
if self._page_anim_prev_tiles:
old_grid = TileGrid(columns=grid.get_column_count(), padding=grid.gap, tile_height=grid._tile_height)
old_grid.tiles.extend(self._page_anim_prev_tiles)
old_grid.set_parent_rect(self._scroll_rect)
old_grid.render(rl.Rectangle(rect.x + prev_offset, rect.y, rect.width, rect.height))
grid.set_parent_rect(self._scroll_rect)
grid.render(rl.Rectangle(rect.x + cur_offset, rect.y, rect.width, rect.height))
self._page_scissor_pop()
grid.render(grid_rect)
else:
cur_offset = self._page_anim_from * (1.0 - t)
self._page_scissor_push(clip_rect)
grid.set_parent_rect(self._scroll_rect)
grid.render(rl.Rectangle(rect.x + cur_offset, rect.y, rect.width, rect.height))
self._page_scissor_pop()
# animation
elapsed = time.monotonic() - self._page_anim_start
duration = self.PAGE_ANIM_DURATION if self._page_anim_committed else self.PAGE_SNAP_DURATION
if elapsed >= duration:
self._page_animating = False
self._page_anim_prev_tiles.clear()
grid.set_parent_rect(self._scroll_rect)
grid.render(grid_rect)
else:
t = elapsed / duration
t = 1.0 - (1.0 - t) ** 3
if self._page_anim_committed:
direction = 1 if self._page_anim_from < 0 else -1
old_target = -direction * rect.width
prev_offset = self._page_anim_from + (old_target - self._page_anim_from) * t
cur_offset = direction * rect.width + (0.0 - direction * rect.width) * t
self._page_scissor_push(clip_rect)
if self._page_anim_prev_tiles:
old_grid = TileGrid(columns=grid.get_column_count(), padding=grid.gap, tile_height=grid._tile_height)
old_grid.tiles.extend(self._page_anim_prev_tiles)
old_grid.set_parent_rect(self._scroll_rect)
old_grid.render(rl.Rectangle(grid_rect.x + prev_offset, grid_rect.y, grid_rect.width, grid_rect.height))
grid.set_parent_rect(self._scroll_rect)
grid.render(rl.Rectangle(grid_rect.x + cur_offset, grid_rect.y, grid_rect.width, grid_rect.height))
self._page_scissor_pop()
else:
cur_offset = self._page_anim_from * (1.0 - t)
self._page_scissor_push(clip_rect)
grid.set_parent_rect(self._scroll_rect)
grid.render(rl.Rectangle(grid_rect.x + cur_offset, grid_rect.y, grid_rect.width, grid_rect.height))
self._page_scissor_pop()
self._draw_page_dots(rect)
# ── mouse handling ─────────────────────────────────────────
@@ -785,11 +804,10 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
def _draw_page_dots(self, rect: rl.Rectangle) -> None:
if not self._has_pagination:
return
clip = self._page_clip_rect
n = min(self._page_count, 8)
total_w = n * self.PAGE_DOT_RADIUS * 2 + max(0, n - 1) * self.PAGE_DOT_GAP
start_x = (clip.x + (clip.width - total_w) / 2) if clip else rect.x + (rect.width - total_w) / 2
dot_y = rect.y + rect.height + 8
start_x = rect.x + (rect.width - total_w) / 2
dot_y = rect.y + rect.height - 12
for i in range(n):
cx = start_x + i * (self.PAGE_DOT_RADIUS * 2 + self.PAGE_DOT_GAP) + self.PAGE_DOT_RADIUS
fill = self.PANEL_STYLE.accent if i == self._current_page else _with_alpha(AetherListColors.MUTED, 100)
@@ -2339,19 +2357,27 @@ class AetherSettingsView(PanelManagerView):
self._content_height = self._measure_content_height(content_width)
self._scroll_panel.set_enabled(self.is_visible)
scroll_disabled = getattr(self, "vertical_scrolling_disabled", False)
effective_height = self._scroll_rect.height if scroll_disabled else self._content_height
self._scroll_offset = self._scroll_panel.update(
self._scroll_rect, max(self._content_height, self._scroll_rect.height))
self._scroll_rect, max(effective_height, self._scroll_rect.height))
if scroll_disabled:
self._scroll_offset = 0.0
rl.begin_scissor_mode(int(self._scroll_rect.x), int(self._scroll_rect.y),
int(self._scroll_rect.width), int(self._scroll_rect.height))
self._draw_scroll_content(self._scroll_rect, content_width)
rl.end_scissor_mode()
if self._content_height > self._scroll_rect.height:
if self._content_height > self._scroll_rect.height and not scroll_disabled:
self._scrollbar.render(self._scroll_rect, self._content_height, self._scroll_offset)
draw_list_scroll_fades(self._scroll_rect, self._content_height, self._scroll_offset,
AetherListColors.PANEL_BG, fade_height=self._fade_height)
if not scroll_disabled:
draw_list_scroll_fades(self._scroll_rect, self._content_height, self._scroll_offset,
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 ""
@@ -67,6 +67,10 @@ def _theme_display_name(value: str) -> str:
# ═══════════════════════════════════════════════════════════════
class AppearanceManagerView(AetherSettingsView):
@property
def vertical_scrolling_disabled(self) -> bool:
return self._active_tab_key == "widgets"
def __init__(self, controller, sections, **kwargs):
super().__init__(controller, sections, **kwargs)
self._toggle_grid = TileGrid(columns=2, padding=12)
@@ -252,7 +256,7 @@ class AppearanceManagerView(AetherSettingsView):
section_overhead = self._metrics.section_header_height + self._metrics.section_header_gap
left_column_total_h = left_h + section_overhead
tiles_content_h = self._toggle_grid.measure_height(col_width - 24)
tiles_content_h = self.measure_page_grid_height(self._toggle_grid, col_width - 24)
right_column_total_h = tiles_content_h + 24 + section_overhead
tab_h = self.TAB_HEIGHT + self.TAB_BOTTOM_GAP if self._tab_defs else 0
@@ -310,7 +314,7 @@ class AppearanceManagerView(AetherSettingsView):
tr("Widgets"), style=self._panel_style
)
y += self._metrics.section_header_height + self._metrics.section_header_gap
tiles_content_h = self._toggle_grid.measure_height(width - 24)
tiles_content_h = self.measure_page_grid_height(self._toggle_grid, width - 24)
draw_list_group_shell(rl.Rectangle(rect.x, y, width, tiles_content_h + 24), style=self._panel_style)
self._render_page_grid(self._toggle_grid, rl.Rectangle(rect.x + 12, y + 12, width - 24, tiles_content_h))
@@ -53,6 +53,10 @@ SOUNDS_PANEL_METRICS = replace(
class SoundsManagerView(PanelManagerView):
METRICS = SOUNDS_PANEL_METRICS
@property
def vertical_scrolling_disabled(self) -> bool:
return True
def __init__(self, controller: StarPilotSoundsLayout):
super().__init__()
self._controller = controller
@@ -110,6 +110,10 @@ class SystemSettingsManagerView(PanelManagerView):
DANGER_PILL_WIDTH = 112
METRICS = SYSTEM_PANEL_METRICS
@property
def vertical_scrolling_disabled(self) -> bool:
return True
def __init__(self, controller: StarPilotSystemLayout):
super().__init__()
self._controller = controller
@@ -478,7 +482,7 @@ class SystemSettingsManagerView(PanelManagerView):
left_h = display_container_h + power_container_h + header_overhead + section_gap
return self._compute_two_column_height(left_h)
else:
tiles_content_h = self._connectivity_tile_grid.measure_height(width - 24)
tiles_content_h = self.measure_page_grid_height(self._connectivity_tile_grid, width - 24)
return self._stacked_section_height([display_h, power_h, tiles_content_h + 24])
def _slider_section_height(self, keys: list[str], width: float) -> float:
@@ -519,7 +523,7 @@ class SystemSettingsManagerView(PanelManagerView):
self._draw_connectivity_tiles_section(y, x, width)
def _draw_connectivity_tiles_section(self, y: float, x: float, width: float):
tiles_content_h = self._connectivity_tile_grid.measure_height(width - 24)
tiles_content_h = self.measure_page_grid_height(self._connectivity_tile_grid, width - 24)
draw_list_group_shell(rl.Rectangle(x, y, width, tiles_content_h + 24), style=PANEL_STYLE)
self._render_page_grid(self._connectivity_tile_grid, rl.Rectangle(x + 12, y + 12, width - 24, tiles_content_h))
@@ -328,7 +328,7 @@ class VehicleSettingsManagerView(PanelManagerView):
if not self._uses_two_columns(width):
self._toggle_grid._columns = 3
avail_w = width - 24
tiles_content_h = self._toggle_grid.measure_height(avail_w)
tiles_content_h = self.measure_page_grid_height(self._toggle_grid, avail_w)
tiles_height = SECTION_GAP + self._section_block_height(tiles_content_h + 24)
if self._uses_two_columns(width):
@@ -420,7 +420,7 @@ class VehicleSettingsManagerView(PanelManagerView):
self._toggle_grid._columns = 3
avail_w = width - 24
tiles_content_h = self._toggle_grid.measure_height(avail_w)
tiles_content_h = self.measure_page_grid_height(self._toggle_grid, avail_w)
draw_list_group_shell(rl.Rectangle(x, y, width, tiles_content_h + 24), style=PANEL_STYLE)
self._render_page_grid(self._toggle_grid, rl.Rectangle(x + 12, y + 12, avail_w, tiles_content_h))