aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-03-14 14:58:38 +0100
committermetamuffin <metamuffin@disroot.org>2025-03-14 14:58:38 +0100
commit7ff78cff53eba1da60b8beb851732e2f8197c221 (patch)
treefa6d914270ba1acdeddbc3aa1ce1cf7cf0824a7b
parent6debd2c0a230d623c06869ca4c4f13519f53eb5d (diff)
downloadunity-tools-7ff78cff53eba1da60b8beb851732e2f8197c221.tar
unity-tools-7ff78cff53eba1da60b8beb851732e2f8197c221.tar.bz2
unity-tools-7ff78cff53eba1da60b8beb851732e2f8197c221.tar.zst
move files around
-rw-r--r--Cargo.lock18
-rw-r--r--Cargo.toml7
-rw-r--r--exporter/Cargo.toml16
-rw-r--r--exporter/src/bin/debug.rs61
-rw-r--r--exporter/src/bin/gltf.rs99
-rw-r--r--exporter/src/bin/json.rs (renamed from src/bin/json.rs)0
-rw-r--r--exporter/src/bin/meshes.rs (renamed from src/bin/meshes.rs)0
-rw-r--r--exporter/src/bin/probe.rs (renamed from src/bin/probe.rs)0
-rw-r--r--exporter/src/bin/textures.rs (renamed from src/bin/textures.rs)0
-rw-r--r--exporter/src/bin/typegraph.rs (renamed from src/bin/typegraph.rs)0
-rw-r--r--exporter/src/bin/yaml.rs (renamed from src/bin/yaml.rs)0
-rw-r--r--exporter/src/main.rs3
-rw-r--r--src/bin/gltf.rs22
-rw-r--r--src/classes/mesh_renderer.rs62
-rw-r--r--src/classes/mod.rs1
15 files changed, 263 insertions, 26 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 13a06e1..6870611 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -306,6 +306,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
+name = "exporter"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "bytemuck",
+ "env_logger",
+ "glam",
+ "gltf",
+ "gltf-json",
+ "log",
+ "serde_json",
+ "serde_yml",
+ "unity-tools",
+]
+
+[[package]]
name = "exr"
version = "1.73.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1191,7 +1207,6 @@ dependencies = [
"anyhow",
"env_logger",
"glam",
- "gltf",
"humansize",
"image",
"log",
@@ -1199,7 +1214,6 @@ dependencies = [
"lzma",
"serde",
"serde_json",
- "serde_yml",
"texpresso",
"texture2ddecoder",
]
diff --git a/Cargo.toml b/Cargo.toml
index ecd0a2f..e148c96 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,3 +1,8 @@
+[workspace]
+resolver = "3"
+members = [".", "exporter"]
+default-members = ["exporter"]
+
[package]
name = "unity-tools"
version = "0.1.0"
@@ -12,9 +17,7 @@ lzma = "0.2.2"
serde_json = "1.0.139"
humansize = "2.1.3"
serde = { version = "1.0.219", features = ["derive"] }
-serde_yml = "0.0.12"
glam = { version = "0.30.0", features = ["serde"] }
texpresso = "2.0.1"
image = "0.25.5"
texture2ddecoder = { git = "https://github.com/UniversalGameExtraction/texture2ddecoder", rev = "d2b4653fda298f1da39917da86bc509b17879808" }
-gltf = "1.4.1"
diff --git a/exporter/Cargo.toml b/exporter/Cargo.toml
new file mode 100644
index 0000000..1894e52
--- /dev/null
+++ b/exporter/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "exporter"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+unity-tools = { path = ".." }
+serde_yml = "0.0.12"
+log = "0.4.25"
+env_logger = "0.11.6"
+serde_json = "1.0.139"
+anyhow = "1.0.95"
+glam = { version = "0.30.0", features = ["serde"] }
+gltf-json = "1.4.1"
+gltf = "1.4.1"
+bytemuck = "1.22.0"
diff --git a/exporter/src/bin/debug.rs b/exporter/src/bin/debug.rs
new file mode 100644
index 0000000..92713ba
--- /dev/null
+++ b/exporter/src/bin/debug.rs
@@ -0,0 +1,61 @@
+use std::{env::args, fs::File, io::BufReader};
+use unity_tools::{serialized_file::SerializedFile, unityfs::UnityFS};
+
+fn main() -> anyhow::Result<()> {
+ env_logger::init_from_env("LOG");
+ let file = BufReader::new(File::open(args().nth(1).unwrap())?);
+ let mut fs = UnityFS::open(file)?;
+
+ let node = fs.find_main_file().unwrap().to_owned();
+ let mut cab = fs.read(&node)?;
+ let file = SerializedFile::read(&mut cab)?;
+
+ for ob in file.objects {
+ // eprintln!("{:#?}", ob);
+ let typetree = if ob.type_id < 0 {
+ unimplemented!()
+ } else {
+ // file.types
+ // .iter()
+ // .find(|t| t.class_id == ob.type_id)
+ // .expect("unknown type")
+ &file.types[ob.type_id as usize]
+ };
+ // fn print_types(tt: &TypeTreeNode) {
+ // println!("{}", tt.type_string);
+ // for c in &tt.children {
+ // print_types(&c);
+ // }
+ // }
+ // fn print_crit_types(tt: &TypeTreeNode) {
+ // let mut crit = tt.byte_size == -1 || tt.children.is_empty();
+ // for c in &tt.children {
+ // print_crit_types(&c);
+ // crit &= c.byte_size != -1
+ // }
+ // if crit {
+ // println!("{}", tt.type_string);
+ // }
+ // }
+ if let Some(tree) = &typetree.type_tree {
+ println!("{}", tree.type_string);
+ // print_crit_types(tree);
+ // print_types(tree);
+ }
+ // eprintln!("{typetree:#?}");
+
+ // let value = read_value(typetree.type_tree.as_ref().unwrap(), e, &mut cab)?;
+
+ // if let Value::Object { class, .. } = &value {
+ // println!("{class}")
+ // }
+
+ // debug!(
+ // "{}",
+ // serde_json::to_string_pretty(&value.to_json()).unwrap()
+ // )
+ }
+ // eprintln!("{:#?}", file.types);
+
+ Ok(())
+}
diff --git a/exporter/src/bin/gltf.rs b/exporter/src/bin/gltf.rs
new file mode 100644
index 0000000..fb6b72d
--- /dev/null
+++ b/exporter/src/bin/gltf.rs
@@ -0,0 +1,99 @@
+#![feature(array_chunks)]
+use anyhow::anyhow;
+use glam::{Affine3A, Mat4};
+use gltf::Glb;
+use log::warn;
+use std::{borrow::Cow, env::args, fs::File, io::BufReader};
+use unity_tools::{
+ classes::{
+ gameobject::GameObject,
+ mesh_renderer::{MeshRenderer, SkinnedMeshRenderer},
+ transform::Transform,
+ },
+ serialized_file::SerializedFile,
+ unityfs::UnityFS,
+};
+
+fn main() -> anyhow::Result<()> {
+ env_logger::init_from_env("LOG");
+ let file = || BufReader::new(File::open(args().nth(1).unwrap()).unwrap());
+ let mut fs = UnityFS::open(file())?;
+
+ let cabfile = fs
+ .find_main_file()
+ .ok_or(anyhow!("no CAB file found"))?
+ .to_owned();
+
+ let mut cab = fs.read(&cabfile)?;
+ let mut file = SerializedFile::read(&mut cab)?;
+ let gameobjects = file
+ .objects
+ .iter()
+ .filter(|ob| file.get_object_type_tree(ob).unwrap().type_string == "GameObject")
+ .cloned()
+ .collect::<Vec<_>>();
+
+ // let mut root_tr = Transform::from_value(file.read_object(ob)?)?;
+ // while !root_tr.father.is_null() {
+ // root_tr = root_tr.father.load(&mut file)?;
+ // }
+ // eprintln!("{root_tr:?}");
+
+ let mut root = gltf_json::Root::default();
+
+ for ob in gameobjects {
+ let go = file.read_object(ob)?.parse::<GameObject>()?;
+ for comp in go.components {
+ let ob = comp.load(&mut file)?;
+ let mut global_transform = Affine3A::default();
+ match ob.class_name().unwrap().as_str() {
+ "Transform" => {
+ let mut tr = ob.parse::<Transform>()?;
+ let mut transforms = Vec::new();
+ loop {
+ transforms.push(
+ Mat4::from_translation(tr.local_position)
+ * Mat4::from_scale(tr.local_scale)
+ * Mat4::from_quat(tr.local_rotation),
+ );
+ if tr.father.is_null() {
+ break;
+ } else {
+ tr = tr.father.load(&mut file)?;
+ }
+ }
+ global_transform =
+ Affine3A::from_mat4(transforms.into_iter().reduce(|a, b| a * b).unwrap())
+ }
+ "SkinnedMeshRenderer" => {
+ let mr = ob.parse::<SkinnedMeshRenderer>()?;
+ }
+ "MeshRenderer" => {
+ let mr = ob.parse::<MeshRenderer>()?;
+ }
+ x => warn!("unknown component {x:?}"),
+ }
+ }
+ }
+
+ let json_string = gltf_json::serialize::to_string(&root).expect("Serialization error");
+ let mut json_offset = json_string.len();
+ align_to_multiple_of_four(&mut json_offset);
+ let glb = Glb {
+ header: gltf::binary::Header {
+ magic: *b"glTF",
+ version: 2,
+ length: json_offset as u32,
+ },
+ bin: None,
+ json: Cow::Owned(json_string.into_bytes()),
+ };
+ let writer = std::fs::File::create("triangle.glb").expect("I/O error");
+ glb.to_writer(writer).expect("glTF binary output error");
+
+ Ok(())
+}
+
+fn align_to_multiple_of_four(n: &mut usize) {
+ *n = (*n + 3) & !3;
+}
diff --git a/src/bin/json.rs b/exporter/src/bin/json.rs
index dd83de6..dd83de6 100644
--- a/src/bin/json.rs
+++ b/exporter/src/bin/json.rs
diff --git a/src/bin/meshes.rs b/exporter/src/bin/meshes.rs
index e3758c4..e3758c4 100644
--- a/src/bin/meshes.rs
+++ b/exporter/src/bin/meshes.rs
diff --git a/src/bin/probe.rs b/exporter/src/bin/probe.rs
index feca633..feca633 100644
--- a/src/bin/probe.rs
+++ b/exporter/src/bin/probe.rs
diff --git a/src/bin/textures.rs b/exporter/src/bin/textures.rs
index 2e077fe..2e077fe 100644
--- a/src/bin/textures.rs
+++ b/exporter/src/bin/textures.rs
diff --git a/src/bin/typegraph.rs b/exporter/src/bin/typegraph.rs
index ea55e05..ea55e05 100644
--- a/src/bin/typegraph.rs
+++ b/exporter/src/bin/typegraph.rs
diff --git a/src/bin/yaml.rs b/exporter/src/bin/yaml.rs
index 4ef8933..4ef8933 100644
--- a/src/bin/yaml.rs
+++ b/exporter/src/bin/yaml.rs
diff --git a/exporter/src/main.rs b/exporter/src/main.rs
new file mode 100644
index 0000000..e7a11a9
--- /dev/null
+++ b/exporter/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/src/bin/gltf.rs b/src/bin/gltf.rs
deleted file mode 100644
index 323b6d2..0000000
--- a/src/bin/gltf.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-#![feature(array_chunks)]
-use anyhow::anyhow;
-use std::{env::args, fs::File, io::BufReader};
-use unity_tools::{serialized_file::SerializedFile, unityfs::UnityFS};
-
-fn main() -> anyhow::Result<()> {
- env_logger::init_from_env("LOG");
- let file = || BufReader::new(File::open(args().nth(1).unwrap()).unwrap());
- let mut fs = UnityFS::open(file())?;
- // let mut fs2 = UnityFS::open(file())?;
-
- let cabfile = fs
- .find_main_file()
- .ok_or(anyhow!("no CAB file found"))?
- .to_owned();
-
- let mut cab = fs.read(&cabfile)?;
- let file = SerializedFile::read(&mut cab)?;
- for _ob in file.objects {}
-
- Ok(())
-}
diff --git a/src/classes/mesh_renderer.rs b/src/classes/mesh_renderer.rs
new file mode 100644
index 0000000..94d6fd7
--- /dev/null
+++ b/src/classes/mesh_renderer.rs
@@ -0,0 +1,62 @@
+use super::{gameobject::GameObject, mesh::Mesh, pptr::PPtr, transform::Transform};
+use crate::object::{
+ Value,
+ parser::{Fields, FromValue},
+};
+use anyhow::Result;
+
+pub struct MeshRenderer {
+ pub enabled: bool,
+ pub mesh: PPtr<Mesh>,
+ pub cast_shadows: u8,
+ pub game_object: PPtr<GameObject>,
+ pub materials: Vec<PPtr>,
+}
+
+pub struct SkinnedMeshRenderer {
+ pub mesh_renderer: MeshRenderer,
+ pub bones: Vec<PPtr<Transform>>,
+ pub root_bone: PPtr<Transform>,
+}
+
+impl FromValue for MeshRenderer {
+ fn from_value(v: Value) -> Result<Self> {
+ Self::from_fields(v.as_class("MeshRenderer")?)
+ }
+}
+impl MeshRenderer {
+ pub fn from_fields(mut fields: Fields) -> Result<Self> {
+ Ok(Self {
+ enabled: fields.field("m_Enabled")?,
+ mesh: fields.field("m_Mesh")?,
+ cast_shadows: fields.field("m_CastShadows")?,
+ game_object: fields.field("m_GameObject")?,
+ materials: fields
+ .remove("m_Materials")
+ .unwrap()
+ .as_vector()
+ .unwrap()
+ .into_iter()
+ .map(|e| e.parse().unwrap())
+ .collect(),
+ })
+ }
+}
+
+impl FromValue for SkinnedMeshRenderer {
+ fn from_value(v: Value) -> Result<Self> {
+ let mut fields = v.as_class("SkinnedMeshRenderer")?;
+ Ok(Self {
+ root_bone: fields.field("m_RootBone")?,
+ bones: fields
+ .remove("m_Bones")
+ .unwrap()
+ .as_vector()
+ .unwrap()
+ .into_iter()
+ .map(|e| e.parse().unwrap())
+ .collect(),
+ mesh_renderer: MeshRenderer::from_fields(fields)?,
+ })
+ }
+}
diff --git a/src/classes/mod.rs b/src/classes/mod.rs
index 52ed401..b4fbe91 100644
--- a/src/classes/mod.rs
+++ b/src/classes/mod.rs
@@ -7,6 +7,7 @@ pub mod streaminginfo;
pub mod texture2d;
pub mod transform;
pub mod vectors;
+pub mod mesh_renderer;
use crate::object::{Value, parser::FromValue};
use anyhow::Result;