Procházet zdrojové kódy

[GDExtension] Implement support for typed arrays.

bruvzg před 2 roky
rodič
revize
163257d51b

+ 3 - 0
core/extension/extension_api_dump.cpp

@@ -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);
 	}

+ 1 - 1
core/variant/array.h

@@ -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:
@@ -131,6 +130,7 @@ public:
 	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();

+ 8 - 0
core/variant/variant_call.cpp

@@ -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());

+ 1 - 0
core/variant/variant_construct.cpp

@@ -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"));

+ 76 - 0
core/variant/variant_construct.h

@@ -336,6 +336,82 @@ public:
 	}
 };
 
+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:

+ 54 - 0
doc/classes/Array.xml

@@ -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" />
@@ -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" />
@@ -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" />
@@ -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>
@@ -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 !=">

+ 27 - 2
modules/text_server_adv/gdextension_build/SConstruct

@@ -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))
@@ -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"])
 
@@ -265,6 +285,7 @@ env_harfbuzz.Append(
     CPPPATH=[
         "../../../thirdparty/harfbuzz/src",
         "../../../thirdparty/icu4c/common/",
+        "../../../thirdparty/icu4c/i18n/",
     ]
 )
 
@@ -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]
 
@@ -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",
@@ -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"])

+ 2 - 2
modules/text_server_adv/text_server_adv.cpp

@@ -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;

+ 2 - 1
modules/text_server_adv/text_server_adv.h

@@ -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>
 
@@ -705,7 +706,7 @@ public:
 
 	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;

+ 20 - 0
modules/text_server_fb/gdextension_build/SConstruct

@@ -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))
@@ -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"])
 

+ 1 - 0
modules/text_server_fb/text_server_fb.h

@@ -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>
 

+ 2 - 2
servers/text/text_server_extension.cpp

@@ -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;
 	}

+ 2 - 2
servers/text/text_server_extension.h

@@ -508,9 +508,9 @@ public:
 	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();

+ 1 - 1
servers/text_server.h

@@ -485,7 +485,7 @@ public:
 	// 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;