diff --git a/src/app.rs b/src/app.rs index c7bcac1..a955bbd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -22,6 +22,7 @@ enum PreviewFocus { Bumpmap, } +#[derive(Clone)] struct TexturePair { heightmap: TextureHandle, bumpmap: TextureHandle, @@ -141,16 +142,18 @@ impl TerrainApp { } } - fn preview_context_menu(&mut self, response: &Response, preview: PreviewFocus) { + fn preview_context_menu(response: &Response) -> bool { + let mut should_copy = false; response.context_menu(|ui| { if ui.button("Copy").clicked() { - self.copy_preview(preview); + should_copy = true; ui.close(); } }); + should_copy } - fn overlay_copy_button(&mut self, ui: &mut Ui, anchor_rect: egui::Rect, preview: PreviewFocus) { + fn overlay_copy_button(ui: &mut Ui, anchor_rect: egui::Rect, preview: PreviewFocus) -> bool { let button_size = Vec2::new(28.0, 28.0); let button_rect = Align2::RIGHT_TOP .align_size_within_rect(button_size, anchor_rect.shrink2(Vec2::new(8.0, 8.0))); @@ -165,7 +168,8 @@ impl TerrainApp { } else { Color32::from_rgba_premultiplied(40, 40, 40, 180) }; - ui.painter().rect_filled(button_rect, CornerRadius::same(6), fill); + ui.painter() + .rect_filled(button_rect, CornerRadius::same(6), fill); ui.painter().rect_stroke( button_rect, CornerRadius::same(6), @@ -180,11 +184,10 @@ impl TerrainApp { Color32::WHITE, ); - if response.clicked() { - self.copy_preview(preview); - } - + let clicked = response.clicked(); response.on_hover_text("Copy"); + let _ = preview; + clicked } fn tab_button(ui: &mut Ui, current: &mut LeftTab, tab: LeftTab, label: &str) { @@ -297,8 +300,13 @@ impl TerrainApp { } fn ui_right_panel(&mut self, ctx: &Context) { + let mut pending_copy = None; + let mut pending_focus = None; + let mut pending_hover = None; + let preview_focus = self.preview_focus; + let textures = self.textures.clone(); egui::CentralPanel::default().show(ctx, |ui| { - let Some(textures) = &self.textures else { + let Some(textures) = &textures else { ui.centered_and_justified(|ui| { ui.label("No generated images yet."); }); @@ -308,10 +316,10 @@ impl TerrainApp { let bumpmap_texture = textures.bumpmap.clone(); let available = ui.available_size(); - let bottom_strip_height = (available.y * 0.24).max(120.0).min(220.0); + let bottom_strip_height = (available.y * 0.24).clamp(120.0, 220.0); let main_height = (available.y - bottom_strip_height - 8.0).max(100.0); - let main_texture = match self.preview_focus { + let main_texture = match preview_focus { PreviewFocus::Heightmap => &heightmap_texture, PreviewFocus::Bumpmap => &bumpmap_texture, }; @@ -319,19 +327,22 @@ impl TerrainApp { let main_response = render_clickable_image(ui, main_texture, Vec2::new(available.x, main_height), true); if main_response.hovered() { - self.hovered_preview = Some(self.preview_focus); + pending_hover = Some(preview_focus); + } + if Self::preview_context_menu(&main_response) + || Self::overlay_copy_button(ui, main_response.rect, preview_focus) + { + pending_copy = Some(preview_focus); } - self.preview_context_menu(&main_response, self.preview_focus); - self.overlay_copy_button(ui, main_response.rect, self.preview_focus); ui.add_space(8.0); - let thumb_width = (available.x * 0.28).max(120.0).min(240.0); + let thumb_width = (available.x * 0.28).clamp(120.0, 240.0); let panel_width = (thumb_width + 32.0).min(available.x); - let secondary_texture = match self.preview_focus { + let secondary_texture = match preview_focus { PreviewFocus::Heightmap => &bumpmap_texture, PreviewFocus::Bumpmap => &heightmap_texture, }; - let secondary_focus = match self.preview_focus { + let secondary_focus = match preview_focus { PreviewFocus::Heightmap => PreviewFocus::Bumpmap, PreviewFocus::Bumpmap => PreviewFocus::Heightmap, }; @@ -354,16 +365,26 @@ impl TerrainApp { true, ); if secondary_response.hovered() { - self.hovered_preview = Some(secondary_focus); + pending_hover = Some(secondary_focus); + } + if Self::preview_context_menu(&secondary_response) { + pending_copy = Some(secondary_focus); } - self.preview_context_menu(&secondary_response, secondary_focus); if secondary_response.clicked() { - self.preview_focus = secondary_focus; + pending_focus = Some(secondary_focus); } }); }); }); }); + + if let Some(preview) = pending_copy { + self.copy_preview(preview); + } + if let Some(preview) = pending_focus { + self.preview_focus = preview; + } + self.hovered_preview = pending_hover; } } @@ -451,7 +472,7 @@ fn render_clickable_image( .sense(if clickable { Sense::click() } else { - Sense::click() + Sense::hover() }); let response = ui.add(image); diff --git a/src/generator.rs b/src/generator.rs index ebde71a..c93866f 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -128,7 +128,7 @@ fn hash22(p: Vec2, random_seed: u64) -> Vec2 { let scrambled_y = splitmix64(random_seed ^ 0xBF58_476D_1CE4_E5B9); let seed_x = u64_to_unit_f64(scrambled_x) * 1024.0; let seed_y = u64_to_unit_f64(scrambled_y) * 1024.0; - let kx = 0.318_309_9_f64; + let kx = std::f64::consts::FRAC_1_PI; let ky = 0.367_879_4_f64; let px = ((p.x as f64) + seed_x) * kx + ky;