use std::collections::HashMap; use std::sync::Arc; #[derive(Debug, Default, Clone)] pub struct SpriteManager { sprites: HashMap, Sprite>, sprite_list: Vec<(u8, Arc)>, } #[derive(Debug, Clone)] pub struct Sprite { texture: Arc, x: f32, y: f32, z: u8, width: f32, height: f32, } impl SpriteManager { pub fn new() -> Self { Self { sprites: HashMap::new(), sprite_list: Vec::new(), } } pub fn with_capacity(capacity: usize) -> Self { Self { sprites: HashMap::with_capacity(capacity), sprite_list: Vec::with_capacity(capacity), } } pub fn add_sprite(&mut self, name: Arc, sprite: Sprite) { let z = sprite.z; self.sprites.insert(name.clone(), sprite); self.sprite_list.push((z, name)); } pub fn clear(&mut self) { self.sprites.clear(); self.sprite_list.clear(); } pub fn remove_sprite(&mut self, name: Arc) { self.sprites.remove(&name); self.sprite_list.retain(|(_, n)| name != n.clone()); } pub fn get_mut_sprite(&mut self, name: &str) -> Option<&mut Sprite> { self.sprites.get_mut(name) } pub fn set_sprite_z(&mut self, name: Arc, new_z: u8) -> Option<()> { let sprite = self.sprites.get_mut(&name)?; sprite.z = new_z; for (depth, n) in &mut self.sprite_list { if n.clone() == name { *depth = new_z; } } Some(()) } fn sort(&mut self) { // in case it's unclear, this is insertion sort // the list is usually already sorted, so this is the most efficient algorithm for i in 0..self.sprite_list.len() { let t = self.sprite_list[i].clone(); let mut j = i; while j > 0 && self.sprite_list[j - 1].0 > t.0 { self.sprite_list[j] = self.sprite_list[j - 1].clone(); j -= 1; } self.sprite_list[j] = t; } } pub fn sorted_sprites(&mut self) -> Vec { self.sort(); let mut sprites = Vec::new(); for (_, sprite) in &self.sprite_list { // i don't like accessing the hashmap every time, but i can't think // of anything better sprites.push(self.sprites[sprite].clone()); } sprites } } impl Sprite { pub fn new(x: f32, y: f32, z: u8, width: f32, height: f32, texture: Arc) -> Self { Self { texture, x, y, z, width, height, } } pub fn x(&self) -> f32 { self.x } pub fn y(&self) -> f32 { self.y } pub fn z(&self) -> u8 { self.z } pub fn width(&self) -> f32 { self.width } pub fn height(&self) -> f32 { self.height } pub fn texture_name(&self) -> &Arc { &self.texture } pub fn set_x(&mut self, x: f32) { self.x = x; } pub fn set_y(&mut self, y: f32) { self.y = y; } pub fn set_width(&mut self, width: f32) { self.width = width; } pub fn set_height(&mut self, height: f32) { self.height = height; } pub fn set_texture(&mut self, texture_name: Arc) { self.texture = texture_name; } }