From 205aca90d6c21f3dd73b576c06f5ab8c1010772a Mon Sep 17 00:00:00 2001 From: metamuffin Date: Sat, 22 Mar 2025 19:48:53 +0100 Subject: horrible pptr external files system --- src/classes/mod.rs | 2 +- src/classes/pptr.rs | 69 +++++++++++++++++++++--------------- src/classes/renderer.rs | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 30 deletions(-) create mode 100644 src/classes/renderer.rs (limited to 'src/classes') diff --git a/src/classes/mod.rs b/src/classes/mod.rs index 165d41e..bff033a 100644 --- a/src/classes/mod.rs +++ b/src/classes/mod.rs @@ -7,7 +7,7 @@ pub mod streaminginfo; pub mod texture2d; pub mod transform; pub mod vectors; -pub mod mesh_renderer; +pub mod renderer; pub mod shader; use crate::object::{Value, parser::FromValue}; diff --git a/src/classes/pptr.rs b/src/classes/pptr.rs index 0e66b5f..5d57c20 100644 --- a/src/classes/pptr.rs +++ b/src/classes/pptr.rs @@ -1,13 +1,15 @@ use crate::{ assetbundle::AssetBundle, object::{Value, parser::FromValue}, + serialized_file::ExternalsContext, }; -use anyhow::{Result, anyhow, bail}; +use anyhow::{Context, Result, anyhow, bail}; use log::debug; use serde::Serialize; use std::{ io::{Read, Seek}, marker::PhantomData, + sync::Arc, }; #[derive(Debug, Serialize)] @@ -15,19 +17,15 @@ pub struct PPtr { #[serde(skip, default)] pub(crate) _class: PhantomData, pub class: String, - pub source_file: usize, + #[serde(skip)] + pub ecx: Arc, pub file_id: i32, pub path_id: i64, } impl FromValue for PPtr { fn from_value(v: Value) -> Result { - let Value::Object { - class, - fields, - file, - } = v - else { + let Value::Object { class, fields, ecx } = v else { bail!("PPtr expected but not an object") }; let inner = class @@ -38,7 +36,7 @@ impl FromValue for PPtr { Ok(PPtr { class: inner.to_owned(), _class: PhantomData, - source_file: file, + ecx, file_id: fields["m_FileID"] .as_i32() .ok_or(anyhow!("PPtr m_FileID is not i32"))?, @@ -54,7 +52,7 @@ impl PPtr { PPtr { _class: PhantomData, class: self.class, - source_file: self.source_file, + ecx: self.ecx.clone(), file_id: self.file_id, path_id: self.path_id, } @@ -67,32 +65,45 @@ impl PPtr { "loading PPtr<{}> file_id={} path_id={}", self.class, self.file_id, self.path_id ); - let main_file = match (self.source_file, self.file_id) { - (0, 0) => true, - (0, 1) => false, - (1, 0) => false, - _ => unreachable!(), + let path = if self.file_id == 0 { + &self.ecx.name + } else { + &self.ecx.externals[self.file_id as usize - 1].path_name }; - if main_file { - let ob = bundle - .main - .objects + if let Some(path) = path.strip_prefix("archive:") { + let path = path.split_once("/").unwrap_or(("", path)).1; + let ni = bundle + .fs + .header + .nodes() .iter() - .find(|o| o.path_id == self.path_id) - .ok_or(anyhow!("object with path id {} not found", self.path_id))? - .to_owned(); - bundle.main.read_object(ob)?.parse() - } else { - let file = bundle.shared_assets.as_mut().ok_or(anyhow!( - "shared assets referenced but not included in bundle" - ))?; + .find(|n| n.name == path) + .unwrap() + .clone(); + let file = bundle.get_fs_file(&ni).unwrap(); + let mut file = file.lock().unwrap(); let ob = file .objects .iter() .find(|o| o.path_id == self.path_id) - .ok_or(anyhow!("object with path id {} not found", self.path_id))? - .to_owned(); + .unwrap() + .clone(); file.read_object(ob)?.parse() + } else if *path == bundle.default_resources.ecx.name { + let ob = bundle + .default_resources + .objects + .iter() + .find(|o| o.path_id == self.path_id) + .unwrap() + .clone(); + bundle + .default_resources + .read_object(ob) + .context("reading object from default res file")? + .parse() + } else { + unreachable!("{path:?}") } } } diff --git a/src/classes/renderer.rs b/src/classes/renderer.rs new file mode 100644 index 0000000..cd50524 --- /dev/null +++ b/src/classes/renderer.rs @@ -0,0 +1,93 @@ +use super::{ + gameobject::GameObject, material::Material, mesh::Mesh, pptr::PPtr, transform::Transform, +}; +use crate::object::{ + Value, + parser::{Fields, FromValue}, +}; +use anyhow::{Context, Result}; + +pub struct Renderer { + pub enabled: bool, + pub cast_shadows: u8, + pub game_object: PPtr, + pub materials: Vec>, +} +pub struct MeshRenderer { + pub renderer: Renderer, + pub additional_vertex_streams: PPtr, +} + +pub struct SkinnedMeshRenderer { + pub renderer: Renderer, + pub bones: Vec>, + pub mesh: PPtr, + pub root_bone: PPtr, +} + +pub struct MeshFilter { + pub gameobject: PPtr, + pub mesh: PPtr, +} + +impl FromValue for Renderer { + fn from_value(v: Value) -> Result { + Self::from_fields(v.as_class("Renderer")?) + } +} +impl Renderer { + pub fn from_fields(mut fields: Fields) -> Result { + Ok(Self { + enabled: fields.field("m_Enabled")?, + cast_shadows: fields.field("m_CastShadows")?, + game_object: fields + .field("m_GameObject") + .context("gameobject of meshrenderer")?, + materials: fields + .remove("m_Materials") + .unwrap() + .as_vector() + .unwrap() + .into_iter() + .map(|e| e.parse().unwrap()) + .collect(), + }) + } +} + +impl FromValue for MeshRenderer { + fn from_value(v: Value) -> Result { + let mut fields = v.as_class("MeshRenderer")?; + Ok(Self { + additional_vertex_streams: fields.field("m_AdditionalVertexStreams")?, + renderer: Renderer::from_fields(fields)?, + }) + } +} +impl FromValue for SkinnedMeshRenderer { + fn from_value(v: Value) -> Result { + let mut fields = v.as_class("SkinnedMeshRenderer")?; + Ok(Self { + root_bone: fields.field("m_RootBone")?, + mesh: fields.field("m_Mesh")?, + bones: fields + .remove("m_Bones") + .unwrap() + .as_vector() + .unwrap() + .into_iter() + .map(|e| e.parse().unwrap()) + .collect(), + renderer: Renderer::from_fields(fields)?, + }) + } +} +impl FromValue for MeshFilter { + fn from_value(v: Value) -> Result { + let mut fields = v.as_class("MeshFilter")?; + Ok(Self { + mesh: fields.field("m_Mesh")?, + gameobject: fields.field("m_GameObject")?, + }) + } +} -- cgit v1.2.3-70-g09d2