summaryrefslogtreecommitdiff
path: root/alligator_resources/src
diff options
context:
space:
mode:
Diffstat (limited to 'alligator_resources/src')
-rw-r--r--alligator_resources/src/texture.rs136
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
- }*/
}