5
5
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
6
*/
7
7
8
- use crate :: builtin:: { Callable , GString , Variant } ;
8
+ use crate :: builtin:: { Callable , Variant } ;
9
9
use crate :: classes:: object:: ConnectFlags ;
10
10
use crate :: obj:: { bounds, Bounds , Gd , GodotClass , WithBaseField } ;
11
- use crate :: registry:: signal:: { ConnectBuilder , SignalReceiver } ;
11
+ use crate :: registry:: signal:: { make_callable_name , make_godot_fn , ConnectBuilder , SignalReceiver } ;
12
12
use crate :: { classes, meta} ;
13
13
use std:: borrow:: Cow ;
14
14
use std:: marker:: PhantomData ;
@@ -117,16 +117,11 @@ impl<'c, C: WithBaseField, Ps: meta::ParamTuple> TypedSignal<'c, C, Ps> {
117
117
where
118
118
F : SignalReceiver < ( ) , Ps > ,
119
119
{
120
- let callable_name = std:: any:: type_name_of_val ( & function) ;
121
-
122
- let godot_fn = move |variant_args : & [ & Variant ] | -> Result < Variant , ( ) > {
123
- let args = Ps :: from_variant_array ( variant_args) ;
120
+ let godot_fn = make_godot_fn ( move |args| {
124
121
function. call ( ( ) , args) ;
122
+ } ) ;
125
123
126
- Ok ( Variant :: nil ( ) )
127
- } ;
128
-
129
- self . inner_connect_local ( callable_name, godot_fn) ;
124
+ self . inner_connect_godot_fn :: < F > ( godot_fn) ;
130
125
}
131
126
132
127
/// Connect a method (member function) with `&mut self` as the first parameter.
@@ -137,27 +132,14 @@ impl<'c, C: WithBaseField, Ps: meta::ParamTuple> TypedSignal<'c, C, Ps> {
137
132
where
138
133
for < ' c_rcv > F : SignalReceiver < & ' c_rcv mut C , Ps > ,
139
134
{
140
- // When using sys::short_type_name() in the future, make sure global "func" and member "MyClass::func" are rendered as such.
141
- // PascalCase heuristic should then be good enough.
142
- let callable_name = std:: any:: type_name_of_val ( & function) ;
143
-
144
- let object = self . owner . to_owned ( ) ;
145
- let godot_fn = move |variant_args : & [ & Variant ] | -> Result < Variant , ( ) > {
146
- let args = Ps :: from_variant_array ( variant_args) ;
147
-
148
- // let mut function = function;
149
- // function.call(instance, args);
150
- let mut object = object. clone ( ) ;
151
-
152
- // TODO: how to avoid another bind, when emitting directly from Rust?
153
- let mut instance = object. bind_mut ( ) ;
135
+ let mut gd = self . owner . to_owned ( ) ;
136
+ let godot_fn = make_godot_fn ( move |args| {
137
+ let mut instance = gd. bind_mut ( ) ;
154
138
let instance = & mut * instance;
155
139
function. call ( instance, args) ;
140
+ } ) ;
156
141
157
- Ok ( Variant :: nil ( ) )
158
- } ;
159
-
160
- self . inner_connect_local ( callable_name, godot_fn) ;
142
+ self . inner_connect_godot_fn :: < F > ( godot_fn) ;
161
143
}
162
144
163
145
/// Connect a method (member function) with any `Gd<T>` (not `self`) as the first parameter.
@@ -169,20 +151,14 @@ impl<'c, C: WithBaseField, Ps: meta::ParamTuple> TypedSignal<'c, C, Ps> {
169
151
OtherC : GodotClass + Bounds < Declarer = bounds:: DeclUser > ,
170
152
for < ' c_rcv > F : SignalReceiver < & ' c_rcv mut OtherC , Ps > ,
171
153
{
172
- let callable_name = std:: any:: type_name_of_val ( & function) ;
173
-
174
- let mut object = object. clone ( ) ;
175
- let godot_fn = move |variant_args : & [ & Variant ] | -> Result < Variant , ( ) > {
176
- let args = Ps :: from_variant_array ( variant_args) ;
177
-
178
- let mut instance = object. bind_mut ( ) ;
154
+ let mut gd = object. clone ( ) ;
155
+ let godot_fn = make_godot_fn ( move |args| {
156
+ let mut instance = gd. bind_mut ( ) ;
179
157
let instance = & mut * instance;
180
158
function. call ( instance, args) ;
159
+ } ) ;
181
160
182
- Ok ( Variant :: nil ( ) )
183
- } ;
184
-
185
- self . inner_connect_local ( callable_name, godot_fn) ;
161
+ self . inner_connect_godot_fn :: < F > ( godot_fn) ;
186
162
}
187
163
188
164
/// Fully customizable connection setup.
@@ -193,19 +169,32 @@ impl<'c, C: WithBaseField, Ps: meta::ParamTuple> TypedSignal<'c, C, Ps> {
193
169
ConnectBuilder :: new ( self )
194
170
}
195
171
196
- fn inner_connect_local < F > ( & mut self , callable_name : impl meta:: AsArg < GString > , godot_fn : F )
197
- where
198
- F : FnMut ( & [ & Variant ] ) -> Result < Variant , ( ) > + ' static ,
199
- {
200
- let signal_name = self . name . as_ref ( ) ;
201
- let callable = Callable :: from_local_fn ( callable_name, godot_fn) ;
172
+ /// Directly connect a Rust callable `godot_fn`, with a name based on `F`.
173
+ ///
174
+ /// This exists as a short-hand for the connect methods on [`TypedSignal`] and avoids the generic instantiation of the full-blown
175
+ /// type state builder for simple + common connections, thus hopefully being a tiny bit lighter on compile times.
176
+ fn inner_connect_godot_fn < F > (
177
+ & mut self ,
178
+ godot_fn : impl FnMut ( & [ & Variant ] ) -> Result < Variant , ( ) > + ' static ,
179
+ ) {
180
+ let callable_name = make_callable_name :: < F > ( ) ;
181
+ let callable = Callable :: from_local_fn ( & callable_name, godot_fn) ;
202
182
183
+ let signal_name = self . name . as_ref ( ) ;
203
184
self . owner . with_object_mut ( |obj| {
204
185
obj. connect ( signal_name, & callable) ;
205
186
} ) ;
206
187
}
207
188
208
- pub ( super ) fn connect_untyped ( & mut self , callable : & Callable , flags : Option < ConnectFlags > ) {
189
+ /// Connect an untyped callable, with optional flags.
190
+ ///
191
+ /// Used by [`ConnectBuilder::done()`]. Any other type-state (such as thread-local/sync, callable debug name, etc.) are baked into
192
+ /// `callable` and thus type-erased into runtime logic.
193
+ pub ( super ) fn inner_connect_untyped (
194
+ & mut self ,
195
+ callable : & Callable ,
196
+ flags : Option < ConnectFlags > ,
197
+ ) {
209
198
use crate :: obj:: EngineBitfield ;
210
199
211
200
let signal_name = self . name . as_ref ( ) ;
0 commit comments