godot::obj

Struct DynGd

pub struct DynGd<T, D>
where T: GodotClass, D: ?Sized,
{ /* private fields */ }
Expand description

Smart pointer integrating Rust traits via dyn dispatch.

DynGd<T, D> extends a Godot object Gd<T> with functionality for Rust’s trait dynamic dispatch.
In this context, the type parameters have the following meaning:

  • T is the Godot class.
  • D is a trait object dyn Trait, where T: Trait.

To register the T -> D relation with godot-rust, T must implement AsDyn<D>. This can be automated with the #[godot_dyn] attribute macro.

§Construction and API

You can convert between Gd and DynGd using Gd::into_dyn() and DynGd::into_gd(). The former sometimes needs an explicit ::<dyn Trait> type argument, but can often be inferred.

The DynGd API is very close to Gd. In fact, both Deref and DerefMut are implemented for DynGd -> Gd, so you can access all the underlying Gd methods as well as Godot class APIs directly.

The main new parts are two methods dyn_bind() and dyn_bind_mut(). These are very similar to Gd’s bind() and bind_mut(), but return a reference guard to the trait object D instead of the Godot class T.

§Example

use godot::obj::{Gd, DynGd,NewGd};
use godot::register::{godot_dyn, GodotClass};
use godot::classes::RefCounted;

#[derive(GodotClass)]
#[class(init)]
struct Monster {
   #[init(val = 100)]
    hitpoints: u16,
}

trait Health {
    fn is_alive(&self) -> bool;
    fn deal_damage(&mut self, damage: u16);
}

// The #[godot_dyn] attribute macro registers the dynamic relation in godot-rust.
// Traits are implemented as usual.
#[godot_dyn]
impl Health for Monster {
    fn is_alive(&self) -> bool {
        self.hitpoints > 0
    }

    fn deal_damage(&mut self, damage: u16) {
        self.hitpoints = self.hitpoints.saturating_sub(damage);
    }
}

// Create a Gd<Monster> and convert it -> DynGd<Monster, dyn Health>.
let monster = Monster::new_gd();
let dyn_monster = monster.into_dyn::<dyn Health>();

// Now upcast it to its base class -> type is DynGd<RefCounted, dyn Health>.
let mut dyn_monster = dyn_monster.upcast::<RefCounted>();

// Due to RefCounted abstraction, you can no longer access concrete Monster properties.
// However, the trait Health is still accessible through dyn_bind().
assert!(dyn_monster.dyn_bind().is_alive());

// To mutate the object, call dyn_bind_mut(). Rust borrow rules apply.
let mut guard = dyn_monster.dyn_bind_mut();
guard.deal_damage(120);
assert!(!guard.is_alive());

§Polymorphic dyn re-enrichment

When passing DynGd<T, D> to Godot, you will lose the D part of the type inside the engine, because Godot doesn’t know about Rust traits. The trait methods won’t be accessible through GDScript, either.

When receiving objects from Godot, the FromGodot trait is used to convert values to their Rust counterparts. FromGodot allows you to use types in #[func] parameters or extract elements from arrays, among others. If you now receive a trait-enabled object back from Godot, you can easily obtain it as Gd<T> – but what if you need the original DynGd<T, D> back? If T is concrete and directly implements D, then Gd::into_dyn() is of course possible. But in reality, you may have a polymorphic base class such as RefCounted or Node and want to ensure that trait object D dispatches to the correct subclass, without manually checking every possible candidate.

To stay with the above example: let’s say Health is implemented for two classes Monster and Knight. You now have a DynGd<RefCounted, dyn Health>, which can represent either of the two classes. We pass this to Godot (e.g. as a Variant), and then back.

trait Health { /* ... */ }

#[derive(GodotClass)]
struct Monster { /* ... */ }
#[godot_dyn]
impl Health for Monster { /* ... */ }

#[derive(GodotClass)]
struct Knight { /* ... */ }
#[godot_dyn]
impl Health for Knight { /* ... */ }

