handle possibility of missing static class (UMapProperty)

This commit is contained in:
Janis 2023-04-20 20:48:54 +02:00
parent 674a54afb9
commit 99a3effc4c

View file

@ -170,10 +170,34 @@ macro_rules! define_utypes {
#[derive(Debug, Clone, Copy)]
pub struct $ty(NonNull<UnsafeCell<()>>);
impl $ty {
pub const fn static_class_name() -> &'static str {
impl traits::StaticClass for $ty {
fn static_class_name() -> &'static str {
concat!("Class CoreUObject.", $name)
}
fn static_class() -> Option<UClass> {
use crate::global_tables::objects::{FindClass, GOBJECTS};
use once_cell::sync::OnceCell;
// this is something that we always do in C/C++ but unfortinately requires a blanket impl Sync + Send on all UObject types..
static CLASS: OnceCell<Option<UClass>> = OnceCell::new();
*CLASS.get_or_init(|| {
let class = match GOBJECTS
.read()
.unwrap()
.as_objects()
.unwrap()
.find_class(Self::static_class_name()) {
Some(class) => {Some(class)},
None => {
log::error!("static class \"{}\" not found!", Self::static_class_name());
None
}
};
log::info!("class for {} is {:?}", Self::static_class_name(), class);
class
})
}
}
impl_asuobject!($ty);
@ -192,6 +216,30 @@ macro_rules! define_utypes {
fn static_class_name() -> &'static str {
concat!("Class CoreUObject.", $name)
}
fn static_class() -> Option<UClass> {
use crate::global_tables::objects::{FindClass, GOBJECTS};
use once_cell::sync::OnceCell;
// this is something that we always do in C/C++ but unfortinately requires a blanket impl Sync + Send on all UObject types..
static CLASS: OnceCell<Option<UClass>> = OnceCell::new();
*CLASS.get_or_init(|| {
let class = match GOBJECTS
.read()
.unwrap()
.as_objects()
.unwrap()
.find_class(Self::static_class_name()) {
Some(class) => {Some(class)},
None => {
log::error!("static class \"{}\" not found!", Self::static_class_name());
None
}
};
log::info!("class for {} is {:?}", Self::static_class_name(), class);
class
})
}
}
impl_asuobject!($ty);
@ -453,15 +501,19 @@ impl UAnyType {
// remember to order this from most specialized to least.
// specifically: a UClass is also a UStruct, so check for UClass first,
// then for any other subtypes of UStruct, then for UStruct
if uobject.is_a(&UEnum::static_class()) {
Self::UEnum(unsafe { uobject.cast() })
} else if uobject.is_a(&UClass::static_class()) {
if uobject.is_a_maybe(&UClass::static_class()) {
Self::UClass(unsafe { uobject.cast() })
} else if uobject.is_a(&UScriptStruct::static_class()) {
} else if uobject.is_a_maybe(&UProperty::static_class()) {
Self::UProperty(unsafe { uobject.cast() })
} else if uobject.is_a_maybe(&UFunction::static_class()) {
Self::UFunction(unsafe { uobject.cast() })
} else if uobject.is_a_maybe(&UScriptStruct::static_class()) {
Self::UScriptStruct(unsafe { uobject.cast() })
} else if uobject.is_a(&UStruct::static_class()) {
} else if uobject.is_a_maybe(&UEnum::static_class()) {
Self::UEnum(unsafe { uobject.cast() })
} else if uobject.is_a_maybe(&UStruct::static_class()) {
Self::UStruct(unsafe { uobject.cast() })
} else if uobject.is_a(&UField::static_class()) {
} else if uobject.is_a_maybe(&UField::static_class()) {
Self::UField(unsafe { uobject.cast() })
} else {
Self::UObject(uobject)
@ -497,30 +549,15 @@ pub mod traits {
use anyhow::Context;
use itertools::Itertools;
use once_cell::sync::OnceCell;
use crate::fname::FName;
use crate::global_tables::objects::{FindClass, GOBJECTS};
use crate::tarray::{FString, TArray};
use super::{EObjectFlags, VTbl};
pub trait StaticClass {
fn static_class_name() -> &'static str;
fn static_class() -> super::UClass {
// this is something that we always do in C/C++ but unfortinately requires a blanket impl Sync + Send on all UObject types..
static CLASS: OnceCell<super::UClass> = OnceCell::new();
*CLASS.get_or_init(|| {
GOBJECTS
.read()
.unwrap()
.as_objects()
.unwrap()
.find_class(Self::static_class_name())
.expect("static class not found!")
})
}
fn static_class() -> Option<super::UClass>;
}
#[const_trait]
@ -601,6 +638,13 @@ pub mod traits {
.map(|class| class.iter_super_classes().contains(other))
.unwrap_or(false)
}
fn is_a_maybe(&self, other: &Option<super::UClass>) -> bool {
other
.as_ref()
.map(|class| self.is_a(class))
.unwrap_or(false)
}
}
impl<T> UObjectNonConst for T where T: UObjectTrait {}