1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-01 14:20:04 -04:00

Make epi::Frame cloneable so you can allocate textures in other threads (#999)

Closes https://github.com/emilk/egui/issues/673

Also adds `epi::Image`
This commit is contained in:
Emil Ernerfeldt
2021-12-26 21:21:28 +01:00
committed by GitHub
parent 647e020824
commit b7441eeee7
28 changed files with 548 additions and 824 deletions

View File

@@ -7,7 +7,7 @@ struct Resource {
text: Option<String>,
/// If set, the response was an image.
image: Option<Image>,
image: Option<epi::Image>,
/// If set, the response was text with some supported syntax highlighting (e.g. ".rs" or ".md").
colored_text: Option<ColoredText>,
@@ -17,7 +17,7 @@ impl Resource {
fn from_response(ctx: &egui::Context, response: ehttp::Response) -> Self {
let content_type = response.content_type().unwrap_or_default();
let image = if content_type.starts_with("image/") {
Image::decode(&response.bytes)
decode_image(&response.bytes)
} else {
None
};
@@ -67,7 +67,7 @@ impl epi::App for HttpApp {
"⬇ HTTP"
}
fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) {
fn update(&mut self, ctx: &egui::CtxRef, frame: &epi::Frame) {
if let Some(receiver) = &mut self.in_progress {
// Are we there yet?
if let Ok(result) = receiver.try_recv() {
@@ -95,13 +95,13 @@ impl epi::App for HttpApp {
if trigger_fetch {
let request = ehttp::Request::get(&self.url);
let repaint_signal = frame.repaint_signal();
let frame = frame.clone();
let (sender, receiver) = std::sync::mpsc::channel();
self.in_progress = Some(receiver);
ehttp::fetch(request, move |response| {
sender.send(response).ok();
repaint_signal.request_repaint();
frame.request_repaint();
});
}
@@ -127,7 +127,7 @@ impl epi::App for HttpApp {
}
}
fn ui_url(ui: &mut egui::Ui, frame: &mut epi::Frame<'_>, url: &mut String) -> bool {
fn ui_url(ui: &mut egui::Ui, frame: &epi::Frame, url: &mut String) -> bool {
let mut trigger_fetch = false;
ui.horizontal(|ui| {
@@ -160,12 +160,7 @@ fn ui_url(ui: &mut egui::Ui, frame: &mut epi::Frame<'_>, url: &mut String) -> bo
trigger_fetch
}
fn ui_resource(
ui: &mut egui::Ui,
frame: &mut epi::Frame<'_>,
tex_mngr: &mut TexMngr,
resource: &Resource,
) {
fn ui_resource(ui: &mut egui::Ui, frame: &epi::Frame, tex_mngr: &mut TexMngr, resource: &Resource) {
let Resource {
response,
text,
@@ -218,7 +213,7 @@ fn ui_resource(
if let Some(image) = image {
if let Some(texture_id) = tex_mngr.texture(frame, &response.url, image) {
let mut size = egui::Vec2::new(image.size.0 as f32, image.size.1 as f32);
let mut size = egui::Vec2::new(image.size[0] as f32, image.size[1] as f32);
size *= (ui.available_width() / size.x).min(1.0);
ui.image(texture_id, size);
}
@@ -304,44 +299,27 @@ struct TexMngr {
impl TexMngr {
fn texture(
&mut self,
frame: &mut epi::Frame<'_>,
frame: &epi::Frame,
url: &str,
image: &Image,
image: &epi::Image,
) -> Option<egui::TextureId> {
if self.loaded_url != url {
if let Some(texture_id) = self.texture_id.take() {
frame.tex_allocator().free(texture_id);
frame.free_texture(texture_id);
}
self.texture_id = Some(
frame
.tex_allocator()
.alloc_srgba_premultiplied(image.size, &image.pixels),
);
self.texture_id = Some(frame.alloc_texture(image.clone()));
self.loaded_url = url.to_owned();
}
self.texture_id
}
}
struct Image {
size: (usize, usize),
pixels: Vec<egui::Color32>,
}
impl Image {
fn decode(bytes: &[u8]) -> Option<Image> {
use image::GenericImageView;
let image = image::load_from_memory(bytes).ok()?;
let image_buffer = image.to_rgba8();
let size = (image.width() as usize, image.height() as usize);
let pixels = image_buffer.into_vec();
assert_eq!(size.0 * size.1 * 4, pixels.len());
let pixels = pixels
.chunks(4)
.map(|p| egui::Color32::from_rgba_unmultiplied(p[0], p[1], p[2], p[3]))
.collect();
Some(Image { size, pixels })
}
fn decode_image(bytes: &[u8]) -> Option<epi::Image> {
use image::GenericImageView;
let image = image::load_from_memory(bytes).ok()?;
let image_buffer = image.to_rgba8();
let size = [image.width() as usize, image.height() as usize];
let pixels = image_buffer.into_vec();
Some(epi::Image::from_rgba_unmultiplied(size, &pixels))
}