copying now uses it's own thread to avoid freezing the ui for larger images
This commit is contained in:
+57
-11
@@ -37,6 +37,8 @@ pub struct TerrainApp {
|
|||||||
generated: Option<GeneratedImages>,
|
generated: Option<GeneratedImages>,
|
||||||
generation_receiver: Option<Receiver<Result<GeneratedImages, String>>>,
|
generation_receiver: Option<Receiver<Result<GeneratedImages, String>>>,
|
||||||
generation_in_progress: bool,
|
generation_in_progress: bool,
|
||||||
|
copy_receiver: Option<Receiver<Result<String, String>>>,
|
||||||
|
copy_in_progress: bool,
|
||||||
status_message: String,
|
status_message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +53,8 @@ impl TerrainApp {
|
|||||||
generated: None,
|
generated: None,
|
||||||
generation_receiver: None,
|
generation_receiver: None,
|
||||||
generation_in_progress: false,
|
generation_in_progress: false,
|
||||||
|
copy_receiver: None,
|
||||||
|
copy_in_progress: false,
|
||||||
status_message: String::from("Adjust parameters and click Generate."),
|
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) {
|
fn install_textures(&mut self, ctx: &Context, images: &GeneratedImages) {
|
||||||
let heightmap = gray_to_color_image(&images.heightmap_image);
|
let heightmap = gray_to_color_image(&images.heightmap_image);
|
||||||
let bumpmap = gray_to_color_image(&images.bumpmap_image);
|
let bumpmap = gray_to_color_image(&images.bumpmap_image);
|
||||||
@@ -119,27 +150,37 @@ impl TerrainApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn copy_preview(&mut self, preview: PreviewFocus) {
|
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 {
|
let Some(generated) = &self.generated else {
|
||||||
self.status_message = String::from("No generated image is available to copy.");
|
self.status_message = String::from("No generated image is available to copy.");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let image = match preview {
|
let image = match preview {
|
||||||
PreviewFocus::Heightmap => &generated.heightmap_image,
|
PreviewFocus::Heightmap => generated.heightmap_image.clone(),
|
||||||
PreviewFocus::Bumpmap => &generated.bumpmap_image,
|
PreviewFocus::Bumpmap => generated.bumpmap_image.clone(),
|
||||||
};
|
};
|
||||||
|
let success_message = match preview {
|
||||||
match copy_gray_image_to_clipboard(image) {
|
|
||||||
Ok(()) => {
|
|
||||||
self.status_message = match preview {
|
|
||||||
PreviewFocus::Heightmap => String::from("Heightmap copied to clipboard."),
|
PreviewFocus::Heightmap => String::from("Heightmap copied to clipboard."),
|
||||||
PreviewFocus::Bumpmap => String::from("Bumpmap copied to clipboard."),
|
PreviewFocus::Bumpmap => String::from("Bumpmap copied to clipboard."),
|
||||||
};
|
};
|
||||||
}
|
|
||||||
Err(error) => {
|
let (tx, rx) = mpsc::channel();
|
||||||
self.status_message = format!("Failed to copy image: {error}");
|
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 {
|
fn preview_context_menu(response: &Response) -> bool {
|
||||||
@@ -236,6 +277,10 @@ impl TerrainApp {
|
|||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
ui.spinner();
|
ui.spinner();
|
||||||
}
|
}
|
||||||
|
if self.copy_in_progress {
|
||||||
|
ui.add_space(4.0);
|
||||||
|
ui.spinner();
|
||||||
|
}
|
||||||
|
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
ui.label(&self.status_message);
|
ui.label(&self.status_message);
|
||||||
@@ -392,6 +437,7 @@ impl eframe::App for TerrainApp {
|
|||||||
fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) {
|
fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) {
|
||||||
self.hovered_preview = None;
|
self.hovered_preview = None;
|
||||||
self.poll_generation(ctx);
|
self.poll_generation(ctx);
|
||||||
|
self.poll_copy(ctx);
|
||||||
self.ui_left_panel(ctx);
|
self.ui_left_panel(ctx);
|
||||||
self.ui_right_panel(ctx);
|
self.ui_right_panel(ctx);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user