Enable Var (including PhantomVar) for engine enums#1438
Enable Var (including PhantomVar) for engine enums#1438Bromeon merged 1 commit intogodot-rust:masterfrom
Var (including PhantomVar) for engine enums#1438Conversation
|
Thanks a lot for the contribution! 👍
Yep, I think that's nice to have.
It's fine, but can you not use the same logic as used in the codegen for introspection methods on I don't think there's a need to reimplement the enum-to-string logic. |
Bromeon
left a comment
There was a problem hiding this comment.
Please also squash commits to 1 eventually, see Contributing guidelines.
| // Bounds for T are somewhat un-idiomatically directly on the type, rather than impls. | ||
| // This improves error messages in IDEs when using the type as a field. | ||
| pub struct PhantomVar<T: GodotType + Var>(PhantomData<T>); | ||
| pub struct PhantomVar<T: GodotConvert + Var>(PhantomData<T>); |
There was a problem hiding this comment.
Why these bound changes everywhere?
There was a problem hiding this comment.
Some are mandatory, such as Var, Export, and Default. Debug, Clone, and Copy might be needed, but they're not in my use case.
As for the rest... I think GodotConvert is more permissive than GodotType, and it only adds cost when actually called, so I modified it accordingly.
There was a problem hiding this comment.
The changes might be finalized tomorrow; it's too late here. Sorry~
There was a problem hiding this comment.
I think
GodotConvertis more permissive thanGodotType
Good point, makes sense 👍
| /// Returns the hint string for the given enum. | ||
| /// | ||
| /// Separate with commas, and remove the `<ENUM_NAME>_` prefix (if possible). | ||
| /// e.g.: "Left,Center,Right,Fill" | ||
| fn make_enum_hint_string(enum_: &Enum) -> String { | ||
| let upper_cast_enum_name = enum_.godot_name.to_shouty_snake_case() + "_"; | ||
| enum_.enumerators | ||
| .iter() | ||
| .map(|enumerator| { | ||
| enumerator.godot_name | ||
| .clone() | ||
| .trim_start_matches(upper_cast_enum_name.as_str()) | ||
| .to_pascal_case() | ||
| }) | ||
| .collect::<Vec<String>>() | ||
| .join(",") | ||
| } |
There was a problem hiding this comment.
As mentioned, this logic should already exist in some form.
There was a problem hiding this comment.
I see. Can you reuse one of these though?
gdext/godot-codegen/src/conv/name_conversions.rs
Lines 57 to 105 in 0b6b792
If not, it should at least become a dedicated conversion function in that file (ideally with a comment on how it differs from the others). Thanks! 🙂
godot-codegen/src/generator/enums.rs
Outdated
|
|
||
| let var_trait_set_property = if enum_.is_exhaustive { | ||
| quote! { | ||
| fn set_property(&mut self, value: Self::Via){ |
There was a problem hiding this comment.
| fn set_property(&mut self, value: Self::Via){ | |
| fn set_property(&mut self, value: Self::Via) { |
Please fix this same formatting error everywhere 🙂
|
API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-1438 |
94eb91e to
f76040c
Compare
| // Bounds for T are somewhat un-idiomatically directly on the type, rather than impls. | ||
| // This improves error messages in IDEs when using the type as a field. | ||
| pub struct PhantomVar<T: GodotType + Var>(PhantomData<T>); | ||
| pub struct PhantomVar<T: GodotConvert + Var>(PhantomData<T>); |
There was a problem hiding this comment.
I think
GodotConvertis more permissive thanGodotType
Good point, makes sense 👍
| /// Returns the hint string for the given enum. | ||
| /// | ||
| /// Separate with commas, and remove the `<ENUM_NAME>_` prefix (if possible). | ||
| /// e.g.: "Left,Center,Right,Fill" | ||
| fn make_enum_hint_string(enum_: &Enum) -> String { | ||
| let upper_cast_enum_name = enum_.godot_name.to_shouty_snake_case() + "_"; | ||
| enum_.enumerators | ||
| .iter() | ||
| .map(|enumerator| { | ||
| enumerator.godot_name | ||
| .clone() | ||
| .trim_start_matches(upper_cast_enum_name.as_str()) | ||
| .to_pascal_case() | ||
| }) | ||
| .collect::<Vec<String>>() | ||
| .join(",") | ||
| } |
There was a problem hiding this comment.
I see. Can you reuse one of these though?
gdext/godot-codegen/src/conv/name_conversions.rs
Lines 57 to 105 in 0b6b792
If not, it should at least become a dedicated conversion function in that file (ideally with a comment on how it differs from the others). Thanks! 🙂
godot-codegen/src/generator/enums.rs
Outdated
| fn var_hint() -> crate::meta::PropertyHintInfo{ | ||
| crate::meta::PropertyHintInfo{ | ||
| hint: #property_hint, | ||
| hint_string: #enum_hint_string.into(), |
There was a problem hiding this comment.
Please use explicit GString::from() here.
| hint_string: #enum_hint_string.into(), | |
| hint_string: GString::from(#enum_hint_string), |
4b2f968 to
e537bc7
Compare
|
Thank you! What would be nice now is to add 1-2 small integration tests, to make sure enums work. You could add
For inspiration how |
|
No problem. But I haven't used the gdext testing framework before; I'll look into how to do this later. |
|
We also have a guide: |
e537bc7 to
3416265
Compare
PhantomVar to work with engine enumsVar (including PhantomVar) for engine enums
|
Thanks a lot, and congrats to your first contribution! 🙂 |

Background
See #1437
Feature
This enables use cases like:
Key Changes
Modify:
In
godot-core/src/registry/property/phantom_var.rsThis makes the requirements for PhantomVar more lenient, because
GodotTypeis a metaphor forGodotConvert. For existing supported typeswhere T: GodotType and Via = T, behavior remains the same.Add
In
godot-codegen/src/generator/enums.rsConcern
Clearly, not all enumerations will be edited as fields in the inspector. However, this PR extensively implements
VarandExportfor godot enums. Is it acceptable to treat all engine enums as "exportable as properties" by default, given that it's purely additive and only used when the user opts into exporting such fields?Additionally, I've provided a
make_enum_hint_stringfunction:It works fairly well, with one exception: for EularOrder, users might prefer to see values like
XYZrather thanXyz. Unfortunately, I cannot distinguish this throughextension_api.json.During my research of the Godot source code, I found this line:
This means that Godot itself does not have a method to convert enum values to hint strings, it's entirely "manually" maintained in every component that uses enum types.
This PR can be interpreted as an "overstepping" of authority, adding extra behavior to gdext that doesn't exist in Godot, but the user experience might be more comfortable than developing components on native Godot.
But is this allowed?
Thanks for considering this!