Exported properties
Like methods, properties can be exported. The #[property]
attribute above a field declaration makes the field available to Godot, with its name and type.
In the previous example, we could replace the count_enemies()
method with a property enemy_count
.
The GDScript code would be changed as follows.
print("enemies: ", api.enemy_count)
That's it.
Export options
The #[property]
attribute can accept a several options to refine the export behavior.
You can specify default property value with the following argument:
If you need to hide this property in Godot editor, use no_editor
option:
Property get/set
Properties can register set
and get
methods to be called from Godot.
Default get/set functions can be registered as per the following example:
#[derive(NativeClass, Default)]
#[inherit(Node)]
struct GodotApi {
// property registration
// Note: This is actually equivalent to #[property]
#[property(get, set)]
prop: i32,
}
If you need custom setters and getters, you can set them in the property
attribute such as in the following example:
Note: get
vs get_ref
There are two ways to return the property.
get
will return a value ofT
which must result in the value being cloned.get_ref
must point to a function that returns&T
, this is useful when working with large data that would be very expensive to copy unnecessarily.
Modifying the previous example accordingly results in the following:
Manual property registration
For cases not covered by the #[property]
attribute, it may be necessary to manually register the properties instead.
This is often the case where custom hint behavior is desired for primitive types, such as an Integer value including an IntEnum
hint.
To do so, you can use the ClassBuilder
-- such as in the following examples -- to manually register each property and customize how they interface in the editor.
Property<T>
and when to use it
Sometimes it can be useful to expose a value as a property instead of as a function. Properties of this type serve as a marker that can be registered with Godot and viewed in the editor without containing any data in Rust.
This can be useful for data (similar to the first sample) where the count serves more as a property of enemies
rather than as its own distinct data, such as the following:
struct Enemy {
// Enemy Data
}
#[derive(NativeClass)]
struct GodotApi {
enemies: Vec<Enemy>,
// Note: As the property is a "marker" property, this will never be used in code.
#[allow(dead_code)]
#[property(get = "Self::get_size")]
enemy_count: Property<u32>,
}
#[methods]
impl GodotApi {
//...
fn get_size(&self, _base: TRef<Reference>) -> u32 {
self.enemies.len() as u32
}
}