Skip to content

Commit 9999333

Browse files
committed
Add VariantType support for exported fields.
Also some PR comment fixes from this and the previous commit.
1 parent 671e0ac commit 9999333

File tree

3 files changed

+101
-41
lines changed

3 files changed

+101
-41
lines changed

godot-macros/src/derive_godot_class.rs

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -228,46 +228,45 @@ struct ExportedField {
228228
field: Field,
229229
getter: String,
230230
setter: String,
231+
variant_type: String,
231232
}
232233

233234
impl ExportedField {
234235
pub fn new_from_kv(
235236
field: Field,
236237
attr: &Attribute,
237238
mut map: KvMap,
238-
) -> Result<ExportedField, venial::Error> {
239-
let export_getter: String;
240-
let export_setter: String;
241-
if let Some(getter) = map.remove("getter") {
242-
if let KvValue::Lit(getter) = getter {
243-
export_getter = getter;
244-
} else {
245-
return Err(bail_error(
246-
"#[property] attribute with a non-literal getter",
247-
attr,
248-
));
249-
}
250-
} else {
251-
return Err(bail_error("#[property] attribute without a getter", attr));
252-
}
253-
if let Some(setter) = map.remove("setter") {
254-
if let KvValue::Lit(setter) = setter {
255-
export_setter = setter;
239+
) -> ParseResult<ExportedField> {
240+
let getter = Self::require_key_value(&mut map, "getter", attr)?;
241+
let setter = Self::require_key_value(&mut map, "setter", attr)?;
242+
let variant_type = Self::require_key_value(&mut map, "variant_type", attr)?;
243+
244+
ensure_kv_empty(map, attr.__span())?;
245+
246+
return Ok(ExportedField {
247+
field,
248+
getter,
249+
setter,
250+
variant_type,
251+
});
252+
}
253+
254+
fn require_key_value(map: &mut KvMap, key: &str, attr: &Attribute) -> ParseResult<String> {
255+
if let Some(value) = map.remove(key) {
256+
if let KvValue::Lit(value) = value {
257+
return Ok(value);
256258
} else {
257-
return Err(bail_error(
258-
"#[property] attribute with a non-literal setter",
259+
return bail(
260+
format!(
261+
"#[export] attribute {} with a non-literal variant_type",
262+
key
263+
),
259264
attr,
260-
));
265+
)?;
261266
}
262267
} else {
263-
return Err(bail_error("#[property] attribute without a setter", attr));
268+
return bail(format!("#[export] attribute without a {}", key), attr);
264269
}
265-
ensure_kv_empty(map, attr.__span())?;
266-
return Ok(ExportedField {
267-
field,
268-
getter: export_getter,
269-
setter: export_setter,
270-
});
271270
}
272271
}
273272

@@ -326,10 +325,12 @@ fn make_exports_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
326325
let name = exported_field.field.name.to_string();
327326
let getter = proc_macro2::Literal::from_str(&exported_field.getter).unwrap();
328327
let setter = proc_macro2::Literal::from_str(&exported_field.setter).unwrap();
328+
let vtype = &exported_field.variant_type;
329+
let variant_type: TokenStream = vtype[1..vtype.len() - 1].parse().unwrap();
329330
quote! {
330331
let class_name = ::godot::builtin::StringName::from(#class_name::CLASS_NAME);
331332
let property_info = ::godot::builtin::meta::PropertyInfo::new(
332-
::godot::sys::VariantType::Int,
333+
#variant_type,
333334
::godot::builtin::meta::ClassName::new::<#class_name>(),
334335
::godot::builtin::StringName::from(#name),
335336
);

itest/godot/ManualFfiTests.gd

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ func run() -> bool:
99
var ok = true
1010
#ok = ok && test_missing_init()
1111
ok = ok && test_to_string()
12+
ok = ok && test_export()
1213

1314
print("[GD] ManualFfi tested (passed=", ok, ")")
1415
return ok
@@ -28,6 +29,20 @@ func test_to_string() -> bool:
2829

2930
func test_export() -> bool:
3031
var obj = HasProperty.new()
31-
obj.val = 5
32-
print("[GD] HasProperty's property is: ", obj.val, " and should be 5")
33-
return obj.val == 5
32+
33+
obj.int_val = 5
34+
print("[GD] HasProperty's int_val property is: ", obj.int_val, " and should be 5")
35+
var int_val_correct = obj.int_val == 5
36+
37+
obj.string_val = "test val"
38+
print("[GD] HasProperty's string_val property is: ", obj.string_val, " and should be \"test val\"")
39+
var string_val_correct = obj.string_val == "test val"
40+
41+
var node = Node.new()
42+
obj.object_val = node
43+
print("[GD] HasProperty's object_val property is: ", obj.object_val, " and should be ", node)
44+
var object_val_correct = obj.object_val == node
45+
46+
obj.free()
47+
48+
return int_val_correct && string_val_correct && object_val_correct

itest/rust/src/export_test.rs

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
55
*/
66

7-
use crate::itest;
87
use godot::prelude::*;
98

109
pub(crate) fn run() -> bool {
11-
let mut ok = true;
10+
let ok = true;
1211
// No tests currently, tests using HasProperty are in Godot scripts.
1312

1413
ok
@@ -17,28 +16,73 @@ pub(crate) fn run() -> bool {
1716
#[derive(GodotClass)]
1817
#[class(base=Node)]
1918
struct HasProperty {
20-
#[export(getter = "get_val", setter = "set_val")]
21-
val: i32,
2219
#[base]
2320
base: Base<Node>,
21+
#[export(
22+
getter = "get_int_val",
23+
setter = "set_int_val",
24+
variant_type = "::godot::sys::VariantType::Int"
25+
)]
26+
int_val: i32,
27+
#[export(
28+
getter = "get_string_val",
29+
setter = "set_string_val",
30+
variant_type = "::godot::sys::VariantType::String"
31+
)]
32+
string_val: GodotString,
33+
#[export(
34+
getter = "get_object_val",
35+
setter = "set_object_val",
36+
variant_type = "::godot::sys::VariantType::Object"
37+
)]
38+
object_val: Option<Gd<Object>>,
2439
}
2540

2641
#[godot_api]
2742
impl HasProperty {
2843
#[func]
29-
pub fn get_val(&self) -> i32 {
30-
return self.val;
44+
pub fn get_int_val(&self) -> i32 {
45+
return self.int_val;
3146
}
3247

3348
#[func]
34-
pub fn set_val(&mut self, val: i32) {
35-
self.val = val;
49+
pub fn set_int_val(&mut self, val: i32) {
50+
self.int_val = val;
51+
}
52+
53+
#[func]
54+
pub fn get_string_val(&self) -> GodotString {
55+
return self.string_val.clone();
56+
}
57+
58+
#[func]
59+
pub fn set_string_val(&mut self, val: GodotString) {
60+
self.string_val = val;
61+
}
62+
63+
#[func]
64+
pub fn get_object_val(&self) -> Variant {
65+
if let Some(object_val) = self.object_val.as_ref() {
66+
return object_val.to_variant();
67+
} else {
68+
return Variant::nil();
69+
}
70+
}
71+
72+
#[func]
73+
pub fn set_object_val(&mut self, val: Gd<Object>) {
74+
self.object_val = Some(val);
3675
}
3776
}
3877

3978
#[godot_api]
4079
impl GodotExt for HasProperty {
4180
fn init(base: Base<Node>) -> Self {
42-
HasProperty { val: 0, base }
81+
HasProperty {
82+
int_val: 0,
83+
object_val: None,
84+
string_val: GodotString::new(),
85+
base,
86+
}
4387
}
4488
}

0 commit comments

Comments
 (0)