aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-03-23 18:33:53 +0100
committermetamuffin <metamuffin@disroot.org>2025-03-23 18:33:53 +0100
commit756664281e6f8c37653e8769890962e8bab933e9 (patch)
tree2cf8ba24052d0482451dd79ed75691b3306d751c
parent52d4405686fac2ab750da16e0fd67be9fb2e9429 (diff)
downloadunity-tools-756664281e6f8c37653e8769890962e8bab933e9.tar
unity-tools-756664281e6f8c37653e8769890962e8bab933e9.tar.bz2
unity-tools-756664281e6f8c37653e8769890962e8bab933e9.tar.zst
allow preloading files
-rw-r--r--exporter/src/bin/typegraph.rs97
-rw-r--r--exporter/src/bin/yaml.rs35
-rw-r--r--src/assetbundle.rs37
-rw-r--r--src/classes/mod.rs2
-rw-r--r--src/classes/pptr.rs5
-rw-r--r--src/classes/vectors.rs2
6 files changed, 103 insertions, 75 deletions
diff --git a/exporter/src/bin/typegraph.rs b/exporter/src/bin/typegraph.rs
index d1e7629..44e395b 100644
--- a/exporter/src/bin/typegraph.rs
+++ b/exporter/src/bin/typegraph.rs
@@ -18,56 +18,63 @@ fn main() -> anyhow::Result<()> {
let mut edges = BTreeSet::new();
let node = fs.find_main_file().unwrap().to_owned();
- let mut cab = fs.read(&node)?;
- let file = SerializedFile::read(&mut cab, node.name)?;
+ let cab = fs.read(&node)?;
+ let file = SerializedFile::read(cab, node.name)?;
+ let mut shared = None;
+ if let Some(ni) = file.find_fs_shared_assets(&fs) {
+ let cab = fs.read(&ni)?;
+ shared = Some(SerializedFile::read(cab, ni.name)?);
+ }
- for ob in file.objects {
- let typetree = if ob.type_id < 0 {
- unimplemented!()
- } else {
- &file.types[ob.type_id as usize]
- };
- fn print_types(
- edges: &mut BTreeSet<(String, String)>,
- filter_prims: bool,
- tt: TypeTreeNode,
- ) {
- for c in tt.children {
- let mut c = vec![c];
- loop {
- let mut nc = Vec::new();
- let mut f = false;
- for mut c in c {
- if let Some(inner) = c.type_string.strip_prefix("PPtr<") {
- c.type_string = inner.strip_suffix(">").unwrap().to_owned();
- f = true;
- } else if matches!(
- c.type_string.as_str(),
- "Array" | "pair" | "map" | "vector"
- ) {
- nc.extend(c.children);
- f = true
- } else {
- nc.push(c);
- };
- }
- c = nc;
- if !f {
- break;
+ for file in [file].into_iter().chain(shared) {
+ for ob in file.objects {
+ let typetree = if ob.type_id < 0 {
+ unimplemented!()
+ } else {
+ &file.types[ob.type_id as usize]
+ };
+ fn print_types(
+ edges: &mut BTreeSet<(String, String)>,
+ filter_prims: bool,
+ tt: TypeTreeNode,
+ ) {
+ for c in tt.children {
+ let mut c = vec![c];
+ loop {
+ let mut nc = Vec::new();
+ let mut f = false;
+ for mut c in c {
+ if let Some(inner) = c.type_string.strip_prefix("PPtr<") {
+ c.type_string = inner.strip_suffix(">").unwrap().to_owned();
+ f = true;
+ nc.push(c);
+ } else if matches!(
+ c.type_string.as_str(),
+ "Array" | "pair" | "map" | "vector"
+ ) {
+ nc.extend(c.children);
+ f = true
+ } else {
+ nc.push(c);
+ };
+ }
+ c = nc;
+ if !f {
+ break;
+ }
}
- }
- for c in c {
- if filter_prims && is_primitive(&c.type_string) {
- continue;
+ for c in c {
+ if filter_prims && is_primitive(&c.type_string) {
+ continue;
+ }
+ edges.insert((tt.type_string.to_owned(), c.type_string.to_owned()));
+ print_types(edges, filter_prims, c);
}
- edges.insert((tt.type_string.to_owned(), c.type_string.to_owned()));
- print_types(edges, filter_prims, c);
}
}
- }
-
- if let Some(tree) = &typetree.type_tree {
- print_types(&mut edges, filter_prims, tree.clone());
+ if let Some(tree) = &typetree.type_tree {
+ print_types(&mut edges, filter_prims, tree.clone());
+ }
}
}
let nodes = edges
diff --git a/exporter/src/bin/yaml.rs b/exporter/src/bin/yaml.rs
index afa016a..a63164a 100644
--- a/exporter/src/bin/yaml.rs
+++ b/exporter/src/bin/yaml.rs
@@ -13,24 +13,31 @@ fn main() -> anyhow::Result<()> {
let filter = args().nth(2);
let node = fs.find_main_file().unwrap().to_owned();
- let mut cab = fs.read(&node)?;
- let mut file = SerializedFile::read(&mut cab, node.name)?;
- for ob in file.objects.clone() {
- if let Some(f) = &filter {
- if file.get_object_type_tree(&ob)?.type_string != *f && ob.path_id.to_string() != *f {
- continue;
+ let cab = fs.read(&node)?;
+ let file = SerializedFile::read(cab, node.name)?;
+ let mut shared = None;
+ if let Some(ni) = file.find_fs_shared_assets(&fs) {
+ let cab = fs.read(&ni)?;
+ shared = Some(SerializedFile::read(cab, ni.name)?);
+ }
+ for mut file in [file].into_iter().chain(shared) {
+ for ob in file.objects.clone() {
+ if let Some(f) = &filter {
+ if file.get_object_type_tree(&ob)?.type_string != *f && ob.path_id.to_string() != *f
+ {
+ continue;
+ }
}
- }
- let value = file.read_object(ob)?;
- let hvalue = HValue::from_value(value)?;
+ let value = file.read_object(ob)?;
+ let hvalue = HValue::from_value(value)?;
- let mut hvalue = serde_yml::to_value(hvalue)?;
- trim_large_arrays(&mut hvalue);
+ let mut hvalue = serde_yml::to_value(hvalue)?;
+ trim_large_arrays(&mut hvalue);
- serde_yml::to_writer(stdout(), &hvalue).unwrap();
- println!()
+ serde_yml::to_writer(stdout(), &hvalue).unwrap();
+ println!()
+ }
}
-
Ok(())
}
diff --git a/src/assetbundle.rs b/src/assetbundle.rs
index 0af9895..f87d7b8 100644
--- a/src/assetbundle.rs
+++ b/src/assetbundle.rs
@@ -1,16 +1,14 @@
use crate::{
classes::pptr::PPtr,
serialized_file::SerializedFile,
- unityfs::{
- NodeReader, UnityFS, block_reader::BlockReader, header::NodeInfo, multi_reader::MultiReader,
- },
+ unityfs::{UnityFS, header::NodeInfo},
};
use anyhow::{Context, Result, anyhow};
use log::debug;
use std::{
collections::HashMap,
fs::File,
- io::{BufReader, Read, Seek},
+ io::{BufReader, Cursor, Read, Seek},
marker::PhantomData,
path::Path,
sync::{Arc, Mutex},
@@ -19,13 +17,16 @@ use std::{
/// High-level wrapper around UnityFS, SerializedFile and all the classes.
pub struct AssetBundle<T> {
pub fs: UnityFS<T>,
- pub ser_files:
- HashMap<String, Arc<Mutex<SerializedFile<NodeReader<BlockReader<MultiReader<T>>>>>>>,
+ pub ser_files: HashMap<String, Arc<Mutex<SerializedFile<Box<dyn ReadSeek>>>>>,
pub main_file: NodeInfo,
pub default_resources: SerializedFile<BufReader<File>>,
+ pub full_decomp: bool,
}
-impl<T: Read + Seek> AssetBundle<T> {
+pub trait ReadSeek: Read + Seek + 'static {}
+impl<T: Read + Seek + 'static> ReadSeek for T {}
+
+impl<T: Read + Seek + 'static> AssetBundle<T> {
pub fn open(inner: T, support_dir: impl AsRef<Path>) -> Result<Self> {
let fs = UnityFS::open(inner).context("opening UnityFS")?;
let main_file = fs
@@ -44,21 +45,29 @@ impl<T: Read + Seek> AssetBundle<T> {
fs,
main_file,
default_resources,
+ full_decomp: false,
ser_files: HashMap::new(),
})
}
pub fn get_fs_file(
&mut self,
- node: &NodeInfo,
- ) -> Result<Arc<Mutex<SerializedFile<NodeReader<BlockReader<MultiReader<T>>>>>>> {
- if !self.ser_files.contains_key(&node.name) {
- let file =
- SerializedFile::read(self.fs.read(node)?, format!("archive:/{}", node.name))?;
+ nodeinfo: &NodeInfo,
+ ) -> Result<Arc<Mutex<SerializedFile<Box<dyn ReadSeek>>>>> {
+ if !self.ser_files.contains_key(&nodeinfo.name) {
+ let mut node = self.fs.read(nodeinfo)?;
+ let node_box = if self.full_decomp {
+ let mut buf = Vec::new();
+ node.read_to_end(&mut buf)?;
+ Box::new(Cursor::new(buf)) as Box<dyn ReadSeek>
+ } else {
+ Box::new(node) as Box<dyn ReadSeek>
+ };
+ let file = SerializedFile::read(node_box, format!("archive:/{}", nodeinfo.name))?;
self.ser_files
- .insert(node.name.clone(), Arc::new(Mutex::new(file)));
+ .insert(nodeinfo.name.clone(), Arc::new(Mutex::new(file)));
}
- Ok(self.ser_files.get(&node.name).unwrap().clone())
+ Ok(self.ser_files.get(&nodeinfo.name).unwrap().clone())
}
pub fn all_toplevel(&mut self) -> Vec<PPtr> {
diff --git a/src/classes/mod.rs b/src/classes/mod.rs
index bff033a..c312c6a 100644
--- a/src/classes/mod.rs
+++ b/src/classes/mod.rs
@@ -9,6 +9,8 @@ pub mod transform;
pub mod vectors;
pub mod renderer;
pub mod shader;
+pub mod cubemap;
+pub mod render_settings;
use crate::object::{Value, parser::FromValue};
use anyhow::Result;
diff --git a/src/classes/pptr.rs b/src/classes/pptr.rs
index 14c72b6..332d3da 100644
--- a/src/classes/pptr.rs
+++ b/src/classes/pptr.rs
@@ -60,7 +60,10 @@ impl<T: FromValue> PPtr<T> {
pub fn is_null(&self) -> bool {
self.path_id == 0 && self.file_id == 0
}
- pub fn load(&self, bundle: &mut AssetBundle<impl Read + Seek>) -> Result<T> {
+ pub fn load(&self, bundle: &mut AssetBundle<impl Read + Seek + 'static>) -> Result<T> {
+ if self.is_null() {
+ bail!("attempted to load null PPtr")
+ }
debug!(
"loading PPtr<{}> file_id={} path_id={}",
self.class, self.file_id, self.path_id
diff --git a/src/classes/vectors.rs b/src/classes/vectors.rs
index 14c5a59..b7127bf 100644
--- a/src/classes/vectors.rs
+++ b/src/classes/vectors.rs
@@ -30,7 +30,7 @@ impl FromValue for Vec4 {
}
}
-#[derive(Debug, Serialize)]
+#[derive(Debug, Serialize, Clone, Copy)]
pub struct ColorRGBA(pub Vec4);
impl FromValue for ColorRGBA {
fn from_value(v: Value) -> anyhow::Result<Self> {