Closed OffsetMOSFET closed 2 months ago
I don't think there is a bug in GDScript. Godot properties in C++ are just setter and getter. Arrays (including Packed*Array
s) are passed by reference. Unlike objects, they do not have signals to track external changes.
The built-in classes you listed do not return a direct reference to the data array (they use other structures under the hood). When the getter is called, a new PackedByteArray
is created and data from this structure is written to it, and when the setter is called, the array is validated and written to the structure.
Here is an example in GDScript:
var data: PackedByteArray:
set(value):
_data = value.duplicate()
get:
return _data.duplicate()
var _data: PackedByteArray
Accordingly, you call resize()
not on the internal data structure, but only on the temporary array returned by the getter.
I agree that the current API misleading and probably this should not be exposed as data
property, but should be two separate methods set_data()
and get_data()
. However, we can't remove the property due to compatibility. We should add a note to the documentation for such properties.
This is documented for Gradient
similar can be applied elsewhere
<member .* type="(Packed.*Array|Array|Dictionary|.*\[\])"
Should probably be documented on each of the packed types as well
Thank you for the clear explanation.
Seeing that the API for stable has been updated to note that the arrays are copies, I will close this.
However, this note is missing for arrays and dictionaries. Also, there are some exceptions where built-in pass-by-reference properties takes modification into account, but this is difficult to detect automatically. CC @AThousandShips
Arrays and dictionaries are a case by case thing as some are passed directly and some are copied, so some manual thing would need to be added
Godot version
4.1.stable
System information
Godot v4.1.stable - Windows 10.0.19044 - Vulkan (Forward+) - dedicated Quadro P2200 () - Intel(R) Xeon(R) Gold 5222 CPU @ 3.80GHz (8 Threads)
Issue description
For Godot (not custom) Resources, a property that is a PackedArray cannot be resized directly. Copying, resizing, then setting the copy currently works as a work-around.
This behavior is different from custom Resource classes that are built in GDScript instead of C++. These allow resizing of PackedArray properties directly.
Steps to reproduce
Put the attached bug_script.gd code a Control node of a new scene, copy the custom class script gd_custom_class.gd as its own file, then run the scene. The output will mark the point of discrepency.
Output:
Minimal reproduction project
bug_script.gd
gd_custom_class.gd