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}