use std::io::Read; use std::collections::HashMap; use crate::valve_mesh; use crate::texture::{Texture,RenderConfigs}; use strafesnet_common::model::{MeshId,TextureId,RenderConfig,RenderConfigId}; pub struct RenderConfigLoader{ texture_count:u32, render_configs:Vec, texture_paths:HashMap>,RenderConfigId>, } impl RenderConfigLoader{ pub fn acquire_render_config_id(&mut self,name:Option<&str>)->RenderConfigId{ let render_id=RenderConfigId::new(self.texture_paths.len() as u32); *self.texture_paths.entry(name.map(Into::into)).or_insert_with(||{ //create the render config. let render_config=if name.is_some(){ let render_config=RenderConfig::texture(TextureId::new(self.texture_count)); self.texture_count+=1; render_config }else{ RenderConfig::default() }; self.render_configs.push(render_config); render_id }) } } pub struct MeshLoader{ mesh_paths:HashMap,MeshId>, } impl MeshLoader{ pub fn acquire_mesh_id(&mut self,name:&str)->MeshId{ let mesh_id=MeshId::new(self.mesh_paths.len() as u32); *self.mesh_paths.entry(name.into()).or_insert(mesh_id) } //load_meshes should look like load_textures pub fn load_meshes(&mut self,bsp:&vbsp::Bsp)->valve_mesh::Meshes{ let mut mesh_data=vec![None;self.mesh_paths.len()]; for (mesh_path,mesh_id) in &self.mesh_paths{ let mesh_path_lower=mesh_path.to_lowercase(); //.mdl, .vvd, .dx90.vtx let path=std::path::PathBuf::from(mesh_path_lower.as_str()); let mut vvd_path=path.clone(); let mut vtx_path=path.clone(); vvd_path.set_extension("vvd"); vtx_path.set_extension("dx90.vtx"); match (bsp.pack.get(mesh_path_lower.as_str()),bsp.pack.get(vvd_path.as_os_str().to_str().unwrap()),bsp.pack.get(vtx_path.as_os_str().to_str().unwrap())){ (Ok(Some(mdl_file)),Ok(Some(vvd_file)),Ok(Some(vtx_file)))=>{ mesh_data[mesh_id.get() as usize]=Some(valve_mesh::ModelData{ mdl:valve_mesh::MdlData::new(mdl_file), vtx:valve_mesh::VtxData::new(vtx_file), vvd:valve_mesh::VvdData::new(vvd_file), }); }, _=>println!("no model name={}",mesh_path), } } valve_mesh::Meshes::new(mesh_data) } } pub struct Loader{ render_config_loader:RenderConfigLoader, mesh_loader:MeshLoader, } impl Loader{ pub fn new()->Self{ Self{ render_config_loader:RenderConfigLoader{ texture_count:0, texture_paths:HashMap::new(), render_configs:Vec::new(), }, mesh_loader:MeshLoader{mesh_paths:HashMap::new()}, } } pub fn get_inner_mut(&mut self)->(&mut RenderConfigLoader,&mut MeshLoader){ (&mut self.render_config_loader,&mut self.mesh_loader) } pub fn into_render_configs(mut self)->Result{ let mut sorted_textures=vec![None;self.render_config_loader.texture_count as usize]; for (texture_path,render_config_id) in self.render_config_loader.texture_paths{ let render_config=self.render_config_loader.render_configs.get_mut(render_config_id.get() as usize).unwrap(); if let (Some(texture_path),Some(texture_id))=(texture_path,render_config.texture){ if let Ok(mut file)=std::fs::File::open(format!("textures/{}.dds",texture_path)){ //TODO: parallel let mut data=Vec::::new(); file.read_to_end(&mut data)?; sorted_textures[texture_id.get() as usize]=Some(Texture::ImageDDS(data)); }else{ //texture failed to load render_config.texture=None; } } } Ok(RenderConfigs::new( sorted_textures, self.render_config_loader.render_configs, )) } }