Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GDExtension] Implement support for typed arrays. #65817

Merged
merged 1 commit into from
Sep 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions core/extension/extension_api_dump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ static String get_type_name(const PropertyInfo &p_info) {
return p_info.hint_string + "*";
}
}
if (p_info.type == Variant::ARRAY && (p_info.hint == PROPERTY_HINT_ARRAY_TYPE)) {
return String("typedarray::") + p_info.hint_string;
}
if (p_info.type == Variant::INT && (p_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM))) {
return String("enum::") + String(p_info.class_name);
}
Expand Down
2 changes: 1 addition & 1 deletion core/variant/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ class Array {
void _unref() const;

protected:
Array(const Array &p_base, uint32_t p_type, const StringName &p_class_name, const Variant &p_script);
bool _assign(const Array &p_array);

public:
Expand Down Expand Up @@ -131,6 +130,7 @@ class Array {
void set_read_only(bool p_enable);
bool is_read_only() const;

Array(const Array &p_base, uint32_t p_type, const StringName &p_class_name, const Variant &p_script);
Array(const Array &p_from);
Array();
~Array();
Expand Down
8 changes: 8 additions & 0 deletions core/variant/variant_call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2065,6 +2065,14 @@ static void _register_variant_builtin_methods() {
bind_method(Array, all, sarray("method"), varray());
bind_method(Array, max, sarray(), varray());
bind_method(Array, min, sarray(), varray());
bind_method(Array, typed_assign, sarray("array"), varray());
bind_method(Array, set_typed, sarray("type", "class_name", "script"), varray());
bind_method(Array, is_typed, sarray(), varray());
bind_method(Array, get_typed_builtin, sarray(), varray());
bind_method(Array, get_typed_class_name, sarray(), varray());
bind_method(Array, get_typed_script, sarray(), varray());
bind_method(Array, set_read_only, sarray("enable"), varray());
bind_method(Array, is_read_only, sarray(), varray());

/* Byte Array */
bind_method(PackedByteArray, size, sarray(), varray());
Expand Down
1 change: 1 addition & 0 deletions core/variant/variant_construct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ void Variant::_register_variant_constructors() {

add_constructor<VariantConstructNoArgs<Array>>(sarray());
add_constructor<VariantConstructor<Array, Array>>(sarray("from"));
add_constructor<VariantConstructorTypedArray>(sarray("base", "type", "class_name", "script"));
add_constructor<VariantConstructorToArray<PackedByteArray>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedInt32Array>>(sarray("from"));
add_constructor<VariantConstructorToArray<PackedInt64Array>>(sarray("from"));
Expand Down
76 changes: 76 additions & 0 deletions core/variant/variant_construct.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,82 @@ class VariantConstructorSignalArgs {
}
};

class VariantConstructorTypedArray {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
if (p_args[0]->get_type() != Variant::ARRAY) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::ARRAY;
return;
}

if (p_args[1]->get_type() != Variant::INT) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::INT;
return;
}

if (p_args[2]->get_type() != Variant::STRING_NAME) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 2;
r_error.expected = Variant::STRING_NAME;
return;
}

const Array &base_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
const uint32_t type = p_args[1]->operator uint32_t();
const StringName &class_name = *VariantGetInternalPtr<StringName>::get_ptr(p_args[2]);
r_ret = Array(base_arr, type, class_name, *p_args[3]);
}

static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
const Array &base_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
const uint32_t type = p_args[1]->operator uint32_t();
const StringName &class_name = *VariantGetInternalPtr<StringName>::get_ptr(p_args[2]);
*r_ret = Array(base_arr, type, class_name, *p_args[3]);
}

