Skip to main content

rusteal_core/
soft_ref.rs

1// SoftObjectRef<T>: UE's TSoftObjectPtr<T>, a reference to an asset by path
2// that does not keep it loaded.
3
4use std::fmt;
5use std::marker::PhantomData;
6
7use crate::error::RustealResult;
8use crate::object_ref::UObjectRef;
9use crate::traits::UeClass;
10use crate::world;
11
12/// A soft reference to an object of class `T`: its path
13/// (`/Game/Meshes/SM_Rifle.SM_Rifle`), loaded on demand. A `#[uproperty]` or
14/// `#[ustruct]` field of this type is a `TSoftObjectPtr<T>`.
15pub struct SoftObjectRef<T: UeClass> {
16    path: String,
17    _marker: PhantomData<T>,
18}
19
20impl<T: UeClass> SoftObjectRef<T> {
21    /// A reference to the object at `path`; empty for none.
22    pub fn new(path: impl Into<String>) -> Self {
23        SoftObjectRef {
24            path: path.into(),
25            _marker: PhantomData,
26        }
27    }
28
29    /// No reference.
30    pub fn null() -> Self {
31        Self::new(String::new())
32    }
33
34    /// The object's path, empty for none.
35    pub fn path(&self) -> &str {
36        &self.path
37    }
38
39    /// Whether it refers to nothing.
40    pub fn is_null(&self) -> bool {
41        self.path.is_empty()
42    }
43
44    /// The object if it is loaded, without loading it (`TSoftObjectPtr::Get`).
45    pub fn get(&self) -> UObjectRef<T> {
46        if self.is_null() {
47            return UObjectRef::null();
48        }
49        world::find_object_raw(T::static_class(), &self.path)
50            .map(|h| unsafe { UObjectRef::from_raw(h) })
51            .unwrap_or_else(|_| UObjectRef::null())
52    }
53
54    /// The object, loaded if it is not (`TSoftObjectPtr::LoadSynchronous`); a
55    /// null reference for none.
56    pub fn load_synchronous(&self) -> RustealResult<UObjectRef<T>> {
57        if self.is_null() {
58            return Ok(UObjectRef::null());
59        }
60        let handle = world::load_object_raw(T::static_class(), &self.path)?;
61        Ok(unsafe { UObjectRef::from_raw(handle) })
62    }
63}
64
65impl<T: UeClass> Default for SoftObjectRef<T> {
66    fn default() -> Self {
67        Self::null()
68    }
69}
70
71impl<T: UeClass> Clone for SoftObjectRef<T> {
72    fn clone(&self) -> Self {
73        Self::new(self.path.clone())
74    }
75}
76
77impl<T: UeClass> PartialEq for SoftObjectRef<T> {
78    fn eq(&self, other: &Self) -> bool {
79        self.path == other.path
80    }
81}
82
83impl<T: UeClass> Eq for SoftObjectRef<T> {}
84
85impl<T: UeClass> fmt::Debug for SoftObjectRef<T> {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        f.debug_tuple("SoftObjectRef").field(&self.path).finish()
88    }
89}