diff --git a/src/main.rs b/src/main.rs index ca96ef8..fce857e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,8 @@ use anyhow::Result as AResult; #[command(author, version, about, long_about = None)] #[command(propagate_version = true)] struct Cli { + #[arg(long)] + vpk_path:Option, #[command(subcommand)] command: Commands, } @@ -14,6 +16,7 @@ struct Cli { enum Commands { Download(MapList), DownloadTextures(PathBufList), + ExtractTextures(PathBufList), ConvertTextures, DownloadMeshes(PathBufList), Extract(PathBufList), @@ -40,6 +43,7 @@ fn main() -> AResult<()> { match cli.command { Commands::Download(map_list)=>download(map_list.maps), Commands::DownloadTextures(pathlist)=>download_textures(pathlist.paths), + Commands::ExtractTextures(pathlist)=>extract_textures(pathlist.paths,cli.vpk_path.unwrap()), Commands::ConvertTextures=>convert_textures(), Commands::DownloadMeshes(pathlist)=>download_meshes(pathlist.paths), Commands::Extract(pathlist)=>extract(pathlist.paths), @@ -1038,3 +1042,57 @@ fn write_attributes() -> AResult<()>{ } Ok(()) } + +fn extract_textures(paths:Vec,vpk_path:std::path::PathBuf)->AResult<()>{ + let vpk_index=vpk::VPK::read(&vpk_path)?; + let mut vpk_cache=std::collections::HashMap::new(); + for path in paths{ + 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); + println!("texture_name={}",texture_file_name); + if let Some(stuff)=vpk_index.tree.get(texture_file_name.as_str()){ + let vpk=if let Some(vpk)=vpk_cache.get(stuff.archive_path.as_str()){ + println!("ayyyy"); + vpk + }else{ + println!("hiii"); + let vpk=vpk::VPK::read(&std::path::PathBuf::from(&stuff.archive_path))?; + println!("hiiiiii"); + vpk_cache.insert(stuff.archive_path.as_str(),vpk); + vpk_cache.get(stuff.archive_path.as_str()).unwrap() + }; + if let Some(stuff)=vpk.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!("zip"); + } + }else{ + println!("nonadat"); + } + } + } + Ok(()) +} \ No newline at end of file