You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: godot-core/src/obj/on_editor.rs
+67-47
Original file line number
Diff line number
Diff line change
@@ -10,63 +10,81 @@ use crate::registry::property::{BuiltinExport, Export, Var};
10
10
11
11
/// Exported property that must be initialized in the editor (or associated code) before use.
12
12
///
13
-
/// Allows to use `Gd<T>`, which by itself never holds null objects, as an `#[export]` that should not be null during runtime.
14
-
/// As such, it can be used as a more ergonomic version of `Option<Gd<T>>` which _assumes_ initialization.
13
+
/// Use this type whenever your Rust code cannot provide a value for a field, but expects one to be specified in the Godot editor.
14
+
///
15
+
/// If you need automatic initialization during `ready()`, e.g. for loading nodes or resources, use [`OnReady<Gd<T>>`](crate::obj::OnReady)
16
+
/// instead. As a general "maybe initialized" type, `Option<Gd<T>>` is always available, even if more verbose.
17
+
///
18
+
///
19
+
/// # What consitutes "initialized"?
20
+
///
21
+
/// Whether a value is considered initialized or not depends on `T`.
22
+
///
23
+
/// - For objects, a value is initialized if it is not null. Exported object propreties in Godot are nullable, but `Gd<T>` and `DynGd<T, D>` do
24
+
/// not support nullability and can thus not directly be exported with `#[export]`. `OnEditor` can bridge this gap, by expecting users
25
+
/// to set a non-null value, and panicking if they don't.
26
+
/// - For built-in types, a value is initialized if it is different from a user-selected sentinel value (e.g. `-1`).
27
+
///
28
+
/// More on this below (see also table-of-contents sidebar).
29
+
///
30
+
/// # Initialization semantics
31
+
///
32
+
/// Panics during access (`Deref/DerefMut` impls) if uninitialized.
15
33
///
16
-
/// Panics during access if uninitialized.
17
34
/// When used inside a node class, `OnEditor` checks if a value has been set before `ready()` is run, and panics otherwise.
18
35
/// This validation is performed for all `OnEditor` fields declared in a given `GodotClass`, regardless of whether they are `#[var]`, `#[export]`, or neither.
19
-
/// Once initialized, it can be used almost as if it was a `T` value itself, due to `Deref`/`DerefMut` impls.
36
+
/// Once initialized, `OnEditor` can be used almost as if it were a `T` value itself, due to `Deref`/`DerefMut` impls.
20
37
///
21
-
/// `OnEditor<T>` should always be used as a property, preferably in tandem with an `#[export]` or `#[var]`.
22
-
/// Initializing `OnEditor` values via code before the first use is supported but should be limited to use cases involving builder or factory patterns.
38
+
/// `OnEditor<T>` should always be used as a struct field, preferably in tandem with an `#[export]` or `#[var]`.
39
+
/// Initializing `OnEditor` values via code before the first use is supported, but should be limited to use cases involving builder or factory patterns.
23
40
///
24
-
/// [`Option<Gd<T>>`](std::option) and [`OnReady<Gd<T>>`](crate::obj::onready::OnReady) should be used for any other late initialization logic.
25
41
///
26
-
/// # Using `OnEditor<T>` with `Gd<T>` and `DynGd<T, D>`
42
+
/// # Using `OnEditor` with classes
27
43
///
28
-
/// ## Example - auto-generated init
44
+
/// You can wrap class smart pointers `Gd<T>` and `DynGd<T, D>` inside `OnEditor`, to make them exportable.
45
+
/// `Gd<T>` itself does not implement the `Export` trait.
29
46
///
30
-
/// ```
31
-
/// use godot::prelude::*;
47
+
/// ## Example: automatic init
32
48
///
49
+
/// This example uses the `Default` impl, which expects a non-null value to be provided.
50
+
///
51
+
/// ```
52
+
/// # use godot::prelude::*;
33
53
/// #[derive(GodotClass)]
34
54
/// #[class(init, base = Node)]
35
-
/// struct MyClass {
55
+
/// struct ResourceHolder {
36
56
/// #[export]
37
57
/// editor_property: OnEditor<Gd<Resource>>,
38
58
/// }
39
59
///
40
60
/// #[godot_api]
41
-
/// impl INode for MyClass {
61
+
/// impl INode for ResourceHolder {
42
62
/// fn ready(&mut self) {
43
63
/// // Will always be valid and **must** be set via editor.
44
-
/// // Additional check is being run before ready()
64
+
/// // Additional check is being run before ready(),
45
65
/// // to ensure that given value can't be null.
46
66
/// let some_variant = self.editor_property.get_meta("SomeName");
47
67
/// }
48
68
/// }
49
-
///
50
69
/// ```
51
70
///
52
-
/// ## Example - user-generated init
71
+
/// ## Example: user-defined init
53
72
///
54
-
/// Uninitialized `OnEditor<Gd<T>>` and `OnEditor<DynGd<T, D>>` can be created with `OnEditor<...>::default()`.
73
+
/// Uninitialized `OnEditor<Gd<T>>` and `OnEditor<DynGd<T, D>>` can be created with `OnEditor::default()`.
55
74
///
56
75
/// ```
57
-
/// use godot::prelude::*;
58
-
///
76
+
/// # use godot::prelude::*;
59
77
/// #[derive(GodotClass)]
60
78
/// #[class(base = Node)]
61
-
/// struct MyClass {
79
+
/// struct NodeHolder {
62
80
/// #[export]
63
81
/// required_node: OnEditor<Gd<Node>>,
64
82
///
65
83
/// base: Base<Node>
66
84
/// }
67
85
///
68
86
/// #[godot_api]
69
-
/// impl INode for MyClass {
87
+
/// impl INode for NodeHolder {
70
88
/// fn init(base: Base<Node>) -> Self {
71
89
/// Self {
72
90
/// base,
@@ -76,14 +94,13 @@ use crate::registry::property::{BuiltinExport, Export, Var};
76
94
/// }
77
95
///```
78
96
///
79
-
/// ## Example - factory pattern
97
+
/// ## Example: factory pattern
80
98
///
81
99
/// ```
82
-
/// use godot::prelude::*;
83
-
///
100
+
/// # use godot::prelude::*;
84
101
/// #[derive(GodotClass)]
85
102
/// #[class(init, base = Node)]
86
-
/// struct SomeClass {
103
+
/// struct NodeHolder {
87
104
/// #[export]
88
105
/// required_node: OnEditor<Gd<Node>>,
89
106
/// }
@@ -92,67 +109,70 @@ use crate::registry::property::{BuiltinExport, Export, Var};
92
109
/// mut this: Gd<Node>,
93
110
/// some_class_scene: Gd<PackedScene>,
94
111
/// some_node: Gd<Node>,
95
-
/// ) -> Gd<SomeClass> {
96
-
/// let mut my_node = some_class_scene.instantiate_as::<SomeClass>();
112
+
/// ) -> Gd<NodeHolder> {
113
+
/// let mut my_node = some_class_scene.instantiate_as::<NodeHolder>();
97
114
///
98
-
/// // Would cause the panic:
115
+
/// // Would cause a panic:
99
116
/// // this.add_child(&my_node);
100
117
///
101
-
/// // Note: Remember that nodes are manually managed.
102
-
/// // They will leak memory if not added to tree and/or pruned.
118
+
/// // It's possible to initialize the value programmatically, although typically
119
+
/// // it is set in the editor and stored in a .tscn file.
120
+
/// // Note: nodes are manually managed and leak memory unless tree-attached or freed.
0 commit comments