diff options
| author | Micha White <botahamec@outlook.com> | 2023-02-05 10:28:43 -0500 |
|---|---|---|
| committer | Micha White <botahamec@outlook.com> | 2023-02-05 10:28:43 -0500 |
| commit | 4b789a715cf7b42f5ae282b8218976fd577664be (patch) | |
| tree | 91b17110d2928f56e146e3308cbdd944bbaf5c69 /alligator_resources/src/texture.rs | |
| parent | 9fd7d6689d5d90679e4b0c12e463ef4e2f8bf515 (diff) | |
Move texture atlas out of alligator_resources
Diffstat (limited to 'alligator_resources/src/texture.rs')
| -rw-r--r-- | alligator_resources/src/texture.rs | 136 |
1 files changed, 15 insertions, 121 deletions
diff --git a/alligator_resources/src/texture.rs b/alligator_resources/src/texture.rs index e5b4147..3a5bf3e 100644 --- a/alligator_resources/src/texture.rs +++ b/alligator_resources/src/texture.rs @@ -1,6 +1,5 @@ use std::cmp::Reverse; -use std::collections::HashMap; -use std::mem::{self}; +use std::mem; use std::path::Path; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::Arc; @@ -8,8 +7,6 @@ use std::sync::Arc; use dashmap::DashMap; use image::ImageBuffer; use parking_lot::Mutex; -use texture_packer::exporter::ImageExporter; -use texture_packer::{Frame, TexturePacker, TexturePackerConfig}; use thiserror::Error; use crate::Priority; @@ -76,7 +73,7 @@ fn convert_image_load_error(e: image::ImageError) -> LoadError { } } -type Rgba16Texture = image::ImageBuffer<image::Rgba<u16>, Box<[u16]>>; +pub type Rgba16Texture = image::ImageBuffer<image::Rgba<u16>, Box<[u16]>>; fn vec_image_to_box(vec_image: image::ImageBuffer<image::Rgba<u16>, Vec<u16>>) -> Rgba16Texture { let width = vec_image.width(); @@ -238,116 +235,18 @@ impl Texture { } } -pub struct TextureAtlas<'a> { - width: u32, - height: u32, - packer: TexturePacker<'a, Rgba16Texture, TextureId>, -} - -impl<'a> TextureAtlas<'a> { - fn new(width: u32, height: u32, textures: &HashMap<TextureId, Texture>) -> Self { - profiling::scope!("new atlas"); - - let mut packer = TexturePacker::new_skyline(TexturePackerConfig { - max_width: width, - max_height: height, - allow_rotation: false, - trim: false, - texture_padding: 0, - ..Default::default() - }); - - for (id, texture) in textures { - if texture.is_loaded() { - let texture = texture - .loaded_texture() - .expect("texture couldn't be loaded"); - - // if the textures don't fit, make a bigger packer - if packer.pack_own(*id, texture.clone()).is_err() { - return Self::new(width * 2, height * 2, textures); - } - } - } - - Self { - width, - height, - packer, - } - } - - fn subtexture(&self, id: TextureId) -> Option<&Frame<TextureId>> { - self.packer.get_frame(&id) - } - - #[must_use] - pub const fn atlas_width(&self) -> u32 { - self.width - } - - #[must_use] - pub const fn atlas_height(&self) -> u32 { - self.height - } - - /// Get the x-position of a texture, if it is in the texture atlas - #[must_use] - #[allow(clippy::cast_precision_loss)] // TODO remove this - pub fn subtexture_x(&self, id: TextureId) -> Option<f32> { - let x = self.subtexture(id)?.frame.x; - Some(x as f32 / self.width as f32) - } - - /// Get the y-position of a texture, if it is in the texture atlas - #[must_use] - #[allow(clippy::cast_precision_loss)] // TODO remove this - pub fn subtexture_y(&self, id: TextureId) -> Option<f32> { - let y = self.subtexture(id)?.frame.y; - Some(y as f32 / self.height as f32) - } - - /// Get the width of a texture, if it is in the texture atlas - #[must_use] - #[allow(clippy::cast_precision_loss)] // TODO remove this - pub fn subtexture_width(&self, id: TextureId) -> Option<f32> { - let width = self.subtexture(id)?.frame.w; - Some(width as f32 / self.width as f32) - } - - /// Get the height of a texture, if it is in the texture atlas - #[must_use] - #[allow(clippy::cast_precision_loss)] // TODO remove this - pub fn subtexture_height(&self, id: TextureId) -> Option<f32> { - let height = self.subtexture(id)?.frame.h; - Some(height as f32 / self.height as f32) - } - - #[must_use] - pub fn to_texture(&self) -> Rgba16Texture { - profiling::scope!("export atlas"); - vec_image_to_box( - ImageExporter::export(&self.packer) - .expect("ImageExporter error?") - .into_rgba16(), - ) - } -} - pub struct TextureManager { textures: DashMap<TextureId, Texture>, max_size: usize, - atlas_width: u32, - atlas_height: u32, needs_atlas_update: AtomicBool, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TextureManagerConfig { + /// The initial capacity of the texture manager. This defaults to 500 textures. pub initial_capacity: usize, + /// The maximum amount of heap usage acceptable. Defaults to 10 MiB. pub max_size: usize, - pub atlas_width: u32, - pub atlas_height: u32, } impl Default for TextureManagerConfig { @@ -355,8 +254,6 @@ impl Default for TextureManagerConfig { Self { initial_capacity: 500, max_size: 10 * 1024 * 1024, // 10 MiB - atlas_width: 3980, - atlas_height: 2160, // 4K resolution } } } @@ -370,8 +267,6 @@ impl TextureManager { Self { textures, max_size: config.max_size, - atlas_width: config.atlas_width, - atlas_height: config.atlas_height, needs_atlas_update: AtomicBool::new(false), } } @@ -408,7 +303,7 @@ impl TextureManager { /// This returns `Expected(DecodingError)` if the given buffer was invalid /// for the given format. pub fn load_from_memory( - &mut self, + &self, buf: &[u8], format: ImageFormat, ) -> Result<TextureId, DecodingError> { @@ -432,7 +327,7 @@ impl TextureManager { /// This returns an error if `priority` is set to [`Priority::Urgent`] but /// there was an error in loading the file to a texture. pub fn load_from_file( - &mut self, + &self, path: impl AsRef<Path>, priority: Priority, ) -> Result<TextureId, LoadError> { @@ -463,7 +358,7 @@ impl TextureManager { /// /// This returns an error if `priority` is set to [`Priority::Urgent`] but /// there was an error in loading the file to a texture. - pub fn set_priority(&mut self, id: TextureId, priority: Priority) -> Result<(), LoadError> { + pub fn set_priority(&self, id: TextureId, priority: Priority) -> Result<(), LoadError> { let mut texture = self.textures.get_mut(&id).expect("invalid texture id"); texture.set_priority(priority); @@ -478,10 +373,17 @@ impl TextureManager { /// This returns `true` if a texture has been set to have an urgent /// priority since the last time this function was called. - pub fn needs_atlas_update(&mut self) -> bool { + pub fn needs_atlas_update(&self) -> bool { self.needs_atlas_update.fetch_and(false, Ordering::AcqRel) } + /// Load a texture into memory, if it hasn't been already. Then return a + /// copy of the texture. + /// + /// # Errors + /// + /// This returns an error if an error occurs in loading the texture from + /// disk, such as the file not existing, or not being a valid texture. pub fn load_texture(&self, id: TextureId) -> Result<Rgba16Texture, LoadError> { self.textures .get_mut(&id) @@ -489,12 +391,4 @@ impl TextureManager { .load_texture() .cloned() } - - // Create a texture atlas - /*pub fn atlas(&mut self) -> TextureAtlas<'_> { - let atlas = TextureAtlas::new(self.atlas_width, self.atlas_height, &self.textures); - self.atlas_width = atlas.atlas_width(); - self.atlas_height = atlas.atlas_height(); - atlas - }*/ } |
