Struct OnEditor
pub struct OnEditor<T> { /* private fields */ }
Expand description
Exported property that must be initialized in the editor (or associated code) before use.
Use this type whenever your Rust code cannot provide a value for a field, but expects one to be specified in the Godot editor.
If you need automatic initialization during ready()
, e.g. for loading nodes or resources, use OnReady<Gd<T>>
instead. As a general “maybe initialized” type, Option<Gd<T>>
is always available, even if more verbose.
§What consitutes “initialized”?
Whether a value is considered initialized or not depends on T
.
- For objects, a value is initialized if it is not null. Exported object propreties in Godot are nullable, but
Gd<T>
andDynGd<T, D>
do not support nullability and can thus not directly be exported with#[export]
.OnEditor
can bridge this gap, by expecting users to set a non-null value, and panicking if they don’t. - For built-in types, a value is initialized if it is different from a user-selected sentinel value (e.g.
-1
).
More on this below (see also table-of-contents sidebar).
§Initialization semantics
Panics during access (Deref/DerefMut
impls) if uninitialized.
When used inside a node class, OnEditor
checks if a value has been set before ready()
is run, and panics otherwise.
This validation is performed for all OnEditor
fields declared in a given GodotClass
, regardless of whether they are #[var]
, #[export]
, or neither.
Once initialized, OnEditor
can be used almost as if it were a T
value itself, due to Deref
/DerefMut
impls.
OnEditor<T>
should always be used as a struct field, preferably in tandem with an #[export]
or #[var]
.
Initializing OnEditor
values via code before the first use is supported, but should be limited to use cases involving builder or factory patterns.
§Using OnEditor
with classes
You can wrap class smart pointers Gd<T>
and DynGd<T, D>
inside OnEditor
, to make them exportable.
Gd<T>
itself does not implement the Export
trait.
§Example: automatic init
This example uses the Default
impl, which expects a non-null value to be provided.
#[derive(GodotClass)]
#[class(init, base = Node)]
struct ResourceHolder {
#[export]
editor_property: OnEditor<Gd<Resource>>,
}
#[godot_api]
impl INode for ResourceHolder {
fn ready(&mut self) {
// Will always be valid and **must** be set via editor.
// Additional check is being run before ready(),
// to ensure that given value can't be null.
let some_variant = self.editor_property.get_meta("SomeName");
}
}
§Example: user-defined init
Uninitialized OnEditor<Gd<T>>
and OnEditor<DynGd<T, D>>
can be created with OnEditor::default()
.
#[derive(GodotClass)]
#[class(base = Node)]
struct NodeHolder {
#[export]
required_node: OnEditor<Gd<Node>>,
base: Base<Node>
}
#[godot_api]
impl INode for NodeHolder {
fn init(base: Base<Node>) -> Self {
Self {
base,
required_node: OnEditor::default(),
}
}
}
§Example: factory pattern
#[derive(GodotClass)]
#[class(init, base = Node)]
struct NodeHolder {
#[export]
required_node: OnEditor<Gd<Node>>,
}
fn create_and_add(
mut this: Gd<Node>,
some_class_scene: Gd<PackedScene>,
some_node: Gd<Node>,
) -> Gd<NodeHolder> {
let mut my_node = some_class_scene.instantiate_as::<NodeHolder>();
// Would cause a panic:
// this.add_child(&my_node);
// It's possible to initialize the value programmatically, although typically
// it is set in the editor and stored in a .tscn file.
// Note: nodes are manually managed and leak memory unless tree-attached or freed.
my_node.bind_mut().required_node.init(some_node);
// Will not panic, since the node is initialized now.
this.add_child(&my_node);
my_node
}
§Using OnEditor
with built-in types
OnEditor<T>
can be used with any #[export]
-enabled builtins, to provide domain-specific validation logic.
An example might be to check whether a game entity has been granted a non-zero ID.
To detect whether a value has been set in the editor, OnEditor<T>
uses a sentinel value. This is a special marker value for
“uninitialized” and is selected by the user. For example, a sentinel value of -1
or 0
might be used to represent an uninitialized i32
.
There is deliberately no Default
implementation for OnEditor
with builtins, as the sentinel is highly domain-specific.
§Example
use godot::prelude::*;
#[derive(GodotClass)]
#[class(init, base = Node)]
struct IntHolder {
// Uninitialized value will be represented by `42` in the editor.
// Will cause panic if not set via the editor or code before use.
#[export]
#[init(sentinel = 42)]
some_primitive: OnEditor<i64>,
}
fn create_and_add(mut this: Gd<Node>, val: i64) -> Gd<IntHolder> {
let mut my_node = IntHolder::new_alloc();
// Would cause a panic:
// this.add_child(&my_node);
// It's possible to initialize the value programmatically, although typically
// it is set in the editor and stored in a .tscn file.
my_node.bind_mut().some_primitive.init(val);
// Will not panic, since the node is initialized now.
this.add_child(&my_node);
my_node
}
§Using OnEditor
with #[class(tool)]
When used with #[class(tool)]
, the before-ready checks are omitted.
Otherwise, OnEditor<T>
behaves the same — accessing an uninitialized value will cause a panic.
Implementations§
§impl<T> OnEditor<T>
OnEditor<T>
is usable only for properties – which is enforced via Var
and FromGodot
bounds.
impl<T> OnEditor<T>
OnEditor<T>
is usable only for properties – which is enforced via Var
and FromGodot
bounds.
Furthermore, PartialEq
is needed to compare against uninitialized sentinel values.
pub fn init(&mut self, val: T)
pub fn init(&mut self, val: T)
pub fn from_sentinel(val: T) -> OnEditor<T>
pub fn from_sentinel(val: T) -> OnEditor<T>
Creates new OnEditor<T>
with a value that is considered invalid.
If this value is not changed in the editor, accessing it from Rust will cause a panic.
Trait Implementations§
§impl<T> Default for OnEditor<Gd<T>>where
T: GodotClass,
impl<T> Default for OnEditor<Gd<T>>where
T: GodotClass,
§impl<T, D> Export for OnEditor<DynGd<T, D>>
#[export]
for OnEditor<DynGd<T, D>>
is available only for T
being Engine class (such as Node or Resource).
impl<T, D> Export for OnEditor<DynGd<T, D>>
#[export]
for OnEditor<DynGd<T, D>>
is available only for T
being Engine class (such as Node or Resource).
Consider exporting OnEditor<Gd<T>>
instead of OnEditor<DynGd<T, D>>
for user-declared GDExtension classes.
§fn export_hint() -> PropertyHintInfo
fn export_hint() -> PropertyHintInfo
§impl<T> Export for OnEditor<Gd<T>>
impl<T> Export for OnEditor<Gd<T>>
§fn export_hint() -> PropertyHintInfo
fn export_hint() -> PropertyHintInfo
§impl<T> Export for OnEditor<T>
impl<T> Export for OnEditor<T>
§fn export_hint() -> PropertyHintInfo
fn export_hint() -> PropertyHintInfo
§impl<T, D> GodotConvert for OnEditor<DynGd<T, D>>where
T: GodotClass,
D: ?Sized,
impl<T, D> GodotConvert for OnEditor<DynGd<T, D>>where
T: GodotClass,
D: ?Sized,
§impl<T> GodotConvert for OnEditor<Gd<T>>
impl<T> GodotConvert for OnEditor<Gd<T>>
§impl<T> GodotConvert for OnEditor<T>
impl<T> GodotConvert for OnEditor<T>
§type Via = <T as GodotConvert>::Via
type Via = <T as GodotConvert>::Via
Self
is represented in Godot.§impl<T, D> Var for OnEditor<DynGd<T, D>>where
T: GodotClass,
D: 'static + ?Sized,
impl<T, D> Var for OnEditor<DynGd<T, D>>where
T: GodotClass,
D: 'static + ?Sized,
fn get_property(&self) -> <OnEditor<DynGd<T, D>> as GodotConvert>::Via
fn set_property(&mut self, value: <OnEditor<DynGd<T, D>> as GodotConvert>::Via)
§fn var_hint() -> PropertyHintInfo
fn var_hint() -> PropertyHintInfo
GodotType::property_info
, e.g. for enums/newtypes.§impl<T> Var for OnEditor<Gd<T>>where
T: GodotClass,
impl<T> Var for OnEditor<Gd<T>>where
T: GodotClass,
fn get_property(&self) -> <OnEditor<Gd<T>> as GodotConvert>::Via
fn set_property(&mut self, value: <OnEditor<Gd<T>> as GodotConvert>::Via)
§fn var_hint() -> PropertyHintInfo
fn var_hint() -> PropertyHintInfo
GodotType::property_info
, e.g. for enums/newtypes.§impl<T> Var for OnEditor<T>where
OnEditor<T>: GodotConvert<Via = <T as GodotConvert>::Via>,
T: Var + FromGodot + PartialEq,
<T as GodotConvert>::Via: BuiltinExport,
impl<T> Var for OnEditor<T>where
OnEditor<T>: GodotConvert<Via = <T as GodotConvert>::Via>,
T: Var + FromGodot + PartialEq,
<T as GodotConvert>::Via: BuiltinExport,
fn get_property(&self) -> <OnEditor<T> as GodotConvert>::Via
fn set_property(&mut self, value: <T as GodotConvert>::Via)
§fn var_hint() -> PropertyHintInfo
fn var_hint() -> PropertyHintInfo
GodotType::property_info
, e.g. for enums/newtypes.