use std::collections::HashMap;
use std::sync::Arc;
use glam::Vec2;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use tracing::warn;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum TextureChannel {
R,
G,
B,
A,
}
pub trait Texture: Send + Sync {
fn sample(&self, channel: TextureChannel, p: Vec2) -> f32;
}
#[non_exhaustive]
pub struct TextureRegistry {
textures: HashMap<String, Arc<dyn Texture>>,
}
impl TextureRegistry {
pub fn new() -> Self {
Self {
textures: HashMap::new(),
}
}
pub fn with_capacity(n: usize) -> Self {
Self {
textures: HashMap::with_capacity(n),
}
}
pub fn len(&self) -> usize {
self.textures.len()
}
pub fn is_empty(&self) -> bool {
self.textures.is_empty()
}
pub fn clear(&mut self) {
self.textures.clear();
}
pub fn register<T>(&mut self, id: impl Into<String>, texture: T)
where
T: Texture + 'static,
{
self.textures.insert(id.into(), Arc::new(texture));
}
pub fn register_arc(&mut self, id: impl Into<String>, texture: Arc<dyn Texture + 'static>) {
self.textures.insert(id.into(), texture);
}
pub fn extend_from(&mut self, other: &TextureRegistry) {
for (k, v) in other.textures.iter() {
self.textures.insert(k.clone(), v.clone());
}
}
pub fn unregister(&mut self, id: &str) -> bool {
self.textures.remove(id).is_some()
}
pub fn contains(&self, id: &str) -> bool {
self.textures.contains_key(id)
}
pub fn get(&self, id: &str) -> Option<Arc<dyn Texture>> {
self.textures.get(id).cloned()
}
#[inline]
pub fn sample(&self, texture_id: &str, channel: TextureChannel, p: Vec2) -> f32 {
if let Some(tex) = self.textures.get(texture_id) {
tex.sample(channel, p)
} else {
warn!("Unknown texture id '{}'.", texture_id);
0.0
}
}
}
impl Default for TextureRegistry {
fn default() -> Self {
Self::new()
}
}