Merge pull request #841 from bruvzg/typed_array

Implement support for typed arrays.
pull/864/head
Rémi Verschelde 2022-09-23 09:19:37 +02:00 committed by GitHub
commit e40aa112ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 2396 additions and 1541 deletions

View File

@ -276,7 +276,10 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
result.append("#include <godot_cpp/variant/array_helpers.hpp>") result.append("#include <godot_cpp/variant/array_helpers.hpp>")
for include in fully_used_classes: for include in fully_used_classes:
result.append(f"#include <godot_cpp/{get_include_path(include)}>") if include == "TypedArray":
result.append("#include <godot_cpp/variant/typed_array.hpp>")
else:
result.append(f"#include <godot_cpp/{get_include_path(include)}>")
if len(fully_used_classes) > 0: if len(fully_used_classes) > 0:
result.append("") result.append("")
@ -860,7 +863,21 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
if type_name.endswith("*"): if type_name.endswith("*"):
type_name = type_name[:-1] type_name = type_name[:-1]
if is_included(type_name, class_name): if is_included(type_name, class_name):
if is_enum(type_name): if type_name.startswith("typedarray::"):
fully_used_classes.add("TypedArray")
array_type_name = type_name.replace("typedarray::", "")
if array_type_name.startswith("const "):
array_type_name = array_type_name[6:]
if array_type_name.endswith("*"):
array_type_name = array_type_name[:-1]
if is_included(array_type_name, class_name):
if is_enum(array_type_name):
fully_used_classes.add(get_enum_class(array_type_name))
elif "default_value" in argument:
fully_used_classes.add(array_type_name)
else:
used_classes.add(array_type_name)
elif is_enum(type_name):
fully_used_classes.add(get_enum_class(type_name)) fully_used_classes.add(get_enum_class(type_name))
elif "default_value" in argument: elif "default_value" in argument:
fully_used_classes.add(type_name) fully_used_classes.add(type_name)
@ -875,7 +892,21 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
if type_name.endswith("*"): if type_name.endswith("*"):
type_name = type_name[:-1] type_name = type_name[:-1]
if is_included(type_name, class_name): if is_included(type_name, class_name):
if is_enum(type_name): if type_name.startswith("typedarray::"):
fully_used_classes.add("TypedArray")
array_type_name = type_name.replace("typedarray::", "")
if array_type_name.startswith("const "):
array_type_name = array_type_name[6:]
if array_type_name.endswith("*"):
array_type_name = array_type_name[:-1]
if is_included(array_type_name, class_name):
if is_enum(array_type_name):
fully_used_classes.add(get_enum_class(array_type_name))
elif is_variant(array_type_name):
fully_used_classes.add(array_type_name)
else:
used_classes.add(array_type_name)
elif is_enum(type_name):
fully_used_classes.add(get_enum_class(type_name)) fully_used_classes.add(get_enum_class(type_name))
elif is_variant(type_name): elif is_variant(type_name):
fully_used_classes.add(type_name) fully_used_classes.add(type_name)
@ -988,7 +1019,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append("") result.append("")
for included in fully_used_classes: for included in fully_used_classes:
result.append(f"#include <godot_cpp/{get_include_path(included)}>") if included == "TypedArray":
result.append("#include <godot_cpp/variant/typed_array.hpp>")
else:
result.append(f"#include <godot_cpp/{get_include_path(included)}>")
if len(fully_used_classes) > 0: if len(fully_used_classes) > 0:
result.append("") result.append("")
@ -1803,7 +1837,12 @@ def get_enum_name(enum_name: str):
def is_variant(type_name): def is_variant(type_name):
return type_name == "Variant" or type_name in builtin_classes or type_name == "Nil" return (
type_name == "Variant"
or type_name in builtin_classes
or type_name == "Nil"
or type_name.startswith("typedarray::")
)
def is_engine_class(type_name): def is_engine_class(type_name):
@ -1825,6 +1864,8 @@ def is_included(type_name, current_type):
Check if a builtin type should be included. Check if a builtin type should be included.
This removes Variant and POD types from inclusion, and the current type. This removes Variant and POD types from inclusion, and the current type.
""" """
if type_name.startswith("typedarray::"):
return True
to_include = get_enum_class(type_name) if is_enum(type_name) else type_name to_include = get_enum_class(type_name) if is_enum(type_name) else type_name
if to_include == current_type or is_pod_type(to_include): if to_include == current_type or is_pod_type(to_include):
return False return False
@ -1850,6 +1891,12 @@ def correct_default_value(value, type_name):
return value return value
def correct_typed_array(type_name):
if type_name.startswith("typedarray::"):
return type_name.replace("typedarray::", "TypedArray<") + ">"
return type_name
def correct_type(type_name, meta=None): def correct_type(type_name, meta=None):
type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"} type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"}
if meta != None: if meta != None:
@ -1861,6 +1908,8 @@ def correct_type(type_name, meta=None):
return meta return meta
if type_name in type_conversion: if type_name in type_conversion:
return type_conversion[type_name] return type_conversion[type_name]
if type_name.startswith("typedarray::"):
return type_name.replace("typedarray::", "TypedArray<") + ">"
if is_enum(type_name): if is_enum(type_name):
if is_bitfield(type_name): if is_bitfield(type_name):
base_class = get_enum_class(type_name) base_class = get_enum_class(type_name)
@ -1962,6 +2011,8 @@ def get_default_value_for_type(type_name):
return "0.0" return "0.0"
if type_name == "bool": if type_name == "bool":
return "false" return "false"
if type_name.startswith("typedarray::"):
return f"{correct_type(type_name)}()"
if is_enum(type_name): if is_enum(type_name):
return f"{correct_type(type_name)}(0)" return f"{correct_type(type_name)}(0)"
if is_variant(type_name): if is_variant(type_name):

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,7 @@
#define GODOT_TYPE_INFO_HPP #define GODOT_TYPE_INFO_HPP
#include <godot_cpp/core/object.hpp> #include <godot_cpp/core/object.hpp>
#include <godot_cpp/variant/typed_array.hpp>
#include <godot_cpp/variant/variant.hpp> #include <godot_cpp/variant/variant.hpp>
#include <godot/gdnative_interface.h> #include <godot/gdnative_interface.h>
@ -284,6 +285,106 @@ inline const char *__constant_get_bitfield_name(T param, const char *p_constant)
return GetTypeInfo<BitField<T>>::get_class_info().class_name; return GetTypeInfo<BitField<T>>::get_class_info().class_name;
} }
template <class T>
struct PtrToArg<TypedArray<T>> {
_FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) {
return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr));
}
typedef Array EncodeT;
_FORCE_INLINE_ static void encode(TypedArray<T> p_val, void *p_ptr) {
*(Array *)p_ptr = p_val;
}
};
template <class T>
struct PtrToArg<const TypedArray<T> &> {
typedef Array EncodeT;
_FORCE_INLINE_ static TypedArray<T>
convert(const void *p_ptr) {
return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr));
}
};
template <typename T>
struct GetTypeInfo<TypedArray<T>> {
static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_ARRAY;
static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline GDNativePropertyInfo get_class_info() {
return make_property_info(GDNATIVE_VARIANT_TYPE_ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, T::get_class_static());
}
};
template <typename T>
struct GetTypeInfo<const TypedArray<T> &> {
static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_ARRAY;
static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline GDNativePropertyInfo get_class_info() {
return make_property_info(GDNATIVE_VARIANT_TYPE_ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, T::get_class_static());
}
};
#define MAKE_TYPED_ARRAY_INFO(m_type, m_variant_type) \
template <> \
struct GetTypeInfo<TypedArray<m_type>> { \
static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_ARRAY; \
static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline GDNativePropertyInfo get_class_info() { \
return make_property_info(GDNATIVE_VARIANT_TYPE_ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, Variant::get_type_name(m_variant_type).utf8().get_data()); \
} \
}; \
template <> \
struct GetTypeInfo<const TypedArray<m_type> &> { \
static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_ARRAY; \
static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline GDNativePropertyInfo get_class_info() { \
return make_property_info(GDNATIVE_VARIANT_TYPE_ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, Variant::get_type_name(m_variant_type).utf8().get_data()); \
} \
};
MAKE_TYPED_ARRAY_INFO(bool, Variant::BOOL)
MAKE_TYPED_ARRAY_INFO(uint8_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(int8_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(uint16_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(int16_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(uint32_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(int32_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(uint64_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(int64_t, Variant::INT)
MAKE_TYPED_ARRAY_INFO(float, Variant::FLOAT)
MAKE_TYPED_ARRAY_INFO(double, Variant::FLOAT)
MAKE_TYPED_ARRAY_INFO(String, Variant::STRING)
MAKE_TYPED_ARRAY_INFO(Vector2, Variant::VECTOR2)
MAKE_TYPED_ARRAY_INFO(Vector2i, Variant::VECTOR2I)
MAKE_TYPED_ARRAY_INFO(Rect2, Variant::RECT2)
MAKE_TYPED_ARRAY_INFO(Rect2i, Variant::RECT2I)
MAKE_TYPED_ARRAY_INFO(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY_INFO(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY_INFO(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_ARRAY_INFO(Plane, Variant::PLANE)
MAKE_TYPED_ARRAY_INFO(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY_INFO(AABB, Variant::AABB)
MAKE_TYPED_ARRAY_INFO(Basis, Variant::BASIS)
MAKE_TYPED_ARRAY_INFO(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_ARRAY_INFO(Color, Variant::COLOR)
MAKE_TYPED_ARRAY_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY_INFO(NodePath, Variant::NODE_PATH)
MAKE_TYPED_ARRAY_INFO(RID, Variant::RID)
MAKE_TYPED_ARRAY_INFO(Callable, Variant::CALLABLE)
MAKE_TYPED_ARRAY_INFO(Signal, Variant::SIGNAL)
MAKE_TYPED_ARRAY_INFO(Dictionary, Variant::DICTIONARY)
MAKE_TYPED_ARRAY_INFO(Array, Variant::ARRAY)
/*
MAKE_TYPED_ARRAY_INFO(Vector<uint8_t>, Variant::PACKED_BYTE_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<int32_t>, Variant::PACKED_INT32_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<int64_t>, Variant::PACKED_INT64_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<float>, Variant::PACKED_FLOAT32_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<double>, Variant::PACKED_FLOAT64_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<String>, Variant::PACKED_STRING_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<Color>, Variant::PACKED_COLOR_ARRAY)
*/
#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info()) #define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
} // namespace godot } // namespace godot

View File

@ -0,0 +1,126 @@
/*************************************************************************/
/* typed_array.hpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef GODOT_CPP_TYPED_ARRAY_HPP
#define GODOT_CPP_TYPED_ARRAY_HPP
#include <godot_cpp/variant/array.hpp>
#include <godot_cpp/variant/variant.hpp>
namespace godot {
template <class T>
class TypedArray : public Array {
public:
template <class U>
_FORCE_INLINE_ void operator=(const TypedArray<U> &p_array) {
static_assert(__is_base_of(T, U));
typed_assign(p_array);
}
_FORCE_INLINE_ void operator=(const Array &p_array) {
typed_assign(p_array);
}
_FORCE_INLINE_ TypedArray(const Variant &p_variant) :
Array(p_variant.operator Array(), Variant::OBJECT, T::get_class_static(), Variant()) {
}
_FORCE_INLINE_ TypedArray(const Array &p_array) :
Array(p_array, Variant::OBJECT, T::get_class_static(), Variant()) {
}
_FORCE_INLINE_ TypedArray() {
set_typed(Variant::OBJECT, T::get_class_static(), Variant());
}
};
// specialization for the rest of variant types
#define MAKE_TYPED_ARRAY(m_type, m_variant_type) \
template <> \
class TypedArray<m_type> : public Array { \
public: \
_FORCE_INLINE_ void operator=(const Array &p_array) { \
typed_assign(p_array); \
} \
_FORCE_INLINE_ TypedArray(const Variant &p_variant) : \
Array(p_variant.operator Array(), m_variant_type, StringName(), Variant()) { \
} \
_FORCE_INLINE_ TypedArray(const Array &p_array) : \
Array(p_array, m_variant_type, StringName(), Variant()) { \
} \
_FORCE_INLINE_ TypedArray() { \
set_typed(m_variant_type, StringName(), Variant()); \
} \
};
MAKE_TYPED_ARRAY(bool, Variant::BOOL)
MAKE_TYPED_ARRAY(uint8_t, Variant::INT)
MAKE_TYPED_ARRAY(int8_t, Variant::INT)
MAKE_TYPED_ARRAY(uint16_t, Variant::INT)
MAKE_TYPED_ARRAY(int16_t, Variant::INT)
MAKE_TYPED_ARRAY(uint32_t, Variant::INT)
MAKE_TYPED_ARRAY(int32_t, Variant::INT)
MAKE_TYPED_ARRAY(uint64_t, Variant::INT)
MAKE_TYPED_ARRAY(int64_t, Variant::INT)
MAKE_TYPED_ARRAY(float, Variant::FLOAT)
MAKE_TYPED_ARRAY(double, Variant::FLOAT)
MAKE_TYPED_ARRAY(String, Variant::STRING)
MAKE_TYPED_ARRAY(Vector2, Variant::VECTOR2)
MAKE_TYPED_ARRAY(Vector2i, Variant::VECTOR2I)
MAKE_TYPED_ARRAY(Rect2, Variant::RECT2)
MAKE_TYPED_ARRAY(Rect2i, Variant::RECT2I)
MAKE_TYPED_ARRAY(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_ARRAY(Plane, Variant::PLANE)
MAKE_TYPED_ARRAY(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY(AABB, Variant::AABB)
MAKE_TYPED_ARRAY(Basis, Variant::BASIS)
MAKE_TYPED_ARRAY(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_ARRAY(Color, Variant::COLOR)
MAKE_TYPED_ARRAY(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY(NodePath, Variant::NODE_PATH)
MAKE_TYPED_ARRAY(RID, Variant::RID)
MAKE_TYPED_ARRAY(Callable, Variant::CALLABLE)
MAKE_TYPED_ARRAY(Signal, Variant::SIGNAL)
MAKE_TYPED_ARRAY(Dictionary, Variant::DICTIONARY)
MAKE_TYPED_ARRAY(Array, Variant::ARRAY)
MAKE_TYPED_ARRAY(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
MAKE_TYPED_ARRAY(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
MAKE_TYPED_ARRAY(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
MAKE_TYPED_ARRAY(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
MAKE_TYPED_ARRAY(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
MAKE_TYPED_ARRAY(PackedStringArray, Variant::PACKED_STRING_ARRAY)
MAKE_TYPED_ARRAY(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_ARRAY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_ARRAY(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
} // namespace godot
#endif // GODOT_CPP_TYPED_ARRAY_HPP

View File

@ -45,7 +45,10 @@ func _ready():
prints("Array and Dictionary") prints("Array and Dictionary")
prints(" test array", $Example.test_array()) prints(" test array", $Example.test_array())
prints(" test tarray", $Example.test_tarray())
prints(" test dictionary", $Example.test_dictionary()) prints(" test dictionary", $Example.test_dictionary())
var array: Array[int] = [1, 2, 3]
$Example.test_tarray_arg(array)
prints("Properties") prints("Properties")
prints(" custom position is", $Example.group_subgroup_custom_position) prints(" custom position is", $Example.group_subgroup_custom_position)

View File

@ -103,6 +103,8 @@ void Example::_bind_methods() {
ClassDB::bind_method(D_METHOD("extended_ref_checks"), &Example::extended_ref_checks); ClassDB::bind_method(D_METHOD("extended_ref_checks"), &Example::extended_ref_checks);
ClassDB::bind_method(D_METHOD("test_array"), &Example::test_array); ClassDB::bind_method(D_METHOD("test_array"), &Example::test_array);
ClassDB::bind_method(D_METHOD("test_tarray_arg", "array"), &Example::test_tarray_arg);
ClassDB::bind_method(D_METHOD("test_tarray"), &Example::test_tarray);
ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary); ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary);
ClassDB::bind_method(D_METHOD("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200)); ClassDB::bind_method(D_METHOD("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200));
@ -223,6 +225,22 @@ Array Example::test_array() const {
return arr; return arr;
} }
void Example::test_tarray_arg(const TypedArray<int64_t> &p_array) {
for (int i = 0; i < p_array.size(); i++) {
UtilityFunctions::print(p_array[i]);
}
}
TypedArray<Vector2> Example::test_tarray() const {
TypedArray<Vector2> arr;
arr.resize(2);
arr[0] = Vector2(1, 2);
arr[1] = Vector2(2, 3);
return arr;
}
Dictionary Example::test_dictionary() const { Dictionary Example::test_dictionary() const {
Dictionary dict; Dictionary dict;

View File

@ -88,6 +88,8 @@ public:
int def_args(int p_a = 100, int p_b = 200); int def_args(int p_a = 100, int p_b = 200);
Array test_array() const; Array test_array() const;
void test_tarray_arg(const TypedArray<int64_t> &p_array);
TypedArray<Vector2> test_tarray() const;
Dictionary test_dictionary() const; Dictionary test_dictionary() const;
// Property. // Property.