Open
Description
Objects that have scripts written in other languages attached can be passed to methods in Rust, the functionality provided by those scripts can't be accessed easily.
This is a proposal to create a procedural macro to use a trait
as the description for an interface of an object.
An implementation of such a trait would use godot_variant_call
to perform the calls.
All functions in the trait
have to return a result type to represent the varcall failing.
When an object is used as an implementation of this interface no immediate checks are performed. Doing type-checking is not possible in the general case, so checks should be performed lazily.
This could work like this:
# adder.gd
extends Reference
var _value = 0
func add(amount: int) -> void:
_value += amount
func tell() -> int:
return _value
// src/lib.rs
// ... [ snip ] ...
#[gdnative::external_interface]
trait Adder: ExtInterface<Base = Reference> {
fn add(&mut self, amount: i64) -> ExtResult<()>;
fn tell(&self) -> ExtResult<i64>;
}
#[derive(gdnative::ExtInterfaceImpl)]
#[gdnative::ext_interface(Adder)]
struct AdderImpl<'a>;
/*
// possible definition of impl-trait
trait ExtInterfaceImpl<'a> {
type Interface: ExtInterface;
fn from(base: &'a Self::Interface::Base) -> Self;
}
*/
// ... [ snip ] ...
#[export]
fn set_to_one_hundred(&self, _owner: Reference, adder: Reference) {
use gdnative::ExtInterfaceImpl;
let adder = AdderImpl::from(&adder);
let current = if let Ok(val) = adder.tell() {
val
} else {
return;
}
let difference = 100 - current;
if difference <= 0 {
return;
}
// TODO check result, maybe the type does not actually implement the interface
let _ = adder.add(different);
let new_value = adder.tell().unwrap_or(0):
assert_eq!(new_value, 100);
}