copying now uses it's own thread to avoid freezing the ui for larger images

This commit is contained in:
grimsace
2026-04-21 14:49:45 -05:00
parent 817a9f4e4f
commit 21c580a3c0
+57 -11
View File
@@ -37,6 +37,8 @@ pub struct TerrainApp {
generated: Option<GeneratedImages>,
generation_receiver: Option<Receiver<Result<GeneratedImages, String>>>,
generation_in_progress: bool,
copy_receiver: Option<Receiver<Result<String, String>>>,
copy_in_progress: bool,
status_message: String,
}
@@ -51,6 +53,8 @@ impl TerrainApp {
generated: None,
generation_receiver: None,
generation_in_progress: false,
copy_receiver: None,
copy_in_progress: false,
status_message: String::from("Adjust parameters and click Generate."),
}
}
@@ -108,6 +112,33 @@ impl TerrainApp {
}
}
fn poll_copy(&mut self, ctx: &Context) {
let Some(receiver) = &self.copy_receiver else {
return;
};
match receiver.try_recv() {
Ok(Ok(message)) => {
self.status_message = message;
self.copy_receiver = None;
self.copy_in_progress = false;
}
Ok(Err(error)) => {
self.status_message = error;
self.copy_receiver = None;
self.copy_in_progress = false;
}
Err(TryRecvError::Empty) => {
ctx.request_repaint();
}
Err(TryRecvError::Disconnected) => {
self.status_message = String::from("Copy worker disconnected.");
self.copy_receiver = None;
self.copy_in_progress = false;
}
}
}
fn install_textures(&mut self, ctx: &Context, images: &GeneratedImages) {
let heightmap = gray_to_color_image(&images.heightmap_image);
let bumpmap = gray_to_color_image(&images.bumpmap_image);
@@ -119,27 +150,37 @@ impl TerrainApp {
}
fn copy_preview(&mut self, preview: PreviewFocus) {
if self.copy_in_progress {
self.status_message = String::from("Copy already in progress...");
return;
}
let Some(generated) = &self.generated else {
self.status_message = String::from("No generated image is available to copy.");
return;
};
let image = match preview {
PreviewFocus::Heightmap => &generated.heightmap_image,
PreviewFocus::Bumpmap => &generated.bumpmap_image,
PreviewFocus::Heightmap => generated.heightmap_image.clone(),
PreviewFocus::Bumpmap => generated.bumpmap_image.clone(),
};
match copy_gray_image_to_clipboard(image) {
Ok(()) => {
self.status_message = match preview {
let success_message = match preview {
PreviewFocus::Heightmap => String::from("Heightmap copied to clipboard."),
PreviewFocus::Bumpmap => String::from("Bumpmap copied to clipboard."),
};
}
Err(error) => {
self.status_message = format!("Failed to copy image: {error}");
}
}
let (tx, rx) = mpsc::channel();
self.copy_receiver = Some(rx);
self.copy_in_progress = true;
self.status_message = match preview {
PreviewFocus::Heightmap => String::from("Copying heightmap to clipboard..."),
PreviewFocus::Bumpmap => String::from("Copying bumpmap to clipboard..."),
};
thread::spawn(move || {
let result = copy_gray_image_to_clipboard(&image).map(|_| success_message);
let _ = tx.send(result);
});
}
fn preview_context_menu(response: &Response) -> bool {
@@ -236,6 +277,10 @@ impl TerrainApp {
ui.add_space(8.0);
ui.spinner();
}
if self.copy_in_progress {
ui.add_space(4.0);
ui.spinner();
}
ui.add_space(8.0);
ui.label(&self.status_message);
@@ -392,6 +437,7 @@ impl eframe::App for TerrainApp {
fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) {
self.hovered_preview = None;
self.poll_generation(ctx);
self.poll_copy(ctx);
self.ui_left_panel(ctx);
self.ui_right_panel(ctx);