diff --git a/src/sdk/process.rs b/src/sdk/process.rs index 8a7a922..55127bd 100644 --- a/src/sdk/process.rs +++ b/src/sdk/process.rs @@ -1,3 +1,4 @@ +use std::collections::BTreeSet; use std::collections::{btree_map::Entry, BTreeMap}; use anyhow::Context; @@ -11,8 +12,9 @@ use crate::v2_types::{ AsUObject, UArrayPropertyTrait, UBoolPropertyTrait, UEnumPropertyTrait, UEnumTrait, UObjectNonConst, UObjectTrait, UPropertyTrait, UStructPropertyTrait, *, }, - UClass, UEnum, UFunction, UProperty, UScriptStruct, + UClass, UEnum, UFunction, UProperty, }; +use crate::v2_types::{UScriptStruct, UStruct}; use super::repr::{ Class, ClassField, ClassMethod, Enum, Package, ProcessedPackage, Type, UnrealType, @@ -61,6 +63,7 @@ impl Enum { }); Ok(UnrealType::Enum(Enum { + obj_ref: value.as_uobject().object_ref(), name: value.get_name().context("could not get name")?, full_name: value.get_full_name().context("could not get full name")?, values, @@ -69,11 +72,107 @@ impl Enum { } impl Class { - pub fn from_uclass(value: UClass) -> anyhow::Result { - todo!() + pub fn from_uclass(class: UClass) -> anyhow::Result { + Ok(UnrealType::Class(Self { + kind: StructKind::Object, + ..Self::from_struct_inner(unsafe { class.cast() })? + })) } - pub fn from_uscriptstruct(value: UScriptStruct) -> anyhow::Result { - todo!() + + pub fn from_actor(class: UClass) -> anyhow::Result { + Ok(UnrealType::Actor(Self { + kind: StructKind::Actor, + ..Self::from_struct_inner(unsafe { class.cast() })? + })) + } + + pub fn from_struct(strct: UScriptStruct) -> anyhow::Result { + Ok(UnrealType::Struct(Self { + kind: StructKind::Struct, + ..Self::from_struct_inner(unsafe { strct.cast() })? + })) + } + + fn from_struct_inner(strct: UStruct) -> anyhow::Result { + let name = strct.get_name().context("could not get function name")?; + let full_name = strct + .get_full_name() + .context("could not get full function name")?; + + let super_class = strct.super_field().and_then(|supr| { + if supr != strct { + Some(supr.as_uobject().object_ref()) + } else { + None + } + }); + + let (fields, methods) = Self::process_children(&strct)?; + + Ok(Self { + obj_ref: strct.as_uobject().object_ref(), + kind: StructKind::Struct, + size: *strct.property_size() as u32, + name, + full_name, + super_class, + properties_size: *strct.property_size() as u32, + min_alignment: *strct.min_alignment() as u32, + fields, + methods, + }) + } + + /// returns tuple of (fields, methods) + fn process_children(strct: &UStruct) -> anyhow::Result<(Vec, Vec)> { + enum ClassChild { + Field(ClassField), + Method(ClassMethod), + } + + let (fields, methods) = strct + .iter_children() + .map(|field| -> anyhow::Result> { + let child = match any_type::AnyField::from_field(field) { + AnyField::Property(prop) => Some(ClassChild::Field(ClassField::from_uprop(prop)?)), + AnyField::Struct(strct) + if let AnyStruct::Function(func) = AnyStruct::from_struct(strct) => { + { + Some(ClassChild::Method(ClassMethod::from_ufunction(func)?)) + } + } + _ => None, + }; + + Ok(child) + }) + .fold_ok( + (Vec::new(), Vec::new()), + |(mut fields, mut methods), child| { + if let Some(child) = child { + match child { + ClassChild::Field(field) => fields.push(field), + ClassChild::Method(method) => methods.push(method), + } + } + (fields, methods) + }, + )?; + + Ok((fields, methods)) + } + + pub fn get_dependent_types(&self) -> Vec { + self.fields + .iter() + .filter_map(|field| field.ty.dependent_type()) + .chain( + self.methods + .iter() + .flat_map(|method| method.get_dependent_types()), + ) + .chain(self.super_class) + .collect::>() } } @@ -90,6 +189,10 @@ impl ClassField { ty: resolve_type(prop).context("failed to get field type")?, }) } + + pub fn get_dependent_types(&self) -> Vec { + self.ty.dependent_type().into_iter().collect() + } } impl ClassMethod { @@ -115,6 +218,13 @@ impl ClassMethod { parameters: params, }) } + + pub fn get_dependent_types(&self) -> Vec { + self.parameters + .iter() + .filter_map(|field| field.ty.dependent_type()) + .collect() + } } impl Package {