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