Skip to content

Commit f67b834

Browse files
committed
feat(core): support easier, type-safe deferred calls
1 parent 55efa97 commit f67b834

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

godot-core/src/obj/gd.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,23 @@ impl<T: GodotClass> Gd<T> {
444444
})
445445
}
446446

447+
/// Runs the given Closure deferred.
448+
///
449+
/// This can be a type-safe alternative to [`classes::Object::call_deferred`], but does not handle dynamic dispatch, unless explicitly used.
450+
/// This constructor only allows the callable to be invoked from the same thread as creating it.The closure receives a reference to this object back.
451+
#[cfg(since_api = "4.2")]
452+
pub fn apply_deferred<F>(&mut self, mut rust_function: F)
453+
where
454+
F: FnMut(Gd<T>) + 'static,
455+
{
456+
let this = self.clone();
457+
let callable = Callable::from_local_fn("apply_deferred", move |_| {
458+
rust_function(this.clone());
459+
Ok(Variant::nil())
460+
});
461+
callable.call_deferred(&[]);
462+
}
463+
447464
/// Returns `Ok(cast_obj)` on success, `Err(self)` on error.
448465
// Visibility: used by DynGd.
449466
pub(crate) fn owned_cast<U>(self) -> Result<Gd<U>, Self>

itest/rust/src/object_tests/deferred_call_test.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,20 @@ impl INode for DeferredTestNode {
6767
fn calls_method_names_deferred(ctx: &crate::framework::TestContext) -> TaskHandle {
6868
let mut test_node = DeferredTestNode::new_alloc();
6969
ctx.scene_tree.clone().add_child(&test_node);
70-
70+
7171
test_node.call_deferred("accept", &[]);
7272

7373
let handle = test_node.bind().as_expectation_task();
7474
handle
7575
}
76+
77+
#[itest(async)]
78+
fn calls_closure_deferred(ctx: &crate::framework::TestContext) -> TaskHandle {
79+
let mut test_node = DeferredTestNode::new_alloc();
80+
ctx.scene_tree.clone().add_child(&test_node);
81+
82+
test_node.apply_deferred(|mut this| this.bind_mut().accept());
83+
84+
let handle = test_node.bind().as_expectation_task();
85+
handle
86+
}

0 commit comments

Comments
 (0)