static void ptr_construct(void *base, const void **p_args) {
const Array &base_arr = PtrToArg<Array>::convert(p_args[0]);
const uint32_t type = PtrToArg<uint32_t>::convert(p_args[1]);
const StringName &class_name = PtrToArg<StringName>::convert(p_args[2]);
const Variant &script = PtrToArg<Variant>::convert(p_args[3]);
Array dst_arr = Array(base_arr, type, class_name, script);

PtrConstruct<Array>::construct(dst_arr, base);
}

static int get_argument_count() {
return 4;
}

static Variant::Type get_argument_type(int p_arg) {
switch (p_arg) {
case 0: {
return Variant::ARRAY;
} break;
case 1: {
return Variant::INT;
} break;
case 2: {
return Variant::STRING_NAME;
} break;
case 3: {
return Variant::NIL;
} break;
default: {
return Variant::NIL;
} break;
}
}

static Variant::Type get_base_type() {
return Variant::ARRAY;
}
};

template <class T>
class VariantConstructorToArray {
public:
Expand Down
54 changes: 54 additions & 0 deletions doc/classes/Array.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@
Constructs an empty [Array].
</description>
</constructor>
<constructor name="Array">
<return type="Array" />
<param index="0" name="base" type="Array" />
<param index="1" name="type" type="int" />
<param index="2" name="class_name" type="StringName" />
<param index="3" name="script" type="Variant" />
<description>
</description>
</constructor>
<constructor name="Array">
<return type="Array" />
<param index="0" name="from" type="Array" />
Expand Down Expand Up @@ -303,6 +312,21 @@
[b]Note:[/b] Calling this function is not the same as writing [code]array[0][/code]. If the array is empty, accessing by index will pause project execution when running from the editor.
</description>
</method>
<method name="get_typed_builtin" qualifiers="const">
<return type="int" />
<description>
</description>
</method>
<method name="get_typed_class_name" qualifiers="const">
<return type="StringName" />
<description>
</description>
</method>
<method name="get_typed_script" qualifiers="const">
<return type="Variant" />
<description>
</description>
</method>
<method name="has" qualifiers="const">
<return type="bool" />
<param index="0" name="value" type="Variant" />
Expand Down Expand Up @@ -366,6 +390,16 @@
Returns [code]true[/code] if the array is empty.
</description>
</method>
<method name="is_read_only" qualifiers="const">
<return type="bool" />
<description>
</description>
</method>
<method name="is_typed" qualifiers="const">
<return type="bool" />
<description>
</description>
</method>
<method name="map" qualifiers="const">
<return type="Array" />
<param index="0" name="method" type="Callable" />
Expand Down Expand Up @@ -479,6 +513,20 @@
Searches the array in reverse order. Optionally, a start search index can be passed. If negative, the start index is considered relative to the end of the array.
</description>
</method>
<method name="set_read_only">
<return type="void" />
<param index="0" name="enable" type="bool" />
<description>
</description>
</method>
<method name="set_typed">
<return type="void" />
<param index="0" name="type" type="int" />
<param index="1" name="class_name" type="StringName" />
<param index="2" name="script" type="Variant" />
<description>
</description>
</method>
<method name="shuffle">
<return type="void" />
<description>
Expand Down Expand Up @@ -556,6 +604,12 @@
[/codeblocks]
</description>
</method>
<method name="typed_assign">
<return type="bool" />
<param index="0" name="array" type="Array" />
<description>
</description>
</method>
</methods>
<operators>
<operator name="operator !=">
Expand Down
29 changes: 27 additions & 2 deletions modules/text_server_adv/gdextension_build/SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ env = SConscript("./godot-cpp/SConstruct")
env.__class__.disable_warnings = methods.disable_warnings

opts = Variables([], ARGUMENTS)
opts.Add(BoolVariable("brotli_enabled", "Use Brotli library", True))
opts.Add(BoolVariable("freetype_enabled", "Use FreeType library", True))
opts.Add(BoolVariable("msdfgen_enabled", "Use MSDFgen library (require FreeType)", True))
opts.Add(BoolVariable("graphite_enabled", "Use Graphite library (require FreeType)", True))
Expand Down Expand Up @@ -162,6 +163,25 @@ if env["freetype_enabled"]:
]
thirdparty_freetype_sources += [thirdparty_zlib_dir + file for file in thirdparty_zlib_sources]

