From 2e3b74cacebc66c2abd0c89cf76440bcfd14b084 Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Fri, 7 Apr 2023 23:38:16 +0200 Subject: [PATCH] Support engine class constants --- godot-codegen/src/api_parser.rs | 11 ++++++++--- godot-codegen/src/class_generator.rs | 23 ++++++++++++++++++++--- godot-codegen/src/util.rs | 11 ++++++++++- itest/rust/src/codegen_test.rs | 8 +++++++- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/godot-codegen/src/api_parser.rs b/godot-codegen/src/api_parser.rs index 3561a672c..6a67760cf 100644 --- a/godot-codegen/src/api_parser.rs +++ b/godot-codegen/src/api_parser.rs @@ -41,7 +41,7 @@ pub struct BuiltinClass { pub indexing_return_type: Option, pub is_keyed: bool, pub members: Option>, - pub constants: Option>, + // pub constants: Option>, pub enums: Option>, // no bitfield pub operators: Vec, pub methods: Option>, @@ -56,7 +56,7 @@ pub struct Class { pub is_instantiable: bool, pub inherits: Option, // pub api_type: String, - // pub constants: Option>, + pub constants: Option>, pub enums: Option>, pub methods: Option>, // pub properties: Option>, @@ -100,13 +100,18 @@ pub struct EnumConstant { pub value: i32, } +pub type ClassConstant = EnumConstant; + +/* +// Constants of builtin types have a string value like "Vector2(1, 1)", hence also a type field #[derive(DeJson)] -pub struct Constant { +pub struct BuiltinConstant { pub name: String, #[nserde(rename = "type")] pub type_: String, pub value: String, } +*/ #[derive(DeJson)] pub struct Operator { diff --git a/godot-codegen/src/class_generator.rs b/godot-codegen/src/class_generator.rs index b27eb91a9..1fd9baf44 100644 --- a/godot-codegen/src/class_generator.rs +++ b/godot-codegen/src/class_generator.rs @@ -173,6 +173,7 @@ fn make_class(class: &Class, class_name: &TyName, ctx: &mut Context) -> Generate let constructor = make_constructor(class, ctx); let methods = make_methods(&class.methods, class_name, ctx); let enums = make_enums(&class.enums, class_name, ctx); + let constants = make_constants(&class.constants, class_name, ctx); let inherits_macro = format_ident!("inherits_transitive_{}", class_name.rust_ty); let all_bases = ctx.inheritance_tree().collect_all_bases(class_name); let virtual_trait = make_virtual_methods_trait(class, &all_bases, &virtual_trait_str, ctx); @@ -205,6 +206,7 @@ fn make_class(class: &Class, class_name: &TyName, ctx: &mut Context) -> Generate impl #class_name { #constructor #methods + #constants } impl crate::obj::GodotClass for #class_name { type Base = #base; @@ -420,9 +422,8 @@ fn make_builtin_methods( } fn make_enums(enums: &Option>, _class_name: &TyName, _ctx: &Context) -> TokenStream { - let enums = match enums { - Some(e) => e, - None => return TokenStream::new(), + let Some(enums) = enums else { + return TokenStream::new(); }; let definitions = enums.iter().map(util::make_enum_definition); @@ -432,6 +433,22 @@ fn make_enums(enums: &Option>, _class_name: &TyName, _ctx: &Context) - } } +fn make_constants( + constants: &Option>, + _class_name: &TyName, + _ctx: &Context, +) -> TokenStream { + let Some(constants) = constants else { + return TokenStream::new(); + }; + + let definitions = constants.iter().map(util::make_constant_definition); + + quote! { + #( #definitions )* + } +} + /// Depending on the built-in class, adds custom constructors and methods. fn make_special_builtin_methods(class_name: &TyName, _ctx: &Context) -> TokenStream { if class_name.godot_ty == "Array" { diff --git a/godot-codegen/src/util.rs b/godot-codegen/src/util.rs index d3b4735f0..8a3c39d49 100644 --- a/godot-codegen/src/util.rs +++ b/godot-codegen/src/util.rs @@ -4,7 +4,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::api_parser::Enum; +use crate::api_parser::{ClassConstant, Enum}; use crate::special_cases::is_builtin_scalar; use crate::{Context, ModName, RustTy, TyName}; use proc_macro2::{Ident, Literal, TokenStream}; @@ -106,6 +106,15 @@ pub fn make_enum_definition(enum_: &Enum) -> TokenStream { } } +pub fn make_constant_definition(constant: &ClassConstant) -> TokenStream { + let ClassConstant { name, value } = constant; + let name = ident(name); + + quote! { + pub const #name: i32 = #value; + } +} + fn make_enum_name(enum_name: &str) -> Ident { // TODO clean up enum name diff --git a/itest/rust/src/codegen_test.rs b/itest/rust/src/codegen_test.rs index 14a7fd0dc..d292acc8c 100644 --- a/itest/rust/src/codegen_test.rs +++ b/itest/rust/src/codegen_test.rs @@ -9,7 +9,7 @@ use crate::itest; use godot::builtin::inner::{InnerColor, InnerString}; -use godot::engine::{FileAccess, HttpRequest, HttpRequestVirtual}; +use godot::engine::{FileAccess, HttpRequest, HttpRequestVirtual, Image}; use godot::prelude::*; #[itest] @@ -50,6 +50,12 @@ fn codegen_static_class_method() { // see also object_test for reference count verification } +#[itest] +fn codegen_constants() { + assert_eq!(Image::MAX_WIDTH, 16777216); + // assert_eq!(Material::RENDER_PRIORITY_MIN, -128); +} + // ---------------------------------------------------------------------------------------------------------------------------------------------- #[derive(GodotClass)]