Attribute Macro gdnative_derive::methods

source ·
#[methods]
Expand description

Collects method signatures of all functions in a NativeClass that have the #[method] attribute and registers them with Godot.

The #[methods] attribute can be used with both impl Type and impl Trait for Type blocks. The semantics change depending on whether a mix-in name is provided for the block.

Universal impl blocks: #[methods]

An impl block that doesn’t have a mixin parameter is universal. Universal #[methods] blocks must not overlap. Usually, this means that only one impl block per struct may be universal.

When applied to a generic impl, the impl block must apply to all monomorphizations of the type, i.e. be universal.

One applicable universal block must be present for each type one wishes to use as a NativeClass. Universal blocks are always registered automatically.

Mix-ins: #[methods(mixin = "Name")]

When given a name with the mixin argument, a block behaves instead as a mix-in block. #[method(mixin = "Name")] creates an opaque type called Name under the current scope, that can be manually registered to any type the impl block covers. This can be done in a register_with callback with builder.mixin::<MyMixin>().

Unlike universal blocks, mix-in blocks have a many-to-many relationship with the types they are registered to. Any number of mix-ins can be applied to any number of compatible types. This can be useful for reusing generics impls, or organizing code for big interfaces.

Additionally, the attribute accepts the following arguments:

  • #[methods(pub)]
    Mix-in types are private by default. The pub argument makes them public instead.

Example

Universal

use gdnative::prelude::*;

#[derive(NativeClass)]
#[inherit(Reference)]
#[no_constructor]
struct Foo {}

#[methods]
impl Foo {
    #[method]
    fn foo(&self, #[base] _base: &Reference, bar: i64) -> i64 {
        bar
    }
}

Mix-in

use gdnative::prelude::*;

#[derive(NativeClass)]
#[inherit(Reference)]
#[register_with(register_foo)]
#[no_constructor]
struct Foo {}

fn register_foo(builder: &ClassBuilder<Foo>) {
    builder.mixin::<FooMixin>();
}

#[methods(mixin = "FooMixin")]
impl Foo {
    #[method]
    fn foo(&self, #[base] _base: &Reference, bar: i64) -> i64 {
        bar
    }
}