Skip to content

Commit d822378

Browse files
authored
Add batched conversion to PackedVector arrays (#784)
* Add batched conversion to PackedVectoXArray
1 parent 4202454 commit d822378

File tree

13 files changed

+370
-28
lines changed

13 files changed

+370
-28
lines changed

harness/tests/src/main/kotlin/godot/tests/packedarray/PackedArrayTest.kt

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,67 +8,109 @@ import godot.core.PackedFloat32Array
88
import godot.core.PackedFloat64Array
99
import godot.core.PackedInt32Array
1010
import godot.core.PackedInt64Array
11+
import godot.core.PackedVector2Array
12+
import godot.core.PackedVector3Array
13+
import godot.core.PackedVector4Array
14+
import godot.core.Vector2
15+
import godot.core.Vector3
16+
import godot.core.Vector4
1117

1218
@RegisterClass
1319
class PackedArrayTest : Node() {
1420

1521
@RegisterFunction
16-
fun convertByteArray() : PackedByteArray {
22+
fun convertByteArray(): PackedByteArray {
1723
val arr = byteArrayOf(0, 1, 2, 4, 8, 16, 32, 64, 127)
1824
return PackedByteArray(arr);
1925
}
2026

2127
@RegisterFunction
22-
fun convertIntArray() : PackedInt32Array {
28+
fun convertIntArray(): PackedInt32Array {
2329
val arr = intArrayOf(0, 1, 2, 4, 8, 16, 32, 64, 127)
2430
return PackedInt32Array(arr);
2531
}
2632

2733
@RegisterFunction
28-
fun convertLongArray() : PackedInt64Array {
34+
fun convertLongArray(): PackedInt64Array {
2935
val arr = longArrayOf(0L, 1L, 2L, 4L, 8L, 16L, 32L, 64L, 127L)
3036
return PackedInt64Array(arr);
3137
}
3238

3339
@RegisterFunction
34-
fun convertFloatArray() : PackedFloat32Array {
40+
fun convertFloatArray(): PackedFloat32Array {
3541
val arr = floatArrayOf(0f, 1f, 2f, 4f, 8f, 16f, 32f, 64f, 127f)
3642
return PackedFloat32Array(arr);
3743
}
3844

3945
@RegisterFunction
40-
fun convertDoubleArray() : PackedFloat64Array {
46+
fun convertDoubleArray(): PackedFloat64Array {
4147
val arr = doubleArrayOf(0.0, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 127.0)
4248
return PackedFloat64Array(arr);
4349
}
4450

4551
@RegisterFunction
46-
fun getByteArrayValue(arr: PackedByteArray, index: Int) : Byte {
52+
fun convertVector2Array(): PackedVector2Array {
53+
val arr = arrayOf(Vector2(0.0, 1.0), Vector2(2.0, 3.0), Vector2(4.0, 5.0), Vector2(1024.0, 2048.0))
54+
return PackedVector2Array(arr);
55+
}
56+
57+
@RegisterFunction
58+
fun convertVector3Array(): PackedVector3Array {
59+
val arr = arrayOf(Vector3(0.0, 1.0, 2.0), Vector3(3.0, 4.0, 5.0), Vector3(6.0, 7.0, 8.0), Vector3(1024.0, 2048.0, 4096.0))
60+
return PackedVector3Array(arr);
61+
}
62+
63+
@RegisterFunction
64+
fun convertVector4Array(): PackedVector4Array {
65+
val arr = arrayOf(Vector4(0.0, 1.0, 2.0, 3.0), Vector4(4.0, 5.0, 6.0, 7.0), Vector4(8.0, 9.0, 10.0, 11.0), Vector4(1024.0, 2048.0, 4096.0, 8092.0))
66+
return PackedVector4Array(arr);
67+
}
68+
69+
@RegisterFunction
70+
fun getByteArrayValue(arr: PackedByteArray, index: Int): Byte {
4771
val kotlinArr = arr.toByteArray()
4872
return kotlinArr[index];
4973
}
5074

5175
@RegisterFunction
52-
fun getIntArrayValue(arr: PackedInt32Array, index: Int) : Int {
76+
fun getIntArrayValue(arr: PackedInt32Array, index: Int): Int {
5377
val kotlinArr = arr.toIntArray()
5478
return kotlinArr[index];
5579
}
5680

5781
@RegisterFunction
58-
fun getLongArrayValue(arr: PackedInt64Array, index: Int) : Long {
82+
fun getLongArrayValue(arr: PackedInt64Array, index: Int): Long {
5983
val kotlinArr = arr.toLongArray()
6084
return kotlinArr[index];
6185
}
6286

6387
@RegisterFunction
64-
fun getFloatArrayValue(arr: PackedFloat32Array, index: Int) : Float {
88+
fun getFloatArrayValue(arr: PackedFloat32Array, index: Int): Float {
6589
val kotlinArr = arr.toFloatArray()
6690
return kotlinArr[index];
6791
}
6892

6993
@RegisterFunction
70-
fun getDoubleArrayValue(arr: PackedFloat64Array, index: Int) : Double {
94+
fun getDoubleArrayValue(arr: PackedFloat64Array, index: Int): Double {
7195
val kotlinArr = arr.toDoubleArray()
7296
return kotlinArr[index];
7397
}
98+
99+
@RegisterFunction
100+
fun getVector2ArrayValue(arr: PackedVector2Array, index: Int): Vector2 {
101+
val kotlinArr = arr.toVector2Array()
102+
return kotlinArr[index];
103+
}
104+
105+
@RegisterFunction
106+
fun getVector3ArrayValue(arr: PackedVector3Array, index: Int): Vector3 {
107+
val kotlinArr = arr.toVector3Array()
108+
return kotlinArr[index];
109+
}
110+
111+
@RegisterFunction
112+
fun getVector4ArrayValue(arr: PackedVector4Array, index: Int): Vector4 {
113+
val kotlinArr = arr.toVector4Array()
114+
return kotlinArr[index];
115+
}
74116
}

harness/tests/test/unit/test_packed_arrays.gd

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,3 +318,51 @@ func test_packed_double_array_bulk_conversion() -> void:
318318
assert_eq(script.get_double_array_value(packed, 8), 127.0, "The original Godot PackedArray value should match the values in the Kotlin DoubleArray")
319319

320320
script.free()
321+
322+
func test_packed_vector2_array_bulk_conversion() -> void:
323+
var script: Object = PackedArrayTest.new()
324+
var packed = script.convert_vector2_array()
325+
326+
assert_eq(packed[0], Vector2(0.0, 1.0), "The Godot PackedArray value should match the values in the original Kotlin Vector2")
327+
assert_eq(packed[1], Vector2(2.0, 3.0), "The Godot PackedArray value should match the values in the original Kotlin Vector2")
328+
assert_eq(packed[2], Vector2(4.0, 5.0), "The Godot PackedArray value should match the values in the original Kotlin Vector2")
329+
assert_eq(packed[3], Vector2(1024.0, 2048.0), "The Godot PackedArray value should match the values in the original Kotlin Vector2")
330+
331+
assert_eq(script.get_vector2_array_value(packed, 0), Vector2(0.0, 1.0), "The original Godot PackedArray value should match the values in the Kotlin Vector2")
332+
assert_eq(script.get_vector2_array_value(packed, 1), Vector2(2.0, 3.0), "The original Godot PackedArray value should match the values in the Kotlin Vector2")
333+
assert_eq(script.get_vector2_array_value(packed, 2), Vector2(4.0, 5.0), "The original Godot PackedArray value should match the values in the Kotlin Vector2")
334+
assert_eq(script.get_vector2_array_value(packed, 3), Vector2(1024.0, 2048.0), "The original Godot PackedArray value should match the values in the Kotlin Vector2")
335+
336+
script.free()
337+
338+
func test_packed_vector3_array_bulk_conversion() -> void:
339+
var script: Object = PackedArrayTest.new()
340+
var packed = script.convert_vector3_array()
341+
342+
assert_eq(packed[0], Vector3(0.0, 1.0, 2.0), "The Godot PackedArray value should match the values in the original Kotlin Vector3")
343+
assert_eq(packed[1], Vector3(3.0, 4.0, 5.0), "The Godot PackedArray value should match the values in the original Kotlin Vector3")
344+
assert_eq(packed[2], Vector3(6.0, 7.0, 8.0), "The Godot PackedArray value should match the values in the original Kotlin Vector3")
345+
assert_eq(packed[3], Vector3(1024.0, 2048.0, 4096.0), "The Godot PackedArray value should match the values in the original Kotlin Vector3")
346+
347+
assert_eq(script.get_vector3_array_value(packed, 0), Vector3(0.0, 1.0, 2.0), "The original Godot PackedArray value should match the values in the Kotlin Vector3")
348+
assert_eq(script.get_vector3_array_value(packed, 1), Vector3(3.0, 4.0, 5.0), "The original Godot PackedArray value should match the values in the Kotlin Vector3")
349+
assert_eq(script.get_vector3_array_value(packed, 2), Vector3(6.0, 7.0, 8.0), "The original Godot PackedArray value should match the values in the Kotlin Vector3")
350+
assert_eq(script.get_vector3_array_value(packed, 3), Vector3(1024.0, 2048.0, 4096.0), "The original Godot PackedArray value should match the values in the Kotlin Vector3")
351+
352+
script.free()
353+
354+
func test_packed_vector4_array_bulk_conversion() -> void:
355+
var script: Object = PackedArrayTest.new()
356+
var packed = script.convert_vector4_array()
357+
358+
assert_eq(packed[0], Vector4(0.0, 1.0, 2.0, 3.0), "The Godot PackedArray value should match the values in the original Kotlin Vector4")
359+
assert_eq(packed[1], Vector4(4.0, 5.0, 6.0, 7.0), "The Godot PackedArray value should match the values in the original Kotlin Vector4")
360+
assert_eq(packed[2], Vector4(8.0, 9.0, 10.0, 11.0), "The Godot PackedArray value should match the values in the original Kotlin Vector4")
361+
assert_eq(packed[3], Vector4(1024.0, 2048.0, 4096.0, 8092.0), "The Godot PackedArray value should match the values in the original Kotlin Vector4")
362+
363+
assert_eq(script.get_vector4_array_value(packed, 0), Vector4(0.0, 1.0, 2.0, 3.0), "The original Godot PackedArray value should match the values in the Kotlin Vector4")
364+
assert_eq(script.get_vector4_array_value(packed, 1), Vector4(4.0, 5.0, 6.0, 7.0), "The original Godot PackedArray value should match the values in the Kotlin Vector4")
365+
assert_eq(script.get_vector4_array_value(packed, 2), Vector4(8.0, 9.0, 10.0, 11.0), "The original Godot PackedArray value should match the values in the Kotlin Vector4")
366+
assert_eq(script.get_vector4_array_value(packed, 3), Vector4(1024.0, 2048.0, 4096.0, 8092.0), "The original Godot PackedArray value should match the values in the Kotlin Vector4")
367+
368+
script.free()

kt/entry-generation/godot-entry-generator/src/main/kotlin/godot/entrygenerator/ext/TypeExtensions.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import godot.tools.common.constants.VARIANT_PARSER_PACKED_INT_64_ARRAY
3030
import godot.tools.common.constants.VARIANT_PARSER_PACKED_STRING_ARRAY
3131
import godot.tools.common.constants.VARIANT_PARSER_PACKED_VECTOR2_ARRAY
3232
import godot.tools.common.constants.VARIANT_PARSER_PACKED_VECTOR3_ARRAY
33+
import godot.tools.common.constants.VARIANT_PARSER_PACKED_VECTOR4_ARRAY
3334
import godot.tools.common.constants.VARIANT_PARSER_STRING
3435
import godot.tools.common.constants.VARIANT_PARSER_STRING_NAME
3536
import godot.tools.common.constants.VARIANT_PARSER_TRANSFORM2D
@@ -71,6 +72,7 @@ fun Type?.toKtVariantType(): ClassName = when {
7172
fqName == "$godotCorePackage.${GodotTypes.packedStringArray}" -> VARIANT_PARSER_PACKED_STRING_ARRAY
7273
fqName == "$godotCorePackage.${GodotTypes.packedVector2Array}" -> VARIANT_PARSER_PACKED_VECTOR2_ARRAY
7374
fqName == "$godotCorePackage.${GodotTypes.packedVector3Array}" -> VARIANT_PARSER_PACKED_VECTOR3_ARRAY
75+
fqName == "$godotCorePackage.${GodotTypes.packedVector4Array}" -> VARIANT_PARSER_PACKED_VECTOR4_ARRAY
7476
fqName == "$godotCorePackage.${GodotTypes.packedColorArray}" -> VARIANT_PARSER_PACKED_COLOR_ARRAY
7577
fqName.startsWith("$godotCorePackage.${GodotTypes.lambdaCallable}") -> VARIANT_PARSER_PACKED_CALLABLE
7678
isCoreType() -> ClassName(
@@ -201,6 +203,7 @@ fun Type.getAsVariantTypeOrdinal(): Int? = when (fqName) {
201203
"$godotCorePackage.${GodotTypes.packedVector2Array}" -> 35
202204
"$godotCorePackage.${GodotTypes.packedVector3Array}" -> 36
203205
"$godotCorePackage.${GodotTypes.packedColorArray}" -> 37
206+
"$godotCorePackage.${GodotTypes.packedVector4Array}" -> 38
204207
else -> if (this.isCompatibleListType()) {
205208
28
206209
} else {

kt/godot-library/godot-core-library/src/main/kotlin/godot/core/bridge/packed/PackedVector2Array.kt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,26 @@ class PackedVector2Array : PackedArray<PackedVector2Array, Vector2> {
4141
MemoryManager.registerNativeCoreType(this, VariantParser.PACKED_VECTOR2_ARRAY)
4242
}
4343

44+
/**
45+
* Constructs a new [PackedVector2Array] from an existing Kotlin [Collection<Vector2>].
46+
*/
47+
constructor(from: Array<Vector2>) {
48+
val floatArray = FloatArray(from.size * 2)
49+
from.forEachIndexed { index, vector ->
50+
val floatIndex = index * 2
51+
floatArray[floatIndex] = vector.x.toFloat()
52+
floatArray[floatIndex + 1] = vector.y.toFloat()
53+
}
54+
55+
ptr = Bridge.engine_convert_to_godot(floatArray)
56+
MemoryManager.registerNativeCoreType(this, VariantParser.PACKED_VECTOR2_ARRAY)
57+
}
58+
59+
/**
60+
* Constructs a new [PackedVector2Array] from an existing Kotlin [Collection<Vector2>].
61+
*/
62+
constructor(from: Collection<Vector2>) : this(from.toTypedArray<Vector2>())
63+
4464
override fun toString(): String {
4565
return "PoolVector2Array(${size})"
4666
}
@@ -63,6 +83,16 @@ class PackedVector2Array : PackedArray<PackedVector2Array, Vector2> {
6383
return ptr.hashCode()
6484
}
6585

86+
fun toVector2Array(): Array<Vector2> {
87+
val floatArray = Bridge.engine_convert_to_jvm(ptr)
88+
return Array<Vector2>(floatArray.size / 2) { vectorIndex ->
89+
val floatIndex = vectorIndex * 2
90+
Vector2(
91+
floatArray[floatIndex],
92+
floatArray[floatIndex + 1]
93+
)
94+
}
95+
}
6696

6797
@Suppress("LocalVariableName")
6898
internal object Bridge : PackedArrayBridge {
@@ -95,5 +125,19 @@ class PackedVector2Array : PackedArray<PackedVector2Array, Vector2> {
95125
external override fun engine_call_slice(_handle: VoidPtr)
96126
external override fun engine_call_sort(_handle: VoidPtr)
97127
external override fun engine_call_to_byte_array(_handle: VoidPtr)
128+
129+
external fun engine_convert_to_godot(array: FloatArray): VoidPtr
130+
external fun engine_convert_to_jvm(_handle: VoidPtr): FloatArray
98131
}
99132
}
133+
134+
/**
135+
* Convert a [Array<Vector2>] into a Godot [PackedVector2Array], this call is optimised for a large amount of data.
136+
*/
137+
fun Array<Vector2>.toPackedArray() = PackedVector2Array(this)
138+
139+
140+
/**
141+
* Convert a [Collection<Vector2>] into a Godot [PackedVector2Array], this call is optimised for a large amount of data.
142+
*/
143+
fun Collection<Vector2>.toPackedArray() = PackedVector2Array(this.toTypedArray())

kt/godot-library/godot-core-library/src/main/kotlin/godot/core/bridge/packed/PackedVector3Array.kt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package godot.core
55
import godot.internal.memory.MemoryManager
66
import godot.internal.memory.TransferContext
77
import godot.common.interop.VoidPtr
8+
import godot.core.PackedVector2Array
89

910
@Suppress("MemberVisibilityCanBePrivate", "unused")
1011
class PackedVector3Array : PackedArray<PackedVector3Array, Vector3> {
@@ -41,6 +42,27 @@ class PackedVector3Array : PackedArray<PackedVector3Array, Vector3> {
4142
MemoryManager.registerNativeCoreType(this, VariantParser.PACKED_VECTOR3_ARRAY)
4243
}
4344

45+
/**
46+
* Constructs a new [PackedVector3Array] from an existing Kotlin [Array<Vector3>].
47+
*/
48+
constructor(from: Array<Vector3>) {
49+
val floatArray = FloatArray(from.size * 3)
50+
from.forEachIndexed { index, vector ->
51+
val floatIndex = index * 3
52+
floatArray[floatIndex] = vector.x.toFloat()
53+
floatArray[floatIndex + 1] = vector.y.toFloat()
54+
floatArray[floatIndex + 2] = vector.z.toFloat()
55+
}
56+
57+
ptr = Bridge.engine_convert_to_godot(floatArray)
58+
MemoryManager.registerNativeCoreType(this, VariantParser.PACKED_VECTOR3_ARRAY)
59+
}
60+
61+
/**
62+
* Constructs a new [PackedVector3Array] from an existing Kotlin [Collection<Vector3>].
63+
*/
64+
constructor(from: Collection<Vector3>) : this(from.toTypedArray<Vector3>())
65+
4466
override fun toString(): String {
4567
return "PoolVector3Array(${size})"
4668
}
@@ -63,6 +85,17 @@ class PackedVector3Array : PackedArray<PackedVector3Array, Vector3> {
6385
return ptr.hashCode()
6486
}
6587

88+
fun toVector3Array(): Array<Vector3> {
89+
val floatArray = Bridge.engine_convert_to_jvm(ptr)
90+
return Array<Vector3>(floatArray.size / 3) { vectorIndex ->
91+
val floatIndex = vectorIndex * 3
92+
Vector3(
93+
floatArray[floatIndex],
94+
floatArray[floatIndex + 1],
95+
floatArray[floatIndex + 2]
96+
)
97+
}
98+
}
6699

67100
@Suppress("LocalVariableName")
68101
internal object Bridge : PackedArrayBridge {
@@ -95,5 +128,19 @@ class PackedVector3Array : PackedArray<PackedVector3Array, Vector3> {
95128
external override fun engine_call_slice(_handle: VoidPtr)
96129
external override fun engine_call_sort(_handle: VoidPtr)
97130
external override fun engine_call_to_byte_array(_handle: VoidPtr)
131+
132+
external fun engine_convert_to_godot(array: FloatArray): VoidPtr
133+
external fun engine_convert_to_jvm(_handle: VoidPtr): FloatArray
98134
}
99135
}
136+
137+
/**
138+
* Convert a [Array<Vector3>] into a Godot [PackedVector3Array], this call is optimised for a large amount of data.
139+
*/
140+
fun Array<Vector3>.toPackedArray() = PackedVector3Array(this)
141+
142+
143+
/**
144+
* Convert a [Collection<Vector3>] into a Godot [PackedVector3Array], this call is optimised for a large amount of data.
145+
*/
146+
fun Collection<Vector3>.toPackedArray() = PackedVector3Array(this.toTypedArray())

0 commit comments

Comments
 (0)