Skip to content

Commit 6861b60

Browse files
committed
Backport virtual bugfix to <Godot 4.4
1 parent f38eb34 commit 6861b60

File tree

5 files changed

+29
-45
lines changed

5 files changed

+29
-45
lines changed

godot-codegen/src/generator/mod.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,9 @@ pub mod native_structures;
2727
pub mod notifications;
2828
pub mod signals;
2929
pub mod utility_functions;
30+
pub mod virtual_definition_consts;
3031
pub mod virtual_traits;
3132

32-
#[cfg(since_api = "4.4")]
33-
pub mod virtual_hashes;
34-
3533
// ----------------------------------------------------------------------------------------------------------------------------------------------
3634

3735
// Some file generation functions are in specific modules:
@@ -43,11 +41,6 @@ pub mod virtual_hashes;
4341
pub fn generate_sys_module_file(sys_gen_path: &Path, submit_fn: &mut SubmitFn) {
4442
// Don't delegate #[cfg] to generated code; causes issues in release CI, reproducible with:
4543
// cargo clippy --features godot/experimental-godot-api,godot/codegen-rustfmt,godot/serde
46-
let virtual_hashes_mod = if cfg!(since_api = "4.4") {
47-
quote! { pub mod virtual_hashes; }
48-
} else {
49-
quote! {}
50-
};
5144

5245
let code = quote! {
5346
pub mod table_builtins;
@@ -56,11 +49,11 @@ pub fn generate_sys_module_file(sys_gen_path: &Path, submit_fn: &mut SubmitFn) {
5649
pub mod table_scene_classes;
5750
pub mod table_editor_classes;
5851
pub mod table_utilities;
59-
#virtual_hashes_mod
6052

6153
pub mod central;
6254
pub mod gdextension_interface;
6355
pub mod interface;
56+
pub mod virtual_consts;
6457
};
6558

6659
submit_fn(sys_gen_path.join("mod.rs"), code);
@@ -93,12 +86,9 @@ pub fn generate_sys_classes_file(
9386

9487
// From 4.4 onward, generate table that maps all virtual methods to their known hashes.
9588
// This allows Godot to fall back to an older compatibility function if one is not supported.
96-
#[cfg(since_api = "4.4")]
97-
{
98-
let code = virtual_hashes::make_virtual_hashes_file(api, ctx);
99-
submit_fn(sys_gen_path.join("virtual_hashes.rs"), code);
100-
watch.record("generate_virtual_hashes_file");
101-
}
89+
let code = virtual_definition_consts::make_virtual_consts_file(api, ctx);
90+
submit_fn(sys_gen_path.join("virtual_consts.rs"), code);
91+
watch.record("generate_virtual_consts_file");
10292
}
10393

10494
pub fn generate_sys_utilities_file(

godot-codegen/src/generator/virtual_hashes.rs renamed to godot-codegen/src/generator/virtual_definition_consts.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::models::domain::{Class, ClassLike, ExtensionApi, FnDirection, Functio
1010
use proc_macro2::TokenStream;
1111
use quote::quote;
1212

13-
pub fn make_virtual_hashes_file(api: &ExtensionApi, ctx: &mut Context) -> TokenStream {
13+
pub fn make_virtual_consts_file(api: &ExtensionApi, ctx: &mut Context) -> TokenStream {
1414
make_virtual_hashes_for_all_classes(&api.classes, ctx)
1515
}
1616

@@ -39,15 +39,25 @@ fn make_virtual_hashes_for_class(class: &Class, ctx: &mut Context) -> TokenStrea
3939
};
4040

4141
let constants = class.methods.iter().filter_map(|method| {
42-
let FnDirection::Virtual { hash } = method.direction() else {
42+
let FnDirection::Virtual {
43+
#[cfg(since_api = "4.4")]
44+
hash,
45+
} = method.direction()
46+
else {
4347
return None;
4448
};
4549

4650
let rust_name = method.name_ident();
4751
let godot_name_str = method.godot_name();
52+
53+
#[cfg(since_api = "4.4")]
4854
let constant = quote! {
4955
pub const #rust_name: (&'static str, u32) = (#godot_name_str, #hash);
5056
};
57+
#[cfg(before_api = "4.4")]
58+
let constant = quote! {
59+
pub const #rust_name: &'static str = #godot_name_str;
60+
};
5161

5262
Some(constant)
5363
});

godot-ffi/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,7 @@ pub use gen::table_editor_classes::*;
8282
pub use gen::table_scene_classes::*;
8383
pub use gen::table_servers_classes::*;
8484
pub use gen::table_utilities::*;
85-
#[cfg(since_api = "4.4")]
86-
pub use gen::virtual_hashes as known_virtual_hashes;
85+
pub use gen::virtual_consts as godot_virtual_consts;
8786

8887
// Other
8988
pub use extras::*;

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

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,8 @@ pub fn transform_trait_impl(mut original_impl: venial::Impl) -> ParseResult<Toke
107107
let match_arm = OverriddenVirtualFn {
108108
cfg_attrs: vec![],
109109
rust_method_name: "_ready".to_string(),
110-
// Can't use `hashes::ready` here, as the base class might not be `Node` (see above why such a branch is still added).
111-
#[cfg(since_api = "4.4")]
112-
godot_name_hash_constant: quote! { ::godot::sys::known_virtual_hashes::Node::ready },
110+
// Can't use `virtuals::ready` here, as the base class might not be `Node` (see above why such a branch is still added).
111+
godot_name_hash_constant: quote! { ::godot::sys::godot_virtual_consts::Node::ready },
113112
signature_info: SignatureInfo::fn_ready(),
114113
before_kind: BeforeKind::OnlyBefore,
115114
interface_trait: None,
@@ -136,16 +135,12 @@ pub fn transform_trait_impl(mut original_impl: venial::Impl) -> ParseResult<Toke
136135
};
137136

138137
// See also __default_virtual_call() codegen.
139-
let (hash_param, hashes_use, match_expr);
138+
let (hash_param, match_expr);
140139
if cfg!(since_api = "4.4") {
141140
hash_param = quote! { hash: u32, };
142-
hashes_use = quote! {
143-
use ::godot::sys::known_virtual_hashes::#trait_base_class as hashes;
144-
};
145141
match_expr = quote! { (name, hash) };
146142
} else {
147143
hash_param = TokenStream::new();
148-
hashes_use = TokenStream::new();
149144
match_expr = quote! { name };
150145
};
151146

@@ -164,9 +159,9 @@ pub fn transform_trait_impl(mut original_impl: venial::Impl) -> ParseResult<Toke
164159
fn __virtual_call(name: &str, #hash_param) -> ::godot::sys::GDExtensionClassCallVirtual {
165160
//println!("virtual_call: {}.{}", std::any::type_name::<Self>(), name);
166161
use ::godot::obj::UserClass as _;
162+
use ::godot::sys::godot_virtual_consts::#trait_base_class as virtuals;
167163
#tool_check
168164

169-
#hashes_use
170165
match #match_expr {
171166
#( #virtual_match_arms )*
172167
_ => None,
@@ -459,7 +454,6 @@ fn handle_regular_virtual_fn<'a>(
459454
cfg_attrs: Vec<&'a venial::Attribute>,
460455
decls: &mut IDecls<'a>,
461456
) -> Option<(venial::Punctuated<venial::FnParam>, Group)> {
462-
#[cfg(since_api = "4.4")]
463457
let method_name_ident = original_method.name.clone();
464458
let method = util::reduce_to_signature(original_method);
465459

@@ -520,10 +514,9 @@ fn handle_regular_virtual_fn<'a>(
520514
cfg_attrs,
521515
rust_method_name: virtual_method_name,
522516
// If ever the `I*` verbatim validation is relaxed (it won't work with use-renames or other weird edge cases), the approach
523-
// with known_virtual_hashes module could be changed to something like the following (GodotBase = nearest Godot base class):
517+
// with godot_virtual_consts module could be changed to something like the following (GodotBase = nearest Godot base class):
524518
// __get_virtual_hash::<Self::GodotBase>("method")
525-
#[cfg(since_api = "4.4")]
526-
godot_name_hash_constant: quote! { hashes::#method_name_ident },
519+
godot_name_hash_constant: quote! { virtuals::#method_name_ident },
527520
signature_info,
528521
before_kind,
529522
interface_trait: Some(trait_path.clone()),
@@ -575,7 +568,8 @@ struct OverriddenVirtualFn<'a> {
575568
cfg_attrs: Vec<&'a venial::Attribute>,
576569
rust_method_name: String,
577570
/// Path to a pre-defined constant storing a `("_virtual_func", 123456789)` tuple with name and hash of the virtual function.
578-
#[cfg(since_api = "4.4")]
571+
///
572+
/// Before Godot 4.4, this just stores the name `"_virtual_func"`.
579573
godot_name_hash_constant: TokenStream,
580574
signature_info: SignatureInfo,
581575
before_kind: BeforeKind,
@@ -585,16 +579,7 @@ struct OverriddenVirtualFn<'a> {
585579
impl OverriddenVirtualFn<'_> {
586580
fn make_match_arm(&self, class_name: &Ident) -> TokenStream {
587581
let cfg_attrs = self.cfg_attrs.iter();
588-
589-
#[cfg(since_api = "4.4")]
590-
let pattern = {
591-
let godot_name_hash_constant = &self.godot_name_hash_constant;
592-
quote! { #godot_name_hash_constant }
593-
};
594-
595-
// Note: this is wrong before 4.4, as some methods are renamed in Rust.
596-
#[cfg(before_api = "4.4")]
597-
let pattern = self.rust_method_name.as_str();
582+
let godot_name_hash_constant = &self.godot_name_hash_constant;
598583

599584
// Lazily generate code for the actual work (calling user function).
600585
let method_callback = make_virtual_callback(
@@ -606,7 +591,7 @@ impl OverriddenVirtualFn<'_> {
606591

607592
quote! {
608593
#(#cfg_attrs)*
609-
#pattern => #method_callback,
594+
#godot_name_hash_constant => #method_callback,
610595
}
611596
}
612597
}

godot-macros/src/class/derive_godot_class.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ fn make_user_class_impl(
404404
if cfg!(since_api = "4.4") {
405405
hash_param = quote! { hash: u32, };
406406
matches_ready_hash = quote! {
407-
(name, hash) == ::godot::sys::known_virtual_hashes::Node::ready
407+
(name, hash) == ::godot::sys::godot_virtual_consts::Node::ready
408408
};
409409
} else {
410410
hash_param = TokenStream::new();

0 commit comments

Comments
 (0)