Skip to content

Commit 4b2f968

Browse files
committed
feat: support engine enums in PhantomVar and implement Var/Export for bindings
1 parent 3416265 commit 4b2f968

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

godot-codegen/src/generator/enums.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
1212
use std::collections::HashSet;
1313

14+
use heck::ToPascalCase;
1415
use proc_macro2::TokenStream;
1516
use quote::{quote, ToTokens};
1617

@@ -45,6 +46,7 @@ pub fn make_enum_definition_with(
4546
// Things needed for the type definition
4647
let derives = enum_.derives();
4748
let enum_doc = make_enum_doc(enum_);
49+
let enum_hint_string = make_enum_hint_string(enum_);
4850
let name = &enum_.name;
4951

5052
// Values
@@ -105,9 +107,28 @@ pub fn make_enum_definition_with(
105107

106108
// Trait implementations.
107109
let engine_trait_impl = make_enum_engine_trait_impl(enum_, enum_bitmask.as_ref());
110+
let property_hint = if enum_.is_bitfield {
111+
quote! { crate::global::PropertyHint::FLAGS }
112+
} else {
113+
quote! { crate::global::PropertyHint::ENUM }
114+
};
108115
let index_enum_impl = make_enum_index_impl(enum_);
109116
let bitwise_impls = make_enum_bitwise_operators(enum_, enum_bitmask.as_ref());
110117

118+
let var_trait_set_property = if enum_.is_exhaustive {
119+
quote! {
120+
fn set_property(&mut self, value: Self::Via) {
121+
*self = <Self as #engine_trait>::from_ord(value);
122+
}
123+
}
124+
} else {
125+
quote! {
126+
fn set_property(&mut self, value: Self::Via) {
127+
self.ord = value;
128+
}
129+
}
130+
};
131+
111132
quote! {
112133
#engine_trait_impl
113134
#index_enum_impl
@@ -131,6 +152,23 @@ pub fn make_enum_definition_with(
131152
.ok_or_else(|| crate::meta::error::FromGodotError::InvalidEnum.into_error(via))
132153
}
133154
}
155+
156+
impl crate::registry::property::Var for #name {
157+
fn get_property(&self) -> Self::Via{
158+
<Self as #engine_trait>::ord(*self)
159+
}
160+
161+
#var_trait_set_property
162+
163+
fn var_hint() -> crate::meta::PropertyHintInfo{
164+
crate::meta::PropertyHintInfo{
165+
hint: #property_hint,
166+
hint_string: crate::builtin::GString::from(#enum_hint_string),
167+
}
168+
}
169+
}
170+
171+
impl crate::registry::property::Export for #name {}
134172
}
135173
});
136174

@@ -481,6 +519,18 @@ fn make_enum_doc(enum_: &Enum) -> Vec<String> {
481519

482520
docs
483521
}
522+
/// Returns the hint string for the given enum.
523+
///
524+
/// Separate with commas, and remove the `<ENUM_NAME>_` prefix (if possible).
525+
/// e.g.: "Left,Center,Right,Fill"
526+
fn make_enum_hint_string(enum_: &Enum) -> String {
527+
enum_
528+
.enumerators
529+
.iter()
530+
.map(|enumerator| enumerator.name.to_string().to_pascal_case())
531+
.collect::<Vec<String>>()
532+
.join(",")
533+
}
484534

485535
/// Creates a definition for `enumerator` of the type `enum_type`.
486536
///

godot-core/src/registry/property/phantom_var.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,15 @@ use crate::registry::property::{Export, Var};
5555
/// This field can now be accessed from GDScript as `banner.text`.
5656
// Bounds for T are somewhat un-idiomatically directly on the type, rather than impls.
5757
// This improves error messages in IDEs when using the type as a field.
58-
pub struct PhantomVar<T: GodotType + Var>(PhantomData<T>);
58+
pub struct PhantomVar<T: GodotConvert + Var>(PhantomData<T>);
5959

60-
impl<T: GodotType + Var> GodotConvert for PhantomVar<T> {
61-
type Via = T;
60+
impl<T: GodotConvert + Var> GodotConvert for PhantomVar<T> {
61+
type Via = <T as GodotConvert>::Via;
6262
}
6363

6464
// `PhantomVar` supports only part of `Var`, but it has to implement it, otherwise we cannot implement `Export` either.
6565
// The `GodotClass` derive macro should ensure that the `Var` implementation is not used.
66-
impl<T: GodotType + Var> Var for PhantomVar<T> {
66+
impl<T: GodotConvert + Var> Var for PhantomVar<T> {
6767
fn get_property(&self) -> Self::Via {
6868
unreachable!("code generated by GodotClass should call the custom getter")
6969
}
@@ -78,7 +78,7 @@ impl<T: GodotType + Var> Var for PhantomVar<T> {
7878
}
7979

8080
// Reuse values from `T`, if any.
81-
impl<T: GodotType + Var + Export> Export for PhantomVar<T> {
81+
impl<T: GodotConvert + Var + Export> Export for PhantomVar<T> {
8282
fn export_hint() -> PropertyHintInfo {
8383
<T as Export>::export_hint()
8484
}
@@ -88,7 +88,7 @@ impl<T: GodotType + Var + Export> Export for PhantomVar<T> {
8888
}
8989
}
9090

91-
impl<T: GodotType + Var> Default for PhantomVar<T> {
91+
impl<T: GodotConvert + Var> Default for PhantomVar<T> {
9292
fn default() -> Self {
9393
Self(Default::default())
9494
}

0 commit comments

Comments
 (0)