mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-30 19:33:45 +08:00
Favorite menu cleanup
This commit is contained in:
@@ -70,11 +70,13 @@ class FavoriteRadialMenu:
|
||||
|
||||
def __init__(self, params: Any, params_memory: Any,
|
||||
option_provider: Callable[[], Iterable[dict[str, Any]]], *,
|
||||
clock: Callable[[], float] = time.monotonic):
|
||||
clock: Callable[[], float] = time.monotonic,
|
||||
cache_render_texture: Callable[..., Any] | None = None):
|
||||
self._params = params
|
||||
self._params_memory = params_memory
|
||||
self._option_provider = option_provider
|
||||
self._clock = clock
|
||||
self._cache_render_texture = cache_render_texture
|
||||
|
||||
self._state = self.STATE_COLLAPSED
|
||||
self._selected_slot: int | None = None
|
||||
@@ -723,11 +725,48 @@ class FavoriteRadialMenu:
|
||||
x0 = self._rect.x
|
||||
y0 = self._rect.y + self._rect.height
|
||||
is_pressed = self._corner_press is not None
|
||||
|
||||
size = 150.0 * scale
|
||||
texture_size = max(1, int(round(size)))
|
||||
texture_scale = texture_size / 150.0
|
||||
# Cache the hint's two appearances instead of rebuilding the mesh every frame.
|
||||
cache = self._cache_render_texture
|
||||
texture = None
|
||||
if cache is not None:
|
||||
variant = "pressed" if is_pressed else "idle"
|
||||
texture = cache(
|
||||
f"favorite-corner-hint:{texture_size}:{variant}",
|
||||
texture_size,
|
||||
texture_size,
|
||||
lambda: FavoriteRadialMenu._draw_corner_hint_geometry(
|
||||
texture_scale, is_pressed, 0.0, float(texture_size),
|
||||
),
|
||||
)
|
||||
|
||||
if texture is not None:
|
||||
rl.begin_blend_mode(rl.BlendMode.BLEND_ALPHA_PREMULTIPLY)
|
||||
try:
|
||||
rl.draw_texture_pro(
|
||||
texture,
|
||||
rl.Rectangle(0, 0, texture_size, -texture_size),
|
||||
rl.Rectangle(x0, y0 - size, size, size),
|
||||
rl.Vector2(0, 0),
|
||||
0.0,
|
||||
rl.WHITE,
|
||||
)
|
||||
finally:
|
||||
rl.end_blend_mode()
|
||||
return
|
||||
|
||||
self._draw_corner_hint_geometry(scale, is_pressed, x0, y0)
|
||||
|
||||
@classmethod
|
||||
def _draw_corner_hint_geometry(cls, scale: float, is_pressed: bool,
|
||||
x0: float, y0: float) -> None:
|
||||
size = 150.0 * scale
|
||||
|
||||
steps = 48
|
||||
|
||||
# 1. Precompute edge vertices to minimize per-frame allocations
|
||||
# Build the gradient mesh once for this cached appearance.
|
||||
v_origin = rl.Vector2(x0, y0)
|
||||
inv_steps = 1.0 / steps
|
||||
pts_top = [rl.Vector2(x0, y0 - size * (k * inv_steps)) for k in range(steps + 1)]
|
||||
@@ -747,7 +786,7 @@ class FavoriteRadialMenu:
|
||||
purple_a = int(purple_max_alpha * ((1.0 - t_mid) ** 1.75))
|
||||
|
||||
for col in (rl.Color(8, 6, 18, base_a) if base_a > 0 else None,
|
||||
self._sample_aether_color(t_mid, purple_a) if purple_a > 0 else None):
|
||||
cls._sample_aether_color(t_mid, purple_a) if purple_a > 0 else None):
|
||||
if col is None:
|
||||
continue
|
||||
if i == 0:
|
||||
@@ -757,8 +796,8 @@ class FavoriteRadialMenu:
|
||||
rl.draw_triangle(v_tb, v_ra, v_rb, col)
|
||||
|
||||
# 3. Ultra-Polished Frosted-Glass Vector Arrow (Nestled deep in purple corner)
|
||||
center = self.corner_center(self._rect)
|
||||
cx, cy = center.x, center.y
|
||||
inset = (cls.CORNER_HINT_RING_RADIUS + cls.CORNER_HINT_EDGE_MARGIN) * scale
|
||||
cx, cy = x0 + inset, y0 - inset
|
||||
|
||||
tip = rl.Vector2(cx + 15.0 * scale, cy - 15.0 * scale)
|
||||
tail = rl.Vector2(cx - 15.0 * scale, cy + 15.0 * scale)
|
||||
|
||||
@@ -52,6 +52,7 @@ class StarPilotOnroadView(AugmentedRoadView):
|
||||
ui_state.ui_params,
|
||||
ui_state.params_memory,
|
||||
self._favorite_slot_options,
|
||||
cache_render_texture=gui_app.cached_render_texture,
|
||||
)
|
||||
self._favorite_input_consumed = False
|
||||
|
||||
|
||||
@@ -77,14 +77,15 @@ def _open_picker(menu, rect, slot_index=0):
|
||||
assert menu.state == FavoriteRadialMenu.STATE_PICKER
|
||||
|
||||
|
||||
def _menu(clock, options=None):
|
||||
def _menu(clock, options=None, cache_render_texture=None):
|
||||
params = FakeParams()
|
||||
memory = FakeParams()
|
||||
options = options or [
|
||||
{"key": "FeatureToggle", "label": "Feature Toggle", "description": "The primary test setting.", "section": "Testing"},
|
||||
{"key": "OtherToggle", "label": "Other Toggle", "description": "Another test setting.", "section": "Testing"},
|
||||
]
|
||||
return FavoriteRadialMenu(params, memory, lambda: options, clock=lambda: clock[0]), params, memory
|
||||
return FavoriteRadialMenu(params, memory, lambda: options, clock=lambda: clock[0],
|
||||
cache_render_texture=cache_render_texture), params, memory
|
||||
|
||||
|
||||
def test_radial_menu_opens_from_corner_tap_and_arranges_three_slots_on_an_arc():
|
||||
@@ -116,6 +117,50 @@ def test_corner_hint_keeps_visible_ring_near_content_corner():
|
||||
assert menu._contains(menu._corner_touch_zone_for(rect), center)
|
||||
|
||||
|
||||
def test_corner_hint_caches_idle_and_pressed_art(monkeypatch):
|
||||
clock = [0.0]
|
||||
cached = {}
|
||||
requests = []
|
||||
geometry = []
|
||||
draws = []
|
||||
blend_modes = []
|
||||
|
||||
def cache(key, width, height, render):
|
||||
requests.append((key, width, height, render))
|
||||
return cached.get(key)
|
||||
|
||||
menu, _params, _memory = _menu(clock, cache_render_texture=cache)
|
||||
menu._rect = rl.Rectangle(0, 0, 2160, 1080)
|
||||
monkeypatch.setattr(FavoriteRadialMenu, "_draw_corner_hint_geometry",
|
||||
staticmethod(lambda *args: geometry.append(args)))
|
||||
monkeypatch.setattr(rl, "draw_texture_pro", lambda *args: draws.append(args))
|
||||
monkeypatch.setattr(rl, "begin_blend_mode", blend_modes.append)
|
||||
monkeypatch.setattr(rl, "end_blend_mode", lambda: None)
|
||||
|
||||
menu._draw_corner_hint()
|
||||
idle_key, width, height, render_idle = requests[-1]
|
||||
assert idle_key == "favorite-corner-hint:150:idle"
|
||||
assert (width, height) == (150, 150)
|
||||
assert geometry == [(1.0, False, 0, 1080)] # Original drawing remains the cache-miss fallback.
|
||||
|
||||
render_idle()
|
||||
assert geometry[-1] == (1.0, False, 0.0, 150.0) # Cached art is drawn in local texture coordinates.
|
||||
|
||||
texture = object()
|
||||
cached[idle_key] = texture
|
||||
menu._draw_corner_hint()
|
||||
assert len(geometry) == 2
|
||||
assert draws[-1][0] is texture
|
||||
destination = draws[-1][2]
|
||||
assert (destination.x, destination.y, destination.width, destination.height) == (0, 930, 150, 150)
|
||||
assert blend_modes == [rl.BlendMode.BLEND_ALPHA_PREMULTIPLY]
|
||||
|
||||
menu._corner_press = object()
|
||||
menu._draw_corner_hint()
|
||||
assert requests[-1][0] == "favorite-corner-hint:150:pressed"
|
||||
assert geometry[-1] == (1.0, True, 0, 1080)
|
||||
|
||||
|
||||
def test_radial_menu_opens_from_diagonal_inward_swipe_and_auto_collapses_after_six_seconds():
|
||||
clock = [0.0]
|
||||
menu, _params, _memory = _menu(clock)
|
||||
|
||||
Reference in New Issue
Block a user