Skip to content

Commit de73f39

Browse files
authored
Merge pull request #441 from HenryWConklin/master
Use the class_name for the field when building PropertyInfo
2 parents 88a7934 + f7217c2 commit de73f39

File tree

6 files changed

+123
-31
lines changed

6 files changed

+123
-31
lines changed

godot-core/src/builtin/macros.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ macro_rules! impl_builtin_traits_inner {
6868
impl Eq for $Type {}
6969
};
7070

71-
( PartialOrd for $Type:ty => $gd_method:ident ) => {
72-
impl PartialOrd for $Type {
71+
( Ord for $Type:ty => $gd_method:ident ) => {
72+
impl Ord for $Type {
7373
#[inline]
74-
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
74+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
7575
let op_less = |lhs, rhs| unsafe {
7676
let mut result = false;
7777
::godot_ffi::builtin_call! {
@@ -81,22 +81,18 @@ macro_rules! impl_builtin_traits_inner {
8181
};
8282

8383
if op_less(self.sys(), other.sys()) {
84-
Some(std::cmp::Ordering::Less)
84+
std::cmp::Ordering::Less
8585
} else if op_less(other.sys(), self.sys()) {
86-
Some(std::cmp::Ordering::Greater)
86+
std::cmp::Ordering::Greater
8787
} else {
88-
Some(std::cmp::Ordering::Equal)
88+
std::cmp::Ordering::Equal
8989
}
9090
}
9191
}
92-
};
93-
94-
( Ord for $Type:ty => $gd_method:ident ) => {
95-
impl_builtin_traits_inner!(PartialOrd for $Type => $gd_method);
96-
impl Ord for $Type {
92+
impl PartialOrd for $Type {
9793
#[inline]
98-
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
99-
PartialOrd::partial_cmp(self, other).expect("PartialOrd::partial_cmp")
94+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
95+
Some(self.cmp(other))
10096
}
10197
}
10298
};

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ pub fn make_property_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
6767
continue;
6868
};
6969

70+
let field_variant_type = util::property_variant_type(field_type);
71+
let field_class_name = util::property_variant_class_name(field_type);
7072
let field_name = field_ident.to_string();
7173

7274
// rustfmt wont format this if we put it in the let-else.
@@ -178,8 +180,8 @@ pub fn make_property_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
178180
let usage = #usage_flags;
179181

180182
let property_info = ::godot::builtin::meta::PropertyInfo {
181-
variant_type: <<#field_type as ::godot::bind::property::Property>::Intermediate as ::godot::builtin::meta::VariantMetadata>::variant_type(),
182-
class_name: #class_name_obj,
183+
variant_type: #field_variant_type,
184+
class_name: #field_class_name,
183185
property_name: #field_name.into(),
184186
hint,
185187
hint_string,
@@ -194,7 +196,7 @@ pub fn make_property_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
194196
unsafe {
195197
::godot::sys::interface_fn!(classdb_register_extension_class_property)(
196198
::godot::sys::get_library(),
197-
#class_name::class_name().string_sys(),
199+
#class_name_obj.string_sys(),
198200
std::ptr::addr_of!(property_info_sys),
199201
setter_name.string_sys(),
200202
getter_name.string_sys(),

godot-macros/src/util/list_parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ impl ListParser {
167167

168168
/// Take the next element of the list, if it is a key-value pair of the form `key = expression`.
169169
pub(crate) fn try_next_key_value(&mut self) -> Option<(Ident, KvValue)> {
170-
let Some(kv) = self.peek() else { return None };
170+
let kv = self.peek()?;
171171

172172
if let Ok((key, value)) = kv.as_key_value() {
173173
_ = self.pop_next();

godot-macros/src/util/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ pub fn class_name_obj(class: &impl ToTokens) -> TokenStream {
3232
quote! { <#class as ::godot::obj::GodotClass>::class_name() }
3333
}
3434

35+
pub fn property_variant_type(property_type: &impl ToTokens) -> TokenStream {
36+
let property_type = property_type.to_token_stream();
37+
quote! {<<#property_type as ::godot::bind::property::Property>::Intermediate as ::godot::builtin::meta::VariantMetadata>::variant_type()}
38+
}
39+
40+
pub fn property_variant_class_name(property_type: &impl ToTokens) -> TokenStream {
41+
let property_type = property_type.to_token_stream();
42+
quote! {<<#property_type as ::godot::bind::property::Property>::Intermediate as ::godot::builtin::meta::VariantMetadata>::class_name()}
43+
}
44+
3545
pub fn bail_fn<R, T>(msg: impl AsRef<str>, tokens: T) -> ParseResult<R>
3646
where
3747
T: Spanned,

itest/rust/src/framework/runner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ fn get_execution_time(test: &Variant) -> Option<Duration> {
364364
fn get_errors(test: &Variant) -> Array<GodotString> {
365365
test.call("get", &["errors".to_variant()])
366366
.try_to::<Array<GodotString>>()
367-
.unwrap_or(Array::new())
367+
.unwrap_or_default()
368368
}
369369

370370
#[must_use]

itest/rust/src/object_tests/property_test.rs

Lines changed: 97 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66

77
use godot::{
88
bind::property::ExportInfo,
9-
engine::{global::PropertyHint, Texture},
9+
engine::{
10+
global::{PropertyHint, PropertyUsageFlags},
11+
Texture,
12+
},
1013
prelude::*,
1114
test::itest,
1215
};
@@ -351,20 +354,101 @@ fn derive_export() {
351354
.iter_shared()
352355
.find(|c| c.get_or_nil("name") == "foo".to_variant())
353356
.unwrap();
354-
assert_eq!(
355-
property.get_or_nil("class_name"),
356-
"DeriveExport".to_variant()
357+
// `class_name` should be empty for non-Object variants.
358+
check_property(&property, "class_name", "");
359+
check_property(&property, "type", VariantType::Int as i32);
360+
check_property(&property, "hint", PropertyHint::PROPERTY_HINT_ENUM.ord());
361+
check_property(&property, "hint_string", "A:0,B:1,C:2");
362+
check_property(
363+
&property,
364+
"usage",
365+
PropertyUsageFlags::PROPERTY_USAGE_DEFAULT.ord(),
357366
);
358-
assert_eq!(
359-
property.get_or_nil("type"),
360-
(VariantType::Int as i32).to_variant()
367+
}
368+
369+
#[derive(GodotClass)]
370+
#[class(init, base=Resource)]
371+
pub struct CustomResource {}
372+
373+
#[godot_api]
374+
impl CustomResource {}
375+
376+
#[godot_api]
377+
impl ResourceVirtual for CustomResource {}
378+
379+
#[derive(GodotClass)]
380+
#[class(init, base=Resource, rename=NewNameCustomResource)]
381+
pub struct RenamedCustomResource {}
382+
383+
#[godot_api]
384+
impl RenamedCustomResource {}
385+
386+
#[godot_api]
387+
impl ResourceVirtual for RenamedCustomResource {}
388+
389+
#[derive(GodotClass)]
390+
#[class(init, base=Node)]
391+
pub struct ExportResource {
392+
#[export]
393+
#[var(usage_flags=[PROPERTY_USAGE_DEFAULT, PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT])]
394+
pub foo: Option<Gd<CustomResource>>,
395+
396+
#[export]
397+
pub bar: Option<Gd<RenamedCustomResource>>,
398+
}
399+
400+
#[godot_api]
401+
impl ExportResource {}
402+
403+
#[godot_api]
404+
impl NodeVirtual for ExportResource {}
405+
406+
#[itest]
407+
fn export_resource() {
408+
let class: Gd<ExportResource> = Gd::new_default();
409+
410+
let property = class
411+
.get_property_list()
412+
.iter_shared()
413+
.find(|c| c.get_or_nil("name") == "foo".to_variant())
414+
.unwrap();
415+
check_property(&property, "class_name", "CustomResource");
416+
check_property(&property, "type", VariantType::Object as i32);
417+
check_property(
418+
&property,
419+
"hint",
420+
PropertyHint::PROPERTY_HINT_RESOURCE_TYPE.ord(),
421+
);
422+
check_property(&property, "hint_string", "CustomResource");
423+
check_property(
424+
&property,
425+
"usage",
426+
PropertyUsageFlags::PROPERTY_USAGE_DEFAULT.ord()
427+
| PropertyUsageFlags::PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT.ord(),
361428
);
362-
assert_eq!(
363-
property.get_or_nil("hint"),
364-
(PropertyHint::PROPERTY_HINT_ENUM.ord()).to_variant()
429+
430+
let property = class
431+
.get_property_list()
432+
.iter_shared()
433+
.find(|c| c.get_or_nil("name") == "bar".to_variant())
434+
.unwrap();
435+
check_property(&property, "class_name", "NewNameCustomResource");
436+
check_property(&property, "type", VariantType::Object as i32);
437+
check_property(
438+
&property,
439+
"hint",
440+
PropertyHint::PROPERTY_HINT_RESOURCE_TYPE.ord(),
365441
);
366-
assert_eq!(
367-
property.get_or_nil("hint_string"),
368-
"A:0,B:1,C:2".to_variant()
442+
check_property(&property, "hint_string", "NewNameCustomResource");
443+
check_property(
444+
&property,
445+
"usage",
446+
PropertyUsageFlags::PROPERTY_USAGE_DEFAULT.ord(),
369447
);
448+
449+
class.free();
450+
}
451+
452+
fn check_property(property: &Dictionary, key: &str, expected: impl ToVariant) {
453+
assert_eq!(property.get_or_nil(key), expected.to_variant());
370454
}

0 commit comments

Comments
 (0)