diff options
| author | Micha White <botahamec@outlook.com> | 2024-08-15 20:14:15 -0400 |
|---|---|---|
| committer | Micha White <botahamec@outlook.com> | 2024-08-15 20:14:15 -0400 |
| commit | f8a80039c74332e2101a177ef3fde31ef2077224 (patch) | |
| tree | f887c96bf9879a28b7ce914ad96161f63ee83190 /textures/src/lib.rs | |
| parent | 488c7ed94b0662222fa0d825ab81b60b0b1e5d6c (diff) | |
Lots a changes
Diffstat (limited to 'textures/src/lib.rs')
| -rw-r--r-- | textures/src/lib.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/textures/src/lib.rs b/textures/src/lib.rs new file mode 100644 index 0000000..c1b56a8 --- /dev/null +++ b/textures/src/lib.rs @@ -0,0 +1,96 @@ +use std::collections::HashMap; +use std::path::Path; +use std::sync::Arc; + +use exun::{RawUnexpected, ResultErrorExt}; +use image::RgbaImage; +use packer::{RectanglePacker, TextureAtlas}; + +type ExunResult<T> = Result<T, RawUnexpected>; + +pub struct TextureManager { + textures: HashMap<Arc<str>, TextureMetadata>, + loaded_textures: HashMap<Arc<str>, Arc<RgbaImage>>, + packer: RectanglePacker, + target_size: usize, + current_size: usize, +} + +struct TextureMetadata { + path: Arc<Path>, + size: usize, +} + +impl TextureManager { + pub fn new(target_size: usize) -> Self { + Self { + textures: HashMap::new(), + loaded_textures: HashMap::new(), + packer: RectanglePacker::new(), + target_size, + current_size: 0, + } + } + + pub fn add_texture(&mut self, name: Arc<str>, path: Arc<Path>, size: usize) { + self.textures.insert(name, TextureMetadata { path, size }); + } + + pub fn try_preload(&mut self, name: Arc<str>) -> ExunResult<Option<bool>> { + let Some(metadata) = self.textures.get(&name) else { + return Ok(None); + }; + + if self.current_size + metadata.size < self.target_size { + self.load(name)?; + Ok(Some(true)) + } else { + Ok(Some(false)) + } + } + + pub fn load(&mut self, name: Arc<str>) -> ExunResult<Option<()>> { + let Some(metadata) = self.textures.get(&name) else { + return Ok(None); + }; + + self.current_size += metadata.size; + let texture = image::open(&metadata.path).unexpect()?.to_rgba8(); + self.loaded_textures.insert(name, Arc::new(texture)); + + Ok(Some(())) + } + + pub fn unload(&mut self, name: Arc<str>) -> Option<()> { + self.loaded_textures.remove(&name)?; + Some(()) + } + + pub fn pack_texture(&mut self, name: Arc<str>) -> ExunResult<()> { + if !self.loaded_textures.contains_key(&name) { + self.load(name.clone())?; + } + + self.packer.add_texture( + name.clone(), + self.loaded_textures + .get(&name) + .expect("we checked to make sure it was loaded") + .clone(), + ); + + Ok(()) + } + + pub fn reset_packer(&mut self) { + self.packer = RectanglePacker::new(); + } + + pub fn reload_texture_atlas( + &mut self, + min_width: u32, + min_height: u32, + ) -> ExunResult<TextureAtlas> { + self.packer.output(min_width, min_height) + } +} |
