summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub2
-rw-r--r--core/extension/gdextension_interface.h136
-rw-r--r--core/input/input_event.cpp2
-rw-r--r--core/io/compression.cpp8
-rw-r--r--core/io/file_access_zip.cpp2
-rw-r--r--core/io/image.cpp26
-rw-r--r--core/io/image.h5
-rw-r--r--core/io/json.cpp8
-rw-r--r--core/io/resource_loader.cpp25
-rw-r--r--core/io/resource_loader.h2
-rw-r--r--core/object/object.cpp8
-rw-r--r--core/object/script_language.cpp10
-rw-r--r--core/object/script_language.h5
-rw-r--r--core/object/script_language_extension.h2
-rw-r--r--core/object/undo_redo.h2
-rw-r--r--core/object/worker_thread_pool.cpp9
-rw-r--r--core/os/os.cpp10
-rw-r--r--core/os/threaded_array_processor.h87
-rw-r--r--core/string/ustring.cpp90
-rw-r--r--core/string/ustring.h1
-rw-r--r--core/variant/callable_bind.cpp22
-rw-r--r--core/variant/callable_bind.h2
-rw-r--r--core/variant/native_ptr.h70
-rw-r--r--core/variant/variant_parser.cpp60
24 files changed, 405 insertions, 189 deletions
diff --git a/core/SCsub b/core/SCsub
index a0176f6c33..7e9cd97351 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -65,7 +65,7 @@ thirdparty_misc_sources = [thirdparty_misc_dir + file for file in thirdparty_mis
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_misc_sources)
# Brotli
-if env["brotli"]:
+if env["brotli"] and env["builtin_brotli"]:
thirdparty_brotli_dir = "#thirdparty/brotli/"
thirdparty_brotli_sources = [
"common/constants.c",
diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h
index 2a328c9a34..4d7bdf9502 100644
--- a/core/extension/gdextension_interface.h
+++ b/core/extension/gdextension_interface.h
@@ -490,6 +490,7 @@ typedef struct {
/**
* @name get_godot_version
+ * @since 4.1
*
* Gets the Godot version that the GDExtension was loaded into.
*
@@ -501,6 +502,7 @@ typedef void (*GDExtensionInterfaceGetGodotVersion)(GDExtensionGodotVersion *r_g
/**
* @name mem_alloc
+ * @since 4.1
*
* Allocates memory.
*
@@ -512,6 +514,7 @@ typedef void *(*GDExtensionInterfaceMemAlloc)(size_t p_bytes);
/**
* @name mem_realloc
+ * @since 4.1
*
* Reallocates memory.
*
@@ -524,6 +527,7 @@ typedef void *(*GDExtensionInterfaceMemRealloc)(void *p_ptr, size_t p_bytes);
/**
* @name mem_free
+ * @since 4.1
*
* Frees memory.
*
@@ -535,6 +539,7 @@ typedef void (*GDExtensionInterfaceMemFree)(void *p_ptr);
/**
* @name print_error
+ * @since 4.1
*
* Logs an error to Godot's built-in debugger and to the OS terminal.
*
@@ -548,6 +553,7 @@ typedef void (*GDExtensionInterfacePrintError)(const char *p_description, const
/**
* @name print_error_with_message
+ * @since 4.1
*
* Logs an error with a message to Godot's built-in debugger and to the OS terminal.
*
@@ -562,6 +568,7 @@ typedef void (*GDExtensionInterfacePrintErrorWithMessage)(const char *p_descript
/**
* @name print_warning
+ * @since 4.1
*
* Logs a warning to Godot's built-in debugger and to the OS terminal.
*
@@ -575,6 +582,7 @@ typedef void (*GDExtensionInterfacePrintWarning)(const char *p_description, cons
/**
* @name print_warning_with_message
+ * @since 4.1
*
* Logs a warning with a message to Godot's built-in debugger and to the OS terminal.
*
@@ -589,6 +597,7 @@ typedef void (*GDExtensionInterfacePrintWarningWithMessage)(const char *p_descri
/**
* @name print_script_error
+ * @since 4.1
*
* Logs a script error to Godot's built-in debugger and to the OS terminal.
*
@@ -602,6 +611,7 @@ typedef void (*GDExtensionInterfacePrintScriptError)(const char *p_description,
/**
* @name print_script_error_with_message
+ * @since 4.1
*
* Logs a script error with a message to Godot's built-in debugger and to the OS terminal.
*
@@ -616,6 +626,7 @@ typedef void (*GDExtensionInterfacePrintScriptErrorWithMessage)(const char *p_de
/**
* @name get_native_struct_size
+ * @since 4.1
*
* Gets the size of a native struct (ex. ObjectID) in bytes.
*
@@ -629,6 +640,7 @@ typedef uint64_t (*GDExtensionInterfaceGetNativeStructSize)(GDExtensionConstStri
/**
* @name variant_new_copy
+ * @since 4.1
*
* Copies one Variant into a another.
*
@@ -639,6 +651,7 @@ typedef void (*GDExtensionInterfaceVariantNewCopy)(GDExtensionUninitializedVaria
/**
* @name variant_new_nil
+ * @since 4.1
*
* Creates a new Variant containing nil.
*
@@ -648,6 +661,7 @@ typedef void (*GDExtensionInterfaceVariantNewNil)(GDExtensionUninitializedVarian
/**
* @name variant_destroy
+ * @since 4.1
*
* Destroys a Variant.
*
@@ -657,6 +671,7 @@ typedef void (*GDExtensionInterfaceVariantDestroy)(GDExtensionVariantPtr p_self)
/**
* @name variant_call
+ * @since 4.1
*
* Calls a method on a Variant.
*
@@ -673,6 +688,7 @@ typedef void (*GDExtensionInterfaceVariantCall)(GDExtensionVariantPtr p_self, GD
/**
* @name variant_call_static
+ * @since 4.1
*
* Calls a static method on a Variant.
*
@@ -689,6 +705,7 @@ typedef void (*GDExtensionInterfaceVariantCallStatic)(GDExtensionVariantType p_t
/**
* @name variant_evaluate
+ * @since 4.1
*
* Evaluate an operator on two Variants.
*
@@ -704,6 +721,7 @@ typedef void (*GDExtensionInterfaceVariantEvaluate)(GDExtensionVariantOperator p
/**
* @name variant_set
+ * @since 4.1
*
* Sets a key on a Variant to a value.
*
@@ -718,6 +736,7 @@ typedef void (*GDExtensionInterfaceVariantSet)(GDExtensionVariantPtr p_self, GDE
/**
* @name variant_set_named
+ * @since 4.1
*
* Sets a named key on a Variant to a value.
*
@@ -732,6 +751,7 @@ typedef void (*GDExtensionInterfaceVariantSetNamed)(GDExtensionVariantPtr p_self
/**
* @name variant_set_keyed
+ * @since 4.1
*
* Sets a keyed property on a Variant to a value.
*
@@ -746,6 +766,7 @@ typedef void (*GDExtensionInterfaceVariantSetKeyed)(GDExtensionVariantPtr p_self
/**
* @name variant_set_indexed
+ * @since 4.1
*
* Sets an index on a Variant to a value.
*
@@ -759,6 +780,7 @@ typedef void (*GDExtensionInterfaceVariantSetIndexed)(GDExtensionVariantPtr p_se
/**
* @name variant_get
+ * @since 4.1
*
* Gets the value of a key from a Variant.
*
@@ -771,6 +793,7 @@ typedef void (*GDExtensionInterfaceVariantGet)(GDExtensionConstVariantPtr p_self
/**
* @name variant_get_named
+ * @since 4.1
*
* Gets the value of a named key from a Variant.
*
@@ -783,6 +806,7 @@ typedef void (*GDExtensionInterfaceVariantGetNamed)(GDExtensionConstVariantPtr p
/**
* @name variant_get_keyed
+ * @since 4.1
*
* Gets the value of a keyed property from a Variant.
*
@@ -795,6 +819,7 @@ typedef void (*GDExtensionInterfaceVariantGetKeyed)(GDExtensionConstVariantPtr p
/**
* @name variant_get_indexed
+ * @since 4.1
*
* Gets the value of an index from a Variant.
*
@@ -808,6 +833,7 @@ typedef void (*GDExtensionInterfaceVariantGetIndexed)(GDExtensionConstVariantPtr
/**
* @name variant_iter_init
+ * @since 4.1
*
* Initializes an iterator over a Variant.
*
@@ -823,6 +849,7 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantIterInit)(GDExtensionConstV
/**
* @name variant_iter_next
+ * @since 4.1
*
* Gets the next value for an iterator over a Variant.
*
@@ -838,6 +865,7 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantIterNext)(GDExtensionConstV
/**
* @name variant_iter_get
+ * @since 4.1
*
* Gets the next value for an iterator over a Variant.
*
@@ -852,6 +880,7 @@ typedef void (*GDExtensionInterfaceVariantIterGet)(GDExtensionConstVariantPtr p_
/**
* @name variant_hash
+ * @since 4.1
*
* Gets the hash of a Variant.
*
@@ -865,6 +894,7 @@ typedef GDExtensionInt (*GDExtensionInterfaceVariantHash)(GDExtensionConstVarian
/**
* @name variant_recursive_hash
+ * @since 4.1
*
* Gets the recursive hash of a Variant.
*
@@ -879,6 +909,7 @@ typedef GDExtensionInt (*GDExtensionInterfaceVariantRecursiveHash)(GDExtensionCo
/**
* @name variant_hash_compare
+ * @since 4.1
*
* Compares two Variants by their hash.
*
@@ -893,6 +924,7 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantHashCompare)(GDExtensionCon
/**
* @name variant_booleanize
+ * @since 4.1
*
* Converts a Variant to a boolean.
*
@@ -904,6 +936,7 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantBooleanize)(GDExtensionCons
/**
* @name variant_duplicate
+ * @since 4.1
*
* Duplicates a Variant.
*
@@ -915,6 +948,7 @@ typedef void (*GDExtensionInterfaceVariantDuplicate)(GDExtensionConstVariantPtr
/**
* @name variant_stringify
+ * @since 4.1
*
* Converts a Variant to a string.
*
@@ -925,6 +959,7 @@ typedef void (*GDExtensionInterfaceVariantStringify)(GDExtensionConstVariantPtr
/**
* @name variant_get_type
+ * @since 4.1
*
* Gets the type of a Variant.
*
@@ -936,6 +971,7 @@ typedef GDExtensionVariantType (*GDExtensionInterfaceVariantGetType)(GDExtension
/**
* @name variant_has_method
+ * @since 4.1
*
* Checks if a Variant has the given method.
*
@@ -948,6 +984,7 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantHasMethod)(GDExtensionConst
/**
* @name variant_has_member
+ * @since 4.1
*
* Checks if a type of Variant has the given member.
*
@@ -960,6 +997,7 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantHasMember)(GDExtensionVaria
/**
* @name variant_has_key
+ * @since 4.1
*
* Checks if a Variant has a key.
*
@@ -973,6 +1011,7 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantHasKey)(GDExtensionConstVar
/**
* @name variant_get_type_name
+ * @since 4.1
*
* Gets the name of a Variant type.
*
@@ -983,6 +1022,7 @@ typedef void (*GDExtensionInterfaceVariantGetTypeName)(GDExtensionVariantType p_
/**
* @name variant_can_convert
+ * @since 4.1
*
* Checks if Variants can be converted from one type to another.
*
@@ -995,6 +1035,7 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantCanConvert)(GDExtensionVari
/**
* @name variant_can_convert_strict
+ * @since 4.1
*
* Checks if Variant can be converted from one type to another using stricter rules.
*
@@ -1007,6 +1048,7 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantCanConvertStrict)(GDExtensi
/**
* @name get_variant_from_type_constructor
+ * @since 4.1
*
* Gets a pointer to a function that can create a Variant of the given type from a raw value.
*
@@ -1018,6 +1060,7 @@ typedef GDExtensionVariantFromTypeConstructorFunc (*GDExtensionInterfaceGetVaria
/**
* @name get_variant_to_type_constructor
+ * @since 4.1
*
* Gets a pointer to a function that can get the raw value from a Variant of the given type.
*
@@ -1029,6 +1072,7 @@ typedef GDExtensionTypeFromVariantConstructorFunc (*GDExtensionInterfaceGetVaria
/**
* @name variant_get_ptr_operator_evaluator
+ * @since 4.1
*
* Gets a pointer to a function that can evaluate the given Variant operator on the given Variant types.
*
@@ -1042,6 +1086,7 @@ typedef GDExtensionPtrOperatorEvaluator (*GDExtensionInterfaceVariantGetPtrOpera
/**
* @name variant_get_ptr_builtin_method
+ * @since 4.1
*
* Gets a pointer to a function that can call a builtin method on a type of Variant.
*
@@ -1055,6 +1100,7 @@ typedef GDExtensionPtrBuiltInMethod (*GDExtensionInterfaceVariantGetPtrBuiltinMe
/**
* @name variant_get_ptr_constructor
+ * @since 4.1
*
* Gets a pointer to a function that can call one of the constructors for a type of Variant.
*
@@ -1067,6 +1113,7 @@ typedef GDExtensionPtrConstructor (*GDExtensionInterfaceVariantGetPtrConstructor
/**
* @name variant_get_ptr_destructor
+ * @since 4.1
*
* Gets a pointer to a function than can call the destructor for a type of Variant.
*
@@ -1078,6 +1125,7 @@ typedef GDExtensionPtrDestructor (*GDExtensionInterfaceVariantGetPtrDestructor)(
/**
* @name variant_construct
+ * @since 4.1
*
* Constructs a Variant of the given type, using the first constructor that matches the given arguments.
*
@@ -1091,6 +1139,7 @@ typedef void (*GDExtensionInterfaceVariantConstruct)(GDExtensionVariantType p_ty
/**
* @name variant_get_ptr_setter
+ * @since 4.1
*
* Gets a pointer to a function that can call a member's setter on the given Variant type.
*
@@ -1103,6 +1152,7 @@ typedef GDExtensionPtrSetter (*GDExtensionInterfaceVariantGetPtrSetter)(GDExtens
/**
* @name variant_get_ptr_getter
+ * @since 4.1
*
* Gets a pointer to a function that can call a member's getter on the given Variant type.
*
@@ -1115,6 +1165,7 @@ typedef GDExtensionPtrGetter (*GDExtensionInterfaceVariantGetPtrGetter)(GDExtens
/**
* @name variant_get_ptr_indexed_setter
+ * @since 4.1
*
* Gets a pointer to a function that can set an index on the given Variant type.
*
@@ -1126,6 +1177,7 @@ typedef GDExtensionPtrIndexedSetter (*GDExtensionInterfaceVariantGetPtrIndexedSe
/**
* @name variant_get_ptr_indexed_getter
+ * @since 4.1
*
* Gets a pointer to a function that can get an index on the given Variant type.
*
@@ -1137,6 +1189,7 @@ typedef GDExtensionPtrIndexedGetter (*GDExtensionInterfaceVariantGetPtrIndexedGe
/**
* @name variant_get_ptr_keyed_setter
+ * @since 4.1
*
* Gets a pointer to a function that can set a key on the given Variant type.
*
@@ -1148,6 +1201,7 @@ typedef GDExtensionPtrKeyedSetter (*GDExtensionInterfaceVariantGetPtrKeyedSetter
/**
* @name variant_get_ptr_keyed_getter
+ * @since 4.1
*
* Gets a pointer to a function that can get a key on the given Variant type.
*
@@ -1159,6 +1213,7 @@ typedef GDExtensionPtrKeyedGetter (*GDExtensionInterfaceVariantGetPtrKeyedGetter
/**
* @name variant_get_ptr_keyed_checker
+ * @since 4.1
*
* Gets a pointer to a function that can check a key on the given Variant type.
*
@@ -1170,6 +1225,7 @@ typedef GDExtensionPtrKeyedChecker (*GDExtensionInterfaceVariantGetPtrKeyedCheck
/**
* @name variant_get_constant_value
+ * @since 4.1
*
* Gets the value of a constant from the given Variant type.
*
@@ -1181,6 +1237,7 @@ typedef void (*GDExtensionInterfaceVariantGetConstantValue)(GDExtensionVariantTy
/**
* @name variant_get_ptr_utility_function
+ * @since 4.1
*
* Gets a pointer to a function that can call a Variant utility function.
*
@@ -1195,6 +1252,7 @@ typedef GDExtensionPtrUtilityFunction (*GDExtensionInterfaceVariantGetPtrUtility
/**
* @name string_new_with_latin1_chars
+ * @since 4.1
*
* Creates a String from a Latin-1 encoded C string.
*
@@ -1205,6 +1263,7 @@ typedef void (*GDExtensionInterfaceStringNewWithLatin1Chars)(GDExtensionUninitia
/**
* @name string_new_with_utf8_chars
+ * @since 4.1
*
* Creates a String from a UTF-8 encoded C string.
*
@@ -1215,6 +1274,7 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf8Chars)(GDExtensionUninitiali
/**
* @name string_new_with_utf16_chars
+ * @since 4.1
*
* Creates a String from a UTF-16 encoded C string.
*
@@ -1225,6 +1285,7 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf16Chars)(GDExtensionUninitial
/**
* @name string_new_with_utf32_chars
+ * @since 4.1
*
* Creates a String from a UTF-32 encoded C string.
*
@@ -1235,6 +1296,7 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf32Chars)(GDExtensionUninitial
/**
* @name string_new_with_wide_chars
+ * @since 4.1
*
* Creates a String from a wide C string.
*
@@ -1245,6 +1307,7 @@ typedef void (*GDExtensionInterfaceStringNewWithWideChars)(GDExtensionUninitiali
/**
* @name string_new_with_latin1_chars_and_len
+ * @since 4.1
*
* Creates a String from a Latin-1 encoded C string with the given length.
*
@@ -1256,6 +1319,7 @@ typedef void (*GDExtensionInterfaceStringNewWithLatin1CharsAndLen)(GDExtensionUn
/**
* @name string_new_with_utf8_chars_and_len
+ * @since 4.1
*
* Creates a String from a UTF-8 encoded C string with the given length.
*
@@ -1267,6 +1331,7 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf8CharsAndLen)(GDExtensionUnin
/**
* @name string_new_with_utf16_chars_and_len
+ * @since 4.1
*
* Creates a String from a UTF-16 encoded C string with the given length.
*
@@ -1278,6 +1343,7 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf16CharsAndLen)(GDExtensionUni
/**
* @name string_new_with_utf32_chars_and_len
+ * @since 4.1
*
* Creates a String from a UTF-32 encoded C string with the given length.
*
@@ -1289,6 +1355,7 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf32CharsAndLen)(GDExtensionUni
/**
* @name string_new_with_wide_chars_and_len
+ * @since 4.1
*
* Creates a String from a wide C string with the given length.
*
@@ -1300,6 +1367,7 @@ typedef void (*GDExtensionInterfaceStringNewWithWideCharsAndLen)(GDExtensionUnin
/**
* @name string_to_latin1_chars
+ * @since 4.1
*
* Converts a String to a Latin-1 encoded C string.
*
@@ -1315,6 +1383,7 @@ typedef GDExtensionInt (*GDExtensionInterfaceStringToLatin1Chars)(GDExtensionCon
/**
* @name string_to_utf8_chars
+ * @since 4.1
*
* Converts a String to a UTF-8 encoded C string.
*
@@ -1330,6 +1399,7 @@ typedef GDExtensionInt (*GDExtensionInterfaceStringToUtf8Chars)(GDExtensionConst
/**
* @name string_to_utf16_chars
+ * @since 4.1
*
* Converts a String to a UTF-16 encoded C string.
*
@@ -1345,6 +1415,7 @@ typedef GDExtensionInt (*GDExtensionInterfaceStringToUtf16Chars)(GDExtensionCons
/**
* @name string_to_utf32_chars
+ * @since 4.1
*
* Converts a String to a UTF-32 encoded C string.
*
@@ -1360,6 +1431,7 @@ typedef GDExtensionInt (*GDExtensionInterfaceStringToUtf32Chars)(GDExtensionCons
/**
* @name string_to_wide_chars
+ * @since 4.1
*
* Converts a String to a wide C string.
*
@@ -1375,6 +1447,7 @@ typedef GDExtensionInt (*GDExtensionInterfaceStringToWideChars)(GDExtensionConst
/**
* @name string_operator_index
+ * @since 4.1
*
* Gets a pointer to the character at the given index from a String.
*
@@ -1387,6 +1460,7 @@ typedef char32_t *(*GDExtensionInterfaceStringOperatorIndex)(GDExtensionStringPt
/**
* @name string_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to the character at the given index from a String.
*
@@ -1399,6 +1473,7 @@ typedef const char32_t *(*GDExtensionInterfaceStringOperatorIndexConst)(GDExtens
/**
* @name string_operator_plus_eq_string
+ * @since 4.1
*
* Appends another String to a String.
*
@@ -1409,6 +1484,7 @@ typedef void (*GDExtensionInterfaceStringOperatorPlusEqString)(GDExtensionString
/**
* @name string_operator_plus_eq_char
+ * @since 4.1
*
* Appends a character to a String.
*
@@ -1419,6 +1495,7 @@ typedef void (*GDExtensionInterfaceStringOperatorPlusEqChar)(GDExtensionStringPt
/**
* @name string_operator_plus_eq_cstr
+ * @since 4.1
*
* Appends a Latin-1 encoded C string to a String.
*
@@ -1429,6 +1506,7 @@ typedef void (*GDExtensionInterfaceStringOperatorPlusEqCstr)(GDExtensionStringPt
/**
* @name string_operator_plus_eq_wcstr
+ * @since 4.1
*
* Appends a wide C string to a String.
*
@@ -1439,6 +1517,7 @@ typedef void (*GDExtensionInterfaceStringOperatorPlusEqWcstr)(GDExtensionStringP
/**
* @name string_operator_plus_eq_c32str
+ * @since 4.1
*
* Appends a UTF-32 encoded C string to a String.
*
@@ -1451,6 +1530,7 @@ typedef void (*GDExtensionInterfaceStringOperatorPlusEqC32str)(GDExtensionString
/**
* @name xml_parser_open_buffer
+ * @since 4.1
*
* Opens a raw XML buffer on an XMLParser instance.
*
@@ -1468,6 +1548,7 @@ typedef GDExtensionInt (*GDExtensionInterfaceXmlParserOpenBuffer)(GDExtensionObj
/**
* @name file_access_store_buffer
+ * @since 4.1
*
* Stores the given buffer using an instance of FileAccess.
*
@@ -1481,6 +1562,7 @@ typedef void (*GDExtensionInterfaceFileAccessStoreBuffer)(GDExtensionObjectPtr p
/**
* @name file_access_get_buffer
+ * @since 4.1
*
* Reads the next p_length bytes into the given buffer using an instance of FileAccess.
*
@@ -1496,6 +1578,7 @@ typedef uint64_t (*GDExtensionInterfaceFileAccessGetBuffer)(GDExtensionConstObje
/**
* @name worker_thread_pool_add_native_group_task
+ * @since 4.1
*
* Adds a group task to an instance of WorkerThreadPool.
*
@@ -1514,6 +1597,7 @@ typedef int64_t (*GDExtensionInterfaceWorkerThreadPoolAddNativeGroupTask)(GDExte
/**
* @name worker_thread_pool_add_native_task
+ * @since 4.1
*
* Adds a task to an instance of WorkerThreadPool.
*
@@ -1531,6 +1615,7 @@ typedef int64_t (*GDExtensionInterfaceWorkerThreadPoolAddNativeTask)(GDExtension
/**
* @name packed_byte_array_operator_index
+ * @since 4.1
*
* Gets a pointer to a byte in a PackedByteArray.
*
@@ -1543,6 +1628,7 @@ typedef uint8_t *(*GDExtensionInterfacePackedByteArrayOperatorIndex)(GDExtension
/**
* @name packed_byte_array_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to a byte in a PackedByteArray.
*
@@ -1555,6 +1641,7 @@ typedef const uint8_t *(*GDExtensionInterfacePackedByteArrayOperatorIndexConst)(
/**
* @name packed_color_array_operator_index
+ * @since 4.1
*
* Gets a pointer to a color in a PackedColorArray.
*
@@ -1567,6 +1654,7 @@ typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndex)(
/**
* @name packed_color_array_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to a color in a PackedColorArray.
*
@@ -1579,6 +1667,7 @@ typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndexCo
/**
* @name packed_float32_array_operator_index
+ * @since 4.1
*
* Gets a pointer to a 32-bit float in a PackedFloat32Array.
*
@@ -1591,6 +1680,7 @@ typedef float *(*GDExtensionInterfacePackedFloat32ArrayOperatorIndex)(GDExtensio
/**
* @name packed_float32_array_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to a 32-bit float in a PackedFloat32Array.
*
@@ -1603,6 +1693,7 @@ typedef const float *(*GDExtensionInterfacePackedFloat32ArrayOperatorIndexConst)
/**
* @name packed_float64_array_operator_index
+ * @since 4.1
*
* Gets a pointer to a 64-bit float in a PackedFloat64Array.
*
@@ -1615,6 +1706,7 @@ typedef double *(*GDExtensionInterfacePackedFloat64ArrayOperatorIndex)(GDExtensi
/**
* @name packed_float64_array_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to a 64-bit float in a PackedFloat64Array.
*
@@ -1627,6 +1719,7 @@ typedef const double *(*GDExtensionInterfacePackedFloat64ArrayOperatorIndexConst
/**
* @name packed_int32_array_operator_index
+ * @since 4.1
*
* Gets a pointer to a 32-bit integer in a PackedInt32Array.
*
@@ -1639,6 +1732,7 @@ typedef int32_t *(*GDExtensionInterfacePackedInt32ArrayOperatorIndex)(GDExtensio
/**
* @name packed_int32_array_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to a 32-bit integer in a PackedInt32Array.
*
@@ -1651,6 +1745,7 @@ typedef const int32_t *(*GDExtensionInterfacePackedInt32ArrayOperatorIndexConst)
/**
* @name packed_int64_array_operator_index
+ * @since 4.1
*
* Gets a pointer to a 64-bit integer in a PackedInt64Array.
*
@@ -1663,6 +1758,7 @@ typedef int64_t *(*GDExtensionInterfacePackedInt64ArrayOperatorIndex)(GDExtensio
/**
* @name packed_int64_array_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to a 64-bit integer in a PackedInt64Array.
*
@@ -1675,6 +1771,7 @@ typedef const int64_t *(*GDExtensionInterfacePackedInt64ArrayOperatorIndexConst)
/**
* @name packed_string_array_operator_index
+ * @since 4.1
*
* Gets a pointer to a string in a PackedStringArray.
*
@@ -1687,6 +1784,7 @@ typedef GDExtensionStringPtr (*GDExtensionInterfacePackedStringArrayOperatorInde
/**
* @name packed_string_array_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to a string in a PackedStringArray.
*
@@ -1699,6 +1797,7 @@ typedef GDExtensionStringPtr (*GDExtensionInterfacePackedStringArrayOperatorInde
/**
* @name packed_vector2_array_operator_index
+ * @since 4.1
*
* Gets a pointer to a Vector2 in a PackedVector2Array.
*
@@ -1711,6 +1810,7 @@ typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector2ArrayOperatorIndex
/**
* @name packed_vector2_array_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to a Vector2 in a PackedVector2Array.
*
@@ -1723,6 +1823,7 @@ typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector2ArrayOperatorIndex
/**
* @name packed_vector3_array_operator_index
+ * @since 4.1
*
* Gets a pointer to a Vector3 in a PackedVector3Array.
*
@@ -1735,6 +1836,7 @@ typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector3ArrayOperatorIndex
/**
* @name packed_vector3_array_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to a Vector3 in a PackedVector3Array.
*
@@ -1747,6 +1849,7 @@ typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector3ArrayOperatorIndex
/**
* @name array_operator_index
+ * @since 4.1
*
* Gets a pointer to a Variant in an Array.
*
@@ -1759,6 +1862,7 @@ typedef GDExtensionVariantPtr (*GDExtensionInterfaceArrayOperatorIndex)(GDExtens
/**
* @name array_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to a Variant in an Array.
*
@@ -1771,6 +1875,7 @@ typedef GDExtensionVariantPtr (*GDExtensionInterfaceArrayOperatorIndexConst)(GDE
/**
* @name array_ref
+ * @since 4.1
*
* Sets an Array to be a reference to another Array object.
*
@@ -1781,6 +1886,7 @@ typedef void (*GDExtensionInterfaceArrayRef)(GDExtensionTypePtr p_self, GDExtens
/**
* @name array_set_typed
+ * @since 4.1
*
* Makes an Array into a typed Array.
*
@@ -1795,6 +1901,7 @@ typedef void (*GDExtensionInterfaceArraySetTyped)(GDExtensionTypePtr p_self, GDE
/**
* @name dictionary_operator_index
+ * @since 4.1
*
* Gets a pointer to a Variant in a Dictionary with the given key.
*
@@ -1807,6 +1914,7 @@ typedef GDExtensionVariantPtr (*GDExtensionInterfaceDictionaryOperatorIndex)(GDE
/**
* @name dictionary_operator_index_const
+ * @since 4.1
*
* Gets a const pointer to a Variant in a Dictionary with the given key.
*
@@ -1821,6 +1929,7 @@ typedef GDExtensionVariantPtr (*GDExtensionInterfaceDictionaryOperatorIndexConst
/**
* @name object_method_bind_call
+ * @since 4.1
*
* Calls a method on an Object.
*
@@ -1835,6 +1944,7 @@ typedef void (*GDExtensionInterfaceObjectMethodBindCall)(GDExtensionMethodBindPt
/**
* @name object_method_bind_ptrcall
+ * @since 4.1
*
* Calls a method on an Object (using a "ptrcall").
*
@@ -1847,6 +1957,7 @@ typedef void (*GDExtensionInterfaceObjectMethodBindPtrcall)(GDExtensionMethodBin
/**
* @name object_destroy
+ * @since 4.1
*
* Destroys an Object.
*
@@ -1856,6 +1967,7 @@ typedef void (*GDExtensionInterfaceObjectDestroy)(GDExtensionObjectPtr p_o);
/**
* @name global_get_singleton
+ * @since 4.1
*
* Gets a global singleton by name.
*
@@ -1867,6 +1979,7 @@ typedef GDExtensionObjectPtr (*GDExtensionInterfaceGlobalGetSingleton)(GDExtensi
/**
* @name object_get_instance_binding
+ * @since 4.1
*
* Gets a pointer representing an Object's instance binding.
*
@@ -1880,6 +1993,7 @@ typedef void *(*GDExtensionInterfaceObjectGetInstanceBinding)(GDExtensionObjectP
/**
* @name object_set_instance_binding
+ * @since 4.1
*
* Sets an Object's instance binding.
*
@@ -1892,6 +2006,7 @@ typedef void (*GDExtensionInterfaceObjectSetInstanceBinding)(GDExtensionObjectPt
/**
* @name object_set_instance
+ * @since 4.1
*
* Sets an extension class instance on a Object.
*
@@ -1903,6 +2018,7 @@ typedef void (*GDExtensionInterfaceObjectSetInstance)(GDExtensionObjectPtr p_o,
/**
* @name object_get_class_name
+ * @since 4.1
*
* Gets the class name of an Object.
*
@@ -1916,6 +2032,7 @@ typedef GDExtensionBool (*GDExtensionInterfaceObjectGetClassName)(GDExtensionCon
/**
* @name object_cast_to
+ * @since 4.1
*
* Casts an Object to a different type.
*
@@ -1928,6 +2045,7 @@ typedef GDExtensionObjectPtr (*GDExtensionInterfaceObjectCastTo)(GDExtensionCons
/**
* @name object_get_instance_from_id
+ * @since 4.1
*
* Gets an Object by its instance ID.
*
@@ -1939,6 +2057,7 @@ typedef GDExtensionObjectPtr (*GDExtensionInterfaceObjectGetInstanceFromId)(GDOb
/**
* @name object_get_instance_id
+ * @since 4.1
*
* Gets the instance ID from an Object.
*
@@ -1952,6 +2071,7 @@ typedef GDObjectInstanceID (*GDExtensionInterfaceObjectGetInstanceId)(GDExtensio
/**
* @name ref_get_object
+ * @since 4.1
*
* Gets the Object from a reference.
*
@@ -1963,6 +2083,7 @@ typedef GDExtensionObjectPtr (*GDExtensionInterfaceRefGetObject)(GDExtensionCons
/**
* @name ref_set_object
+ * @since 4.1
*
* Sets the Object referred to by a reference.
*
@@ -1975,6 +2096,7 @@ typedef void (*GDExtensionInterfaceRefSetObject)(GDExtensionRefPtr p_ref, GDExte
/**
* @name script_instance_create
+ * @since 4.1
*
* Creates a script instance that contains the given info and instance data.
*
@@ -1989,6 +2111,7 @@ typedef GDExtensionScriptInstancePtr (*GDExtensionInterfaceScriptInstanceCreate)
/**
* @name classdb_construct_object
+ * @since 4.1
*
* Constructs an Object of the requested class.
*
@@ -2002,6 +2125,7 @@ typedef GDExtensionObjectPtr (*GDExtensionInterfaceClassdbConstructObject)(GDExt
/**
* @name classdb_get_method_bind
+ * @since 4.1
*
* Gets a pointer to the MethodBind in ClassDB for the given class, method and hash.
*
@@ -2015,6 +2139,7 @@ typedef GDExtensionMethodBindPtr (*GDExtensionInterfaceClassdbGetMethodBind)(GDE
/**
* @name classdb_get_class_tag
+ * @since 4.1
*
* Gets a pointer uniquely identifying the given built-in class in the ClassDB.
*
@@ -2028,6 +2153,7 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa
/**
* @name classdb_register_extension_class
+ * @since 4.1
*
* Registers an extension class in the ClassDB.
*
@@ -2042,6 +2168,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionCla
/**
* @name classdb_register_extension_class_method
+ * @since 4.1
*
* Registers a method on an extension class in the ClassDB.
*
@@ -2055,6 +2182,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassMethod)(GDExtens
/**
* @name classdb_register_extension_class_integer_constant
+ * @since 4.1
*
* Registers an integer constant on an extension class in the ClassDB.
*
@@ -2069,6 +2197,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant)
/**
* @name classdb_register_extension_class_property
+ * @since 4.1
*
* Registers a property on an extension class in the ClassDB.
*
@@ -2084,6 +2213,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassProperty)(GDExte
/**
* @name classdb_register_extension_class_property_group
+ * @since 4.1
*
* Registers a property group on an extension class in the ClassDB.
*
@@ -2096,6 +2226,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup)(G
/**
* @name classdb_register_extension_class_property_subgroup
+ * @since 4.1
*
* Registers a property subgroup on an extension class in the ClassDB.
*
@@ -2108,6 +2239,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup
/**
* @name classdb_register_extension_class_signal
+ * @since 4.1
*
* Registers a signal on an extension class in the ClassDB.
*
@@ -2123,6 +2255,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassSignal)(GDExtens
/**
* @name classdb_unregister_extension_class
+ * @since 4.1
*
* Unregisters an extension class in the ClassDB.
*
@@ -2133,6 +2266,7 @@ typedef void (*GDExtensionInterfaceClassdbUnregisterExtensionClass)(GDExtensionC
/**
* @name get_library_path
+ * @since 4.1
*
* Gets the path to the current GDExtension library.
*
@@ -2143,6 +2277,7 @@ typedef void (*GDExtensionInterfaceGetLibraryPath)(GDExtensionClassLibraryPtr p_
/**
* @name editor_add_plugin
+ * @since 4.1
*
* Adds an editor plugin.
*
@@ -2154,6 +2289,7 @@ typedef void (*GDExtensionInterfaceEditorAddPlugin)(GDExtensionConstStringNamePt
/**
* @name editor_remove_plugin
+ * @since 4.1
*
* Removes an editor plugin.
*
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index e547b04d0b..e37886cbe9 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -1192,7 +1192,7 @@ static const char *_joy_button_descriptions[(size_t)JoyButton::SDL_MAX] = {
TTRC("Top Action, Sony Triangle, Xbox Y, Nintendo X"),
TTRC("Back, Sony Select, Xbox Back, Nintendo -"),
TTRC("Guide, Sony PS, Xbox Home"),
- TTRC("Start, Nintendo +"),
+ TTRC("Start, Xbox Menu, Nintendo +"),
TTRC("Left Stick, Sony L3, Xbox L/LS"),
TTRC("Right Stick, Sony R3, Xbox R/RS"),
TTRC("Left Shoulder, Sony L1, Xbox LB"),
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index ac4a637597..e36fb0afa4 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -35,13 +35,13 @@
#include "thirdparty/misc/fastlz.h"
-#ifdef BROTLI_ENABLED
-#include "thirdparty/brotli/include/brotli/decode.h"
-#endif
-
#include <zlib.h>
#include <zstd.h>
+#ifdef BROTLI_ENABLED
+#include <brotli/decode.h>
+#endif
+
int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode) {
switch (p_mode) {
case MODE_BROTLI: {
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index 064353476f..c7f1a73f97 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -47,7 +47,7 @@ static void *godot_open(voidpf opaque, const char *p_fname, int mode) {
return nullptr;
}
- Ref<FileAccess> f = FileAccess::open(p_fname, FileAccess::READ);
+ Ref<FileAccess> f = FileAccess::open(String::utf8(p_fname), FileAccess::READ);
ERR_FAIL_COND_V(f.is_null(), nullptr);
ZipData *zd = memnew(ZipData);
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 9bb987b670..1711e4c265 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -3004,6 +3004,7 @@ ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr;
+ScalableImageMemLoadFunc Image::_svg_scalable_mem_loader_func = nullptr;
void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr;
@@ -3476,6 +3477,9 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_tga_from_buffer", "buffer"), &Image::load_tga_from_buffer);
ClassDB::bind_method(D_METHOD("load_bmp_from_buffer", "buffer"), &Image::load_bmp_from_buffer);
+ ClassDB::bind_method(D_METHOD("load_svg_from_buffer", "buffer", "scale"), &Image::load_svg_from_buffer, DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("load_svg_from_string", "svg_str", "scale"), &Image::load_svg_from_string, DEFVAL(1.0));
+
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data");
BIND_CONSTANT(MAX_WIDTH);
@@ -3825,6 +3829,28 @@ Error Image::load_bmp_from_buffer(const Vector<uint8_t> &p_array) {
return _load_from_buffer(p_array, _bmp_mem_loader_func);
}
+Error Image::load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale) {
+ ERR_FAIL_NULL_V_MSG(
+ _svg_scalable_mem_loader_func,
+ ERR_UNAVAILABLE,
+ "The SVG module isn't enabled. Recompile the Godot editor or export template binary with the `module_svg_enabled=yes` SCons option.");
+
+ int buffer_size = p_array.size();
+
+ ERR_FAIL_COND_V(buffer_size == 0, ERR_INVALID_PARAMETER);
+
+ Ref<Image> image = _svg_scalable_mem_loader_func(p_array.ptr(), buffer_size, scale);
+ ERR_FAIL_COND_V(!image.is_valid(), ERR_PARSE_ERROR);
+
+ copy_internals_from(image);
+
+ return OK;
+}
+
+Error Image::load_svg_from_string(const String &p_svg_str, float scale) {
+ return load_svg_from_buffer(p_svg_str.to_utf8_buffer(), scale);
+}
+
void Image::convert_rg_to_ra_rgba8() {
ERR_FAIL_COND(format != FORMAT_RGBA8);
ERR_FAIL_COND(!data.size());
diff --git a/core/io/image.h b/core/io/image.h
index 8e353a8bb7..f877b00ee6 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -48,6 +48,7 @@ typedef Vector<uint8_t> (*SavePNGBufferFunc)(const Ref<Image> &p_img);
typedef Error (*SaveJPGFunc)(const String &p_path, const Ref<Image> &p_img, float p_quality);
typedef Vector<uint8_t> (*SaveJPGBufferFunc)(const Ref<Image> &p_img, float p_quality);
typedef Ref<Image> (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size);
+typedef Ref<Image> (*ScalableImageMemLoadFunc)(const uint8_t *p_data, int p_size, float p_scale);
typedef Error (*SaveWebPFunc)(const String &p_path, const Ref<Image> &p_img, const bool p_lossy, const float p_quality);
typedef Vector<uint8_t> (*SaveWebPBufferFunc)(const Ref<Image> &p_img, const bool p_lossy, const float p_quality);
@@ -148,6 +149,7 @@ public:
static ImageMemLoadFunc _webp_mem_loader_func;
static ImageMemLoadFunc _tga_mem_loader_func;
static ImageMemLoadFunc _bmp_mem_loader_func;
+ static ScalableImageMemLoadFunc _svg_scalable_mem_loader_func;
static void (*_image_compress_bc_func)(Image *, UsedChannels p_channels);
static void (*_image_compress_bptc_func)(Image *, UsedChannels p_channels);
@@ -401,6 +403,9 @@ public:
Error load_tga_from_buffer(const Vector<uint8_t> &p_array);
Error load_bmp_from_buffer(const Vector<uint8_t> &p_array);
+ Error load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale = 1.0);
+ Error load_svg_from_string(const String &p_svg_str, float scale = 1.0);
+
void convert_rg_to_ra_rgba8();
void convert_ra_rgba8_to_rg();
void convert_rgba8_to_bgra8();
diff --git a/core/io/json.cpp b/core/io/json.cpp
index a6e054a9fe..496400a5ea 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -299,9 +299,15 @@ Error JSON::_get_token(const char32_t *p_str, int &index, int p_len, Token &r_to
}
} break;
- default: {
+ case '"':
+ case '\\':
+ case '/': {
res = next;
} break;
+ default: {
+ r_err_str = "Invalid escape sequence.";
+ return ERR_PARSE_ERROR;
+ }
}
str += res;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 525c41cf87..1fe662b1fa 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -239,15 +239,15 @@ ResourceLoader::LoadToken::~LoadToken() {
Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress) {
load_nesting++;
- if (load_paths_stack.size()) {
+ if (load_paths_stack->size()) {
thread_load_mutex.lock();
- HashMap<String, ThreadLoadTask>::Iterator E = thread_load_tasks.find(load_paths_stack[load_paths_stack.size() - 1]);
+ HashMap<String, ThreadLoadTask>::Iterator E = thread_load_tasks.find(load_paths_stack->get(load_paths_stack->size() - 1));
if (E) {
E->value.sub_tasks.insert(p_path);
}
thread_load_mutex.unlock();
}
- load_paths_stack.push_back(p_path);
+ load_paths_stack->push_back(p_path);
// Try all loaders and pick the first match for the type hint
bool found = false;
@@ -263,7 +263,7 @@ Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_origin
}
}
- load_paths_stack.resize(load_paths_stack.size() - 1);
+ load_paths_stack->resize(load_paths_stack->size() - 1);
load_nesting--;
if (!res.is_null()) {
@@ -296,8 +296,10 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
// Thread-safe either if it's the current thread or a brand new one.
CallQueue *mq_override = nullptr;
if (load_nesting == 0) {
+ load_paths_stack = memnew(Vector<String>);
+
if (!load_task.dependent_path.is_empty()) {
- load_paths_stack.push_back(load_task.dependent_path);
+ load_paths_stack->push_back(load_task.dependent_path);
}
if (!Thread::is_main_thread()) {
mq_override = memnew(CallQueue);
@@ -309,6 +311,10 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
}
// --
+ if (!Thread::is_main_thread()) {
+ set_current_thread_safe_for_nodes(true);
+ }
+
Ref<Resource> res = _load(load_task.remapped_path, load_task.remapped_path != load_task.local_path ? load_task.local_path : String(), load_task.type_hint, load_task.cache_mode, &load_task.error, load_task.use_sub_threads, &load_task.progress);
if (mq_override) {
mq_override->flush();
@@ -356,8 +362,11 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
thread_load_mutex.unlock();
- if (load_nesting == 0 && mq_override) {
- memdelete(mq_override);
+ if (load_nesting == 0) {
+ if (mq_override) {
+ memdelete(mq_override);
+ }
+ memdelete(load_paths_stack);
}
}
@@ -1166,7 +1175,7 @@ bool ResourceLoader::timestamp_on_load = false;
thread_local int ResourceLoader::load_nesting = 0;
thread_local WorkerThreadPool::TaskID ResourceLoader::caller_task_id = 0;
-thread_local Vector<String> ResourceLoader::load_paths_stack;
+thread_local Vector<String> *ResourceLoader::load_paths_stack;
template <>
thread_local uint32_t SafeBinaryMutex<ResourceLoader::BINARY_MUTEX_TAG>::count = 0;
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 592befb603..2701caa3f4 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -182,7 +182,7 @@ private:
static thread_local int load_nesting;
static thread_local WorkerThreadPool::TaskID caller_task_id;
- static thread_local Vector<String> load_paths_stack;
+ static thread_local Vector<String> *load_paths_stack; // A pointer to avoid broken TLS implementations from double-running the destructor.
static SafeBinaryMutex<BINARY_MUTEX_TAG> thread_load_mutex;
static HashMap<String, ThreadLoadTask> thread_load_tasks;
static bool cleaning_tasks;
diff --git a/core/object/object.cpp b/core/object/object.cpp
index c76188a2cd..4d19a2c75b 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -836,14 +836,16 @@ void Object::set_script(const Variant &p_script) {
return;
}
+ Ref<Script> s = p_script;
+ ERR_FAIL_COND_MSG(s.is_null() && !p_script.is_null(), "Invalid parameter, it should be a reference to a valid script (or null).");
+
+ script = p_script;
+
if (script_instance) {
memdelete(script_instance);
script_instance = nullptr;
}
- script = p_script;
- Ref<Script> s = script;
-
if (!s.is_null()) {
if (s->can_instantiate()) {
OBJ_DEBUG_LOCK
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 6f047d80aa..a8b0e426ae 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -42,7 +42,7 @@ int ScriptServer::_language_count = 0;
bool ScriptServer::scripting_enabled = true;
bool ScriptServer::reload_scripts_on_save = false;
-bool ScriptServer::languages_finished = false;
+SafeFlag ScriptServer::languages_finished; // Used until GH-76581 is fixed properly.
ScriptEditRequestFunction ScriptServer::edit_request_func = nullptr;
void Script::_notification(int p_what) {
@@ -228,7 +228,7 @@ void ScriptServer::finish_languages() {
_languages[i]->finish();
}
global_classes_clear();
- languages_finished = true;
+ languages_finished.set();
}
void ScriptServer::set_reload_scripts_on_save(bool p_enable) {
@@ -240,12 +240,18 @@ bool ScriptServer::is_reload_scripts_on_save_enabled() {
}
void ScriptServer::thread_enter() {
+ if (!languages_finished.is_set()) {
+ return;
+ }
for (int i = 0; i < _language_count; i++) {
_languages[i]->thread_enter();
}
}
void ScriptServer::thread_exit() {
+ if (!languages_finished.is_set()) {
+ return;
+ }
for (int i = 0; i < _language_count; i++) {
_languages[i]->thread_exit();
}
diff --git a/core/object/script_language.h b/core/object/script_language.h
index c22890e30a..2b685c77a3 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -35,6 +35,7 @@
#include "core/io/resource.h"
#include "core/templates/pair.h"
#include "core/templates/rb_map.h"
+#include "core/templates/safe_refcount.h"
#include "core/variant/typed_array.h"
class ScriptLanguage;
@@ -52,7 +53,7 @@ class ScriptServer {
static int _language_count;
static bool scripting_enabled;
static bool reload_scripts_on_save;
- static bool languages_finished;
+ static SafeFlag languages_finished; // Used until GH-76581 is fixed properly.
struct GlobalScriptClass {
StringName language;
@@ -97,7 +98,7 @@ public:
static void init_languages();
static void finish_languages();
- static bool are_languages_finished() { return languages_finished; }
+ static bool are_languages_finished() { return languages_finished.is_set(); }
};
class ScriptInstance;
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index 79cf712119..1a0ec29479 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -651,7 +651,7 @@ public:
#ifdef TOOLS_ENABLED
Ref<Script> script = get_script();
- if (script->is_valid() && pcount > 0) {
+ if (script.is_valid() && pcount > 0) {
p_list->push_back(script->get_class_category());
}
#endif // TOOLS_ENABLED
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index 2ee17867f2..389d8714f7 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -58,7 +58,7 @@ private:
TYPE_REFERENCE
} type;
- bool force_keep_in_merge_ends;
+ bool force_keep_in_merge_ends = false;
Ref<RefCounted> ref;
ObjectID object;
StringName name;
diff --git a/core/object/worker_thread_pool.cpp b/core/object/worker_thread_pool.cpp
index d285be3e70..5ec3e1a1a8 100644
--- a/core/object/worker_thread_pool.cpp
+++ b/core/object/worker_thread_pool.cpp
@@ -56,6 +56,8 @@ void WorkerThreadPool::_process_task(Task *p_task) {
Task *prev_low_prio_task = nullptr; // In case this is recursively called.
if (!use_native_low_priority_threads) {
+ // Tasks must start with this unset. They are free to set-and-forget otherwise.
+ set_current_thread_safe_for_nodes(false);
pool_thread_index = thread_ids[Thread::get_caller_id()];
ThreadData &curr_thread = threads[pool_thread_index];
task_mutex.lock();
@@ -179,9 +181,6 @@ void WorkerThreadPool::_process_task(Task *p_task) {
if (post) {
task_available_semaphore.post();
}
-
- // Engine/user tasks can set-and-forget, so we must be sure it's back to normal by the end of the task.
- set_current_thread_safe_for_nodes(false);
}
}
@@ -371,7 +370,9 @@ Error WorkerThreadPool::wait_for_task_completion(TaskID p_task_id) {
must_exit = true;
} else {
// Solve tasks while they are around.
+ bool safe_for_nodes_backup = is_current_thread_safe_for_nodes();
_process_task_queue();
+ set_current_thread_safe_for_nodes(safe_for_nodes_backup);
continue;
}
} else if (!use_native_low_priority_threads && task->low_priority) {
@@ -415,7 +416,7 @@ Error WorkerThreadPool::wait_for_task_completion(TaskID p_task_id) {
WorkerThreadPool::GroupID WorkerThreadPool::_add_group_task(const Callable &p_callable, void (*p_func)(void *, uint32_t), void *p_userdata, BaseTemplateUserdata *p_template_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description) {
ERR_FAIL_COND_V(p_elements < 0, INVALID_TASK_ID);
if (p_tasks < 0) {
- p_tasks = threads.size();
+ p_tasks = MAX(1u, threads.size());
}
task_mutex.lock();
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 5704ef7a40..67423128a3 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -295,12 +295,14 @@ Error OS::shell_open(String p_uri) {
}
Error OS::shell_show_in_file_manager(String p_path, bool p_open_folder) {
- if (!p_path.begins_with("file://")) {
- p_path = String("file://") + p_path;
- }
- if (!p_path.ends_with("/")) {
+ p_path = p_path.trim_prefix("file://");
+
+ if (!DirAccess::dir_exists_absolute(p_path)) {
p_path = p_path.get_base_dir();
}
+
+ p_path = String("file://") + p_path;
+
return shell_open(p_path);
}
// implement these with the canvas?
diff --git a/core/os/threaded_array_processor.h b/core/os/threaded_array_processor.h
deleted file mode 100644
index 34b417ae57..0000000000
--- a/core/os/threaded_array_processor.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/**************************************************************************/
-/* threaded_array_processor.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 THREADED_ARRAY_PROCESSOR_H
-#define THREADED_ARRAY_PROCESSOR_H
-
-#include "core/os/os.h"
-#include "core/os/thread.h"
-#include "core/os/thread_safe.h"
-#include "core/templates/safe_refcount.h"
-
-template <class C, class U>
-struct ThreadArrayProcessData {
- uint32_t elements;
- SafeNumeric<uint32_t> index;
- C *instance;
- U userdata;
- void (C::*method)(uint32_t, U);
-
- void process(uint32_t p_index) {
- (instance->*method)(p_index, userdata);
- }
-};
-
-template <class T>
-void process_array_thread(void *ud) {
- T &data = *(T *)ud;
- while (true) {
- uint32_t index = data.index.increment();
- if (index >= data.elements) {
- break;
- }
- data.process(index);
- }
-}
-
-template <class C, class M, class U>
-void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
- ThreadArrayProcessData<C, U> data;
- data.method = p_method;
- data.instance = p_instance;
- data.userdata = p_userdata;
- data.index.set(0);
- data.elements = p_elements;
- data.process(0); //process first, let threads increment for next
-
- int thread_count = OS::get_singleton()->get_processor_count();
- Thread *threads = memnew_arr(Thread, thread_count);
-
- for (int i = 0; i < thread_count; i++) {
- threads[i].start(process_array_thread<ThreadArrayProcessData<C, U>>, &data);
- }
-
- for (int i = 0; i < thread_count; i++) {
- threads[i].wait_to_finish();
- }
- memdelete_arr(threads);
-}
-
-#endif // THREADED_ARRAY_PROCESSOR_H
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index c276f20f99..12e6423724 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -62,6 +62,7 @@ static _FORCE_INLINE_ char32_t lower_case(char32_t c) {
const char CharString::_null = 0;
const char16_t Char16String::_null = 0;
const char32_t String::_null = 0;
+const char32_t String::_replacement_char = 0xfffd;
bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end) {
const String &s = p_s;
@@ -307,7 +308,7 @@ void String::copy_from(const char *p_cstr) {
uint8_t c = p_cstr[i] >= 0 ? p_cstr[i] : uint8_t(256 + p_cstr[i]);
if (c == 0 && i < len) {
print_unicode_error("NUL character", true);
- dst[i] = 0x20;
+ dst[i] = _replacement_char;
} else {
dst[i] = c;
}
@@ -340,7 +341,7 @@ void String::copy_from(const char *p_cstr, const int p_clip_to) {
uint8_t c = p_cstr[i] >= 0 ? p_cstr[i] : uint8_t(256 + p_cstr[i]);
if (c == 0) {
print_unicode_error("NUL character", true);
- dst[i] = 0x20;
+ dst[i] = _replacement_char;
} else {
dst[i] = c;
}
@@ -373,17 +374,21 @@ void String::copy_from(const char32_t &p_char) {
print_unicode_error("NUL character", true);
return;
}
+
+ resize(2);
+
+ char32_t *dst = ptrw();
+
if ((p_char & 0xfffff800) == 0xd800) {
print_unicode_error(vformat("Unpaired surrogate (%x)", (uint32_t)p_char));
- }
- if (p_char > 0x10ffff) {
+ dst[0] = _replacement_char;
+ } else if (p_char > 0x10ffff) {
print_unicode_error(vformat("Invalid unicode codepoint (%x)", (uint32_t)p_char));
+ dst[0] = _replacement_char;
+ } else {
+ dst[0] = p_char;
}
- resize(2);
-
- char32_t *dst = ptrw();
- dst[0] = p_char;
dst[1] = 0;
}
@@ -439,14 +444,18 @@ void String::copy_from_unchecked(const char32_t *p_char, const int p_length) {
for (int i = 0; i < p_length; i++) {
if (p_char[i] == 0) {
print_unicode_error("NUL character", true);
- dst[i] = 0x20;
+ dst[i] = _replacement_char;
continue;
}
if ((p_char[i] & 0xfffff800) == 0xd800) {
print_unicode_error(vformat("Unpaired surrogate (%x)", (uint32_t)p_char[i]));
+ dst[i] = _replacement_char;
+ continue;
}
if (p_char[i] > 0x10ffff) {
print_unicode_error(vformat("Invalid unicode codepoint (%x)", (uint32_t)p_char[i]));
+ dst[i] = _replacement_char;
+ continue;
}
dst[i] = p_char[i];
}
@@ -538,7 +547,7 @@ String &String::operator+=(const char *p_str) {
uint8_t c = p_str[i] >= 0 ? p_str[i] : uint8_t(256 + p_str[i]);
if (c == 0 && i < rhs_len) {
print_unicode_error("NUL character", true);
- dst[i] = 0x20;
+ dst[i] = _replacement_char;
} else {
dst[i] = c;
}
@@ -568,17 +577,21 @@ String &String::operator+=(char32_t p_char) {
print_unicode_error("NUL character", true);
return *this;
}
+
+ const int lhs_len = length();
+ resize(lhs_len + 2);
+ char32_t *dst = ptrw();
+
if ((p_char & 0xfffff800) == 0xd800) {
print_unicode_error(vformat("Unpaired surrogate (%x)", (uint32_t)p_char));
- }
- if (p_char > 0x10ffff) {
+ dst[lhs_len] = _replacement_char;
+ } else if (p_char > 0x10ffff) {
print_unicode_error(vformat("Invalid unicode codepoint (%x)", (uint32_t)p_char));
+ dst[lhs_len] = _replacement_char;
+ } else {
+ dst[lhs_len] = p_char;
}
- const int lhs_len = length();
- resize(lhs_len + 2);
- char32_t *dst = ptrw();
- dst[lhs_len] = p_char;
dst[lhs_len + 1] = 0;
return *this;
@@ -1737,7 +1750,7 @@ Vector<uint8_t> String::hex_decode() const {
void String::print_unicode_error(const String &p_message, bool p_critical) const {
if (p_critical) {
- print_error(vformat("Unicode parsing error, some characters were replaced with spaces: %s", p_message));
+ print_error(vformat("Unicode parsing error, some characters were replaced with � (U+FFFD): %s", p_message));
} else {
print_error(vformat("Unicode parsing error: %s", p_message));
}
@@ -1757,7 +1770,7 @@ CharString String::ascii(bool p_allow_extended) const {
cs[i] = c;
} else {
print_unicode_error(vformat("Invalid unicode codepoint (%x), cannot represent as ASCII/Latin-1", (uint32_t)c));
- cs[i] = 0x20;
+ cs[i] = 0x20; // ascii doesn't have a replacement character like unicode, 0x1a is sometimes used but is kinda arcane
}
}
@@ -1897,13 +1910,13 @@ Error String::parse_utf8(const char *p_utf8, int p_len, bool p_skip_cr) {
unichar = (0xff >> 7) & c;
skip = 5;
} else {
- *(dst++) = 0x20;
+ *(dst++) = _replacement_char;
unichar = 0;
skip = 0;
}
} else {
if (c < 0x80 || c > 0xbf) {
- *(dst++) = 0x20;
+ *(dst++) = _replacement_char;
skip = 0;
} else {
unichar = (unichar << 6) | (c & 0x3f);
@@ -1912,15 +1925,15 @@ Error String::parse_utf8(const char *p_utf8, int p_len, bool p_skip_cr) {
if (unichar == 0) {
print_unicode_error("NUL character", true);
decode_failed = true;
- unichar = 0x20;
- }
- if ((unichar & 0xfffff800) == 0xd800) {
- print_unicode_error(vformat("Unpaired surrogate (%x)", unichar));
- decode_error = true;
- }
- if (unichar > 0x10ffff) {
- print_unicode_error(vformat("Invalid unicode codepoint (%x)", unichar));
- decode_error = true;
+ unichar = _replacement_char;
+ } else if ((unichar & 0xfffff800) == 0xd800) {
+ print_unicode_error(vformat("Unpaired surrogate (%x)", unichar), true);
+ decode_failed = true;
+ unichar = _replacement_char;
+ } else if (unichar > 0x10ffff) {
+ print_unicode_error(vformat("Invalid unicode codepoint (%x)", unichar), true);
+ decode_failed = true;
+ unichar = _replacement_char;
}
*(dst++) = unichar;
}
@@ -2014,7 +2027,11 @@ CharString String::utf8() const {
APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Lower lower middle 6 bits.
APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits.
} else {
- APPEND_CHAR(0x20);
+ // the string is a valid UTF32, so it should never happen ...
+ print_unicode_error(vformat("Non scalar value (%x)", c), true);
+ APPEND_CHAR(uint32_t(0xe0 | ((_replacement_char >> 12) & 0x0f))); // Top 4 bits.
+ APPEND_CHAR(uint32_t(0x80 | ((_replacement_char >> 6) & 0x3f))); // Middle 6 bits.
+ APPEND_CHAR(uint32_t(0x80 | (_replacement_char & 0x3f))); // Bottom 6 bits.
}
}
#undef APPEND_CHAR
@@ -2187,7 +2204,9 @@ Char16String String::utf16() const {
APPEND_CHAR(uint32_t((c >> 10) + 0xd7c0)); // lead surrogate.
APPEND_CHAR(uint32_t((c & 0x3ff) | 0xdc00)); // trail surrogate.
} else {
- APPEND_CHAR(0x20);
+ // the string is a valid UTF32, so it should never happen ...
+ APPEND_CHAR(uint32_t((_replacement_char >> 10) + 0xd7c0));
+ APPEND_CHAR(uint32_t((_replacement_char & 0x3ff) | 0xdc00));
}
}
#undef APPEND_CHAR
@@ -4262,12 +4281,13 @@ String String::pad_zeros(int p_digits) const {
begin++;
}
- if (begin >= end) {
+ int zeros_to_add = p_digits - (end - begin);
+
+ if (zeros_to_add <= 0) {
return s;
+ } else {
+ return s.insert(begin, String("0").repeat(zeros_to_add));
}
-
- int zeros_to_add = p_digits - (end - begin);
- return s.insert(begin, String("0").repeat(zeros_to_add));
}
String String::trim_prefix(const String &p_prefix) const {
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 782ca47507..295625395d 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -183,6 +183,7 @@ struct StrRange {
class String {
CowData<char32_t> _cowdata;
static const char32_t _null;
+ static const char32_t _replacement_char;
void copy_from(const char *p_cstr);
void copy_from(const char *p_cstr, const int p_clip_to);
diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp
index 378d1ff618..e493e50467 100644
--- a/core/variant/callable_bind.cpp
+++ b/core/variant/callable_bind.cpp
@@ -144,6 +144,18 @@ void CallableCustomBind::call(const Variant **p_arguments, int p_argcount, Varia
callable.callp(args, p_argcount + binds.size(), r_return_value, r_call_error);
}
+Error CallableCustomBind::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
+ const Variant **args = (const Variant **)alloca(sizeof(const Variant **) * (binds.size() + p_argcount));
+ for (int i = 0; i < p_argcount; i++) {
+ args[i] = (const Variant *)p_arguments[i];
+ }
+ for (int i = 0; i < binds.size(); i++) {
+ args[i + p_argcount] = (const Variant *)&binds[i];
+ }
+
+ return callable.rpcp(p_peer_id, args, p_argcount + binds.size(), r_call_error);
+}
+
CallableCustomBind::CallableCustomBind(const Callable &p_callable, const Vector<Variant> &p_binds) {
callable = p_callable;
binds = p_binds;
@@ -242,6 +254,16 @@ void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Var
callable.callp(p_arguments, p_argcount - argcount, r_return_value, r_call_error);
}
+Error CallableCustomUnbind::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
+ if (argcount > p_argcount) {
+ r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_call_error.argument = 0;
+ r_call_error.expected = argcount;
+ return ERR_UNCONFIGURED;
+ }
+ return callable.rpcp(p_peer_id, p_arguments, p_argcount - argcount, r_call_error);
+}
+
CallableCustomUnbind::CallableCustomUnbind(const Callable &p_callable, int p_argcount) {
callable = p_callable;
argcount = p_argcount;
diff --git a/core/variant/callable_bind.h b/core/variant/callable_bind.h
index b51076ad0f..5798797a3d 100644
--- a/core/variant/callable_bind.h
+++ b/core/variant/callable_bind.h
@@ -51,6 +51,7 @@ public:
virtual StringName get_method() const override;
virtual ObjectID get_object() const override;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
+ virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override;
virtual int get_bound_arguments_count() const override;
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
@@ -78,6 +79,7 @@ public:
virtual StringName get_method() const override;
virtual ObjectID get_object() const override;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
+ virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override;
virtual int get_bound_arguments_count() const override;
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
diff --git a/core/variant/native_ptr.h b/core/variant/native_ptr.h
index ea811daabf..9199b12845 100644
--- a/core/variant/native_ptr.h
+++ b/core/variant/native_ptr.h
@@ -53,36 +53,46 @@ struct GDExtensionPtr {
operator Variant() const { return uint64_t(data); }
};
-#define GDVIRTUAL_NATIVE_PTR(m_type) \
- template <> \
- struct GDExtensionConstPtr<const m_type> { \
- const m_type *data = nullptr; \
- GDExtensionConstPtr() {} \
- GDExtensionConstPtr(const m_type *p_assign) { data = p_assign; } \
- static const char *get_name() { return "const " #m_type; } \
- operator const m_type *() const { return data; } \
- operator Variant() const { return uint64_t(data); } \
- }; \
- template <> \
- struct VariantCaster<GDExtensionConstPtr<const m_type>> { \
- static _FORCE_INLINE_ GDExtensionConstPtr<const m_type> cast(const Variant &p_variant) { \
- return GDExtensionConstPtr<const m_type>((const m_type *)p_variant.operator uint64_t()); \
- } \
- }; \
- template <> \
- struct GDExtensionPtr<m_type> { \
- m_type *data = nullptr; \
- GDExtensionPtr() {} \
- GDExtensionPtr(m_type *p_assign) { data = p_assign; } \
- static const char *get_name() { return #m_type; } \
- operator m_type *() const { return data; } \
- operator Variant() const { return uint64_t(data); } \
- }; \
- template <> \
- struct VariantCaster<GDExtensionPtr<m_type>> { \
- static _FORCE_INLINE_ GDExtensionPtr<m_type> cast(const Variant &p_variant) { \
- return GDExtensionPtr<m_type>((m_type *)p_variant.operator uint64_t()); \
- } \
+#define GDVIRTUAL_NATIVE_PTR(m_type) \
+ template <> \
+ struct GDExtensionConstPtr<const m_type> { \
+ const m_type *data = nullptr; \
+ GDExtensionConstPtr() {} \
+ GDExtensionConstPtr(const m_type *p_assign) { data = p_assign; } \
+ static const char *get_name() { return "const " #m_type; } \
+ operator const m_type *() const { return data; } \
+ operator Variant() const { return uint64_t(data); } \
+ }; \
+ template <> \
+ struct VariantCaster<GDExtensionConstPtr<const m_type>> { \
+ static _FORCE_INLINE_ GDExtensionConstPtr<const m_type> cast(const Variant &p_variant) { \
+ return GDExtensionConstPtr<const m_type>((const m_type *)p_variant.operator uint64_t()); \
+ } \
+ }; \
+ template <> \
+ struct VariantInternalAccessor<GDExtensionConstPtr<const m_type>> { \
+ static _FORCE_INLINE_ const GDExtensionConstPtr<const m_type> &get(const Variant *v) { return *reinterpret_cast<const GDExtensionConstPtr<const m_type> *>(VariantInternal::get_int(v)); } \
+ static _FORCE_INLINE_ void set(Variant *v, const GDExtensionConstPtr<const m_type> &p_value) { *VariantInternal::get_int(v) = uint64_t(p_value.data); } \
+ }; \
+ template <> \
+ struct GDExtensionPtr<m_type> { \
+ m_type *data = nullptr; \
+ GDExtensionPtr() {} \
+ GDExtensionPtr(m_type *p_assign) { data = p_assign; } \
+ static const char *get_name() { return #m_type; } \
+ operator m_type *() const { return data; } \
+ operator Variant() const { return uint64_t(data); } \
+ }; \
+ template <> \
+ struct VariantCaster<GDExtensionPtr<m_type>> { \
+ static _FORCE_INLINE_ GDExtensionPtr<m_type> cast(const Variant &p_variant) { \
+ return GDExtensionPtr<m_type>((m_type *)p_variant.operator uint64_t()); \
+ } \
+ }; \
+ template <> \
+ struct VariantInternalAccessor<GDExtensionPtr<m_type>> { \
+ static _FORCE_INLINE_ const GDExtensionPtr<m_type> &get(const Variant *v) { return *reinterpret_cast<const GDExtensionPtr<m_type> *>(VariantInternal::get_int(v)); } \
+ static _FORCE_INLINE_ void set(Variant *v, const GDExtensionPtr<m_type> &p_value) { *VariantInternal::get_int(v) = uint64_t(p_value.data); } \
};
template <class T>
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index a40fcfbd47..3320750994 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -865,12 +865,46 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
get_token(p_stream, token, line, r_err_str);
- if (token.type != TK_NUMBER) {
- r_err_str = "Expected number as argument";
+ // Permit empty RID.
+ if (token.type == TK_PARENTHESIS_CLOSE) {
+ value = RID();
+ return OK;
+ } else if (token.type != TK_NUMBER) {
+ r_err_str = "Expected number as argument or ')'";
return ERR_PARSE_ERROR;
}
- value = token.value;
+ value = RID::from_uint64(token.value);
+
+ get_token(p_stream, token, line, r_err_str);
+ if (token.type != TK_PARENTHESIS_CLOSE) {
+ r_err_str = "Expected ')'";
+ return ERR_PARSE_ERROR;
+ }
+ } else if (id == "Signal") {
+ get_token(p_stream, token, line, r_err_str);
+ if (token.type != TK_PARENTHESIS_OPEN) {
+ r_err_str = "Expected '('";
+ return ERR_PARSE_ERROR;
+ }
+
+ // Load as empty.
+ value = Signal();
+
+ get_token(p_stream, token, line, r_err_str);
+ if (token.type != TK_PARENTHESIS_CLOSE) {
+ r_err_str = "Expected ')'";
+ return ERR_PARSE_ERROR;
+ }
+ } else if (id == "Callable") {
+ get_token(p_stream, token, line, r_err_str);
+ if (token.type != TK_PARENTHESIS_OPEN) {
+ r_err_str = "Expected '('";
+ return ERR_PARSE_ERROR;
+ }
+
+ // Load as empty.
+ value = Callable();
get_token(p_stream, token, line, r_err_str);
if (token.type != TK_PARENTHESIS_CLOSE) {
@@ -1832,6 +1866,24 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
+ case Variant::RID: {
+ RID rid = p_variant;
+
+ if (rid == RID()) {
+ p_store_string_func(p_store_string_ud, "RID()");
+ } else {
+ p_store_string_func(p_store_string_ud, "RID(" + itos(rid.get_id()) + ")");
+ }
+ } break;
+
+ // Do not really store these, but ensure that assignments are not empty.
+ case Variant::SIGNAL: {
+ p_store_string_func(p_store_string_ud, "Signal()");
+ } break;
+ case Variant::CALLABLE: {
+ p_store_string_func(p_store_string_ud, "Callable()");
+ } break;
+
case Variant::OBJECT: {
Object *obj = p_variant.get_validated_object();
@@ -2129,6 +2181,8 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
default: {
+ ERR_PRINT("Unknown variant type");
+ return ERR_BUG;
}
}