use crate::ImageSize;
pub struct TexturePacker<T> {
pub textures: Vec<T>,
pub atlas: usize,
pub skyline: Vec<[u32; 2]>,
}
impl<T: ImageSize> TexturePacker<T> {
pub fn new() -> TexturePacker<T> {
TexturePacker {
textures: vec![],
atlas: 0,
skyline: vec![],
}
}
pub fn create(&mut self, size: [u32; 2], texture: T) -> usize {
let id = self.textures.len();
if !self.textures.is_empty() {
self.atlas += 1;
}
self.skyline = vec![[0, size[1]], [size[0], 0]];
self.textures.push(texture);
id
}
pub fn update(&mut self, ind: usize, size: [u32; 2]) -> (usize, [u32; 2]) {
let texture = self.atlas;
let offset = self.skyline[ind];
let mut w = 0;
for i in ind..self.skyline.len() {
if self.skyline[i][1] <= offset[1] {
self.skyline[i][1] = offset[1] + size[1];
}
w = self.skyline[i][0] - offset[0];
if w >= size[1] {
break;
}
}
if w == 0 {
self.skyline.push([offset[0] + size[0], offset[1]]);
self.skyline.sort();
}
(texture, offset)
}
pub fn find_space(&self, size: [u32; 2]) -> Option<usize> {
if self.textures.is_empty() {
return None;
};
let texture = &self.textures[self.atlas];
let mut min: Option<(usize, u32)> = None;
for i in 0..self.skyline.len() {
let a = self.skyline[i];
let mut nxt = [texture.get_width(), texture.get_height()];
for j in i + 1..self.skyline.len() {
let b = self.skyline[j];
nxt[0] = b[0];
if b[1] > a[1] {
break;
};
}
if nxt[0] - a[0] >= size[0] && nxt[1] - a[1] >= size[1] {
if min.is_none()
|| min.unwrap().1 > nxt[0] - a[0]
|| self.skyline[min.unwrap().0][1] > a[1]
{
min = Some((i, nxt[0] - a[0]));
}
}
}
min.map(|n| n.0)
}
}
impl<T: ImageSize> Default for TexturePacker<T> {
fn default() -> TexturePacker<T> {
TexturePacker::new()
}
}