if env["brotli_enabled"]:
thirdparty_brotli_dir = "../../../thirdparty/brotli/"
thirdparty_brotli_sources = [
"common/constants.c",
"common/context.c",
"common/dictionary.c",
"common/platform.c",
"common/shared_dictionary.c",
"common/transform.c",
"dec/bit_reader.c",
"dec/decode.c",
"dec/huffman.c",
"dec/state.c",
]
thirdparty_freetype_sources += [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources]
env_freetype.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
env_freetype.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
env.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])

env_freetype.Append(CPPPATH=[thirdparty_freetype_dir + "/include", thirdparty_zlib_dir, thirdparty_png_dir])
env.Append(CPPPATH=[thirdparty_freetype_dir + "/include"])

Expand Down Expand Up @@ -265,6 +285,7 @@ env_harfbuzz.Append(
CPPPATH=[
"../../../thirdparty/harfbuzz/src",
"../../../thirdparty/icu4c/common/",
"../../../thirdparty/icu4c/i18n/",
]
)

Expand Down Expand Up @@ -569,6 +590,10 @@ thirdparty_icu_sources = [
"common/uvectr32.cpp",
"common/uvectr64.cpp",
"common/wintz.cpp",
"i18n/scriptset.cpp",
"i18n/ucln_in.cpp",
"i18n/uspoof.cpp",
"i18n/uspoof_impl.cpp",
]
thirdparty_icu_sources = [thirdparty_icu_dir + file for file in thirdparty_icu_sources]

Expand All @@ -584,7 +609,7 @@ if env["static_icu_data"]:
else:
thirdparty_sources += ["../icu_data/icudata_stub.cpp"]

