forked from StrafesNET/map-tool
recursive vmt loader
This commit is contained in:
parent
0e1b9494c2
commit
894584f855
175
src/main.rs
175
src/main.rs
@ -1045,6 +1045,79 @@ fn write_attributes() -> AResult<()>{
|
|||||||
Ok(())
|
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<()>{
|
fn extract_textures(paths:Vec<std::path::PathBuf>,vpk_path:std::path::PathBuf)->AResult<()>{
|
||||||
let vpk_index=vpk::VPK::read(&vpk_path)?;
|
let vpk_index=vpk::VPK::read(&vpk_path)?;
|
||||||
for path in paths{
|
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);
|
let model=vmdl::Model::from_parts(mdl,vtx,vvd);
|
||||||
for texture in model.textures(){
|
for texture in model.textures(){
|
||||||
println!("prop texture={}",texture.name.as_str());
|
println!("prop texture={}",texture.name.as_str());
|
||||||
|
println!("search paths={:?}",texture.search_paths);
|
||||||
deduplicate.insert(std::path::PathBuf::from(texture.name.as_str()));
|
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;
|
let tree=&vpk_index.tree;
|
||||||
std::thread::scope(move|s|{
|
std::thread::scope(move|s|{
|
||||||
let mut thread_handles=Vec::new();
|
let mut thread_handles=Vec::new();
|
||||||
for texture_name in deduplicate{
|
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;
|
let mut found_texture=false;
|
||||||
//LMAO imagine having to write type names
|
//LMAO imagine having to write type names
|
||||||
let write_image=|mut stuff,write_file_name|{
|
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)?;
|
dds.write(&mut writer)?;
|
||||||
Ok::<(),anyhow::Error>(())
|
Ok::<(),anyhow::Error>(())
|
||||||
};
|
};
|
||||||
let mut find_stuff=|search_file_name|{
|
let find_stuff=|search_file_name:String|{
|
||||||
//println!("search_file_name={}",search_file_name);
|
//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)){
|
match pack.get(search_file_name.as_str()){
|
||||||
(Ok(mut zip_file),None)=>{
|
Ok(file)=>return Ok(file),
|
||||||
let mut buf=Vec::new();
|
_=>(),
|
||||||
zip_file.read_to_end(&mut buf)?;
|
}
|
||||||
Some(buf)
|
//search pak list
|
||||||
},
|
for tree in [tree]{
|
||||||
(_,Some(vpk_entry))=>Some(vpk_entry.get()?.to_vec()),
|
if let Some(vpk_entry)=tree.get(search_file_name.as_str()){
|
||||||
_=>None,
|
return Ok(Some(vpk_entry.get()?.to_vec()));
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
Ok::<Option<Vec<u8>>,anyhow::Error>(None)
|
||||||
};
|
};
|
||||||
if let Some(stuff)=find_stuff(texture_file_name.as_os_str().to_str().unwrap())?{
|
let loader=|texture_name:String|{
|
||||||
|
let mut texture_file_name=std::path::PathBuf::from("materials");
|
||||||
|
//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");
|
||||||
|
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;
|
found_texture=true;
|
||||||
let texture_name=texture_name.clone();
|
let texture_name=texture_name.clone();
|
||||||
thread_handles.push(s.spawn(move||write_image(stuff,texture_name)));
|
thread_handles.push(s.spawn(move||write_image(stuff,texture_name)));
|
||||||
}
|
}
|
||||||
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")),
|
|
||||||
};
|
|
||||||
if let Some(search_texture_name)=some_texture{
|
|
||||||
println!("searching for some random texture: {}",search_texture_name);
|
|
||||||
let mut texture_file_name=std::path::PathBuf::from("materials");
|
|
||||||
texture_file_name.push(search_texture_name);
|
|
||||||
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);
|
|
||||||
found_texture=true;
|
|
||||||
let texture_name=texture_name.clone();
|
|
||||||
thread_handles.push(s.spawn(move||write_image(stuff,texture_name)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found_texture{
|
if !found_texture{
|
||||||
println!("no data");
|
println!("no data");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user