pub struct IndirectMultiMesh { /* private fields */ }Expand description
A MultiMesh allocated with use_indirect, plus the cleanup Godot forgets.
Godot never releases an indirect MultiMesh’s internal command buffer when the
multimesh is freed — an engine bug, reproducible with no CelestialSim code at all
(allocate four indirect multimeshes in GDScript, drop them, and Godot reports
4 RIDs of type "StorageBuffer" were leaked on exit). Since every planet rebuild
(a builder re-set, a tile_res edit, a scatter-layer change) allocates a fresh set,
the leak grows without bound.
So the multimesh is owned through this handle: on drop it releases the command buffer
before letting go of the Gd<MultiMesh>, which is the free Godot should have done.
If a future Godot fixes the bug, this becomes a double free — it will announce itself
loudly as a “free of invalid RID” error on the next engine bump, which is the failure
mode we want (noisy, not silent).
Implementations§
Methods from Deref<Target = Gd<MultiMesh>>§
pub fn bind(&self) -> GdRef<'_, 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
Gdsmart pointer pointing to the same Rust instance has a liveGdMutguard bound. - If there is an ongoing function call from GDScript to Rust, which currently holds a
&mut Treference to the user instance. This can happen through re-entrancy (Rust -> GDScript -> Rust call). - If the object is a placeholder instance – i.e. it has no Rust instance attached. This can happen when a non-
#[class(tool)]object is loaded or instantiated in the editor. Since Godot 4.3, non-tool classes are registered as “runtime classes”, meaning the editor only creates a Godot-side placeholder without invoking the Rust constructor. If you need tobind()such an object in the editor (e.g. a loaded resource), mark its class as#[class(tool)].
pub fn instance_id(&self) -> InstanceId
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
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()][Self::instance_id] instead.
This method is safe and never panics.
pub fn is_instance_valid(&self) -> bool
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) -> &Basewhere
Base: GodotClass<Declarer = DeclEngine> + Bounds,
T: Inherits<Base>,
pub fn upcast_ref<Base>(&self) -> &Basewhere
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 callable(&self, method_name: impl AsArg<StringName>) -> Callable
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)][Callable::from_object_method].
pub fn linked_callable<R, F>(
&self,
method_name: impl Into<Cow<'static, str>>,
rust_function: F,
) -> Callablewhere
R: ToGodot,
F: 'static + FnMut(&[&Variant]) -> R,
pub fn linked_callable<R, F>(
&self,
method_name: impl Into<Cow<'static, str>>,
rust_function: F,
) -> Callablewhere
R: ToGodot,
F: 'static + FnMut(&[&Variant]) -> R,
Creates a new callable linked to the given object from single-threaded Rust function or closure.
This is shorter syntax for [Callable::from_linked_fn()].
name is used for the string representation of the closure, which helps with debugging.
Such a callable will be automatically invalidated by Godot when a linked Object is freed.
If you need a Callable which can live indefinitely, use [Callable::from_fn()].
pub fn signals(&self) -> <T as WithSignals>::SignalCollection<'_, T>
pub fn signals(&self) -> <T as WithSignals>::SignalCollection<'_, T>
Access user-defined signals of this object.
For classes that have at least one #[signal] defined, returns a collection of signal names. Each returned signal has a specialized
API for connecting and emitting signals in a type-safe way. This method is the equivalent of WithUserSignals::signals(), but when
called externally (not from self). Furthermore, this is also available for engine classes, not just user-defined ones.
When you are within the impl of a class, use self.signals() directly instead.
If you haven’t already, read the book chapter about signals for a walkthrough.
pub fn duplicate_node(&self) -> Gd<T>
pub fn duplicate_node(&self) -> Gd<T>
⚠️ Returns a new node with all of its properties, signals, groups, and children copied from the original.
See [duplicate_node_ex()][Self::duplicate_node_ex] for details and panics.
§Example
use godot::prelude::*;
let mut node = Node2D::new_alloc();
node.set_position(Vector2::new(1.0, 2.0));
let copy = node.duplicate_node(); // type Gd<Node2D>
assert_eq!(copy.get_position(), Vector2::new(1.0, 2.0));
node.free();
copy.free();pub fn duplicate_node_ex(&self) -> ExDuplicateNode<'_, T>
pub fn duplicate_node_ex(&self) -> ExDuplicateNode<'_, T>
Duplicates this node with a fluent builder API for fine-grained control.
By default, all flags are enabled, just like [duplicate_node()][Self::duplicate_node]:
- Properties, signals, groups, and children are copied.
- Internal nodes are not duplicated.
You can change this behavior with [flags()][ExDuplicateNode::flags]. For nodes with attached scripts: if the script’s _init() has
required parameters, the duplicated node will not have a script.
This function can be used polymorphically: duplicating Gd<Node> pointing to dynamic type Node2D duplicates the concrete Node2D.
§Panics
Panics if duplication fails. Likely causes:
- The dynamic (runtime) type of the node is not default-constructible. For example, if a
Gd<Node>actually points to an instance ofMyClass(inheritingNode), andMyClasshas noinitor uses#[class(no_init)], then duplication will fail. - Called from a thread other than the main thread (Godot’s scene tree is single-threaded).
- You use [
DuplicateFlags::USE_INSTANTIATION] and the scene file cannot be loaded. - Any child node’s duplication fails.
To avoid panics, use [ExDuplicateNode::done_or_null()].
§Example
use godot::prelude::*;
use godot::classes::node::DuplicateFlags;
let node: Gd<Node> = Node::new_alloc();
// Configure node...
let copy = node.duplicate_node_ex()
.flags(DuplicateFlags::SIGNALS | DuplicateFlags::GROUPS)
.done();pub fn duplicate_resource(&self) -> Gd<T>
pub fn duplicate_resource(&self) -> Gd<T>
⚠️ Returns a shallow duplicate of this resource.
See [duplicate_resource_ex()][Self::duplicate_resource_ex] for details, panics, and version-specific behavior.
§Example
use godot::prelude::*;
let resource = Resource::new_gd();
let copy = resource.duplicate_resource(); // Gd<Resource>.
assert_ne!(copy, resource); // Different Gd pointer.pub fn duplicate_resource_ex(&self) -> ExDuplicateResource<'_, T>
pub fn duplicate_resource_ex(&self) -> ExDuplicateResource<'_, T>
Duplicates this resource with a fluent builder API for fine-grained control.
By default, performs a shallow copy, same as [duplicate_resource()][Self::duplicate_resource].
Use [deep_internal()][ExDuplicateResource::deep_internal] or [deep()][ExDuplicateResource::deep] to control
subresource duplication.
Works polymorphically: duplicating Gd<Resource> pointing to a dynamic type duplicates the concrete type.
§Panics
If the dynamic type is not default-constructible (e.g. #[class(no_init)]).
Use [ExDuplicateResource::done_or_null()] to handle errors.
§Behavior table
The behavior has changed in PR #100673 for Godot 4.5, and with both duplicate()
and duplicate_deep(), there is now partial semantic overlap in Godot. The following table summarizes the behavior and elaborates
how it maps to godot-rust.
See also Godot docs
for Resource.duplicate() and Resource.duplicate_deep().
| godot-rust | Godot | 4.2–4.4 | 4.5+ |
|---|---|---|---|
duplicate_resource()duplicate_resource_ex() | duplicate(false) | A/D1 shallow-copied, subresources shared | A/D only referenced |
_ex().deep_internal() | duplicate(true) | A/D shallow-copied, subresources in A/D ignored (bug) | A/D deep-copied, internal subresources duplicated2 |
_ex().deep(NONE) | duplicate_deep(NONE) | A/D deep-copied, subresources shared | |
_ex().deep(INTERNAL) | duplicate_deep(INTERNAL) | A/D deep-copied, internal subresources duplicated | |
_ex().deep(ALL) | duplicate_deep(ALL) | A/D deep-copied, all subresources duplicated |