diff --git a/src/lib.rs b/src/lib.rs index 4fed855..c8b5e99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,10 @@ mod roblox; mod source; pub mod texture; +#[cfg(any(feature="source",feature="legacy"))] pub mod valve_mesh; +#[cfg(any(feature="roblox",feature="legacy"))] +pub mod roblox_mesh; #[cfg(feature="legacy")] pub fn roblox_legacy()->roblox_legacy::Loader{ diff --git a/src/roblox_legacy.rs b/src/roblox_legacy.rs index d4f70a2..9da167e 100644 --- a/src/roblox_legacy.rs +++ b/src/roblox_legacy.rs @@ -1,7 +1,8 @@ use std::io::Read; use std::collections::HashMap; -use crate::texture::{Texture,RenderConfigs}; -use strafesnet_common::model::{TextureId,RenderConfigId,RenderConfig}; +use crate::roblox_mesh; +use crate::texture::{RenderConfigs,Texture}; +use strafesnet_common::model::{MeshId,RenderConfig,RenderConfigId,TextureId}; #[derive(Hash,Eq,PartialEq)] struct RobloxAssetId(u64); @@ -28,22 +29,14 @@ impl std::fmt::Display for RobloxAssetIdParseErr{ } impl std::error::Error for RobloxAssetIdParseErr{} -pub struct Loader{ +#[derive(Default)] +pub struct RenderConfigLoader{ texture_count:u32, render_configs:Vec, render_config_id_from_asset_id:HashMap,RenderConfigId>, } -impl Loader{ - pub fn new()->Self{ - Self{ - texture_count:0, - render_configs:Vec::new(), - render_config_id_from_asset_id:HashMap::new(), - } - } -} -impl Loader{ +impl RenderConfigLoader{ pub fn acquire_render_config_id(&mut self,name:Option<&str>)->RenderConfigId{ let render_id=RenderConfigId::new(self.render_config_id_from_asset_id.len() as u32); let index=name.and_then(|name|{ @@ -68,11 +61,62 @@ impl Loader{ render_id }) } +} + +#[derive(Default)] +pub struct MeshLoader{ + mesh_id_from_asset_id:HashMap,MeshId>, +} + +impl MeshLoader{ + pub fn acquire_mesh_id(&mut self,name:&str)->MeshId{ + let mesh_id=MeshId::new(self.mesh_id_from_asset_id.len() as u32); + let index=match name.parse::(){ + Ok(asset_id)=>Some(asset_id), + Err(e)=>{ + println!("Failed to parse AssetId: {e}"); + None + }, + }; + *self.mesh_id_from_asset_id.entry(index).or_insert(mesh_id) + } + pub fn load_meshes(&mut self)->Result{ + let mut mesh_data=vec![None;self.mesh_id_from_asset_id.len()]; + for (asset_id_option,mesh_id) in &self.mesh_id_from_asset_id{ + if let Some(asset_id)=asset_id_option{ + if let Ok(mut file)=std::fs::File::open(format!("meshes/{}",asset_id.0)){ + //TODO: parallel + let mut data=Vec::::new(); + file.read_to_end(&mut data)?; + mesh_data[mesh_id.get() as usize]=Some(roblox_mesh::RobloxMeshData::new(data)); + }else{ + println!("no model name={}",asset_id.0); + } + } + } + Ok(roblox_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::default(), + mesh_loader:MeshLoader::default(), + } + } + 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.texture_count as usize]; - for (asset_id,render_config_id) in self.render_config_id_from_asset_id{ - let render_config=self.render_configs.get_mut(render_config_id.get() as usize).unwrap(); - if let (Some(asset_id),Some(texture_id))=(asset_id,render_config.texture){ + let mut sorted_textures=vec![None;self.render_config_loader.texture_count as usize]; + for (asset_id_option,render_config_id) in self.render_config_loader.render_config_id_from_asset_id{ + let render_config=self.render_config_loader.render_configs.get_mut(render_config_id.get() as usize).unwrap(); + if let (Some(asset_id),Some(texture_id))=(asset_id_option,render_config.texture){ if let Ok(mut file)=std::fs::File::open(format!("textures/{}.dds",asset_id.0)){ //TODO: parallel let mut data=Vec::::new(); @@ -86,7 +130,7 @@ impl Loader{ } Ok(RenderConfigs::new( sorted_textures, - self.render_configs, + self.render_config_loader.render_configs, )) } } \ No newline at end of file diff --git a/src/roblox_mesh.rs b/src/roblox_mesh.rs new file mode 100644 index 0000000..cdb545f --- /dev/null +++ b/src/roblox_mesh.rs @@ -0,0 +1,30 @@ +use strafesnet_common::model::MeshId; + +#[derive(Clone)] +pub struct RobloxMeshData(Vec); +impl RobloxMeshData{ + pub(crate) fn new(data:Vec)->Self{ + Self(data) + } + pub fn get(self)->Vec{ + self.0 + } +} +pub struct Meshes{ + meshes:Vec>, +} +impl Meshes{ + pub(crate) const fn new(meshes:Vec>)->Self{ + Self{ + meshes, + } + } + pub fn get_texture(&self,texture_id:MeshId)->Option<&RobloxMeshData>{ + self.meshes.get(texture_id.get() as usize)?.as_ref() + } + pub fn into_iter(self)->impl Iterator{ + self.meshes.into_iter().enumerate().filter_map(|(mesh_id,maybe_mesh)| + maybe_mesh.map(|mesh|(MeshId::new(mesh_id as u32),mesh)) + ) + } +} \ No newline at end of file