diff --git a/src/main.rs b/src/main.rs index 8dfd44a..bab609d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1047,43 +1047,115 @@ fn write_attributes() -> AResult<()>{ fn extract_textures(paths:Vec,vpk_path:std::path::PathBuf)->AResult<()>{ let vpk_index=vpk::VPK::read(&vpk_path)?; - let mut deduplicate=std::collections::HashSet::new(); for path in paths{ + let mut deduplicate=std::collections::HashSet::new(); let bsp=vbsp::Bsp::read(std::fs::read(path)?.as_ref())?; for texture in bsp.textures(){ - let texture_name=texture.texture_data().name(); - let texture_file_name=format!("materials/{}.vtf",texture_name.to_lowercase()); - if !deduplicate.insert(texture_file_name.clone()){ - continue; - } - println!("texture_name={}",texture_file_name); - if let Some(stuff)=vpk_index.tree.get(texture_file_name.as_str()){ - let image=vtf::from_bytes(&mut stuff.get()?.to_vec())?.highres_image.decode(0)?.to_rgba8(); - - let format=if image.width()%4!=0||image.height()%4!=0{ - image_dds::ImageFormat::R8G8B8A8Srgb - }else{ - image_dds::ImageFormat::BC7Srgb - }; - //this fails if the image dimensions are not a multiple of 4 - let dds = image_dds::dds_from_image( - &image, - format, - image_dds::Quality::Slow, - image_dds::Mipmaps::GeneratedAutomatic, - )?; - - //write dds - let mut dest=std::path::PathBuf::from("textures/dds"); - dest.push(texture_name); - dest.set_extension("dds"); - std::fs::create_dir_all(dest.parent().unwrap())?; - let mut writer = std::io::BufWriter::new(std::fs::File::create(dest)?); - dds.write(&mut writer)?; - }else{ - println!("nonadat"); - } + deduplicate.insert(std::path::PathBuf::from(texture.name())); } + let mut zippyt=bsp.pack.into_zip().into_inner().unwrap(); + let tree=&vpk_index.tree; + std::thread::scope(move|s|{ + for texture_name in deduplicate{ + let mut texture_file_name=std::path::PathBuf::from("materials"); + //lower case + let texture_file_name_lowercase=texture_name.to_string_lossy().to_lowercase(); + texture_file_name.push(texture_file_name_lowercase.clone()); + //remove stem and search for both vtf and vmt files + let stem=std::path::PathBuf::from(texture_file_name.file_stem().unwrap()); + texture_file_name.pop(); + texture_file_name.push(stem); + //somehow search for both files + let mut texture_file_name2=texture_file_name.clone(); + texture_file_name.set_extension("vtf"); + texture_file_name2.set_extension("vmt"); + println!("texture_name={:?}",texture_file_name); + let mut found_texture=false; + //why can't I write a function for this without importing the ZipArchive lib + { + if let Some(mut stuff)=match (zippyt.by_name(texture_file_name.to_str().unwrap()),tree.get(texture_file_name.to_str().unwrap())){ + (Ok(mut zip_file),None)=>{ + let mut buf=Vec::new(); + zip_file.read_to_end(&mut buf)?; + Some(buf) + }, + (_,Some(vpk_entry))=>Some(vpk_entry.get()?.to_vec()), + _=>None, + }{ + found_texture=true; + let texture_name=texture_name.clone(); + s.spawn(move||{ + let image=vtf::from_bytes(&mut stuff)?.highres_image.decode(0)?.to_rgba8(); + + let format=if image.width()%4!=0||image.height()%4!=0{ + image_dds::ImageFormat::R8G8B8A8Srgb + }else{ + image_dds::ImageFormat::BC7Srgb + }; + //this fails if the image dimensions are not a multiple of 4 + let dds = image_dds::dds_from_image( + &image, + format, + image_dds::Quality::Slow, + image_dds::Mipmaps::GeneratedAutomatic, + )?; + + //write dds + let mut dest=std::path::PathBuf::from("textures/dds"); + dest.push(texture_name); + dest.set_extension("dds"); + std::fs::create_dir_all(dest.parent().unwrap())?; + let mut writer = std::io::BufWriter::new(std::fs::File::create(dest)?); + dds.write(&mut writer)?; + Ok::<(),anyhow::Error>(()) + }); + } + } + { + if let Some(mut stuff)=match (zippyt.by_name(texture_file_name2.to_str().unwrap()),tree.get(texture_file_name2.to_str().unwrap())){ + (Ok(mut zip_file),None)=>{ + let mut buf=Vec::new(); + zip_file.read_to_end(&mut buf)?; + Some(buf) + }, + (_,Some(vpk_entry))=>Some(vpk_entry.get()?.to_vec()), + _=>None, + }{ + found_texture=true; + let texture_name=texture_name.clone(); + s.spawn(move||{ + let image=vtf::from_bytes(&mut stuff)?.highres_image.decode(0)?.to_rgba8(); + + let format=if image.width()%4!=0||image.height()%4!=0{ + image_dds::ImageFormat::R8G8B8A8Srgb + }else{ + image_dds::ImageFormat::BC7Srgb + }; + //this fails if the image dimensions are not a multiple of 4 + let dds = image_dds::dds_from_image( + &image, + format, + image_dds::Quality::Slow, + image_dds::Mipmaps::GeneratedAutomatic, + )?; + + //write dds + let mut dest=std::path::PathBuf::from("textures/dds"); + dest.push(texture_name); + dest.set_extension("dds"); + std::fs::create_dir_all(dest.parent().unwrap())?; + let mut writer = std::io::BufWriter::new(std::fs::File::create(dest)?); + dds.write(&mut writer)?; + Ok::<(),anyhow::Error>(()) + }); + } + } + if !found_texture{ + println!("no data"); + } + } + Ok::<(),anyhow::Error>(()) + })? } Ok(()) }