// Let's construct a DynGd, and pass it to Godot as a Variant.
let variant = if runtime_condition {
    // DynGd<Knight, dyn Health>
    Knight::new_gd().into_dyn::<dyn Health>().to_variant()
} else {
    // DynGd<Monster, dyn Health>
    Monster::new_gd().into_dyn::<dyn Health>().to_variant()
};

// Now convert back into a DynGd -- but we don't know the concrete type.
// We can still represent it as DynGd<RefCounted, dyn Health>.
let dyn_gd: DynGd<RefCounted, dyn Health> = variant.to();
// Now work with the abstract object as usual.

When converting from Godot back into DynGd, we say that the dyn Health trait object is re-enriched.

godot-rust achieves this thanks to the registration done by #[godot_dyn]: the library knows for which classes Health is implemented, and it can query the dynamic type of the object. Based on that type, it can find the impl Health implementation matching the correct class. Behind the scenes, everything is wired up correctly so that you can restore the original DynGd even after it has passed through Godot.

Implementations§

§

impl<T, D> DynGd<T, D>
where T: GodotClass, D: ?Sized,

pub fn dyn_bind(&self) -> DynGdRef<'_, D>

Acquires a shared reference guard to the trait object D.

The resulting guard implements Deref<Target = D>, allowing shared access to the trait’s methods.

See Gd::bind() for borrow checking semantics and panics.

pub fn dyn_bind_mut(&mut self) -> DynGdMut<'_, D>

Acquires an exclusive reference guard to the trait object D.

The resulting guard implements DerefMut<Target = D>, allowing exclusive mutable access to the trait’s methods.

See Gd::bind_mut() for borrow checking semantics and panics.

pub fn upcast<Base>(self) -> DynGd<Base, D>
where Base: GodotClass, T: Inherits<Base>,

Upcast to a Godot base, while retaining the D trait object.

This is useful when you want to gather multiple objects under a common Godot base (e.g. Node), but still enable common functionality. The common functionality is still accessible through D even when upcasting.

See also Gd::upcast().

pub fn try_cast<Derived>(self) -> Result<DynGd<Derived, D>, DynGd<T, D>>
where Derived: Inherits<T>,

Downcast to a more specific Godot class, while retaining the D trait object.

If T’s dynamic type is not Derived or one of its subclasses, Err(self) is returned, meaning you can reuse the original object for further casts.

See also Gd::try_cast().

pub fn cast<Derived>(self) -> DynGd<Derived, D>
where Derived: Inherits<T>,

⚠️ Downcast: to a more specific Godot class, while retaining the D trait object.

See also Gd::cast().

§Panics

If the class’ dynamic type is not Derived or one of its subclasses. Use Self::try_cast() if you want to check the result.

pub fn into_gd(self) -> Gd<T>

Downgrades to a Gd<T> pointer, abandoning the D abstraction.

§

impl<T, D> DynGd<T, D>
where T: GodotClass<Memory = MemManual> + Bounds, D: ?Sized,

pub fn free(self)

Destroy the manually-managed Godot object.

See Gd::free() for semantics and panics.

Methods from Deref<Target = Gd<T>>§

pub fn bind(&self) -> GdRef<'_, T>

Hands out a guard for a shared borrow, through which the user instance can be read.

The pattern is very similar to interior mutability with standard RefCell. You can either have multiple GdRef shared guards, or a single GdMut exclusive guard to a Rust GodotClass instance, independently of how many Gd smart pointers point to it. There are runtime checks to ensure that Rust safety rules (e.g. no & and &mut coexistence) are upheld.

Drop the guard as soon as you don’t need it anymore. See also Bind guards.

§Panics
  • If another Gd smart pointer pointing to the same Rust instance has a live GdMut guard bound.
  • If there is an ongoing function call from GDScript to Rust, which currently holds a &mut T reference to the user instance. This can happen through re-entrancy (Rust -> GDScript -> Rust call).

