gdnative_core/export/
signal.rs

1use crate::core_types::{GodotString, Variant, VariantType};
2use crate::export::{ClassBuilder, ExportInfo, NativeClass, PropertyUsage};
3
4/// Class to construct a signal. Make sure to call [`Self::done()`] in the end.
5///
6/// Signal parameters can be added with the various `param*()` methods.
7/// Keep in mind that unlike function parameters, signal parameters (both their lengths and types)
8/// are not statically checked in Godot. The parameter signature you specify is simply to assist you
9/// in the editor UI and with auto-generation of GDScript signal handlers.
10#[must_use = "SignalBuilder left unbuilt -- did you forget to call done()?"]
11pub struct SignalBuilder<'a, C> {
12    class_builder: &'a ClassBuilder<C>,
13    name: GodotString,
14    args: Vec<SignalParam>,
15}
16
17impl<'a, C: NativeClass> SignalBuilder<'a, C> {
18    pub(super) fn new(class_builder: &'a ClassBuilder<C>, signal_name: GodotString) -> Self {
19        Self {
20            class_builder,
21            name: signal_name,
22            args: vec![],
23        }
24    }
25
26    /// Add a parameter for the signal with a name and type.
27    ///
28    /// Note that GDScript signal parameters are generally untyped and not checked at runtime.
29    /// The type is solely used for UI purposes.
30    #[inline]
31    pub fn with_param(self, parameter_name: &str, parameter_type: VariantType) -> Self {
32        self.with_param_custom(SignalParam {
33            name: parameter_name.into(),
34            default: Variant::nil(),
35            export_info: ExportInfo::new(parameter_type),
36            usage: PropertyUsage::DEFAULT,
37        })
38    }
39
40    /// Add a parameter for the signal with a name and default value.
41    ///
42    /// The type is inferred from the default value.
43    /// Note that GDScript signal parameters are generally untyped and not checked at runtime.
44    /// The type is solely used for UI purposes.
45    #[inline]
46    pub fn with_param_default(self, parameter_name: &str, default_value: Variant) -> Self {
47        let variant_type = default_value.get_type();
48
49        self.with_param_custom(SignalParam {
50            name: parameter_name.into(),
51            default: default_value,
52            export_info: ExportInfo::new(variant_type),
53            usage: PropertyUsage::DEFAULT,
54        })
55    }
56
57    /// Add a (untyped) parameter for the signal with a name.
58    ///
59    /// Types are not required or checked at runtime, but they help for editor UI and auto-generation of signal listeners.
60    #[inline]
61    pub fn with_param_untyped(self, parameter_name: &str) -> Self {
62        // Note: the use of 'Nil' to express "untyped" is not following official documentation and could be improved.
63
64        self.with_param_custom(SignalParam {
65            name: parameter_name.into(),
66            default: Variant::nil(),
67            export_info: ExportInfo::new(VariantType::Nil),
68            usage: PropertyUsage::DEFAULT,
69        })
70    }
71
72    /// Add a parameter for the signal, manually configured.
73    #[inline]
74    pub fn with_param_custom(mut self, parameter: SignalParam) -> Self {
75        self.args.push(parameter);
76        self
77    }
78
79    /// Finish registering the signal.
80    #[inline]
81    pub fn done(self) {
82        self.class_builder.add_signal(Signal {
83            name: self.name,
84            args: self.args,
85        });
86    }
87}
88
89pub(crate) struct Signal {
90    pub name: GodotString,
91    pub args: Vec<SignalParam>,
92}
93
94/// Parameter in a signal declaration.
95///
96/// Instead of providing values for each field, check out the `param*()` methods in [`SignalBuilder`].
97pub struct SignalParam {
98    /// Parameter name.
99    pub name: GodotString,
100
101    /// Default value, used when no argument is provided.
102    pub default: Variant,
103
104    /// Metadata and UI hints about exporting, e.g. parameter type.
105    pub export_info: ExportInfo,
106
107    /// In which context the signal parameter is used.
108    pub usage: PropertyUsage,
109}