106 self.templates.get(template_type).and_then(|t| thread_rng().choose(t)) |
106 self.templates.get(template_type).and_then(|t| thread_rng().choose(t)) |
107 } |
107 } |
108 |
108 |
109 pub fn make_texture(&self, land: &Land2D<u8>, theme: &Theme) -> Vec2D<u32> { |
109 pub fn make_texture(&self, land: &Land2D<u8>, theme: &Theme) -> Vec2D<u32> { |
110 let mut texture = Vec2D::new(land.size(), 0); |
110 let mut texture = Vec2D::new(land.size(), 0); |
|
111 |
111 if let Some(land_sprite) = theme.land_texture() { |
112 if let Some(land_sprite) = theme.land_texture() { |
112 for (row_index, (land_row, tex_row)) in land.rows() |
113 for (row_index, (land_row, tex_row)) in land.rows() |
113 .zip(texture.rows_mut()) |
114 .zip(texture.rows_mut()) |
114 .enumerate() |
115 .enumerate() |
115 { |
116 { |
134 &sprite_row[..land.width() - x_offset] |
135 &sprite_row[..land.width() - x_offset] |
135 ); |
136 ); |
136 } |
137 } |
137 } |
138 } |
138 } |
139 } |
|
140 |
|
141 if let Some(border_sprite) = theme.border_texture() { |
|
142 assert!(border_sprite.height() <= 512); |
|
143 let border_width = (border_sprite.height() / 2) as u8; |
|
144 |
|
145 let mut offsets = vec![255u8; land.width()]; |
|
146 |
|
147 land_border_pass( |
|
148 land.rows().rev().zip(texture.rows_mut().rev()), |
|
149 &mut offsets, |
|
150 border_width, |
|
151 |x, y| border_sprite.get_pixel( |
|
152 x % border_sprite.width(), |
|
153 border_sprite.height() - 1 - y, |
|
154 ) |
|
155 ); |
|
156 |
|
157 offsets.iter_mut().for_each(|v| *v = 255); |
|
158 |
|
159 land_border_pass( |
|
160 land.rows().zip(texture.rows_mut()), |
|
161 &mut offsets, |
|
162 border_width, |
|
163 |x, y| border_sprite.get_pixel( |
|
164 x % border_sprite.width(), |
|
165 y, |
|
166 ) |
|
167 ); |
|
168 } |
|
169 |
139 texture |
170 texture |
|
171 } |
|
172 } |
|
173 |
|
174 #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
|
175 struct Color(u32); |
|
176 |
|
177 impl Color { |
|
178 #[inline] |
|
179 fn red(self) -> u8 { |
|
180 (self.0 >> 0 & 0xFF) as u8 |
|
181 } |
|
182 |
|
183 #[inline] |
|
184 fn green(self) -> u8 { |
|
185 (self.0 >> 8 & 0xFF) as u8 |
|
186 } |
|
187 |
|
188 #[inline] |
|
189 fn blue(self) -> u8 { |
|
190 (self.0 >> 16 & 0xFF) as u8 |
|
191 } |
|
192 |
|
193 #[inline] |
|
194 fn alpha(self) -> u8 { |
|
195 (self.0 >> 24 & 0xFF) as u8 |
|
196 } |
|
197 } |
|
198 |
|
199 #[inline] |
|
200 fn lerp(from: u8, to: u8, coef: u8) -> u8 { |
|
201 ((from as u16 * (256 - coef as u16) + to as u16 * coef as u16) / 256) as u8 |
|
202 } |
|
203 |
|
204 #[inline] |
|
205 fn blend(source: u32, target: u32) -> u32 { |
|
206 let source = Color(source); |
|
207 let target = Color(target); |
|
208 let alpha = lerp(target.alpha(), 255, source.alpha()); |
|
209 let red = lerp(target.red(), source.red(), source.alpha()); |
|
210 let green = lerp(target.green(), source.green(), source.alpha()); |
|
211 let blue = lerp(target.blue(), source.blue(), source.alpha()); |
|
212 (red as u32) << 0 | (green as u32) << 8 | (blue as u32) << 16 | (alpha as u32) << 24 |
|
213 } |
|
214 |
|
215 fn land_border_pass<'a, T, F>(rows: T, offsets: &mut [u8], border_width: u8, pixel_getter: F) |
|
216 where T: Iterator<Item = (&'a [u8], &'a mut [u32])>, |
|
217 F: (Fn(usize, usize) -> u32) |
|
218 { |
|
219 for (land_row, tex_row) in rows { |
|
220 for (x, ((land_v, tex_v), offset_v)) in land_row.iter() |
|
221 .zip(tex_row.iter_mut()) |
|
222 .zip(offsets.iter_mut()) |
|
223 .enumerate() |
|
224 { |
|
225 *offset_v = if *land_v == 0 { |
|
226 if *offset_v < border_width { |
|
227 *tex_v = blend( |
|
228 pixel_getter(x, *offset_v as usize), |
|
229 *tex_v, |
|
230 ) |
|
231 } |
|
232 offset_v.saturating_add(1) |
|
233 } else { |
|
234 0 |
|
235 } |
|
236 } |
140 } |
237 } |
141 } |
238 } |
142 |
239 |
143 fn tex_row_copy(land_row: &[u8], tex_row: &mut [u32], sprite_row: &[u32]) { |
240 fn tex_row_copy(land_row: &[u8], tex_row: &mut [u32], sprite_row: &[u32]) { |
144 for ((land_v, tex_v), sprite_v) in |
241 for ((land_v, tex_v), sprite_v) in |