pub fn bind_mut(&mut self) -> GdMut<'_, T>

Hands out a guard for an exclusive borrow, through which the user instance can be read and written.

The pattern is very similar to interior mutability with standard RefCell. You can either have multiple GdRef shared guards, or a single GdMut exclusive guard to a Rust GodotClass instance, independently of how many Gd smart pointers point to it. There are runtime checks to ensure that Rust safety rules (e.g. no &mut aliasing) are upheld.

Drop the guard as soon as you don’t need it anymore. See also Bind guards.

§Panics
  • If another Gd smart pointer pointing to the same Rust instance has a live GdRef or GdMut guard bound.
  • If there is an ongoing function call from GDScript to Rust, which currently holds a &T or &mut T reference to the user instance. This can happen through re-entrancy (Rust -> GDScript -> Rust call).

pub fn instance_id(&self) -> InstanceId

⚠️ Returns the instance ID of this object (panics when dead).

§Panics

If this object is no longer alive (registered in Godot’s object database).

pub fn instance_id_unchecked(&self) -> InstanceId

Returns the last known, possibly invalid instance ID of this object.

This function does not check that the returned instance ID points to a valid instance! Unless performance is a problem, use instance_id() instead.

This method is safe and never panics.

pub fn is_instance_valid(&self) -> bool

Checks if this smart pointer points to a live object (read description!).

Using this method is often indicative of bad design – you should dispose of your pointers once an object is destroyed. However, this method exists because GDScript offers it and there may be rare use cases.

Do not use this method to check if you can safely access an object. Accessing dead objects is generally safe and will panic in a defined manner. Encountering such panics is almost always a bug you should fix, and not a runtime condition to check against.

pub fn upcast_ref<Base>(&self) -> &Base
where Base: GodotClass<Declarer = DeclEngine> + Bounds, T: Inherits<Base>,

Upcast shared-ref: access this object as a shared reference to a base class.

This is semantically equivalent to multiple applications of Self::deref(). Not really useful on its own, but combined with generic programming:

fn print_node_name<T>(node: &Gd<T>)
where
    T: Inherits<Node>,
{
    println!("Node name: {}", node.upcast_ref().get_name());
}

Note that this cannot be used to get a reference to Rust classes, for that you should use Gd::bind(). For instance this will fail:

#[derive(GodotClass)]
#[class(init, base = Node)]
struct SomeClass {}

#[godot_api]
impl INode for SomeClass {
    fn ready(&mut self) {
        let other = SomeClass::new_alloc();
        let _ = other.upcast_ref::<SomeClass>();
    }
}

pub fn upcast_mut<Base>(&mut self) -> &mut Base
where Base: GodotClass<Declarer = DeclEngine> + Bounds, T: Inherits<Base>,

Upcast exclusive-ref: access this object as an exclusive reference to a base class.

This is semantically equivalent to multiple applications of Self::deref_mut(). Not really useful on its own, but combined with generic programming:

fn set_node_name<T>(node: &mut Gd<T>, name: &str)
where
    T: Inherits<Node>,
{
    node.upcast_mut().set_name(name);
}

Note that this cannot be used to get a mutable reference to Rust classes, for that you should use Gd::bind_mut(). For instance this will fail:

#[derive(GodotClass)]
#[class(init, base = Node)]
struct SomeClass {}

#[godot_api]
impl INode for SomeClass {
    fn ready(&mut self) {
        let mut other = SomeClass::new_alloc();
        let _ = other.upcast_mut::<SomeClass>();
    }
}

pub fn callable(&self, method_name: impl AsArg<StringName>) -> Callable

Returns a callable referencing a method from this object named method_name.

This is shorter syntax for Callable::from_object_method(self, method_name).

Trait Implementations§

§

impl<T, D> Clone for DynGd<T, D>
where T: GodotClass, D: ?Sized,

§

fn clone(&self) -> DynGd<T, D>

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl<T, D> Debug for DynGd<T, D>
where T: GodotClass, D: ?Sized,

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl<T, D> Deref for DynGd<T, D>
where T: GodotClass, D: ?Sized,

