diff --git a/godot-core/src/builtin/collections/array.rs b/godot-core/src/builtin/collections/array.rs index cc561520a..b39fd4776 100644 --- a/godot-core/src/builtin/collections/array.rs +++ b/godot-core/src/builtin/collections/array.rs @@ -895,9 +895,22 @@ impl Var for Array { fn get_property(&self) -> Self::Via { self.to_godot() } + fn set_property(&mut self, value: Self::Via) { *self = FromGodot::from_godot(value) } + + fn property_hint() -> PropertyHintInfo { + // For array #[var], the hint string is "PackedInt32Array", "Node" etc. for typed arrays, and "" for untyped arrays. + if Self::has_variant_t() { + PropertyHintInfo::none() + } else if sys::GdextBuild::since_api("4.2") { + PropertyHintInfo::var_array_element::() + } else { + // Godot 4.1 was missing PropertyHint::ARRAY_TYPE, so we use the type name instead. + PropertyHintInfo::none() + } + } } impl Export for Array { @@ -906,7 +919,7 @@ impl Export for Array { if Self::has_variant_t() { PropertyHintInfo::with_type_name::() } else { - PropertyHintInfo::with_array_element::() + PropertyHintInfo::export_array_element::() } } } diff --git a/godot-core/src/builtin/collections/dictionary.rs b/godot-core/src/builtin/collections/dictionary.rs index 1b0eadbd0..3d682949a 100644 --- a/godot-core/src/builtin/collections/dictionary.rs +++ b/godot-core/src/builtin/collections/dictionary.rs @@ -9,7 +9,6 @@ use godot_ffi as sys; use crate::builtin::{inner, Variant, VariantArray}; use crate::meta::{FromGodot, ToGodot}; -use crate::registry::property::{Export, PropertyHintInfo, Var}; use sys::types::OpaqueDictionary; use sys::{ffi_methods, interface_fn, GodotFfi}; @@ -400,22 +399,6 @@ impl Clone for Dictionary { } } -impl Var for Dictionary { - fn get_property(&self) -> Self::Via { - self.to_godot() - } - - fn set_property(&mut self, value: Self::Via) { - *self = FromGodot::from_godot(value) - } -} - -impl Export for Dictionary { - fn default_export_info() -> PropertyHintInfo { - PropertyHintInfo::with_hint_none("Dictionary") - } -} - // ---------------------------------------------------------------------------------------------------------------------------------------------- // Conversion traits diff --git a/godot-core/src/builtin/collections/packed_array.rs b/godot-core/src/builtin/collections/packed_array.rs index dfcfae207..8e0c5d5e7 100644 --- a/godot-core/src/builtin/collections/packed_array.rs +++ b/godot-core/src/builtin/collections/packed_array.rs @@ -548,7 +548,7 @@ macro_rules! impl_packed_array { fn default_export_info() -> $crate::registry::property::PropertyHintInfo { // In 4.3 Godot can (and does) use type hint strings for packed arrays, see https://github.com/godotengine/godot/pull/82952. if sys::GdextBuild::since_api("4.3") { - $crate::registry::property::PropertyHintInfo::with_array_element::<$Element>() + $crate::registry::property::PropertyHintInfo::export_array_element::<$Element>() } else { $crate::registry::property::PropertyHintInfo::with_type_name::<$PackedArray>() } diff --git a/godot-core/src/meta/traits.rs b/godot-core/src/meta/traits.rs index e69f59dba..1603981b4 100644 --- a/godot-core/src/meta/traits.rs +++ b/godot-core/src/meta/traits.rs @@ -81,6 +81,9 @@ pub trait GodotType: #[doc(hidden)] fn property_hint_info() -> PropertyHintInfo { + // The default implementation is mostly good for builtin types. + //PropertyHintInfo::with_type_name::() + PropertyHintInfo::none() } diff --git a/godot-core/src/registry/property.rs b/godot-core/src/registry/property.rs index 837920330..65c156b34 100644 --- a/godot-core/src/registry/property.rs +++ b/godot-core/src/registry/property.rs @@ -37,6 +37,15 @@ pub trait Var: GodotConvert { /// Specific property hints, only override if they deviate from [`GodotType::property_info`], e.g. for enums/newtypes. fn property_hint() -> PropertyHintInfo { + // From Godot 4.3 onward, properties are typically exported with "" hint_string. This needs to be manually overridden for types + // that need a hint string, like arrays. See also https://github.com/godotengine/godot/pull/82952 and property_template_test.rs. + // if sys::GdextBuild::since_api("4.3") { + // PropertyHintInfo::with_type_name::() + // } else { + // Self::Via::property_hint_info() + // } + + //PropertyHintInfo::with_hint_none("") Self::Via::property_hint_info() } } @@ -50,7 +59,9 @@ pub trait Var: GodotConvert { )] pub trait Export: Var { /// The export info to use for an exported field of this type, if no other export info is specified. - fn default_export_info() -> PropertyHintInfo; + fn default_export_info() -> PropertyHintInfo { + ::property_hint() + } } // ---------------------------------------------------------------------------------------------------------------------------------------------- @@ -125,13 +136,19 @@ impl PropertyHintInfo { } } - pub fn with_array_element() -> Self { + pub fn var_array_element() -> Self { + Self { + hint: PropertyHint::ARRAY_TYPE, + hint_string: GString::from(T::godot_type_name()), + } + } + + pub fn export_array_element() -> Self { Self { hint: PropertyHint::TYPE_STRING, hint_string: GString::from(T::element_type_string()), } } - pub fn with_type_name() -> Self { Self::with_hint_none(T::godot_type_name()) } @@ -457,8 +474,10 @@ mod export_impls { impl_property_by_godot_convert!(Color); - // Arrays - // We manually implement `Export`. + // Dictionary: will need to be done manually once they become typed. + impl_property_by_godot_convert!(Dictionary); + + // Packed arrays: we manually implement `Export`. impl_property_by_godot_convert!(PackedByteArray, no_export); impl_property_by_godot_convert!(PackedInt32Array, no_export); impl_property_by_godot_convert!(PackedInt64Array, no_export); diff --git a/godot-macros/src/derive/derive_export.rs b/godot-macros/src/derive/derive_export.rs index 8720f6b9f..d671a44a5 100644 --- a/godot-macros/src/derive/derive_export.rs +++ b/godot-macros/src/derive/derive_export.rs @@ -19,10 +19,6 @@ pub fn derive_export(item: venial::Item) -> ParseResult { let GodotConvert { ty_name: name, .. } = GodotConvert::parse_declaration(item)?; Ok(quote! { - impl ::godot::register::property::Export for #name { - fn default_export_info() -> ::godot::register::property::PropertyHintInfo { - <#name as ::godot::register::property::Var>::property_hint() - } - } + impl ::godot::register::property::Export for #name {} }) } diff --git a/godot-macros/src/derive/derive_var.rs b/godot-macros/src/derive/derive_var.rs index 7f684c399..78ec612d8 100644 --- a/godot-macros/src/derive/derive_var.rs +++ b/godot-macros/src/derive/derive_var.rs @@ -34,7 +34,6 @@ pub fn derive_var(item: venial::Item) -> ParseResult { fn property_hint() -> ::godot::register::property::PropertyHintInfo { #property_hint_impl } - } }) } diff --git a/itest/rust/src/object_tests/property_template_test.rs b/itest/rust/src/object_tests/property_template_test.rs index ed78f422d..2c78f2084 100644 --- a/itest/rust/src/object_tests/property_template_test.rs +++ b/itest/rust/src/object_tests/property_template_test.rs @@ -73,7 +73,7 @@ fn property_template_test(ctx: &TestContext) { if rust_prop != property { errors.push(format!( - "mismatch in property {name}, GDScript: {property:?}, Rust: {rust_prop:?}" + "mismatch in property {name}:\n GDScript: {property:?}\n Rust: {rust_prop:?}" )); } }