1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use crate::error::error::BlpError;
use crate::core::image::MAX_MIPS;
use crate::ui::viewer::app::App;
use eframe::egui::{ColorImage, Context, TextureOptions, vec2};
use std::sync::mpsc::TryRecvError;
impl App {
pub(crate) fn poll_decoder(&mut self, ctx: &Context) {
if !self.loading {
return;
}
// Чтобы UI не "замерзал", просим перерисовку
ctx.request_repaint();
// ВАЖНО: сначала вынуть rx из self, чтобы дальше можно было менять self.*
let Some(rx) = self.decode_rx.take() else {
// канала нет — считать, что загрузка сорвалась
self.loading = false;
return;
};
match rx.try_recv() {
// === успех ===
Ok(Ok(blp)) => {
// Заливка текстур только для существующих уровней
self.mip_visible.fill(false);
for (i, m) in blp
.mipmaps
.iter()
.enumerate()
.take(MAX_MIPS)
{
if let Some(img) = &m.image {
let (w, h) = (m.width as usize, m.height as usize);
let mut ci = ColorImage::from_rgba_unmultiplied([w, h], img.as_raw());
ci.source_size = vec2(w as f32, h as f32);
self.mip_textures[i] = Some(ctx.load_texture(format!("mip_{i}"), ci, TextureOptions::LINEAR));
self.mip_visible[i] = true;
} else {
self.mip_textures[i] = None;
self.mip_visible[i] = false;
}
}
self.blp = Some(blp);
self.loading = false;
// rx дропаем — декодер завершён
}
// === ошибка из воркера (AppErr) ===
Ok(Err(err)) => {
// Вкладываем как причину в "внешний" ключ, если нужен контекст
self.error = Some(BlpError::new("error-poll-decoder").push_blp(err));
self.blp = None;
self.loading = false;
// rx дропаем
}
// === канал пуст — оставляем rx и ждём следующего кадра ===
Err(TryRecvError::Empty) => {
self.decode_rx = Some(rx); // вернуть канал назад
// self.loading остаётся true
}
// === воркер умер — фиксируем явную ошибку ===
Err(TryRecvError::Disconnected) => {
self.error = Some(BlpError::new("blp.decode-thread-disconnected").with_arg("msg", "decoder thread disconnected"));
self.blp = None;
self.loading = false;
// rx дропаем
}
}
}
}