mirror of
https://codeberg.org/icewind/vmdl.git
synced 2026-06-03 16:44:11 +02:00
extract loader into crate
This commit is contained in:
parent
585a485031
commit
d330108905
7 changed files with 28 additions and 135 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
|
@ -2581,6 +2581,18 @@ version = "0.16.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
|
||||
|
||||
[[package]]
|
||||
name = "tf-asset-loader"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d19874714b7454f34d6142f9a2e2521b6e48ff4b3929cbac7acc72f161baf7bf"
|
||||
dependencies = [
|
||||
"steamlocate",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"vpk",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.50"
|
||||
|
|
@ -2878,13 +2890,12 @@ dependencies = [
|
|||
"main_error",
|
||||
"miette",
|
||||
"static_assertions",
|
||||
"steamlocate",
|
||||
"tf-asset-loader",
|
||||
"thiserror",
|
||||
"three-d",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"vmt-parser",
|
||||
"vpk",
|
||||
"vtf",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,7 @@ three-d = { version = "0.14.0", features = ["egui-gui"] }
|
|||
miette = { version = "5.5.0", features = ["fancy"] }
|
||||
criterion = "0.4.0"
|
||||
iai = "0.1"
|
||||
steamlocate = "2.0.0-alpha.0"
|
||||
vtf = "0.1.6"
|
||||
vpk = "0.2.0"
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = "0.3.18"
|
||||
gltf-json = "1.3.0"
|
||||
|
|
@ -30,6 +28,7 @@ image = "0.23.14"
|
|||
clap = { version = "4.4.11", features = ["derive"] }
|
||||
main_error = "0.1.2"
|
||||
vmt-parser = { version = "0.1", git = "https://github.com/icewind1991/vmt-parser" }
|
||||
tf-asset-loader = "0.1"
|
||||
|
||||
[[bench]]
|
||||
name = "parse"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::loader::LoadError;
|
||||
use miette::Diagnostic;
|
||||
use std::string::FromUtf8Error;
|
||||
use tf_asset_loader::LoaderError;
|
||||
use thiserror::Error;
|
||||
use vmt_parser::VdfError;
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ pub enum Error {
|
|||
#[error(transparent)]
|
||||
IO(#[from] std::io::Error),
|
||||
#[error(transparent)]
|
||||
Loader(#[from] LoadError),
|
||||
Loader(#[from] LoaderError),
|
||||
#[error(transparent)]
|
||||
Vtf(#[from] vtf::Error),
|
||||
#[error(transparent)]
|
||||
|
|
|
|||
|
|
@ -1,118 +0,0 @@
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use steamlocate::SteamDir;
|
||||
use thiserror::Error;
|
||||
use tracing::{debug, error, info};
|
||||
use vpk::VPK;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum LoadError {
|
||||
#[error("{0}")]
|
||||
Other(&'static str),
|
||||
#[error(transparent)]
|
||||
IO(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
impl From<&'static str> for LoadError {
|
||||
fn from(e: &'static str) -> Self {
|
||||
LoadError::Other(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Loader {
|
||||
tf_dir: PathBuf,
|
||||
download: PathBuf,
|
||||
vpks: Vec<VPK>,
|
||||
}
|
||||
|
||||
impl Debug for Loader {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Loader")
|
||||
.field("tf_dir", &self.tf_dir)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl Loader {
|
||||
pub fn new() -> Result<Self, LoadError> {
|
||||
let tf_dir = SteamDir::locate()
|
||||
.ok_or("Can't find steam directory")?
|
||||
.app(&440)
|
||||
.ok_or("Can't find tf2 directory")?
|
||||
.path
|
||||
.join("tf");
|
||||
let download = tf_dir.join("download");
|
||||
let vpks = tf_dir
|
||||
.read_dir()?
|
||||
.filter_map(|item| item.ok())
|
||||
.filter_map(|item| Some(item.path().to_str()?.to_string()))
|
||||
.filter(|path| path.ends_with("dir.vpk"))
|
||||
.map(|path| vpk::from_path(&path))
|
||||
.filter_map(|res| res.ok())
|
||||
.collect();
|
||||
|
||||
Ok(Loader {
|
||||
tf_dir,
|
||||
download,
|
||||
vpks,
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub fn exists(&self, name: &str) -> bool {
|
||||
debug!("loading {}", name);
|
||||
if name.ends_with("bsp") {
|
||||
let path = self.tf_dir.join(name);
|
||||
if path.exists() {
|
||||
return true;
|
||||
}
|
||||
let path = self.download.join(name);
|
||||
if path.exists() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for vpk in self.vpks.iter() {
|
||||
if vpk.tree.contains_key(name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub fn load(&self, name: &str) -> Result<Vec<u8>, LoadError> {
|
||||
debug!("loading {}", name);
|
||||
if name.ends_with("bsp") {
|
||||
let path = self.tf_dir.join(name);
|
||||
if path.exists() {
|
||||
debug!("found in tf2 dir");
|
||||
return Ok(fs::read(path)?);
|
||||
}
|
||||
let path = self.download.join(name);
|
||||
if path.exists() {
|
||||
debug!("found in download dir");
|
||||
return Ok(fs::read(path)?);
|
||||
}
|
||||
}
|
||||
for vpk in self.vpks.iter() {
|
||||
if let Some(entry) = vpk.tree.get(name) {
|
||||
let data = entry.get()?.into_owned();
|
||||
debug!("got {} bytes from vpk", data.len());
|
||||
return Ok(data);
|
||||
}
|
||||
}
|
||||
info!("Failed to find {} in vpk", name);
|
||||
Err(LoadError::Other("Can't find file in vpks"))
|
||||
}
|
||||
|
||||
pub fn find_in_paths(&self, name: &str, paths: &[String]) -> Option<String> {
|
||||
for path in paths {
|
||||
let full_path = format!("{}{}", path, name);
|
||||
if self.exists(&full_path) {
|
||||
return Some(full_path);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::loader::{LoadError, Loader};
|
||||
use crate::Error;
|
||||
use image::DynamicImage;
|
||||
use tf_asset_loader::Loader;
|
||||
use tracing::{error, instrument};
|
||||
use vmt_parser::from_str;
|
||||
use vtf::vtf::VTF;
|
||||
|
|
@ -54,8 +54,8 @@ pub fn load_material(
|
|||
let path = format!("{}.vmt", name.to_ascii_lowercase().trim_end_matches(".vmt"));
|
||||
let path = loader
|
||||
.find_in_paths(&path, &dirs)
|
||||
.ok_or(LoadError::Other("Can't find file in vpks"))?;
|
||||
let raw = loader.load(&path)?;
|
||||
.ok_or(Error::Other(format!("Can't find file {}", path)))?;
|
||||
let raw = loader.load(&path)?.expect("didn't find foudn path?");
|
||||
let vdf = String::from_utf8(raw)?;
|
||||
|
||||
let material = from_str(&vdf).map_err(|e| {
|
||||
|
|
@ -64,7 +64,9 @@ pub fn load_material(
|
|||
Error::Other(format!("Failed to load material {}", path))
|
||||
})?;
|
||||
let material = material.resolve(|path| {
|
||||
let data = loader.load(path)?;
|
||||
let data = loader
|
||||
.load(path)?
|
||||
.ok_or(Error::Other(format!("Can't find file {}", path)))?;
|
||||
let vdf = String::from_utf8(data)?;
|
||||
Ok::<_, Error>(vdf)
|
||||
})?;
|
||||
|
|
@ -102,7 +104,9 @@ fn load_texture(name: &str, loader: &Loader) -> Result<DynamicImage, Error> {
|
|||
"materials/{}.vtf",
|
||||
name.trim_end_matches(".vtf").trim_start_matches('/')
|
||||
);
|
||||
let mut raw = loader.load(&path)?;
|
||||
let mut raw = loader
|
||||
.load(&path)?
|
||||
.ok_or(Error::Other(format!("Can't find file {}", path)))?;
|
||||
let vtf = VTF::read(&mut raw)?;
|
||||
let image = vtf.highres_image.decode(0)?;
|
||||
Ok(image)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
mod convert;
|
||||
#[path = "../common/error.rs"]
|
||||
mod error;
|
||||
#[path = "../common/loader.rs"]
|
||||
mod loader;
|
||||
#[path = "../common/materials.rs"]
|
||||
mod material;
|
||||
|
||||
|
|
@ -11,7 +9,6 @@ use gltf_json as json;
|
|||
use std::fs;
|
||||
|
||||
use crate::convert::{push_material, push_model};
|
||||
use crate::loader::Loader;
|
||||
use crate::material::load_material_fallback;
|
||||
use clap::Parser;
|
||||
pub use error::Error;
|
||||
|
|
@ -20,6 +17,7 @@ use main_error::MainResult;
|
|||
use std::borrow::Cow;
|
||||
use std::collections::BTreeSet;
|
||||
use std::path::PathBuf;
|
||||
use tf_asset_loader::Loader;
|
||||
use vmdl::Model;
|
||||
|
||||
fn align_to_multiple_of_four(n: &mut u32) {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
#[path = "../common/error.rs"]
|
||||
mod error;
|
||||
#[path = "../common/loader.rs"]
|
||||
mod loader;
|
||||
#[path = "../common/materials.rs"]
|
||||
mod material;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::loader::Loader;
|
||||
use crate::material::{load_material_fallback, MaterialData};
|
||||
use image::GenericImageView;
|
||||
use std::env::args_os;
|
||||
use std::path::PathBuf;
|
||||
use tf_asset_loader::Loader;
|
||||
use thiserror::Error;
|
||||
use three_d::*;
|
||||
use vmdl::{Model, Vector};
|
||||
|
|
@ -59,6 +57,7 @@ fn main() -> Result<(), Error> {
|
|||
let mut gui = three_d::GUI::new(&context);
|
||||
|
||||
let loader = Loader::new().expect("loader");
|
||||
dbg!(&loader);
|
||||
let skin_count = source_model.skin_tables().count();
|
||||
|
||||
let cpu_models = (0..skin_count).map(|skin| model_to_model(&source_model, &loader, skin));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue