Skip to content

Commit a2f793d

Browse files
committed
Clarify + test Packed*Array behavior w.r.t. copy-and-write + #[var]
1 parent 1606a7f commit a2f793d

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

godot-core/src/builtin/collections/packed_array.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ macro_rules! impl_packed_array {
6868
///
6969
/// # Registering properties
7070
///
71-
/// You can use both `#[var]` and `#[export]` with packed arrays. However, since they use copy-on-write, GDScript (for `#[var]`) and the
72-
/// editor (for `#[export]`) will effectively keep an independent copy of the array. Writes to the packed array from Rust are thus not
73-
/// reflected on the other side -- you may need to replace the entire array.
71+
/// You can use both `#[var]` and `#[export]` with packed arrays. In godot-rust, modifications to packed array properties are
72+
/// properly synchronized between Rust and GDScript/reflection access.
7473
///
75-
/// See also [godot/#76150](https://github.com/godotengine/godot/issues/76150) for details.
74+
/// In GDScript, mutating methods like `append_array()` may not work on `Packed*Array` properties of engine classes.
75+
/// See [godot/#76150](https://github.com/godotengine/godot/issues/76150) for details.
7676
///
7777
/// # Thread safety
7878
///

itest/rust/src/object_tests/property_test.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
66
*/
77

8-
use godot::builtin::{vdict, vslice, Color, Dictionary, GString, Variant, VariantType};
8+
use godot::builtin::{
9+
vdict, vslice, Color, Dictionary, GString, PackedInt32Array, Variant, VariantType,
10+
};
911
use godot::classes::{INode, IRefCounted, Node, Object, RefCounted, Resource, Texture};
1012
use godot::global::{PropertyHint, PropertyUsageFlags};
1113
use godot::meta::{GodotConvert, PropertyHintInfo, ToGodot};
@@ -48,6 +50,9 @@ struct HasProperty {
4850

4951
#[var(get = get_texture_val, set = set_texture_val, hint = RESOURCE_TYPE, hint_string = "Texture")]
5052
texture_val_rw: Option<Gd<Texture>>,
53+
54+
#[var]
55+
packed_int_array: PackedInt32Array,
5156
}
5257

5358
#[godot_api]
@@ -141,6 +146,7 @@ impl INode for HasProperty {
141146
string_val: GString::new(),
142147
texture_val: OnEditor::default(),
143148
texture_val_rw: None,
149+
packed_int_array: PackedInt32Array::new(),
144150
}
145151
}
146152
}
@@ -628,6 +634,33 @@ fn test_var_with_renamed_funcs() {
628634
obj.free();
629635
}
630636

637+
// Tests that CoW packed-arrays' changes are reflected from Rust. See:
638+
// * Rust (sync does work): https://github.com/godot-rust/gdext/pull/576
639+
// * GDScript (not synced): https://github.com/godotengine/godot/issues/76150
640+
#[itest]
641+
fn test_copy_on_write_var() {
642+
let mut obj = HasProperty::new_alloc();
643+
644+
// Mutate property via reflection -> verify change is reflected in Rust.
645+
obj.set(
646+
"packed_int_array",
647+
&PackedInt32Array::from([1, 2, 3]).to_variant(),
648+
);
649+
assert_eq!(
650+
obj.bind().packed_int_array,
651+
PackedInt32Array::from(&[1, 2, 3])
652+
);
653+
654+
// Mutate property in Rust -> verify change is reflected in Godot.
655+
obj.bind_mut().packed_int_array.push(4);
656+
assert_eq!(
657+
obj.get("packed_int_array").to::<PackedInt32Array>(),
658+
PackedInt32Array::from(&[1, 2, 3, 4])
659+
);
660+
661+
obj.free();
662+
}
663+
631664
// ----------------------------------------------------------------------------------------------------------------------------------------------
632665

633666
#[derive(GodotClass)]

0 commit comments

Comments
 (0)