terrain_forge/compose/
layer.rs1use crate::{Algorithm, Grid, Tile};
4
5#[derive(Debug, Clone, Copy)]
6pub enum BlendMode {
7 Replace,
8 Union,
9 Intersect,
10 Difference,
11 Mask,
12}
13
14pub struct LayeredGenerator {
15 layers: Vec<(Box<dyn Algorithm<Tile>>, BlendMode)>,
16}
17
18impl LayeredGenerator {
19 pub fn new() -> Self {
20 Self { layers: Vec::new() }
21 }
22
23 pub fn base<A: Algorithm<Tile> + 'static>(mut self, algo: A) -> Self {
24 self.layers.push((Box::new(algo), BlendMode::Replace));
25 self
26 }
27
28 pub fn union<A: Algorithm<Tile> + 'static>(mut self, algo: A) -> Self {
29 self.layers.push((Box::new(algo), BlendMode::Union));
30 self
31 }
32
33 pub fn intersect<A: Algorithm<Tile> + 'static>(mut self, algo: A) -> Self {
34 self.layers.push((Box::new(algo), BlendMode::Intersect));
35 self
36 }
37
38 pub fn difference<A: Algorithm<Tile> + 'static>(mut self, algo: A) -> Self {
39 self.layers.push((Box::new(algo), BlendMode::Difference));
40 self
41 }
42
43 pub fn add<A: Algorithm<Tile> + 'static>(mut self, algo: A, mode: BlendMode) -> Self {
44 self.layers.push((Box::new(algo), mode));
45 self
46 }
47}
48
49impl Default for LayeredGenerator {
50 fn default() -> Self {
51 Self::new()
52 }
53}
54
55impl Algorithm<Tile> for LayeredGenerator {
56 fn generate(&self, grid: &mut Grid<Tile>, seed: u64) {
57 for (i, (algo, mode)) in self.layers.iter().enumerate() {
58 let layer_seed = seed.wrapping_add(i as u64 * 1000);
59
60 match mode {
61 BlendMode::Replace => {
62 algo.generate(grid, layer_seed);
63 }
64 BlendMode::Union => {
65 let mut layer = Grid::new(grid.width(), grid.height());
66 algo.generate(&mut layer, layer_seed);
67 for y in 0..grid.height() {
68 for x in 0..grid.width() {
69 if layer[(x, y)].is_floor() {
70 grid.set(x as i32, y as i32, Tile::Floor);
71 }
72 }
73 }
74 }
75 BlendMode::Intersect => {
76 let mut layer = Grid::new(grid.width(), grid.height());
77 algo.generate(&mut layer, layer_seed);
78 for y in 0..grid.height() {
79 for x in 0..grid.width() {
80 if !layer[(x, y)].is_floor() {
81 grid.set(x as i32, y as i32, Tile::Wall);
82 }
83 }
84 }
85 }
86 BlendMode::Difference => {
87 let mut layer = Grid::new(grid.width(), grid.height());
88 algo.generate(&mut layer, layer_seed);
89 for y in 0..grid.height() {
90 for x in 0..grid.width() {
91 if layer[(x, y)].is_floor() {
92 grid.set(x as i32, y as i32, Tile::Wall);
93 }
94 }
95 }
96 }
97 BlendMode::Mask => {
98 let mut mask = Grid::new(grid.width(), grid.height());
99 algo.generate(&mut mask, layer_seed);
100 for y in 0..grid.height() {
101 for x in 0..grid.width() {
102 if !mask[(x, y)].is_floor() {
103 grid.set(x as i32, y as i32, Tile::Wall);
104 }
105 }
106 }
107 }
108 }
109 }
110 }
111
112 fn name(&self) -> &'static str {
113 "LayeredGenerator"
114 }
115}