Skip to content

Add generic Gd::duplicate_node + Gd::duplicate_resource #1492

Merged
Bromeon merged 3 commits intomasterfrom
feature/generic-duplicate
Feb 5, 2026
Merged

Add generic Gd::duplicate_node + Gd::duplicate_resource #1492
Bromeon merged 3 commits intomasterfrom
feature/generic-duplicate

Conversation

@Bromeon
Copy link
Copy Markdown
Member

@Bromeon Bromeon commented Feb 5, 2026

This PR adds type-safe methods to duplicate Node and Resource, handling all the tiny nuances across Godot versions.

In contrast to existing Node::duplicate and Resource::duplicate, these methods are directly defined on Gd<T>.
This takes into account the generic type T and thus returns an object of the same type, rather than always Gd<Node>/Gd<Resource>. Furthermore, no more Option<Gd<...>> is returned unless you explicitly want to handle rare fallible cases with *_ex().done_or_null().

Closes #1421.

New API

let node = Node2D::new_alloc();
let resource = Resource::new_gd();

// -------------- Nodes --------------

// Duplicate node -> Gd<Node2D>.
let copy = node.duplicate_node();

// Custom flags.
let copy = node.duplicate_node_ex()
    .flags(DuplicateFlags::SIGNALS | DuplicateFlags::GROUPS)
    .done();

// Fallible (if class has no default contructor).
let copy = node.duplicate_node_ex()
    .done_or_null();

// ------------- Resources -------------

// Duplicate resource -> Gd<Resource>.
let copy = resource.duplicate_resource();

// Deep duplication (Godot 4.5+).
let copy = resource.duplicate_resource_ex()
    .deep(DeepDuplicateMode::INTERNAL)
    .done();
    
// Compat duplication (Godot 4.2-4.4).
let copy = resource.duplicate_resource_ex()
    .deep_internal()
    .done();

Old methods are now deprecated and will be removed in godot-rust v0.6:

  • Node::duplicate
  • Node::duplicate_ex
  • Resource::duplicate
  • Resource::duplicate_ex
  • Resource::duplicate_deep
  • Resource::duplicate_deep_ex

Nuances

This took me much longer than I would have liked, because Godot's Resource::duplicate* APIs are quite a mess.
In fairness, PR #100673 made a lot better, but with backwards compatibility the resulting API surface is very confusing.

  1. There was Resource::duplicate(subresources=false). All good so far.
  2. Godot 4.5 renamed the parameter subresources to deep.
    • With default parameters mapping to builder methods in Rust, this is a breaking change for us. Or any language using named parameters, like Kotlin.
    • So this is also a pain for every godot-rust user planning to use this API across versions, as they need to call different versions.
  3. Godot 4.5 also introduced Resource::duplicate_deep(mode=INTERNAL).
    • The default argument overlaps with duplicate(deep=true).
    • There is a DeepDuplicateMode::NONE, which one might think does not duplicate deeply. Except it does, just without subresources. Arrays/dicts are deep-copied, unlike duplicate(deep=false) which references them.
  4. Godot 4.5 also changed how subresources in arrays/dictionaries are handled.
    • So it changed semantics of duplicate(deep=false) to reference arrays/dicts instead of shallow-copy them.
    • It also addressed a bug where subresources in arrays/dicts are now duplicated, but they weren't.

I hope you never have to write a plugin that supports these versions and need duplicate.
Anyway, in case you do, I wrote a nice table that explains all the differences. And the Rust API is stable.

@Bromeon Bromeon added this to the 0.5 milestone Feb 5, 2026
@Bromeon Bromeon added feature Adds functionality to the library c: engine Godot classes (nodes, resources, ...) labels Feb 5, 2026
@Bromeon Bromeon force-pushed the feature/generic-duplicate branch 2 times, most recently from 041c28b to 327fa91 Compare February 5, 2026 18:32
@Bromeon Bromeon force-pushed the feature/generic-duplicate branch from 327fa91 to 9021ce5 Compare February 5, 2026 18:51
@Bromeon Bromeon enabled auto-merge February 5, 2026 18:55
@Bromeon Bromeon added this pull request to the merge queue Feb 5, 2026
Merged via the queue into master with commit 34c97cd Feb 5, 2026
23 checks passed
@Bromeon Bromeon deleted the feature/generic-duplicate branch February 5, 2026 19:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c: engine Godot classes (nodes, resources, ...) feature Adds functionality to the library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Turbofish support for node.duplicate()

1 participant