Skip to content

Commit 6037464

Browse files
committed
Rename signal related symbols
Changes: * connect_builder() -> builder() * GodotDeref -> UniformObjectDeref
1 parent 43b4b1c commit 6037464

File tree

6 files changed

+136
-109
lines changed

6 files changed

+136
-109
lines changed

godot-core/src/registry/signal/connect_builder.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use std::fmt::Debug;
2222
///
2323
/// # Customization
2424
/// Customizing your signal connection must be done **before** providing the function being connected
25-
/// (can be done by using of the `connect_**` methods) (see section `Finalizing` bellow).
25+
/// (can be done by using of the `connect_*` methods) (see section `Finalizing` bellow).
2626
///
2727
/// All these methods are optional, and they can be combined.
2828
// Use HTML link due to conditional compilation; renders badly if target symbol is unavailable.
@@ -40,6 +40,9 @@ use std::fmt::Debug;
4040
/// | `self` | [`connect_self_mut`][Self::connect_self_mut] | [`connect_self_gd`][Self::connect_self_gd] |
4141
/// | other object | [`connect_other_mut`][Self::connect_other_mut] | [`connect_other_gd`][Self::connect_other_gd] |
4242
///
43+
/// Methods taking `&C` can (e.g. using interior mutability) can be indirectly connected through a `*_gd` overload + a `Gd::bind()` call.
44+
/// If this turns out to be a common use case, we could consider `connect_*_ref()` in the future.
45+
///
4346
/// <br>
4447
///
4548
/// For **global functions, associated functions and closures**, you can use the following APIs:
@@ -143,8 +146,8 @@ macro_rules! impl_builder_connect {
143146
///
144147
/// Example usages:
145148
/// ```ignore
146-
/// sig.connect_builder().connect(Self::static_func);
147-
/// sig.connect_builder().flags(ConnectFlags::DEFERRED).connect(global_func);
149+
/// sig.builder().connect(Self::static_func);
150+
/// sig.builder().flags(ConnectFlags::DEFERRED).connect(global_func);
148151
/// sig.connect(|arg| { /* closure */ });
149152
/// ```
150153
///

godot-core/src/registry/signal/godot_deref.rs

Lines changed: 0 additions & 75 deletions
This file was deleted.

godot-core/src/registry/signal/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,22 @@
88
// Whole module only available in Godot 4.2+.
99

1010
mod connect_builder;
11-
mod godot_deref;
1211
mod signal_object;
1312
mod typed_signal;
13+
mod uniform_object_deref;
1414

1515
use crate::builtin::{GString, Variant};
1616
use crate::meta;
1717
pub(crate) use connect_builder::*;
18-
use godot_deref::GodotDeref;
1918
pub(crate) use signal_object::*;
2019
pub(crate) use typed_signal::*;
20+
use uniform_object_deref::UniformObjectDeref;
2121

2222
// Used in `godot` crate.
2323
pub mod re_export {
2424
pub use super::connect_builder::ConnectBuilder;
2525
pub use super::typed_signal::TypedSignal;
26+
pub use super::uniform_object_deref::UniformObjectDeref;
2627
}
2728

2829
// Used in `godot::private` module.

godot-core/src/registry/signal/typed_signal.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
66
*/
77

8-
use super::{make_callable_name, make_godot_fn, ConnectBuilder, GodotDeref, SignalObject};
8+
use super::{make_callable_name, make_godot_fn, ConnectBuilder, SignalObject, UniformObjectDeref};
99
use crate::builtin::{Callable, Variant};
1010
use crate::classes::object::ConnectFlags;
1111
use crate::meta;
@@ -54,7 +54,7 @@ impl<C: WithBaseField> ToSignalObj<C> for C {
5454
/// - [`connect()`][Self::connect]: Connect a global/associated function or a closure.
5555
/// - [`connect_self()`][Self::connect_self]: Connect a method or closure that runs on the signal emitter.
5656
/// - [`connect_other()`][Self::connect_other]: Connect a method or closure that runs on a separate object.
57-
/// - [`connect_builder()`][Self::connect_builder] for more complex setups (such as choosing [`ConnectFlags`] or making thread-safe connections).
57+
/// - [`builder()`][Self::builder] for more complex setups (such as choosing [`ConnectFlags`] or making thread-safe connections).
5858
///
5959
/// # Emitting a signal
6060
/// Code-generated signal types provide a method `emit(...)`, which adopts the names and types of the `#[signal]` parameter list.
@@ -119,8 +119,8 @@ impl<'c, C: WithSignals, Ps: meta::ParamTuple> TypedSignal<'c, C, Ps> {
119119
/// Fully customizable connection setup.
120120
///
121121
/// The returned builder provides several methods to configure how to connect the signal. It needs to be finalized with a call
122-
/// to any of the builder's `connect_**` methods.
123-
pub fn connect_builder<'ts>(&'ts self) -> ConnectBuilder<'ts, 'c, C, Ps> {
122+
/// to any of the builder's `connect_*` methods.
123+
pub fn builder<'ts>(&'ts self) -> ConnectBuilder<'ts, 'c, C, Ps> {
124124
ConnectBuilder::new(self)
125125
}
126126

@@ -189,7 +189,7 @@ macro_rules! impl_signal_connect {
189189
/// ```
190190
///
191191
/// - To connect to a method on the object that owns this signal, use [`connect_self()`][Self::connect_self].
192-
/// - If you need [`connect flags`](ConnectFlags) or cross-thread signals, use [`connect_builder()`][Self::connect_builder].
192+
/// - If you need [`connect flags`](ConnectFlags) or cross-thread signals, use [`builder()`][Self::builder].
193193
pub fn connect<F, R>(&self, mut function: F)
194194
where
195195
F: FnMut($($Ps),*) -> R + 'static,
@@ -204,15 +204,15 @@ macro_rules! impl_signal_connect {
204204
/// Connect a method (member function) with `&mut self` as the first parameter.
205205
///
206206
/// - To connect to methods on other objects, use [`connect_other()`][Self::connect_other].
207-
/// - If you need [`connect flags`](ConnectFlags) or cross-thread signals, use [`connect_builder()`][Self::connect_builder].
208-
pub fn connect_self<F, R, Decl>(&self, mut function: F)
207+
/// - If you need [`connect flags`](ConnectFlags) or cross-thread signals, use [`builder()`][Self::builder].
208+
pub fn connect_self<F, R, Declarer>(&self, mut function: F)
209209
where
210210
F: FnMut(&mut C, $($Ps),*) -> R + 'static,
211-
C: GodotDeref<Decl>,
211+
C: UniformObjectDeref<Declarer>,
212212
{
213213
let mut gd = self.receiver_object();
214214
let godot_fn = make_godot_fn(move |($($args,)*):($($Ps,)*)| {
215-
let mut target = C::get_mut(&mut gd);
215+
let mut target = C::object_as_mut(&mut gd);
216216
let target_mut = target.deref_mut();
217217
function(target_mut, $($args),*);
218218
});
@@ -231,16 +231,16 @@ macro_rules! impl_signal_connect {
231231
/// ---
232232
///
233233
/// - To connect to methods on the object that owns this signal, use [`connect_self()`][Self::connect_self].
234-
/// - If you need [`connect flags`](ConnectFlags) or cross-thread signals, use [`connect_builder()`][Self::connect_builder].
235-
pub fn connect_other<F, R, OtherC, Decl>(&self, object: &impl ToSignalObj<OtherC>, mut method: F)
234+
/// - If you need [`connect flags`](ConnectFlags) or cross-thread signals, use [`builder()`][Self::builder].
235+
pub fn connect_other<F, R, OtherC, Declarer>(&self, object: &impl ToSignalObj<OtherC>, mut method: F)
236236
where
237237
F: FnMut(&mut OtherC, $($Ps),*) -> R + 'static,
238-
OtherC: GodotDeref<Decl>,
238+
OtherC: UniformObjectDeref<Declarer>,
239239
{
240240
let mut gd = object.to_signal_obj();
241241

242242
let godot_fn = make_godot_fn(move |($($args,)*):($($Ps,)*)| {
243-
let mut target = OtherC::get_mut(&mut gd);
243+
let mut target = OtherC::object_as_mut(&mut gd);
244244
let target_mut = target.deref_mut();
245245
method(target_mut, $($args),*);
246246
});
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright (c) godot-rust; Bromeon and contributors.
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
use crate::obj::bounds::{DeclEngine, DeclUser};
9+
use crate::obj::{Gd, GdMut, GdRef, GodotClass, WithBaseField};
10+
use std::ops::{Deref, DerefMut};
11+
12+
/// Unifies dereferencing of user and engine classes, as `&T`/`&mut T` and `Gd<T>`.
13+
///
14+
/// This is mainly used by the `connect_*` functions of [`TypedSignal`](crate::registry::signal::TypedSignal).
15+
///
16+
/// # Motivation
17+
/// Although both user and engine classes are often wrapped in a `Gd<T>`, dereferencing them is done differently depending
18+
/// on whether they are made by the user or engine:
19+
/// - `Gd<EngineClass>` can be deref-ed directly into `&EngineClass` and `&mut EngineClass`.
20+
/// - `Gd<UserClass>` must first go through [`bind()`](Gd::bind)/[`bind_mut()`](Gd::bind_mut), which can finally
21+
/// be deref-ed into `&UserClass` and `&mut UserClass`, respectively.
22+
///
23+
/// Without this trait, there's no clear/generic way of writing functions that can accept both user and engine classes,
24+
/// but need to deref said classes in some way.
25+
///
26+
/// [`UniformObjectDeref`](Self) solves this by explicitly handling each category in a different way, but still resulting
27+
/// in a variable that can be deref-ed into `&T`/`&mut T`.
28+
///
29+
/// # Generic param `Declarer`
30+
/// Rustc [does not acknowledge associated type bounds when checking for overlapping impls](https://github.com/rust-lang/rust/issues/20400),
31+
/// this parameter is essentially used to create 2 different traits, one for each "category" (user or engine).
32+
///
33+
/// Despite being 2 different traits, a function can accept both by simply being generic over `Declarer`:
34+
/// ```no_run
35+
/// # use godot::register::UniformObjectDeref;
36+
/// # use godot::prelude::*;
37+
/// fn abstract_over_objects<Declarer, C>(obj: &Gd<C>)
38+
/// where
39+
/// C: UniformObjectDeref<Declarer>,
40+
/// {
41+
/// let ref_provider = UniformObjectDeref::object_as_ref(obj);
42+
/// let obj_ref: &C = & *ref_provider;
43+
/// // Regardless of `Declarer`, we can still deref, since the bounds on
44+
/// // `TargetRef`/`TargetMut` enforce that.
45+
/// }
46+
///
47+
/// #[derive(GodotClass)]
48+
/// #[class(init)]
49+
/// struct MyClass {
50+
/// _base: Base<RefCounted>
51+
/// }
52+
///
53+
/// fn main() {
54+
/// let engine_obj: Gd<RefCounted> = RefCounted::new_gd();
55+
/// let user_obj: Gd<MyClass> = MyClass::new_gd();
56+
///
57+
/// abstract_over_objects(&engine_obj);
58+
/// abstract_over_objects(&user_obj);
59+
/// }
60+
/// ```
61+
//
62+
// The crate `https://crates.io/crates/disjoint_impls` handles this in a more user-friendly way, we should
63+
// consider using it if disjoint impls are going to be frequently used.
64+
//
65+
// See also Declarer::DerefTarget in the library, which has a similar but different purpose: finding the nearest engine class
66+
// (`&Node` for `Node`, `&Node` for `MyClass`).
67+
#[allow(clippy::needless_lifetimes)] // False positive.
68+
pub trait UniformObjectDeref<Declarer>: GodotClass {
69+
// Currently, only the mut parts are used within the library; but ref might be useful too.
70+
type TargetRef<'a>: Deref<Target = Self>;
71+
type TargetMut<'a>: DerefMut<Target = Self>;
72+
73+
fn object_as_ref<'a>(gd: &'a Gd<Self>) -> Self::TargetRef<'a>;
74+
fn object_as_mut<'a>(gd: &'a mut Gd<Self>) -> Self::TargetMut<'a>;
75+
}
76+
77+
#[allow(clippy::needless_lifetimes)] // False positive.
78+
impl<T: GodotClass<Declarer = DeclEngine>> UniformObjectDeref<DeclEngine> for T {
79+
type TargetRef<'a> = Gd<T>;
80+
type TargetMut<'a> = Gd<T>;
81+
82+
fn object_as_ref<'a>(gd: &'a Gd<Self>) -> Self::TargetRef<'a> {
83+
gd.clone()
84+
}
85+
fn object_as_mut<'a>(gd: &'a mut Gd<Self>) -> Self::TargetMut<'a> {
86+
gd.clone()
87+
}
88+
}
89+
90+
#[allow(clippy::needless_lifetimes)] // False positive.
91+
impl<T: WithBaseField> UniformObjectDeref<DeclUser> for T {
92+
type TargetRef<'a> = GdRef<'a, T>;
93+
type TargetMut<'a> = GdMut<'a, T>;
94+
95+
fn object_as_ref<'a>(gd: &'a Gd<Self>) -> Self::TargetRef<'a> {
96+
gd.bind()
97+
}
98+
fn object_as_mut<'a>(gd: &'a mut Gd<Self>) -> Self::TargetMut<'a> {
99+
gd.bind_mut()
100+
}
101+
}

0 commit comments

Comments
 (0)