diff --git a/doc/classes/CollisionPolygon2D.xml b/doc/classes/CollisionPolygon2D.xml
index 29535ffd648..1805683de51 100644
--- a/doc/classes/CollisionPolygon2D.xml
+++ b/doc/classes/CollisionPolygon2D.xml
@@ -26,7 +26,6 @@
The polygon's list of vertices. Each point will be connected to the next, and the final point will be connected to the first.
[b]Note:[/b] The returned vertices are in the local coordinate space of the given [CollisionPolygon2D].
- [b]Warning:[/b] The returned value is a clone of the [PackedVector2Array], not a reference.
diff --git a/doc/classes/CollisionPolygon3D.xml b/doc/classes/CollisionPolygon3D.xml
index 16090c203e8..4f5866c3484 100644
--- a/doc/classes/CollisionPolygon3D.xml
+++ b/doc/classes/CollisionPolygon3D.xml
@@ -21,7 +21,6 @@
Array of vertices which define the 2D polygon in the local XY plane.
- [b]Note:[/b] The returned value is a copy of the original. Methods which mutate the size or properties of the return value will not impact the original polygon. To change properties of the polygon, assign it to a temporary variable and make changes before reassigning the class property.
diff --git a/doc/classes/Gradient.xml b/doc/classes/Gradient.xml
index c7fa1f40e0c..c85b3acafae 100644
--- a/doc/classes/Gradient.xml
+++ b/doc/classes/Gradient.xml
@@ -78,8 +78,8 @@
- Gradient's colors returned as a [PackedColorArray].
- [b]Note:[/b] This property returns a copy, modifying the return value does not update the gradient. To update the gradient use [method set_color] method (for updating colors individually) or assign to this property directly (for bulk-updating all colors at once).
+ Gradient's colors as a [PackedColorArray].
+ [b]Note:[/b] Setting this property updates all colors at once. To update any color individually use [method set_color].
The color space used to interpolate between points of the gradient. It does not affect the returned colors, which will always be in sRGB space. See [enum ColorSpace] for available modes.
@@ -89,8 +89,8 @@
The algorithm used to interpolate between points of the gradient. See [enum InterpolationMode] for available modes.
- Gradient's offsets returned as a [PackedFloat32Array].
- [b]Note:[/b] This property returns a copy, modifying the return value does not update the gradient. To update the gradient use [method set_offset] method (for updating offsets individually) or assign to this property directly (for bulk-updating all offsets at once).
+ Gradient's offsets as a [PackedFloat32Array].
+ [b]Note:[/b] Setting this property updates all offsets at once. To update any offset individually use [method set_offset].
diff --git a/doc/classes/OccluderPolygon2D.xml b/doc/classes/OccluderPolygon2D.xml
index a78375ad01c..36e1540b392 100644
--- a/doc/classes/OccluderPolygon2D.xml
+++ b/doc/classes/OccluderPolygon2D.xml
@@ -17,7 +17,6 @@
A [Vector2] array with the index for polygon's vertices positions.
- [b]Note:[/b] The returned value is a copy of the underlying array, rather than a reference.
diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml
index 0c1532f61ae..e179c111a29 100644
--- a/doc/classes/PackedByteArray.xml
+++ b/doc/classes/PackedByteArray.xml
@@ -6,6 +6,7 @@
An array specifically designed to hold bytes. Packs data tightly, so it saves memory for large array sizes.
[PackedByteArray] also provides methods to encode/decode various types to/from bytes. The way values are encoded is an implementation detail and shouldn't be relied upon when interacting with external apps.
+ [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again.
diff --git a/doc/classes/PackedColorArray.xml b/doc/classes/PackedColorArray.xml
index c2156e511ff..57295cb1e33 100644
--- a/doc/classes/PackedColorArray.xml
+++ b/doc/classes/PackedColorArray.xml
@@ -6,6 +6,7 @@
An array specifically designed to hold [Color]. Packs data tightly, so it saves memory for large array sizes.
[b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedColorArray] versus [code]Array[Color][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays.
+ [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again.
diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml
index 6f1ecacca45..2db1386fd02 100644
--- a/doc/classes/PackedFloat32Array.xml
+++ b/doc/classes/PackedFloat32Array.xml
@@ -6,6 +6,7 @@
An array specifically designed to hold 32-bit floating-point values (float). Packs data tightly, so it saves memory for large array sizes.
If you need to pack 64-bit floats tightly, see [PackedFloat64Array].
+ [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again.
diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml
index 9b62df2adad..0bcee918eda 100644
--- a/doc/classes/PackedFloat64Array.xml
+++ b/doc/classes/PackedFloat64Array.xml
@@ -7,6 +7,7 @@
An array specifically designed to hold 64-bit floating-point values (double). Packs data tightly, so it saves memory for large array sizes.
If you only need to pack 32-bit floats tightly, see [PackedFloat32Array] for a more memory-friendly alternative.
[b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedFloat64Array] versus [code]Array[float][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays.
+ [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again.
diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml
index e6396e2a938..93b2ae7394a 100644
--- a/doc/classes/PackedInt32Array.xml
+++ b/doc/classes/PackedInt32Array.xml
@@ -6,6 +6,7 @@
An array specifically designed to hold 32-bit integer values. Packs data tightly, so it saves memory for large array sizes.
[b]Note:[/b] This type stores signed 32-bit integers, which means it can take values in the interval [code][-2^31, 2^31 - 1][/code], i.e. [code][-2147483648, 2147483647][/code]. Exceeding those bounds will wrap around. In comparison, [int] uses signed 64-bit integers which can hold much larger values. If you need to pack 64-bit integers tightly, see [PackedInt64Array].
+ [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again.
diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml
index cbbcdb12d70..3d341659156 100644
--- a/doc/classes/PackedInt64Array.xml
+++ b/doc/classes/PackedInt64Array.xml
@@ -7,6 +7,7 @@
An array specifically designed to hold 64-bit integer values. Packs data tightly, so it saves memory for large array sizes.
[b]Note:[/b] This type stores signed 64-bit integers, which means it can take values in the interval [code][-2^63, 2^63 - 1][/code], i.e. [code][-9223372036854775808, 9223372036854775807][/code]. Exceeding those bounds will wrap around. If you only need to pack 32-bit integers tightly, see [PackedInt32Array] for a more memory-friendly alternative.
[b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedInt32Array] versus [code]Array[int][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays.
+ [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again.
diff --git a/doc/classes/PackedStringArray.xml b/doc/classes/PackedStringArray.xml
index b2a9f2ca7ec..621831c7a3a 100644
--- a/doc/classes/PackedStringArray.xml
+++ b/doc/classes/PackedStringArray.xml
@@ -12,6 +12,7 @@
print(string) # "hello world"
[/codeblock]
[b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedStringArray] versus [code]Array[String][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays.
+ [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again.
https://godotengine.org/asset-library/asset/2789
diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml
index bc0f9f9ccea..14a38163534 100644
--- a/doc/classes/PackedVector2Array.xml
+++ b/doc/classes/PackedVector2Array.xml
@@ -6,6 +6,7 @@
An array specifically designed to hold [Vector2]. Packs data tightly, so it saves memory for large array sizes.
[b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedVector3Array] versus [code]Array[Vector2][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays.
+ [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again.
https://godotengine.org/asset-library/asset/2723
diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml
index e610dea0a4d..49220c6fd62 100644
--- a/doc/classes/PackedVector3Array.xml
+++ b/doc/classes/PackedVector3Array.xml
@@ -6,6 +6,7 @@
An array specifically designed to hold [Vector3]. Packs data tightly, so it saves memory for large array sizes.
[b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedVector3Array] versus [code]Array[Vector3][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays.
+ [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again.
diff --git a/doc/classes/Polygon2D.xml b/doc/classes/Polygon2D.xml
index 029a69a399d..90d3522002e 100644
--- a/doc/classes/Polygon2D.xml
+++ b/doc/classes/Polygon2D.xml
@@ -91,7 +91,6 @@
The polygon's list of vertices. The final point will be connected to the first.
- [b]Note:[/b] This returns a copy of the [PackedVector2Array] rather than a reference.
The list of polygons, in case more than one is being represented. Every individual polygon is stored as a [PackedInt32Array] where each [int] is an index to a point in [member polygon]. If empty, this property will be ignored, and the resulting single polygon will be composed of all points in [member polygon], using the order they are stored in.
diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py
index 0d2bc87f55e..d7230db6a68 100755
--- a/doc/tools/make_rst.py
+++ b/doc/tools/make_rst.py
@@ -87,6 +87,7 @@ BASE_STRINGS = [
"This method may be changed or removed in future versions.",
"This operator may be changed or removed in future versions.",
"This theme property may be changed or removed in future versions.",
+ "[b]Note:[/b] The returned array is [i]copied[/i] and any changes to it will not update the original property value. See [%s] for more details.",
]
strings_l10n: Dict[str, str] = {}
@@ -145,6 +146,18 @@ CLASSES_WITH_CSHARP_DIFFERENCES: List[str] = [
"Variant",
]
+PACKED_ARRAY_TYPES: List[str] = [
+ "PackedByteArray",
+ "PackedColorArray",
+ "PackedFloat32Array",
+ "Packedfloat64Array",
+ "PackedInt32Array",
+ "PackedInt64Array",
+ "PackedStringArray",
+ "PackedVector2Array",
+ "PackedVector3Array",
+]
+
class State:
def __init__(self) -> None:
@@ -1277,6 +1290,9 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if property_def.text is not None and property_def.text.strip() != "":
f.write(f"{format_text_block(property_def.text.strip(), property_def, state)}\n\n")
+ if property_def.type_name.type_name in PACKED_ARRAY_TYPES:
+ tmp = f"[b]Note:[/b] The returned array is [i]copied[/i] and any changes to it will not update the original property value. See [{property_def.type_name.type_name}] for more details."
+ f.write(f"{format_text_block(tmp, property_def, state)}\n\n")
elif property_def.deprecated is None and property_def.experimental is None:
f.write(".. container:: contribute\n\n\t")
f.write(
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index bba1939f72b..cd498ce0895 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -96,6 +96,18 @@ const Vector classes_with_csharp_differences = {
};
#endif
+const Vector packed_array_types = {
+ "PackedByteArray",
+ "PackedColorArray",
+ "PackedFloat32Array",
+ "PackedFloat64Array",
+ "PackedInt32Array",
+ "PackedInt64Array",
+ "PackedStringArray",
+ "PackedVector2Array",
+ "PackedVector3Array",
+};
+
// TODO: this is sometimes used directly as doc->something, other times as EditorHelp::get_doc_data(), which is thread-safe.
// Might this be a problem?
DocTools *EditorHelp::doc = nullptr;
@@ -2193,6 +2205,12 @@ void EditorHelp::_update_doc() {
}
has_prev_text = true;
_add_text(descr);
+ // Add copy note to built-in properties returning Packed*Array.
+ if (!cd.is_script_doc && packed_array_types.has(prop.type)) {
+ class_desc->add_newline();
+ class_desc->add_newline();
+ _add_text(vformat(TTR("[b]Note:[/b] The returned array is [i]copied[/i] and any changes to it will not update the original property value. See [%s] for more details."), prop.type));
+ }
} else if (!has_prev_text) {
class_desc->add_image(get_editor_theme_icon(SNAME("Error")));
class_desc->add_text(" ");