§

type Target = Gd<T>

The resulting type after dereferencing.
§

fn deref(&self) -> &<DynGd<T, D> as Deref>::Target

Dereferences the value.
§

impl<T, D> DerefMut for DynGd<T, D>
where T: GodotClass, D: ?Sized,

§

fn deref_mut(&mut self) -> &mut <DynGd<T, D> as Deref>::Target

Mutably dereferences the value.
§

impl<T, D> Display for DynGd<T, D>
where T: GodotClass, D: ?Sized,

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl<T, D> FromGodot for DynGd<T, D>
where T: GodotClass, D: 'static + ?Sized,

§

fn try_from_godot( via: <DynGd<T, D> as GodotConvert>::Via, ) -> Result<DynGd<T, D>, ConvertError>

Converts the Godot representation to this type, returning Err on failure.
§

fn from_godot(via: Self::Via) -> Self

⚠️ Converts the Godot representation to this type. Read more
§

fn try_from_variant(variant: &Variant) -> Result<Self, ConvertError>

Performs the conversion from a Variant, returning Err on failure.
§

fn from_variant(variant: &Variant) -> Self

⚠️ Performs the conversion from a Variant. Read more
§

impl<T, D> GodotConvert for DynGd<T, D>
where T: GodotClass, D: ?Sized,

§

type Via = Gd<T>

The type through which Self is represented in Godot.
§

impl<T, D> Hash for DynGd<T, D>
where T: GodotClass, D: ?Sized,

§

fn hash<H>(&self, state: &mut H)
where H: Hasher,

⚠️ Hashes this object based on its instance ID.

§Panics

When self is dead.

1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
§

impl<T, D> ParamType for DynGd<T, D>
where T: GodotClass, D: 'static + ?Sized,

§

fn owned_to_arg<'v>(self) -> <DynGd<T, D> as ParamType>::Arg<'v>

Converts an owned value to the canonical argument type, which can be passed to impl AsArg<T>. Read more
§

impl<T, D> PartialEq for DynGd<T, D>
where T: GodotClass, D: ?Sized,

§

fn eq(&self, other: &DynGd<T, D>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
§

impl<T, D> ToGodot for DynGd<T, D>
where T: GodotClass, D: ?Sized,

§

type ToVia<'v> = <Gd<T> as ToGodot>::ToVia<'v> where D: 'v

Target type of to_godot(), which can differ from Via for pass-by-reference types. Read more
§

fn to_godot(&self) -> <DynGd<T, D> as ToGodot>::ToVia<'_>

Converts this type to the Godot type by reference, usually by cloning.
§

fn to_variant(&self) -> Variant

Converts this type to a Variant.
§

impl<T, D> ArrayElement for DynGd<T, D>
where T: GodotClass, D: 'static + ?Sized,

§

impl<'r, T, D> AsArg<DynGd<T, D>> for &'r DynGd<T, D>
where T: GodotClass, D: 'static + ?Sized,

§

impl<T, U, D> AsObjectArg<T> for &DynGd<U, D>
where T: GodotClass<Declarer = DeclEngine> + Bounds, U: Inherits<T>, D: ?Sized,

§

impl<T, D> Eq for DynGd<T, D>
where T: GodotClass, D: ?Sized,

Auto Trait Implementations§

§

impl<T, D> Freeze for DynGd<T, D>
where <<T as Bounds>::Declarer as Declarer>::InstanceCache: Freeze, D: ?Sized,

§

impl<T, D> !RefUnwindSafe for DynGd<T, D>

§

impl<T, D> !Send for DynGd<T, D>

§

impl<T, D> !Sync for DynGd<T, D>

§

impl<T, D> Unpin for DynGd<T, D>
where <<T as Bounds>::Declarer as Declarer>::InstanceCache: Unpin, D: ?Sized,

§

impl<T, D> !UnwindSafe for DynGd<T, D>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.