recursive vmt loader
This commit is contained in:
parent
0e1b9494c2
commit
894584f855
169
src/main.rs
169
src/main.rs
@ -1045,6 +1045,79 @@ fn write_attributes() -> AResult<()>{
|
||||
Ok(())
|
||||
}
|
||||
|
||||
enum VMTContent{
|
||||
VMT(String),
|
||||
VTF(String),
|
||||
Patch(vmt_parser::material::PatchMaterial),
|
||||
Unsupported,//don't want to deal with whatever vmt variant
|
||||
Unresolved,//could not locate a texture because of vmt content
|
||||
}
|
||||
impl VMTContent{
|
||||
fn vtf(opt:Option<String>)->Self{
|
||||
match opt{
|
||||
Some(s)=>Self::VTF(s),
|
||||
None=>Self::Unresolved,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_some_texture(material:vmt_parser::material::Material)->AResult<VMTContent>{
|
||||
//just grab some texture from somewhere for now
|
||||
Ok(match material{
|
||||
vmt_parser::material::Material::LightMappedGeneric(mat)=>VMTContent::vtf(Some(mat.base_texture)),
|
||||
vmt_parser::material::Material::VertexLitGeneric(mat)=>VMTContent::vtf(mat.base_texture.or(mat.decal_texture)),//this just dies if there is none
|
||||
vmt_parser::material::Material::VertexLitGenericDx6(mat)=>VMTContent::vtf(mat.base_texture.or(mat.decal_texture)),
|
||||
vmt_parser::material::Material::UnlitGeneric(mat)=>VMTContent::vtf(mat.base_texture),
|
||||
vmt_parser::material::Material::UnlitTwoTexture(mat)=>VMTContent::vtf(mat.base_texture),
|
||||
vmt_parser::material::Material::Water(mat)=>VMTContent::vtf(mat.base_texture),
|
||||
vmt_parser::material::Material::WorldVertexTransition(mat)=>VMTContent::vtf(Some(mat.base_texture)),
|
||||
vmt_parser::material::Material::EyeRefract(mat)=>VMTContent::vtf(Some(mat.cornea_texture)),
|
||||
vmt_parser::material::Material::SubRect(mat)=>VMTContent::VMT(mat.material),//recursive
|
||||
vmt_parser::material::Material::Sprite(mat)=>VMTContent::vtf(Some(mat.base_texture)),
|
||||
vmt_parser::material::Material::SpriteCard(mat)=>VMTContent::vtf(mat.base_texture),
|
||||
vmt_parser::material::Material::Cable(mat)=>VMTContent::vtf(Some(mat.base_texture)),
|
||||
vmt_parser::material::Material::Refract(mat)=>VMTContent::vtf(mat.base_texture),
|
||||
vmt_parser::material::Material::Modulate(mat)=>VMTContent::vtf(Some(mat.base_texture)),
|
||||
vmt_parser::material::Material::DecalModulate(mat)=>VMTContent::vtf(Some(mat.base_texture)),
|
||||
vmt_parser::material::Material::Sky(mat)=>VMTContent::vtf(Some(mat.base_texture)),
|
||||
vmt_parser::material::Material::Replacements(_mat)=>VMTContent::Unsupported,
|
||||
vmt_parser::material::Material::Patch(mat)=>VMTContent::Patch(mat),
|
||||
_=>return Err(anyhow::Error::msg("vmt failed to parse")),
|
||||
})
|
||||
}
|
||||
|
||||
fn get_vmt<F:Fn(String)->AResult<Option<Vec<u8>>>>(find_stuff:&F,search_name:String)->AResult<Option<vmt_parser::material::Material>>{
|
||||
if let Some(stuff)=find_stuff(search_name)?{
|
||||
//println!("woahh its a vmt {:?}",search_name);
|
||||
//decode vmt and then write
|
||||
let stuff=String::from_utf8(stuff)?;
|
||||
let material=vmt_parser::from_str(stuff.as_str())?;
|
||||
println!("vmt material={:?}",material);
|
||||
return Ok(Some(material));
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn recursive_vmt_loader<F:Fn(String)->AResult<Option<Vec<u8>>>>(find_stuff:&F,material:vmt_parser::material::Material)->AResult<Option<Vec<u8>>>{
|
||||
match get_some_texture(material)?{
|
||||
VMTContent::VMT(s)=>match get_vmt(find_stuff,s)?{
|
||||
Some(mat)=>recursive_vmt_loader(find_stuff,mat),
|
||||
None=>Ok(None),
|
||||
},
|
||||
VMTContent::VTF(s)=>find_stuff(s),
|
||||
VMTContent::Patch(mat)=>recursive_vmt_loader(find_stuff,
|
||||
mat.resolve(|search_name|
|
||||
match find_stuff(search_name.to_string())?{
|
||||
Some(bytes)=>Ok(String::from_utf8(bytes)?),
|
||||
None=>Err(anyhow::Error::msg("could not find vmt")),
|
||||
}
|
||||
)?
|
||||
),
|
||||
VMTContent::Unsupported=>Ok(None),
|
||||
VMTContent::Unresolved=>Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_textures(paths:Vec<std::path::PathBuf>,vpk_path:std::path::PathBuf)->AResult<()>{
|
||||
let vpk_index=vpk::VPK::read(&vpk_path)?;
|
||||
for path in paths{
|
||||
@ -1077,6 +1150,7 @@ fn extract_textures(paths:Vec<std::path::PathBuf>,vpk_path:std::path::PathBuf)->
|
||||
let model=vmdl::Model::from_parts(mdl,vtx,vvd);
|
||||
for texture in model.textures(){
|
||||
println!("prop texture={}",texture.name.as_str());
|
||||
println!("search paths={:?}",texture.search_paths);
|
||||
deduplicate.insert(std::path::PathBuf::from(texture.name.as_str()));
|
||||
}
|
||||
},
|
||||
@ -1087,23 +1161,11 @@ fn extract_textures(paths:Vec<std::path::PathBuf>,vpk_path:std::path::PathBuf)->
|
||||
}
|
||||
}
|
||||
|
||||
let mut zippyt=bsp.pack.into_zip().into_inner().unwrap();
|
||||
let pack=&bsp.pack;
|
||||
let tree=&vpk_index.tree;
|
||||
std::thread::scope(move|s|{
|
||||
let mut thread_handles=Vec::new();
|
||||
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");
|
||||
let mut found_texture=false;
|
||||
//LMAO imagine having to write type names
|
||||
let write_image=|mut stuff,write_file_name|{
|
||||
@ -1131,65 +1193,46 @@ fn extract_textures(paths:Vec<std::path::PathBuf>,vpk_path:std::path::PathBuf)->
|
||||
dds.write(&mut writer)?;
|
||||
Ok::<(),anyhow::Error>(())
|
||||
};
|
||||
let mut find_stuff=|search_file_name|{
|
||||
let find_stuff=|search_file_name:String|{
|
||||
//println!("search_file_name={}",search_file_name);
|
||||
Ok::<Option<Vec<u8>>,anyhow::Error>(match (zippyt.by_name(search_file_name),tree.get(search_file_name)){
|
||||
(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,
|
||||
})
|
||||
};
|
||||
if let Some(stuff)=find_stuff(texture_file_name.as_os_str().to_str().unwrap())?{
|
||||
found_texture=true;
|
||||
let texture_name=texture_name.clone();
|
||||
thread_handles.push(s.spawn(move||write_image(stuff,texture_name)));
|
||||
match pack.get(search_file_name.as_str()){
|
||||
Ok(file)=>return Ok(file),
|
||||
_=>(),
|
||||
}
|
||||
if let Some(stuff)=find_stuff(texture_file_name2.as_os_str().to_str().unwrap())?{
|
||||
println!("woahh its a vmt {:?}",texture_file_name2);
|
||||
//decode vmt and then write
|
||||
let stuff=String::from_utf8(stuff)?;
|
||||
|
||||
//just grab some texture from somewhere for now
|
||||
let vmt=vmt_parser::from_str(stuff.as_str())?;
|
||||
println!("le vmt {:?}",vmt);
|
||||
let some_texture=match vmt{
|
||||
vmt_parser::material::Material::LightMappedGeneric(mat)=>Some(mat.base_texture),
|
||||
vmt_parser::material::Material::VertexLitGeneric(mat)=>mat.base_texture.or(mat.decal_texture),//this just dies if there is none
|
||||
vmt_parser::material::Material::VertexLitGenericDx6(mat)=>mat.base_texture.or(mat.decal_texture),
|
||||
vmt_parser::material::Material::UnlitGeneric(mat)=>mat.base_texture,
|
||||
vmt_parser::material::Material::UnlitTwoTexture(mat)=>mat.base_texture,
|
||||
vmt_parser::material::Material::Water(mat)=>mat.base_texture,
|
||||
vmt_parser::material::Material::WorldVertexTransition(mat)=>Some(mat.base_texture),
|
||||
vmt_parser::material::Material::EyeRefract(mat)=>Some(mat.cornea_texture),
|
||||
vmt_parser::material::Material::SubRect(_mat)=>None,//recursive
|
||||
vmt_parser::material::Material::Sprite(mat)=>Some(mat.base_texture),
|
||||
vmt_parser::material::Material::SpriteCard(mat)=>mat.base_texture,
|
||||
vmt_parser::material::Material::Cable(mat)=>Some(mat.base_texture),
|
||||
vmt_parser::material::Material::Refract(mat)=>mat.base_texture,
|
||||
vmt_parser::material::Material::Modulate(mat)=>Some(mat.base_texture),
|
||||
vmt_parser::material::Material::DecalModulate(mat)=>Some(mat.base_texture),
|
||||
vmt_parser::material::Material::Sky(mat)=>Some(mat.base_texture),
|
||||
vmt_parser::material::Material::Replacements(_mat)=>None,
|
||||
vmt_parser::material::Material::Patch(_mat)=>None,//recursive
|
||||
_=>return Err(anyhow::Error::msg("vmt failed to parse")),
|
||||
//search pak list
|
||||
for tree in [tree]{
|
||||
if let Some(vpk_entry)=tree.get(search_file_name.as_str()){
|
||||
return Ok(Some(vpk_entry.get()?.to_vec()));
|
||||
}
|
||||
}
|
||||
Ok::<Option<Vec<u8>>,anyhow::Error>(None)
|
||||
};
|
||||
if let Some(search_texture_name)=some_texture{
|
||||
println!("searching for some random texture: {}",search_texture_name);
|
||||
let loader=|texture_name:String|{
|
||||
let mut texture_file_name=std::path::PathBuf::from("materials");
|
||||
texture_file_name.push(search_texture_name);
|
||||
//lower case
|
||||
let texture_file_name_lowercase=texture_name.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");
|
||||
if let Some(stuff)=find_stuff(texture_file_name.as_os_str().to_str().unwrap())?{
|
||||
println!("got it! writing to {:?}",texture_name);
|
||||
texture_file_name2.set_extension("vmt");
|
||||
if let Some(stuff)=find_stuff(texture_file_name.to_string_lossy().to_string())?{
|
||||
return Ok(Some(stuff))
|
||||
}
|
||||
if let Some(mat)=get_vmt(&find_stuff,texture_file_name2.to_string_lossy().to_string())?{
|
||||
return recursive_vmt_loader(&find_stuff,mat);
|
||||
}
|
||||
Ok(None)
|
||||
};
|
||||
if let Some(stuff)=loader(texture_name.to_string_lossy().to_string())?{
|
||||
found_texture=true;
|
||||
let texture_name=texture_name.clone();
|
||||
thread_handles.push(s.spawn(move||write_image(stuff,texture_name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found_texture{
|
||||
println!("no data");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user