1 pub mod theme; |
1 pub mod theme; |
2 |
2 |
3 use self::theme::Theme; |
3 use self::theme::Theme; |
4 use integral_geometry::{Point, Rect, Size}; |
4 use integral_geometry::{Point, Rect, Size}; |
5 use land2d::Land2D; |
5 use land2d::Land2D; |
6 use landgen::outline_template::OutlineTemplate; |
6 use landgen::{outline_template::OutlineTemplate, LandGenerationParameters}; |
7 use rand::{thread_rng, Rng}; |
|
8 use serde_derive::Deserialize; |
7 use serde_derive::Deserialize; |
9 use serde_yaml; |
8 use serde_yaml; |
10 use std::{borrow::Borrow, collections::hash_map::HashMap, mem::replace}; |
9 use std::{borrow::Borrow, collections::hash_map::HashMap, mem::replace}; |
11 use vec2d::Vec2D; |
10 use vec2d::Vec2D; |
|
11 use rand::{Rng, seq::SliceRandom}; |
12 |
12 |
13 #[derive(Deserialize)] |
13 #[derive(Deserialize)] |
14 struct PointDesc { |
14 struct PointDesc { |
15 x: u32, |
15 x: u32, |
16 y: u32, |
16 y: u32, |
109 ) |
109 ) |
110 }) |
110 }) |
111 .collect(); |
111 .collect(); |
112 } |
112 } |
113 |
113 |
114 pub fn get_template(&self, template_type: &str) -> Option<&OutlineTemplate> { |
114 pub fn get_template<R: Rng>(&self, template_type: &str, rng: &mut R) -> Option<&OutlineTemplate> { |
115 self.templates |
115 self.templates |
116 .get(template_type) |
116 .get(template_type) |
117 .and_then(|t| thread_rng().choose(t)) |
117 .and_then(|t| t.as_slice().choose(rng)) |
118 } |
118 } |
119 |
119 |
120 pub fn make_texture<LandT>(&self, land: &Land2D<LandT>, theme: &Theme) -> Vec2D<u32> |
120 pub fn make_texture<LandT>( |
|
121 &self, |
|
122 land: &Land2D<LandT>, |
|
123 parameters: &LandGenerationParameters<LandT>, |
|
124 theme: &Theme, |
|
125 ) -> Vec2D<u32> |
121 where |
126 where |
122 LandT: Copy + Default + PartialEq, |
127 LandT: Copy + Default + PartialEq, |
123 { |
128 { |
124 let mut texture = Vec2D::new(land.size().size(), 0); |
129 let mut texture = Vec2D::new(land.size().size(), 0); |
125 |
130 |
129 let sprite_row = land_sprite.get_row(row_index % land_sprite.height()); |
134 let sprite_row = land_sprite.get_row(row_index % land_sprite.height()); |
130 let mut x_offset = 0; |
135 let mut x_offset = 0; |
131 while sprite_row.len() < land.width() - x_offset { |
136 while sprite_row.len() < land.width() - x_offset { |
132 let copy_range = x_offset..x_offset + sprite_row.len(); |
137 let copy_range = x_offset..x_offset + sprite_row.len(); |
133 tex_row_copy( |
138 tex_row_copy( |
|
139 parameters.basic(), |
134 &land_row[copy_range.clone()], |
140 &land_row[copy_range.clone()], |
135 &mut tex_row[copy_range], |
141 &mut tex_row[copy_range], |
136 sprite_row, |
142 sprite_row, |
137 ); |
143 ); |
138 |
144 |
140 } |
146 } |
141 |
147 |
142 if x_offset < land.width() { |
148 if x_offset < land.width() { |
143 let final_range = x_offset..land.width(); |
149 let final_range = x_offset..land.width(); |
144 tex_row_copy( |
150 tex_row_copy( |
|
151 parameters.basic(), |
145 &land_row[final_range.clone()], |
152 &land_row[final_range.clone()], |
146 &mut tex_row[final_range], |
153 &mut tex_row[final_range], |
147 &sprite_row[..land.width() - x_offset], |
154 &sprite_row[..land.width() - x_offset], |
148 ); |
155 ); |
149 } |
156 } |
168 ); |
176 ); |
169 |
177 |
170 offsets.iter_mut().for_each(|v| *v = 255); |
178 offsets.iter_mut().for_each(|v| *v = 255); |
171 |
179 |
172 land_border_pass( |
180 land_border_pass( |
|
181 parameters.basic(), |
173 land.rows().zip(texture.rows_mut()), |
182 land.rows().zip(texture.rows_mut()), |
174 &mut offsets, |
183 &mut offsets, |
175 border_width, |
184 border_width, |
176 |x, y| border_sprite.get_pixel(x % border_sprite.width(), y), |
185 |x, y| border_sprite.get_pixel(x % border_sprite.width(), y), |
177 ); |
186 ); |
220 let green = lerp(target.green(), source.green(), source.alpha()); |
229 let green = lerp(target.green(), source.green(), source.alpha()); |
221 let blue = lerp(target.blue(), source.blue(), source.alpha()); |
230 let blue = lerp(target.blue(), source.blue(), source.alpha()); |
222 (red as u32) << 0 | (green as u32) << 8 | (blue as u32) << 16 | (alpha as u32) << 24 |
231 (red as u32) << 0 | (green as u32) << 8 | (blue as u32) << 16 | (alpha as u32) << 24 |
223 } |
232 } |
224 |
233 |
225 fn land_border_pass<'a, LandT, T, F>(rows: T, offsets: &mut [u8], border_width: u8, pixel_getter: F) |
234 fn land_border_pass<'a, LandT, T, F>( |
226 where |
235 basic_value: LandT, |
|
236 rows: T, |
|
237 offsets: &mut [u8], |
|
238 border_width: u8, |
|
239 pixel_getter: F, |
|
240 ) where |
227 LandT: Default + PartialEq + 'a, |
241 LandT: Default + PartialEq + 'a, |
228 T: Iterator<Item = (&'a [LandT], &'a mut [u32])>, |
242 T: Iterator<Item = (&'a [LandT], &'a mut [u32])>, |
229 F: (Fn(usize, usize) -> u32), |
243 F: (Fn(usize, usize) -> u32), |
230 { |
244 { |
231 for (land_row, tex_row) in rows { |
245 for (land_row, tex_row) in rows { |
233 .iter() |
247 .iter() |
234 .zip(tex_row.iter_mut()) |
248 .zip(tex_row.iter_mut()) |
235 .zip(offsets.iter_mut()) |
249 .zip(offsets.iter_mut()) |
236 .enumerate() |
250 .enumerate() |
237 { |
251 { |
238 *offset_v = if *land_v == LandT::default() { |
252 *offset_v = if *land_v == basic_value { |
239 if *offset_v < border_width { |
253 if *offset_v < border_width { |
240 *tex_v = blend(pixel_getter(x, *offset_v as usize), *tex_v) |
254 *tex_v = blend(pixel_getter(x, *offset_v as usize), *tex_v) |
241 } |
255 } |
242 offset_v.saturating_add(1) |
256 offset_v.saturating_add(1) |
243 } else { |
257 } else { |
245 } |
259 } |
246 } |
260 } |
247 } |
261 } |
248 } |
262 } |
249 |
263 |
250 fn tex_row_copy<LandT>(land_row: &[LandT], tex_row: &mut [u32], sprite_row: &[u32]) |
264 fn tex_row_copy<LandT>( |
251 where |
265 basic_value: LandT, |
|
266 land_row: &[LandT], |
|
267 tex_row: &mut [u32], |
|
268 sprite_row: &[u32], |
|
269 ) where |
252 LandT: Default + PartialEq, |
270 LandT: Default + PartialEq, |
253 { |
271 { |
254 for ((land_v, tex_v), sprite_v) in land_row.iter().zip(tex_row.iter_mut()).zip(sprite_row) { |
272 for ((land_v, tex_v), sprite_v) in land_row.iter().zip(tex_row.iter_mut()).zip(sprite_row) { |
255 *tex_v = if *land_v == LandT::default() { |
273 *tex_v = if *land_v == basic_value { *sprite_v } else { 0 } |
256 *sprite_v |
|
257 } else { |
|
258 0 |
|
259 } |
|
260 } |
274 } |
261 } |
275 } |
262 |
276 |
263 #[cfg(test)] |
277 #[cfg(test)] |
264 mod tests { |
278 mod tests { |