a large number of small ui changes

This commit is contained in:
grimsace
2026-04-21 14:12:02 -05:00
parent 4295bb6b0f
commit 82f8323ff4
2 changed files with 77 additions and 45 deletions
+60 -41
View File
@@ -2,7 +2,7 @@ use std::sync::mpsc::{self, Receiver, TryRecvError};
use std::thread; use std::thread;
use eframe::egui::{ use eframe::egui::{
self, Color32, ColorImage, Context, DragValue, RichText, Sense, Slider, TextureHandle, self, Color32, ColorImage, Context, DragValue, Frame, RichText, Sense, Slider, TextureHandle,
TextureOptions, Ui, Vec2, TextureOptions, Ui, Vec2,
}; };
use rand::Rng; use rand::Rng;
@@ -42,7 +42,7 @@ impl TerrainApp {
Self { Self {
params: GenerationParams::default(), params: GenerationParams::default(),
generation_tab: LeftTab::Generation, generation_tab: LeftTab::Generation,
preview_focus: PreviewFocus::Heightmap, preview_focus: PreviewFocus::Bumpmap,
textures: None, textures: None,
generated: None, generated: None,
generation_receiver: None, generation_receiver: None,
@@ -127,11 +127,16 @@ impl TerrainApp {
.default_width(320.0) .default_width(320.0)
.min_width(280.0) .min_width(280.0)
.show(ctx, |ui| { .show(ctx, |ui| {
ui.heading("Terrain Generator"); ui.heading("Advanced Erosion Terrain Generator");
ui.add_space(8.0); ui.add_space(8.0);
ui.horizontal(|ui| { ui.horizontal(|ui| {
Self::tab_button(ui, &mut self.generation_tab, LeftTab::Generation, "Generation"); Self::tab_button(
ui,
&mut self.generation_tab,
LeftTab::Generation,
"Generation",
);
Self::tab_button(ui, &mut self.generation_tab, LeftTab::Advanced, "Advanced"); Self::tab_button(ui, &mut self.generation_tab, LeftTab::Advanced, "Advanced");
}); });
@@ -231,46 +236,46 @@ impl TerrainApp {
let bottom_strip_height = (available.y * 0.24).max(120.0).min(220.0); let bottom_strip_height = (available.y * 0.24).max(120.0).min(220.0);
let main_height = (available.y - bottom_strip_height - 8.0).max(100.0); let main_height = (available.y - bottom_strip_height - 8.0).max(100.0);
let (main_texture, bottom_texture) = match self.preview_focus { let main_texture = match self.preview_focus {
PreviewFocus::Heightmap => (&textures.heightmap, &textures.bumpmap), PreviewFocus::Heightmap => &textures.heightmap,
PreviewFocus::Bumpmap => (&textures.bumpmap, &textures.heightmap), PreviewFocus::Bumpmap => &textures.bumpmap,
}; };
render_clickable_image(ui, main_texture, Vec2::new(available.x, main_height), false); render_clickable_image(ui, main_texture, Vec2::new(available.x, main_height), false);
ui.add_space(8.0); ui.add_space(8.0);
let thumb_width = (available.x * 0.28).max(120.0).min(240.0);
let panel_width = (thumb_width + 32.0).min(available.x);
let secondary_texture = match self.preview_focus {
PreviewFocus::Heightmap => &textures.bumpmap,
PreviewFocus::Bumpmap => &textures.heightmap,
};
let secondary_focus = match self.preview_focus {
PreviewFocus::Heightmap => PreviewFocus::Bumpmap,
PreviewFocus::Bumpmap => PreviewFocus::Heightmap,
};
let secondary_label = match secondary_focus {
PreviewFocus::Heightmap => "Heightmap",
PreviewFocus::Bumpmap => "Bumpmap",
};
ui.horizontal_centered(|ui| { ui.horizontal_centered(|ui| {
let thumb_width = ((available.x - 24.0) * 0.28).max(100.0).min(220.0); Frame::group(ui.style()).show(ui, |ui| {
let spacer = (available.x - thumb_width * 2.0).max(0.0); ui.set_min_width(panel_width);
ui.set_max_width(panel_width);
let main_thumb_clicked = render_clickable_image( ui.vertical_centered(|ui| {
ui, ui.label(RichText::new(secondary_label).strong());
match self.preview_focus { ui.add_space(6.0);
PreviewFocus::Heightmap => &textures.heightmap, if render_clickable_image(
PreviewFocus::Bumpmap => &textures.bumpmap, ui,
}, secondary_texture,
Vec2::new(thumb_width, bottom_strip_height), Vec2::new(thumb_width, bottom_strip_height - 32.0),
true, true,
); ) {
self.preview_focus = secondary_focus;
ui.add_space(spacer); }
});
let secondary_clicked = });
render_clickable_image(ui, bottom_texture, Vec2::new(thumb_width, bottom_strip_height), true);
if main_thumb_clicked {
self.preview_focus = match self.preview_focus {
PreviewFocus::Heightmap => PreviewFocus::Heightmap,
PreviewFocus::Bumpmap => PreviewFocus::Bumpmap,
};
}
if secondary_clicked {
self.preview_focus = match self.preview_focus {
PreviewFocus::Heightmap => PreviewFocus::Bumpmap,
PreviewFocus::Bumpmap => PreviewFocus::Heightmap,
};
}
}); });
}); });
} }
@@ -294,7 +299,12 @@ fn gray_to_color_image(image: &image::GrayImage) -> ColorImage {
ColorImage::new(size, pixels) ColorImage::new(size, pixels)
} }
fn labeled_int_slider(ui: &mut Ui, label: &str, value: &mut usize, range: std::ops::RangeInclusive<usize>) { fn labeled_int_slider(
ui: &mut Ui,
label: &str,
value: &mut usize,
range: std::ops::RangeInclusive<usize>,
) {
ui.label(label); ui.label(label);
let mut slider_value = *value as u32; let mut slider_value = *value as u32;
if ui if ui
@@ -320,12 +330,21 @@ fn labeled_float_slider(
ui.add(slider); ui.add(slider);
} }
fn render_clickable_image(ui: &mut Ui, texture: &TextureHandle, max_size: Vec2, clickable: bool) -> bool { fn render_clickable_image(
ui: &mut Ui,
texture: &TextureHandle,
max_size: Vec2,
clickable: bool,
) -> bool {
let image_size = texture.size_vec2(); let image_size = texture.size_vec2();
let scale = (max_size.x / image_size.x).min(max_size.y / image_size.y); let scale = (max_size.x / image_size.x).min(max_size.y / image_size.y);
let desired_size = image_size * scale.max(0.01); let desired_size = image_size * scale.max(0.01);
let image = egui::Image::new(texture) let image = egui::Image::new(texture)
.fit_to_exact_size(desired_size) .fit_to_exact_size(desired_size)
.sense(if clickable { Sense::click() } else { Sense::hover() }); .sense(if clickable {
Sense::click()
} else {
Sense::hover()
});
ui.add(image).clicked() ui.add(image).clicked()
} }
+17 -4
View File
@@ -28,7 +28,7 @@ impl Default for GenerationParams {
Self { Self {
image_width: 512, image_width: 512,
image_height: 512, image_height: 512,
generation_scale: 6.0, generation_scale: 1.0,
erosion_scale: 0.15, erosion_scale: 0.15,
random_seed: 0, random_seed: 0,
erosion_strength: 0.05, erosion_strength: 0.05,
@@ -124,9 +124,10 @@ fn clamp01(x: f32) -> f32 {
} }
fn hash22(p: Vec2, random_seed: u64) -> Vec2 { fn hash22(p: Vec2, random_seed: u64) -> Vec2 {
let seed = random_seed as f64; let scrambled_x = splitmix64(random_seed ^ 0x9E37_79B9_7F4A_7C15);
let seed_x = seed * 0.754_877_666_246_692_7; let scrambled_y = splitmix64(random_seed ^ 0xBF58_476D_1CE4_E5B9);
let seed_y = seed * 0.569_840_290_998_053_2; 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 = 0.318_309_9_f64;
let ky = 0.367_879_4_f64; let ky = 0.367_879_4_f64;
@@ -140,6 +141,18 @@ fn hash22(p: Vec2, random_seed: u64) -> Vec2 {
Vec2::new(rx as f32, ry as f32) Vec2::new(rx as f32, ry as f32)
} }
fn splitmix64(mut x: u64) -> u64 {
x = x.wrapping_add(0x9E37_79B9_7F4A_7C15);
x = (x ^ (x >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
x = (x ^ (x >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
x ^ (x >> 31)
}
fn u64_to_unit_f64(value: u64) -> f64 {
const SCALE: f64 = 1.0 / (u64::MAX as f64);
(value as f64) * SCALE
}
fn noised(p: Vec2, random_seed: u64) -> (f32, Vec2) { fn noised(p: Vec2, random_seed: u64) -> (f32, Vec2) {
let i = Vec2::new(p.x.floor(), p.y.floor()); let i = Vec2::new(p.x.floor(), p.y.floor());
let f = Vec2::new(p.x - i.x, p.y - i.y); let f = Vec2::new(p.x - i.x, p.y - i.y);