1pub mod auto_tile;
2
3use crate::grid::Grid;
4use noise::NoiseFn;
5use std::ops::{Add, Div, Mul, Range, Sub};
6use vek::{Mat4, Vec2};
7
8pub trait GridGenetator<T: Copy> {
9 fn generate(
10 &mut self,
11 location: Vec2<usize>,
12 size: Vec2<usize>,
13 current: T,
14 grid: &Grid<T>,
15 ) -> T;
16}
17
18impl<T: Copy, F: FnMut(Vec2<usize>, Vec2<usize>, T) -> T> GridGenetator<T> for F {
19 fn generate(&mut self, location: Vec2<usize>, size: Vec2<usize>, current: T, _: &Grid<T>) -> T {
20 self(location, size, current)
21 }
22}
23
24pub struct ConstGenerator<T: Copy>(pub T);
25
26impl<T: Copy> GridGenetator<T> for ConstGenerator<T> {
27 fn generate(&mut self, _: Vec2<usize>, _: Vec2<usize>, _: T, _: &Grid<T>) -> T {
28 self.0
29 }
30}
31
32pub struct OffsetLocationGenerator<'a, T: Copy> {
33 pub generator: &'a mut dyn GridGenetator<T>,
34 pub offsets: &'a Grid<Vec2<isize>>,
35}
36
37impl<T: Copy> GridGenetator<T> for OffsetLocationGenerator<'_, T> {
38 fn generate(
39 &mut self,
40 mut location: Vec2<usize>,
41 size: Vec2<usize>,
42 current: T,
43 grid: &Grid<T>,
44 ) -> T {
45 let offset = self.offsets.get(location).unwrap_or_default();
46 if offset.x >= 0 {
47 location.x = (location.x + offset.x as usize) % size.x;
48 } else {
49 location.x = (location.x + size.x - offset.x.unsigned_abs() % size.x) % size.x;
50 }
51 if offset.y >= 0 {
52 location.y = (location.y + offset.y as usize) % size.y;
53 } else {
54 location.y = (location.y + size.y - offset.y.unsigned_abs() % size.y) % size.y;
55 }
56 self.generator.generate(location, size, current, grid)
57 }
58}
59
60pub struct NoiseGenerator<T: NoiseFn<f64, 2>> {
61 pub noise: T,
62 pub transform: Mat4<f64>,
63}
64
65impl<T: NoiseFn<f64, 2>> NoiseGenerator<T> {
66 pub fn new(noise: T) -> Self {
67 Self {
68 noise,
69 transform: Mat4::identity(),
70 }
71 }
72
73 pub fn transform(mut self, transform: Mat4<f64>) -> Self {
74 self.transform = transform;
75 self
76 }
77}
78
79impl<T: NoiseFn<f64, 2>> GridGenetator<f64> for NoiseGenerator<T> {
80 fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, _: f64, _: &Grid<f64>) -> f64 {
81 let point = self.transform.mul_point(Vec2 {
82 x: location.x as f64,
83 y: location.y as f64,
84 });
85 self.noise.get(point.into_array())
86 }
87}
88
89pub struct CopyGenerator<'a, T: Copy> {
90 pub other: &'a Grid<T>,
91}
92
93impl<T: Copy + Add<Output = T> + Default> GridGenetator<T> for CopyGenerator<'_, T> {
94 fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, _: T, _: &Grid<T>) -> T {
95 self.other.get(location).unwrap_or_default()
96 }
97}
98
99pub struct AddGenerator<'a, T: Copy> {
100 pub other: &'a Grid<T>,
101}
102
103impl<T: Copy + Add<Output = T> + Default> GridGenetator<T> for AddGenerator<'_, T> {
104 fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
105 current + self.other.get(location).unwrap_or_default()
106 }
107}
108
109pub struct SubGenerator<'a, T: Copy> {
110 pub other: &'a Grid<T>,
111}
112
113impl<T: Copy + Sub<Output = T> + Default> GridGenetator<T> for SubGenerator<'_, T> {
114 fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
115 current - self.other.get(location).unwrap_or_default()
116 }
117}
118
119pub struct MulGenerator<'a, T: Copy> {
120 pub other: &'a Grid<T>,
121}
122
123impl<T: Copy + Mul<Output = T> + Default> GridGenetator<T> for MulGenerator<'_, T> {
124 fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
125 current * self.other.get(location).unwrap_or_default()
126 }
127}
128
129pub struct DivGenerator<'a, T: Copy> {
130 pub other: &'a Grid<T>,
131}
132
133impl<T: Copy + Div<Output = T> + Default> GridGenetator<T> for DivGenerator<'_, T> {
134 fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
135 current / self.other.get(location).unwrap_or_default()
136 }
137}
138
139pub struct MinGenerator<'a, T: Copy> {
140 pub other: &'a Grid<T>,
141}
142
143impl<T: Copy + Div<Output = T> + Ord + Default> GridGenetator<T> for MinGenerator<'_, T> {
144 fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
145 current.min(self.other.get(location).unwrap_or_default())
146 }
147}
148
149pub struct MaxGenerator<'a, T: Copy> {
150 pub other: &'a Grid<T>,
151}
152
153impl<T: Copy + Div<Output = T> + Ord + Default> GridGenetator<T> for MaxGenerator<'_, T> {
154 fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
155 current.max(self.other.get(location).unwrap_or_default())
156 }
157}
158
159pub struct ClampGenerator<T: Copy> {
160 pub min: T,
161 pub max: T,
162}
163
164impl<T: Copy + Ord + Default> GridGenetator<T> for ClampGenerator<T> {
165 fn generate(&mut self, _: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
166 current.clamp(self.min, self.max)
167 }
168}
169
170pub struct RemapGenerator<T: Copy> {
171 pub from: Range<T>,
172 pub to: Range<T>,
173}
174
175impl<T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>>
176 GridGenetator<T> for RemapGenerator<T>
177{
178 fn generate(&mut self, _: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
179 let factor = (current - self.from.start) / (self.from.end - self.from.start);
180 (self.to.end - self.to.start) * factor + self.to.start
181 }
182}
183
184pub enum ThresholdGenerator<'a, T: Copy> {
185 Constant {
186 threshold: T,
187 value_upper: T,
188 value_lower: T,
189 },
190 Samples {
191 thresholds: &'a Grid<T>,
192 value_upper: T,
193 value_lower: T,
194 },
195}
196
197impl<T: Copy + PartialOrd + Default> GridGenetator<T> for ThresholdGenerator<'_, T> {
198 fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
199 match self {
200 Self::Constant {
201 threshold,
202 value_upper,
203 value_lower,
204 } => {
205 if current > *threshold {
206 *value_upper
207 } else {
208 *value_lower
209 }
210 }
211 Self::Samples {
212 thresholds,
213 value_upper,
214 value_lower,
215 } => {
216 if current > thresholds.get(location).unwrap_or_default() {
217 *value_upper
218 } else {
219 *value_lower
220 }
221 }
222 }
223 }
224}
225
226pub struct Kernel33Generator<'a, T: Copy> {
227 pub other: &'a Grid<T>,
228 pub kernel: [T; 9],
229}
230
231impl<'a> Kernel33Generator<'a, f64> {
232 pub fn identity(other: &'a Grid<f64>) -> Self {
233 Self {
234 other,
235 kernel: [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
236 }
237 }
238
239 pub fn ridge(other: &'a Grid<f64>) -> Self {
240 Self {
241 other,
242 kernel: [0.0, -1.0, 0.0, -1.0, 4.0, -1.0, 0.0, -1.0, 0.0],
243 }
244 }
245
246 pub fn edge_detection(other: &'a Grid<f64>) -> Self {
247 Self {
248 other,
249 kernel: [-1.0, -1.0, -1.0, -1.0, 8.0, -1.0, -1.0, -1.0, -1.0],
250 }
251 }
252
253 pub fn sharpen(other: &'a Grid<f64>) -> Self {
254 Self {
255 other,
256 kernel: [0.0, -1.0, 0.0, -1.0, 5.0, -1.0, 0.0, -1.0, 0.0],
257 }
258 }
259
260 pub fn emboss(other: &'a Grid<f64>) -> Self {
261 Self {
262 other,
263 kernel: [-2.0, -1.0, 0.0, -1.0, 1.0, 1.0, 0.0, 1.0, 2.0],
264 }
265 }
266
267 pub fn box_blur(other: &'a Grid<f64>) -> Self {
268 Self {
269 other,
270 kernel: [
271 1.0 / 9.0,
272 1.0 / 9.0,
273 1.0 / 9.0,
274 1.0 / 9.0,
275 1.0 / 9.0,
276 1.0 / 9.0,
277 1.0 / 9.0,
278 1.0 / 9.0,
279 1.0 / 9.0,
280 ],
281 }
282 }
283
284 pub fn gaussian_blur(other: &'a Grid<f64>) -> Self {
285 Self {
286 other,
287 kernel: [
288 1.0 / 16.0,
289 2.0 / 16.0,
290 1.0 / 16.0,
291 2.0 / 16.0,
292 4.0 / 16.0,
293 2.0 / 16.0,
294 1.0 / 16.0,
295 2.0 / 16.0,
296 1.0 / 16.0,
297 ],
298 }
299 }
300}
301
302impl<T: Copy + Add<Output = T> + Mul<Output = T> + Default> GridGenetator<T>
303 for Kernel33Generator<'_, T>
304{
305 fn generate(&mut self, location: Vec2<usize>, size: Vec2<usize>, _: T, _: &Grid<T>) -> T {
306 let region = [
307 self.other
308 .get(location + Vec2::new(size.x - 1, size.y - 1))
309 .unwrap_or_default(),
310 self.other
311 .get(location + Vec2::new(0, size.y - 1))
312 .unwrap_or_default(),
313 self.other
314 .get(location + Vec2::new(1, size.y - 1))
315 .unwrap_or_default(),
316 self.other
317 .get(location + Vec2::new(size.x - 1, 0))
318 .unwrap_or_default(),
319 self.other.get(location).unwrap_or_default(),
320 self.other
321 .get(location + Vec2::new(1, 0))
322 .unwrap_or_default(),
323 self.other
324 .get(location + Vec2::new(size.x - 1, 1))
325 .unwrap_or_default(),
326 self.other
327 .get(location + Vec2::new(0, 1))
328 .unwrap_or_default(),
329 self.other
330 .get(location + Vec2::new(1, 1))
331 .unwrap_or_default(),
332 ];
333 region
334 .into_iter()
335 .zip(self.kernel)
336 .fold(Default::default(), |accumulator, (value, kernel)| {
337 value * kernel + accumulator
338 })
339 }
340}