summaryrefslogtreecommitdiff
path: root/sprites/src/lib.rs
blob: 40a5fe61fba709efd8a1ec04d18abfee46782108 (plain)
use std::collections::HashMap;
use std::sync::Arc;

#[derive(Debug, Default, Clone)]
pub struct SpriteManager {
	sprites: HashMap<Arc<str>, Sprite>,
	sprite_list: Vec<(u8, Arc<str>)>,
}

#[derive(Debug, Clone)]
pub struct Sprite {
	texture: Arc<str>,
	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<str>, 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<str>) {
		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<str>, 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<Sprite> {
		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<str>) -> 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<str> {
		&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<str>) {
		self.texture = texture_name;
	}
}