Skip to content

Commit a752851

Browse files
authored
Merge pull request #1110 from godot-rust/feature/f32-process
Support `f32` directly in `process` and `physics_process`
2 parents 8340843 + f9b3cea commit a752851

File tree

7 files changed

+518
-258
lines changed

7 files changed

+518
-258
lines changed

godot-codegen/src/models/domain_mapping.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,6 @@ impl ClassMethod {
469469
}
470470

471471
let is_private = special_cases::is_method_private(class_name, &method.name);
472-
473472
let godot_method_name = method.name.clone();
474473

475474
let qualifier = {

godot-codegen/src/special_cases/special_cases.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
// NOTE: the methods are generally implemented on Godot types (e.g. AABB, not Aabb)
2323

24+
// This file is deliberately private -- all checks must go through `special_cases`.
25+
2426
#![allow(clippy::match_like_matches_macro)] // if there is only one rule
2527

2628
use crate::conv::to_enum_type_uncached;
@@ -30,7 +32,6 @@ use crate::special_cases::codegen_special_cases;
3032
use crate::util::option_as_slice;
3133
use crate::Context;
3234
use proc_macro2::Ident;
33-
// Deliberately private -- all checks must go through `special_cases`.
3435

3536
#[rustfmt::skip]
3637
pub fn is_class_method_deleted(class_name: &TyName, method: &JsonClassMethod, ctx: &mut Context) -> bool {
@@ -63,7 +64,7 @@ pub fn is_class_method_deleted(class_name: &TyName, method: &JsonClassMethod, ct
6364
| ("VisualShaderNodeComment", "set_description")
6465
| ("VisualShaderNodeComment", "get_description")
6566
=> true,
66-
67+
6768
// Workaround for methods unexposed in Release mode, see https://github.com/godotengine/godot/pull/100317
6869
// and https://github.com/godotengine/godot/pull/100328.
6970
#[cfg(not(debug_assertions))]
@@ -849,9 +850,9 @@ pub fn is_enum_private(class_name: Option<&TyName>, enum_name: &str) -> bool {
849850
}
850851

851852
/// Certain enums that are extremely unlikely to get new identifiers in the future.
852-
///
853+
///
853854
/// `class_name` = None for global enums.
854-
///
855+
///
855856
/// Very conservative, only includes a few enums. Even `VariantType` was extended over time.
856857
/// Also does not work for any enums containing duplicate ordinals.
857858
#[rustfmt::skip]
@@ -882,7 +883,7 @@ pub fn is_enum_bitfield(class_name: Option<&TyName>, enum_name: &str) -> Option<
882883
match (class_name, enum_name) {
883884
| (Some("Object"), "ConnectFlags")
884885

885-
=> Some(true),
886+
=> Some(true),
886887
_ => None
887888
}
888889
}

godot-core/src/obj/traits.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ pub trait WithBaseField: GodotClass + Bounds<Declarer = bounds::DeclUser> {
292292
///
293293
/// #[godot_api]
294294
/// impl INode for MyClass {
295-
/// fn process(&mut self, _delta: f64) {
295+
/// fn process(&mut self, _delta: f32) {
296296
/// let name = self.base().get_name();
297297
/// godot_print!("name is {name}");
298298
/// }
@@ -318,7 +318,7 @@ pub trait WithBaseField: GodotClass + Bounds<Declarer = bounds::DeclUser> {
318318
///
319319
/// #[godot_api]
320320
/// impl INode for MyClass {
321-
/// fn process(&mut self, _delta: f64) {
321+
/// fn process(&mut self, _delta: f32) {
322322
/// let node = Node::new_alloc();
323323
/// // fails because `add_child` requires a mutable reference.
324324
/// self.base().add_child(&node);
@@ -361,7 +361,7 @@ pub trait WithBaseField: GodotClass + Bounds<Declarer = bounds::DeclUser> {
361361
///
362362
/// #[godot_api]
363363
/// impl INode for MyClass {
364-
/// fn process(&mut self, _delta: f64) {
364+
/// fn process(&mut self, _delta: f32) {
365365
/// let node = Node::new_alloc();
366366
/// self.base_mut().add_child(&node);
367367
/// }
@@ -386,7 +386,7 @@ pub trait WithBaseField: GodotClass + Bounds<Declarer = bounds::DeclUser> {
386386
///
387387
/// #[godot_api]
388388
/// impl INode for MyClass {
389-
/// fn process(&mut self, _delta: f64) {
389+
/// fn process(&mut self, _delta: f32) {
390390
/// self.base_mut().call("other_method", &[]);
391391
/// }
392392
/// }

godot-macros/src/class/data_models/func.rs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,14 @@ pub struct SignatureInfo {
187187
pub method_name: Ident,
188188
pub receiver_type: ReceiverType,
189189
pub param_idents: Vec<Ident>,
190+
/// Parameter types *without* receiver.
190191
pub param_types: Vec<venial::TypeExpr>,
191192
pub return_type: TokenStream,
193+
194+
/// `(original index, new type)` only for changed parameters; empty if no changes.
195+
///
196+
/// Index points into original venial tokens (i.e. takes into account potential receiver params).
197+
pub modified_param_types: Vec<(usize, venial::TypeExpr)>,
192198
}
193199

194200
impl SignatureInfo {
@@ -199,6 +205,7 @@ impl SignatureInfo {
199205
param_idents: vec![],
200206
param_types: vec![],
201207
return_type: quote! { () },
208+
modified_param_types: vec![],
202209
}
203210
}
204211

@@ -359,7 +366,8 @@ pub(crate) fn into_signature_info(
359366
};
360367

361368
let mut next_unnamed_index = 0;
362-
for (arg, _) in signature.params.inner {
369+
let mut modified_param_types = vec![];
370+
for (index, (arg, _)) in signature.params.inner.into_iter().enumerate() {
363371
match arg {
364372
venial::FnParam::Receiver(recv) => {
365373
if receiver_type == ReceiverType::GdSelf {
@@ -377,8 +385,17 @@ pub(crate) fn into_signature_info(
377385
}
378386
venial::FnParam::Typed(arg) => {
379387
let ident = maybe_rename_parameter(arg.name, &mut next_unnamed_index);
380-
let ty = venial::TypeExpr {
381-
tokens: map_self_to_class_name(arg.ty.tokens, class_name),
388+
let ty = match maybe_change_parameter_type(arg.ty, &method_name, index) {
389+
// Parameter type was modified.
390+
Ok(ty) => {
391+
modified_param_types.push((index, ty.clone()));
392+
ty
393+
}
394+
395+
// Not an error, just unchanged.
396+
Err(ty) => venial::TypeExpr {
397+
tokens: map_self_to_class_name(ty.tokens, class_name),
398+
},
382399
};
383400

384401
param_types.push(ty);
@@ -393,6 +410,28 @@ pub(crate) fn into_signature_info(
393410
param_idents,
394411
param_types,
395412
return_type: ret_type,
413+
modified_param_types,
414+
}
415+
}
416+
417+
/// If `f32` is used for a delta parameter in a virtual process function, transparently use `f64` behind the scenes.
418+
fn maybe_change_parameter_type(
419+
param_ty: venial::TypeExpr,
420+
method_name: &Ident,
421+
param_index: usize,
422+
) -> Result<venial::TypeExpr, venial::TypeExpr> {
423+
// A bit hackish, but TokenStream APIs are also notoriously annoying to work with. Not even PartialEq...
424+
425+
if param_index == 1
426+
&& (method_name == "process" || method_name == "physics_process")
427+
&& param_ty.tokens.len() == 1
428+
&& param_ty.tokens[0].to_string() == "f32"
429+
{
430+
Ok(venial::TypeExpr {
431+
tokens: vec![TokenTree::Ident(ident("f64"))],
432+
})
433+
} else {
434+
Err(param_ty)
396435
}
397436
}
398437

0 commit comments

Comments
 (0)