summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/config/engine.cpp1
-rw-r--r--core/config/project_settings.cpp4
-rw-r--r--core/core_constants.cpp4
-rw-r--r--core/debugger/remote_debugger.cpp41
-rw-r--r--core/debugger/remote_debugger.h1
-rw-r--r--core/doc_data.h45
-rw-r--r--core/error/error_macros.h20
-rw-r--r--core/extension/gdextension.cpp18
-rw-r--r--core/extension/gdextension.h20
-rw-r--r--core/extension/gdextension_interface.cpp17
-rw-r--r--core/extension/gdextension_interface.h25
-rw-r--r--core/input/gamecontrollerdb.txt38
-rw-r--r--core/input/input.cpp28
-rw-r--r--core/input/input.h5
-rw-r--r--core/input/input_builders.py4
-rw-r--r--core/input/input_event.cpp100
-rw-r--r--core/input/input_event.h21
-rw-r--r--core/io/file_access.cpp2
-rw-r--r--core/io/file_access_memory.cpp2
-rw-r--r--core/io/image.cpp30
-rw-r--r--core/io/image.h2
-rw-r--r--core/io/image_loader.cpp2
-rw-r--r--core/io/packet_peer.cpp6
-rw-r--r--core/io/resource_loader.cpp21
-rw-r--r--core/io/resource_loader.h6
-rw-r--r--core/io/xml_parser.cpp2
-rw-r--r--core/math/aabb.h6
-rw-r--r--core/math/basis.cpp4
-rw-r--r--core/math/convex_hull.cpp16
-rw-r--r--core/math/geometry_2d.cpp2
-rw-r--r--core/math/geometry_2d.h26
-rw-r--r--core/math/quaternion.cpp22
-rw-r--r--core/math/quaternion.h5
-rw-r--r--core/math/vector2.cpp8
-rw-r--r--core/math/vector3.cpp2
-rw-r--r--core/math/vector3.h10
-rw-r--r--core/object/class_db.cpp7
-rw-r--r--core/object/class_db.h20
-rw-r--r--core/object/message_queue.cpp12
-rw-r--r--core/object/object.cpp3
-rw-r--r--core/object/ref_counted.h5
-rw-r--r--core/object/script_language.cpp12
-rw-r--r--core/object/script_language.h2
-rw-r--r--core/object/script_language_extension.h1
-rw-r--r--core/object/undo_redo.cpp20
-rw-r--r--core/object/undo_redo.h4
-rw-r--r--core/object/worker_thread_pool.cpp6
-rw-r--r--core/os/condition_variable.h14
-rw-r--r--core/os/keyboard.h6
-rw-r--r--core/os/memory.cpp24
-rw-r--r--core/os/memory.h43
-rw-r--r--core/os/mutex.cpp4
-rw-r--r--core/os/mutex.h96
-rw-r--r--core/os/os.cpp6
-rw-r--r--core/os/safe_binary_mutex.h124
-rw-r--r--core/os/semaphore.h17
-rw-r--r--core/os/spin_lock.h21
-rw-r--r--core/os/thread.cpp9
-rw-r--r--core/os/thread.h64
-rw-r--r--core/os/time.cpp3
-rw-r--r--core/register_core_types.cpp3
-rw-r--r--core/string/char_range.inc4
-rw-r--r--core/string/translation_po.cpp4
-rw-r--r--core/string/ustring.cpp28
-rw-r--r--core/templates/cowdata.h218
-rw-r--r--core/templates/hashfuncs.h4
-rw-r--r--core/templates/local_vector.h10
-rw-r--r--core/templates/paged_allocator.h2
-rw-r--r--core/templates/paged_array.h16
-rw-r--r--core/templates/ring_buffer.h2
-rw-r--r--core/templates/safe_refcount.h2
-rw-r--r--core/templates/vector.h69
-rw-r--r--core/typedefs.h1
-rw-r--r--core/variant/array.cpp6
-rw-r--r--core/variant/binder_common.h9
-rw-r--r--core/variant/dictionary.cpp2
-rw-r--r--core/variant/type_info.h12
-rw-r--r--core/variant/typed_array.h44
-rw-r--r--core/variant/variant.cpp212
-rw-r--r--core/variant/variant.h47
-rw-r--r--core/variant/variant_call.cpp10
-rw-r--r--core/version.h6
82 files changed, 1260 insertions, 540 deletions
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index 24080c056a..203f8c3882 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -110,7 +110,6 @@ Dictionary Engine::get_version_info() const {
dict["hex"] = VERSION_HEX;
dict["status"] = VERSION_STATUS;
dict["build"] = VERSION_BUILD;
- dict["year"] = VERSION_YEAR;
String hash = String(VERSION_HASH);
dict["hash"] = hash.is_empty() ? String("unknown") : hash;
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 90e2e27320..329af9068e 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -1410,8 +1410,8 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("display/window/size/extend_to_title", false);
GLOBAL_DEF("display/window/size/no_focus", false);
- GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "1,7680,1,or_greater"), 0); // 8K resolution
- GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "1,4320,1,or_greater"), 0); // 8K resolution
+ GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"), 0); // 8K resolution
+ GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"), 0); // 8K resolution
GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true);
GLOBAL_DEF("display/window/energy_saving/keep_screen_on.editor", false);
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 3b96fc20c6..aaabbabfd9 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -507,6 +507,10 @@ void register_global_constants() {
BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, KPAD);
BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, GROUP_SWITCH);
+ BIND_CORE_ENUM_CLASS_CONSTANT(KeyLocation, KEY_LOCATION, UNSPECIFIED);
+ BIND_CORE_ENUM_CLASS_CONSTANT(KeyLocation, KEY_LOCATION, LEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(KeyLocation, KEY_LOCATION, RIGHT);
+
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, NONE);
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, LEFT);
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, RIGHT);
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index a817ea871d..6f2036705d 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -36,6 +36,7 @@
#include "core/debugger/engine_profiler.h"
#include "core/debugger/script_debugger.h"
#include "core/input/input.h"
+#include "core/io/resource_loader.h"
#include "core/object/script_language.h"
#include "core/os/os.h"
@@ -435,9 +436,7 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
messages.insert(Thread::get_caller_id(), List<Message>());
}
- mutex.lock();
while (is_peer_connected()) {
- mutex.unlock();
flush_output();
_poll_messages();
@@ -515,8 +514,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
_send_stack_vars(globals, globals_vals, 2);
} else if (command == "reload_scripts") {
+ script_paths_to_reload = data;
+ } else if (command == "reload_all_scripts") {
reload_all_scripts = true;
-
} else if (command == "breakpoint") {
ERR_FAIL_COND(data.size() < 3);
bool set = data[2];
@@ -527,7 +527,7 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
}
} else if (command == "set_skip_breakpoints") {
- ERR_FAIL_COND(data.size() < 1);
+ ERR_FAIL_COND(data.is_empty());
script_debugger->set_skip_breakpoints(data[0]);
} else {
bool captured = false;
@@ -591,19 +591,36 @@ void RemoteDebugger::poll_events(bool p_is_idle) {
}
// Reload scripts during idle poll only.
- if (p_is_idle && reload_all_scripts) {
- for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- ScriptServer::get_language(i)->reload_all_scripts();
+ if (p_is_idle) {
+ if (reload_all_scripts) {
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ ScriptServer::get_language(i)->reload_all_scripts();
+ }
+ reload_all_scripts = false;
+ } else if (!script_paths_to_reload.is_empty()) {
+ Array scripts_to_reload;
+ for (int i = 0; i < script_paths_to_reload.size(); ++i) {
+ String path = script_paths_to_reload[i];
+ Error err = OK;
+ Ref<Script> script = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err);
+ ERR_CONTINUE_MSG(err != OK, vformat("Could not reload script '%s': %s", path, error_names[err]));
+ ERR_CONTINUE_MSG(script.is_null(), vformat("Could not reload script '%s': Not a script!", path, error_names[err]));
+ scripts_to_reload.push_back(script);
+ }
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ ScriptServer::get_language(i)->reload_scripts(scripts_to_reload, true);
+ }
}
- reload_all_scripts = false;
+ script_paths_to_reload.clear();
}
}
Error RemoteDebugger::_core_capture(const String &p_cmd, const Array &p_data, bool &r_captured) {
r_captured = true;
if (p_cmd == "reload_scripts") {
+ script_paths_to_reload = p_data;
+ } else if (p_cmd == "reload_all_scripts") {
reload_all_scripts = true;
-
} else if (p_cmd == "breakpoint") {
ERR_FAIL_COND_V(p_data.size() < 3, ERR_INVALID_DATA);
bool set = p_data[2];
@@ -614,7 +631,7 @@ Error RemoteDebugger::_core_capture(const String &p_cmd, const Array &p_data, bo
}
} else if (p_cmd == "set_skip_breakpoints") {
- ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(p_data.is_empty(), ERR_INVALID_DATA);
script_debugger->set_skip_breakpoints(p_data[0]);
} else if (p_cmd == "break") {
script_debugger->debug(script_debugger->get_break_language());
@@ -626,7 +643,7 @@ Error RemoteDebugger::_core_capture(const String &p_cmd, const Array &p_data, bo
Error RemoteDebugger::_profiler_capture(const String &p_cmd, const Array &p_data, bool &r_captured) {
r_captured = false;
- ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(p_data.is_empty(), ERR_INVALID_DATA);
ERR_FAIL_COND_V(p_data[0].get_type() != Variant::BOOL, ERR_INVALID_DATA);
ERR_FAIL_COND_V(!has_profiler(p_cmd), ERR_UNAVAILABLE);
Array opts;
@@ -648,7 +665,7 @@ RemoteDebugger::RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer) {
// Performance Profiler
Object *perf = Engine::get_singleton()->get_singleton_object("Performance");
if (perf) {
- performance_profiler = Ref<PerformanceProfiler>(memnew(PerformanceProfiler(perf)));
+ performance_profiler.instantiate(perf);
performance_profiler->bind("performance");
profiler_enable("performance", true);
}
diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h
index 7c399178c6..519a90e7cc 100644
--- a/core/debugger/remote_debugger.h
+++ b/core/debugger/remote_debugger.h
@@ -74,6 +74,7 @@ private:
int warn_count = 0;
int last_reset = 0;
bool reload_all_scripts = false;
+ Array script_paths_to_reload;
// Make handlers and send_message thread safe.
Mutex mutex;
diff --git a/core/doc_data.h b/core/doc_data.h
index b8c92a4b67..45463f5931 100644
--- a/core/doc_data.h
+++ b/core/doc_data.h
@@ -117,6 +117,7 @@ public:
bool is_experimental = false;
Vector<ArgumentDoc> arguments;
Vector<int> errors_returned;
+ String keywords;
bool operator<(const MethodDoc &p_method) const {
if (name == p_method.name) {
// Must be an operator or a constructor since there is no other overloading
@@ -195,6 +196,10 @@ public:
doc.errors_returned.push_back(errors_returned[i]);
}
+ if (p_dict.has("keywords")) {
+ doc.keywords = p_dict["keywords"];
+ }
+
return doc;
}
static Dictionary to_dict(const MethodDoc &p_doc) {
@@ -225,6 +230,10 @@ public:
dict["is_experimental"] = p_doc.is_experimental;
+ if (!p_doc.keywords.is_empty()) {
+ dict["keywords"] = p_doc.keywords;
+ }
+
if (!p_doc.arguments.is_empty()) {
Array arguments;
for (int i = 0; i < p_doc.arguments.size(); i++) {
@@ -254,6 +263,7 @@ public:
String description;
bool is_deprecated = false;
bool is_experimental = false;
+ String keywords;
bool operator<(const ConstantDoc &p_const) const {
return name < p_const.name;
}
@@ -291,6 +301,10 @@ public:
doc.is_experimental = p_dict["is_experimental"];
}
+ if (p_dict.has("keywords")) {
+ doc.keywords = p_dict["keywords"];
+ }
+
return doc;
}
static Dictionary to_dict(const ConstantDoc &p_doc) {
@@ -319,6 +333,10 @@ public:
dict["is_experimental"] = p_doc.is_experimental;
+ if (!p_doc.keywords.is_empty()) {
+ dict["keywords"] = p_doc.keywords;
+ }
+
return dict;
}
};
@@ -335,6 +353,7 @@ public:
String overrides;
bool is_deprecated = false;
bool is_experimental = false;
+ String keywords;
bool operator<(const PropertyDoc &p_prop) const {
return name.naturalcasecmp_to(p_prop.name) < 0;
}
@@ -388,6 +407,10 @@ public:
doc.is_experimental = p_dict["is_experimental"];
}
+ if (p_dict.has("keywords")) {
+ doc.keywords = p_dict["keywords"];
+ }
+
return doc;
}
static Dictionary to_dict(const PropertyDoc &p_doc) {
@@ -432,6 +455,10 @@ public:
dict["is_experimental"] = p_doc.is_experimental;
+ if (!p_doc.keywords.is_empty()) {
+ dict["keywords"] = p_doc.keywords;
+ }
+
return dict;
}
};
@@ -442,6 +469,7 @@ public:
String data_type;
String description;
String default_value;
+ String keywords;
bool operator<(const ThemeItemDoc &p_theme_item) const {
// First sort by the data type, then by name.
if (data_type == p_theme_item.data_type) {
@@ -472,6 +500,10 @@ public:
doc.default_value = p_dict["default_value"];
}
+ if (p_dict.has("keywords")) {
+ doc.keywords = p_dict["keywords"];
+ }
+
return doc;
}
static Dictionary to_dict(const ThemeItemDoc &p_doc) {
@@ -497,6 +529,10 @@ public:
dict["default_value"] = p_doc.default_value;
}
+ if (!p_doc.keywords.is_empty()) {
+ dict["keywords"] = p_doc.keywords;
+ }
+
return dict;
}
};
@@ -573,6 +609,7 @@ public:
String inherits;
String brief_description;
String description;
+ String keywords;
Vector<TutorialDoc> tutorials;
Vector<MethodDoc> constructors;
Vector<MethodDoc> methods;
@@ -609,6 +646,10 @@ public:
doc.description = p_dict["description"];
}
+ if (p_dict.has("keywords")) {
+ doc.keywords = p_dict["keywords"];
+ }
+
Array tutorials;
if (p_dict.has("tutorials")) {
tutorials = p_dict["tutorials"];
@@ -816,6 +857,10 @@ public:
dict["script_path"] = p_doc.script_path;
}
+ if (!p_doc.keywords.is_empty()) {
+ dict["keywords"] = p_doc.keywords;
+ }
+
return dict;
}
};
diff --git a/core/error/error_macros.h b/core/error/error_macros.h
index c8182975d5..ab7dbcbd44 100644
--- a/core/error/error_macros.h
+++ b/core/error/error_macros.h
@@ -730,6 +730,16 @@ void _err_flush_stdout();
} else \
((void)0)
+/**
+ * Warns about `m_msg` only when verbose mode is enabled.
+ */
+#define WARN_VERBOSE(m_msg) \
+ { \
+ if (is_print_verbose_enabled()) { \
+ WARN_PRINT(m_msg); \
+ } \
+ }
+
// Print deprecated warning message macros.
/**
@@ -812,4 +822,14 @@ void _err_flush_stdout();
#define DEV_ASSERT(m_cond)
#endif
+#ifdef DEV_ENABLED
+#define DEV_CHECK_ONCE(m_cond) \
+ if (unlikely(!(m_cond))) { \
+ ERR_PRINT_ONCE("DEV_CHECK_ONCE failed \"" _STR(m_cond) "\" is false."); \
+ } else \
+ ((void)0)
+#else
+#define DEV_CHECK_ONCE(m_cond)
+#endif
+
#endif // ERROR_MACROS_H
diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp
index ce01531b5c..aba96befd6 100644
--- a/core/extension/gdextension.cpp
+++ b/core/extension/gdextension.cpp
@@ -653,6 +653,8 @@ void GDExtension::_unregister_extension_class(GDExtensionClassLibraryPtr p_libra
if (!ext->is_reloading) {
self->extension_classes.erase(class_name);
}
+
+ GDExtensionEditorHelp::remove_class(class_name);
#else
self->extension_classes.erase(class_name);
#endif
@@ -792,6 +794,9 @@ void GDExtension::deinitialize_library(InitializationLevel p_level) {
ERR_FAIL_COND(p_level > int32_t(level_initialized));
level_initialized = int32_t(p_level) - 1;
+
+ ERR_FAIL_NULL(initialization.deinitialize);
+
initialization.deinitialize(initialization.userdata, GDExtensionInitializationLevel(p_level));
}
@@ -1196,4 +1201,17 @@ void GDExtensionEditorPlugins::remove_extension_class(const StringName &p_class_
extension_classes.erase(p_class_name);
}
}
+
+GDExtensionEditorHelp::EditorHelpLoadXmlBufferFunc GDExtensionEditorHelp::editor_help_load_xml_buffer = nullptr;
+GDExtensionEditorHelp::EditorHelpRemoveClassFunc GDExtensionEditorHelp::editor_help_remove_class = nullptr;
+
+void GDExtensionEditorHelp::load_xml_buffer(const uint8_t *p_buffer, int p_size) {
+ ERR_FAIL_NULL(editor_help_load_xml_buffer);
+ editor_help_load_xml_buffer(p_buffer, p_size);
+}
+
+void GDExtensionEditorHelp::remove_class(const String &p_class) {
+ ERR_FAIL_NULL(editor_help_remove_class);
+ editor_help_remove_class(p_class);
+}
#endif // TOOLS_ENABLED
diff --git a/core/extension/gdextension.h b/core/extension/gdextension.h
index 0b39581751..588efed017 100644
--- a/core/extension/gdextension.h
+++ b/core/extension/gdextension.h
@@ -197,6 +197,26 @@ public:
return extension_classes;
}
};
+
+class GDExtensionEditorHelp {
+protected:
+ friend class EditorHelp;
+
+ // Similarly to EditorNode above, we need to be able to ask EditorHelp to parse
+ // new documentation data. Note though that, differently from EditorHelp, this
+ // is initialized even _before_ it gets instantiated, as we need to rely on
+ // this method while initializing the engine.
+ typedef void (*EditorHelpLoadXmlBufferFunc)(const uint8_t *p_buffer, int p_size);
+ static EditorHelpLoadXmlBufferFunc editor_help_load_xml_buffer;
+
+ typedef void (*EditorHelpRemoveClassFunc)(const String &p_class);
+ static EditorHelpRemoveClassFunc editor_help_remove_class;
+
+public:
+ static void load_xml_buffer(const uint8_t *p_buffer, int p_size);
+ static void remove_class(const String &p_class);
+};
+
#endif // TOOLS_ENABLED
#endif // GDEXTENSION_H
diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp
index e02e7aa701..88572f24f0 100644
--- a/core/extension/gdextension_interface.cpp
+++ b/core/extension/gdextension_interface.cpp
@@ -42,6 +42,8 @@
#include "core/variant/variant.h"
#include "core/version.h"
+#include <string.h>
+
class CallableCustomExtension : public CallableCustom {
void *userdata;
void *token;
@@ -1373,6 +1375,19 @@ static void gdextension_editor_remove_plugin(GDExtensionConstStringNamePtr p_cla
#endif
}
+static void gdextension_editor_help_load_xml_from_utf8_chars_and_len(const char *p_data, GDExtensionInt p_size) {
+#ifdef TOOLS_ENABLED
+ GDExtensionEditorHelp::load_xml_buffer((const uint8_t *)p_data, p_size);
+#endif
+}
+
+static void gdextension_editor_help_load_xml_from_utf8_chars(const char *p_data) {
+#ifdef TOOLS_ENABLED
+ size_t len = strlen(p_data);
+ gdextension_editor_help_load_xml_from_utf8_chars_and_len(p_data, len);
+#endif
+}
+
#define REGISTER_INTERFACE_FUNC(m_name) GDExtension::register_interface_function(#m_name, (GDExtensionInterfaceFunctionPtr)&gdextension_##m_name)
void gdextension_setup_interface() {
@@ -1516,6 +1531,8 @@ void gdextension_setup_interface() {
REGISTER_INTERFACE_FUNC(classdb_get_class_tag);
REGISTER_INTERFACE_FUNC(editor_add_plugin);
REGISTER_INTERFACE_FUNC(editor_remove_plugin);
+ REGISTER_INTERFACE_FUNC(editor_help_load_xml_from_utf8_chars);
+ REGISTER_INTERFACE_FUNC(editor_help_load_xml_from_utf8_chars_and_len);
}
#undef REGISTER_INTERFACE_FUNCTION
diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h
index d58f0226d8..8fda11c651 100644
--- a/core/extension/gdextension_interface.h
+++ b/core/extension/gdextension_interface.h
@@ -2617,6 +2617,31 @@ typedef void (*GDExtensionInterfaceEditorAddPlugin)(GDExtensionConstStringNamePt
*/
typedef void (*GDExtensionInterfaceEditorRemovePlugin)(GDExtensionConstStringNamePtr p_class_name);
+/**
+ * @name editor_help_load_xml_from_utf8_chars
+ * @since 4.3
+ *
+ * Loads new XML-formatted documentation data in the editor.
+ *
+ * The provided pointer can be immediately freed once the function returns.
+ *
+ * @param p_data A pointer to an UTF-8 encoded C string (null terminated).
+ */
+typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char *p_data);
+
+/**
+ * @name editor_help_load_xml_from_utf8_chars_and_len
+ * @since 4.3
+ *
+ * Loads new XML-formatted documentation data in the editor.
+ *
+ * The provided pointer can be immediately freed once the function returns.
+ *
+ * @param p_data A pointer to an UTF-8 encoded C string.
+ * @param p_size The number of bytes (not code units).
+ */
+typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen)(const char *p_data, GDExtensionInt p_size);
+
#ifdef __cplusplus
}
#endif
diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt
index 77655e9b6a..420de7f9b7 100644
--- a/core/input/gamecontrollerdb.txt
+++ b/core/input/gamecontrollerdb.txt
@@ -314,6 +314,7 @@
03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows,
03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows,
03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows,
+03000000242e00006a48000000000000,Hyperkin RetroN Sq,a:b3,b:b7,back:b5,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b0,rightshoulder:b1,start:b4,x:b2,y:b6,platform:Windows,
03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows,
03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -352,7 +353,7 @@
030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,
030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006d0400001ec2000000000000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000006d04000019c2000000000000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -429,6 +430,8 @@
03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows,
030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+0300000085320000170d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+0300000085320000190d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
030000006b140000100d000000000000,Nacon Revolution Infinity PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006b140000080d000000000000,Nacon Revolution Unlimited Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000bd12000001c0000000000000,Nebular,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
@@ -450,7 +453,7 @@
03000000550900001072000000000000,NVIDIA Shield,a:b9,b:b8,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b3,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b2,righttrigger:a4,rightx:a2,righty:a5,start:b0,x:b7,y:b6,platform:Windows,
030000005509000000b4000000000000,NVIDIA Virtual,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000120c00000288000000000000,Nyko Air Flo Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
-030000004b120000014d000000000000,Nyko Airflo,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows,
+030000004b120000014d000000000000,NYKO Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000d62000001d57000000000000,Nyko Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000791d00000900000000000000,Nyko Playpad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000782300000a10000000000000,Onlive Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows,
@@ -459,7 +462,7 @@
030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
-03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,
+03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,
03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000006f0e00008501000000000000,PDP Fightpad Pro GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
@@ -532,6 +535,7 @@
030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000004c0500005f0e000000000000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
030000004c050000f20d000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
03000000830500005020000000000000,PSX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Windows,
@@ -556,6 +560,7 @@
030000009b2800003200000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows,
+030000009b2800006100000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows,
030000009b2800006300000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows,
030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows,
030000009b2800004400000000000000,Raphnet PS1 and PS2 Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows,
@@ -608,6 +613,7 @@
03000000050b00001a1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
03000000050b00001c1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
030000004f04000001d0000000000000,Rumble Force,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+030000000d0f0000ad00000000000000,RX Gamepad,a:b0,b:b4,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b6,start:b9,x:b2,y:b1,platform:Windows,
030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
@@ -674,6 +680,7 @@
03000000457500002211000000000000,Szmy Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows,
030000000d0f00007b00000000000000,TAC GEAR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000e40a00000307000000000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows,
03000000e40a00000207000000000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows,
03000000d814000001a0000000000000,TE Kitty,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -961,6 +968,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+0300004b4c0500005f0e000000010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
030000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
@@ -1013,6 +1021,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,
030000000d0f0000f600000000010000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000e40a00000307000001000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X,
+03000000e40a00000207000001000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X,
03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000591c00002400000021000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000591c00002600000021000000,THEGamepad,a:b2,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Mac OS X,
@@ -1164,14 +1174,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000c31100000791000011010000,Be1 GC101 Controller 1.03,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000005e0400008e02000003030000,Be1 GC101 Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
-03000000bc2000004d50000011010000,BEITONG A1T2 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-05000000bc2000000055000001000000,BETOP AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000bc2000004d50000011010000,Beitong A1T2 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000bc2000000055000001000000,Betop AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
030000006b1400000209000011010000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000120c0000200e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000120c0000210e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux,
030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux,
03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,
03000000a306000022f6000011010000,Cyborg V3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
@@ -1218,7 +1229,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
06000000adde0000efbe000002010000,Hidromancer Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,
03000000c9110000f055000011010000,HJC Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
-03000000632500002605000010010000,HJDX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000000d0f00000d00000000010000,Hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,
030000000d0f00006d00000020010000,Hori EDGE 301,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000000d0f00008400000011010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
@@ -1256,6 +1266,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000f00300008d03000011010000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000830500006020000010010000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
+030000008f0e00001330000001010000,iCode Retro Adapter,b:b3,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b1,start:b7,x:b2,y:b0,platform:Linux,
050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
03000000d80400008200000003000000,IMS PCU0,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux,
@@ -1389,6 +1400,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
05000000550900001472000001000000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
+030000004b120000014d000000010000,NYKO Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
19000000010000000100000001010000,ODROID Go 2,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,
19000000010000000200000011000000,ODROID Go 2,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux,
@@ -1407,6 +1419,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006f0e00002801000011010000,PDP PS3 Rock Candy Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006f0e00000901000011010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+030000006f0e00002f01000011010000,PDP Wired PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000ad1b000004f9000000010000,PDP Xbox 360 Versus Fighting,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,
030000006f0e0000a802000023020000,PDP Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000006f0e0000a702000023020000,PDP Xbox One Raven Black,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -1463,6 +1476,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+0300004b4c0500005f0e000011010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
030000004c050000f20d000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
@@ -1528,9 +1542,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000632500002305000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000632500002605000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000632500007505000010010000,Shanwan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000bc2000000055000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000f025000021c1000010010000,Shanwan Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
-03000000632500007505000010010000,Shanwan PS3 PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
-03000000bc2000000055000010010000,Shanwan PS3 PC ,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
@@ -1564,6 +1579,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000457500000401000011010000,SZMY Power DS4 Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000457500002211000010010000,SZMY Power Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
030000008f0e00001431000010010000,SZMY Power PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000e40a00000307000011010000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux,
+03000000e40a00000207000011010000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux,
03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux,
03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000591c00002400000010010000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
@@ -1871,9 +1888,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
36313938306539326233393732613361,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
526574726f466c616720576972656420,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,rightshoulder:b18,start:b10,x:b2,y:b3,platform:Android,
61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android,
+526574726f696420506f636b65742043,Retroid Pocket,a:b1,b:b0,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+582d426f7820436f6e74726f6c6c6572,Retroid Pocket,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
-526574726f696420506f636b65742043,Retroid Pocket Flip,a:b1,b:b0,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
-582d426f7820436f6e74726f6c6c6572,Retroid Pocket Flip,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b6,platform:Android,
37393234373533633333323633646531,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android,
5365616c6965436f6d707574696e6720,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android,
@@ -1902,6 +1919,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,
0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android,
35306436396437373135383665646464,SteelSeries Nimbus Plus,a:b0,b:b1,leftshoulder:b3,leftstick:b17,lefttrigger:b9,leftx:a0,rightshoulder:b20,rightstick:b18,righttrigger:b10,rightx:a2,x:b19,y:b2,platform:Android,
+33313930373536613937326534303931,Taito Egret II Mini Control Panel,a:b25,b:b23,back:b27,guide:b30,leftx:a0,lefty:a1,rightshoulder:b21,righttrigger:b22,start:b28,x:b29,y:b24,platform:Android,
54475a20436f6e74726f6c6c65720000,TGZ Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
62363434353532386238336663643836,TGZ Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
37323236633763666465316365313236,THEC64 Joystick,a:b21,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b27,x:b23,y:b24,platform:Android,
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 2ba4b1d1e8..d87a8824f7 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -130,6 +130,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_magnetometer", "value"), &Input::set_magnetometer);
ClassDB::bind_method(D_METHOD("set_gyroscope", "value"), &Input::set_gyroscope);
ClassDB::bind_method(D_METHOD("get_last_mouse_velocity"), &Input::get_last_mouse_velocity);
+ ClassDB::bind_method(D_METHOD("get_last_mouse_screen_velocity"), &Input::get_last_mouse_screen_velocity);
ClassDB::bind_method(D_METHOD("get_mouse_button_mask"), &Input::get_mouse_button_mask);
ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &Input::set_mouse_mode);
ClassDB::bind_method(D_METHOD("get_mouse_mode"), &Input::get_mouse_mode);
@@ -201,7 +202,7 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S
Object::get_argument_options(p_function, p_idx, r_options);
}
-void Input::VelocityTrack::update(const Vector2 &p_delta_p) {
+void Input::VelocityTrack::update(const Vector2 &p_delta_p, const Vector2 &p_screen_delta_p) {
uint64_t tick = OS::get_singleton()->get_ticks_usec();
uint32_t tdiff = tick - last_tick;
float delta_t = tdiff / 1000000.0;
@@ -210,12 +211,15 @@ void Input::VelocityTrack::update(const Vector2 &p_delta_p) {
if (delta_t > max_ref_frame) {
// First movement in a long time, reset and start again.
velocity = Vector2();
+ screen_velocity = Vector2();
accum = p_delta_p;
+ screen_accum = p_screen_delta_p;
accum_t = 0;
return;
}
accum += p_delta_p;
+ screen_accum += p_screen_delta_p;
accum_t += delta_t;
if (accum_t < min_ref_frame) {
@@ -224,6 +228,7 @@ void Input::VelocityTrack::update(const Vector2 &p_delta_p) {
}
velocity = accum / accum_t;
+ screen_velocity = screen_accum / accum_t;
accum = Vector2();
accum_t = 0;
}
@@ -594,7 +599,8 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
set_mouse_position(position);
}
Vector2 relative = mm->get_relative();
- mouse_velocity_track.update(relative);
+ Vector2 screen_relative = mm->get_relative_screen_position();
+ mouse_velocity_track.update(relative, screen_relative);
if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && mm->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
Ref<InputEventScreenDrag> drag_event;
@@ -602,10 +608,12 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
drag_event->set_position(position);
drag_event->set_relative(relative);
+ drag_event->set_relative_screen_position(screen_relative);
drag_event->set_tilt(mm->get_tilt());
drag_event->set_pen_inverted(mm->get_pen_inverted());
drag_event->set_pressure(mm->get_pressure());
drag_event->set_velocity(get_last_mouse_velocity());
+ drag_event->set_screen_velocity(get_last_mouse_screen_velocity());
drag_event->set_device(InputEvent::DEVICE_ID_EMULATION);
_THREAD_SAFE_UNLOCK_
@@ -669,8 +677,9 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
if (sd.is_valid()) {
VelocityTrack &track = touch_velocity_track[sd->get_index()];
- track.update(sd->get_relative());
+ track.update(sd->get_relative(), sd->get_relative_screen_position());
sd->set_velocity(track.velocity);
+ sd->set_screen_velocity(track.screen_velocity);
if (emulate_mouse_from_touch && sd->get_index() == mouse_from_touch_index) {
Ref<InputEventMouseMotion> motion_event;
@@ -683,7 +692,9 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
motion_event->set_position(sd->get_position());
motion_event->set_global_position(sd->get_position());
motion_event->set_relative(sd->get_relative());
+ motion_event->set_relative_screen_position(sd->get_relative_screen_position());
motion_event->set_velocity(sd->get_velocity());
+ motion_event->set_screen_velocity(sd->get_screen_velocity());
motion_event->set_button_mask(mouse_button_mask);
_parse_input_event_impl(motion_event, true);
@@ -827,10 +838,15 @@ Point2 Input::get_mouse_position() const {
}
Point2 Input::get_last_mouse_velocity() {
- mouse_velocity_track.update(Vector2());
+ mouse_velocity_track.update(Vector2(), Vector2());
return mouse_velocity_track.velocity;
}
+Point2 Input::get_last_mouse_screen_velocity() {
+ mouse_velocity_track.update(Vector2(), Vector2());
+ return mouse_velocity_track.screen_velocity;
+}
+
BitField<MouseButtonMask> Input::get_mouse_button_mask() const {
return mouse_button_mask; // do not trust OS implementation, should remove it - OS::get_singleton()->get_mouse_button_state();
}
@@ -865,6 +881,8 @@ Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, con
}
void Input::action_press(const StringName &p_action, float p_strength) {
+ ERR_FAIL_COND_MSG(!InputMap::get_singleton()->has_action(p_action), InputMap::get_singleton()->suggest_actions(p_action));
+
// Create or retrieve existing action.
ActionState &action_state = action_states[p_action];
@@ -879,6 +897,8 @@ void Input::action_press(const StringName &p_action, float p_strength) {
}
void Input::action_release(const StringName &p_action) {
+ ERR_FAIL_COND_MSG(!InputMap::get_singleton()->has_action(p_action), InputMap::get_singleton()->suggest_actions(p_action));
+
// Create or retrieve existing action.
ActionState &action_state = action_states[p_action];
action_state.cache.pressed = 0;
diff --git a/core/input/input.h b/core/input/input.h
index b98406e884..a7ae3349b2 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -145,12 +145,14 @@ private:
struct VelocityTrack {
uint64_t last_tick = 0;
Vector2 velocity;
+ Vector2 screen_velocity;
Vector2 accum;
+ Vector2 screen_accum;
float accum_t = 0.0f;
float min_ref_frame;
float max_ref_frame;
- void update(const Vector2 &p_delta_p);
+ void update(const Vector2 &p_delta_p, const Vector2 &p_screen_delta_p);
void reset();
VelocityTrack();
};
@@ -302,6 +304,7 @@ public:
Point2 get_mouse_position() const;
Vector2 get_last_mouse_velocity();
+ Vector2 get_last_mouse_screen_velocity();
BitField<MouseButtonMask> get_mouse_button_mask() const;
void warp_mouse(const Vector2 &p_position);
diff --git a/core/input/input_builders.py b/core/input/input_builders.py
index e98e2441e2..94c566493e 100644
--- a/core/input/input_builders.py
+++ b/core/input/input_builders.py
@@ -45,10 +45,10 @@ def make_default_controller_mappings(target, source, env):
platform_mappings[current_platform][guid] = line
platform_variables = {
- "Linux": "#if LINUXBSD_ENABLED",
+ "Linux": "#ifdef LINUXBSD_ENABLED",
"Windows": "#ifdef WINDOWS_ENABLED",
"Mac OS X": "#ifdef MACOS_ENABLED",
- "Android": "#if defined(__ANDROID__)",
+ "Android": "#ifdef ANDROID_ENABLED",
"iOS": "#ifdef IOS_ENABLED",
"Web": "#ifdef WEB_ENABLED",
}
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index e99dd04599..bd1fde5a85 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -364,6 +364,15 @@ char32_t InputEventKey::get_unicode() const {
return unicode;
}
+void InputEventKey::set_location(KeyLocation p_key_location) {
+ location = p_key_location;
+ emit_changed();
+}
+
+KeyLocation InputEventKey::get_location() const {
+ return location;
+}
+
void InputEventKey::set_echo(bool p_enable) {
echo = p_enable;
emit_changed();
@@ -436,6 +445,23 @@ String InputEventKey::as_text_key_label() const {
return mods_text.is_empty() ? kc : mods_text + "+" + kc;
}
+String InputEventKey::as_text_location() const {
+ String loc;
+
+ switch (location) {
+ case KeyLocation::LEFT:
+ loc = "left";
+ break;
+ case KeyLocation::RIGHT:
+ loc = "right";
+ break;
+ default:
+ break;
+ }
+
+ return loc;
+}
+
String InputEventKey::as_text() const {
String kc;
@@ -464,6 +490,11 @@ String InputEventKey::to_string() {
String kc = "";
String physical = "false";
+ String loc = as_text_location();
+ if (loc.is_empty()) {
+ loc = "unspecified";
+ }
+
if (keycode == Key::NONE && physical_keycode == Key::NONE && unicode != 0) {
kc = "U+" + String::num_uint64(unicode, 16) + " (" + String::chr(unicode) + ")";
} else if (keycode != Key::NONE) {
@@ -478,7 +509,7 @@ String InputEventKey::to_string() {
String mods = InputEventWithModifiers::as_text();
mods = mods.is_empty() ? "none" : mods;
- return vformat("InputEventKey: keycode=%s, mods=%s, physical=%s, pressed=%s, echo=%s", kc, mods, physical, p, e);
+ return vformat("InputEventKey: keycode=%s, mods=%s, physical=%s, location=%s, pressed=%s, echo=%s", kc, mods, physical, loc, p, e);
}
Ref<InputEventKey> InputEventKey::create_reference(Key p_keycode, bool p_physical) {
@@ -531,6 +562,9 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool p_exact_ma
match = keycode == key->keycode;
} else if (physical_keycode != Key::NONE) {
match = physical_keycode == key->physical_keycode;
+ if (location != KeyLocation::UNSPECIFIED) {
+ match &= location == key->location;
+ }
} else {
match = false;
}
@@ -572,6 +606,9 @@ bool InputEventKey::is_match(const Ref<InputEvent> &p_event, bool p_exact_match)
return (keycode == key->keycode) &&
(!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask());
} else if (physical_keycode != Key::NONE) {
+ if (location != KeyLocation::UNSPECIFIED && location != key->location) {
+ return false;
+ }
return (physical_keycode == key->physical_keycode) &&
(!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask());
} else {
@@ -594,6 +631,9 @@ void InputEventKey::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_unicode", "unicode"), &InputEventKey::set_unicode);
ClassDB::bind_method(D_METHOD("get_unicode"), &InputEventKey::get_unicode);
+ ClassDB::bind_method(D_METHOD("set_location", "location"), &InputEventKey::set_location);
+ ClassDB::bind_method(D_METHOD("get_location"), &InputEventKey::get_location);
+
ClassDB::bind_method(D_METHOD("set_echo", "echo"), &InputEventKey::set_echo);
ClassDB::bind_method(D_METHOD("get_keycode_with_modifiers"), &InputEventKey::get_keycode_with_modifiers);
@@ -603,12 +643,14 @@ void InputEventKey::_bind_methods() {
ClassDB::bind_method(D_METHOD("as_text_keycode"), &InputEventKey::as_text_keycode);
ClassDB::bind_method(D_METHOD("as_text_physical_keycode"), &InputEventKey::as_text_physical_keycode);
ClassDB::bind_method(D_METHOD("as_text_key_label"), &InputEventKey::as_text_key_label);
+ ClassDB::bind_method(D_METHOD("as_text_location"), &InputEventKey::as_text_location);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "keycode"), "set_keycode", "get_keycode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "physical_keycode"), "set_physical_keycode", "get_physical_keycode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "key_label"), "set_key_label", "get_key_label");
ADD_PROPERTY(PropertyInfo(Variant::INT, "unicode"), "set_unicode", "get_unicode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "location", PROPERTY_HINT_ENUM, "Unspecified,Left,Right"), "set_location", "get_location");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "echo"), "set_echo", "is_echo");
}
@@ -885,6 +927,14 @@ Vector2 InputEventMouseMotion::get_relative() const {
return relative;
}
+void InputEventMouseMotion::set_relative_screen_position(const Vector2 &p_relative) {
+ screen_relative = p_relative;
+}
+
+Vector2 InputEventMouseMotion::get_relative_screen_position() const {
+ return screen_relative;
+}
+
void InputEventMouseMotion::set_velocity(const Vector2 &p_velocity) {
velocity = p_velocity;
}
@@ -893,6 +943,14 @@ Vector2 InputEventMouseMotion::get_velocity() const {
return velocity;
}
+void InputEventMouseMotion::set_screen_velocity(const Vector2 &p_velocity) {
+ screen_velocity = p_velocity;
+}
+
+Vector2 InputEventMouseMotion::get_screen_velocity() const {
+ return screen_velocity;
+}
+
Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
Ref<InputEventMouseMotion> mm;
mm.instantiate();
@@ -910,7 +968,9 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co
mm->set_button_mask(get_button_mask());
mm->set_relative(p_xform.basis_xform(get_relative()));
+ mm->set_relative_screen_position(get_relative_screen_position());
mm->set_velocity(p_xform.basis_xform(get_velocity()));
+ mm->set_screen_velocity(get_screen_velocity());
return mm;
}
@@ -985,7 +1045,9 @@ bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) {
set_position(motion->get_position());
set_global_position(motion->get_global_position());
set_velocity(motion->get_velocity());
+ set_screen_velocity(motion->get_screen_velocity());
relative += motion->get_relative();
+ screen_relative += motion->get_relative_screen_position();
return true;
}
@@ -1003,14 +1065,22 @@ void InputEventMouseMotion::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventMouseMotion::set_relative);
ClassDB::bind_method(D_METHOD("get_relative"), &InputEventMouseMotion::get_relative);
+ ClassDB::bind_method(D_METHOD("set_screen_relative", "relative"), &InputEventMouseMotion::set_relative_screen_position);
+ ClassDB::bind_method(D_METHOD("get_screen_relative"), &InputEventMouseMotion::get_relative_screen_position);
+
ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &InputEventMouseMotion::set_velocity);
ClassDB::bind_method(D_METHOD("get_velocity"), &InputEventMouseMotion::get_velocity);
+ ClassDB::bind_method(D_METHOD("set_screen_velocity", "velocity"), &InputEventMouseMotion::set_screen_velocity);
+ ClassDB::bind_method(D_METHOD("get_screen_velocity"), &InputEventMouseMotion::get_screen_velocity);
+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure"), "set_pressure", "get_pressure");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pen_inverted"), "set_pen_inverted", "get_pen_inverted");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative", PROPERTY_HINT_NONE, "suffix:px"), "set_relative", "get_relative");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "screen_relative", PROPERTY_HINT_NONE, "suffix:px"), "set_screen_relative", "get_screen_relative");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_velocity", "get_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "screen_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_screen_velocity", "get_screen_velocity");
}
///////////////////////////////////
@@ -1380,6 +1450,14 @@ Vector2 InputEventScreenDrag::get_relative() const {
return relative;
}
+void InputEventScreenDrag::set_relative_screen_position(const Vector2 &p_relative) {
+ screen_relative = p_relative;
+}
+
+Vector2 InputEventScreenDrag::get_relative_screen_position() const {
+ return screen_relative;
+}
+
void InputEventScreenDrag::set_velocity(const Vector2 &p_velocity) {
velocity = p_velocity;
}
@@ -1388,6 +1466,14 @@ Vector2 InputEventScreenDrag::get_velocity() const {
return velocity;
}
+void InputEventScreenDrag::set_screen_velocity(const Vector2 &p_velocity) {
+ screen_velocity = p_velocity;
+}
+
+Vector2 InputEventScreenDrag::get_screen_velocity() const {
+ return screen_velocity;
+}
+
Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
Ref<InputEventScreenDrag> sd;
@@ -1402,7 +1488,9 @@ Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, con
sd->set_tilt(get_tilt());
sd->set_position(p_xform.xform(pos + p_local_ofs));
sd->set_relative(p_xform.basis_xform(relative));
+ sd->set_relative_screen_position(get_relative_screen_position());
sd->set_velocity(p_xform.basis_xform(velocity));
+ sd->set_screen_velocity(get_screen_velocity());
return sd;
}
@@ -1427,7 +1515,9 @@ bool InputEventScreenDrag::accumulate(const Ref<InputEvent> &p_event) {
set_position(drag->get_position());
set_velocity(drag->get_velocity());
+ set_screen_velocity(drag->get_screen_velocity());
relative += drag->get_relative();
+ screen_relative += drag->get_relative_screen_position();
return true;
}
@@ -1451,16 +1541,24 @@ void InputEventScreenDrag::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventScreenDrag::set_relative);
ClassDB::bind_method(D_METHOD("get_relative"), &InputEventScreenDrag::get_relative);
+ ClassDB::bind_method(D_METHOD("set_screen_relative", "relative"), &InputEventScreenDrag::set_relative_screen_position);
+ ClassDB::bind_method(D_METHOD("get_screen_relative"), &InputEventScreenDrag::get_relative_screen_position);
+
ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &InputEventScreenDrag::set_velocity);
ClassDB::bind_method(D_METHOD("get_velocity"), &InputEventScreenDrag::get_velocity);
+ ClassDB::bind_method(D_METHOD("set_screen_velocity", "velocity"), &InputEventScreenDrag::set_screen_velocity);
+ ClassDB::bind_method(D_METHOD("get_screen_velocity"), &InputEventScreenDrag::get_screen_velocity);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure"), "set_pressure", "get_pressure");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pen_inverted"), "set_pen_inverted", "get_pen_inverted");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative", PROPERTY_HINT_NONE, "suffix:px"), "set_relative", "get_relative");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "screen_relative", PROPERTY_HINT_NONE, "suffix:px"), "set_screen_relative", "get_screen_relative");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_velocity", "get_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "screen_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_screen_velocity", "get_screen_velocity");
}
///////////////////////////////////
diff --git a/core/input/input_event.h b/core/input/input_event.h
index ed7ccf0a9f..21b61f3bc2 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -157,6 +157,7 @@ class InputEventKey : public InputEventWithModifiers {
Key physical_keycode = Key::NONE;
Key key_label = Key::NONE;
uint32_t unicode = 0; ///unicode
+ KeyLocation location = KeyLocation::UNSPECIFIED;
bool echo = false; /// true if this is an echo key
@@ -178,6 +179,9 @@ public:
void set_unicode(char32_t p_unicode);
char32_t get_unicode() const;
+ void set_location(KeyLocation p_key_location);
+ KeyLocation get_location() const;
+
void set_echo(bool p_enable);
virtual bool is_echo() const override;
@@ -193,6 +197,7 @@ public:
virtual String as_text_physical_keycode() const;
virtual String as_text_keycode() const;
virtual String as_text_key_label() const;
+ virtual String as_text_location() const;
virtual String as_text() const override;
virtual String to_string() override;
@@ -266,7 +271,9 @@ class InputEventMouseMotion : public InputEventMouse {
Vector2 tilt;
float pressure = 0;
Vector2 relative;
+ Vector2 screen_relative;
Vector2 velocity;
+ Vector2 screen_velocity;
bool pen_inverted = false;
protected:
@@ -285,9 +292,15 @@ public:
void set_relative(const Vector2 &p_relative);
Vector2 get_relative() const;
+ void set_relative_screen_position(const Vector2 &p_relative);
+ Vector2 get_relative_screen_position() const;
+
void set_velocity(const Vector2 &p_velocity);
Vector2 get_velocity() const;
+ void set_screen_velocity(const Vector2 &p_velocity);
+ Vector2 get_screen_velocity() const;
+
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
virtual String as_text() const override;
virtual String to_string() override;
@@ -388,7 +401,9 @@ class InputEventScreenDrag : public InputEventFromWindow {
int index = 0;
Vector2 pos;
Vector2 relative;
+ Vector2 screen_relative;
Vector2 velocity;
+ Vector2 screen_velocity;
Vector2 tilt;
float pressure = 0;
bool pen_inverted = false;
@@ -415,9 +430,15 @@ public:
void set_relative(const Vector2 &p_relative);
Vector2 get_relative() const;
+ void set_relative_screen_position(const Vector2 &p_relative);
+ Vector2 get_relative_screen_position() const;
+
void set_velocity(const Vector2 &p_velocity);
Vector2 get_velocity() const;
+ void set_screen_velocity(const Vector2 &p_velocity);
+ Vector2 get_screen_velocity() const;
+
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
virtual String as_text() const override;
virtual String to_string() override;
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
index 6026dbf896..55286277fa 100644
--- a/core/io/file_access.cpp
+++ b/core/io/file_access.cpp
@@ -38,7 +38,7 @@
#include "core/io/marshalls.h"
#include "core/os/os.h"
-FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = { nullptr, nullptr };
+FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = {};
FileAccess::FileCloseFailNotify FileAccess::close_fail_notify = nullptr;
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 0983920b94..da02c883e8 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -119,7 +119,7 @@ uint64_t FileAccessMemory::get_length() const {
}
bool FileAccessMemory::eof_reached() const {
- return pos > length;
+ return pos >= length;
}
uint8_t FileAccessMemory::get_8() const {
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 9aa7c9794a..24caccca5f 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -1029,7 +1029,7 @@ void Image::resize_to_po2(bool p_square, Interpolation p_interpolation) {
}
void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
- ERR_FAIL_COND_MSG(data.size() == 0, "Cannot resize image before creating it, use set_data() first.");
+ ERR_FAIL_COND_MSG(data.is_empty(), "Cannot resize image before creating it, use set_data() first.");
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats.");
bool mipmap_aware = p_interpolation == INTERPOLATE_TRILINEAR /* || p_interpolation == INTERPOLATE_TRICUBIC */;
@@ -1700,7 +1700,7 @@ static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint3
}
void Image::shrink_x2() {
- ERR_FAIL_COND(data.size() == 0);
+ ERR_FAIL_COND(data.is_empty());
if (mipmaps) {
//just use the lower mipmap as base and copy all
@@ -1710,7 +1710,7 @@ void Image::shrink_x2() {
int new_size = data.size() - ofs;
new_img.resize(new_size);
- ERR_FAIL_COND(new_img.size() == 0);
+ ERR_FAIL_COND(new_img.is_empty());
{
uint8_t *w = new_img.ptrw();
@@ -1729,8 +1729,8 @@ void Image::shrink_x2() {
ERR_FAIL_COND(!_can_modify(format));
int ps = get_format_pixel_size(format);
new_img.resize((width / 2) * (height / 2) * ps);
- ERR_FAIL_COND(new_img.size() == 0);
- ERR_FAIL_COND(data.size() == 0);
+ ERR_FAIL_COND(new_img.is_empty());
+ ERR_FAIL_COND(data.is_empty());
{
uint8_t *w = new_img.ptrw();
@@ -2781,7 +2781,7 @@ void Image::_get_clipped_src_and_dest_rects(const Ref<Image> &p_src, const Rect2
}
void Image::blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest) {
- ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
+ ERR_FAIL_COND_MSG(p_src.is_null(), "Cannot blit_rect an image: invalid source Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
ERR_FAIL_COND(dsize == 0);
@@ -2823,8 +2823,8 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const P
}
void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest) {
- ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
- ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object.");
+ ERR_FAIL_COND_MSG(p_src.is_null(), "Cannot blit_rect_mask an image: invalid source Image object.");
+ ERR_FAIL_COND_MSG(p_mask.is_null(), "Cannot blit_rect_mask an image: invalid mask Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
int maskdsize = p_mask->data.size();
@@ -2873,7 +2873,7 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
}
void Image::blend_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest) {
- ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
+ ERR_FAIL_COND_MSG(p_src.is_null(), "Cannot blend_rect an image: invalid source Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
ERR_FAIL_COND(dsize == 0);
@@ -2908,8 +2908,8 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const
}
void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest) {
- ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
- ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object.");
+ ERR_FAIL_COND_MSG(p_src.is_null(), "Cannot blend_rect_mask an image: invalid source Image object.");
+ ERR_FAIL_COND_MSG(p_mask.is_null(), "Cannot blend_rect_mask an image: invalid mask Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
int maskdsize = p_mask->data.size();
@@ -3323,7 +3323,7 @@ void Image::adjust_bcs(float p_brightness, float p_contrast, float p_saturation)
}
Image::UsedChannels Image::detect_used_channels(CompressSource p_source) const {
- ERR_FAIL_COND_V(data.size() == 0, USED_CHANNELS_RGBA);
+ ERR_FAIL_COND_V(data.is_empty(), USED_CHANNELS_RGBA);
ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA);
bool r = false, g = false, b = false, a = false, c = false;
@@ -3878,7 +3878,7 @@ Error Image::load_ktx_from_buffer(const Vector<uint8_t> &p_array) {
void Image::convert_rg_to_ra_rgba8() {
ERR_FAIL_COND(format != FORMAT_RGBA8);
- ERR_FAIL_COND(!data.size());
+ ERR_FAIL_COND(data.is_empty());
int s = data.size();
uint8_t *w = data.ptrw();
@@ -3891,7 +3891,7 @@ void Image::convert_rg_to_ra_rgba8() {
void Image::convert_ra_rgba8_to_rg() {
ERR_FAIL_COND(format != FORMAT_RGBA8);
- ERR_FAIL_COND(!data.size());
+ ERR_FAIL_COND(data.is_empty());
int s = data.size();
uint8_t *w = data.ptrw();
@@ -3904,7 +3904,7 @@ void Image::convert_ra_rgba8_to_rg() {
void Image::convert_rgba8_to_bgra8() {
ERR_FAIL_COND(format != FORMAT_RGBA8);
- ERR_FAIL_COND(!data.size());
+ ERR_FAIL_COND(data.is_empty());
int s = data.size();
uint8_t *w = data.ptrw();
diff --git a/core/io/image.h b/core/io/image.h
index be308b0ac1..e35b359a79 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -431,7 +431,7 @@ public:
void set_as_black();
void copy_internals_from(const Ref<Image> &p_image) {
- ERR_FAIL_COND_MSG(p_image.is_null(), "It's not a reference to a valid Image object.");
+ ERR_FAIL_COND_MSG(p_image.is_null(), "Cannot copy image internals: invalid Image object.");
format = p_image->format;
width = p_image->width;
height = p_image->height;
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index c6452f1033..bef515f259 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -81,7 +81,7 @@ void ImageFormatLoaderExtension::_bind_methods() {
}
Error ImageLoader::load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom, BitField<ImageFormatLoader::LoaderFlags> p_flags, float p_scale) {
- ERR_FAIL_COND_V_MSG(p_image.is_null(), ERR_INVALID_PARAMETER, "It's not a reference to a valid Image object.");
+ ERR_FAIL_COND_V_MSG(p_image.is_null(), ERR_INVALID_PARAMETER, "Can't load an image: invalid Image object.");
Ref<FileAccess> f = p_custom;
if (f.is_null()) {
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index 48806fba73..0329ace313 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -318,9 +318,9 @@ int PacketPeerStream::get_output_buffer_max_size() const {
}
PacketPeerStream::PacketPeerStream() {
- int rbsize = GLOBAL_GET("network/limits/packet_peer_stream/max_buffer_po2");
+ int64_t rbsize = GLOBAL_GET("network/limits/packet_peer_stream/max_buffer_po2");
ring_buffer.resize(rbsize);
- input_buffer.resize(1 << rbsize);
- output_buffer.resize(1 << rbsize);
+ input_buffer.resize(int64_t(1) << rbsize);
+ output_buffer.resize(int64_t(1) << rbsize);
}
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index ba11d84bce..2fb3bda87d 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -36,6 +36,7 @@
#include "core/object/script_language.h"
#include "core/os/condition_variable.h"
#include "core/os/os.h"
+#include "core/os/safe_binary_mutex.h"
#include "core/string/print_string.h"
#include "core/string/translation.h"
#include "core/variant/variant_parser.h"
@@ -244,11 +245,11 @@ Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_origin
thread_load_mutex.lock();
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);
+ E->value.sub_tasks.insert(p_original_path);
}
thread_load_mutex.unlock();
}
- load_paths_stack->push_back(p_path);
+ load_paths_stack->push_back(p_original_path);
// Try all loaders and pick the first match for the type hint
bool found = false;
@@ -509,20 +510,20 @@ Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start(const String &p_path,
float ResourceLoader::_dependency_get_progress(const String &p_path) {
if (thread_load_tasks.has(p_path)) {
ThreadLoadTask &load_task = thread_load_tasks[p_path];
+ float current_progress = 0.0;
int dep_count = load_task.sub_tasks.size();
if (dep_count > 0) {
- float dep_progress = 0;
for (const String &E : load_task.sub_tasks) {
- dep_progress += _dependency_get_progress(E);
+ current_progress += _dependency_get_progress(E);
}
- dep_progress /= float(dep_count);
- dep_progress *= 0.5;
- dep_progress += load_task.progress * 0.5;
- return dep_progress;
+ current_progress /= float(dep_count);
+ current_progress *= 0.5;
+ current_progress += load_task.progress * 0.5;
} else {
- return load_task.progress;
+ current_progress = load_task.progress;
}
-
+ load_task.max_reported_progress = MAX(load_task.max_reported_progress, current_progress);
+ return load_task.max_reported_progress;
} else {
return 1.0; //assume finished loading it so it no longer exists
}
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 3c32a19066..3099d9aab3 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -39,6 +39,9 @@
class ConditionVariable;
+template <int Tag>
+class SafeBinaryMutex;
+
class ResourceFormatLoader : public RefCounted {
GDCLASS(ResourceFormatLoader, RefCounted);
@@ -167,7 +170,8 @@ private:
String remapped_path;
String dependent_path;
String type_hint;
- float progress = 0.0;
+ float progress = 0.0f;
+ float max_reported_progress = 0.0f;
ThreadLoadStatus status = THREAD_LOAD_IN_PROGRESS;
ResourceFormatLoader::CacheMode cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE;
Error error = OK;
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index faf7d75172..06888c7cda 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -454,7 +454,7 @@ bool XMLParser::is_empty() const {
}
Error XMLParser::open_buffer(const Vector<uint8_t> &p_buffer) {
- ERR_FAIL_COND_V(p_buffer.size() == 0, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(p_buffer.is_empty(), ERR_INVALID_DATA);
if (data_copy) {
memdelete_arr(data_copy);
diff --git a/core/math/aabb.h b/core/math/aabb.h
index 859810df37..cea845bf7c 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -200,11 +200,11 @@ inline bool AABB::encloses(const AABB &p_aabb) const {
return (
(src_min.x <= dst_min.x) &&
- (src_max.x > dst_max.x) &&
+ (src_max.x >= dst_max.x) &&
(src_min.y <= dst_min.y) &&
- (src_max.y > dst_max.y) &&
+ (src_max.y >= dst_max.y) &&
(src_min.z <= dst_min.z) &&
- (src_max.z > dst_max.z));
+ (src_max.z >= dst_max.z));
}
Vector3 AABB::get_support(const Vector3 &p_normal) const {
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index cd8c87b158..1ff6cdd588 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -722,7 +722,7 @@ Basis::operator String() const {
Quaternion Basis::get_quaternion() const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors.");
+ ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis " + operator String() + " must be normalized in order to be casted to a Quaternion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors.");
#endif
/* Allow getting a quaternion from an unnormalized transform */
Basis m = *this;
@@ -849,7 +849,7 @@ void Basis::set_quaternion(const Quaternion &p_quaternion) {
void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_angle) {
// Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_angle
#ifdef MATH_CHECKS
- ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
+ ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 " + p_axis.operator String() + " must be normalized.");
#endif
Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z);
real_t cosine = Math::cos(p_angle);
diff --git a/core/math/convex_hull.cpp b/core/math/convex_hull.cpp
index 68d995fe67..478fde3a64 100644
--- a/core/math/convex_hull.cpp
+++ b/core/math/convex_hull.cpp
@@ -344,31 +344,31 @@ public:
Rational128(int64_t p_value) {
if (p_value > 0) {
sign = 1;
- this->numerator = p_value;
+ numerator = p_value;
} else if (p_value < 0) {
sign = -1;
- this->numerator = -p_value;
+ numerator = -p_value;
} else {
sign = 0;
- this->numerator = (uint64_t)0;
+ numerator = (uint64_t)0;
}
- this->denominator = (uint64_t)1;
+ denominator = (uint64_t)1;
is_int_64 = true;
}
Rational128(const Int128 &p_numerator, const Int128 &p_denominator) {
sign = p_numerator.get_sign();
if (sign >= 0) {
- this->numerator = p_numerator;
+ numerator = p_numerator;
} else {
- this->numerator = -p_numerator;
+ numerator = -p_numerator;
}
int32_t dsign = p_denominator.get_sign();
if (dsign >= 0) {
- this->denominator = p_denominator;
+ denominator = p_denominator;
} else {
sign = -sign;
- this->denominator = -p_denominator;
+ denominator = -p_denominator;
}
is_int_64 = false;
}
diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp
index 74cb92539a..1e5f12bebf 100644
--- a/core/math/geometry_2d.cpp
+++ b/core/math/geometry_2d.cpp
@@ -93,7 +93,7 @@ void Geometry2D::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_re
// For example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a
// 256x8192 atlas (won't work anywhere).
- ERR_FAIL_COND(p_rects.size() == 0);
+ ERR_FAIL_COND(p_rects.is_empty());
for (int i = 0; i < p_rects.size(); i++) {
ERR_FAIL_COND(p_rects[i].width <= 0);
ERR_FAIL_COND(p_rects[i].height <= 0);
diff --git a/core/math/geometry_2d.h b/core/math/geometry_2d.h
index b37fce9e9c..9907d579a5 100644
--- a/core/math/geometry_2d.h
+++ b/core/math/geometry_2d.h
@@ -119,6 +119,10 @@ public:
}
}
+ static real_t get_distance_to_segment(const Vector2 &p_point, const Vector2 *p_segment) {
+ return p_point.distance_to(get_closest_point_to_segment(p_point, p_segment));
+ }
+
static bool is_point_in_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) {
Vector2 an = a - s;
Vector2 bn = b - s;
@@ -249,6 +253,28 @@ public:
return -1;
}
+ static bool segment_intersects_rect(const Vector2 &p_from, const Vector2 &p_to, const Rect2 &p_rect) {
+ if (p_rect.has_point(p_from) || p_rect.has_point(p_to)) {
+ return true;
+ }
+
+ const Vector2 rect_points[4] = {
+ p_rect.position,
+ p_rect.position + Vector2(p_rect.size.x, 0),
+ p_rect.position + p_rect.size,
+ p_rect.position + Vector2(0, p_rect.size.y)
+ };
+
+ // Check if any of the rect's edges intersect the segment.
+ for (int i = 0; i < 4; i++) {
+ if (segment_intersects_segment(p_from, p_to, rect_points[i], rect_points[(i + 1) % 4], nullptr)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
enum PolyBooleanOperation {
OPERATION_UNION,
OPERATION_DIFFERENCE,
diff --git a/core/math/quaternion.cpp b/core/math/quaternion.cpp
index e4ad17c8ef..cbaaa1371a 100644
--- a/core/math/quaternion.cpp
+++ b/core/math/quaternion.cpp
@@ -41,7 +41,7 @@ real_t Quaternion::angle_to(const Quaternion &p_to) const {
Vector3 Quaternion::get_euler(EulerOrder p_order) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion " + operator String() + " must be normalized.");
#endif
return Basis(*this).get_euler(p_order);
}
@@ -88,7 +88,7 @@ bool Quaternion::is_normalized() const {
Quaternion Quaternion::inverse() const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion " + operator String() + " must be normalized.");
#endif
return Quaternion(-x, -y, -z, w);
}
@@ -112,8 +112,8 @@ Quaternion Quaternion::exp() const {
Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized.");
#endif
Quaternion to1;
real_t omega, cosom, sinom, scale0, scale1;
@@ -153,8 +153,8 @@ Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) con
Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized.");
#endif
const Quaternion &from = *this;
@@ -177,8 +177,8 @@ Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) c
Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized.");
#endif
Quaternion from_q = *this;
Quaternion pre_q = p_pre_a;
@@ -228,8 +228,8 @@ Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const
Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight,
const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized.");
#endif
Quaternion from_q = *this;
Quaternion pre_q = p_pre_a;
@@ -294,7 +294,7 @@ real_t Quaternion::get_angle() const {
Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
+ ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 " + p_axis.operator String() + " must be normalized.");
#endif
real_t d = p_axis.length();
if (d == 0) {
diff --git a/core/math/quaternion.h b/core/math/quaternion.h
index ea952304a5..f8133df559 100644
--- a/core/math/quaternion.h
+++ b/core/math/quaternion.h
@@ -33,8 +33,7 @@
#include "core/math/math_funcs.h"
#include "core/math/vector3.h"
-
-class String;
+#include "core/string/ustring.h"
struct _NO_DISCARD_ Quaternion {
union {
@@ -90,7 +89,7 @@ struct _NO_DISCARD_ Quaternion {
_FORCE_INLINE_ Vector3 xform(const Vector3 &v) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion " + operator String() + " must be normalized.");
#endif
Vector3 u(x, y, z);
Vector3 uv = u.cross(v);
diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp
index df8c804243..74631d3e29 100644
--- a/core/math/vector2.cpp
+++ b/core/math/vector2.cpp
@@ -162,9 +162,9 @@ Vector2 Vector2::move_toward(const Vector2 &p_to, const real_t p_delta) const {
// slide returns the component of the vector along the given plane, specified by its normal vector.
Vector2 Vector2::slide(const Vector2 &p_normal) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 " + p_normal.operator String() + "must be normalized.");
#endif
- return *this - p_normal * this->dot(p_normal);
+ return *this - p_normal * dot(p_normal);
}
Vector2 Vector2::bounce(const Vector2 &p_normal) const {
@@ -173,9 +173,9 @@ Vector2 Vector2::bounce(const Vector2 &p_normal) const {
Vector2 Vector2::reflect(const Vector2 &p_normal) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 " + p_normal.operator String() + "must be normalized.");
#endif
- return 2.0f * p_normal * this->dot(p_normal) - *this;
+ return 2.0f * p_normal * dot(p_normal) - *this;
}
bool Vector2::is_equal_approx(const Vector2 &p_v) const {
diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp
index ae009fc4ef..c483d659a3 100644
--- a/core/math/vector3.cpp
+++ b/core/math/vector3.cpp
@@ -109,7 +109,7 @@ Vector3 Vector3::octahedron_decode(const Vector2 &p_oct) {
Vector2 Vector3::octahedron_tangent_encode(const float sign) const {
const float bias = 1.0f / 32767.0f;
- Vector2 res = this->octahedron_encode();
+ Vector2 res = octahedron_encode();
res.y = MAX(res.y, bias);
res.y = res.y * 0.5f + 0.5f;
res.y = sign >= 0.0f ? res.y : 1 - res.y;
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 18943a820f..5d4e2c7d87 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -33,8 +33,8 @@
#include "core/error/error_macros.h"
#include "core/math/math_funcs.h"
+#include "core/string/ustring.h"
-class String;
struct Basis;
struct Vector2;
struct Vector3i;
@@ -512,9 +512,9 @@ void Vector3::zero() {
// slide returns the component of the vector along the given plane, specified by its normal vector.
Vector3 Vector3::slide(const Vector3 &p_normal) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 " + p_normal.operator String() + " must be normalized.");
#endif
- return *this - p_normal * this->dot(p_normal);
+ return *this - p_normal * dot(p_normal);
}
Vector3 Vector3::bounce(const Vector3 &p_normal) const {
@@ -523,9 +523,9 @@ Vector3 Vector3::bounce(const Vector3 &p_normal) const {
Vector3 Vector3::reflect(const Vector3 &p_normal) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 " + p_normal.operator String() + " must be normalized.");
#endif
- return 2.0f * p_normal * this->dot(p_normal) - *this;
+ return 2.0f * p_normal * dot(p_normal) - *this;
}
#endif // VECTOR3_H
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index bf1bd0de93..45fbb19f88 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -31,6 +31,7 @@
#include "class_db.h"
#include "core/config/engine.h"
+#include "core/core_string_names.h"
#include "core/io/resource_loader.h"
#include "core/object/script_language.h"
#include "core/os/mutex.h"
@@ -1299,6 +1300,12 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia
check = check->inherits_ptr;
}
+ // The "free()" method is special, so we assume it exists and return a Callable.
+ if (p_property == CoreStringNames::get_singleton()->_free) {
+ r_value = Callable(p_object, p_property);
+ return true;
+ }
+
return false;
}
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 7a4ee1afa4..21243230de 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -188,7 +188,7 @@ public:
template <class T>
static void register_class(bool p_virtual = false) {
GLOBAL_LOCK_FUNCTION;
- static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
+ static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_NULL(t);
@@ -203,7 +203,7 @@ public:
template <class T>
static void register_abstract_class() {
GLOBAL_LOCK_FUNCTION;
- static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
+ static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_NULL(t);
@@ -216,7 +216,7 @@ public:
template <class T>
static void register_internal_class() {
GLOBAL_LOCK_FUNCTION;
- static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
+ static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_NULL(t);
@@ -239,7 +239,7 @@ public:
template <class T>
static void register_custom_instance_class() {
GLOBAL_LOCK_FUNCTION;
- static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
+ static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_NULL(t);
@@ -296,7 +296,7 @@ public:
argptrs[i] = &args[i];
}
MethodBind *bind = create_method_bind(p_method);
- if constexpr (std::is_same<typename member_function_traits<M>::return_type, Object *>::value) {
+ if constexpr (std::is_same_v<typename member_function_traits<M>::return_type, Object *>) {
bind->set_return_type_is_raw_object_ptr(true);
}
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, false, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
@@ -311,7 +311,7 @@ public:
}
MethodBind *bind = create_static_method_bind(p_method);
bind->set_instance_class(p_class);
- if constexpr (std::is_same<typename member_function_traits<M>::return_type, Object *>::value) {
+ if constexpr (std::is_same_v<typename member_function_traits<M>::return_type, Object *>) {
bind->set_return_type_is_raw_object_ptr(true);
}
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, false, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
@@ -325,7 +325,7 @@ public:
argptrs[i] = &args[i];
}
MethodBind *bind = create_method_bind(p_method);
- if constexpr (std::is_same<typename member_function_traits<M>::return_type, Object *>::value) {
+ if constexpr (std::is_same_v<typename member_function_traits<M>::return_type, Object *>) {
bind->set_return_type_is_raw_object_ptr(true);
}
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, true, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
@@ -340,7 +340,7 @@ public:
}
MethodBind *bind = create_static_method_bind(p_method);
bind->set_instance_class(p_class);
- if constexpr (std::is_same<typename member_function_traits<M>::return_type, Object *>::value) {
+ if constexpr (std::is_same_v<typename member_function_traits<M>::return_type, Object *>) {
bind->set_return_type_is_raw_object_ptr(true);
}
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, true, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
@@ -353,7 +353,7 @@ public:
MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
ERR_FAIL_NULL_V(bind, nullptr);
- if constexpr (std::is_same<typename member_function_traits<M>::return_type, Object *>::value) {
+ if constexpr (std::is_same_v<typename member_function_traits<M>::return_type, Object *>) {
bind->set_return_type_is_raw_object_ptr(true);
}
return _bind_vararg_method(bind, p_name, p_default_args, false);
@@ -366,7 +366,7 @@ public:
MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
ERR_FAIL_NULL_V(bind, nullptr);
- if constexpr (std::is_same<typename member_function_traits<M>::return_type, Object *>::value) {
+ if constexpr (std::is_same_v<typename member_function_traits<M>::return_type, Object *>) {
bind->set_return_type_is_raw_object_ptr(true);
}
return _bind_vararg_method(bind, p_name, p_default_args, true);
diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp
index a394c957d0..83a19554dc 100644
--- a/core/object/message_queue.cpp
+++ b/core/object/message_queue.cpp
@@ -40,12 +40,12 @@
#ifdef DEV_ENABLED
// Includes safety checks to ensure that a queue set as a thread singleton override
// is only ever called from the thread it was set for.
-#define LOCK_MUTEX \
- if (this != MessageQueue::thread_singleton) { \
- DEV_ASSERT(!this->is_current_thread_override); \
- mutex.lock(); \
- } else { \
- DEV_ASSERT(this->is_current_thread_override); \
+#define LOCK_MUTEX \
+ if (this != MessageQueue::thread_singleton) { \
+ DEV_ASSERT(!is_current_thread_override); \
+ mutex.lock(); \
+ } else { \
+ DEV_ASSERT(is_current_thread_override); \
}
#else
#define LOCK_MUTEX \
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 5a776e2106..cc33d0ab8a 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -728,7 +728,7 @@ Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_
r_error.expected = 0;
return Variant();
}
- if (Object::cast_to<RefCounted>(this)) {
+ if (is_ref_counted()) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
ERR_FAIL_V_MSG(Variant(), "Can't 'free' a reference.");
}
@@ -1683,6 +1683,7 @@ void Object::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_POSTINITIALIZE);
BIND_CONSTANT(NOTIFICATION_PREDELETE);
+ BIND_CONSTANT(NOTIFICATION_EXTENSION_RELOADED);
BIND_ENUM_CONSTANT(CONNECT_DEFERRED);
BIND_ENUM_CONSTANT(CONNECT_PERSIST);
diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h
index 228373d662..10be27b879 100644
--- a/core/object/ref_counted.h
+++ b/core/object/ref_counted.h
@@ -212,8 +212,9 @@ public:
reference = nullptr;
}
- void instantiate() {
- ref(memnew(T));
+ template <typename... VarArgs>
+ void instantiate(VarArgs... p_params) {
+ ref(memnew(T(p_params...)));
}
Ref() {}
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 0b2d5e41cf..3b9b1f9094 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -168,6 +168,18 @@ ScriptLanguage *ScriptServer::get_language(int p_idx) {
return _languages[p_idx];
}
+ScriptLanguage *ScriptServer::get_language_for_extension(const String &p_extension) {
+ MutexLock lock(languages_mutex);
+
+ for (int i = 0; i < _language_count; i++) {
+ if (_languages[i] && _languages[i]->get_extension() == p_extension) {
+ return _languages[i];
+ }
+ }
+
+ return nullptr;
+}
+
Error ScriptServer::register_language(ScriptLanguage *p_language) {
MutexLock lock(languages_mutex);
ERR_FAIL_NULL_V(p_language, ERR_INVALID_PARAMETER);
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 66106bf139..294231a3e7 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -75,6 +75,7 @@ public:
static bool is_scripting_enabled();
_FORCE_INLINE_ static int get_language_count() { return _language_count; }
static ScriptLanguage *get_language(int p_idx);
+ static ScriptLanguage *get_language_for_extension(const String &p_extension);
static Error register_language(ScriptLanguage *p_language);
static Error unregister_language(const ScriptLanguage *p_language);
@@ -371,6 +372,7 @@ public:
virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); }
virtual void reload_all_scripts() = 0;
+ virtual void reload_scripts(const Array &p_scripts, bool p_soft_reload) = 0;
virtual void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) = 0;
/* LOADER FUNCTIONS */
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index 8b01667519..5b10739486 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -562,6 +562,7 @@ public:
}
EXBIND0(reload_all_scripts)
+ EXBIND2(reload_scripts, const Array &, bool)
EXBIND2(reload_tool_script, const Ref<Script> &, bool)
/* LOADER FUNCTIONS */
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index 3c1d4ef95e..569e6ae19f 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -316,6 +316,14 @@ void UndoRedo::commit_action(bool p_execute) {
_redo(p_execute); // perform action
committing--;
+ if (max_steps > 0) {
+ // Clear early steps.
+
+ while (actions.size() > max_steps) {
+ _pop_history_tail();
+ }
+ }
+
if (add_message && callback && actions.size() > 0) {
callback(callback_ud, actions[actions.size() - 1].name);
}
@@ -473,6 +481,14 @@ uint64_t UndoRedo::get_version() const {
return version;
}
+void UndoRedo::set_max_steps(int p_max_steps) {
+ max_steps = p_max_steps;
+}
+
+int UndoRedo::get_max_steps() const {
+ return max_steps;
+}
+
void UndoRedo::set_commit_notify_callback(CommitNotifyCallback p_callback, void *p_ud) {
callback = p_callback;
callback_ud = p_ud;
@@ -517,9 +533,13 @@ void UndoRedo::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_undo"), &UndoRedo::has_undo);
ClassDB::bind_method(D_METHOD("has_redo"), &UndoRedo::has_redo);
ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version);
+ ClassDB::bind_method(D_METHOD("set_max_steps", "max_steps"), &UndoRedo::set_max_steps);
+ ClassDB::bind_method(D_METHOD("get_max_steps"), &UndoRedo::get_max_steps);
ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo);
ClassDB::bind_method(D_METHOD("undo"), &UndoRedo::undo);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_steps", PROPERTY_HINT_RANGE, "0,50,1,or_greater"), "set_max_steps", "get_max_steps");
+
ADD_SIGNAL(MethodInfo("version_changed"));
BIND_ENUM_CONSTANT(MERGE_DISABLE);
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index b3a3322e4b..62aebff877 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -80,6 +80,7 @@ private:
int current_action = -1;
bool force_keep_in_merge_ends = false;
int action_level = 0;
+ int max_steps = 0;
MergeMode merge_mode = MERGE_DISABLE;
bool merging = false;
uint64_t version = 1;
@@ -135,6 +136,9 @@ public:
uint64_t get_version() const;
+ void set_max_steps(int p_max_steps);
+ int get_max_steps() const;
+
void set_commit_notify_callback(CommitNotifyCallback p_callback, void *p_ud);
void set_method_notify_callback(MethodNotifyCallback p_method_callback, void *p_ud);
diff --git a/core/object/worker_thread_pool.cpp b/core/object/worker_thread_pool.cpp
index 8e8a2ef06b..e2ab473b01 100644
--- a/core/object/worker_thread_pool.cpp
+++ b/core/object/worker_thread_pool.cpp
@@ -47,6 +47,7 @@ WorkerThreadPool *WorkerThreadPool::singleton = nullptr;
thread_local CommandQueueMT *WorkerThreadPool::flushing_cmd_queue = nullptr;
void WorkerThreadPool::_process_task(Task *p_task) {
+#ifdef THREADS_ENABLED
int pool_thread_index = thread_ids[Thread::get_caller_id()];
ThreadData &curr_thread = threads[pool_thread_index];
Task *prev_task = nullptr; // In case this is recursively called.
@@ -69,6 +70,7 @@ void WorkerThreadPool::_process_task(Task *p_task) {
curr_thread.current_task = p_task;
task_mutex.unlock();
}
+#endif
if (p_task->group) {
// Handling a group
@@ -143,6 +145,7 @@ void WorkerThreadPool::_process_task(Task *p_task) {
}
}
+#ifdef THREADS_ENABLED
{
curr_thread.current_task = prev_task;
if (p_task->low_priority) {
@@ -159,6 +162,7 @@ void WorkerThreadPool::_process_task(Task *p_task) {
}
set_current_thread_safe_for_nodes(safe_for_nodes_backup);
+#endif
}
void WorkerThreadPool::_thread_function(void *p_user) {
@@ -542,6 +546,7 @@ bool WorkerThreadPool::is_group_task_completed(GroupID p_group) const {
}
void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) {
+#ifdef THREADS_ENABLED
task_mutex.lock();
Group **groupp = groups.getptr(p_group);
task_mutex.unlock();
@@ -574,6 +579,7 @@ void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) {
task_mutex.lock(); // This mutex is needed when Physics 2D and/or 3D is selected to run on a separate thread.
groups.erase(p_group);
task_mutex.unlock();
+#endif
}
int WorkerThreadPool::get_thread_index() {
diff --git a/core/os/condition_variable.h b/core/os/condition_variable.h
index 6a49ced31b..2b6b272e18 100644
--- a/core/os/condition_variable.h
+++ b/core/os/condition_variable.h
@@ -33,6 +33,8 @@
#include "core/os/mutex.h"
+#ifdef THREADS_ENABLED
+
#ifdef MINGW_ENABLED
#define MINGW_STDTHREAD_REDUNDANCY_WARNING
#include "thirdparty/mingw-std-threads/mingw.condition_variable.h"
@@ -66,4 +68,16 @@ public:
}
};
+#else // No threads.
+
+class ConditionVariable {
+public:
+ template <class BinaryMutexT>
+ void wait(const MutexLock<BinaryMutexT> &p_lock) const {}
+ void notify_one() const {}
+ void notify_all() const {}
+};
+
+#endif // THREADS_ENABLED
+
#endif // CONDITION_VARIABLE_H
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index 785972d31d..2051973336 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -260,6 +260,12 @@ enum class KeyModifierMask {
GROUP_SWITCH = (1 << 30)
};
+enum class KeyLocation {
+ UNSPECIFIED,
+ LEFT,
+ RIGHT
+};
+
// To avoid having unnecessary operators, only define the ones that are needed.
constexpr Key operator-(uint32_t a, Key b) {
diff --git a/core/os/memory.cpp b/core/os/memory.cpp
index 5f6216a5f1..32c316e58e 100644
--- a/core/os/memory.cpp
+++ b/core/os/memory.cpp
@@ -72,23 +72,23 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
bool prepad = p_pad_align;
#endif
- void *mem = malloc(p_bytes + (prepad ? PAD_ALIGN : 0));
+ void *mem = malloc(p_bytes + (prepad ? DATA_OFFSET : 0));
ERR_FAIL_NULL_V(mem, nullptr);
alloc_count.increment();
if (prepad) {
- uint64_t *s = (uint64_t *)mem;
- *s = p_bytes;
-
uint8_t *s8 = (uint8_t *)mem;
+ uint64_t *s = (uint64_t *)(s8 + SIZE_OFFSET);
+ *s = p_bytes;
+
#ifdef DEBUG_ENABLED
uint64_t new_mem_usage = mem_usage.add(p_bytes);
max_usage.exchange_if_greater(new_mem_usage);
#endif
- return s8 + PAD_ALIGN;
+ return s8 + DATA_OFFSET;
} else {
return mem;
}
@@ -108,8 +108,8 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
#endif
if (prepad) {
- mem -= PAD_ALIGN;
- uint64_t *s = (uint64_t *)mem;
+ mem -= DATA_OFFSET;
+ uint64_t *s = (uint64_t *)(mem + SIZE_OFFSET);
#ifdef DEBUG_ENABLED
if (p_bytes > *s) {
@@ -126,14 +126,14 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
} else {
*s = p_bytes;
- mem = (uint8_t *)realloc(mem, p_bytes + PAD_ALIGN);
+ mem = (uint8_t *)realloc(mem, p_bytes + DATA_OFFSET);
ERR_FAIL_NULL_V(mem, nullptr);
- s = (uint64_t *)mem;
+ s = (uint64_t *)(mem + SIZE_OFFSET);
*s = p_bytes;
- return mem + PAD_ALIGN;
+ return mem + DATA_OFFSET;
}
} else {
mem = (uint8_t *)realloc(mem, p_bytes);
@@ -158,10 +158,10 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) {
alloc_count.decrement();
if (prepad) {
- mem -= PAD_ALIGN;
+ mem -= DATA_OFFSET;
#ifdef DEBUG_ENABLED
- uint64_t *s = (uint64_t *)mem;
+ uint64_t *s = (uint64_t *)(mem + SIZE_OFFSET);
mem_usage.sub(*s);
#endif
diff --git a/core/os/memory.h b/core/os/memory.h
index a0524b0ea2..6f3f6fed39 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -38,10 +38,6 @@
#include <new>
#include <type_traits>
-#ifndef PAD_ALIGN
-#define PAD_ALIGN 16 //must always be greater than this at much
-#endif
-
class Memory {
#ifdef DEBUG_ENABLED
static SafeNumeric<uint64_t> mem_usage;
@@ -51,6 +47,17 @@ class Memory {
static SafeNumeric<uint64_t> alloc_count;
public:
+ // Alignment: ↓ max_align_t ↓ uint64_t ↓ max_align_t
+ // ┌─────────────────┬──┬────────────────┬──┬───────────...
+ // │ uint64_t │░░│ uint64_t │░░│ T[]
+ // │ alloc size │░░│ element count │░░│ data
+ // └─────────────────┴──┴────────────────┴──┴───────────...
+ // Offset: ↑ SIZE_OFFSET ↑ ELEMENT_OFFSET ↑ DATA_OFFSET
+
+ static constexpr size_t SIZE_OFFSET = 0;
+ static constexpr size_t ELEMENT_OFFSET = ((SIZE_OFFSET + sizeof(uint64_t)) % alignof(uint64_t) == 0) ? (SIZE_OFFSET + sizeof(uint64_t)) : ((SIZE_OFFSET + sizeof(uint64_t)) + alignof(uint64_t) - ((SIZE_OFFSET + sizeof(uint64_t)) % alignof(uint64_t)));
+ static constexpr size_t DATA_OFFSET = ((ELEMENT_OFFSET + sizeof(uint64_t)) % alignof(max_align_t) == 0) ? (ELEMENT_OFFSET + sizeof(uint64_t)) : ((ELEMENT_OFFSET + sizeof(uint64_t)) + alignof(max_align_t) - ((ELEMENT_OFFSET + sizeof(uint64_t)) % alignof(max_align_t)));
+
static void *alloc_static(size_t p_bytes, bool p_pad_align = false);
static void *realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align = false);
static void free_static(void *p_ptr, bool p_pad_align = false);
@@ -105,7 +112,7 @@ void memdelete(T *p_class) {
if (!predelete_handler(p_class)) {
return; // doesn't want to be deleted
}
- if (!std::is_trivially_destructible<T>::value) {
+ if constexpr (!std::is_trivially_destructible_v<T>) {
p_class->~T();
}
@@ -117,7 +124,7 @@ void memdelete_allocator(T *p_class) {
if (!predelete_handler(p_class)) {
return; // doesn't want to be deleted
}
- if (!std::is_trivially_destructible<T>::value) {
+ if constexpr (!std::is_trivially_destructible_v<T>) {
p_class->~T();
}
@@ -133,6 +140,10 @@ void memdelete_allocator(T *p_class) {
#define memnew_arr(m_class, m_count) memnew_arr_template<m_class>(m_count)
+_FORCE_INLINE_ uint64_t *_get_element_count_ptr(uint8_t *p_ptr) {
+ return (uint64_t *)(p_ptr - Memory::DATA_OFFSET + Memory::ELEMENT_OFFSET);
+}
+
template <typename T>
T *memnew_arr_template(size_t p_elements) {
if (p_elements == 0) {
@@ -142,12 +153,14 @@ T *memnew_arr_template(size_t p_elements) {
same strategy used by std::vector, and the Vector class, so it should be safe.*/
size_t len = sizeof(T) * p_elements;
- uint64_t *mem = (uint64_t *)Memory::alloc_static(len, true);
+ uint8_t *mem = (uint8_t *)Memory::alloc_static(len, true);
T *failptr = nullptr; //get rid of a warning
ERR_FAIL_NULL_V(mem, failptr);
- *(mem - 1) = p_elements;
- if (!std::is_trivially_constructible<T>::value) {
+ uint64_t *_elem_count_ptr = _get_element_count_ptr(mem);
+ *(_elem_count_ptr) = p_elements;
+
+ if constexpr (!std::is_trivially_constructible_v<T>) {
T *elems = (T *)mem;
/* call operator new */
@@ -166,16 +179,18 @@ T *memnew_arr_template(size_t p_elements) {
template <typename T>
size_t memarr_len(const T *p_class) {
- uint64_t *ptr = (uint64_t *)p_class;
- return *(ptr - 1);
+ uint8_t *ptr = (uint8_t *)p_class;
+ uint64_t *_elem_count_ptr = _get_element_count_ptr(ptr);
+ return *(_elem_count_ptr);
}
template <typename T>
void memdelete_arr(T *p_class) {
- uint64_t *ptr = (uint64_t *)p_class;
+ uint8_t *ptr = (uint8_t *)p_class;
- if (!std::is_trivially_destructible<T>::value) {
- uint64_t elem_count = *(ptr - 1);
+ if constexpr (!std::is_trivially_destructible_v<T>) {
+ uint64_t *_elem_count_ptr = _get_element_count_ptr(ptr);
+ uint64_t elem_count = *(_elem_count_ptr);
for (uint64_t i = 0; i < elem_count; i++) {
p_class[i].~T();
diff --git a/core/os/mutex.cpp b/core/os/mutex.cpp
index 5d4e457c5f..9a8a2a2961 100644
--- a/core/os/mutex.cpp
+++ b/core/os/mutex.cpp
@@ -40,7 +40,11 @@ void _global_unlock() {
_global_mutex.unlock();
}
+#ifdef THREADS_ENABLED
+
template class MutexImpl<THREADING_NAMESPACE::recursive_mutex>;
template class MutexImpl<THREADING_NAMESPACE::mutex>;
template class MutexLock<MutexImpl<THREADING_NAMESPACE::recursive_mutex>>;
template class MutexLock<MutexImpl<THREADING_NAMESPACE::mutex>>;
+
+#endif
diff --git a/core/os/mutex.h b/core/os/mutex.h
index 03af48ca7c..a4eab0cd86 100644
--- a/core/os/mutex.h
+++ b/core/os/mutex.h
@@ -43,6 +43,8 @@
#define THREADING_NAMESPACE std
#endif
+#ifdef THREADS_ENABLED
+
template <class MutexT>
class MutexLock;
@@ -68,56 +70,6 @@ public:
}
};
-// A very special kind of mutex, used in scenarios where these
-// requirements hold at the same time:
-// - Must be used with a condition variable (only binary mutexes are suitable).
-// - Must have recursive semnantics (or simulate, as this one does).
-// The implementation keeps the lock count in TS. Therefore, only
-// one object of each version of the template can exists; hence the Tag argument.
-// Tags must be unique across the Godot codebase.
-// Also, don't forget to declare the thread_local variable on each use.
-template <int Tag>
-class SafeBinaryMutex {
- friend class MutexLock<SafeBinaryMutex>;
-
- using StdMutexType = THREADING_NAMESPACE::mutex;
-
- mutable THREADING_NAMESPACE::mutex mutex;
- static thread_local uint32_t count;
-
-public:
- _ALWAYS_INLINE_ void lock() const {
- if (++count == 1) {
- mutex.lock();
- }
- }
-
- _ALWAYS_INLINE_ void unlock() const {
- DEV_ASSERT(count);
- if (--count == 0) {
- mutex.unlock();
- }
- }
-
- _ALWAYS_INLINE_ bool try_lock() const {
- if (count) {
- count++;
- return true;
- } else {
- if (mutex.try_lock()) {
- count++;
- return true;
- } else {
- return false;
- }
- }
- }
-
- ~SafeBinaryMutex() {
- DEV_ASSERT(!count);
- }
-};
-
template <class MutexT>
class MutexLock {
friend class ConditionVariable;
@@ -125,26 +77,8 @@ class MutexLock {
THREADING_NAMESPACE::unique_lock<typename MutexT::StdMutexType> lock;
public:
- _ALWAYS_INLINE_ explicit MutexLock(const MutexT &p_mutex) :
- lock(p_mutex.mutex){};
-};
-
-// This specialization is needed so manual locking and MutexLock can be used
-// at the same time on a SafeBinaryMutex.
-template <int Tag>
-class MutexLock<SafeBinaryMutex<Tag>> {
- friend class ConditionVariable;
-
- THREADING_NAMESPACE::unique_lock<THREADING_NAMESPACE::mutex> lock;
-
-public:
- _ALWAYS_INLINE_ explicit MutexLock(const SafeBinaryMutex<Tag> &p_mutex) :
- lock(p_mutex.mutex) {
- SafeBinaryMutex<Tag>::count++;
- };
- _ALWAYS_INLINE_ ~MutexLock() {
- SafeBinaryMutex<Tag>::count--;
- };
+ explicit MutexLock(const MutexT &p_mutex) :
+ lock(p_mutex.mutex) {}
};
using Mutex = MutexImpl<THREADING_NAMESPACE::recursive_mutex>; // Recursive, for general use
@@ -155,4 +89,26 @@ extern template class MutexImpl<THREADING_NAMESPACE::mutex>;
extern template class MutexLock<MutexImpl<THREADING_NAMESPACE::recursive_mutex>>;
extern template class MutexLock<MutexImpl<THREADING_NAMESPACE::mutex>>;
+#else // No threads.
+
+class MutexImpl {
+ mutable THREADING_NAMESPACE::mutex mutex;
+
+public:
+ void lock() const {}
+ void unlock() const {}
+ bool try_lock() const { return true; }
+};
+
+template <class MutexT>
+class MutexLock {
+public:
+ MutexLock(const MutexT &p_mutex) {}
+};
+
+using Mutex = MutexImpl;
+using BinaryMutex = MutexImpl;
+
+#endif // THREADS_ENABLED
+
#endif // MUTEX_H
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 26ae286979..d5d9988cc1 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -504,6 +504,12 @@ bool OS::has_feature(const String &p_feature) {
}
#endif
+#ifdef THREADS_ENABLED
+ if (p_feature == "threads") {
+ return true;
+ }
+#endif
+
if (_check_internal_feature_support(p_feature)) {
return true;
}
diff --git a/core/os/safe_binary_mutex.h b/core/os/safe_binary_mutex.h
new file mode 100644
index 0000000000..1e98cc074c
--- /dev/null
+++ b/core/os/safe_binary_mutex.h
@@ -0,0 +1,124 @@
+/**************************************************************************/
+/* safe_binary_mutex.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 SAFE_BINARY_MUTEX_H
+#define SAFE_BINARY_MUTEX_H
+
+#include "core/error/error_macros.h"
+#include "core/os/mutex.h"
+#include "core/typedefs.h"
+
+#ifdef THREADS_ENABLED
+
+// A very special kind of mutex, used in scenarios where these
+// requirements hold at the same time:
+// - Must be used with a condition variable (only binary mutexes are suitable).
+// - Must have recursive semnantics (or simulate, as this one does).
+// The implementation keeps the lock count in TS. Therefore, only
+// one object of each version of the template can exists; hence the Tag argument.
+// Tags must be unique across the Godot codebase.
+// Also, don't forget to declare the thread_local variable on each use.
+template <int Tag>
+class SafeBinaryMutex {
+ friend class MutexLock<SafeBinaryMutex>;
+
+ using StdMutexType = THREADING_NAMESPACE::mutex;
+
+ mutable THREADING_NAMESPACE::mutex mutex;
+ static thread_local uint32_t count;
+
+public:
+ _ALWAYS_INLINE_ void lock() const {
+ if (++count == 1) {
+ mutex.lock();
+ }
+ }
+
+ _ALWAYS_INLINE_ void unlock() const {
+ DEV_ASSERT(count);
+ if (--count == 0) {
+ mutex.unlock();
+ }
+ }
+
+ _ALWAYS_INLINE_ bool try_lock() const {
+ if (count) {
+ count++;
+ return true;
+ } else {
+ if (mutex.try_lock()) {
+ count++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ ~SafeBinaryMutex() {
+ DEV_ASSERT(!count);
+ }
+};
+
+// This specialization is needed so manual locking and MutexLock can be used
+// at the same time on a SafeBinaryMutex.
+template <int Tag>
+class MutexLock<SafeBinaryMutex<Tag>> {
+ friend class ConditionVariable;
+
+ THREADING_NAMESPACE::unique_lock<THREADING_NAMESPACE::mutex> lock;
+
+public:
+ _ALWAYS_INLINE_ explicit MutexLock(const SafeBinaryMutex<Tag> &p_mutex) :
+ lock(p_mutex.mutex) {
+ SafeBinaryMutex<Tag>::count++;
+ };
+ _ALWAYS_INLINE_ ~MutexLock() {
+ SafeBinaryMutex<Tag>::count--;
+ };
+};
+
+#else // No threads.
+
+template <int Tag>
+class SafeBinaryMutex : public MutexImpl {
+ static thread_local uint32_t count;
+};
+
+template <int Tag>
+class MutexLock<SafeBinaryMutex<Tag>> {
+public:
+ MutexLock(const SafeBinaryMutex<Tag> &p_mutex) {}
+ ~MutexLock() {}
+};
+
+#endif // THREADS_ENABLED
+
+#endif // SAFE_BINARY_MUTEX_H
diff --git a/core/os/semaphore.h b/core/os/semaphore.h
index b8ae35b86b..19ef1dedc0 100644
--- a/core/os/semaphore.h
+++ b/core/os/semaphore.h
@@ -31,6 +31,10 @@
#ifndef SEMAPHORE_H
#define SEMAPHORE_H
+#include <cstdint>
+
+#ifdef THREADS_ENABLED
+
#include "core/error/error_list.h"
#include "core/typedefs.h"
#ifdef DEBUG_ENABLED
@@ -132,4 +136,17 @@ public:
#endif
};
+#else // No threads.
+
+class Semaphore {
+public:
+ void post(uint32_t p_count = 1) const {}
+ void wait() const {}
+ bool try_wait() const {
+ return true;
+ }
+};
+
+#endif // THREADS_ENABLED
+
#endif // SEMAPHORE_H
diff --git a/core/os/spin_lock.h b/core/os/spin_lock.h
index 93ea782b60..d386cd5890 100644
--- a/core/os/spin_lock.h
+++ b/core/os/spin_lock.h
@@ -33,6 +33,25 @@
#include "core/typedefs.h"
+#if defined(__APPLE__)
+
+#include <os/lock.h>
+
+class SpinLock {
+ mutable os_unfair_lock _lock = OS_UNFAIR_LOCK_INIT;
+
+public:
+ _ALWAYS_INLINE_ void lock() const {
+ os_unfair_lock_lock(&_lock);
+ }
+
+ _ALWAYS_INLINE_ void unlock() const {
+ os_unfair_lock_unlock(&_lock);
+ }
+};
+
+#else
+
#include <atomic>
class SpinLock {
@@ -49,4 +68,6 @@ public:
}
};
+#endif // __APPLE__
+
#endif // SPIN_LOCK_H
diff --git a/core/os/thread.cpp b/core/os/thread.cpp
index 2ba90ba42c..afc74364f6 100644
--- a/core/os/thread.cpp
+++ b/core/os/thread.cpp
@@ -33,19 +33,22 @@
#include "thread.h"
+#ifdef THREADS_ENABLED
#include "core/object/script_language.h"
#include "core/templates/safe_refcount.h"
-Thread::PlatformFunctions Thread::platform_functions;
-
SafeNumeric<uint64_t> Thread::id_counter(1); // The first value after .increment() is 2, hence by default the main thread ID should be 1.
thread_local Thread::ID Thread::caller_id = Thread::UNASSIGNED_ID;
+#endif
+
+Thread::PlatformFunctions Thread::platform_functions;
void Thread::_set_platform_functions(const PlatformFunctions &p_functions) {
platform_functions = p_functions;
}
+#ifdef THREADS_ENABLED
void Thread::callback(ID p_caller_id, const Settings &p_settings, Callback p_callback, void *p_userdata) {
Thread::caller_id = p_caller_id;
if (platform_functions.set_priority) {
@@ -107,4 +110,6 @@ Thread::~Thread() {
}
}
+#endif // THREADS_ENABLED
+
#endif // PLATFORM_THREAD_OVERRIDE
diff --git a/core/os/thread.h b/core/os/thread.h
index cc954678f9..a0ecc24c91 100644
--- a/core/os/thread.h
+++ b/core/os/thread.h
@@ -53,6 +53,8 @@
class String;
+#ifdef THREADS_ENABLED
+
class Thread {
public:
typedef void (*Callback)(void *p_userdata);
@@ -86,6 +88,8 @@ public:
private:
friend class Main;
+ static PlatformFunctions platform_functions;
+
ID id = UNASSIGNED_ID;
static SafeNumeric<uint64_t> id_counter;
static thread_local ID caller_id;
@@ -93,8 +97,6 @@ private:
static void callback(ID p_caller_id, const Settings &p_settings, Thread::Callback p_callback, void *p_userdata);
- static PlatformFunctions platform_functions;
-
static void make_main_thread() { caller_id = MAIN_ID; }
static void release_main_thread() { caller_id = UNASSIGNED_ID; }
@@ -125,6 +127,64 @@ public:
~Thread();
};
+#else // No threads.
+
+class Thread {
+public:
+ typedef void (*Callback)(void *p_userdata);
+
+ typedef uint64_t ID;
+
+ enum : ID {
+ UNASSIGNED_ID = 0,
+ MAIN_ID = 1
+ };
+
+ enum Priority {
+ PRIORITY_LOW,
+ PRIORITY_NORMAL,
+ PRIORITY_HIGH
+ };
+
+ struct Settings {
+ Priority priority;
+ Settings() { priority = PRIORITY_NORMAL; }
+ };
+
+ struct PlatformFunctions {
+ Error (*set_name)(const String &) = nullptr;
+ void (*set_priority)(Thread::Priority) = nullptr;
+ void (*init)() = nullptr;
+ void (*wrapper)(Thread::Callback, void *) = nullptr;
+ void (*term)() = nullptr;
+ };
+
+private:
+ friend class Main;
+
+ static PlatformFunctions platform_functions;
+
+ static void make_main_thread() {}
+ static void release_main_thread() {}
+
+public:
+ static void _set_platform_functions(const PlatformFunctions &p_functions);
+
+ _FORCE_INLINE_ ID get_id() const { return 0; }
+ _FORCE_INLINE_ static ID get_caller_id() { return MAIN_ID; }
+ _FORCE_INLINE_ static ID get_main_id() { return MAIN_ID; }
+
+ _FORCE_INLINE_ static bool is_main_thread() { return true; }
+
+ static Error set_name(const String &p_name) { return ERR_UNAVAILABLE; }
+
+ void start(Thread::Callback p_callback, void *p_user, const Settings &p_settings = Settings()) {}
+ bool is_started() const { return false; }
+ void wait_to_finish() {}
+};
+
+#endif // THREADS_ENABLED
+
#endif // THREAD_H
#endif // PLATFORM_THREAD_OVERRIDE
diff --git a/core/os/time.cpp b/core/os/time.cpp
index bad5cc2e4f..7068935d36 100644
--- a/core/os/time.cpp
+++ b/core/os/time.cpp
@@ -189,9 +189,6 @@ static const uint8_t MONTH_DAYS_TABLE[2][12] = {
Time *Time::singleton = nullptr;
Time *Time::get_singleton() {
- if (!singleton) {
- memnew(Time);
- }
return singleton;
}
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 82b3d27942..4c1ed8a69a 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -102,6 +102,7 @@ static core_bind::Marshalls *_marshalls = nullptr;
static core_bind::EngineDebugger *_engine_debugger = nullptr;
static IP *ip = nullptr;
+static Time *_time = nullptr;
static core_bind::Geometry2D *_geometry_2d = nullptr;
static core_bind::Geometry3D *_geometry_3d = nullptr;
@@ -128,6 +129,7 @@ void register_core_types() {
ObjectDB::setup();
StringName::setup();
+ _time = memnew(Time);
ResourceLoader::initialize();
register_global_constants();
@@ -436,6 +438,7 @@ void unregister_core_types() {
ResourceLoader::finalize();
ClassDB::cleanup_defaults();
+ memdelete(_time);
ObjectDB::cleanup();
Variant::unregister_types();
diff --git a/core/string/char_range.inc b/core/string/char_range.inc
index be5516e243..5dffe4f20d 100644
--- a/core/string/char_range.inc
+++ b/core/string/char_range.inc
@@ -38,7 +38,7 @@ struct CharRange {
char32_t end;
};
-static CharRange xid_start[] = {
+inline constexpr CharRange xid_start[] = {
{ 0x41, 0x5a },
{ 0x5f, 0x5f },
{ 0x61, 0x7a },
@@ -692,7 +692,7 @@ static CharRange xid_start[] = {
{ 0x0, 0x0 },
};
-static CharRange xid_continue[] = {
+inline constexpr CharRange xid_continue[] = {
{ 0x30, 0x39 },
{ 0x41, 0x5a },
{ 0x5f, 0x5f },
diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp
index 6b1595174a..06fd4717d7 100644
--- a/core/string/translation_po.cpp
+++ b/core/string/translation_po.cpp
@@ -41,8 +41,8 @@ void TranslationPO::print_translation_map() {
return;
}
- file->store_line("NPlural : " + String::num_int64(this->get_plural_forms()));
- file->store_line("Plural rule : " + this->get_plural_rule());
+ file->store_line("NPlural : " + String::num_int64(get_plural_forms()));
+ file->store_line("Plural rule : " + get_plural_rule());
file->store_line("");
List<StringName> context_l;
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 6afe28a6a7..d094184c4b 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -302,7 +302,7 @@ void String::copy_from(const char *p_cstr) {
resize(len + 1); // include 0
- char32_t *dst = this->ptrw();
+ char32_t *dst = ptrw();
for (size_t i = 0; i <= len; i++) {
#if CHAR_MIN == 0
@@ -339,7 +339,7 @@ void String::copy_from(const char *p_cstr, const int p_clip_to) {
resize(len + 1); // include 0
- char32_t *dst = this->ptrw();
+ char32_t *dst = ptrw();
for (int i = 0; i < len; i++) {
#if CHAR_MIN == 0
@@ -1043,7 +1043,7 @@ String String::_camelcase_to_underscore() const {
String new_string;
int start_index = 0;
- for (int i = 1; i < this->size(); i++) {
+ for (int i = 1; i < size(); i++) {
bool is_prev_upper = is_ascii_upper_case(cstr[i - 1]);
bool is_prev_lower = is_ascii_lower_case(cstr[i - 1]);
bool is_prev_digit = is_digit(cstr[i - 1]);
@@ -1053,7 +1053,7 @@ String String::_camelcase_to_underscore() const {
bool is_curr_digit = is_digit(cstr[i]);
bool is_next_lower = false;
- if (i + 1 < this->size()) {
+ if (i + 1 < size()) {
is_next_lower = is_ascii_lower_case(cstr[i + 1]);
}
@@ -1063,17 +1063,17 @@ String String::_camelcase_to_underscore() const {
const bool cond_d = (is_prev_upper || is_prev_lower) && is_curr_digit; // A2, a2
if (cond_a || cond_b || cond_c || cond_d) {
- new_string += this->substr(start_index, i - start_index) + "_";
+ new_string += substr(start_index, i - start_index) + "_";
start_index = i;
}
}
- new_string += this->substr(start_index, this->size() - start_index);
+ new_string += substr(start_index, size() - start_index);
return new_string.to_lower();
}
String String::capitalize() const {
- String aux = this->_camelcase_to_underscore().replace("_", " ").strip_edges();
+ String aux = _camelcase_to_underscore().replace("_", " ").strip_edges();
String cap;
for (int i = 0; i < aux.get_slice_count(" "); i++) {
String slice = aux.get_slicec(' ', i);
@@ -1090,7 +1090,7 @@ String String::capitalize() const {
}
String String::to_camel_case() const {
- String s = this->to_pascal_case();
+ String s = to_pascal_case();
if (!s.is_empty()) {
s[0] = _find_lower(s[0]);
}
@@ -1098,11 +1098,11 @@ String String::to_camel_case() const {
}
String String::to_pascal_case() const {
- return this->capitalize().replace(" ", "");
+ return capitalize().replace(" ", "");
}
String String::to_snake_case() const {
- return this->_camelcase_to_underscore().replace(" ", "_").strip_edges();
+ return _camelcase_to_underscore().replace(" ", "_").strip_edges();
}
String String::get_with_code_lines() const {
@@ -1185,7 +1185,7 @@ String String::get_slicec(char32_t p_splitter, int p_slice) const {
return String();
}
- const char32_t *c = this->ptr();
+ const char32_t *c = ptr();
int i = 0;
int prev = 0;
int count = 0;
@@ -3516,7 +3516,7 @@ bool String::matchn(const String &p_wildcard) const {
}
String String::format(const Variant &values, const String &placeholder) const {
- String new_string = String(this->ptr());
+ String new_string = String(ptr());
if (values.get_type() == Variant::ARRAY) {
Array values_arr = values;
@@ -4467,7 +4467,7 @@ bool String::is_valid_float() const {
String String::path_to_file(const String &p_path) const {
// Don't get base dir for src, this is expected to be a dir already.
- String src = this->replace("\\", "/");
+ String src = replace("\\", "/");
String dst = p_path.replace("\\", "/").get_base_dir();
String rel = src.path_to(dst);
if (rel == dst) { // failed
@@ -4478,7 +4478,7 @@ String String::path_to_file(const String &p_path) const {
}
String String::path_to(const String &p_path) const {
- String src = this->replace("\\", "/");
+ String src = replace("\\", "/");
String dst = p_path.replace("\\", "/");
if (!src.ends_with("/")) {
src += "/";
diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h
index 46d9797d6c..466658951e 100644
--- a/core/templates/cowdata.h
+++ b/core/templates/cowdata.h
@@ -46,7 +46,7 @@ class CharString;
template <class T, class V>
class VMap;
-SAFE_NUMERIC_TYPE_PUN_GUARANTEES(uint32_t)
+static_assert(std::is_trivially_destructible_v<std::atomic<uint64_t>>);
// Silence a false positive warning (see GH-52119).
#if defined(__GNUC__) && !defined(__clang__)
@@ -64,45 +64,92 @@ class CowData {
template <class TV, class VV>
friend class VMap;
+public:
+ typedef int64_t Size;
+ typedef uint64_t USize;
+ static constexpr USize MAX_INT = INT64_MAX;
+
private:
+ // Function to find the next power of 2 to an integer.
+ static _FORCE_INLINE_ USize next_po2(USize x) {
+ if (x == 0) {
+ return 0;
+ }
+
+ --x;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ if (sizeof(USize) == 8) {
+ x |= x >> 32;
+ }
+
+ return ++x;
+ }
+
+ // Alignment: ↓ max_align_t ↓ USize ↓ max_align_t
+ // ┌────────────────────┬──┬─────────────┬──┬───────────...
+ // │ SafeNumeric<USize> │░░│ USize │░░│ T[]
+ // │ ref. count │░░│ data size │░░│ data
+ // └────────────────────┴──┴─────────────┴──┴───────────...
+ // Offset: ↑ REF_COUNT_OFFSET ↑ SIZE_OFFSET ↑ DATA_OFFSET
+
+ static constexpr size_t REF_COUNT_OFFSET = 0;
+ static constexpr size_t SIZE_OFFSET = ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) % alignof(USize) == 0) ? (REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) : ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) + alignof(USize) - ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) % alignof(USize)));
+ static constexpr size_t DATA_OFFSET = ((SIZE_OFFSET + sizeof(USize)) % alignof(max_align_t) == 0) ? (SIZE_OFFSET + sizeof(USize)) : ((SIZE_OFFSET + sizeof(USize)) + alignof(max_align_t) - ((SIZE_OFFSET + sizeof(USize)) % alignof(max_align_t)));
+
mutable T *_ptr = nullptr;
// internal helpers
- _FORCE_INLINE_ SafeNumeric<uint32_t> *_get_refcount() const {
+ static _FORCE_INLINE_ SafeNumeric<USize> *_get_refcount_ptr(uint8_t *p_ptr) {
+ return (SafeNumeric<USize> *)(p_ptr + REF_COUNT_OFFSET);
+ }
+
+ static _FORCE_INLINE_ USize *_get_size_ptr(uint8_t *p_ptr) {
+ return (USize *)(p_ptr + SIZE_OFFSET);
+ }
+
+ static _FORCE_INLINE_ T *_get_data_ptr(uint8_t *p_ptr) {
+ return (T *)(p_ptr + DATA_OFFSET);
+ }
+
+ _FORCE_INLINE_ SafeNumeric<USize> *_get_refcount() const {
if (!_ptr) {
return nullptr;
}
- return reinterpret_cast<SafeNumeric<uint32_t> *>(_ptr) - 2;
+ return (SafeNumeric<USize> *)((uint8_t *)_ptr - DATA_OFFSET + REF_COUNT_OFFSET);
}
- _FORCE_INLINE_ uint32_t *_get_size() const {
+ _FORCE_INLINE_ USize *_get_size() const {
if (!_ptr) {
return nullptr;
}
- return reinterpret_cast<uint32_t *>(_ptr) - 1;
+ return (USize *)((uint8_t *)_ptr - DATA_OFFSET + SIZE_OFFSET);
}
- _FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const {
- return next_power_of_2(p_elements * sizeof(T));
+ _FORCE_INLINE_ USize _get_alloc_size(USize p_elements) const {
+ return next_po2(p_elements * sizeof(T));
}
- _FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const {
+ _FORCE_INLINE_ bool _get_alloc_size_checked(USize p_elements, USize *out) const {
if (unlikely(p_elements == 0)) {
*out = 0;
return true;
}
-#if defined(__GNUC__)
- size_t o;
- size_t p;
+#if defined(__GNUC__) && defined(IS_32_BIT)
+ USize o;
+ USize p;
if (__builtin_mul_overflow(p_elements, sizeof(T), &o)) {
*out = 0;
return false;
}
- *out = next_power_of_2(o);
- if (__builtin_add_overflow(o, static_cast<size_t>(32), &p)) {
+ *out = next_po2(o);
+ if (__builtin_add_overflow(o, static_cast<USize>(32), &p)) {
return false; // No longer allocated here.
}
#else
@@ -116,7 +163,7 @@ private:
void _unref(void *p_data);
void _ref(const CowData *p_from);
void _ref(const CowData &p_from);
- uint32_t _copy_on_write();
+ USize _copy_on_write();
public:
void operator=(const CowData<T> &p_from) { _ref(p_from); }
@@ -130,8 +177,8 @@ public:
return _ptr;
}
- _FORCE_INLINE_ int size() const {
- uint32_t *size = (uint32_t *)_get_size();
+ _FORCE_INLINE_ Size size() const {
+ USize *size = (USize *)_get_size();
if (size) {
return *size;
} else {
@@ -142,42 +189,42 @@ public:
_FORCE_INLINE_ void clear() { resize(0); }
_FORCE_INLINE_ bool is_empty() const { return _ptr == nullptr; }
- _FORCE_INLINE_ void set(int p_index, const T &p_elem) {
+ _FORCE_INLINE_ void set(Size p_index, const T &p_elem) {
ERR_FAIL_INDEX(p_index, size());
_copy_on_write();
_ptr[p_index] = p_elem;
}
- _FORCE_INLINE_ T &get_m(int p_index) {
+ _FORCE_INLINE_ T &get_m(Size p_index) {
CRASH_BAD_INDEX(p_index, size());
_copy_on_write();
return _ptr[p_index];
}
- _FORCE_INLINE_ const T &get(int p_index) const {
+ _FORCE_INLINE_ const T &get(Size p_index) const {
CRASH_BAD_INDEX(p_index, size());
return _ptr[p_index];
}
template <bool p_ensure_zero = false>
- Error resize(int p_size);
+ Error resize(Size p_size);
- _FORCE_INLINE_ void remove_at(int p_index) {
+ _FORCE_INLINE_ void remove_at(Size p_index) {
ERR_FAIL_INDEX(p_index, size());
T *p = ptrw();
- int len = size();
- for (int i = p_index; i < len - 1; i++) {
+ Size len = size();
+ for (Size i = p_index; i < len - 1; i++) {
p[i] = p[i + 1];
}
resize(len - 1);
}
- Error insert(int p_pos, const T &p_val) {
+ Error insert(Size p_pos, const T &p_val) {
ERR_FAIL_INDEX_V(p_pos, size() + 1, ERR_INVALID_PARAMETER);
resize(size() + 1);
- for (int i = (size() - 1); i > p_pos; i--) {
+ for (Size i = (size() - 1); i > p_pos; i--) {
set(i, get(i - 1));
}
set(p_pos, p_val);
@@ -185,9 +232,9 @@ public:
return OK;
}
- int find(const T &p_val, int p_from = 0) const;
- int rfind(const T &p_val, int p_from = -1) const;
- int count(const T &p_val) const;
+ Size find(const T &p_val, Size p_from = 0) const;
+ Size rfind(const T &p_val, Size p_from = -1) const;
+ Size count(const T &p_val) const;
_FORCE_INLINE_ CowData() {}
_FORCE_INLINE_ ~CowData();
@@ -200,59 +247,61 @@ void CowData<T>::_unref(void *p_data) {
return;
}
- SafeNumeric<uint32_t> *refc = _get_refcount();
+ SafeNumeric<USize> *refc = _get_refcount();
if (refc->decrement() > 0) {
return; // still in use
}
// clean up
- if (!std::is_trivially_destructible<T>::value) {
- uint32_t *count = _get_size();
+ if constexpr (!std::is_trivially_destructible_v<T>) {
+ USize *count = _get_size();
T *data = (T *)(count + 1);
- for (uint32_t i = 0; i < *count; ++i) {
+ for (USize i = 0; i < *count; ++i) {
// call destructors
data[i].~T();
}
}
// free mem
- Memory::free_static((uint8_t *)p_data, true);
+ Memory::free_static(((uint8_t *)p_data) - DATA_OFFSET, false);
}
template <class T>
-uint32_t CowData<T>::_copy_on_write() {
+typename CowData<T>::USize CowData<T>::_copy_on_write() {
if (!_ptr) {
return 0;
}
- SafeNumeric<uint32_t> *refc = _get_refcount();
+ SafeNumeric<USize> *refc = _get_refcount();
- uint32_t rc = refc->get();
+ USize rc = refc->get();
if (unlikely(rc > 1)) {
/* in use by more than me */
- uint32_t current_size = *_get_size();
+ USize current_size = *_get_size();
- uint32_t *mem_new = (uint32_t *)Memory::alloc_static(_get_alloc_size(current_size), true);
+ uint8_t *mem_new = (uint8_t *)Memory::alloc_static(_get_alloc_size(current_size) + DATA_OFFSET, false);
+ ERR_FAIL_NULL_V(mem_new, 0);
- new (mem_new - 2) SafeNumeric<uint32_t>(1); //refcount
- *(mem_new - 1) = current_size; //size
+ SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new);
+ USize *_size_ptr = _get_size_ptr(mem_new);
+ T *_data_ptr = _get_data_ptr(mem_new);
- T *_data = (T *)(mem_new);
+ new (_refc_ptr) SafeNumeric<USize>(1); //refcount
+ *(_size_ptr) = current_size; //size
// initialize new elements
- if (std::is_trivially_copyable<T>::value) {
- memcpy(mem_new, _ptr, current_size * sizeof(T));
-
+ if constexpr (std::is_trivially_copyable_v<T>) {
+ memcpy((uint8_t *)_data_ptr, _ptr, current_size * sizeof(T));
} else {
- for (uint32_t i = 0; i < current_size; i++) {
- memnew_placement(&_data[i], T(_ptr[i]));
+ for (USize i = 0; i < current_size; i++) {
+ memnew_placement(&_data_ptr[i], T(_ptr[i]));
}
}
_unref(_ptr);
- _ptr = _data;
+ _ptr = _data_ptr;
rc = 1;
}
@@ -261,10 +310,10 @@ uint32_t CowData<T>::_copy_on_write() {
template <class T>
template <bool p_ensure_zero>
-Error CowData<T>::resize(int p_size) {
+Error CowData<T>::resize(Size p_size) {
ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER);
- int current_size = size();
+ Size current_size = size();
if (p_size == current_size) {
return OK;
@@ -278,36 +327,45 @@ Error CowData<T>::resize(int p_size) {
}
// possibly changing size, copy on write
- uint32_t rc = _copy_on_write();
+ USize rc = _copy_on_write();
- size_t current_alloc_size = _get_alloc_size(current_size);
- size_t alloc_size;
+ USize current_alloc_size = _get_alloc_size(current_size);
+ USize alloc_size;
ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY);
if (p_size > current_size) {
if (alloc_size != current_alloc_size) {
if (current_size == 0) {
// alloc from scratch
- uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size, true);
- ERR_FAIL_NULL_V(ptr, ERR_OUT_OF_MEMORY);
- *(ptr - 1) = 0; //size, currently none
- new (ptr - 2) SafeNumeric<uint32_t>(1); //refcount
+ uint8_t *mem_new = (uint8_t *)Memory::alloc_static(alloc_size + DATA_OFFSET, false);
+ ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY);
- _ptr = (T *)ptr;
+ SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new);
+ USize *_size_ptr = _get_size_ptr(mem_new);
+ T *_data_ptr = _get_data_ptr(mem_new);
+
+ new (_refc_ptr) SafeNumeric<USize>(1); //refcount
+ *(_size_ptr) = 0; //size, currently none
+
+ _ptr = _data_ptr;
} else {
- uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
- ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY);
- new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); //refcount
+ uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, alloc_size + DATA_OFFSET, false);
+ ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY);
+
+ SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new);
+ T *_data_ptr = _get_data_ptr(mem_new);
- _ptr = (T *)(_ptrnew);
+ new (_refc_ptr) SafeNumeric<USize>(rc); //refcount
+
+ _ptr = _data_ptr;
}
}
// construct the newly created elements
- if (!std::is_trivially_constructible<T>::value) {
- for (int i = *_get_size(); i < p_size; i++) {
+ if constexpr (!std::is_trivially_constructible_v<T>) {
+ for (Size i = *_get_size(); i < p_size; i++) {
memnew_placement(&_ptr[i], T);
}
} else if (p_ensure_zero) {
@@ -317,20 +375,24 @@ Error CowData<T>::resize(int p_size) {
*_get_size() = p_size;
} else if (p_size < current_size) {
- if (!std::is_trivially_destructible<T>::value) {
+ if constexpr (!std::is_trivially_destructible_v<T>) {
// deinitialize no longer needed elements
- for (uint32_t i = p_size; i < *_get_size(); i++) {
+ for (USize i = p_size; i < *_get_size(); i++) {
T *t = &_ptr[i];
t->~T();
}
}
if (alloc_size != current_alloc_size) {
- uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
- ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY);
- new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); //refcount
+ uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, alloc_size + DATA_OFFSET, false);
+ ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY);
+
+ SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new);
+ T *_data_ptr = _get_data_ptr(mem_new);
+
+ new (_refc_ptr) SafeNumeric<USize>(rc); //refcount
- _ptr = (T *)(_ptrnew);
+ _ptr = _data_ptr;
}
*_get_size() = p_size;
@@ -340,14 +402,14 @@ Error CowData<T>::resize(int p_size) {
}
template <class T>
-int CowData<T>::find(const T &p_val, int p_from) const {
- int ret = -1;
+typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const {
+ Size ret = -1;
if (p_from < 0 || size() == 0) {
return ret;
}
- for (int i = p_from; i < size(); i++) {
+ for (Size i = p_from; i < size(); i++) {
if (get(i) == p_val) {
ret = i;
break;
@@ -358,8 +420,8 @@ int CowData<T>::find(const T &p_val, int p_from) const {
}
template <class T>
-int CowData<T>::rfind(const T &p_val, int p_from) const {
- const int s = size();
+typename CowData<T>::Size CowData<T>::rfind(const T &p_val, Size p_from) const {
+ const Size s = size();
if (p_from < 0) {
p_from = s + p_from;
@@ -368,7 +430,7 @@ int CowData<T>::rfind(const T &p_val, int p_from) const {
p_from = s - 1;
}
- for (int i = p_from; i >= 0; i--) {
+ for (Size i = p_from; i >= 0; i--) {
if (get(i) == p_val) {
return i;
}
@@ -377,9 +439,9 @@ int CowData<T>::rfind(const T &p_val, int p_from) const {
}
template <class T>
-int CowData<T>::count(const T &p_val) const {
- int amount = 0;
- for (int i = 0; i < size(); i++) {
+typename CowData<T>::Size CowData<T>::count(const T &p_val) const {
+ Size amount = 0;
+ for (Size i = 0; i < size(); i++) {
if (get(i) == p_val) {
amount++;
}
diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h
index 05960292f5..a16f655524 100644
--- a/core/templates/hashfuncs.h
+++ b/core/templates/hashfuncs.h
@@ -429,7 +429,7 @@ struct HashMapComparatorDefault<Vector3> {
constexpr uint32_t HASH_TABLE_SIZE_MAX = 29;
-const uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = {
+inline constexpr uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = {
5,
13,
23,
@@ -462,7 +462,7 @@ const uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = {
};
// Computed with elem_i = UINT64_C (0 x FFFFFFFF FFFFFFFF ) / d_i + 1, where d_i is the i-th element of the above array.
-const uint64_t hash_table_size_primes_inv[HASH_TABLE_SIZE_MAX] = {
+inline constexpr uint64_t hash_table_size_primes_inv[HASH_TABLE_SIZE_MAX] = {
3689348814741910324,
1418980313362273202,
802032351030850071,
diff --git a/core/templates/local_vector.h b/core/templates/local_vector.h
index b454821a8f..17ddbf6161 100644
--- a/core/templates/local_vector.h
+++ b/core/templates/local_vector.h
@@ -64,7 +64,7 @@ public:
CRASH_COND_MSG(!data, "Out of memory");
}
- if constexpr (!std::is_trivially_constructible<T>::value && !force_trivial) {
+ if constexpr (!std::is_trivially_constructible_v<T> && !force_trivial) {
memnew_placement(&data[count++], T(p_elem));
} else {
data[count++] = p_elem;
@@ -77,7 +77,7 @@ public:
for (U i = p_index; i < count; i++) {
data[i] = data[i + 1];
}
- if constexpr (!std::is_trivially_destructible<T>::value && !force_trivial) {
+ if constexpr (!std::is_trivially_destructible_v<T> && !force_trivial) {
data[count].~T();
}
}
@@ -90,7 +90,7 @@ public:
if (count > p_index) {
data[p_index] = data[count];
}
- if constexpr (!std::is_trivially_destructible<T>::value && !force_trivial) {
+ if constexpr (!std::is_trivially_destructible_v<T> && !force_trivial) {
data[count].~T();
}
}
@@ -133,7 +133,7 @@ public:
_FORCE_INLINE_ U size() const { return count; }
void resize(U p_size) {
if (p_size < count) {
- if constexpr (!std::is_trivially_destructible<T>::value && !force_trivial) {
+ if constexpr (!std::is_trivially_destructible_v<T> && !force_trivial) {
for (U i = p_size; i < count; i++) {
data[i].~T();
}
@@ -145,7 +145,7 @@ public:
data = (T *)memrealloc(data, capacity * sizeof(T));
CRASH_COND_MSG(!data, "Out of memory");
}
- if constexpr (!std::is_trivially_constructible<T>::value && !force_trivial) {
+ if constexpr (!std::is_trivially_constructible_v<T> && !force_trivial) {
for (U i = count; i < p_size; i++) {
memnew_placement(&data[i], T);
}
diff --git a/core/templates/paged_allocator.h b/core/templates/paged_allocator.h
index d880eae0c3..48110d37e5 100644
--- a/core/templates/paged_allocator.h
+++ b/core/templates/paged_allocator.h
@@ -101,7 +101,7 @@ public:
private:
void _reset(bool p_allow_unfreed) {
- if (!p_allow_unfreed || !std::is_trivially_destructible<T>::value) {
+ if (!p_allow_unfreed || !std::is_trivially_destructible_v<T>) {
ERR_FAIL_COND(allocs_available < pages_allocated * page_size);
}
if (pages_allocated) {
diff --git a/core/templates/paged_array.h b/core/templates/paged_array.h
index 69a792958a..21053dd033 100644
--- a/core/templates/paged_array.h
+++ b/core/templates/paged_array.h
@@ -202,7 +202,7 @@ public:
uint32_t page = count >> page_size_shift;
uint32_t offset = count & page_size_mask;
- if (!std::is_trivially_constructible<T>::value) {
+ if constexpr (!std::is_trivially_constructible_v<T>) {
memnew_placement(&page_data[page][offset], T(p_value));
} else {
page_data[page][offset] = p_value;
@@ -214,7 +214,7 @@ public:
_FORCE_INLINE_ void pop_back() {
ERR_FAIL_COND(count == 0);
- if (!std::is_trivially_destructible<T>::value) {
+ if constexpr (!std::is_trivially_destructible_v<T>) {
uint32_t page = (count - 1) >> page_size_shift;
uint32_t offset = (count - 1) & page_size_mask;
page_data[page][offset].~T();
@@ -229,9 +229,15 @@ public:
count--;
}
+ void remove_at_unordered(uint64_t p_index) {
+ ERR_FAIL_UNSIGNED_INDEX(p_index, count);
+ (*this)[p_index] = (*this)[count - 1];
+ pop_back();
+ }
+
void clear() {
//destruct if needed
- if (!std::is_trivially_destructible<T>::value) {
+ if constexpr (!std::is_trivially_destructible_v<T>) {
for (uint64_t i = 0; i < count; i++) {
uint32_t page = i >> page_size_shift;
uint32_t offset = i & page_size_mask;
@@ -312,13 +318,13 @@ public:
uint32_t to_copy = MIN(page_size - new_remainder, remainder);
for (uint32_t i = 0; i < to_copy; i++) {
- if (!std::is_trivially_constructible<T>::value) {
+ if constexpr (!std::is_trivially_constructible_v<T>) {
memnew_placement(&dst_page[i + new_remainder], T(remainder_page[i + remainder - to_copy]));
} else {
dst_page[i + new_remainder] = remainder_page[i + remainder - to_copy];
}
- if (!std::is_trivially_destructible<T>::value) {
+ if constexpr (!std::is_trivially_destructible_v<T>) {
remainder_page[i + remainder - to_copy].~T();
}
}
diff --git a/core/templates/ring_buffer.h b/core/templates/ring_buffer.h
index d878894946..54148a59bf 100644
--- a/core/templates/ring_buffer.h
+++ b/core/templates/ring_buffer.h
@@ -197,7 +197,7 @@ public:
int old_size = size();
int new_size = 1 << p_power;
int mask = new_size - 1;
- data.resize(1 << p_power);
+ data.resize(int64_t(1) << int64_t(p_power));
if (old_size < new_size && read_pos > write_pos) {
for (int i = 0; i < write_pos; i++) {
data.write[(old_size + i) & mask] = data[i];
diff --git a/core/templates/safe_refcount.h b/core/templates/safe_refcount.h
index 20fb0c6501..7bbceadc8d 100644
--- a/core/templates/safe_refcount.h
+++ b/core/templates/safe_refcount.h
@@ -54,7 +54,7 @@
#define SAFE_NUMERIC_TYPE_PUN_GUARANTEES(m_type) \
static_assert(sizeof(SafeNumeric<m_type>) == sizeof(m_type)); \
static_assert(alignof(SafeNumeric<m_type>) == alignof(m_type)); \
- static_assert(std::is_trivially_destructible<std::atomic<m_type>>::value);
+ static_assert(std::is_trivially_destructible_v<std::atomic<m_type>>);
#define SAFE_FLAG_TYPE_PUN_GUARANTEES \
static_assert(sizeof(SafeFlag) == sizeof(bool)); \
static_assert(alignof(SafeFlag) == alignof(bool));
diff --git a/core/templates/vector.h b/core/templates/vector.h
index d8bac0870f..361a7f56d5 100644
--- a/core/templates/vector.h
+++ b/core/templates/vector.h
@@ -48,7 +48,7 @@
template <class T>
class VectorWriteProxy {
public:
- _FORCE_INLINE_ T &operator[](int p_index) {
+ _FORCE_INLINE_ T &operator[](typename CowData<T>::Size p_index) {
CRASH_BAD_INDEX(p_index, ((Vector<T> *)(this))->_cowdata.size());
return ((Vector<T> *)(this))->_cowdata.ptrw()[p_index];
@@ -61,6 +61,7 @@ class Vector {
public:
VectorWriteProxy<T> write;
+ typedef typename CowData<T>::Size Size;
private:
CowData<T> _cowdata;
@@ -70,9 +71,9 @@ public:
_FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } //alias
void fill(T p_elem);
- void remove_at(int p_index) { _cowdata.remove_at(p_index); }
+ void remove_at(Size p_index) { _cowdata.remove_at(p_index); }
_FORCE_INLINE_ bool erase(const T &p_val) {
- int idx = find(p_val);
+ Size idx = find(p_val);
if (idx >= 0) {
remove_at(idx);
return true;
@@ -87,17 +88,17 @@ public:
_FORCE_INLINE_ void clear() { resize(0); }
_FORCE_INLINE_ bool is_empty() const { return _cowdata.is_empty(); }
- _FORCE_INLINE_ T get(int p_index) { return _cowdata.get(p_index); }
- _FORCE_INLINE_ const T &get(int p_index) const { return _cowdata.get(p_index); }
- _FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
- _FORCE_INLINE_ int size() const { return _cowdata.size(); }
- Error resize(int p_size) { return _cowdata.resize(p_size); }
- Error resize_zeroed(int p_size) { return _cowdata.template resize<true>(p_size); }
- _FORCE_INLINE_ const T &operator[](int p_index) const { return _cowdata.get(p_index); }
- Error insert(int p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); }
- int find(const T &p_val, int p_from = 0) const { return _cowdata.find(p_val, p_from); }
- int rfind(const T &p_val, int p_from = -1) const { return _cowdata.rfind(p_val, p_from); }
- int count(const T &p_val) const { return _cowdata.count(p_val); }
+ _FORCE_INLINE_ T get(Size p_index) { return _cowdata.get(p_index); }
+ _FORCE_INLINE_ const T &get(Size p_index) const { return _cowdata.get(p_index); }
+ _FORCE_INLINE_ void set(Size p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
+ _FORCE_INLINE_ Size size() const { return _cowdata.size(); }
+ Error resize(Size p_size) { return _cowdata.resize(p_size); }
+ Error resize_zeroed(Size p_size) { return _cowdata.template resize<true>(p_size); }
+ _FORCE_INLINE_ const T &operator[](Size p_index) const { return _cowdata.get(p_index); }
+ Error insert(Size p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); }
+ Size find(const T &p_val, Size p_from = 0) const { return _cowdata.find(p_val, p_from); }
+ Size rfind(const T &p_val, Size p_from = -1) const { return _cowdata.rfind(p_val, p_from); }
+ Size count(const T &p_val) const { return _cowdata.count(p_val); }
void append_array(Vector<T> p_other);
@@ -109,7 +110,7 @@ public:
template <class Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, class... Args>
void sort_custom(Args &&...args) {
- int len = _cowdata.size();
+ Size len = _cowdata.size();
if (len == 0) {
return;
}
@@ -119,12 +120,12 @@ public:
sorter.sort(data, len);
}
- int bsearch(const T &p_value, bool p_before) {
+ Size bsearch(const T &p_value, bool p_before) {
return bsearch_custom<_DefaultComparator<T>>(p_value, p_before);
}
template <class Comparator, class Value, class... Args>
- int bsearch_custom(const Value &p_value, bool p_before, Args &&...args) {
+ Size bsearch_custom(const Value &p_value, bool p_before, Args &&...args) {
SearchArray<T, Comparator> search{ args... };
return search.bisect(ptrw(), size(), p_value, p_before);
}
@@ -134,7 +135,7 @@ public:
}
void ordered_insert(const T &p_val) {
- int i;
+ Size i;
for (i = 0; i < _cowdata.size(); i++) {
if (p_val < operator[](i)) {
break;
@@ -157,28 +158,28 @@ public:
return ret;
}
- Vector<T> slice(int p_begin, int p_end = INT_MAX) const {
+ Vector<T> slice(Size p_begin, Size p_end = CowData<T>::MAX_INT) const {
Vector<T> result;
- const int s = size();
+ const Size s = size();
- int begin = CLAMP(p_begin, -s, s);
+ Size begin = CLAMP(p_begin, -s, s);
if (begin < 0) {
begin += s;
}
- int end = CLAMP(p_end, -s, s);
+ Size end = CLAMP(p_end, -s, s);
if (end < 0) {
end += s;
}
ERR_FAIL_COND_V(begin > end, result);
- int result_size = end - begin;
+ Size result_size = end - begin;
result.resize(result_size);
const T *const r = ptr();
T *const w = result.ptrw();
- for (int i = 0; i < result_size; ++i) {
+ for (Size i = 0; i < result_size; ++i) {
w[i] = r[begin + i];
}
@@ -186,11 +187,11 @@ public:
}
bool operator==(const Vector<T> &p_arr) const {
- int s = size();
+ Size s = size();
if (s != p_arr.size()) {
return false;
}
- for (int i = 0; i < s; i++) {
+ for (Size i = 0; i < s; i++) {
if (operator[](i) != p_arr[i]) {
return false;
}
@@ -199,11 +200,11 @@ public:
}
bool operator!=(const Vector<T> &p_arr) const {
- int s = size();
+ Size s = size();
if (s != p_arr.size()) {
return true;
}
- for (int i = 0; i < s; i++) {
+ for (Size i = 0; i < s; i++) {
if (operator[](i) != p_arr[i]) {
return true;
}
@@ -280,7 +281,7 @@ public:
Error err = _cowdata.resize(p_init.size());
ERR_FAIL_COND(err);
- int i = 0;
+ Size i = 0;
for (const T &element : p_init) {
_cowdata.set(i++, element);
}
@@ -292,7 +293,7 @@ public:
template <class T>
void Vector<T>::reverse() {
- for (int i = 0; i < size() / 2; i++) {
+ for (Size i = 0; i < size() / 2; i++) {
T *p = ptrw();
SWAP(p[i], p[size() - i - 1]);
}
@@ -300,13 +301,13 @@ void Vector<T>::reverse() {
template <class T>
void Vector<T>::append_array(Vector<T> p_other) {
- const int ds = p_other.size();
+ const Size ds = p_other.size();
if (ds == 0) {
return;
}
- const int bs = size();
+ const Size bs = size();
resize(bs + ds);
- for (int i = 0; i < ds; ++i) {
+ for (Size i = 0; i < ds; ++i) {
ptrw()[bs + i] = p_other[i];
}
}
@@ -323,7 +324,7 @@ bool Vector<T>::push_back(T p_elem) {
template <class T>
void Vector<T>::fill(T p_elem) {
T *p = ptrw();
- for (int i = 0; i < size(); i++) {
+ for (Size i = 0; i < size(); i++) {
p[i] = p_elem;
}
}
diff --git a/core/typedefs.h b/core/typedefs.h
index 8b04960b9a..8807ee3c99 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -93,6 +93,7 @@
#undef OK
#undef CONNECT_DEFERRED // override from Windows SDK, clashes with Object enum
#undef MemoryBarrier
+#undef MONO_FONT
#endif
// Make room for our constexpr's below by overriding potential system-specific macros.
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index ab0315ae34..5d6fbb8bed 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -316,17 +316,17 @@ void Array::erase(const Variant &p_value) {
}
Variant Array::front() const {
- ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array.");
+ ERR_FAIL_COND_V_MSG(_p->array.is_empty(), Variant(), "Can't take value from empty array.");
return operator[](0);
}
Variant Array::back() const {
- ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array.");
+ ERR_FAIL_COND_V_MSG(_p->array.is_empty(), Variant(), "Can't take value from empty array.");
return operator[](_p->array.size() - 1);
}
Variant Array::pick_random() const {
- ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array.");
+ ERR_FAIL_COND_V_MSG(_p->array.is_empty(), Variant(), "Can't take value from empty array.");
return operator[](Math::rand() % _p->array.size());
}
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 34b54f1d00..a44b938395 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -51,7 +51,7 @@ template <class T>
struct VariantCaster {
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
- if constexpr (std::is_base_of<Object, TStripped>::value) {
+ if constexpr (std::is_base_of_v<Object, TStripped>) {
return Object::cast_to<TStripped>(p_variant);
} else {
return p_variant;
@@ -63,7 +63,7 @@ template <class T>
struct VariantCaster<T &> {
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
- if constexpr (std::is_base_of<Object, TStripped>::value) {
+ if constexpr (std::is_base_of_v<Object, TStripped>) {
return Object::cast_to<TStripped>(p_variant);
} else {
return p_variant;
@@ -75,7 +75,7 @@ template <class T>
struct VariantCaster<const T &> {
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
- if constexpr (std::is_base_of<Object, TStripped>::value) {
+ if constexpr (std::is_base_of_v<Object, TStripped>) {
return Object::cast_to<TStripped>(p_variant);
} else {
return p_variant;
@@ -176,6 +176,7 @@ VARIANT_ENUM_CAST(Variant::Operator);
VARIANT_ENUM_CAST(Key);
VARIANT_BITFIELD_CAST(KeyModifierMask);
+VARIANT_ENUM_CAST(KeyLocation);
static inline Key &operator|=(Key &a, BitField<KeyModifierMask> b) {
a = static_cast<Key>(static_cast<int>(a) | static_cast<int>(b.operator int64_t()));
@@ -225,7 +226,7 @@ template <typename T>
struct VariantObjectClassChecker {
static _FORCE_INLINE_ bool check(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
- if constexpr (std::is_base_of<Object, TStripped>::value) {
+ if constexpr (std::is_base_of_v<Object, TStripped>) {
Object *obj = p_variant;
return Object::cast_to<TStripped>(p_variant) || !obj;
} else {
diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp
index 8b61a8993a..9f65a73c6f 100644
--- a/core/variant/dictionary.cpp
+++ b/core/variant/dictionary.cpp
@@ -251,7 +251,7 @@ void Dictionary::clear() {
void Dictionary::merge(const Dictionary &p_dictionary, bool p_overwrite) {
for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) {
if (p_overwrite || !has(E.key)) {
- this->operator[](E.key) = E.value;
+ operator[](E.key) = E.value;
}
}
}
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index c1f2f86a96..49c4db8229 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -43,14 +43,10 @@ struct EnableIf<false, T> {
};
template <typename, typename>
-struct TypesAreSame {
- static bool const value = false;
-};
+inline constexpr bool types_are_same_v = false;
-template <typename A>
-struct TypesAreSame<A, A> {
- static bool const value = true;
-};
+template <typename T>
+inline constexpr bool types_are_same_v<T, T> = true;
template <typename B, typename D>
struct TypeInherits {
@@ -60,7 +56,7 @@ struct TypeInherits {
static char (&test(...))[2];
static bool const value = sizeof(test(get_d())) == sizeof(char) &&
- !TypesAreSame<B volatile const, void volatile const>::value;
+ !types_are_same_v<B volatile const, void volatile const>;
};
namespace GodotTypeInfo {
diff --git a/core/variant/typed_array.h b/core/variant/typed_array.h
index 037c5c7c2e..ed973b9daa 100644
--- a/core/variant/typed_array.h
+++ b/core/variant/typed_array.h
@@ -88,6 +88,8 @@ struct VariantInternalAccessor<const TypedArray<T> &> {
} \
};
+// All Variant::OBJECT types are intentionally omitted from this list because they are handled by
+// the unspecialized TypedArray definition.
MAKE_TYPED_ARRAY(bool, Variant::BOOL)
MAKE_TYPED_ARRAY(uint8_t, Variant::INT)
MAKE_TYPED_ARRAY(int8_t, Variant::INT)
@@ -107,11 +109,14 @@ MAKE_TYPED_ARRAY(Rect2i, Variant::RECT2I)
MAKE_TYPED_ARRAY(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY(Transform2D, Variant::TRANSFORM2D)
+MAKE_TYPED_ARRAY(Vector4, Variant::VECTOR4)
+MAKE_TYPED_ARRAY(Vector4i, Variant::VECTOR4I)
MAKE_TYPED_ARRAY(Plane, Variant::PLANE)
MAKE_TYPED_ARRAY(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY(AABB, Variant::AABB)
MAKE_TYPED_ARRAY(Basis, Variant::BASIS)
MAKE_TYPED_ARRAY(Transform3D, Variant::TRANSFORM3D)
+MAKE_TYPED_ARRAY(Projection, Variant::PROJECTION)
MAKE_TYPED_ARRAY(Color, Variant::COLOR)
MAKE_TYPED_ARRAY(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY(NodePath, Variant::NODE_PATH)
@@ -120,15 +125,15 @@ MAKE_TYPED_ARRAY(Callable, Variant::CALLABLE)
MAKE_TYPED_ARRAY(Signal, Variant::SIGNAL)
MAKE_TYPED_ARRAY(Dictionary, Variant::DICTIONARY)
MAKE_TYPED_ARRAY(Array, Variant::ARRAY)
-MAKE_TYPED_ARRAY(Vector<uint8_t>, Variant::PACKED_BYTE_ARRAY)
-MAKE_TYPED_ARRAY(Vector<int32_t>, Variant::PACKED_INT32_ARRAY)
-MAKE_TYPED_ARRAY(Vector<int64_t>, Variant::PACKED_INT64_ARRAY)
-MAKE_TYPED_ARRAY(Vector<float>, Variant::PACKED_FLOAT32_ARRAY)
-MAKE_TYPED_ARRAY(Vector<double>, Variant::PACKED_FLOAT64_ARRAY)
-MAKE_TYPED_ARRAY(Vector<String>, Variant::PACKED_STRING_ARRAY)
-MAKE_TYPED_ARRAY(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY)
-MAKE_TYPED_ARRAY(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY)
-MAKE_TYPED_ARRAY(Vector<Color>, Variant::PACKED_COLOR_ARRAY)
+MAKE_TYPED_ARRAY(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
+MAKE_TYPED_ARRAY(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
+MAKE_TYPED_ARRAY(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
+MAKE_TYPED_ARRAY(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
+MAKE_TYPED_ARRAY(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
+MAKE_TYPED_ARRAY(PackedStringArray, Variant::PACKED_STRING_ARRAY)
+MAKE_TYPED_ARRAY(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
+MAKE_TYPED_ARRAY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
+MAKE_TYPED_ARRAY(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
MAKE_TYPED_ARRAY(IPAddress, Variant::STRING)
template <class T>
@@ -205,11 +210,14 @@ MAKE_TYPED_ARRAY_INFO(Rect2i, Variant::RECT2I)
MAKE_TYPED_ARRAY_INFO(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY_INFO(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY_INFO(Transform2D, Variant::TRANSFORM2D)
+MAKE_TYPED_ARRAY_INFO(Vector4, Variant::VECTOR4)
+MAKE_TYPED_ARRAY_INFO(Vector4i, Variant::VECTOR4I)
MAKE_TYPED_ARRAY_INFO(Plane, Variant::PLANE)
MAKE_TYPED_ARRAY_INFO(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY_INFO(AABB, Variant::AABB)
MAKE_TYPED_ARRAY_INFO(Basis, Variant::BASIS)
MAKE_TYPED_ARRAY_INFO(Transform3D, Variant::TRANSFORM3D)
+MAKE_TYPED_ARRAY_INFO(Projection, Variant::PROJECTION)
MAKE_TYPED_ARRAY_INFO(Color, Variant::COLOR)
MAKE_TYPED_ARRAY_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY_INFO(NodePath, Variant::NODE_PATH)
@@ -218,15 +226,15 @@ MAKE_TYPED_ARRAY_INFO(Callable, Variant::CALLABLE)
MAKE_TYPED_ARRAY_INFO(Signal, Variant::SIGNAL)
MAKE_TYPED_ARRAY_INFO(Dictionary, Variant::DICTIONARY)
MAKE_TYPED_ARRAY_INFO(Array, Variant::ARRAY)
-MAKE_TYPED_ARRAY_INFO(Vector<uint8_t>, Variant::PACKED_BYTE_ARRAY)
-MAKE_TYPED_ARRAY_INFO(Vector<int32_t>, Variant::PACKED_INT32_ARRAY)
-MAKE_TYPED_ARRAY_INFO(Vector<int64_t>, Variant::PACKED_INT64_ARRAY)
-MAKE_TYPED_ARRAY_INFO(Vector<float>, Variant::PACKED_FLOAT32_ARRAY)
-MAKE_TYPED_ARRAY_INFO(Vector<double>, Variant::PACKED_FLOAT64_ARRAY)
-MAKE_TYPED_ARRAY_INFO(Vector<String>, Variant::PACKED_STRING_ARRAY)
-MAKE_TYPED_ARRAY_INFO(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY)
-MAKE_TYPED_ARRAY_INFO(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY)
-MAKE_TYPED_ARRAY_INFO(Vector<Color>, Variant::PACKED_COLOR_ARRAY)
+MAKE_TYPED_ARRAY_INFO(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
+MAKE_TYPED_ARRAY_INFO(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
+MAKE_TYPED_ARRAY_INFO(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
+MAKE_TYPED_ARRAY_INFO(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
+MAKE_TYPED_ARRAY_INFO(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
+MAKE_TYPED_ARRAY_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY)
+MAKE_TYPED_ARRAY_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
+MAKE_TYPED_ARRAY_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
+MAKE_TYPED_ARRAY_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
MAKE_TYPED_ARRAY_INFO(IPAddress, Variant::STRING)
#undef MAKE_TYPED_ARRAY
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index c352d800f9..67f2c10099 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -1246,53 +1246,53 @@ void Variant::zero() {
case NIL:
break;
case BOOL:
- this->_data._bool = false;
+ _data._bool = false;
break;
case INT:
- this->_data._int = 0;
+ _data._int = 0;
break;
case FLOAT:
- this->_data._float = 0;
+ _data._float = 0;
break;
case VECTOR2:
- *reinterpret_cast<Vector2 *>(this->_data._mem) = Vector2();
+ *reinterpret_cast<Vector2 *>(_data._mem) = Vector2();
break;
case VECTOR2I:
- *reinterpret_cast<Vector2i *>(this->_data._mem) = Vector2i();
+ *reinterpret_cast<Vector2i *>(_data._mem) = Vector2i();
break;
case RECT2:
- *reinterpret_cast<Rect2 *>(this->_data._mem) = Rect2();
+ *reinterpret_cast<Rect2 *>(_data._mem) = Rect2();
break;
case RECT2I:
- *reinterpret_cast<Rect2i *>(this->_data._mem) = Rect2i();
+ *reinterpret_cast<Rect2i *>(_data._mem) = Rect2i();
break;
case VECTOR3:
- *reinterpret_cast<Vector3 *>(this->_data._mem) = Vector3();
+ *reinterpret_cast<Vector3 *>(_data._mem) = Vector3();
break;
case VECTOR3I:
- *reinterpret_cast<Vector3i *>(this->_data._mem) = Vector3i();
+ *reinterpret_cast<Vector3i *>(_data._mem) = Vector3i();
break;
case VECTOR4:
- *reinterpret_cast<Vector4 *>(this->_data._mem) = Vector4();
+ *reinterpret_cast<Vector4 *>(_data._mem) = Vector4();
break;
case VECTOR4I:
- *reinterpret_cast<Vector4i *>(this->_data._mem) = Vector4i();
+ *reinterpret_cast<Vector4i *>(_data._mem) = Vector4i();
break;
case PLANE:
- *reinterpret_cast<Plane *>(this->_data._mem) = Plane();
+ *reinterpret_cast<Plane *>(_data._mem) = Plane();
break;
case QUATERNION:
- *reinterpret_cast<Quaternion *>(this->_data._mem) = Quaternion();
+ *reinterpret_cast<Quaternion *>(_data._mem) = Quaternion();
break;
case COLOR:
- *reinterpret_cast<Color *>(this->_data._mem) = Color();
+ *reinterpret_cast<Color *>(_data._mem) = Color();
break;
default:
Type prev_type = type;
- this->clear();
+ clear();
if (type != prev_type) {
// clear() changes type to NIL, so it needs to be restored.
Callable::CallError ce;
@@ -1793,31 +1793,31 @@ String Variant::stringify(int recursion_count) const {
}
// Packed arrays cannot contain recursive structures, the recursion_count increment is not needed.
case PACKED_VECTOR2_ARRAY: {
- return stringify_vector(operator Vector<Vector2>(), recursion_count);
+ return stringify_vector(operator PackedVector2Array(), recursion_count);
}
case PACKED_VECTOR3_ARRAY: {
- return stringify_vector(operator Vector<Vector3>(), recursion_count);
+ return stringify_vector(operator PackedVector3Array(), recursion_count);
}
case PACKED_COLOR_ARRAY: {
- return stringify_vector(operator Vector<Color>(), recursion_count);
+ return stringify_vector(operator PackedColorArray(), recursion_count);
}
case PACKED_STRING_ARRAY: {
- return stringify_vector(operator Vector<String>(), recursion_count);
+ return stringify_vector(operator PackedStringArray(), recursion_count);
}
case PACKED_BYTE_ARRAY: {
- return stringify_vector(operator Vector<uint8_t>(), recursion_count);
+ return stringify_vector(operator PackedByteArray(), recursion_count);
}
case PACKED_INT32_ARRAY: {
- return stringify_vector(operator Vector<int32_t>(), recursion_count);
+ return stringify_vector(operator PackedInt32Array(), recursion_count);
}
case PACKED_INT64_ARRAY: {
- return stringify_vector(operator Vector<int64_t>(), recursion_count);
+ return stringify_vector(operator PackedInt64Array(), recursion_count);
}
case PACKED_FLOAT32_ARRAY: {
- return stringify_vector(operator Vector<float>(), recursion_count);
+ return stringify_vector(operator PackedFloat32Array(), recursion_count);
}
case PACKED_FLOAT64_ARRAY: {
- return stringify_vector(operator Vector<double>(), recursion_count);
+ return stringify_vector(operator PackedFloat64Array(), recursion_count);
}
case ARRAY: {
ERR_FAIL_COND_V_MSG(recursion_count > MAX_RECURSION, "[...]", "Maximum array recursion reached!");
@@ -2207,31 +2207,31 @@ inline DA _convert_array_from_variant(const Variant &p_variant) {
return _convert_array<DA, Array>(p_variant.operator Array());
}
case Variant::PACKED_BYTE_ARRAY: {
- return _convert_array<DA, Vector<uint8_t>>(p_variant.operator Vector<uint8_t>());
+ return _convert_array<DA, PackedByteArray>(p_variant.operator PackedByteArray());
}
case Variant::PACKED_INT32_ARRAY: {
- return _convert_array<DA, Vector<int32_t>>(p_variant.operator Vector<int32_t>());
+ return _convert_array<DA, PackedInt32Array>(p_variant.operator PackedInt32Array());
}
case Variant::PACKED_INT64_ARRAY: {
- return _convert_array<DA, Vector<int64_t>>(p_variant.operator Vector<int64_t>());
+ return _convert_array<DA, PackedInt64Array>(p_variant.operator PackedInt64Array());
}
case Variant::PACKED_FLOAT32_ARRAY: {
- return _convert_array<DA, Vector<float>>(p_variant.operator Vector<float>());
+ return _convert_array<DA, PackedFloat32Array>(p_variant.operator PackedFloat32Array());
}
case Variant::PACKED_FLOAT64_ARRAY: {
- return _convert_array<DA, Vector<double>>(p_variant.operator Vector<double>());
+ return _convert_array<DA, PackedFloat64Array>(p_variant.operator PackedFloat64Array());
}
case Variant::PACKED_STRING_ARRAY: {
- return _convert_array<DA, Vector<String>>(p_variant.operator Vector<String>());
+ return _convert_array<DA, PackedStringArray>(p_variant.operator PackedStringArray());
}
case Variant::PACKED_VECTOR2_ARRAY: {
- return _convert_array<DA, Vector<Vector2>>(p_variant.operator Vector<Vector2>());
+ return _convert_array<DA, PackedVector2Array>(p_variant.operator PackedVector2Array());
}
case Variant::PACKED_VECTOR3_ARRAY: {
- return _convert_array<DA, Vector<Vector3>>(p_variant.operator Vector<Vector3>());
+ return _convert_array<DA, PackedVector3Array>(p_variant.operator PackedVector3Array());
}
case Variant::PACKED_COLOR_ARRAY: {
- return _convert_array<DA, Vector<Color>>(p_variant.operator Vector<Color>());
+ return _convert_array<DA, PackedColorArray>(p_variant.operator PackedColorArray());
}
default: {
return DA();
@@ -2247,75 +2247,75 @@ Variant::operator Array() const {
}
}
-Variant::operator Vector<uint8_t>() const {
+Variant::operator PackedByteArray() const {
if (type == PACKED_BYTE_ARRAY) {
return static_cast<PackedArrayRef<uint8_t> *>(_data.packed_array)->array;
} else {
- return _convert_array_from_variant<Vector<uint8_t>>(*this);
+ return _convert_array_from_variant<PackedByteArray>(*this);
}
}
-Variant::operator Vector<int32_t>() const {
+Variant::operator PackedInt32Array() const {
if (type == PACKED_INT32_ARRAY) {
return static_cast<PackedArrayRef<int32_t> *>(_data.packed_array)->array;
} else {
- return _convert_array_from_variant<Vector<int>>(*this);
+ return _convert_array_from_variant<PackedInt32Array>(*this);
}
}
-Variant::operator Vector<int64_t>() const {
+Variant::operator PackedInt64Array() const {
if (type == PACKED_INT64_ARRAY) {
return static_cast<PackedArrayRef<int64_t> *>(_data.packed_array)->array;
} else {
- return _convert_array_from_variant<Vector<int64_t>>(*this);
+ return _convert_array_from_variant<PackedInt64Array>(*this);
}
}
-Variant::operator Vector<float>() const {
+Variant::operator PackedFloat32Array() const {
if (type == PACKED_FLOAT32_ARRAY) {
return static_cast<PackedArrayRef<float> *>(_data.packed_array)->array;
} else {
- return _convert_array_from_variant<Vector<float>>(*this);
+ return _convert_array_from_variant<PackedFloat32Array>(*this);
}
}
-Variant::operator Vector<double>() const {
+Variant::operator PackedFloat64Array() const {
if (type == PACKED_FLOAT64_ARRAY) {
return static_cast<PackedArrayRef<double> *>(_data.packed_array)->array;
} else {
- return _convert_array_from_variant<Vector<double>>(*this);
+ return _convert_array_from_variant<PackedFloat64Array>(*this);
}
}
-Variant::operator Vector<String>() const {
+Variant::operator PackedStringArray() const {
if (type == PACKED_STRING_ARRAY) {
return static_cast<PackedArrayRef<String> *>(_data.packed_array)->array;
} else {
- return _convert_array_from_variant<Vector<String>>(*this);
+ return _convert_array_from_variant<PackedStringArray>(*this);
}
}
-Variant::operator Vector<Vector3>() const {
- if (type == PACKED_VECTOR3_ARRAY) {
- return static_cast<PackedArrayRef<Vector3> *>(_data.packed_array)->array;
+Variant::operator PackedVector2Array() const {
+ if (type == PACKED_VECTOR2_ARRAY) {
+ return static_cast<PackedArrayRef<Vector2> *>(_data.packed_array)->array;
} else {
- return _convert_array_from_variant<Vector<Vector3>>(*this);
+ return _convert_array_from_variant<PackedVector2Array>(*this);
}
}
-Variant::operator Vector<Vector2>() const {
- if (type == PACKED_VECTOR2_ARRAY) {
- return static_cast<PackedArrayRef<Vector2> *>(_data.packed_array)->array;
+Variant::operator PackedVector3Array() const {
+ if (type == PACKED_VECTOR3_ARRAY) {
+ return static_cast<PackedArrayRef<Vector3> *>(_data.packed_array)->array;
} else {
- return _convert_array_from_variant<Vector<Vector2>>(*this);
+ return _convert_array_from_variant<PackedVector3Array>(*this);
}
}
-Variant::operator Vector<Color>() const {
+Variant::operator PackedColorArray() const {
if (type == PACKED_COLOR_ARRAY) {
return static_cast<PackedArrayRef<Color> *>(_data.packed_array)->array;
} else {
- return _convert_array_from_variant<Vector<Color>>(*this);
+ return _convert_array_from_variant<PackedColorArray>(*this);
}
}
@@ -2350,7 +2350,7 @@ Variant::operator Vector<Plane>() const {
}
Variant::operator Vector<Face3>() const {
- Vector<Vector3> va = operator Vector<Vector3>();
+ PackedVector3Array va = operator PackedVector3Array();
Vector<Face3> faces;
int va_size = va.size();
if (va_size == 0) {
@@ -2386,7 +2386,7 @@ Variant::operator Vector<Variant>() const {
}
Variant::operator Vector<StringName>() const {
- Vector<String> from = operator Vector<String>();
+ PackedStringArray from = operator PackedStringArray();
Vector<StringName> to;
int len = from.size();
to.resize(len);
@@ -2646,78 +2646,79 @@ Variant::Variant(const Array &p_array) {
memnew_placement(_data._mem, Array(p_array));
}
-Variant::Variant(const Vector<Plane> &p_array) {
- type = ARRAY;
-
- Array *plane_array = memnew_placement(_data._mem, Array);
-
- plane_array->resize(p_array.size());
-
- for (int i = 0; i < p_array.size(); i++) {
- plane_array->operator[](i) = Variant(p_array[i]);
- }
-}
-
-Variant::Variant(const Vector<::RID> &p_array) {
- type = ARRAY;
-
- Array *rid_array = memnew_placement(_data._mem, Array);
-
- rid_array->resize(p_array.size());
-
- for (int i = 0; i < p_array.size(); i++) {
- rid_array->set(i, Variant(p_array[i]));
- }
-}
-
-Variant::Variant(const Vector<uint8_t> &p_byte_array) {
+Variant::Variant(const PackedByteArray &p_byte_array) {
type = PACKED_BYTE_ARRAY;
_data.packed_array = PackedArrayRef<uint8_t>::create(p_byte_array);
}
-Variant::Variant(const Vector<int32_t> &p_int32_array) {
+Variant::Variant(const PackedInt32Array &p_int32_array) {
type = PACKED_INT32_ARRAY;
_data.packed_array = PackedArrayRef<int32_t>::create(p_int32_array);
}
-Variant::Variant(const Vector<int64_t> &p_int64_array) {
+Variant::Variant(const PackedInt64Array &p_int64_array) {
type = PACKED_INT64_ARRAY;
_data.packed_array = PackedArrayRef<int64_t>::create(p_int64_array);
}
-Variant::Variant(const Vector<float> &p_float32_array) {
+Variant::Variant(const PackedFloat32Array &p_float32_array) {
type = PACKED_FLOAT32_ARRAY;
_data.packed_array = PackedArrayRef<float>::create(p_float32_array);
}
-Variant::Variant(const Vector<double> &p_float64_array) {
+Variant::Variant(const PackedFloat64Array &p_float64_array) {
type = PACKED_FLOAT64_ARRAY;
_data.packed_array = PackedArrayRef<double>::create(p_float64_array);
}
-Variant::Variant(const Vector<String> &p_string_array) {
+Variant::Variant(const PackedStringArray &p_string_array) {
type = PACKED_STRING_ARRAY;
_data.packed_array = PackedArrayRef<String>::create(p_string_array);
}
-Variant::Variant(const Vector<Vector3> &p_vector3_array) {
- type = PACKED_VECTOR3_ARRAY;
- _data.packed_array = PackedArrayRef<Vector3>::create(p_vector3_array);
-}
-
-Variant::Variant(const Vector<Vector2> &p_vector2_array) {
+Variant::Variant(const PackedVector2Array &p_vector2_array) {
type = PACKED_VECTOR2_ARRAY;
_data.packed_array = PackedArrayRef<Vector2>::create(p_vector2_array);
}
-Variant::Variant(const Vector<Color> &p_color_array) {
+Variant::Variant(const PackedVector3Array &p_vector3_array) {
+ type = PACKED_VECTOR3_ARRAY;
+ _data.packed_array = PackedArrayRef<Vector3>::create(p_vector3_array);
+}
+
+Variant::Variant(const PackedColorArray &p_color_array) {
type = PACKED_COLOR_ARRAY;
_data.packed_array = PackedArrayRef<Color>::create(p_color_array);
}
+/* helpers */
+Variant::Variant(const Vector<::RID> &p_array) {
+ type = ARRAY;
+
+ Array *rid_array = memnew_placement(_data._mem, Array);
+
+ rid_array->resize(p_array.size());
+
+ for (int i = 0; i < p_array.size(); i++) {
+ rid_array->set(i, Variant(p_array[i]));
+ }
+}
+
+Variant::Variant(const Vector<Plane> &p_array) {
+ type = ARRAY;
+
+ Array *plane_array = memnew_placement(_data._mem, Array);
+
+ plane_array->resize(p_array.size());
+
+ for (int i = 0; i < p_array.size(); i++) {
+ plane_array->operator[](i) = Variant(p_array[i]);
+ }
+}
+
Variant::Variant(const Vector<Face3> &p_face_array) {
- Vector<Vector3> vertices;
+ PackedVector3Array vertices;
int face_count = p_face_array.size();
vertices.resize(face_count * 3);
@@ -2737,7 +2738,6 @@ Variant::Variant(const Vector<Face3> &p_face_array) {
*this = vertices;
}
-/* helpers */
Variant::Variant(const Vector<Variant> &p_array) {
type = NIL;
Array arr;
@@ -2750,7 +2750,7 @@ Variant::Variant(const Vector<Variant> &p_array) {
Variant::Variant(const Vector<StringName> &p_array) {
type = NIL;
- Vector<String> v;
+ PackedStringArray v;
int len = p_array.size();
v.resize(len);
for (int i = 0; i < len; i++) {
@@ -3100,7 +3100,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
} break;
case PACKED_BYTE_ARRAY: {
- const Vector<uint8_t> &arr = PackedArrayRef<uint8_t>::get_array(_data.packed_array);
+ const PackedByteArray &arr = PackedArrayRef<uint8_t>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
const uint8_t *r = arr.ptr();
@@ -3111,7 +3111,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
} break;
case PACKED_INT32_ARRAY: {
- const Vector<int32_t> &arr = PackedArrayRef<int32_t>::get_array(_data.packed_array);
+ const PackedInt32Array &arr = PackedArrayRef<int32_t>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
const int32_t *r = arr.ptr();
@@ -3122,7 +3122,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
} break;
case PACKED_INT64_ARRAY: {
- const Vector<int64_t> &arr = PackedArrayRef<int64_t>::get_array(_data.packed_array);
+ const PackedInt64Array &arr = PackedArrayRef<int64_t>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
const int64_t *r = arr.ptr();
@@ -3133,7 +3133,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
} break;
case PACKED_FLOAT32_ARRAY: {
- const Vector<float> &arr = PackedArrayRef<float>::get_array(_data.packed_array);
+ const PackedFloat32Array &arr = PackedArrayRef<float>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
@@ -3149,7 +3149,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
} break;
case PACKED_FLOAT64_ARRAY: {
- const Vector<double> &arr = PackedArrayRef<double>::get_array(_data.packed_array);
+ const PackedFloat64Array &arr = PackedArrayRef<double>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
@@ -3166,7 +3166,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
} break;
case PACKED_STRING_ARRAY: {
uint32_t hash = HASH_MURMUR3_SEED;
- const Vector<String> &arr = PackedArrayRef<String>::get_array(_data.packed_array);
+ const PackedStringArray &arr = PackedArrayRef<String>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
@@ -3182,7 +3182,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
} break;
case PACKED_VECTOR2_ARRAY: {
uint32_t hash = HASH_MURMUR3_SEED;
- const Vector<Vector2> &arr = PackedArrayRef<Vector2>::get_array(_data.packed_array);
+ const PackedVector2Array &arr = PackedArrayRef<Vector2>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
@@ -3199,7 +3199,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
} break;
case PACKED_VECTOR3_ARRAY: {
uint32_t hash = HASH_MURMUR3_SEED;
- const Vector<Vector3> &arr = PackedArrayRef<Vector3>::get_array(_data.packed_array);
+ const PackedVector3Array &arr = PackedArrayRef<Vector3>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
@@ -3217,7 +3217,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
} break;
case PACKED_COLOR_ARRAY: {
uint32_t hash = HASH_MURMUR3_SEED;
- const Vector<Color> &arr = PackedArrayRef<Color>::get_array(_data.packed_array);
+ const PackedColorArray &arr = PackedArrayRef<Color>::get_array(_data.packed_array);
int len = arr.size();
if (likely(len)) {
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 602d287f22..d685444c30 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -176,7 +176,7 @@ private:
struct PackedArrayRefBase {
SafeRefCount refcount;
_FORCE_INLINE_ PackedArrayRefBase *reference() {
- if (this->refcount.ref()) {
+ if (refcount.ref()) {
return this;
} else {
return nullptr;
@@ -404,21 +404,21 @@ public:
operator Dictionary() const;
operator Array() const;
- operator Vector<uint8_t>() const;
- operator Vector<int32_t>() const;
- operator Vector<int64_t>() const;
- operator Vector<float>() const;
- operator Vector<double>() const;
- operator Vector<String>() const;
- operator Vector<Vector3>() const;
- operator Vector<Color>() const;
+ operator PackedByteArray() const;
+ operator PackedInt32Array() const;
+ operator PackedInt64Array() const;
+ operator PackedFloat32Array() const;
+ operator PackedFloat64Array() const;
+ operator PackedStringArray() const;
+ operator PackedVector3Array() const;
+ operator PackedVector2Array() const;
+ operator PackedColorArray() const;
+
+ operator Vector<::RID>() const;
operator Vector<Plane>() const;
operator Vector<Face3>() const;
-
operator Vector<Variant>() const;
operator Vector<StringName>() const;
- operator Vector<::RID>() const;
- operator Vector<Vector2>() const;
// some core type enums to convert to
operator Side() const;
@@ -473,21 +473,21 @@ public:
Variant(const Dictionary &p_dictionary);
Variant(const Array &p_array);
+ Variant(const PackedByteArray &p_byte_array);
+ Variant(const PackedInt32Array &p_int32_array);
+ Variant(const PackedInt64Array &p_int64_array);
+ Variant(const PackedFloat32Array &p_float32_array);
+ Variant(const PackedFloat64Array &p_float64_array);
+ Variant(const PackedStringArray &p_string_array);
+ Variant(const PackedVector2Array &p_vector2_array);
+ Variant(const PackedVector3Array &p_vector3_array);
+ Variant(const PackedColorArray &p_color_array);
+
+ Variant(const Vector<::RID> &p_array); // helper
Variant(const Vector<Plane> &p_array); // helper
- Variant(const Vector<uint8_t> &p_byte_array);
- Variant(const Vector<int32_t> &p_int32_array);
- Variant(const Vector<int64_t> &p_int64_array);
- Variant(const Vector<float> &p_float32_array);
- Variant(const Vector<double> &p_float64_array);
- Variant(const Vector<String> &p_string_array);
- Variant(const Vector<Vector3> &p_vector3_array);
- Variant(const Vector<Color> &p_color_array);
Variant(const Vector<Face3> &p_face_array);
-
Variant(const Vector<Variant> &p_array);
Variant(const Vector<StringName> &p_array);
- Variant(const Vector<::RID> &p_array); // helper
- Variant(const Vector<Vector2> &p_array); // helper
Variant(const IPAddress &p_address);
@@ -502,6 +502,7 @@ public:
VARIANT_ENUM_CLASS_CONSTRUCTOR(JoyAxis)
VARIANT_ENUM_CLASS_CONSTRUCTOR(JoyButton)
VARIANT_ENUM_CLASS_CONSTRUCTOR(Key)
+ VARIANT_ENUM_CLASS_CONSTRUCTOR(KeyLocation)
VARIANT_ENUM_CLASS_CONSTRUCTOR(MIDIMessage)
VARIANT_ENUM_CLASS_CONSTRUCTOR(MouseButton)
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 03836985f3..b551a7059e 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -666,7 +666,7 @@ struct _VariantCall {
CharString cs;
cs.resize(p_instance->size() + 1);
memcpy(cs.ptrw(), r, p_instance->size());
- cs[p_instance->size()] = 0;
+ cs[(int)p_instance->size()] = 0;
s = cs.get_data();
}
@@ -885,7 +885,7 @@ struct _VariantCall {
ERR_FAIL_COND_V_MSG(size % sizeof(int32_t), dest, "PackedByteArray size must be a multiple of 4 (size of 32-bit integer) to convert to PackedInt32Array.");
const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(int32_t));
- ERR_FAIL_COND_V(dest.size() == 0, dest); // Avoid UB in case resize failed.
+ ERR_FAIL_COND_V(dest.is_empty(), dest); // Avoid UB in case resize failed.
memcpy(dest.ptrw(), r, dest.size() * sizeof(int32_t));
return dest;
}
@@ -899,7 +899,7 @@ struct _VariantCall {
ERR_FAIL_COND_V_MSG(size % sizeof(int64_t), dest, "PackedByteArray size must be a multiple of 8 (size of 64-bit integer) to convert to PackedInt64Array.");
const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(int64_t));
- ERR_FAIL_COND_V(dest.size() == 0, dest); // Avoid UB in case resize failed.
+ ERR_FAIL_COND_V(dest.is_empty(), dest); // Avoid UB in case resize failed.
memcpy(dest.ptrw(), r, dest.size() * sizeof(int64_t));
return dest;
}
@@ -913,7 +913,7 @@ struct _VariantCall {
ERR_FAIL_COND_V_MSG(size % sizeof(float), dest, "PackedByteArray size must be a multiple of 4 (size of 32-bit float) to convert to PackedFloat32Array.");
const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(float));
- ERR_FAIL_COND_V(dest.size() == 0, dest); // Avoid UB in case resize failed.
+ ERR_FAIL_COND_V(dest.is_empty(), dest); // Avoid UB in case resize failed.
memcpy(dest.ptrw(), r, dest.size() * sizeof(float));
return dest;
}
@@ -927,7 +927,7 @@ struct _VariantCall {
ERR_FAIL_COND_V_MSG(size % sizeof(double), dest, "PackedByteArray size must be a multiple of 8 (size of 64-bit double) to convert to PackedFloat64Array.");
const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(double));
- ERR_FAIL_COND_V(dest.size() == 0, dest); // Avoid UB in case resize failed.
+ ERR_FAIL_COND_V(dest.is_empty(), dest); // Avoid UB in case resize failed.
memcpy(dest.ptrw(), r, dest.size() * sizeof(double));
return dest;
}
diff --git a/core/version.h b/core/version.h
index 5ddb09284e..abb81312ac 100644
--- a/core/version.h
+++ b/core/version.h
@@ -33,6 +33,12 @@
#include "core/version_generated.gen.h"
+// Copied from typedefs.h to stay lean.
+#ifndef _STR
+#define _STR(m_x) #m_x
+#define _MKSTR(m_x) _STR(m_x)
+#endif
+
// Godot versions are of the form <major>.<minor> for the initial release,
// and then <major>.<minor>.<patch> for subsequent bugfix releases where <patch> != 0
// That's arbitrary, but we find it pretty and it's the current policy.