172 |
172 |
173 pub fn insert_sprite(&mut self, size: Size) -> bool { |
173 pub fn insert_sprite(&mut self, size: Size) -> bool { |
174 if !self.texture_size.contains(size) { |
174 if !self.texture_size.contains(size) { |
175 false |
175 false |
176 } else { |
176 } else { |
177 if let Some(rect) = self |
177 if let Some(rect) = self.atlases.iter_mut().find_map(|a| a.insert(size)) { |
178 .atlases |
|
179 .iter_mut() |
|
180 .find_map(|a| a.insert(size)) |
|
181 { |
|
182 |
178 |
183 } else if !self.repack(size) { |
179 } else if !self.repack(size) { |
184 let mut atlas = Atlas::new(self.texture_size); |
180 let mut atlas = Atlas::new(self.texture_size); |
185 atlas.insert(size); |
181 atlas.insert(size); |
186 self.atlases.push(atlas); |
182 self.atlases.push(atlas); |
215 |
211 |
216 #[cfg(test)] |
212 #[cfg(test)] |
217 mod tests { |
213 mod tests { |
218 use super::Atlas; |
214 use super::Atlas; |
219 use integral_geometry::{Rect, Size}; |
215 use integral_geometry::{Rect, Size}; |
|
216 use proptest::prelude::*; |
220 |
217 |
221 #[test] |
218 #[test] |
222 fn insert() { |
219 fn insert() { |
223 let atlas_size = Size::square(16); |
220 let atlas_size = Size::square(16); |
224 let mut atlas = Atlas::new(atlas_size); |
221 let mut atlas = Atlas::new(atlas_size); |
225 |
222 |
226 assert_eq!(None, atlas.insert(Size::square(20))); |
223 assert_eq!(None, atlas.insert(Size::square(20))); |
227 |
224 |
228 let rect_size = Size::new(11, 3); |
225 let rect_size = Size::new(11, 3); |
229 let rect = atlas.insert(rect_size).unwrap(); |
226 let rect = atlas.insert(rect_size).unwrap(); |
|
227 |
230 assert_eq!(rect, Rect::at_origin(rect_size)); |
228 assert_eq!(rect, Rect::at_origin(rect_size)); |
231 assert_eq!(2, atlas.free_rects.len()); |
229 assert_eq!(2, atlas.free_rects.len()); |
232 } |
230 } |
233 } |
231 |
|
232 #[derive(Debug, Clone)] |
|
233 struct TestRect(Size); |
|
234 struct TestRectParameters(Size); |
|
235 |
|
236 impl Default for TestRectParameters { |
|
237 fn default() -> Self { |
|
238 Self(Size::square(64)) |
|
239 } |
|
240 } |
|
241 |
|
242 impl Arbitrary for TestRect { |
|
243 type Parameters = TestRectParameters; |
|
244 |
|
245 fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { |
|
246 (1..=args.0.width, 1..=args.0.height) |
|
247 .prop_map(|(w, h)| TestRect(Size::new(w, h))) |
|
248 .boxed() |
|
249 } |
|
250 |
|
251 type Strategy = BoxedStrategy<TestRect>; |
|
252 } |
|
253 |
|
254 trait HasSize { |
|
255 fn size(&self) -> Size; |
|
256 } |
|
257 |
|
258 impl HasSize for TestRect { |
|
259 fn size(&self) -> Size { |
|
260 self.0 |
|
261 } |
|
262 } |
|
263 |
|
264 impl HasSize for Rect { |
|
265 fn size(&self) -> Size { |
|
266 self.size() |
|
267 } |
|
268 } |
|
269 |
|
270 fn sum_area<S: HasSize>(items: &[S]) -> usize { |
|
271 items.iter().map(|s| s.size().area()).sum() |
|
272 } |
|
273 |
|
274 proptest! { |
|
275 #[test] |
|
276 fn prop_insert(rects in Vec::<TestRect>::arbitrary()) { |
|
277 let mut atlas = Atlas::new(Size::square(2048)); |
|
278 let inserted: Vec<_> = rects.iter().take_while(|TestRect(size)| atlas.insert(*size).is_some()).cloned().collect(); |
|
279 |
|
280 assert_eq!(inserted.len(), atlas.used_rects.len()); |
|
281 assert_eq!(sum_area(&inserted), sum_area(&atlas.used_rects)); |
|
282 } |
|
283 } |
|
284 } |