despero 0.1.0

Rusty game engine, using API Vulkan and implementing paradigm of ECS
Documentation
use std::sync::Arc;
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
use serde::{Serialize, Deserialize};
use ash::vk;

use crate::render::*;

#[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub struct AssetHandle(usize);

impl AssetHandle {
    pub fn new() -> Self {
        AssetHandle::default()
    }
    
    pub fn from_index(index: usize) -> Self {
        AssetHandle(index)
    }
    
    pub fn invalid() -> Self {
        AssetHandle(usize::MAX)
    }
    
    pub fn unwrap(&self) -> usize {
        self.0
    }
    
    pub fn append(&mut self, count: usize) {
        self.0 += count;
    }
}

impl From<AssetHandle> for u32 {
    fn from(value: AssetHandle) -> Self {
        value.unwrap() as u32
    }
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct AssetManager {
    pub textures: Vec<Texture>,
    pub materials: Vec<Arc<Mutex<Box<dyn Material>>>>,
}

impl AssetManager {
    pub fn new() -> Self {
        AssetManager::default()
    }
    
    pub fn create_texture(
        &mut self,
        path: &'static str,
        filter: Filter,
    ) -> AssetHandle {
        let new_texture = Texture::new_blank(
            path,
            filter,
        );
        
        let new_id = self.textures.len();
        self.textures.push(new_texture);
        AssetHandle(new_id)
    }
    
    pub fn create_material<M: Material + Send + Sync>(
        &mut self,
        material: M,
    ) -> AssetHandle {
        let index = self.materials.len();
        self.materials.push(Arc::new(Mutex::new(Box::new(material))));
        AssetHandle(index)
    }
    
    pub fn get_texture(&self, handle: AssetHandle) -> Option<&Texture> {
        self.textures.get(handle.0)
    }
    
    pub fn get_texture_mut(&mut self, handle: AssetHandle) -> Option<&mut Texture> {
        self.textures.get_mut(handle.0)
    }

    pub fn get_material(&self, handle: AssetHandle) -> Option<MutexGuard<Box<dyn Material>>> {
        if let Some(material) = self.materials.get(handle.0) {
            return Some(material.lock());  
        }

        None
    }
    
    pub fn get_material_downcast<M: Material>(&self, handle: AssetHandle) -> Option<MappedMutexGuard<M>> {
        if let Some(material) = self.materials.get(handle.0) {
            let data = material.lock();
            return MutexGuard::try_map(data, |data| {
                data.as_any_mut().downcast_mut::<M>()
            }).ok()            
        }

        None
    }
    
    pub fn append(&mut self, other: Self) {
        self.textures.extend(other.textures);
        self.materials.extend(other.materials);
    }
    
    pub fn descriptor_image_info(&self) -> Vec<vk::DescriptorImageInfo> {
        self.textures
            .iter()
            .filter_map(|t| {
                if let (Some(image_view), Some(sampler)) = (t.imageview, t.sampler) {
                    Some(
                        vk::DescriptorImageInfo {
                            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
                            image_view,
                            sampler,
                            ..Default::default()
                        }
                    )
                } else {
                    None
                }
            })
            .collect()
    }
    
    pub fn cleanup(
        &mut self,
        renderer: &mut Renderer,
    ){
        for texture in &mut self.textures {
            texture.cleanup(renderer);
        }
        
        self.textures.clear();
        self.materials.clear();
    }    
}