@@ -10,10 +10,9 @@ use crate::builtin::{Callable, GString, Variant};
10
10
use crate :: classes:: object:: ConnectFlags ;
11
11
use crate :: meta;
12
12
use crate :: meta:: FromGodot ;
13
- use crate :: obj:: WithSignals ;
14
- use crate :: registry:: signal:: { GodotDeref , ToSignalObj , TypedSignal } ;
13
+ use crate :: obj:: { bounds , Bounds , Gd , GodotClass , WithSignals } ;
14
+ use crate :: registry:: signal:: { ToSignalObj , TypedSignal } ;
15
15
use std:: fmt:: Debug ;
16
- use std:: ops:: DerefMut ;
17
16
18
17
/// Builder for customizing signal connections.
19
18
///
@@ -150,50 +149,94 @@ macro_rules! impl_builder_connect {
150
149
self . inner_connect_godot_fn:: <F >( godot_fn) ;
151
150
}
152
151
153
- /// Connect a method (member function) with `&mut self` as the first parameter.
152
+ /// Connect a method with `&mut self` as the first parameter (user classes only) .
154
153
///
155
- /// - To connect to methods on other objects, use [`connect_other()`][Self::connect_other].
156
- /// - If you need [`connect flags`](ConnectFlags), call [`flags()`](Self::flags) before this.
157
- /// - If you need cross-thread signals, use [`connect_sync()`](#method.connect_sync) instead (requires feature "experimental-threads").
158
- pub fn connect_self<F , R , Decl >( self , mut function: F )
154
+ /// - Use [`connect_self_gd()`][Self::connect_self_gd] to receive `Gd<Self>` instead and avoid implicit `bind_mut()` on emit.
155
+ /// For engine classes, `&mut self` is not supported at all.
156
+ /// - To connect to methods on other objects, use [`connect_other_mut()`][Self::connect_other_mut].
157
+ /// - If you need [connect flags](ConnectFlags), call [`flags()`](Self::flags) before this.
158
+ /// - If you need cross-thread signals, use [`connect_sync()`](#method.connect_sync) instead (requires feature `experimental-threads`).
159
+ pub fn connect_self_mut<F , R >( self , mut function: F )
159
160
where
161
+ C : Bounds <Declarer = bounds:: DeclUser >,
160
162
F : FnMut ( & mut C , $( $Ps) ,* ) -> R + ' static ,
161
- C : GodotDeref <Decl >,
162
163
{
163
164
let mut gd = self . parent_sig. receiver_object( ) ;
164
- let godot_fn = make_godot_fn( move |( $( $args, ) * ) : ( $( $Ps, ) * ) | {
165
- let mut target = C :: get_mut( & mut gd) ;
166
- let target_mut = target. deref_mut( ) ;
167
- function( target_mut, $( $args) ,* ) ;
165
+ let godot_fn = make_godot_fn( move |( $( $args, ) * ) : ( $( $Ps, ) * ) | {
166
+ let mut guard = Gd :: bind_mut( & mut gd) ;
167
+ function( & mut * guard, $( $args) ,* ) ;
168
+ } ) ;
169
+
170
+ self . inner_connect_godot_fn:: <F >( godot_fn) ;
171
+ }
172
+
173
+ /// Connect a method with `&mut Gd<Self>` as the first parameter (user + engine classes).
174
+ ///
175
+ /// - If your class `C` is user-defined and you'd like to have an automatic `bind_mut()` and receive `&mut self`, then
176
+ /// use [`connect_self_mut()`][Self::connect_self_mut] instead.
177
+ /// - To connect to methods on other objects, use [`connect_other_gd()`][Self::connect_other_gd].
178
+ /// - If you need [connect flags](ConnectFlags), call [`flags()`](Self::flags) before this.
179
+ /// - If you need cross-thread signals, use [`connect_sync()`](#method.connect_sync) instead (requires feature `experimental-threads`).
180
+ pub fn connect_self_gd<F , R >( self , mut function: F )
181
+ where
182
+ F : FnMut ( & mut Gd <C >, $( $Ps) ,* ) -> R + ' static ,
183
+ {
184
+ let mut gd = self . parent_sig. receiver_object( ) ;
185
+ let godot_fn = make_godot_fn( move |( $( $args, ) * ) : ( $( $Ps, ) * ) | {
186
+ function( & mut gd, $( $args) ,* ) ;
168
187
} ) ;
169
188
170
189
self . inner_connect_godot_fn:: <F >( godot_fn) ;
171
190
}
172
191
173
- /// Connect a method (member function) with any `&mut OtherC` as the first parameter, where
174
- /// `OtherC`: [`GodotClass`](crate::obj::GodotClass) (both user and engine classes are accepted).
192
+ /// Connect a method with any `&mut OtherC` as the first parameter (user classes only).
175
193
///
176
194
/// The parameter `object` can be of 2 different "categories":
177
- /// - Any `&Gd<OtherC>` (e.g.: `&Gd<Node>`, `&Gd<CustomUserClass >`).
178
- /// - `&OtherC`, as long as `OtherC` is a user class that contains a `base ` field (it implements the
195
+ /// - Any `&Gd<OtherC>` (e.g.: `&Gd<Node>`, `&Gd<MyClass >`).
196
+ /// - `&OtherC`, as long as `OtherC` is a user class that contains a `Base<T> ` field (it implements the
179
197
/// [`WithBaseField`](crate::obj::WithBaseField) trait).
180
198
///
181
199
/// ---
182
200
///
183
- /// - To connect to methods on the object that owns this signal, use [`connect_self ()`][Self::connect_self].
184
- /// - If you need [` connect flags` ](ConnectFlags), call [`flags()`](Self::flags) before this.
201
+ /// - To connect to methods on the object that owns this signal, use [`connect_self_mut ()`][Self::connect_self].
202
+ /// - If you need [connect flags](ConnectFlags), call [`flags()`](Self::flags) before this.
185
203
/// - If you need cross-thread signals, use [`connect_sync()`](#method.connect_sync) instead (requires feature "experimental-threads").
186
- pub fn connect_other <F , R , OtherC , Decl >( self , object: & impl ToSignalObj <OtherC >, mut method: F )
204
+ pub fn connect_other_mut <F , R , OtherC >( self , object: & impl ToSignalObj <OtherC >, mut method: F )
187
205
where
206
+ OtherC : GodotClass + Bounds <Declarer = bounds:: DeclUser >,
188
207
F : FnMut ( & mut OtherC , $( $Ps) ,* ) -> R + ' static ,
189
- OtherC : GodotDeref <Decl >,
190
208
{
191
209
let mut gd = object. to_signal_obj( ) ;
192
210
193
- let godot_fn = make_godot_fn( move |( $( $args, ) * ) : ( $( $Ps, ) * ) | {
194
- let mut target = OtherC :: get_mut( & mut gd) ;
195
- let target_mut = target. deref_mut( ) ;
196
- method( target_mut, $( $args) ,* ) ;
211
+ let godot_fn = make_godot_fn( move |( $( $args, ) * ) : ( $( $Ps, ) * ) | {
212
+ let mut guard = Gd :: bind_mut( & mut gd) ;
213
+ method( & mut * guard, $( $args) ,* ) ;
214
+ } ) ;
215
+
216
+ self . inner_connect_godot_fn:: <F >( godot_fn) ;
217
+ }
218
+
219
+ /// Connect a method with any `&mut Gd<OtherC>` as the first parameter (user + engine classes).
220
+ ///
221
+ /// The parameter `object` can be of 2 different "categories":
222
+ /// - Any `&Gd<OtherC>` (e.g.: `&Gd<Node>`, `&Gd<MyClass>`).
223
+ /// - `&OtherC`, as long as `OtherC` is a user class that contains a `Base<T>` field (it implements the
224
+ /// [`WithBaseField`](crate::obj::WithBaseField) trait).
225
+ ///
226
+ /// ---
227
+ ///
228
+ /// - To connect to methods on the object that owns this signal, use [`connect_self_gd()`][Self::connect_self_gd].
229
+ /// - If you need [connect flags](ConnectFlags), call [`flags()`](Self::flags) before this.
230
+ /// - If you need cross-thread signals, use [`connect_sync()`](#method.connect_sync) instead (requires feature "experimental-threads").
231
+ pub fn connect_other_gd<F , R , OtherC >( self , object: & impl ToSignalObj <OtherC >, mut method: F )
232
+ where
233
+ OtherC : GodotClass ,
234
+ F : FnMut ( & mut Gd <OtherC >, $( $Ps) ,* ) -> R + ' static ,
235
+ {
236
+ let mut gd = object. to_signal_obj( ) ;
237
+
238
+ let godot_fn = make_godot_fn( move |( $( $args, ) * ) : ( $( $Ps, ) * ) | {
239
+ method( & mut gd, $( $args) ,* ) ;
197
240
} ) ;
198
241
199
242
self . inner_connect_godot_fn:: <F >( godot_fn) ;
@@ -204,15 +247,15 @@ macro_rules! impl_builder_connect {
204
247
/// Requires `Send` + `Sync` bounds on the provided function `F`, and is only available for the `experimental-threads`
205
248
/// Cargo feature.
206
249
///
207
- /// If you need [` connect flags` ](ConnectFlags), call [`flags()`](Self::flags) before this.
250
+ /// If you need [connect flags](ConnectFlags), call [`flags()`](Self::flags) before this.
208
251
#[ cfg( feature = "experimental-threads" ) ]
209
252
pub fn connect_sync<F , R >( self , mut function: F )
210
253
where
211
254
// Why both Send+Sync: closure can not only impact another thread (Sync), but it's also possible to share such Callables across threads
212
255
// (Send) or even call them from multiple threads (Sync). We don't differentiate the fine-grained needs, it's either thread-safe or not.
213
256
F : FnMut ( $( $Ps) ,* ) -> R + Send + Sync + ' static ,
214
257
{
215
- let godot_fn = make_godot_fn( move |( $( $args, ) * ) : ( $( $Ps, ) * ) | {
258
+ let godot_fn = make_godot_fn( move |( $( $args, ) * ) : ( $( $Ps, ) * ) | {
216
259
function( $( $args) ,* ) ;
217
260
} ) ;
218
261
0 commit comments