env_icu.Append(CPPPATH=["../../../thirdparty/icu4c/common/"])
env_icu.Append(CPPPATH=["../../../thirdparty/icu4c/common/", "../../../thirdparty/icu4c/i18n/"])
env_icu.Append(
CXXFLAGS=[
"-DU_STATIC_IMPLEMENTATION",
Expand All @@ -610,7 +635,7 @@ env.Append(
"-DICU_DATA_NAME=" + icu_data_name,
]
)
env.Append(CPPPATH=["../../../thirdparty/icu4c/common/"])
env.Append(CPPPATH=["../../../thirdparty/icu4c/common/", "../../../thirdparty/icu4c/i18n/"])

if env["platform"] == "windows":
env.Append(LIBS=["advapi32"])
Expand Down
4 changes: 2 additions & 2 deletions modules/text_server_adv/text_server_adv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5851,9 +5851,9 @@ String TextServerAdvanced::percent_sign(const String &p_language) const {
return "%";
}

int TextServerAdvanced::is_confusable(const String &p_string, const PackedStringArray &p_dict) const {
int64_t TextServerAdvanced::is_confusable(const String &p_string, const PackedStringArray &p_dict) const {
UErrorCode status = U_ZERO_ERROR;
int match_index = -1;
int64_t match_index = -1;

Char16String utf16 = p_string.utf16();
Vector<UChar *> skeletons;
Expand Down
3 changes: 2 additions & 1 deletion modules/text_server_adv/text_server_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include <godot_cpp/variant/rect2.hpp>
#include <godot_cpp/variant/rid.hpp>
#include <godot_cpp/variant/string.hpp>
#include <godot_cpp/variant/typed_array.hpp>
#include <godot_cpp/variant/vector2.hpp>
#include <godot_cpp/variant/vector2i.hpp>

Expand Down Expand Up @@ -705,7 +706,7 @@ class TextServerAdvanced : public TextServerExtension {

virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const override;

virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const override;
virtual int64_t is_confusable(const String &p_string, const PackedStringArray &p_dict) const override;
virtual bool spoof_check(const String &p_string) const override;

virtual String strip_diacritics(const String &p_string) const override;
Expand Down
20 changes: 20 additions & 0 deletions modules/text_server_fb/gdextension_build/SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ env = SConscript("./godot-cpp/SConstruct")
env.__class__.disable_warnings = methods.disable_warnings

opts = Variables([], ARGUMENTS)
opts.Add(BoolVariable("brotli_enabled", "Use Brotli library", True))
opts.Add(BoolVariable("freetype_enabled", "Use FreeType library", True))
opts.Add(BoolVariable("msdfgen_enabled", "Use MSDFgen library (require FreeType)", True))
opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
Expand Down Expand Up @@ -157,6 +158,25 @@ if env["freetype_enabled"]:
]
thirdparty_freetype_sources += [thirdparty_zlib_dir + file for file in thirdparty_zlib_sources]

if env["brotli_enabled"]:
thirdparty_brotli_dir = "../../../thirdparty/brotli/"
thirdparty_brotli_sources = [
"common/constants.c",
"common/context.c",
"common/dictionary.c",
"common/platform.c",
"common/shared_dictionary.c",
"common/transform.c",
"dec/bit_reader.c",
"dec/decode.c",
"dec/huffman.c",
"dec/state.c",
]
thirdparty_freetype_sources += [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources]
env_freetype.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
env_freetype.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
env.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])

env_freetype.Append(CPPPATH=[thirdparty_freetype_dir + "/include", thirdparty_zlib_dir, thirdparty_png_dir])
env.Append(CPPPATH=[thirdparty_freetype_dir + "/include"])

Expand Down
1 change: 1 addition & 0 deletions modules/text_server_fb/text_server_fb.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include <godot_cpp/variant/rect2.hpp>
#include <godot_cpp/variant/rid.hpp>
#include <godot_cpp/variant/string.hpp>
#include <godot_cpp/variant/typed_array.hpp>
#include <godot_cpp/variant/vector2.hpp>
#include <godot_cpp/variant/vector2i.hpp>

Expand Down
4 changes: 2 additions & 2 deletions servers/text/text_server_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1550,8 +1550,8 @@ PackedInt32Array TextServerExtension::string_get_word_breaks(const String &p_str
return PackedInt32Array();
}

int TextServerExtension::is_confusable(const String &p_string, const PackedStringArray &p_dict) const {
int ret;
int64_t TextServerExtension::is_confusable(const String &p_string, const PackedStringArray &p_dict) const {
int64_t ret;
if (GDVIRTUAL_CALL(is_confusable, p_string, p_dict, ret)) {
return ret;
}
Expand Down
4 changes: 2 additions & 2 deletions servers/text/text_server_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,9 @@ class TextServerExtension : public TextServer {
TypedArray<Vector2i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
GDVIRTUAL3RC(TypedArray<Vector2i>, parse_structured_text, StructuredTextParser, const Array &, const String &);

virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const override;
virtual int64_t is_confusable(const String &p_string, const PackedStringArray &p_dict) const override;
virtual bool spoof_check(const String &p_string) const override;
GDVIRTUAL2RC(int, is_confusable, const String &, const PackedStringArray &);
GDVIRTUAL2RC(int64_t, is_confusable, const String &, const PackedStringArray &);
GDVIRTUAL1RC(bool, spoof_check, const String &);

TextServerExtension();
Expand Down
2 changes: 1 addition & 1 deletion servers/text_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ class TextServer : public RefCounted {
// String functions.
virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const = 0;

virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const { return -1; };
virtual int64_t is_confusable(const String &p_string, const PackedStringArray &p_dict) const { return -1; };
virtual bool spoof_check(const String &p_string) const { return false; };

virtual String strip_diacritics(const String &p_string) const;
Expand Down