gdnative_bindings/
utils.rs

1//! Utility functions and extension traits that depend on generated bindings
2
3use gdnative_core::core_types::NodePath;
4use gdnative_core::export::NativeClass;
5use gdnative_core::object::{SubClass, TInstance, TRef};
6
7use super::generated::{Engine, Node, SceneTree};
8
9/// Convenience method  to obtain a reference to an "auto-load" node, that is a child of the root
10/// node.
11///
12/// Returns `None` if the node does not exist or is not of the correct type.
13///
14/// # Safety
15///
16/// This method accesses the scene tree. As a result, any calls to this function must
17/// follow the official [thread-safety guidelines][thread-safety]. `assume_safe`
18/// invariants must be observed for the resulting node during `'a`, if any.
19///
20/// [thread-safety]: https://docs.godotengine.org/en/stable/tutorials/threads/thread_safe_apis.html
21pub unsafe fn autoload<'a, T>(name: &str) -> Option<TRef<'a, T>>
22where
23    T: SubClass<Node>,
24{
25    Engine::godot_singleton()
26        .get_main_loop()?
27        .assume_safe()
28        .cast::<SceneTree>()?
29        .root()?
30        .assume_safe()
31        .get_node(name)?
32        .assume_safe()
33        .cast::<T>()
34}
35
36pub trait NodeResolveExt<P: Into<NodePath>> {
37    /// Convenience method to obtain a reference to a node at `path` relative to `self`,
38    /// and cast it to the desired type. Returns `None` if the node does not exist or is
39    /// not of the correct type.
40    ///
41    /// # Safety
42    ///
43    /// This method accesses the scene tree. As a result, any calls to this function must
44    /// follow the official [thread-safety guidelines][thread-safety]. `assume_safe`
45    /// invariants must be observed for the resulting node during `'a`, if any.
46    ///
47    /// [thread-safety]: https://docs.godotengine.org/en/stable/tutorials/threads/thread_safe_apis.html
48    unsafe fn get_node_as<'a, T>(&self, path: P) -> Option<TRef<'a, T>>
49    where
50        T: SubClass<Node>;
51
52    /// Convenience method to obtain a reference to a node at `path` relative to `self`,
53    /// and cast it to an instance of the desired `NativeClass` type. Returns `None` if
54    /// the node does not exist or is not of the correct type.
55    ///
56    /// # Safety
57    ///
58    /// This method accesses the scene tree. As a result, any calls to this function must
59    /// follow the official [thread-safety guidelines][thread-safety]. `assume_safe`
60    /// invariants must be observed for the resulting node during `'a`, if any.
61    ///
62    /// [thread-safety]: https://docs.godotengine.org/en/stable/tutorials/threads/thread_safe_apis.html
63    unsafe fn get_node_as_instance<'a, T>(&self, path: P) -> Option<TInstance<'a, T>>
64    where
65        T: NativeClass,
66        T::Base: SubClass<Node>,
67    {
68        self.get_node_as::<T::Base>(path)?.cast_instance()
69    }
70}
71
72impl<N: SubClass<Node>, P: Into<NodePath>> NodeResolveExt<P> for N {
73    unsafe fn get_node_as<'a, T>(&self, path: P) -> Option<TRef<'a, T>>
74    where
75        T: SubClass<Node>,
76    {
77        self.upcast().get_node(path)?.assume_safe().cast()
78    }
79}