use std::io::Read; use std::collections::HashMap; use crate::texture::{Texture,RenderConfigs}; use strafesnet_common::model::{TextureId,RenderConfigId,RenderConfig}; #[derive(Hash,Eq,PartialEq)] struct RobloxAssetId(u64); #[derive(Debug)] pub struct RobloxAssetIdParseErr(String); impl std::str::FromStr for RobloxAssetId{ type Err=RobloxAssetIdParseErr; fn from_str(s:&str)->Result{ let regman=lazy_regex::regex!(r"(\d+)$"); if let Some(captures)=regman.captures(s){ if captures.len()==2{//captures[0] is all captures concatenated, and then each individual capture if let Ok(id)=captures[0].parse::(){ return Ok(Self(id)); } } } Err(RobloxAssetIdParseErr(s.to_owned())) } } impl std::fmt::Display for RobloxAssetIdParseErr{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ write!(f,"{self:?}") } } impl std::error::Error for RobloxAssetIdParseErr{} pub struct Loader{ 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{ 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|{ match name.parse::(){ Ok(asset_id)=>Some(asset_id), Err(e)=>{ println!("Failed to parse AssetId: {e}"); None }, } }); *self.render_config_id_from_asset_id.entry(index).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 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){ if let Ok(mut file)=std::fs::File::open(format!("textures/{}.dds",asset_id.0)){ //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_configs, )) } }