Skip to main content

uika_runtime/
weak_ptr.rs

1// TWeakObjectPtr<T>: typed weak reference to a UObject.
2// Does not prevent garbage collection. Can be resolved to UObjectRef<T>
3// if the object is still alive.
4
5use std::marker::PhantomData;
6
7use uika_ffi::{FWeakObjectHandle, UObjectHandle};
8
9use crate::api::api;
10use crate::object_ref::UObjectRef;
11use crate::traits::UeClass;
12
13/// A typed weak reference to a UObject.
14///
15/// Unlike `UObjectRef<T>`, a weak pointer uses UE's internal weak reference
16/// system (ObjectIndex + SerialNumber) which can reliably detect when an
17/// object has been garbage collected.
18///
19/// Use `get()` to attempt to resolve to a strong `UObjectRef<T>`.
20#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
21pub struct TWeakObjectPtr<T: UeClass> {
22    handle: FWeakObjectHandle,
23    _marker: PhantomData<*const T>,
24}
25
26unsafe impl<T: UeClass> Send for TWeakObjectPtr<T> {}
27
28impl<T: UeClass> TWeakObjectPtr<T> {
29    /// Create a weak pointer from a strong UObjectRef.
30    pub fn from_ref(obj: &UObjectRef<T>) -> Self {
31        let handle = unsafe { ((*api().core).make_weak)(obj.raw()) };
32        TWeakObjectPtr {
33            handle,
34            _marker: PhantomData,
35        }
36    }
37
38    /// Attempt to resolve to a strong reference. Returns `None` if the
39    /// object has been garbage collected.
40    pub fn get(&self) -> Option<UObjectRef<T>> {
41        let obj = unsafe { ((*api().core).resolve_weak)(self.handle) };
42        if obj == (UObjectHandle(std::ptr::null_mut())) {
43            None
44        } else {
45            Some(unsafe { UObjectRef::from_raw(obj) })
46        }
47    }
48
49    /// Check if the referenced object is still alive.
50    pub fn is_valid(&self) -> bool {
51        unsafe { ((*api().core).is_weak_valid)(self.handle) }
52    }
53
54    /// Get the underlying FFI handle.
55    #[inline]
56    pub fn handle(&self) -> FWeakObjectHandle {
57        self.handle
58    }
59}
60
61impl<T: UeClass> Default for TWeakObjectPtr<T> {
62    fn default() -> Self {
63        TWeakObjectPtr {
64            handle: FWeakObjectHandle::default(),
65            _marker: PhantomData,
66        }
67    }
68}