Skip to content

Commit d013d2f

Browse files
committed
EngineBitfield::all_constants()
1 parent 17004dc commit d013d2f

File tree

5 files changed

+94
-29
lines changed

5 files changed

+94
-29
lines changed

godot-codegen/src/generator/enums.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ fn make_enum_engine_trait_impl(enum_: &Enum, enum_bitmask: Option<&RustTy>) -> T
227227
if enum_.is_bitfield {
228228
// Bitfields: u64, assume any combination is valid.
229229

230+
let constants_function = make_bitfield_constants_function(enum_);
231+
230232
quote! {
231233
// We may want to add this in the future.
232234
//
@@ -242,6 +244,8 @@ fn make_enum_engine_trait_impl(enum_: &Enum, enum_bitmask: Option<&RustTy>) -> T
242244
fn ord(self) -> u64 {
243245
self.ord
244246
}
247+
248+
#constants_function
245249
}
246250
}
247251
} else if enum_.is_exhaustive {
@@ -347,7 +351,7 @@ fn make_enum_values_and_constants_functions(enum_: &Enum) -> TokenStream {
347351

348352
// all_constants() includes every constant unconditionally.
349353
all_constants.push(quote! {
350-
crate::meta::inspect::EnumConstant::new(#rust_name, #godot_name, #ordinal, #name::#constant)
354+
crate::meta::inspect::EnumConstant::new(#rust_name, #godot_name, #name::#constant)
351355
});
352356

353357
// values() contains value only if distinct (first time seen) and not MAX.
@@ -433,6 +437,40 @@ fn make_enum_str_functions(enum_: &Enum) -> TokenStream {
433437
}
434438
}
435439

440+
/// Creates the `all_constants()` implementation for the bitfield.
441+
fn make_bitfield_constants_function(enum_: &Enum) -> TokenStream {
442+
let name = &enum_.name;
443+
444+
let all_constants = enum_.enumerators.iter().map(|enumerator| {
445+
let Enumerator {
446+
name: constant,
447+
godot_name,
448+
value: EnumeratorValue::Bitfield(_ord),
449+
..
450+
} = enumerator
451+
else {
452+
panic!("bitfield enum contains non-bitfield enumerators")
453+
};
454+
455+
let rust_name = constant.to_string();
456+
let godot_name_str = godot_name.to_string();
457+
458+
quote! {
459+
crate::meta::inspect::EnumConstant::new(#rust_name, #godot_name_str, #name::#constant)
460+
}
461+
});
462+
463+
quote! {
464+
fn all_constants() -> &'static [crate::meta::inspect::EnumConstant<#name>] {
465+
const {
466+
&[
467+
#( #all_constants ),*
468+
]
469+
}
470+
}
471+
}
472+
}
473+
436474
/// Creates implementations for bitwise operators for the given enum.
437475
///
438476
/// Currently, this is just [`BitOr`](std::ops::BitOr) for bitfields but that could be expanded in the future.

godot-core/src/builtin/vectors/vector_axis.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ macro_rules! impl_vector_axis_enum {
6969
EnumConstant::new(
7070
stringify!($axis),
7171
concat!("AXIS_", stringify!($axis)),
72-
$AxisEnum::$axis as i32,
7372
$AxisEnum::$axis
7473
),
7574
)+

godot-core/src/meta/inspect.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,32 @@
77

88
//! Introspection metadata for Godot engine types.
99
10-
/// Metadata for a single enum constant.
10+
/// Metadata for a single enum or bitfield constant.
11+
///
12+
/// Returned by [`EngineEnum::all_constants()`][crate::obj::EngineEnum::all_constants] and
13+
/// [`EngineBitfield::all_constants()`][crate::obj::EngineBitfield::all_constants].
1114
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1215
pub struct EnumConstant<T: Copy + 'static> {
1316
rust_name: &'static str,
1417
godot_name: &'static str,
15-
ord: i32,
1618
value: T,
1719
}
1820

1921
impl<T: Copy + 'static> EnumConstant<T> {
2022
/// Creates a new enum constant metadata entry.
21-
pub(crate) const fn new(
22-
rust_name: &'static str,
23-
godot_name: &'static str,
24-
ord: i32,
25-
value: T,
26-
) -> Self {
23+
pub(crate) const fn new(rust_name: &'static str, godot_name: &'static str, value: T) -> Self {
2724
Self {
2825
rust_name,
2926
godot_name,
30-
ord,
3127
value,
3228
}
3329
}
3430

35-
/// Rust name of the enum variant, usually without Prefix (e.g. `"ESCAPE"` for `Key::ESCAPE`).
31+
/// Rust name of the constant, usually without prefix (e.g. `"ESCAPE"` for `Key::ESCAPE`).
3632
///
37-
/// This is returned by [`EngineEnum::as_str()`](crate::obj::EngineEnum::as_str()).
33+
/// For enums, this is the value returned by [`EngineEnum::as_str()`](crate::obj::EngineEnum::as_str()) **if the value is unique.**
34+
/// If multiple enum values share the same ordinal, then this function will return each one separately, while `as_str()` will return the
35+
/// first one.
3836
pub const fn rust_name(&self) -> &'static str {
3937
self.rust_name
4038
}
@@ -44,12 +42,9 @@ impl<T: Copy + 'static> EnumConstant<T> {
4442
self.godot_name
4543
}
4644

47-
/// Ordinal value of this enum variant.
48-
pub const fn ord(&self) -> i32 {
49-
self.ord
50-
}
51-
52-
/// The enum value itself.
45+
/// The Rust value itself.
46+
///
47+
/// Use `value().ord()` to get the ordinal value.
5348
pub const fn value(&self) -> T {
5449
self.value
5550
}

godot-core/src/obj/traits.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,10 @@ pub trait EngineEnum: Copy {
200200

201201
/// Returns a slice of distinct enum values.
202202
///
203-
/// This excludes MAX constants and deduplicates aliases, providing only meaningful enum values.
203+
/// This excludes `MAX` constants at the end (existing only to express the number of enumerators) and deduplicates aliases,
204+
/// providing only meaningful enum values. See [`all_constants()`][Self::all_constants] for a complete list of all constants,
204205
///
205-
/// This enables iteration over distinct enum variants:
206+
/// Enables iteration over distinct enum variants:
206207
/// ```no_run
207208
/// use godot::classes::window;
208209
/// use godot::obj::EngineEnum;
@@ -215,18 +216,19 @@ pub trait EngineEnum: Copy {
215216

216217
/// Returns metadata for all enum constants.
217218
///
218-
/// This includes all constants as they appear in the enum definition, including duplicates and MAX constants.
219+
/// This includes all constants as they appear in the enum definition, including duplicates and `MAX` constants.
220+
/// For a list of useful, distinct values, use [`values()`][Self::values].
219221
///
220-
/// This enables complete introspection and debugging:
222+
/// This enables introspection of available constants:
221223
/// ```no_run
222224
/// use godot::classes::window;
223225
/// use godot::obj::EngineEnum;
224226
///
225227
/// for constant in window::Mode::all_constants() {
226-
/// println!("* {}: {} (ord: {})",
228+
/// println!("* window::Mode.{} (original {}) has ordinal value {}.",
227229
/// constant.rust_name(),
228230
/// constant.godot_name(),
229-
/// constant.ord()
231+
/// constant.value().ord()
230232
/// );
231233
/// }
232234
/// ```
@@ -249,6 +251,25 @@ pub trait EngineBitfield: Copy {
249251
fn is_set(self, flag: Self) -> bool {
250252
self.ord() & flag.ord() != 0
251253
}
254+
255+
/// Returns metadata for all bitfield constants.
256+
///
257+
/// This includes all constants as they appear in the bitfield definition.
258+
///
259+
/// Enables introspection of available constants:
260+
/// ```no_run
261+
/// use godot::global::KeyModifierMask;
262+
/// use godot::obj::EngineBitfield;
263+
///
264+
/// for constant in KeyModifierMask::all_constants() {
265+
/// println!("* KeyModifierMask.{} (original {}) has ordinal value {}.",
266+
/// constant.rust_name(),
267+
/// constant.godot_name(),
268+
/// constant.value().ord()
269+
/// );
270+
/// }
271+
/// ```
272+
fn all_constants() -> &'static [EnumConstant<Self>];
252273
}
253274

254275
/// Trait for enums that can be used as indices in arrays.

itest/rust/src/engine_tests/engine_enum_test.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ fn enum_values_duplicates() {
9797
}
9898

9999
assert_eq!(c.value(), value);
100-
assert_eq!(c.ord(), ord);
100+
assert_eq!(c.value().ord(), ord);
101101
}
102102

103103
assert_eq!(InlineAlignment::values(), &expected_distinct_values);
@@ -156,26 +156,38 @@ fn enum_all_constants() {
156156
let first = constants[0];
157157
assert_eq!(first.rust_name(), "TOP_TO");
158158
assert_eq!(first.godot_name(), "INLINE_ALIGNMENT_TOP_TO");
159-
assert_eq!(first.ord(), 0);
160159
assert_eq!(first.value(), InlineAlignment::TOP_TO);
160+
assert_eq!(first.value().ord(), 0);
161161

162162
// Check specific constants at known indices, with equal ordinals.
163163
let known_a = constants[2];
164164
let known_b = constants[11];
165165

166-
assert_eq!(known_a.ord(), 3);
167166
assert_eq!(known_a.rust_name(), "BASELINE_TO");
168167
assert_eq!(known_a.godot_name(), "INLINE_ALIGNMENT_BASELINE_TO");
169168
assert_eq!(known_a.value(), InlineAlignment::BASELINE_TO);
169+
assert_eq!(known_a.value().ord(), 3);
170170

171-
assert_eq!(known_b.ord(), 3);
172171
assert_eq!(known_b.rust_name(), "IMAGE_MASK");
173172
assert_eq!(known_b.godot_name(), "INLINE_ALIGNMENT_IMAGE_MASK");
174173
assert_eq!(known_b.value(), InlineAlignment::IMAGE_MASK);
174+
assert_eq!(known_b.value().ord(), 3);
175175

176176
// "Front-end" values are equal, too.
177177
assert_eq!(
178178
InlineAlignment::IMAGE_MASK.ord(),
179179
InlineAlignment::BASELINE_TO.ord()
180180
);
181181
}
182+
183+
#[itest]
184+
fn bitfield_all_constants() {
185+
let shift_constant = KeyModifierMask::all_constants()
186+
.iter()
187+
.find(|c| c.rust_name() == "SHIFT")
188+
.expect("SHIFT constant should exist");
189+
190+
assert_eq!(shift_constant.godot_name(), "KEY_MASK_SHIFT");
191+
assert_eq!(shift_constant.value(), KeyModifierMask::SHIFT);
192+
assert_eq!(shift_constant.value().ord(), 1 << 25);
193+
}

0 commit comments

Comments
 (0)