Skip to content

Commit

Permalink
Improve noise layer generation / post processing
Browse files Browse the repository at this point in the history
- make noise layers optional
- move some functions around to more reasonable locations
- add `Settings` menu bar option to toggle noise layers
  and verbose time printing for post processing steps
  • Loading branch information
iMilchshake committed Feb 13, 2025
1 parent 677bf40 commit 36c44de
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 101 deletions.
1 change: 1 addition & 0 deletions src/bin/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ fn main() {
gen_config,
map_config,
&ThemeConfig::default(),
false,
)
});

Expand Down
1 change: 1 addition & 0 deletions src/bin/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ fn main() {
gen_config,
map_config,
&ThemeConfig::default(),
false, // TODO: add CLIArg
)
});

Expand Down
2 changes: 2 additions & 0 deletions src/bin/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ async fn main() {
&editor.gen_config,
&editor.thm_config,
&mut editor.debug_layers,
editor.generate_noise_layers,
editor.verbose_post_process,
)
.unwrap_or_else(|err| {
println!("Post Processing Failed: {:}", err);
Expand Down
19 changes: 17 additions & 2 deletions src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ pub struct Editor {

/// whether to keep using the same seed for next generations
pub retry_on_failure: bool,

/// whether to generate noise layers. this is computational expensive and should only be done
/// for debugging purposes, or if the map is intended to be exported.
pub generate_noise_layers: bool,

pub verbose_post_process: bool,
}

impl Editor {
Expand Down Expand Up @@ -143,6 +149,8 @@ impl Editor {
show_theme_widget: false,
show_debug_widget: false,
show_debug_layers: false,
generate_noise_layers: true,
verbose_post_process: false,
};

// initialize debug layers
Expand Down Expand Up @@ -183,7 +191,10 @@ impl Editor {
}

pub fn initialize_debug_layers(&mut self) {
assert!(!self.disable_debug_layers);
assert!(
!self.disable_debug_layers,
"debug layers already initialized"
);

// if possible, get currently active layers for re-using
let previously_active_layers = self.debug_layers.take().map(|d| d.active_layers);
Expand Down Expand Up @@ -284,7 +295,11 @@ impl Editor {
&self.thm_config,
self.user_seed.clone(),
);
self.initialize_debug_layers();

// reset debug layers, if used
if !self.disable_debug_layers {
self.initialize_debug_layers();
}
}

fn mouse_in_viewport(cam: &Camera2D) -> bool {
Expand Down
103 changes: 28 additions & 75 deletions src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,17 @@ use crate::{
debug::DebugLayers,
kernel::Kernel,
map::{BlockType, Map, Overwrite},
noise,
position::Position,
post_processing::{self as post, get_flood_fill},
random::{Random, Seed},
utils::safe_slice_mut,
walker::CuteWalker,
};

const PRINT_TIMES: bool = false;

pub fn print_time(timer: &Timer, message: &str) {
// TODO: add cli flag for this
if PRINT_TIMES {
pub fn print_time(timer: &mut Timer, message: &str, print: bool) {
if print {
println!("{}: {:?}", message, timer.elapsed());
*timer = Timer::start() // start new timer
}
}

Expand Down Expand Up @@ -302,28 +299,14 @@ impl Generator {
&Overwrite::Force,
);

self.write_text(
self.map.write_text(
&textbox_top_left
.shifted_by(text_margin, text_margin)
.unwrap(),
&info_text,
);
}

pub fn write_text(&mut self, pos: &Position, text: &str) {
let mut cursor = pos.clone();

for ch in text.chars() {
if ch == '\n' {
cursor.y += 1;
cursor.x = pos.x;
} else {
self.map.font_layer[cursor.as_index()] = ch;
cursor.x += 1;
}
}
}

/// perform one step of the map generation
pub fn step(
&mut self,
Expand Down Expand Up @@ -416,21 +399,22 @@ impl Generator {
Some(subwaypoints)
}

// TODO: move this "do all" function into post processing script?
pub fn perform_all_post_processing(
&mut self,
gen_config: &GenerationConfig,
thm_config: &ThemeConfig,
debug_layers: &mut Option<DebugLayers>,
export_preprocess: bool,
verbose: bool,
) -> Result<(), &'static str> {
let timer = Timer::start();
let mut timer = Timer::start();

// lock all remaining blocks
self.walker
.lock_previous_location(&self.map, gen_config, true)?;

let edge_bugs = post::fix_edge_bugs(self).expect("fix edge bugs failed");
print_time(&timer, "fix edge bugs");
print_time(&mut timer, "fix edge bugs", verbose);

self.generate_spawn(thm_config);

Expand All @@ -444,17 +428,18 @@ impl Generator {
Some(&BlockType::Finish),
)
.expect("start finish room generation");
self.write_text(&self.walker.pos.shifted_by(-2, 0)?, "GG :>");
print_time(&timer, "place rooms");
self.map
.write_text(&self.walker.pos.shifted_by(-2, 0)?, "GG :>");
print_time(&mut timer, "place rooms", verbose);

if gen_config.min_freeze_size > 0 {
// TODO: Maybe add some alternative function for the case of min_freeze_size=1
post::remove_freeze_blobs(self, gen_config.min_freeze_size, debug_layers);
print_time(&timer, "detect blobs");
print_time(&mut timer, "detect blobs", verbose);
}

let flood_fill = get_flood_fill(self, &self.spawn, debug_layers);
print_time(&timer, "flood fill");
print_time(&mut timer, "flood fill", verbose);

post::gen_all_platform_candidates(
&self.walker.position_history,
Expand All @@ -463,7 +448,7 @@ impl Generator {
gen_config,
debug_layers,
);
print_time(&timer, "platforms");
print_time(&mut timer, "platforms", verbose);

post::generate_all_skips(
self,
Expand All @@ -473,10 +458,10 @@ impl Generator {
&flood_fill,
debug_layers,
);
print_time(&timer, "generate skips");
print_time(&mut timer, "generate skips", verbose);

post::fill_open_areas(self, &gen_config.max_distance, debug_layers);
print_time(&timer, "place obstacles");
print_time(&mut timer, "place obstacles", verbose);

// post::remove_unused_blocks(&mut self.map, &self.walker.locked_positions);

Expand All @@ -485,51 +470,12 @@ impl Generator {
self.walker.locked_positions.clone();
debug_layers.bool_layers.get_mut("edge_bugs").unwrap().grid = edge_bugs;
}
print_time(&timer, "set debug layers");
print_time(&mut timer, "set debug layers", verbose);

// TODO: map noise is only required for maps that are actually **exported**,
// so these should be defined as optional steps.
self.map.noise_overlay = noise::generate_noise_array(
&self.map,
thm_config.overlay_noise_scale,
thm_config.overlay_noise_invert,
thm_config.overlay_noise_threshold,
thm_config.overlay_noise_type,
true,
false,
self.rnd.get_u32(),
);
print_time(&timer, "noise overlay");

if let Some(debug_layers) = debug_layers {
debug_layers.bool_layers.get_mut("noise_o").unwrap().grid =
self.map.noise_overlay.clone();
if export_preprocess {
post::generate_noise_layers(&mut self.map, &mut self.rnd, thm_config, debug_layers);
print_time(&mut timer, "generate noise layers", verbose);
}
print_time(&timer, "noise overlay (DEBUG)");

let noise_background = noise::generate_noise_array(
&self.map,
thm_config.background_noise_scale,
thm_config.background_noise_invert,
thm_config.background_noise_threshold,
thm_config.background_noise_type,
false,
true,
self.rnd.get_u32(),
);
print_time(&timer, "noise background");

self.map.noise_background = noise::opening(&noise::closing(&noise_background));

print_time(&timer, "noise background (MORPH)");

if let Some(debug_layers) = debug_layers {
debug_layers.bool_layers.get_mut("noise_b").unwrap().grid =
self.map.noise_background.clone();
}

print_time(&timer, "noise background (DEBUG)");
print_time(&timer, "test");

Ok(())
}
Expand All @@ -543,6 +489,7 @@ impl Generator {
gen_config: &GenerationConfig,
map_config: &MapConfig,
thm_config: &ThemeConfig,
export_preprocess: bool,
) -> Result<Map, &'static str> {
let mut gen = Generator::new(gen_config, map_config, thm_config, seed.clone());

Expand All @@ -558,7 +505,13 @@ impl Generator {
}

// perform all post processing step without creating any debug layers
gen.perform_all_post_processing(gen_config, thm_config, &mut None)?;
gen.perform_all_post_processing(
gen_config,
thm_config,
&mut None,
export_preprocess,
false,
)?;

Ok(gen.map)
}
Expand Down
7 changes: 4 additions & 3 deletions src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,10 @@ pub fn menu(ctx: &Context, editor: &mut Editor) {
editor.map_cam.reset();
}
});
ui.menu_button("Settings", |ui| {
ui.checkbox(&mut editor.generate_noise_layers, "noise layers");
ui.checkbox(&mut editor.verbose_post_process, "verbose post");
});
ui.menu_button("Help", |ui| if ui.button("About").clicked() {});
});
});
Expand Down Expand Up @@ -328,9 +332,6 @@ pub fn sidebar(ctx: &Context, editor: &mut Editor) {

ui.horizontal(|ui| {
ui.checkbox(&mut editor.fixed_seed, "fixed seed");
if ui.button("save map").clicked() {
editor.save_map_dialog();
}
});
}
ui.separator();
Expand Down
22 changes: 18 additions & 4 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ pub enum KernelType {
pub struct Map {
pub grid: Array2<BlockType>,
pub font_layer: Array2<char>,
pub noise_overlay: Array2<bool>,
pub noise_background: Array2<bool>,
pub noise_overlay: Option<Array2<bool>>,
pub noise_background: Option<Array2<bool>>,
pub height: usize,
pub width: usize,
pub chunk_edited: Array2<bool>, // TODO: make this optional in case editor is not used!
Expand All @@ -127,8 +127,8 @@ impl Map {
Map {
grid: Array2::from_elem((width, height), default),
font_layer: Array2::from_elem((width, height), ' '),
noise_overlay: Array2::from_elem((width, height), false),
noise_background: Array2::from_elem((width, height), false),
noise_overlay: None,
noise_background: None,
width,
height,
chunk_edited: Array2::from_elem(
Expand Down Expand Up @@ -326,4 +326,18 @@ impl Map {

None // criterion was never fulfilled
}

pub fn write_text(&mut self, pos: &Position, text: &str) {
let mut cursor = pos.clone();

for ch in text.chars() {
if ch == '\n' {
cursor.y += 1;
cursor.x = pos.x;
} else {
self.font_layer[cursor.as_index()] = ch;
cursor.x += 1;
}
}
}
}
42 changes: 41 additions & 1 deletion src/post_processing.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::{
config::GenerationConfig,
config::{GenerationConfig, ThemeConfig},
debug::DebugLayers,
generator::Generator,
map::{BlockType, Map, Overwrite},
noise,
position::{Position, ShiftDirection},
random::Random,
};

use std::{collections::VecDeque, f32::consts::SQRT_2};
Expand Down Expand Up @@ -889,3 +891,41 @@ pub fn gen_all_platform_candidates(
);
}
}

pub fn generate_noise_layers(
map: &mut Map,
rnd: &mut Random,
thm_config: &ThemeConfig,
debug_layers: &mut Option<DebugLayers>,
) {
map.noise_overlay = Some(noise::generate_noise_array(
&map,
thm_config.overlay_noise_scale,
thm_config.overlay_noise_invert,
thm_config.overlay_noise_threshold,
thm_config.overlay_noise_type,
true,
false,
rnd.get_u32(),
));
let noise_background = noise::generate_noise_array(
&map,
thm_config.background_noise_scale,
thm_config.background_noise_invert,
thm_config.background_noise_threshold,
thm_config.background_noise_type,
false,
true,
rnd.get_u32(),
);
map.noise_background = Some(noise::opening(&noise::closing(&noise_background)));

if let Some(debug_layers) = debug_layers {
debug_layers.bool_layers.get_mut("noise_o").unwrap().grid =
map.noise_overlay.clone().unwrap();
}
if let Some(debug_layers) = debug_layers {
debug_layers.bool_layers.get_mut("noise_b").unwrap().grid =
map.noise_background.clone().unwrap();
}
}
Loading

0 comments on commit 36c44de

Please sign in to comment.