aboutsummaryrefslogtreecommitdiff
path: root/src/classes
diff options
context:
space:
mode:
Diffstat (limited to 'src/classes')
-rw-r--r--src/classes/assetinfo.rs23
-rw-r--r--src/classes/gameobject.rs40
-rw-r--r--src/classes/mod.rs109
-rw-r--r--src/classes/pptr.rs39
-rw-r--r--src/classes/transform.rs26
5 files changed, 237 insertions, 0 deletions
diff --git a/src/classes/assetinfo.rs b/src/classes/assetinfo.rs
new file mode 100644
index 0000000..dadcea3
--- /dev/null
+++ b/src/classes/assetinfo.rs
@@ -0,0 +1,23 @@
+use super::{gameobject::GameObject, pptr::PPtr};
+use crate::object::Value;
+use anyhow::Result;
+use serde::Serialize;
+
+#[derive(Debug, Serialize)]
+pub struct AssetInfo {
+ pub preload_index: i32,
+ pub preload_size: i32,
+ pub asset: PPtr<GameObject>,
+}
+impl AssetInfo {
+ pub fn from_value(v: Value) -> Result<Self> {
+ let mut fields = v.as_class("AssetInfo").unwrap();
+ Ok(AssetInfo {
+ preload_index: fields["preloadIndex"].as_i32().unwrap(),
+ preload_size: fields["preloadSize"].as_i32().unwrap(),
+ asset: PPtr::from_value(fields.remove("asset").unwrap())
+ .unwrap()
+ .cast(),
+ })
+ }
+}
diff --git a/src/classes/gameobject.rs b/src/classes/gameobject.rs
new file mode 100644
index 0000000..fde042d
--- /dev/null
+++ b/src/classes/gameobject.rs
@@ -0,0 +1,40 @@
+use anyhow::Result;
+use serde::Serialize;
+use crate::object::Value;
+use super::pptr::PPtr;
+
+#[derive(Debug, Serialize)]
+pub struct GameObject {
+ pub components: Vec<PPtr>,
+ pub layer: u32,
+ pub tag: u16,
+ pub name: String,
+ pub is_active: bool,
+}
+impl GameObject {
+ pub fn from_value(v: Value) -> Result<Self> {
+ let mut fields = v.as_class("GameObject").unwrap();
+ Ok(GameObject {
+ components: fields
+ .remove("m_Component")
+ .unwrap()
+ .as_array()
+ .unwrap()
+ .into_iter()
+ .map(|e| {
+ PPtr::from_value(
+ e.as_class("ComponentPair")
+ .unwrap()
+ .remove("component")
+ .unwrap(),
+ )
+ .unwrap()
+ })
+ .collect(),
+ layer: fields["m_Layer"].as_u32().unwrap(),
+ tag: fields["m_Tag"].as_u16().unwrap(),
+ name: fields["m_Name"].clone().as_string().unwrap(),
+ is_active: fields["m_IsActive"].as_bool().unwrap(),
+ })
+ }
+}
diff --git a/src/classes/mod.rs b/src/classes/mod.rs
new file mode 100644
index 0000000..bfde8ad
--- /dev/null
+++ b/src/classes/mod.rs
@@ -0,0 +1,109 @@
+pub mod assetinfo;
+pub mod gameobject;
+pub mod pptr;
+pub mod transform;
+
+use crate::object::Value;
+use anyhow::Result;
+use assetinfo::AssetInfo;
+use gameobject::GameObject;
+use pptr::PPtr;
+use serde::Serialize;
+use std::collections::BTreeMap;
+use transform::Transform;
+
+#[derive(Debug, Serialize)]
+pub enum HValue {
+ AssetInfo(AssetInfo),
+ GameObject(GameObject),
+ Transform(Transform),
+ PPtr(PPtr),
+
+ Pair(Box<HValue>, Box<HValue>),
+ Value([Value; 1]),
+ Map(BTreeMap<String, HValue>),
+ Array(Vec<HValue>),
+ Object {
+ class: String,
+ fields: BTreeMap<String, HValue>,
+ },
+}
+
+impl HValue {
+ pub fn from_value(v: Value) -> Result<HValue> {
+ Ok(match v {
+ value @ Value::Object { .. } => {
+ let class = value.class_name().unwrap();
+ match class.as_str() {
+ x if x.starts_with("PPtr<") => Self::PPtr(PPtr::from_value(value)?),
+ "AssetInfo" => Self::AssetInfo(AssetInfo::from_value(value)?),
+ "GameObject" => Self::GameObject(GameObject::from_value(value)?),
+ _ => {
+ let Value::Object { class, fields } = value else {
+ unreachable!()
+ };
+ let mut fields = fields
+ .into_iter()
+ .map(|(k, v)| Ok((k, HValue::from_value(v)?)))
+ .collect::<Result<BTreeMap<_, _>>>()?;
+ match class.as_str() {
+ "map" => {
+ let Self::Array(a) = fields.remove("Array").unwrap() else {
+ unreachable!()
+ };
+ Self::Map(
+ a.into_iter()
+ .map(|e| {
+ let Self::Pair(k, v) = e else { unreachable!() };
+ (k.as_value().unwrap().clone().as_string().unwrap(), *v)
+ })
+ .collect(),
+ )
+ }
+ "pair" => Self::Pair(
+ Box::new(fields.remove("first").unwrap()),
+ Box::new(fields.remove("second").unwrap()),
+ ),
+ "vector" => fields.remove("Array").unwrap(),
+ _ => Self::Object { class, fields },
+ }
+ }
+ }
+ }
+ Value::Array(a) => Self::Array(
+ a.into_iter()
+ .map(|e| HValue::from_value(e))
+ .collect::<Result<Vec<_>>>()?,
+ ),
+ x => Self::Value([x]),
+ })
+ }
+ pub fn as_value(&self) -> Option<&Value> {
+ if let HValue::Value(v) = self {
+ Some(&v[0])
+ } else {
+ None
+ }
+ }
+ pub fn as_pptr(self) -> Option<PPtr> {
+ if let HValue::PPtr(v) = self {
+ Some(v)
+ } else {
+ None
+ }
+ }
+ pub fn as_array(self) -> Option<Vec<HValue>> {
+ if let HValue::Array(v) = self {
+ Some(v)
+ } else {
+ None
+ }
+ }
+ pub fn as_class(self, name: &str) -> Option<BTreeMap<String, HValue>> {
+ if let HValue::Object { class, fields } = self {
+ if class == name { Some(fields) } else { None }
+ } else {
+ None
+ }
+ }
+}
diff --git a/src/classes/pptr.rs b/src/classes/pptr.rs
new file mode 100644
index 0000000..1f615ab
--- /dev/null
+++ b/src/classes/pptr.rs
@@ -0,0 +1,39 @@
+use super::HValue;
+use crate::object::Value;
+use anyhow::Result;
+use serde::Serialize;
+use std::marker::PhantomData;
+
+#[derive(Debug, Serialize)]
+pub struct PPtr<T = HValue> {
+ _class: PhantomData<T>,
+ pub class: String,
+ pub file_id: i32,
+ pub path_id: i64,
+}
+impl PPtr {
+ pub fn from_value(v: Value) -> Result<Self> {
+ let Value::Object { class, fields } = v else {
+ unreachable!()
+ };
+ let inner = class
+ .strip_prefix("PPtr<")
+ .unwrap()
+ .strip_suffix(">")
+ .unwrap();
+ Ok(PPtr {
+ class: inner.to_owned(),
+ _class: PhantomData,
+ file_id: fields["m_FileID"].as_i32().unwrap(),
+ path_id: fields["m_PathID"].as_i64().unwrap(),
+ })
+ }
+ pub fn cast<T>(self) -> PPtr<T> {
+ PPtr {
+ _class: PhantomData,
+ class: self.class,
+ file_id: self.file_id,
+ path_id: self.path_id,
+ }
+ }
+}
diff --git a/src/classes/transform.rs b/src/classes/transform.rs
new file mode 100644
index 0000000..518e248
--- /dev/null
+++ b/src/classes/transform.rs
@@ -0,0 +1,26 @@
+use super::pptr::PPtr;
+use crate::object::Value;
+use anyhow::Result;
+use serde::Serialize;
+
+#[derive(Debug, Serialize)]
+pub struct Transform {
+ pub father: PPtr<Transform>,
+ pub children: Vec<PPtr<Transform>>,
+}
+impl Transform {
+ pub fn from_value(v: Value) -> Result<Self> {
+ let mut fields = v.as_class("Transform").unwrap();
+ Ok(Self {
+ children: fields
+ .remove("m_Children")
+ .unwrap()
+ .as_array()
+ .unwrap()
+ .into_iter()
+ .map(|e| PPtr::from_value(e).unwrap().cast())
+ .collect(),
+ father: PPtr::from_value(fields.remove("m_Father").unwrap())?.cast(),
+ })
+ }
+}