forked from StrafesNET/strafe-project
117 lines
3.5 KiB
Rust
117 lines
3.5 KiB
Rust
use std::collections::HashMap;
|
|
use crate::loader::Loader;
|
|
use crate::mesh::Meshes;
|
|
use crate::texture::{RenderConfigs,Texture};
|
|
use strafesnet_common::model::{Mesh,MeshId,RenderConfig,RenderConfigId,TextureId};
|
|
|
|
#[derive(Clone,Copy,Debug)]
|
|
pub enum LoadFailureMode{
|
|
DefaultToNone,
|
|
Fatal,
|
|
}
|
|
|
|
pub struct RenderConfigDeferredLoader<H>{
|
|
texture_count:u32,
|
|
render_configs:Vec<RenderConfig>,
|
|
render_config_id_from_asset_id:HashMap<Option<H>,RenderConfigId>,
|
|
}
|
|
impl<H> RenderConfigDeferredLoader<H>{
|
|
pub fn new()->Self{
|
|
Self{
|
|
texture_count:0,
|
|
render_configs:Vec::new(),
|
|
render_config_id_from_asset_id:HashMap::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<H:core::hash::Hash+Eq> RenderConfigDeferredLoader<H>{
|
|
pub fn acquire_render_config_id(&mut self,index:Option<H>)->RenderConfigId{
|
|
let some_texture=index.is_some();
|
|
*self.render_config_id_from_asset_id.entry(index).or_insert_with(||{
|
|
//create the render config.
|
|
let render_config=if some_texture{
|
|
let render_config=RenderConfig::texture(TextureId::new(self.texture_count));
|
|
self.texture_count+=1;
|
|
render_config
|
|
}else{
|
|
RenderConfig::default()
|
|
};
|
|
let render_id=RenderConfigId::new(self.render_configs.len() as u32);
|
|
self.render_configs.push(render_config);
|
|
render_id
|
|
})
|
|
}
|
|
pub fn into_indices(self)->impl Iterator<Item=H>{
|
|
self.render_config_id_from_asset_id.into_keys().flatten()
|
|
}
|
|
pub fn into_render_configs<L:Loader<Resource=Texture,Index=H>>(mut self,loader:&mut L,failure_mode:LoadFailureMode)->Result<RenderConfigs,L::Error>{
|
|
let mut sorted_textures=vec![None;self.texture_count as usize];
|
|
for (index_option,render_config_id) in self.render_config_id_from_asset_id{
|
|
let render_config=&mut self.render_configs[render_config_id.get() as usize];
|
|
if let (Some(index),Some(texture_id))=(index_option,render_config.texture){
|
|
let resource_result=loader.load(index);
|
|
let texture=match failure_mode{
|
|
// if texture fails to load, use no texture
|
|
LoadFailureMode::DefaultToNone=>match resource_result{
|
|
Ok(texture)=>Some(texture),
|
|
Err(e)=>{
|
|
render_config.texture=None;
|
|
println!("Error loading texture: {e}");
|
|
None
|
|
},
|
|
},
|
|
// loading failure is fatal
|
|
LoadFailureMode::Fatal=>Some(resource_result?)
|
|
};
|
|
sorted_textures[texture_id.get() as usize]=texture;
|
|
}
|
|
}
|
|
Ok(RenderConfigs::new(
|
|
sorted_textures,
|
|
self.render_configs,
|
|
))
|
|
}
|
|
}
|
|
|
|
pub struct MeshDeferredLoader<H>{
|
|
mesh_id_from_asset_id:HashMap<H,MeshId>,
|
|
}
|
|
impl<H> MeshDeferredLoader<H>{
|
|
pub fn new()->Self{
|
|
Self{
|
|
mesh_id_from_asset_id:HashMap::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<H:core::hash::Hash+Eq> MeshDeferredLoader<H>{
|
|
pub fn acquire_mesh_id(&mut self,index:H)->MeshId{
|
|
let mesh_id=MeshId::new(self.mesh_id_from_asset_id.len() as u32);
|
|
*self.mesh_id_from_asset_id.entry(index).or_insert(mesh_id)
|
|
}
|
|
pub fn into_indices(self)->impl Iterator<Item=H>{
|
|
self.mesh_id_from_asset_id.into_keys()
|
|
}
|
|
pub fn into_meshes<L:Loader<Resource=Mesh,Index=H>>(self,loader:&mut L,failure_mode:LoadFailureMode)->Result<Meshes,L::Error>{
|
|
let mut mesh_list=vec![None;self.mesh_id_from_asset_id.len()];
|
|
for (index,mesh_id) in self.mesh_id_from_asset_id{
|
|
let resource_result=loader.load(index);
|
|
let mesh=match failure_mode{
|
|
// if mesh fails to load, use no mesh
|
|
LoadFailureMode::DefaultToNone=>match resource_result{
|
|
Ok(mesh)=>Some(mesh),
|
|
Err(e)=>{
|
|
println!("Error loading mesh: {e}");
|
|
None
|
|
},
|
|
},
|
|
// loading failure is fatal
|
|
LoadFailureMode::Fatal=>Some(resource_result?)
|
|
};
|
|
mesh_list[mesh_id.get() as usize]=mesh;
|
|
}
|
|
Ok(Meshes::new(mesh_list))
|
|
}
|
|
}
|