mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-02 03:52:11 +08:00
raylib: background onboarding texture loading (#36343)
* this seems best so far * better * clean up * debug * debug * clean up * final
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
import re
|
||||
import threading
|
||||
from enum import IntEnum
|
||||
|
||||
import pyray as rl
|
||||
@@ -38,15 +39,24 @@ class TrainingGuide(Widget):
|
||||
self._completed_callback = completed_callback
|
||||
|
||||
self._step = 0
|
||||
self._load_images()
|
||||
self._load_image_paths()
|
||||
|
||||
def _load_images(self):
|
||||
self._images = []
|
||||
# Load first image now so we show something immediately
|
||||
self._textures = [gui_app.texture(self._image_paths[0])]
|
||||
self._image_objs = []
|
||||
|
||||
threading.Thread(target=self._preload_thread, daemon=True).start()
|
||||
|
||||
def _load_image_paths(self):
|
||||
paths = [fn for fn in os.listdir(os.path.join(BASEDIR, "selfdrive/assets/training")) if re.match(r'^step\d*\.png$', fn)]
|
||||
paths = sorted(paths, key=lambda x: int(re.search(r'\d+', x).group()))
|
||||
for fn in paths:
|
||||
path = os.path.join(BASEDIR, "selfdrive/assets/training", fn)
|
||||
self._images.append(gui_app.texture(path))
|
||||
self._image_paths = [os.path.join(BASEDIR, "selfdrive/assets/training", fn) for fn in paths]
|
||||
|
||||
def _preload_thread(self):
|
||||
# PNG loading is slow in raylib, so we preload in a thread and upload to GPU in main thread
|
||||
# We've already loaded the first image on init
|
||||
for path in self._image_paths[1:]:
|
||||
self._image_objs.append(gui_app._load_image_from_path(path))
|
||||
|
||||
def _handle_mouse_release(self, mouse_pos):
|
||||
if rl.check_collision_point_rec(mouse_pos, STEP_RECTS[self._step]):
|
||||
@@ -57,30 +67,36 @@ class TrainingGuide(Widget):
|
||||
ui_state.params.put_bool("RecordFront", yes)
|
||||
|
||||
# Restart training?
|
||||
elif self._step == len(self._images) - 1:
|
||||
elif self._step == len(self._image_paths) - 1:
|
||||
if rl.check_collision_point_rec(mouse_pos, RESTART_TRAINING_RECT):
|
||||
self._step = -1
|
||||
|
||||
self._step += 1
|
||||
|
||||
# Finished?
|
||||
if self._step >= len(self._images):
|
||||
if self._step >= len(self._image_paths):
|
||||
self._step = 0
|
||||
if self._completed_callback:
|
||||
self._completed_callback()
|
||||
|
||||
def _update_state(self):
|
||||
if len(self._image_objs):
|
||||
self._textures.append(gui_app._load_texture_from_image(self._image_objs.pop(0)))
|
||||
|
||||
def _render(self, _):
|
||||
rl.draw_texture(self._images[self._step], 0, 0, rl.WHITE)
|
||||
# Safeguard against fast tapping
|
||||
step = min(self._step, len(self._textures) - 1)
|
||||
rl.draw_texture(self._textures[step], 0, 0, rl.WHITE)
|
||||
|
||||
# progress bar
|
||||
if 0 < self._step < len(STEP_RECTS) - 1:
|
||||
if 0 < step < len(STEP_RECTS) - 1:
|
||||
h = 20
|
||||
w = int((self._step / (len(STEP_RECTS) - 1)) * self._rect.width)
|
||||
w = int((step / (len(STEP_RECTS) - 1)) * self._rect.width)
|
||||
rl.draw_rectangle(int(self._rect.x), int(self._rect.y + self._rect.height - h),
|
||||
w, h, rl.Color(70, 91, 234, 255))
|
||||
|
||||
if DEBUG:
|
||||
rl.draw_rectangle_lines_ex(STEP_RECTS[self._step], 3, rl.RED)
|
||||
rl.draw_rectangle_lines_ex(STEP_RECTS[step], 3, rl.RED)
|
||||
|
||||
return -1
|
||||
|
||||
|
||||
@@ -196,13 +196,14 @@ class GuiApplication:
|
||||
return self._textures[cache_key]
|
||||
|
||||
with as_file(ASSETS_DIR.joinpath(asset_path)) as fspath:
|
||||
texture_obj = self._load_texture_from_image(fspath.as_posix(), width, height, alpha_premultiply, keep_aspect_ratio)
|
||||
image_obj = self._load_image_from_path(fspath.as_posix(), width, height, alpha_premultiply, keep_aspect_ratio)
|
||||
texture_obj = self._load_texture_from_image(image_obj)
|
||||
self._textures[cache_key] = texture_obj
|
||||
return texture_obj
|
||||
|
||||
def _load_texture_from_image(self, image_path: str, width: int | None = None, height: int | None = None,
|
||||
alpha_premultiply=False, keep_aspect_ratio=True):
|
||||
"""Load and resize a texture, storing it for later automatic unloading."""
|
||||
def _load_image_from_path(self, image_path: str, width: int | None = None, height: int | None = None,
|
||||
alpha_premultiply: bool = False, keep_aspect_ratio: bool = True) -> rl.Image:
|
||||
"""Load and resize an image, storing it for later automatic unloading."""
|
||||
image = rl.load_image(image_path)
|
||||
|
||||
if alpha_premultiply:
|
||||
@@ -225,7 +226,10 @@ class GuiApplication:
|
||||
rl.image_resize(image, new_width, new_height)
|
||||
else:
|
||||
rl.image_resize(image, width, height)
|
||||
return image
|
||||
|
||||
def _load_texture_from_image(self, image: rl.Image) -> rl.Texture:
|
||||
"""Send image to GPU and unload original image."""
|
||||
texture = rl.load_texture_from_image(image)
|
||||
# Set texture filtering to smooth the result
|
||||
rl.set_texture_filter(texture, rl.TextureFilter.TEXTURE_FILTER_BILINEAR)
|
||||
|
||||
Reference in New Issue
Block a user