diff options
Diffstat (limited to 'core')
71 files changed, 912 insertions, 465 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 00e74a7cce..f0de22f2ef 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -40,6 +40,7 @@ #include "core/io/file_access_pack.h" #include "core/io/marshalls.h" #include "core/os/keyboard.h" +#include "core/variant/typed_array.h" #include "core/variant/variant_parser.h" #include "core/version.h" @@ -221,7 +222,9 @@ String ProjectSettings::localize_path(const String &p_path) const { void ProjectSettings::set_initial_value(const String &p_name, const Variant &p_value) { ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); - props[p_name].initial = p_value; + + // Duplicate so that if value is array or dictionary, changing the setting will not change the stored initial value. + props[p_name].initial = p_value.duplicate(); } void ProjectSettings::set_restart_if_changed(const String &p_name, bool p_restart) { @@ -299,13 +302,13 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) { for (int i = 1; i < s.size(); i++) { String feature = s[i].strip_edges(); - Pair<StringName, StringName> fo(feature, p_name); + Pair<StringName, StringName> feature_override(feature, p_name); if (!feature_overrides.has(s[0])) { feature_overrides[s[0]] = LocalVector<Pair<StringName, StringName>>(); } - feature_overrides[s[0]].push_back(fo); + feature_overrides[s[0]].push_back(feature_override); } } } @@ -1116,7 +1119,9 @@ bool ProjectSettings::_property_get_revert(const StringName &p_name, Variant &r_ return false; } - r_property = props[p_name].initial; + // Duplicate so that if value is array or dictionary, changing the setting will not change the stored initial value. + r_property = props[p_name].initial.duplicate(); + return true; } @@ -1132,27 +1137,40 @@ Variant ProjectSettings::get_setting(const String &p_setting, const Variant &p_d } } -Array ProjectSettings::get_global_class_list() { - Array script_classes; +TypedArray<Dictionary> ProjectSettings::get_global_class_list() { + if (is_global_class_list_loaded) { + return global_class_list; + } Ref<ConfigFile> cf; cf.instantiate(); - if (cf->load(get_project_data_path().path_join("global_script_class_cache.cfg")) == OK) { - script_classes = cf->get_value("", "list"); + if (cf->load(get_global_class_list_path()) == OK) { + global_class_list = cf->get_value("", "list", Array()); } else { #ifndef TOOLS_ENABLED // Script classes can't be recreated in exported project, so print an error. ERR_PRINT("Could not load global script cache."); #endif } - return script_classes; + + // File read succeeded or failed. If it failed, assume everything is still okay. + // We will later receive updated class data in store_global_class_list(). + is_global_class_list_loaded = true; + + return global_class_list; +} + +String ProjectSettings::get_global_class_list_path() const { + return get_project_data_path().path_join("global_script_class_cache.cfg"); } void ProjectSettings::store_global_class_list(const Array &p_classes) { Ref<ConfigFile> cf; cf.instantiate(); cf->set_value("", "list", p_classes); - cf->save(get_project_data_path().path_join("global_script_class_cache.cfg")); + cf->save(get_global_class_list_path()); + + global_class_list = p_classes; } bool ProjectSettings::has_custom_feature(const String &p_feature) const { @@ -1187,6 +1205,7 @@ void ProjectSettings::_bind_methods() { ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &ProjectSettings::set_setting); ClassDB::bind_method(D_METHOD("get_setting", "name", "default_value"), &ProjectSettings::get_setting, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("get_setting_with_override", "name"), &ProjectSettings::get_setting_with_override); + ClassDB::bind_method(D_METHOD("get_global_class_list"), &ProjectSettings::get_global_class_list); ClassDB::bind_method(D_METHOD("set_order", "name", "position"), &ProjectSettings::set_order); ClassDB::bind_method(D_METHOD("get_order", "name"), &ProjectSettings::get_order); ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &ProjectSettings::set_initial_value); diff --git a/core/config/project_settings.h b/core/config/project_settings.h index d1704a7c31..50cb274831 100644 --- a/core/config/project_settings.h +++ b/core/config/project_settings.h @@ -37,6 +37,9 @@ #include "core/templates/local_vector.h" #include "core/templates/rb_set.h" +template <typename T> +class TypedArray; + class ProjectSettings : public Object { GDCLASS(ProjectSettings, Object); _THREAD_SAFE_CLASS_ @@ -99,6 +102,9 @@ protected: HashMap<StringName, AutoloadInfo> autoloads; + Array global_class_list; + bool is_global_class_list_loaded = false; + String project_data_dir_name; bool _set(const StringName &p_name, const Variant &p_value); @@ -141,8 +147,9 @@ public: void set_setting(const String &p_setting, const Variant &p_value); Variant get_setting(const String &p_setting, const Variant &p_default_value = Variant()) const; - Array get_global_class_list(); + TypedArray<Dictionary> get_global_class_list(); void store_global_class_list(const Array &p_classes); + String get_global_class_list_path() const; bool has_setting(String p_var) const; String localize_path(const String &p_path) const; diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 9de901754a..f2eb7823e2 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -717,7 +717,7 @@ TypedArray<PackedVector2Array> Geometry2D::decompose_polygon_in_convex(const Vec TypedArray<PackedVector2Array> Geometry2D::merge_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { Vector<Vector<Point2>> polys = ::Geometry2D::merge_polygons(p_polygon_a, p_polygon_b); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -739,7 +739,7 @@ TypedArray<PackedVector2Array> Geometry2D::clip_polygons(const Vector<Vector2> & TypedArray<PackedVector2Array> Geometry2D::intersect_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { Vector<Vector<Point2>> polys = ::Geometry2D::intersect_polygons(p_polygon_a, p_polygon_b); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -750,7 +750,7 @@ TypedArray<PackedVector2Array> Geometry2D::intersect_polygons(const Vector<Vecto TypedArray<PackedVector2Array> Geometry2D::exclude_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { Vector<Vector<Point2>> polys = ::Geometry2D::exclude_polygons(p_polygon_a, p_polygon_b); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -761,7 +761,7 @@ TypedArray<PackedVector2Array> Geometry2D::exclude_polygons(const Vector<Vector2 TypedArray<PackedVector2Array> Geometry2D::clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { Vector<Vector<Point2>> polys = ::Geometry2D::clip_polyline_with_polygon(p_polyline, p_polygon); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -772,7 +772,7 @@ TypedArray<PackedVector2Array> Geometry2D::clip_polyline_with_polygon(const Vect TypedArray<PackedVector2Array> Geometry2D::intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { Vector<Vector<Point2>> polys = ::Geometry2D::intersect_polyline_with_polygon(p_polyline, p_polygon); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -783,7 +783,7 @@ TypedArray<PackedVector2Array> Geometry2D::intersect_polyline_with_polygon(const TypedArray<PackedVector2Array> Geometry2D::offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) { Vector<Vector<Point2>> polys = ::Geometry2D::offset_polygon(p_polygon, p_delta, ::Geometry2D::PolyJoinType(p_join_type)); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -794,7 +794,7 @@ TypedArray<PackedVector2Array> Geometry2D::offset_polygon(const Vector<Vector2> TypedArray<PackedVector2Array> Geometry2D::offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { Vector<Vector<Point2>> polys = ::Geometry2D::offset_polyline(p_polygon, p_delta, ::Geometry2D::PolyJoinType(p_join_type), ::Geometry2D::PolyEndType(p_end_type)); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -1590,8 +1590,12 @@ Vector<String> Engine::get_singleton_list() const { return ret; } -void Engine::register_script_language(ScriptLanguage *p_language) { - ScriptServer::register_language(p_language); +Error Engine::register_script_language(ScriptLanguage *p_language) { + return ScriptServer::register_language(p_language); +} + +Error Engine::unregister_script_language(const ScriptLanguage *p_language) { + return ScriptServer::unregister_language(p_language); } int Engine::get_script_language_count() { @@ -1662,6 +1666,7 @@ void Engine::_bind_methods() { ClassDB::bind_method(D_METHOD("get_singleton_list"), &Engine::get_singleton_list); ClassDB::bind_method(D_METHOD("register_script_language", "language"), &Engine::register_script_language); + ClassDB::bind_method(D_METHOD("unregister_script_language", "language"), &Engine::unregister_script_language); ClassDB::bind_method(D_METHOD("get_script_language_count"), &Engine::get_script_language_count); ClassDB::bind_method(D_METHOD("get_script_language", "index"), &Engine::get_script_language); diff --git a/core/core_bind.h b/core/core_bind.h index 8852463234..675da48591 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -499,7 +499,8 @@ public: void unregister_singleton(const StringName &p_name); Vector<String> get_singleton_list() const; - void register_script_language(ScriptLanguage *p_language); + Error register_script_language(ScriptLanguage *p_language); + Error unregister_script_language(const ScriptLanguage *p_language); int get_script_language_count(); ScriptLanguage *get_script_language(int p_index) const; diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index cbb18a277f..939c1c298f 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -65,6 +65,45 @@ void X509Certificate::_bind_methods() { ClassDB::bind_method(D_METHOD("load", "path"), &X509Certificate::load); } +/// TLSOptions + +Ref<TLSOptions> TLSOptions::client(Ref<X509Certificate> p_trusted_chain, const String &p_common_name_override) { + Ref<TLSOptions> opts; + opts.instantiate(); + opts->trusted_ca_chain = p_trusted_chain; + opts->common_name = p_common_name_override; + opts->verify_mode = TLS_VERIFY_FULL; + return opts; +} + +Ref<TLSOptions> TLSOptions::client_unsafe(Ref<X509Certificate> p_trusted_chain) { + Ref<TLSOptions> opts; + opts.instantiate(); + opts->trusted_ca_chain = p_trusted_chain; + if (p_trusted_chain.is_null()) { + opts->verify_mode = TLS_VERIFY_NONE; + } else { + opts->verify_mode = TLS_VERIFY_CERT; + } + return opts; +} + +Ref<TLSOptions> TLSOptions::server(Ref<CryptoKey> p_own_key, Ref<X509Certificate> p_own_certificate) { + Ref<TLSOptions> opts; + opts.instantiate(); + opts->server_mode = true; + opts->own_certificate = p_own_certificate; + opts->private_key = p_own_key; + opts->verify_mode = TLS_VERIFY_NONE; + return opts; +} + +void TLSOptions::_bind_methods() { + ClassDB::bind_static_method("TLSOptions", D_METHOD("client", "trusted_chain", "common_name_override"), &TLSOptions::client, DEFVAL(Ref<X509Certificate>()), DEFVAL(String())); + ClassDB::bind_static_method("TLSOptions", D_METHOD("client_unsafe", "trusted_chain"), &TLSOptions::client_unsafe, DEFVAL(Ref<X509Certificate>())); + ClassDB::bind_static_method("TLSOptions", D_METHOD("server", "key", "certificate"), &TLSOptions::server); +} + /// HMACContext void HMACContext::_bind_methods() { diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h index 981f67883c..999fe076d6 100644 --- a/core/crypto/crypto.h +++ b/core/crypto/crypto.h @@ -67,6 +67,40 @@ public: virtual Error save(String p_path) = 0; }; +class TLSOptions : public RefCounted { + GDCLASS(TLSOptions, RefCounted); + +public: + enum TLSVerifyMode { + TLS_VERIFY_NONE = 0, + TLS_VERIFY_CERT = 1, + TLS_VERIFY_FULL = 2, + }; + +private: + bool server_mode = false; + String common_name; + TLSVerifyMode verify_mode = TLS_VERIFY_FULL; + Ref<X509Certificate> trusted_ca_chain; + Ref<X509Certificate> own_certificate; + Ref<CryptoKey> private_key; + +protected: + static void _bind_methods(); + +public: + static Ref<TLSOptions> client(Ref<X509Certificate> p_trusted_chain = Ref<X509Certificate>(), const String &p_common_name_override = String()); + static Ref<TLSOptions> client_unsafe(Ref<X509Certificate> p_trusted_chain); + static Ref<TLSOptions> server(Ref<CryptoKey> p_own_key, Ref<X509Certificate> p_own_certificate); + + TLSVerifyMode get_verify_mode() const { return verify_mode; } + String get_common_name() const { return common_name; } + Ref<X509Certificate> get_trusted_ca_chain() const { return trusted_ca_chain; } + Ref<X509Certificate> get_own_certificate() const { return own_certificate; } + Ref<CryptoKey> get_private_key() const { return private_key; } + bool is_server() const { return server_mode; } +}; + class HMACContext : public RefCounted { GDCLASS(HMACContext, RefCounted); diff --git a/core/doc_data.cpp b/core/doc_data.cpp index f90dbe1423..5e09e560d5 100644 --- a/core/doc_data.cpp +++ b/core/doc_data.cpp @@ -30,6 +30,14 @@ #include "doc_data.h" +String DocData::get_default_value_string(const Variant &p_value) { + if (p_value.get_type() == Variant::ARRAY) { + return Variant(Array(p_value, 0, StringName(), Variant())).get_construct_string().replace("\n", " "); + } else { + return p_value.get_construct_string().replace("\n", " "); + } +} + void DocData::return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo) { if (p_retinfo.type == Variant::INT && p_retinfo.hint == PROPERTY_HINT_INT_IS_POINTER) { p_method.return_type = p_retinfo.hint_string; @@ -105,7 +113,7 @@ void DocData::property_doc_from_scriptmemberinfo(DocData::PropertyDoc &p_propert p_property.getter = p_memberinfo.getter; if (p_memberinfo.has_default_value && p_memberinfo.default_value.get_type() != Variant::OBJECT) { - p_property.default_value = p_memberinfo.default_value.get_construct_string().replace("\n", ""); + p_property.default_value = get_default_value_string(p_memberinfo.default_value); } p_property.overridden = false; @@ -148,7 +156,7 @@ void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const Met int default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size()); if (default_arg_index >= 0) { Variant default_arg = p_methodinfo.default_arguments[default_arg_index]; - argument.default_value = default_arg.get_construct_string().replace("\n", ""); + argument.default_value = get_default_value_string(default_arg); } p_method.arguments.push_back(argument); } diff --git a/core/doc_data.h b/core/doc_data.h index 1cf4e4f206..c503a4e0d6 100644 --- a/core/doc_data.h +++ b/core/doc_data.h @@ -516,6 +516,8 @@ public: } }; + static String get_default_value_string(const Variant &p_value); + static void return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo); static void argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo); static void property_doc_from_scriptmemberinfo(DocData::PropertyDoc &p_property, const ScriptMemberInfo &p_memberinfo); diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp index a9063c8b27..2bedb623e4 100644 --- a/core/extension/gdextension_interface.cpp +++ b/core/extension/gdextension_interface.cpp @@ -54,14 +54,23 @@ static void gdextension_free(void *p_mem) { } // Helper print functions. -static void gdextension_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { - _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_ERROR); +static void gdextension_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_editor_notify, ERR_HANDLER_ERROR); } -static void gdextension_print_warning(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { - _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_WARNING); +static void gdextension_print_error_with_message(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_message, p_editor_notify, ERR_HANDLER_ERROR); } -static void gdextension_print_script_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { - _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT); +static void gdextension_print_warning(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_editor_notify, ERR_HANDLER_WARNING); +} +static void gdextension_print_warning_with_message(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_message, p_editor_notify, ERR_HANDLER_WARNING); +} +static void gdextension_print_script_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_editor_notify, ERR_HANDLER_SCRIPT); +} +static void gdextension_print_script_error_with_message(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_message, p_editor_notify, ERR_HANDLER_SCRIPT); } uint64_t gdextension_get_native_struct_size(GDExtensionConstStringNamePtr p_name) { @@ -856,6 +865,19 @@ static GDExtensionVariantPtr gdextension_array_operator_index_const(GDExtensionC return (GDExtensionVariantPtr)&self->operator[](p_index); } +void gdextension_array_ref(GDExtensionTypePtr p_self, GDExtensionConstTypePtr p_from) { + Array *self = (Array *)p_self; + const Array *from = (const Array *)p_from; + self->_ref(*from); +} + +void gdextension_array_set_typed(GDExtensionTypePtr p_self, GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstVariantPtr p_script) { + Array *self = reinterpret_cast<Array *>(p_self); + const StringName *class_name = reinterpret_cast<const StringName *>(p_class_name); + const Variant *script = reinterpret_cast<const Variant *>(p_script); + self->set_typed((uint32_t)p_type, *class_name, *script); +} + /* Dictionary functions */ static GDExtensionVariantPtr gdextension_dictionary_operator_index(GDExtensionTypePtr p_self, GDExtensionConstVariantPtr p_key) { @@ -1001,8 +1023,11 @@ void gdextension_setup_interface(GDExtensionInterface *p_interface) { gde_interface.mem_free = gdextension_free; gde_interface.print_error = gdextension_print_error; + gde_interface.print_error_with_message = gdextension_print_error_with_message; gde_interface.print_warning = gdextension_print_warning; + gde_interface.print_warning_with_message = gdextension_print_warning_with_message; gde_interface.print_script_error = gdextension_print_script_error; + gde_interface.print_script_error_with_message = gdextension_print_script_error_with_message; gde_interface.get_native_struct_size = gdextension_get_native_struct_size; @@ -1129,6 +1154,8 @@ void gdextension_setup_interface(GDExtensionInterface *p_interface) { gde_interface.array_operator_index = gdextension_array_operator_index; gde_interface.array_operator_index_const = gdextension_array_operator_index_const; + gde_interface.array_ref = gdextension_array_ref; + gde_interface.array_set_typed = gdextension_array_set_typed; /* Dictionary functions */ diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h index 6e5dee8265..f323b2aa53 100644 --- a/core/extension/gdextension_interface.h +++ b/core/extension/gdextension_interface.h @@ -37,7 +37,6 @@ #include <stddef.h> #include <stdint.h> -#include <stdio.h> #ifndef __cplusplus typedef uint32_t char32_t; @@ -415,9 +414,12 @@ typedef struct { void *(*mem_realloc)(void *p_ptr, size_t p_bytes); void (*mem_free)(void *p_ptr); - void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); - void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); - void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); + void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); + void (*print_error_with_message)(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); + void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); + void (*print_warning_with_message)(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); + void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); + void (*print_script_error_with_message)(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); uint64_t (*get_native_struct_size)(GDExtensionConstStringNamePtr p_name); @@ -551,6 +553,8 @@ typedef struct { GDExtensionVariantPtr (*array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr GDExtensionVariantPtr (*array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr + void (*array_ref)(GDExtensionTypePtr p_self, GDExtensionConstTypePtr p_from); // p_self should be an Array ptr + void (*array_set_typed)(GDExtensionTypePtr p_self, GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstVariantPtr p_script); // p_self should be an Array ptr /* Dictionary functions */ diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt index dcb6aefb00..59461959d5 100644 --- a/core/input/gamecontrollerdb.txt +++ b/core/input/gamecontrollerdb.txt @@ -69,7 +69,7 @@ 03000000c82d00000121000000000000,8BitDo SN30 Pro for Android,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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00001130000000000000,8BitDo Ultimate Wired,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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001130000000000000,8BitDo Ultimate Wired,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,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00001230000000000000,8BitDo Ultimate Wireless,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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00001330000000000000,8BitDo Ultimate Wireless,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,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, 03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, @@ -383,7 +383,7 @@ 0300000079000000d218000000000000,Mayflash Magic NS,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:Windows, 03000000d620000010a7000000000000,Mayflash Magic NS,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, 03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows, -030000008f0e00001030000000000000,Mayflash Sega Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows, +030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, 0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, 03000000790000000318000000000000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, 03000000790000000018000000000000,Mayflash Wii U Pro Adapter,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, @@ -407,7 +407,6 @@ 03000000c62400002b89000000000000,Moga XP5A Plus,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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000c62400001a89000000000000,Moga XP5X Plus,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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000c62400001b89000000000000,Moga XP5X Plus,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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000efbe0000edfe000000000000,Monect Virtual Controller,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:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, 03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,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:b8,x:b3,y:b0,platform:Windows, 03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows, 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, @@ -484,8 +483,8 @@ 030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows, 030000004f1f00000800000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 03000000632500007505000000000000,PS3 Controller,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:Windows, -03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, -03000000888800000804000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,leftshoulder:b10,leftstick:b1,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, +03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows, +03000000888800000804000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, 030000008f0e00000300000000000000,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:a5,start:b9,x:b3,y:b0,platform:Windows, 030000008f0e00001431000000000000,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, 03000000ba2200002010000000000000,PS3 Controller,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:Windows, @@ -542,8 +541,9 @@ 030000009b2800005600000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, 030000009b2800005700000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, 030000009b2800001e00000000000000,Raphnet Vectrex Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows, -030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, -030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,x:b0,y:b5,back:b2,guide:b10,start:b3,leftshoulder:b6,rightshoulder:b7,dpup:b12,dpleft:b14,dpdown:b13,dpright:b15,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows, 03000000321500000003000000000000,Razer Hydra,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,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000321500000204000000000000,Razer Panthera 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, 03000000321500000104000000000000,Razer Panthera PS4,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, @@ -574,7 +574,7 @@ 030000006f0e00001e01000000000000,Rock Candy 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, 030000006f0e00002801000000000000,Rock Candy 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, 030000006f0e00002f01000000000000,Rock Candy 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, -030000006f0e00008701000000000000,Rock Candy Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00008701000000000000,Rock Candy Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000050b0000e318000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, 03000000050b0000e518000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, 03000000050b00005819000000000000,ROG Chakram Core,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, @@ -678,7 +678,7 @@ 030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows, 03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows, 03000000d90400000200000000000000,TwinShock PS2 Controller,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000151900005678000000000000,Uniplay U6,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b10,x:b3,y:b4,platform:Windows, +03000000151900005678000000000000,Uniplay U6,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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000101c0000171c000000000000,uRage 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:Windows, 030000000b0400003065000000000000,USB 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:a5,start:b9,x:b3,y:b0,platform:Windows, 03000000242f00006e00000000000000,USB Controller,a:b1,b:b4,back:b10,leftshoulder:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b3,platform:Windows, @@ -798,7 +798,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00001130000000020000,8BitDo Ultimate Wired,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:Mac OS X, +03000000c82d00001130000000020000,8BitDo Ultimate Wired,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,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000c82d00001330000001000000,8BitDo Ultimate Wireless,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,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000c82d00001330000000020000,8BitDo Ultimate Wireless Controller,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,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, @@ -843,6 +843,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00008400000000010000,Hori Fighting Commander 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: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, 030000000d0f00008500000000010000,Hori Fighting Commander 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:Mac OS X, +03000000341a00000302000014010000,Hori Fighting Stick Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00008800000000010000,Hori Fighting Stick mini 4 (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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00008700000000010000,Hori Fighting Stick mini 4 (PS4),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:Mac OS X, 030000000d0f00004d00000000000000,Hori Gem Pad 3,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, @@ -881,6 +882,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X, 0300000079000000d218000026010000,Mayflash Magic NS,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:Mac OS X, 03000000d620000010a7000003010000,Mayflash Magic NS,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, +030000008f0e00001030000011010000,Mayflash Saturn Adapter,a:b0,b:b2,dpdown:b28,dpleft:b30,dpright:b26,dpup:b24,leftshoulder:b10,lefttrigger:b14,rightshoulder:b12,righttrigger:b4,start:b18,x:b6,y:b8,platform:Mac OS X, 0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, 03000000790000000318000000010000,Mayflash Wii DolphinBar,a:b8,b:b12,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b44,leftshoulder:b16,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b4,platform:Mac OS X, 03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, @@ -897,6 +899,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000d620000011a7000010050000,Nintendo Switch PowerA 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:Mac OS X, 030000007e0500000920000000000000,Nintendo Switch Pro Controller,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:Mac OS X, 030000007e0500000920000001000000,Nintendo Switch Pro Controller,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:Mac OS X, +050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,platform:Mac OS X, 030000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Mac OS X, 030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,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:Mac OS X, @@ -919,6 +922,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 050000004c050000f20d000000010000,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, +030000005e040000e002000001000000,PXN P30 Pro Mobile,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:Mac OS X, 03000000222c00000225000000010000,Qanba Dragon Arcade Joystick (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:Mac OS X, 03000000222c00000020000000010000,Qanba Drone Arcade Stick,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, 030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, @@ -940,7 +944,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Mac OS X, 030000006b140000010d000000010000,Revolution Pro 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, 030000006b140000130d000000010000,Revolution Pro Controller 3,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, +030000004c0500006802000002100000,Rii RK707,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b3,righttrigger:b9,rightx:a2,righty:a3,start:b1,x:b15,y:b12,platform:Mac OS X, 03000000c6240000fefa000000000000,Rock Candy PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000006f0e00008701000005010000,Rock Candy Switch 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:Mac OS X, 03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Mac OS X, 03000000a30c00002500000006020000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Mac OS X, 03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, @@ -973,6 +979,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005f140000c501000000020000,Trust 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:Mac OS X, 03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, 03000000632500002605000000010000,Uberwith 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, +03000000151900005678000010010000,Uniplay U6,a:b3,b:b6,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,leftstick:b31,lefttrigger:b21,leftx:a1,lefty:a3,rightshoulder:b19,rightstick:b33,righttrigger:b23,rightx:a4,righty:a5,start:b27,x:b11,y:b13,platform:Mac OS X, 030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,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:Mac OS X, 030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,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,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, @@ -985,6 +992,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000130b000011050000,Xbox One Controller,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:Mac OS X, 030000005e040000200b000011050000,Xbox One Controller,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:Mac OS X, 030000005e040000200b000013050000,Xbox One Controller,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:Mac OS X, +030000005e040000200b000015050000,Xbox One Controller,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Mac OS X, 030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,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:Mac OS X, @@ -1029,8 +1037,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux, -03000000c82d00001030000011010000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux, 05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux, +03000000c82d00000631000014010000,8BitDo Pro 2 Wired 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, +03000000c82d00001030000011010000,8BitDo Pro 2 Wired Controller,a:b1,b:b0,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:b4,y:b3,platform:Linux, +03000000c82d00000020000000000000,8BitDo Pro 2 Wired Controller for Xbox,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, +06000000c82d00000020000006010000,8BitDo Pro 2 Wired Controller for Xbox,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, 03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000231000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, @@ -1053,7 +1064,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00000260000011010000,8BitDo SN30 Pro Plus,a:b1,b:b0,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:b4,y:b3,platform:Linux, 05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,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:b4,y:b3,platform:Linux, 05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00001130000011010000,8BitDo Ultimate Wired,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, +03000000c82d00001130000011010000,8BitDo Ultimate Wired,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,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,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:b4,y:b3,platform:Linux, 03000000c82d00001230000011010000,8BitDo Ultimate Wireless,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, 03000000c82d00001330000011010000,8BitDo Ultimate Wireless,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,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, @@ -1116,12 +1127,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, 19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 03000000ac0500005b05000010010000,GameSir G3w,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, 03000000bc2000000055000011010000,GameSir G3w,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, 03000000558500001b06000010010000,GameSir G4 Pro,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, 05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,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, 03000000bc2000005656000011010000,GameSir T4w,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, +03000000ac0500001a06000011010000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,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, 0500000047532047616d657061640000,GameStop 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, 030000006f0e00000104000000010000,Gamestop Logic3 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, 030000008f0e00000800000010010000,Gasia PlayStation 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, @@ -1149,6 +1162,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000000d0f00005001000009040000,Hori Fighting Commander OCTA Xbox One,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, 030000000d0f00008500000010010000,Hori Fighting Commander 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, 030000000d0f00008600000002010000,Hori Fighting Commander Xbox 360,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, +030000000d0f00003701000013010000,Hori Fighting Stick Mini,a:b1,b:b0,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:b3,y:b2,platform:Linux, 030000000d0f00008800000011010000,Hori Fighting Stick mini 4 (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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f00008700000011010000,Hori Fighting Stick mini 4 (PS4),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,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f00001000000011010000,Hori Fightstick 3,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, @@ -1173,6 +1187,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000242e00000b20000001000000,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:Linux, 03000000242e0000ff0b000011010000,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:Linux, 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 SNES 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, 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, @@ -1230,8 +1245,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 0300000079000000d218000011010000,Mayflash Magic NS,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, 03000000d620000010a7000011010000,Mayflash Magic NS,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, 03000000242f0000f700000001010000,Mayflash Magic S Pro,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, +030000008f0e00001030000010010000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux, 0300000025090000e803000001010000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, 03000000790000000318000011010000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux, +03000000790000000018000011010000,Mayflash Wii U Pro Adapter,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, 03000000b50700001203000010010000,Mega World Logic 3 Controller,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, 03000000780000000600000010010000,Microntek Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 030000005e0400002800000000010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Linux, @@ -1276,12 +1293,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000009b2800008000000020020000,Nintendo Classic Controller,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux, 030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux, 03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux, +060000004e696e74656e646f20537700,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, 060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, 060000007e0500000820000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, 050000004c69632050726f20436f6e00,Nintendo Switch Controller,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b16,b:b15,back:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,platform:Linux, 03000000d620000013a7000011010000,Nintendo Switch PowerA 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, 03000000d620000011a7000011010000,Nintendo Switch PowerA Core Plus 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, +030000007e0500000920000000026803,Nintendo Switch Pro Controller,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Linux, 030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, 050000007e0500000920000001000000,Nintendo Switch Pro Controller,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,misc1:b4,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, @@ -1312,7 +1331,6 @@ 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, 030000006f0e00008501000011010000,PDP Nintendo Switch Fightpad Pro,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, 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, -030000006f0e00008701000011010000,PDP Rock Nintendo Switch Candy Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,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, 030000006f0e00000901000011010000,PDP 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, 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, @@ -1330,6 +1348,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000d62000000228000001010000,PowerA Xbox One 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, 03000000c62400001a54000001010000,PowerA Xbox One Mini 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, 03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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, +03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,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, 030000006d040000d2ca000011010000,Precision 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, 03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000341a00003608000011010000,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, @@ -1369,6 +1388,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux, 03000000222c00000225000011010000,Qanba Dragon Arcade Joystick (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, 03000000222c00000025000011010000,Qanba Dragon Arcade Joystick (PS4),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, +03000000222c00000020000011010000,Qanba Drone Arcade PS4 Joystick,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,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Linux, 03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux, 03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick (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, 03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick (PS4),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, @@ -1400,6 +1420,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006b140000130d000011010000,Revolution Pro Controller 3,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, 030000006f0e00001f01000000010000,Rock Candy,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, 030000006f0e00001e01000011010000,Rock Candy 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, +030000006f0e00008701000011010000,Rock Candy Switch Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,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, 03000000c6240000fefa000000010000,Rock Candy Xbox 360 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, 030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,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, 03000000a306000023f6000011010000,Saitek Cyborg V1 PlayStation 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:a4,start:b9,x:b0,y:b3,platform:Linux, @@ -1429,6 +1450,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e0400008e02000073050000,Speedlink Torid,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, 030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,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, 03000000d11800000094000011010000,Stadia 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +05000000d11800000094000000010000,Stadia 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, 03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, 03000000de2800000112000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, 03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, @@ -1482,6 +1504,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000f00600000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux, 030000005f140000c501000010010000,Trust 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, 03000000100800000100000010010000,Twin PS2 Adapter,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000151900005678000010010000,Uniplay U6,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, 03000000100800000300000010010000,USB Gamepad,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000790000000600000007010000,USB 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:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, 03000000790000001100000000010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, @@ -1656,9 +1679,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a5,righty:a2,start:b30,x:b23,y:b24,platform:Android, 436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, 65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +37316565396364386635383230353365,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, +4875694a696120205553422047616d65,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, 535a4d792d706f776572204c54442043,Mayflash Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b31,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, 30653962643666303631376438373532,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, -484a5a204d6179666c61736820576969,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, +39346131396233376535393665363161,Mayflash Wii U Pro Adapter,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftstick:b31,lefttrigger:b27,rightshoulder:b26,rightstick:b0,righttrigger:b28,rightx:a0,righty:a1,start:b30,x:b21,y:b24,platform:Android, 31323564663862633234646330373138,Mega Drive,a:b23,b:b22,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, 37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, 64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Android, @@ -1737,10 +1762,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 526574726f5553422e636f6d20534e45,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android, 64643037633038386238303966376137,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android, +37656564346533643138636436356230,Rock Candy Switch Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, 33373336396634316434323337666361,RumblePad 2,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android, 66386565396238363534313863353065,Sanwa PlayOnline Mobile,a:b21,b:b22,back:b23,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b24,platform:Android, 32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, -37316565396364386635383230353365,Saturn,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, 38613865396530353338373763623431,Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b10,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android, 61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, 30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, @@ -1753,6 +1778,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android, 63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android, 476f6f676c65204c4c43205374616469,Stadia Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +5374616469614e3848532d6532633400,Stadia Controller,a:b0,b:b1,back:b15,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000de2800000511000001000000,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, 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, diff --git a/core/input/godotcontrollerdb.txt b/core/input/godotcontrollerdb.txt index e11099f380..eb4a1a1578 100644 --- a/core/input/godotcontrollerdb.txt +++ b/core/input/godotcontrollerdb.txt @@ -32,7 +32,7 @@ Linux046dc216,046d-c216-Logitech Logitech Dual Action,a:b1,b:b2,y:b3,x:b0,start: Linux20d6a713,Bensussen Deutsch & Associates Inc.(BDA) NSW Wired controller,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:-a5,dpleft:-a4,dpdown:+a5,dpright:+a4,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Web Linux054c05c4,Sony Computer Entertainment Wireless Controller,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:-a7,dpleft:-a6,dpdown:+a7,dpright:+a6,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Web Linux18d19400,18d1-9400-Google LLC Stadia Controller rev. A,a:b0,b:b1,y:b3,x:b2,start:b7,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:-a7,dpleft:-a6,dpdown:+a7,dpright:+a6,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Web -Linux054c0268,054c-0268-Sony PLAYSTATION(R)3 Controller,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Web +Linux054c0268,054c-0268-Sony PLAYSTATION(R)3 Controller,a:b0,b:b1,y:b2,x:b3,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Web # UWP __UWP_GAMEPAD__,Xbox Controller,a:b2,b:b3,x:b4,y:b5,start:b0,back:b1,leftstick:b12,rightstick:b13,leftshoulder:b10,rightshoulder:b11,dpup:b6,dpdown:b7,dpleft:b8,dpright:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:UWP, diff --git a/core/input/input.cpp b/core/input/input.cpp index 3cf83fd64b..b2164b8e76 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -231,14 +231,17 @@ Input::VelocityTrack::VelocityTrack() { bool Input::is_anything_pressed() const { _THREAD_SAFE_METHOD_ + if (!keys_pressed.is_empty() || !joy_buttons_pressed.is_empty() || !mouse_button_mask.is_empty()) { + return true; + } + for (const KeyValue<StringName, Input::Action> &E : action_state) { if (E.value.pressed) { return true; } } - return !keys_pressed.is_empty() || - !joy_buttons_pressed.is_empty() || - !mouse_button_mask.is_empty(); + + return false; } bool Input::is_key_pressed(Key p_keycode) const { @@ -533,6 +536,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em touch_event->set_pressed(mb->is_pressed()); touch_event->set_position(mb->get_position()); touch_event->set_double_tap(mb->is_double_click()); + touch_event->set_device(InputEvent::DEVICE_ID_EMULATION); event_dispatch_function(touch_event); } } @@ -557,6 +561,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em 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_device(InputEvent::DEVICE_ID_EMULATION); event_dispatch_function(drag_event); } @@ -592,7 +597,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em Ref<InputEventMouseButton> button_event; button_event.instantiate(); - button_event->set_device(InputEvent::DEVICE_ID_TOUCH_MOUSE); + button_event->set_device(InputEvent::DEVICE_ID_EMULATION); button_event->set_position(st->get_position()); button_event->set_global_position(st->get_position()); button_event->set_pressed(st->is_pressed()); @@ -623,7 +628,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em Ref<InputEventMouseMotion> motion_event; motion_event.instantiate(); - motion_event->set_device(InputEvent::DEVICE_ID_TOUCH_MOUSE); + motion_event->set_device(InputEvent::DEVICE_ID_EMULATION); motion_event->set_tilt(sd->get_tilt()); motion_event->set_pen_inverted(sd->get_pen_inverted()); motion_event->set_pressure(sd->get_pressure()); @@ -832,7 +837,7 @@ void Input::ensure_touch_mouse_raised() { Ref<InputEventMouseButton> button_event; button_event.instantiate(); - button_event->set_device(InputEvent::DEVICE_ID_TOUCH_MOUSE); + button_event->set_device(InputEvent::DEVICE_ID_EMULATION); button_event->set_position(mouse_pos); button_event->set_global_position(mouse_pos); button_event->set_pressed(false); @@ -869,6 +874,7 @@ void Input::set_default_cursor_shape(CursorShape p_shape) { mm.instantiate(); mm->set_position(mouse_pos); mm->set_global_position(mouse_pos); + mm->set_device(InputEvent::DEVICE_ID_INTERNAL); parse_input_event(mm); } @@ -891,6 +897,31 @@ void Input::parse_input_event(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); +#ifdef DEBUG_ENABLED + uint64_t curr_frame = Engine::get_singleton()->get_process_frames(); + if (curr_frame != last_parsed_frame) { + frame_parsed_events.clear(); + last_parsed_frame = curr_frame; + frame_parsed_events.insert(p_event); + } else if (frame_parsed_events.has(p_event)) { + // It would be technically safe to send the same event in cases such as: + // - After an explicit flush. + // - In platforms using buffering when agile flushing is enabled, after one of the mid-frame flushes. + // - If platform doesn't use buffering and event accumulation is disabled. + // - If platform doesn't use buffering and the event type is not accumulable. + // However, it wouldn't be reasonable to ask users to remember the full ruleset and be aware at all times + // of the possibilities of the target platform, project settings and engine internals, which may change + // without prior notice. + // Therefore, the guideline is, "don't send the same event object more than once per frame". + WARN_PRINT_ONCE( + "An input event object is being parsed more than once in the same frame, which is unsafe.\n" + "If you are generating events in a script, you have to instantiate a new event instead of sending the same one more than once, unless the original one was sent on an earlier frame.\n" + "You can call duplicate() on the event to get a new instance with identical values."); + } else { + frame_parsed_events.insert(p_event); + } +#endif + if (use_accumulated_input) { if (buffered_events.is_empty() || !buffered_events.back()->get()->accumulate(p_event)) { buffered_events.push_back(p_event); @@ -1334,8 +1365,9 @@ void Input::parse_mapping(String p_mapping) { JoyButton output_button = _get_output_button(output); JoyAxis output_axis = _get_output_axis(output); - ERR_CONTINUE_MSG(output_button == JoyButton::INVALID && output_axis == JoyAxis::INVALID, - vformat("Unrecognized output string \"%s\" in mapping:\n%s", output, p_mapping)); + if (output_button == JoyButton::INVALID && output_axis == JoyAxis::INVALID) { + print_verbose(vformat("Unrecognized output string \"%s\" in mapping:\n%s", output, p_mapping)); + } ERR_CONTINUE_MSG(output_button != JoyButton::INVALID && output_axis != JoyAxis::INVALID, vformat("Output string \"%s\" matched both button and axis in mapping:\n%s", output, p_mapping)); diff --git a/core/input/input.h b/core/input/input.h index f2de56b6b9..c254650ef8 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -223,6 +223,10 @@ private: void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated); List<Ref<InputEvent>> buffered_events; +#ifdef DEBUG_ENABLED + HashSet<Ref<InputEvent>> frame_parsed_events; + uint64_t last_parsed_frame = UINT64_MAX; +#endif friend class DisplayServer; diff --git a/core/input/input_enums.h b/core/input/input_enums.h index 02efde2d30..7974ee639d 100644 --- a/core/input/input_enums.h +++ b/core/input/input_enums.h @@ -122,6 +122,7 @@ enum class MouseButton { }; enum class MouseButtonMask { + NONE = 0, LEFT = (1 << (int(MouseButton::LEFT) - 1)), RIGHT = (1 << (int(MouseButton::RIGHT) - 1)), MIDDLE = (1 << (int(MouseButton::MIDDLE) - 1)), diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 5a9ec74184..a6c1bb168c 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -34,7 +34,7 @@ #include "core/input/shortcut.h" #include "core/os/keyboard.h" -const int InputEvent::DEVICE_ID_TOUCH_MOUSE = -1; +const int InputEvent::DEVICE_ID_EMULATION = -1; const int InputEvent::DEVICE_ID_INTERNAL = -2; void InputEvent::set_device(int p_device) { @@ -1186,14 +1186,14 @@ static const char *_joy_button_descriptions[(size_t)JoyButton::SDL_MAX] = { }; String InputEventJoypadButton::as_text() const { - String text = "Joypad Button " + itos((int64_t)button_index); + String text = vformat(RTR("Joypad Button %d"), (int64_t)button_index); if (button_index > JoyButton::INVALID && button_index < JoyButton::SDL_MAX) { - text += vformat(" (%s)", _joy_button_descriptions[(size_t)button_index]); + text += vformat(" (%s)", TTRGET(_joy_button_descriptions[(size_t)button_index])); } if (pressure != 0) { - text += ", Pressure:" + String(Variant(pressure)); + text += ", " + RTR("Pressure:") + " " + String(Variant(pressure)); } return text; diff --git a/core/input/input_event.h b/core/input/input_event.h index 797761b208..eff8d479db 100644 --- a/core/input/input_event.h +++ b/core/input/input_event.h @@ -59,7 +59,7 @@ protected: static void _bind_methods(); public: - static const int DEVICE_ID_TOUCH_MOUSE; + static const int DEVICE_ID_EMULATION; static const int DEVICE_ID_INTERNAL; void set_device(int p_device); diff --git a/core/io/dtls_server.cpp b/core/io/dtls_server.cpp index c542e394a1..07d62d3a8d 100644 --- a/core/io/dtls_server.cpp +++ b/core/io/dtls_server.cpp @@ -48,6 +48,6 @@ bool DTLSServer::is_available() { } void DTLSServer::_bind_methods() { - ClassDB::bind_method(D_METHOD("setup", "key", "certificate", "chain"), &DTLSServer::setup, DEFVAL(Ref<X509Certificate>())); + ClassDB::bind_method(D_METHOD("setup", "server_options"), &DTLSServer::setup); ClassDB::bind_method(D_METHOD("take_connection", "udp_peer"), &DTLSServer::take_connection); } diff --git a/core/io/dtls_server.h b/core/io/dtls_server.h index e749e6968b..f3fbde3c15 100644 --- a/core/io/dtls_server.h +++ b/core/io/dtls_server.h @@ -47,7 +47,7 @@ public: static bool is_available(); static DTLSServer *create(); - virtual Error setup(Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain = Ref<X509Certificate>()) = 0; + virtual Error setup(Ref<TLSOptions> p_options) = 0; virtual void stop() = 0; virtual Ref<PacketPeerDTLS> take_connection(Ref<PacketPeerUDP> p_peer) = 0; diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 829abdc614..190edbfb82 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -138,7 +138,7 @@ PackedStringArray HTTPClient::_get_response_headers() { } void HTTPClient::_bind_methods() { - ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "use_tls", "verify_host"), &HTTPClient::connect_to_host, DEFVAL(-1), DEFVAL(false), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "tls_options"), &HTTPClient::connect_to_host, DEFVAL(-1), DEFVAL(Ref<TLSOptions>())); ClassDB::bind_method(D_METHOD("set_connection", "connection"), &HTTPClient::set_connection); ClassDB::bind_method(D_METHOD("get_connection"), &HTTPClient::get_connection); ClassDB::bind_method(D_METHOD("request_raw", "method", "url", "headers", "body"), &HTTPClient::_request_raw); diff --git a/core/io/http_client.h b/core/io/http_client.h index 853ea7f472..9e018182e3 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -31,6 +31,7 @@ #ifndef HTTP_CLIENT_H #define HTTP_CLIENT_H +#include "core/crypto/crypto.h" #include "core/io/ip.h" #include "core/io/stream_peer.h" #include "core/io/stream_peer_tcp.h" @@ -168,7 +169,7 @@ public: Error verify_headers(const Vector<String> &p_headers); virtual Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const uint8_t *p_body, int p_body_size) = 0; - virtual Error connect_to_host(const String &p_host, int p_port = -1, bool p_tls = false, bool p_verify_host = true) = 0; + virtual Error connect_to_host(const String &p_host, int p_port = -1, Ref<TLSOptions> p_tls_options = Ref<TLSOptions>()) = 0; virtual void set_connection(const Ref<StreamPeer> &p_connection) = 0; virtual Ref<StreamPeer> get_connection() const = 0; diff --git a/core/io/http_client_tcp.cpp b/core/io/http_client_tcp.cpp index 5cdb13fa06..3788fa501e 100644 --- a/core/io/http_client_tcp.cpp +++ b/core/io/http_client_tcp.cpp @@ -39,29 +39,31 @@ HTTPClient *HTTPClientTCP::_create_func() { return memnew(HTTPClientTCP); } -Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, bool p_tls, bool p_verify_host) { +Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, Ref<TLSOptions> p_options) { close(); conn_port = p_port; conn_host = p_host; + tls_options = p_options; ip_candidates.clear(); - tls = p_tls; - tls_verify_host = p_verify_host; - String host_lower = conn_host.to_lower(); if (host_lower.begins_with("http://")) { conn_host = conn_host.substr(7, conn_host.length() - 7); + tls_options.unref(); } else if (host_lower.begins_with("https://")) { - tls = true; + if (tls_options.is_null()) { + tls_options = TLSOptions::client(); + } conn_host = conn_host.substr(8, conn_host.length() - 8); } + ERR_FAIL_COND_V(tls_options.is_valid() && tls_options->is_server(), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(conn_host.length() < HOST_MIN_LEN, ERR_INVALID_PARAMETER); if (conn_port < 0) { - if (tls) { + if (tls_options.is_valid()) { conn_port = PORT_HTTPS; } else { conn_port = PORT_HTTP; @@ -70,11 +72,11 @@ Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, bool p_tl connection = tcp_connection; - if (tls && https_proxy_port != -1) { + if (tls_options.is_valid() && https_proxy_port != -1) { proxy_client.instantiate(); // Needs proxy negotiation. server_host = https_proxy_host; server_port = https_proxy_port; - } else if (!tls && http_proxy_port != -1) { + } else if (tls_options.is_null() && http_proxy_port != -1) { server_host = http_proxy_host; server_port = http_proxy_port; } else { @@ -107,7 +109,7 @@ Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, bool p_tl void HTTPClientTCP::set_connection(const Ref<StreamPeer> &p_connection) { ERR_FAIL_COND_MSG(p_connection.is_null(), "Connection is not a reference to a valid StreamPeer object."); - if (tls) { + if (tls_options.is_valid()) { ERR_FAIL_NULL_MSG(Object::cast_to<StreamPeerTLS>(p_connection.ptr()), "Connection is not a reference to a valid StreamPeerTLS object."); } @@ -156,7 +158,7 @@ Error HTTPClientTCP::request(Method p_method, const String &p_url, const Vector< } String uri = p_url; - if (!tls && http_proxy_port != -1) { + if (tls_options.is_null() && http_proxy_port != -1) { uri = vformat("http://%s:%d%s", conn_host, conn_port, p_url); } @@ -181,7 +183,7 @@ Error HTTPClientTCP::request(Method p_method, const String &p_url, const Vector< } } if (add_host) { - if ((tls && conn_port == PORT_HTTPS) || (!tls && conn_port == PORT_HTTP)) { + if ((tls_options.is_valid() && conn_port == PORT_HTTPS) || (tls_options.is_null() && conn_port == PORT_HTTP)) { // Don't append the standard ports. request += "Host: " + conn_host + "\r\n"; } else { @@ -316,7 +318,7 @@ Error HTTPClientTCP::poll() { return OK; } break; case StreamPeerTCP::STATUS_CONNECTED: { - if (tls && proxy_client.is_valid()) { + if (tls_options.is_valid() && proxy_client.is_valid()) { Error err = proxy_client->poll(); if (err == ERR_UNCONFIGURED) { proxy_client->set_connection(tcp_connection); @@ -357,13 +359,12 @@ Error HTTPClientTCP::poll() { return ERR_CANT_CONNECT; } break; } - } else if (tls) { + } else if (tls_options.is_valid()) { Ref<StreamPeerTLS> tls_conn; if (!handshaking) { // Connect the StreamPeerTLS and start handshaking. tls_conn = Ref<StreamPeerTLS>(StreamPeerTLS::create()); - tls_conn->set_blocking_handshake_enabled(false); - Error err = tls_conn->connect_to_stream(tcp_connection, tls_verify_host, conn_host); + Error err = tls_conn->connect_to_stream(tcp_connection, conn_host, tls_options); if (err != OK) { close(); status = STATUS_TLS_HANDSHAKE_ERROR; @@ -421,7 +422,7 @@ Error HTTPClientTCP::poll() { case STATUS_BODY: case STATUS_CONNECTED: { // Check if we are still connected. - if (tls) { + if (tls_options.is_valid()) { Ref<StreamPeerTLS> tmp = connection; tmp->poll(); if (tmp->get_status() != StreamPeerTLS::STATUS_CONNECTED) { diff --git a/core/io/http_client_tcp.h b/core/io/http_client_tcp.h index 97ac2d76a7..6060c975bc 100644 --- a/core/io/http_client_tcp.h +++ b/core/io/http_client_tcp.h @@ -33,6 +33,8 @@ #include "http_client.h" +#include "core/crypto/crypto.h" + class HTTPClientTCP : public HTTPClient { private: Status status = STATUS_DISCONNECTED; @@ -46,11 +48,10 @@ private: String http_proxy_host; int https_proxy_port = -1; // Proxy server for https requests. String https_proxy_host; - bool tls = false; - bool tls_verify_host = false; bool blocking = false; bool handshaking = false; bool head_request = false; + Ref<TLSOptions> tls_options; Vector<uint8_t> response_str; @@ -79,7 +80,7 @@ public: Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const uint8_t *p_body, int p_body_size) override; - Error connect_to_host(const String &p_host, int p_port = -1, bool p_tls = false, bool p_verify_host = true) override; + Error connect_to_host(const String &p_host, int p_port = -1, Ref<TLSOptions> p_tls_options = Ref<TLSOptions>()) override; void set_connection(const Ref<StreamPeer> &p_connection) override; Ref<StreamPeer> get_connection() const override; void close() override; diff --git a/core/io/image.cpp b/core/io/image.cpp index 9408a9c103..736a3ec82e 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -78,6 +78,10 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "ETC2_RGB8A1", "ETC2_RA_AS_RG", "FORMAT_DXT5_RA_AS_RG", + "ASTC_4x4", + "ASTC_4x4_HDR", + "ASTC_8x8", + "ASTC_8x8_HDR", }; SavePNGFunc Image::save_png_func = nullptr; @@ -2187,16 +2191,16 @@ void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Forma int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); if (unlikely(p_data.size() != size)) { - String description_mipmaps; + String description_mipmaps = get_format_name(p_format) + " "; if (p_use_mipmaps) { const int num_mipmaps = get_image_required_mipmaps(p_width, p_height, p_format); if (num_mipmaps != 1) { - description_mipmaps = vformat("with %d mipmaps", num_mipmaps); + description_mipmaps += vformat("with %d mipmaps", num_mipmaps); } else { - description_mipmaps = "with 1 mipmap"; + description_mipmaps += "with 1 mipmap"; } } else { - description_mipmaps = "without mipmaps"; + description_mipmaps += "without mipmaps"; } const String description = vformat("%dx%dx%d (%s)", p_width, p_height, get_format_pixel_size(p_format), description_mipmaps); ERR_FAIL_MSG(vformat("Expected Image data size of %s = %d bytes, got %d bytes instead.", description, size, p_data.size())); @@ -2618,35 +2622,35 @@ Error Image::decompress() { return OK; } -Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality, ASTCFormat p_astc_format) { +Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p_astc_format) { ERR_FAIL_INDEX_V_MSG(p_mode, COMPRESS_MAX, ERR_INVALID_PARAMETER, "Invalid compress mode."); ERR_FAIL_INDEX_V_MSG(p_source, COMPRESS_SOURCE_MAX, ERR_INVALID_PARAMETER, "Invalid compress source."); - return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality, p_astc_format); + return compress_from_channels(p_mode, detect_used_channels(p_source), p_astc_format); } -Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality, ASTCFormat p_astc_format) { +Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format) { ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA); switch (p_mode) { case COMPRESS_S3TC: { ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE); - _image_compress_bc_func(this, p_lossy_quality, p_channels); + _image_compress_bc_func(this, p_channels); } break; case COMPRESS_ETC: { ERR_FAIL_COND_V(!_image_compress_etc1_func, ERR_UNAVAILABLE); - _image_compress_etc1_func(this, p_lossy_quality); + _image_compress_etc1_func(this); } break; case COMPRESS_ETC2: { ERR_FAIL_COND_V(!_image_compress_etc2_func, ERR_UNAVAILABLE); - _image_compress_etc2_func(this, p_lossy_quality, p_channels); + _image_compress_etc2_func(this, p_channels); } break; case COMPRESS_BPTC: { ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE); - _image_compress_bptc_func(this, p_lossy_quality, p_channels); + _image_compress_bptc_func(this, p_channels); } break; case COMPRESS_ASTC: { ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE); - _image_compress_astc_func(this, p_lossy_quality, p_astc_format); + _image_compress_astc_func(this, p_astc_format); } break; case COMPRESS_MAX: { ERR_FAIL_V(ERR_INVALID_PARAMETER); @@ -3000,11 +3004,11 @@ ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr; ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr; ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr; -void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = nullptr; -void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = nullptr; -void (*Image::_image_compress_etc1_func)(Image *, float) = nullptr; -void (*Image::_image_compress_etc2_func)(Image *, float, Image::UsedChannels) = nullptr; -void (*Image::_image_compress_astc_func)(Image *, float, Image::ASTCFormat) = nullptr; +void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr; +void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr; +void (*Image::_image_compress_etc1_func)(Image *) = nullptr; +void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr; +void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr; void (*Image::_image_decompress_bc)(Image *) = nullptr; void (*Image::_image_decompress_bptc)(Image *) = nullptr; void (*Image::_image_decompress_etc1)(Image *) = nullptr; @@ -3426,8 +3430,8 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible); ClassDB::bind_method(D_METHOD("detect_used_channels", "source"), &Image::detect_used_channels, DEFVAL(COMPRESS_SOURCE_GENERIC)); - ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality", "astc_format"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(0.7), DEFVAL(ASTC_FORMAT_4x4)); - ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "lossy_quality", "astc_format"), &Image::compress_from_channels, DEFVAL(0.7), DEFVAL(ASTC_FORMAT_4x4)); + ClassDB::bind_method(D_METHOD("compress", "mode", "source", "astc_format"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(ASTC_FORMAT_4x4)); + ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "astc_format"), &Image::compress_from_channels, DEFVAL(ASTC_FORMAT_4x4)); ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress); ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed); @@ -3547,11 +3551,11 @@ void Image::_bind_methods() { BIND_ENUM_CONSTANT(ASTC_FORMAT_8x8); } -void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)) { +void Image::set_compress_bc_func(void (*p_compress_func)(Image *, UsedChannels)) { _image_compress_bc_func = p_compress_func; } -void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels)) { +void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, UsedChannels)) { _image_compress_bptc_func = p_compress_func; } diff --git a/core/io/image.h b/core/io/image.h index 29ceb9478f..8e353a8bb7 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -149,11 +149,11 @@ public: static ImageMemLoadFunc _tga_mem_loader_func; static ImageMemLoadFunc _bmp_mem_loader_func; - static void (*_image_compress_bc_func)(Image *, float, UsedChannels p_channels); - static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, UsedChannels p_channels); - static void (*_image_compress_etc1_func)(Image *, float); - static void (*_image_compress_etc2_func)(Image *, float, UsedChannels p_channels); - static void (*_image_compress_astc_func)(Image *, float, ASTCFormat p_format); + static void (*_image_compress_bc_func)(Image *, UsedChannels p_channels); + static void (*_image_compress_bptc_func)(Image *, UsedChannels p_channels); + static void (*_image_compress_etc1_func)(Image *); + static void (*_image_compress_etc2_func)(Image *, UsedChannels p_channels); + static void (*_image_compress_astc_func)(Image *, ASTCFormat p_format); static void (*_image_decompress_bc)(Image *); static void (*_image_decompress_bptc)(Image *); @@ -368,8 +368,8 @@ public: COMPRESS_SOURCE_MAX, }; - Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); - Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality = 0.7, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); + Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); + Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); Error decompress(); bool is_compressed() const; @@ -391,8 +391,8 @@ public: Rect2i get_used_rect() const; Ref<Image> get_region(const Rect2i &p_area) const; - static void set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)); - static void set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels)); + static void set_compress_bc_func(void (*p_compress_func)(Image *, UsedChannels)); + static void set_compress_bptc_func(void (*p_compress_func)(Image *, UsedChannels)); static String get_format_name(Format p_format); Error load_png_from_buffer(const Vector<uint8_t> &p_array); diff --git a/core/io/packet_peer_dtls.cpp b/core/io/packet_peer_dtls.cpp index c0998f10bc..18bef3ff3c 100644 --- a/core/io/packet_peer_dtls.cpp +++ b/core/io/packet_peer_dtls.cpp @@ -48,7 +48,7 @@ bool PacketPeerDTLS::is_available() { void PacketPeerDTLS::_bind_methods() { ClassDB::bind_method(D_METHOD("poll"), &PacketPeerDTLS::poll); - ClassDB::bind_method(D_METHOD("connect_to_peer", "packet_peer", "validate_certs", "for_hostname", "valid_certificate"), &PacketPeerDTLS::connect_to_peer, DEFVAL(true), DEFVAL(String()), DEFVAL(Ref<X509Certificate>())); + ClassDB::bind_method(D_METHOD("connect_to_peer", "packet_peer", "hostname", "client_options"), &PacketPeerDTLS::connect_to_peer, DEFVAL(Ref<TLSOptions>())); ClassDB::bind_method(D_METHOD("get_status"), &PacketPeerDTLS::get_status); ClassDB::bind_method(D_METHOD("disconnect_from_peer"), &PacketPeerDTLS::disconnect_from_peer); diff --git a/core/io/packet_peer_dtls.h b/core/io/packet_peer_dtls.h index 5ba1faed7c..3990a851f7 100644 --- a/core/io/packet_peer_dtls.h +++ b/core/io/packet_peer_dtls.h @@ -53,7 +53,7 @@ public: }; virtual void poll() = 0; - virtual Error connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_validate_certs = true, const String &p_for_hostname = String(), Ref<X509Certificate> p_ca_certs = Ref<X509Certificate>()) = 0; + virtual Error connect_to_peer(Ref<PacketPeerUDP> p_base, const String &p_hostname, Ref<TLSOptions> p_options = Ref<TLSOptions>()) = 0; virtual void disconnect_from_peer() = 0; virtual Status get_status() const = 0; diff --git a/core/io/resource.cpp b/core/io/resource.cpp index e44bbc246b..4abcbffb61 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -260,15 +260,35 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const { } Variant p = get(E.name); - if ((p.get_type() == Variant::DICTIONARY || p.get_type() == Variant::ARRAY)) { - r->set(E.name, p.duplicate(p_subresources)); - } else if (p.get_type() == Variant::OBJECT && !(E.usage & PROPERTY_USAGE_NEVER_DUPLICATE) && (p_subresources || (E.usage & PROPERTY_USAGE_ALWAYS_DUPLICATE))) { - Ref<Resource> sr = p; - if (sr.is_valid()) { - r->set(E.name, sr->duplicate(p_subresources)); + switch (p.get_type()) { + case Variant::Type::DICTIONARY: + case Variant::Type::ARRAY: + case Variant::Type::PACKED_BYTE_ARRAY: + case Variant::Type::PACKED_COLOR_ARRAY: + case Variant::Type::PACKED_INT32_ARRAY: + case Variant::Type::PACKED_INT64_ARRAY: + case Variant::Type::PACKED_FLOAT32_ARRAY: + case Variant::Type::PACKED_FLOAT64_ARRAY: + case Variant::Type::PACKED_STRING_ARRAY: + case Variant::Type::PACKED_VECTOR2_ARRAY: + case Variant::Type::PACKED_VECTOR3_ARRAY: { + r->set(E.name, p.duplicate(p_subresources)); + } break; + + case Variant::Type::OBJECT: { + if (!(E.usage & PROPERTY_USAGE_NEVER_DUPLICATE) && (p_subresources || (E.usage & PROPERTY_USAGE_ALWAYS_DUPLICATE))) { + Ref<Resource> sr = p; + if (sr.is_valid()) { + r->set(E.name, sr->duplicate(p_subresources)); + } + } else { + r->set(E.name, p); + } + } break; + + default: { + r->set(E.name, p); } - } else { - r->set(E.name, p); } } diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index c0463de427..38f41d645c 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -832,6 +832,18 @@ Error ResourceLoaderBinary::load() { } } + if (value.get_type() == Variant::ARRAY) { + Array set_array = value; + bool is_get_valid = false; + Variant get_value = res->get(name, &is_get_valid); + if (is_get_valid && get_value.get_type() == Variant::ARRAY) { + Array get_array = get_value; + if (!set_array.is_same_typed(get_array)) { + value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script()); + } + } + } + if (set_valid) { res->set(name, value); } diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 7447119ab7..fc3547261b 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -176,9 +176,9 @@ Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Hash deps_dict[E.key] = E.value; } - int64_t err = OK; + Error err = OK; GDVIRTUAL_CALL(_rename_dependencies, p_path, deps_dict, err); - return (Error)err; + return err; } void ResourceFormatLoader::_bind_methods() { diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index eb8155e046..c47b6c950a 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -58,7 +58,7 @@ protected: GDVIRTUAL1RC(ResourceUID::ID, _get_resource_uid, String) GDVIRTUAL2RC(Vector<String>, _get_dependencies, String, bool) GDVIRTUAL1RC(Vector<String>, _get_classes_used, String) - GDVIRTUAL2RC(int64_t, _rename_dependencies, String, Dictionary) + GDVIRTUAL2RC(Error, _rename_dependencies, String, Dictionary) GDVIRTUAL1RC(bool, _exists, String) GDVIRTUAL4RC(Variant, _load, String, String, bool, int) diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index b8201cc6b9..6e377847a8 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -42,9 +42,9 @@ ResourceSavedCallback ResourceSaver::save_callback = nullptr; ResourceSaverGetResourceIDForPath ResourceSaver::save_get_id_for_path = nullptr; Error ResourceFormatSaver::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { - int64_t res = ERR_METHOD_NOT_FOUND; - GDVIRTUAL_CALL(_save, p_resource, p_path, p_flags, res); - return (Error)res; + Error err = ERR_METHOD_NOT_FOUND; + GDVIRTUAL_CALL(_save, p_resource, p_path, p_flags, err); + return err; } Error ResourceFormatSaver::set_uid(const String &p_path, ResourceUID::ID p_uid) { diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h index 9e88b2086b..572742d129 100644 --- a/core/io/resource_saver.h +++ b/core/io/resource_saver.h @@ -41,7 +41,7 @@ class ResourceFormatSaver : public RefCounted { protected: static void _bind_methods(); - GDVIRTUAL3R(int64_t, _save, Ref<Resource>, String, uint32_t) + GDVIRTUAL3R(Error, _save, Ref<Resource>, String, uint32_t) GDVIRTUAL2R(Error, _set_uid, String, ResourceUID::ID) GDVIRTUAL1RC(bool, _recognize, Ref<Resource>) GDVIRTUAL1RC(Vector<String>, _get_recognized_extensions, Ref<Resource>) diff --git a/core/io/stream_peer_tls.cpp b/core/io/stream_peer_tls.cpp index 71fadd1d30..69877974e6 100644 --- a/core/io/stream_peer_tls.cpp +++ b/core/io/stream_peer_tls.cpp @@ -41,31 +41,17 @@ StreamPeerTLS *StreamPeerTLS::create() { return nullptr; } -bool StreamPeerTLS::available = false; - bool StreamPeerTLS::is_available() { - return available; -} - -void StreamPeerTLS::set_blocking_handshake_enabled(bool p_enabled) { - blocking_handshake = p_enabled; -} - -bool StreamPeerTLS::is_blocking_handshake_enabled() const { - return blocking_handshake; + return _create != nullptr; } void StreamPeerTLS::_bind_methods() { ClassDB::bind_method(D_METHOD("poll"), &StreamPeerTLS::poll); - ClassDB::bind_method(D_METHOD("accept_stream", "stream", "private_key", "certificate", "chain"), &StreamPeerTLS::accept_stream, DEFVAL(Ref<X509Certificate>())); - ClassDB::bind_method(D_METHOD("connect_to_stream", "stream", "validate_certs", "for_hostname", "valid_certificate"), &StreamPeerTLS::connect_to_stream, DEFVAL(false), DEFVAL(String()), DEFVAL(Ref<X509Certificate>())); + ClassDB::bind_method(D_METHOD("accept_stream", "stream", "server_options"), &StreamPeerTLS::accept_stream); + ClassDB::bind_method(D_METHOD("connect_to_stream", "stream", "common_name", "client_options"), &StreamPeerTLS::connect_to_stream, DEFVAL(Ref<TLSOptions>())); ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTLS::get_status); ClassDB::bind_method(D_METHOD("get_stream"), &StreamPeerTLS::get_stream); ClassDB::bind_method(D_METHOD("disconnect_from_stream"), &StreamPeerTLS::disconnect_from_stream); - ClassDB::bind_method(D_METHOD("set_blocking_handshake_enabled", "enabled"), &StreamPeerTLS::set_blocking_handshake_enabled); - ClassDB::bind_method(D_METHOD("is_blocking_handshake_enabled"), &StreamPeerTLS::is_blocking_handshake_enabled); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "blocking_handshake"), "set_blocking_handshake_enabled", "is_blocking_handshake_enabled"); BIND_ENUM_CONSTANT(STATUS_DISCONNECTED); BIND_ENUM_CONSTANT(STATUS_HANDSHAKING); diff --git a/core/io/stream_peer_tls.h b/core/io/stream_peer_tls.h index 6666107ad8..5894abb7a4 100644 --- a/core/io/stream_peer_tls.h +++ b/core/io/stream_peer_tls.h @@ -41,10 +41,6 @@ protected: static StreamPeerTLS *(*_create)(); static void _bind_methods(); - static bool available; - - bool blocking_handshake = true; - public: enum Status { STATUS_DISCONNECTED, @@ -54,12 +50,9 @@ public: STATUS_ERROR_HOSTNAME_MISMATCH }; - void set_blocking_handshake_enabled(bool p_enabled); - bool is_blocking_handshake_enabled() const; - virtual void poll() = 0; - virtual Error accept_stream(Ref<StreamPeer> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain = Ref<X509Certificate>()) = 0; - virtual Error connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs = false, const String &p_for_hostname = String(), Ref<X509Certificate> p_valid_cert = Ref<X509Certificate>()) = 0; + virtual Error accept_stream(Ref<StreamPeer> p_base, Ref<TLSOptions> p_options) = 0; + virtual Error connect_to_stream(Ref<StreamPeer> p_base, const String &p_common_name, Ref<TLSOptions> p_options) = 0; virtual Status get_status() const = 0; virtual Ref<StreamPeer> get_stream() const = 0; diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 234a4ddb79..95a4187062 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -239,13 +239,18 @@ void Basis::scale_orthogonal(const Vector3 &p_scale) { Basis Basis::scaled_orthogonal(const Vector3 &p_scale) const { Basis m = *this; Vector3 s = Vector3(-1, -1, -1) + p_scale; + bool sign = signbit(s.x + s.y + s.z); + Basis b = m.orthonormalized(); + s = b.xform_inv(s); Vector3 dots; - Basis b; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { dots[j] += s[i] * abs(m.get_column(i).normalized().dot(b.get_column(j))); } } + if (sign != signbit(dots.x + dots.y + dots.z)) { + dots = -dots; + } m.scale_local(Vector3(1, 1, 1) + dots); return m; } diff --git a/core/math/dynamic_bvh.cpp b/core/math/dynamic_bvh.cpp index 4452445241..e1315d1c64 100644 --- a/core/math/dynamic_bvh.cpp +++ b/core/math/dynamic_bvh.cpp @@ -36,8 +36,8 @@ void DynamicBVH::_delete_node(Node *p_node) { void DynamicBVH::_recurse_delete_node(Node *p_node) { if (!p_node->is_leaf()) { - _recurse_delete_node(p_node->childs[0]); - _recurse_delete_node(p_node->childs[1]); + _recurse_delete_node(p_node->children[0]); + _recurse_delete_node(p_node->children[1]); } if (p_node == bvh_root) { bvh_root = nullptr; @@ -65,31 +65,31 @@ void DynamicBVH::_insert_leaf(Node *p_root, Node *p_leaf) { } else { if (!p_root->is_leaf()) { do { - p_root = p_root->childs[p_leaf->volume.select_by_proximity( - p_root->childs[0]->volume, - p_root->childs[1]->volume)]; + p_root = p_root->children[p_leaf->volume.select_by_proximity( + p_root->children[0]->volume, + p_root->children[1]->volume)]; } while (!p_root->is_leaf()); } Node *prev = p_root->parent; Node *node = _create_node_with_volume(prev, p_leaf->volume.merge(p_root->volume), nullptr); if (prev) { - prev->childs[p_root->get_index_in_parent()] = node; - node->childs[0] = p_root; + prev->children[p_root->get_index_in_parent()] = node; + node->children[0] = p_root; p_root->parent = node; - node->childs[1] = p_leaf; + node->children[1] = p_leaf; p_leaf->parent = node; do { if (!prev->volume.contains(node->volume)) { - prev->volume = prev->childs[0]->volume.merge(prev->childs[1]->volume); + prev->volume = prev->children[0]->volume.merge(prev->children[1]->volume); } else { break; } node = prev; } while (nullptr != (prev = node->parent)); } else { - node->childs[0] = p_root; + node->children[0] = p_root; p_root->parent = node; - node->childs[1] = p_leaf; + node->children[1] = p_leaf; p_leaf->parent = node; bvh_root = node; } @@ -103,14 +103,14 @@ DynamicBVH::Node *DynamicBVH::_remove_leaf(Node *leaf) { } else { Node *parent = leaf->parent; Node *prev = parent->parent; - Node *sibling = parent->childs[1 - leaf->get_index_in_parent()]; + Node *sibling = parent->children[1 - leaf->get_index_in_parent()]; if (prev) { - prev->childs[parent->get_index_in_parent()] = sibling; + prev->children[parent->get_index_in_parent()] = sibling; sibling->parent = prev; _delete_node(parent); while (prev) { const Volume pb = prev->volume; - prev->volume = prev->childs[0]->volume.merge(prev->childs[1]->volume); + prev->volume = prev->children[0]->volume.merge(prev->children[1]->volume); if (pb.is_not_equal_to(prev->volume)) { prev = prev->parent; } else { @@ -129,8 +129,8 @@ DynamicBVH::Node *DynamicBVH::_remove_leaf(Node *leaf) { void DynamicBVH::_fetch_leaves(Node *p_root, LocalVector<Node *> &r_leaves, int p_depth) { if (p_root->is_internal() && p_depth) { - _fetch_leaves(p_root->childs[0], r_leaves, p_depth - 1); - _fetch_leaves(p_root->childs[1], r_leaves, p_depth - 1); + _fetch_leaves(p_root->children[0], r_leaves, p_depth - 1); + _fetch_leaves(p_root->children[1], r_leaves, p_depth - 1); _delete_node(p_root); } else { r_leaves.push_back(p_root); @@ -195,8 +195,8 @@ void DynamicBVH::_bottom_up(Node **leaves, int p_count) { } Node *n[] = { leaves[minidx[0]], leaves[minidx[1]] }; Node *p = _create_node_with_volume(nullptr, n[0]->volume.merge(n[1]->volume), nullptr); - p->childs[0] = n[0]; - p->childs[1] = n[1]; + p->children[0] = n[0]; + p->children[1] = n[1]; n[0]->parent = p; n[1]->parent = p; leaves[minidx[0]] = p; @@ -241,10 +241,10 @@ DynamicBVH::Node *DynamicBVH::_top_down(Node **leaves, int p_count, int p_bu_thr } Node *node = _create_node_with_volume(nullptr, vol, nullptr); - node->childs[0] = _top_down(&leaves[0], partition, p_bu_threshold); - node->childs[1] = _top_down(&leaves[partition], p_count - partition, p_bu_threshold); - node->childs[0]->parent = node; - node->childs[1]->parent = node; + node->children[0] = _top_down(&leaves[0], partition, p_bu_threshold); + node->children[1] = _top_down(&leaves[partition], p_count - partition, p_bu_threshold); + node->children[0]->parent = node; + node->children[1]->parent = node; return (node); } else { _bottom_up(leaves, p_count); @@ -260,23 +260,23 @@ DynamicBVH::Node *DynamicBVH::_node_sort(Node *n, Node *&r) { if (p > n) { const int i = n->get_index_in_parent(); const int j = 1 - i; - Node *s = p->childs[j]; + Node *s = p->children[j]; Node *q = p->parent; - ERR_FAIL_COND_V(n != p->childs[i], nullptr); + ERR_FAIL_COND_V(n != p->children[i], nullptr); if (q) { - q->childs[p->get_index_in_parent()] = n; + q->children[p->get_index_in_parent()] = n; } else { r = n; } s->parent = n; p->parent = n; n->parent = q; - p->childs[0] = n->childs[0]; - p->childs[1] = n->childs[1]; - n->childs[0]->parent = p; - n->childs[1]->parent = p; - n->childs[i] = p; - n->childs[j] = s; + p->children[0] = n->children[0]; + p->children[1] = n->children[1]; + n->children[0]->parent = p; + n->children[1]->parent = p; + n->children[i] = p; + n->children[j] = s; SWAP(p->volume, n->volume); return (p); } @@ -320,7 +320,7 @@ void DynamicBVH::optimize_incremental(int passes) { Node *node = bvh_root; unsigned bit = 0; while (node->is_internal()) { - node = _node_sort(node, bvh_root)->childs[(opath >> bit) & 1]; + node = _node_sort(node, bvh_root)->children[(opath >> bit) & 1]; bit = (bit + 1) & (sizeof(unsigned) * 8 - 1); } _update(node); @@ -396,8 +396,8 @@ void DynamicBVH::remove(const ID &p_id) { void DynamicBVH::_extract_leaves(Node *p_node, List<ID> *r_elements) { if (p_node->is_internal()) { - _extract_leaves(p_node->childs[0], r_elements); - _extract_leaves(p_node->childs[1], r_elements); + _extract_leaves(p_node->children[0], r_elements); + _extract_leaves(p_node->children[1], r_elements); } else { ID id; id.node = p_node; diff --git a/core/math/dynamic_bvh.h b/core/math/dynamic_bvh.h index 46bf56ae58..21b5340aaa 100644 --- a/core/math/dynamic_bvh.h +++ b/core/math/dynamic_bvh.h @@ -182,21 +182,21 @@ private: Volume volume; Node *parent = nullptr; union { - Node *childs[2]; + Node *children[2]; void *data; }; - _FORCE_INLINE_ bool is_leaf() const { return childs[1] == nullptr; } + _FORCE_INLINE_ bool is_leaf() const { return children[1] == nullptr; } _FORCE_INLINE_ bool is_internal() const { return (!is_leaf()); } _FORCE_INLINE_ int get_index_in_parent() const { ERR_FAIL_COND_V(!parent, 0); - return (parent->childs[1] == this) ? 1 : 0; + return (parent->children[1] == this) ? 1 : 0; } void get_max_depth(int depth, int &maxdepth) { if (is_internal()) { - childs[0]->get_max_depth(depth + 1, maxdepth); - childs[1]->get_max_depth(depth + 1, maxdepth); + children[0]->get_max_depth(depth + 1, maxdepth); + children[1]->get_max_depth(depth + 1, maxdepth); } else { maxdepth = MAX(maxdepth, depth); } @@ -205,7 +205,7 @@ private: // int count_leaves() const { if (is_internal()) { - return childs[0]->count_leaves() + childs[1]->count_leaves(); + return children[0]->count_leaves() + children[1]->count_leaves(); } else { return (1); } @@ -216,8 +216,8 @@ private: } Node() { - childs[0] = nullptr; - childs[1] = nullptr; + children[0] = nullptr; + children[1] = nullptr; } }; @@ -350,8 +350,8 @@ void DynamicBVH::aabb_query(const AABB &p_box, QueryResult &r_result) { stack = aux_stack.ptr(); threshold = aux_stack.size() - 2; } - stack[depth++] = n->childs[0]; - stack[depth++] = n->childs[1]; + stack[depth++] = n->children[0]; + stack[depth++] = n->children[1]; } else { if (r_result(n->data)) { return; @@ -406,8 +406,8 @@ void DynamicBVH::convex_query(const Plane *p_planes, int p_plane_count, const Ve stack = aux_stack.ptr(); threshold = aux_stack.size() - 2; } - stack[depth++] = n->childs[0]; - stack[depth++] = n->childs[1]; + stack[depth++] = n->children[0]; + stack[depth++] = n->children[1]; } else { if (r_result(n->data)) { return; @@ -463,8 +463,8 @@ void DynamicBVH::ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResu stack = aux_stack.ptr(); threshold = aux_stack.size() - 2; } - stack[depth++] = node->childs[0]; - stack[depth++] = node->childs[1]; + stack[depth++] = node->children[0]; + stack[depth++] = node->children[1]; } else { if (r_result(node->data)) { return; diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 0fa82bb8c1..078320d620 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -31,6 +31,7 @@ #ifndef MATH_FUNCS_H #define MATH_FUNCS_H +#include "core/error/error_macros.h" #include "core/math/math_defs.h" #include "core/math/random_pcg.h" #include "core/typedefs.h" @@ -225,6 +226,7 @@ public: } static _ALWAYS_INLINE_ int64_t posmod(int64_t p_x, int64_t p_y) { + ERR_FAIL_COND_V_MSG(p_y == 0, 0, "Division by zero in posmod is undefined. Returning 0 as fallback."); int64_t value = p_x % p_y; if (((value < 0) && (p_y > 0)) || ((value > 0) && (p_y < 0))) { value += p_y; diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index 9488c6bcff..4483f61bc4 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -383,15 +383,15 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ if (O->get().plane.is_equal_approx(f.plane)) { //merge and delete edge and contiguous face, while repointing edges (uuugh!) - int ois = O->get().indices.size(); + int o_index_size = O->get().indices.size(); - for (int j = 0; j < ois; j++) { + for (int j = 0; j < o_index_size; j++) { //search a if (O->get().indices[j] == a) { //append the rest - for (int k = 0; k < ois; k++) { - int idx = O->get().indices[(k + j) % ois]; - int idxn = O->get().indices[(k + j + 1) % ois]; + for (int k = 0; k < o_index_size; k++) { + int idx = O->get().indices[(k + j) % o_index_size]; + int idxn = O->get().indices[(k + j + 1) % o_index_size]; if (idx == b && idxn == a) { //already have b! break; } diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp index 910995d717..868665cb5c 100644 --- a/core/math/transform_2d.cpp +++ b/core/math/transform_2d.cpp @@ -151,7 +151,7 @@ void Transform2D::orthonormalize() { Vector2 y = columns[1]; x.normalize(); - y = (y - x * (x.dot(y))); + y = y - x * x.dot(y); y.normalize(); columns[0] = x; @@ -159,9 +159,9 @@ void Transform2D::orthonormalize() { } Transform2D Transform2D::orthonormalized() const { - Transform2D on = *this; - on.orthonormalize(); - return on; + Transform2D ortho = *this; + ortho.orthonormalize(); + return ortho; } bool Transform2D::is_equal_approx(const Transform2D &p_transform) const { @@ -263,39 +263,12 @@ real_t Transform2D::basis_determinant() const { return columns[0].x * columns[1].y - columns[0].y * columns[1].x; } -Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, const real_t p_c) const { - //extract parameters - Vector2 p1 = get_origin(); - Vector2 p2 = p_transform.get_origin(); - - real_t r1 = get_rotation(); - real_t r2 = p_transform.get_rotation(); - - Size2 s1 = get_scale(); - Size2 s2 = p_transform.get_scale(); - - //slerp rotation - Vector2 v1(Math::cos(r1), Math::sin(r1)); - Vector2 v2(Math::cos(r2), Math::sin(r2)); - - real_t dot = v1.dot(v2); - - dot = CLAMP(dot, (real_t)-1.0, (real_t)1.0); - - Vector2 v; - - if (dot > 0.9995f) { - v = v1.lerp(v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues - } else { - real_t angle = p_c * Math::acos(dot); - Vector2 v3 = (v2 - v1 * dot).normalized(); - v = v1 * Math::cos(angle) + v3 * Math::sin(angle); - } - - //construct matrix - Transform2D res(v.angle(), p1.lerp(p2, p_c)); - res.scale_basis(s1.lerp(s2, p_c)); - return res; +Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, const real_t p_weight) const { + return Transform2D( + Math::lerp_angle(get_rotation(), p_transform.get_rotation(), p_weight), + get_scale().lerp(p_transform.get_scale(), p_weight), + Math::lerp_angle(get_skew(), p_transform.get_skew(), p_weight), + get_origin().lerp(p_transform.get_origin(), p_weight)); } void Transform2D::operator*=(const real_t p_val) { diff --git a/core/math/vector3.h b/core/math/vector3.h index bd8739d024..18943a820f 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -76,6 +76,14 @@ struct _NO_DISCARD_ Vector3 { return x < y ? (y < z ? Vector3::AXIS_Z : Vector3::AXIS_Y) : (x < z ? Vector3::AXIS_Z : Vector3::AXIS_X); } + Vector3 min(const Vector3 &p_vector3) const { + return Vector3(MIN(x, p_vector3.x), MIN(y, p_vector3.y), MIN(z, p_vector3.z)); + } + + Vector3 max(const Vector3 &p_vector3) const { + return Vector3(MAX(x, p_vector3.x), MAX(y, p_vector3.y), MAX(z, p_vector3.z)); + } + _FORCE_INLINE_ real_t length() const; _FORCE_INLINE_ real_t length_squared() const; diff --git a/core/math/vector3i.h b/core/math/vector3i.h index 96f9beef12..53d3829a99 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -69,6 +69,14 @@ struct _NO_DISCARD_ Vector3i { Vector3i::Axis min_axis_index() const; Vector3i::Axis max_axis_index() const; + Vector3i min(const Vector3i &p_vector3i) const { + return Vector3i(MIN(x, p_vector3i.x), MIN(y, p_vector3i.y), MIN(z, p_vector3i.z)); + } + + Vector3i max(const Vector3i &p_vector3i) const { + return Vector3i(MAX(x, p_vector3i.x), MAX(y, p_vector3i.y), MAX(z, p_vector3i.z)); + } + _FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ double length() const; diff --git a/core/math/vector4.h b/core/math/vector4.h index 0509261f33..f16b040317 100644 --- a/core/math/vector4.h +++ b/core/math/vector4.h @@ -68,6 +68,14 @@ struct _NO_DISCARD_ Vector4 { Vector4::Axis min_axis_index() const; Vector4::Axis max_axis_index() const; + Vector4 min(const Vector4 &p_vector4) const { + return Vector4(MIN(x, p_vector4.x), MIN(y, p_vector4.y), MIN(z, p_vector4.z), MIN(w, p_vector4.w)); + } + + Vector4 max(const Vector4 &p_vector4) const { + return Vector4(MAX(x, p_vector4.x), MAX(y, p_vector4.y), MAX(z, p_vector4.z), MAX(w, p_vector4.w)); + } + _FORCE_INLINE_ real_t length_squared() const; bool is_equal_approx(const Vector4 &p_vec4) const; bool is_zero_approx() const; diff --git a/core/math/vector4i.h b/core/math/vector4i.h index d38a9de6f1..b815aa8e76 100644 --- a/core/math/vector4i.h +++ b/core/math/vector4i.h @@ -71,6 +71,14 @@ struct _NO_DISCARD_ Vector4i { Vector4i::Axis min_axis_index() const; Vector4i::Axis max_axis_index() const; + Vector4i min(const Vector4i &p_vector4i) const { + return Vector4i(MIN(x, p_vector4i.x), MIN(y, p_vector4i.y), MIN(z, p_vector4i.z), MIN(w, p_vector4i.w)); + } + + Vector4i max(const Vector4i &p_vector4i) const { + return Vector4i(MAX(x, p_vector4i.x), MAX(y, p_vector4i.y), MAX(z, p_vector4i.z), MAX(w, p_vector4i.w)); + } + _FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ double length() const; diff --git a/core/object/class_db.h b/core/object/class_db.h index 0e408e8845..0b62cf40f7 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -40,6 +40,8 @@ #include "core/object/callable_method_pointer.h" #include "core/templates/hash_set.h" +#include <type_traits> + #define DEFVAL(m_defval) (m_defval) #ifdef DEBUG_METHODS_ENABLED @@ -241,6 +243,24 @@ public: static uint64_t get_api_hash(APIType p_api); + template <typename> + struct member_function_traits; + + template <typename R, typename T, typename... Args> + struct member_function_traits<R (T::*)(Args...)> { + using return_type = R; + }; + + template <typename R, typename T, typename... Args> + struct member_function_traits<R (T::*)(Args...) const> { + using return_type = R; + }; + + template <typename R, typename... Args> + struct member_function_traits<R (*)(Args...)> { + using return_type = R; + }; + template <class N, class M, typename... VarArgs> static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args) { Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. @@ -249,6 +269,9 @@ 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) { + bind->set_return_type_is_raw_object_ptr(true); + } return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); } @@ -261,6 +284,9 @@ 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) { + bind->set_return_type_is_raw_object_ptr(true); + } return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); } @@ -273,6 +299,9 @@ public: bind->set_name(p_name); bind->set_default_arguments(p_default_args); + if constexpr (std::is_same<typename member_function_traits<M>::return_type, Object *>::value) { + bind->set_return_type_is_raw_object_ptr(true); + } String instance_type = bind->get_instance_class(); diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp index ebed6c21e9..decf030e27 100644 --- a/core/object/message_queue.cpp +++ b/core/object/message_queue.cpp @@ -55,9 +55,9 @@ Error MessageQueue::push_set(ObjectID p_id, const StringName &p_prop, const Vari if (ObjectDB::get_instance(p_id)) { type = ObjectDB::get_instance(p_id)->get_class(); } - print_line("Failed set: " + type + ":" + p_prop + " target ID: " + itos(p_id)); + ERR_PRINT("Failed set: " + type + ":" + p_prop + " target ID: " + itos(p_id) + ". Message queue out of memory. Try increasing 'memory/limits/message_queue/max_size_kb' in project settings."); statistics(); - ERR_FAIL_V_MSG(ERR_OUT_OF_MEMORY, "Message queue out of memory. Try increasing 'memory/limits/message_queue/max_size_kb' in project settings."); + return ERR_OUT_OF_MEMORY; } Message *msg = memnew_placement(&buffer[buffer_end], Message); @@ -82,9 +82,9 @@ Error MessageQueue::push_notification(ObjectID p_id, int p_notification) { uint8_t room_needed = sizeof(Message); if ((buffer_end + room_needed) >= buffer_size) { - print_line("Failed notification: " + itos(p_notification) + " target ID: " + itos(p_id)); + ERR_PRINT("Failed notification: " + itos(p_notification) + " target ID: " + itos(p_id) + ". Message queue out of memory. Try increasing 'memory/limits/message_queue/max_size_kb' in project settings."); statistics(); - ERR_FAIL_V_MSG(ERR_OUT_OF_MEMORY, "Message queue out of memory. Try increasing 'memory/limits/message_queue/max_size_kb' in project settings."); + return ERR_OUT_OF_MEMORY; } Message *msg = memnew_placement(&buffer[buffer_end], Message); @@ -117,9 +117,9 @@ Error MessageQueue::push_callablep(const Callable &p_callable, const Variant **p int room_needed = sizeof(Message) + sizeof(Variant) * p_argcount; if ((buffer_end + room_needed) >= buffer_size) { - print_line("Failed method: " + p_callable); + ERR_PRINT("Failed method: " + p_callable + ". Message queue out of memory. Try increasing 'memory/limits/message_queue/max_size_kb' in project settings."); statistics(); - ERR_FAIL_V_MSG(ERR_OUT_OF_MEMORY, "Message queue out of memory. Try increasing 'memory/limits/message_queue/max_size_kb' in project settings."); + return ERR_OUT_OF_MEMORY; } Message *msg = memnew_placement(&buffer[buffer_end], Message); diff --git a/core/object/method_bind.h b/core/object/method_bind.h index 8334a7eef6..d37479f45b 100644 --- a/core/object/method_bind.h +++ b/core/object/method_bind.h @@ -49,6 +49,7 @@ class MethodBind { bool _static = false; bool _const = false; bool _returns = false; + bool _returns_raw_obj_ptr = false; protected: Variant::Type *argument_types = nullptr; @@ -121,6 +122,9 @@ public: _FORCE_INLINE_ bool has_return() const { return _returns; } virtual bool is_vararg() const { return false; } + _FORCE_INLINE_ bool is_return_type_raw_object_ptr() { return _returns_raw_obj_ptr; } + _FORCE_INLINE_ void set_return_type_is_raw_object_ptr(bool p_returns_raw_obj) { _returns_raw_obj_ptr = p_returns_raw_obj; } + void set_default_arguments(const Vector<Variant> &p_defargs); uint32_t get_hash() const; diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index df5486512d..71f40660f4 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -165,22 +165,30 @@ ScriptLanguage *ScriptServer::get_language(int p_idx) { return _languages[p_idx]; } -void ScriptServer::register_language(ScriptLanguage *p_language) { - ERR_FAIL_NULL(p_language); - ERR_FAIL_COND(_language_count >= MAX_LANGUAGES); +Error ScriptServer::register_language(ScriptLanguage *p_language) { + ERR_FAIL_NULL_V(p_language, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V_MSG(_language_count >= MAX_LANGUAGES, ERR_UNAVAILABLE, "Script languages limit has been reach, cannot register more."); + for (int i = 0; i < _language_count; i++) { + const ScriptLanguage *other_language = _languages[i]; + ERR_FAIL_COND_V_MSG(other_language->get_extension() == p_language->get_extension(), ERR_ALREADY_EXISTS, "A script language with extension '" + p_language->get_extension() + "' is already registered."); + ERR_FAIL_COND_V_MSG(other_language->get_name() == p_language->get_name(), ERR_ALREADY_EXISTS, "A script language with name '" + p_language->get_name() + "' is already registered."); + ERR_FAIL_COND_V_MSG(other_language->get_type() == p_language->get_type(), ERR_ALREADY_EXISTS, "A script language with type '" + p_language->get_type() + "' is already registered."); + } _languages[_language_count++] = p_language; + return OK; } -void ScriptServer::unregister_language(const ScriptLanguage *p_language) { +Error ScriptServer::unregister_language(const ScriptLanguage *p_language) { for (int i = 0; i < _language_count; i++) { if (_languages[i] == p_language) { _language_count--; if (i < _language_count) { SWAP(_languages[i], _languages[_language_count]); } - return; + return OK; } } + return ERR_DOES_NOT_EXIST; } void ScriptServer::init_languages() { @@ -369,6 +377,10 @@ void ScriptServer::save_global_classes() { ProjectSettings::get_singleton()->store_global_class_list(gcarr); } +String ScriptServer::get_global_class_cache_file_path() { + return ProjectSettings::get_singleton()->get_global_class_list_path(); +} + //////////////////// Variant ScriptInstance::call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { diff --git a/core/object/script_language.h b/core/object/script_language.h index f82b58439f..3ef121a8e7 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -70,8 +70,8 @@ public: static bool is_scripting_enabled(); _FORCE_INLINE_ static int get_language_count() { return _language_count; } static ScriptLanguage *get_language(int p_idx); - static void register_language(ScriptLanguage *p_language); - static void unregister_language(const ScriptLanguage *p_language); + static Error register_language(ScriptLanguage *p_language); + static Error unregister_language(const ScriptLanguage *p_language); static void set_reload_scripts_on_save(bool p_enable); static bool is_reload_scripts_on_save_enabled(); @@ -91,6 +91,7 @@ public: static void get_global_class_list(List<StringName> *r_global_classes); static void get_inheriters_list(const StringName &p_base_type, List<StringName> *r_classes); static void save_global_classes(); + static String get_global_class_cache_file_path(); static void init_languages(); static void finish_languages(); diff --git a/core/object/worker_thread_pool.h b/core/object/worker_thread_pool.h index cf3f7f0885..c62e05fc28 100644 --- a/core/object/worker_thread_pool.h +++ b/core/object/worker_thread_pool.h @@ -173,8 +173,8 @@ public: template <class C, class M, class U> GroupID add_template_group_task(C *p_instance, M p_method, U p_userdata, int p_elements, int p_tasks = -1, bool p_high_priority = false, const String &p_description = String()) { - typedef GroupUserData<C, M, U> GUD; - GUD *ud = memnew(GUD); + typedef GroupUserData<C, M, U> GroupUD; + GroupUD *ud = memnew(GroupUD); ud->instance = p_instance; ud->method = p_method; ud->userdata = p_userdata; diff --git a/core/os/os.cpp b/core/os/os.cpp index 86469852e3..ef7d860d19 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -553,6 +553,16 @@ void OS::add_frame_delay(bool p_can_draw) { } } +OS::PreferredTextureFormat OS::get_preferred_texture_format() const { +#if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) + return PREFERRED_TEXTURE_FORMAT_ETC2_ASTC; // By rule, ARM hardware uses ETC texture compression. +#elif defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86) + return PREFERRED_TEXTURE_FORMAT_S3TC_BPTC; // By rule, X86 hardware prefers S3TC and derivatives. +#else + return PREFERRED_TEXTURE_FORMAT_S3TC_BPTC; // Override in platform if needed. +#endif +} + OS::OS() { singleton = this; diff --git a/core/os/os.h b/core/os/os.h index 436a83eae3..d77890d89d 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -290,6 +290,14 @@ public: virtual Vector<String> get_granted_permissions() const { return Vector<String>(); } virtual void process_and_drop_events() {} + + enum PreferredTextureFormat { + PREFERRED_TEXTURE_FORMAT_S3TC_BPTC, + PREFERRED_TEXTURE_FORMAT_ETC2_ASTC + }; + + virtual PreferredTextureFormat get_preferred_texture_format() const; + OS(); virtual ~OS(); }; diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 700174bdae..a374e7c009 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -209,6 +209,7 @@ void register_core_types() { GDREGISTER_CLASS(AESContext); ClassDB::register_custom_instance_class<X509Certificate>(); ClassDB::register_custom_instance_class<CryptoKey>(); + GDREGISTER_ABSTRACT_CLASS(TLSOptions); ClassDB::register_custom_instance_class<HMACContext>(); ClassDB::register_custom_instance_class<Crypto>(); ClassDB::register_custom_instance_class<StreamPeerTLS>(); diff --git a/core/string/node_path.cpp b/core/string/node_path.cpp index 9ce1c2d4bb..af7c18741d 100644 --- a/core/string/node_path.cpp +++ b/core/string/node_path.cpp @@ -339,7 +339,6 @@ NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute) { data->refcount.init(); data->absolute = p_absolute; data->path = p_path; - data->has_slashes = true; data->hash_cache_valid = false; } @@ -353,7 +352,6 @@ NodePath::NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p data->absolute = p_absolute; data->path = p_path; data->subpath = p_subpath; - data->has_slashes = true; data->hash_cache_valid = false; } @@ -373,7 +371,6 @@ NodePath::NodePath(const String &p_path) { bool absolute = (path[0] == '/'); bool last_is_slash = true; - bool has_slashes = false; int slices = 0; int subpath_pos = path.find(":"); @@ -402,7 +399,6 @@ NodePath::NodePath(const String &p_path) { for (int i = (int)absolute; i < path.length(); i++) { if (path[i] == '/') { last_is_slash = true; - has_slashes = true; } else { if (last_is_slash) { slices++; @@ -419,7 +415,6 @@ NodePath::NodePath(const String &p_path) { data = memnew(Data); data->refcount.init(); data->absolute = absolute; - data->has_slashes = has_slashes; data->subpath = subpath; data->hash_cache_valid = false; diff --git a/core/string/node_path.h b/core/string/node_path.h index 7053798cb2..876d69924e 100644 --- a/core/string/node_path.h +++ b/core/string/node_path.h @@ -42,7 +42,6 @@ class NodePath { StringName concatenated_path; StringName concatenated_subpath; bool absolute; - bool has_slashes; mutable bool hash_cache_valid; mutable uint32_t hash_cache; }; diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp index 95812fc311..df9b6b3f1a 100644 --- a/core/string/string_name.cpp +++ b/core/string/string_name.cpp @@ -226,19 +226,16 @@ StringName::StringName(const char *p_name, bool p_static) { _data = _data->next; } - if (_data) { - if (_data->refcount.ref()) { - // exists - if (p_static) { - _data->static_count.increment(); - } + if (_data && _data->refcount.ref()) { + // exists + if (p_static) { + _data->static_count.increment(); + } #ifdef DEBUG_ENABLED - if (unlikely(debug_stringname)) { - _data->debug_references++; - } -#endif + if (unlikely(debug_stringname)) { + _data->debug_references++; } - +#endif return; } @@ -288,19 +285,17 @@ StringName::StringName(const StaticCString &p_static_string, bool p_static) { _data = _data->next; } - if (_data) { - if (_data->refcount.ref()) { - // exists - if (p_static) { - _data->static_count.increment(); - } + if (_data && _data->refcount.ref()) { + // exists + if (p_static) { + _data->static_count.increment(); + } #ifdef DEBUG_ENABLED - if (unlikely(debug_stringname)) { - _data->debug_references++; - } -#endif - return; + if (unlikely(debug_stringname)) { + _data->debug_references++; } +#endif + return; } _data = memnew(_Data); @@ -348,19 +343,17 @@ StringName::StringName(const String &p_name, bool p_static) { _data = _data->next; } - if (_data) { - if (_data->refcount.ref()) { - // exists - if (p_static) { - _data->static_count.increment(); - } + if (_data && _data->refcount.ref()) { + // exists + if (p_static) { + _data->static_count.increment(); + } #ifdef DEBUG_ENABLED - if (unlikely(debug_stringname)) { - _data->debug_references++; - } -#endif - return; + if (unlikely(debug_stringname)) { + _data->debug_references++; } +#endif + return; } _data = memnew(_Data); diff --git a/core/string/translation.cpp b/core/string/translation.cpp index 60dca8ebc6..b9d5d3b538 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -768,6 +768,20 @@ StringName TranslationServer::doc_translate_plural(const StringName &p_message, return p_message_plural; } +void TranslationServer::set_property_translation(const Ref<Translation> &p_translation) { + property_translation = p_translation; +} + +StringName TranslationServer::property_translate(const StringName &p_message) const { + if (property_translation.is_valid()) { + StringName r = property_translation->get_message(p_message); + if (r) { + return r; + } + } + return p_message; +} + bool TranslationServer::is_pseudolocalization_enabled() const { return pseudolocalization_enabled; } diff --git a/core/string/translation.h b/core/string/translation.h index 8646635eb8..01d239f81c 100644 --- a/core/string/translation.h +++ b/core/string/translation.h @@ -78,6 +78,7 @@ class TranslationServer : public Object { HashSet<Ref<Translation>> translations; Ref<Translation> tool_translation; Ref<Translation> doc_translation; + Ref<Translation> property_translation; bool enabled = true; @@ -174,6 +175,8 @@ public: void set_doc_translation(const Ref<Translation> &p_translation); StringName doc_translate(const StringName &p_message, const StringName &p_context = "") const; StringName doc_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const; + void set_property_translation(const Ref<Translation> &p_translation); + StringName property_translate(const StringName &p_message) const; void setup(); diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp index 2d3a9c7575..6b1595174a 100644 --- a/core/string/translation_po.cpp +++ b/core/string/translation_po.cpp @@ -254,11 +254,6 @@ StringName TranslationPO::get_plural_message(const StringName &p_src_text, const } ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].is_empty(), StringName(), "Source text \"" + String(p_src_text) + "\" is registered but doesn't have a translation. Please report this bug."); - if (translation_map[p_context][p_src_text].size() == 1) { - WARN_PRINT("Source string \"" + String(p_src_text) + "\" doesn't have plural translations. Use singular translation API for such as tr(), TTR() to translate \"" + String(p_src_text) + "\""); - return translation_map[p_context][p_src_text][0]; - } - int plural_index = _get_plural_index(p_n); ERR_FAIL_COND_V_MSG(plural_index < 0 || translation_map[p_context][p_src_text].size() < plural_index + 1, StringName(), "Plural index returned or number of plural translations is not valid. Please report this bug."); diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index b34d9f3271..1b3b070592 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -1157,6 +1157,14 @@ Vector<String> String::split_spaces() const { Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const { Vector<String> ret; + + if (is_empty()) { + if (p_allow_empty) { + ret.push_back(""); + } + return ret; + } + int from = 0; int len = length(); diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 94d1596514..d156c35343 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -64,7 +64,7 @@ void Array::_ref(const Array &p_from) const { _unref(); - _p = p_from._p; + _p = _fp; } void Array::_unref() const { @@ -191,62 +191,76 @@ uint32_t Array::recursive_hash(int recursion_count) const { return hash_fmix32(h); } -bool Array::_assign(const Array &p_array) { - bool can_convert = p_array._p->typed.type == Variant::NIL; - can_convert |= _p->typed.type == Variant::STRING && p_array._p->typed.type == Variant::STRING_NAME; - can_convert |= _p->typed.type == Variant::STRING_NAME && p_array._p->typed.type == Variant::STRING; +void Array::operator=(const Array &p_array) { + if (this == &p_array) { + return; + } + _ref(p_array); +} + +void Array::assign(const Array &p_array) { + const ContainerTypeValidate &typed = _p->typed; + const ContainerTypeValidate &source_typed = p_array._p->typed; - if (_p->typed.type != Variant::OBJECT && _p->typed.type == p_array._p->typed.type) { - //same type or untyped, just reference, should be fine - _ref(p_array); - } else if (_p->typed.type == Variant::NIL) { //from typed to untyped, must copy, but this is cheap anyway + if (typed == source_typed || typed.type == Variant::NIL || (source_typed.type == Variant::OBJECT && typed.can_reference(source_typed))) { + // from same to same or + // from anything to variants or + // from subclasses to base classes _p->array = p_array._p->array; - } else if (can_convert) { //from untyped to typed, must try to check if they are all valid - if (_p->typed.type == Variant::OBJECT) { - //for objects, it needs full validation, either can be converted or fail - for (int i = 0; i < p_array._p->array.size(); i++) { - const Variant &element = p_array._p->array[i]; - if (element.get_type() != Variant::OBJECT || !_p->typed.validate_object(element, "assign")) { - return false; - } - } - _p->array = p_array._p->array; //then just copy, which is cheap anyway + return; + } - } else { - //for non objects, we need to check if there is a valid conversion, which needs to happen one by one, so this is the worst case. - Vector<Variant> new_array; - new_array.resize(p_array._p->array.size()); - for (int i = 0; i < p_array._p->array.size(); i++) { - Variant src_val = p_array._p->array[i]; - if (src_val.get_type() == _p->typed.type) { - new_array.write[i] = src_val; - } else if (Variant::can_convert_strict(src_val.get_type(), _p->typed.type)) { - Variant *ptr = &src_val; - Callable::CallError ce; - Variant::construct(_p->typed.type, new_array.write[i], (const Variant **)&ptr, 1, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_FAIL_V_MSG(false, "Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'."); - } - } else { - ERR_FAIL_V_MSG(false, "Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'."); - } + const Variant *source = p_array._p->array.ptr(); + int size = p_array._p->array.size(); + + if ((source_typed.type == Variant::NIL && typed.type == Variant::OBJECT) || (source_typed.type == Variant::OBJECT && source_typed.can_reference(typed))) { + // from variants to objects or + // from base classes to subclasses + for (int i = 0; i < size; i++) { + const Variant &element = source[i]; + if (element.get_type() != Variant::NIL && (element.get_type() != Variant::OBJECT || !typed.validate_object(element, "assign"))) { + ERR_FAIL_MSG(vformat(R"(Unable to convert array index %i from "%s" to "%s".)", i, Variant::get_type_name(element.get_type()), Variant::get_type_name(typed.type))); } + } + _p->array = p_array._p->array; + return; + } + if (typed.type == Variant::OBJECT || source_typed.type == Variant::OBJECT) { + ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Array[%s]" to "Array[%s]".)", Variant::get_type_name(source_typed.type), Variant::get_type_name(typed.type))); + } - _p->array = new_array; + Vector<Variant> array; + array.resize(size); + Variant *data = array.ptrw(); + + if (source_typed.type == Variant::NIL && typed.type != Variant::OBJECT) { + // from variants to primitives + for (int i = 0; i < size; i++) { + const Variant *value = source + i; + if (value->get_type() == typed.type) { + data[i] = *value; + continue; + } + if (!Variant::can_convert_strict(value->get_type(), typed.type)) { + ERR_FAIL_MSG("Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(value->get_type()) + "' to '" + Variant::get_type_name(typed.type) + "'."); + } + Callable::CallError ce; + Variant::construct(typed.type, data[i], &value, 1, ce); + ERR_FAIL_COND_MSG(ce.error, vformat(R"(Unable to convert array index %i from "%s" to "%s".)", i, Variant::get_type_name(value->get_type()), Variant::get_type_name(typed.type))); + } + } else if (Variant::can_convert_strict(source_typed.type, typed.type)) { + // from primitives to different convertible primitives + for (int i = 0; i < size; i++) { + const Variant *value = source + i; + Callable::CallError ce; + Variant::construct(typed.type, data[i], &value, 1, ce); + ERR_FAIL_COND_MSG(ce.error, vformat(R"(Unable to convert array index %i from "%s" to "%s".)", i, Variant::get_type_name(value->get_type()), Variant::get_type_name(typed.type))); } - } else if (_p->typed.can_reference(p_array._p->typed)) { //same type or compatible - _ref(p_array); } else { - ERR_FAIL_V_MSG(false, "Assignment of arrays of incompatible types."); + ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Array[%s]" to "Array[%s]".)", Variant::get_type_name(source_typed.type), Variant::get_type_name(typed.type))); } - return true; -} -void Array::operator=(const Array &p_array) { - if (this == &p_array) { - return; - } - _ref(p_array); + _p->array = array; } void Array::push_back(const Variant &p_value) { @@ -269,7 +283,15 @@ void Array::append_array(const Array &p_array) { Error Array::resize(int p_new_size) { ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state."); - return _p->array.resize(p_new_size); + Variant::Type &variant_type = _p->typed.type; + int old_size = _p->array.size(); + Error err = _p->array.resize_zeroed(p_new_size); + if (!err && variant_type != Variant::NIL && variant_type != Variant::OBJECT) { + for (int i = old_size; i < p_new_size; i++) { + VariantInternal::initialize(&_p->array.write[i], variant_type); + } + } + return err; } Error Array::insert(int p_pos, const Variant &p_value) { @@ -403,24 +425,22 @@ Array Array::duplicate(bool p_deep) const { Array Array::recursive_duplicate(bool p_deep, int recursion_count) const { Array new_arr; + new_arr._p->typed = _p->typed; if (recursion_count > MAX_RECURSION) { ERR_PRINT("Max recursion reached"); return new_arr; } - int element_count = size(); - new_arr.resize(element_count); - new_arr._p->typed = _p->typed; if (p_deep) { recursion_count++; + int element_count = size(); + new_arr.resize(element_count); for (int i = 0; i < element_count; i++) { new_arr[i] = get(i).recursive_duplicate(true, recursion_count); } } else { - for (int i = 0; i < element_count; i++) { - new_arr[i] = get(i); - } + new_arr._p->array = _p->array; } return new_arr; @@ -612,14 +632,14 @@ void Array::shuffle() { } } -int Array::bsearch(const Variant &p_value, bool p_before) { +int Array::bsearch(const Variant &p_value, bool p_before) const { Variant value = p_value; ERR_FAIL_COND_V(!_p->typed.validate(value, "binary search"), -1); SearchArray<Variant, _ArrayVariantSort> avs; return avs.bisect(_p->array.ptrw(), _p->array.size(), value, p_before); } -int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before) { +int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before) const { Variant value = p_value; ERR_FAIL_COND_V(!_p->typed.validate(value, "custom binary search"), -1); @@ -737,11 +757,7 @@ Array::Array(const Array &p_from, uint32_t p_type, const StringName &p_class_nam _p = memnew(ArrayPrivate); _p->refcount.init(); set_typed(p_type, p_class_name, p_script); - _assign(p_from); -} - -bool Array::typed_assign(const Array &p_other) { - return _assign(p_other); + assign(p_from); } void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script) { @@ -763,6 +779,10 @@ bool Array::is_typed() const { return _p->typed.type != Variant::NIL; } +bool Array::is_same_typed(const Array &p_other) const { + return _p->typed == p_other._p->typed; +} + uint32_t Array::get_typed_builtin() const { return _p->typed.type; } diff --git a/core/variant/array.h b/core/variant/array.h index d9ca3278fb..8b1f8c0678 100644 --- a/core/variant/array.h +++ b/core/variant/array.h @@ -43,13 +43,11 @@ class Callable; class Array { mutable ArrayPrivate *_p; - void _ref(const Array &p_from) const; void _unref() const; -protected: - bool _assign(const Array &p_array); - public: + void _ref(const Array &p_from) const; + Variant &operator[](int p_idx); const Variant &operator[](int p_idx) const; @@ -68,6 +66,7 @@ public: uint32_t recursive_hash(int recursion_count) const; void operator=(const Array &p_array); + void assign(const Array &p_array); void push_back(const Variant &p_value); _FORCE_INLINE_ void append(const Variant &p_value) { push_back(p_value); } //for python compatibility void append_array(const Array &p_array); @@ -84,8 +83,8 @@ public: void sort(); void sort_custom(const Callable &p_callable); void shuffle(); - int bsearch(const Variant &p_value, bool p_before = true); - int bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before = true); + int bsearch(const Variant &p_value, bool p_before = true) const; + int bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before = true) const; void reverse(); int find(const Variant &p_value, int p_from = 0) const; @@ -120,9 +119,9 @@ public: const void *id() const; - bool typed_assign(const Array &p_other); void set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script); bool is_typed() const; + bool is_same_typed(const Array &p_other) const; uint32_t get_typed_builtin() const; StringName get_typed_class_name() const; Variant get_typed_script() const; diff --git a/core/variant/container_type_validate.h b/core/variant/container_type_validate.h index 377be03bdf..ffe1dc90a3 100644 --- a/core/variant/container_type_validate.h +++ b/core/variant/container_type_validate.h @@ -41,41 +41,40 @@ struct ContainerTypeValidate { const char *where = "container"; _FORCE_INLINE_ bool can_reference(const ContainerTypeValidate &p_type) const { - if (type == p_type.type) { - if (type != Variant::OBJECT) { - return true; //nothing else to check - } - } else { + if (type != p_type.type) { return false; + } else if (type != Variant::OBJECT) { + return true; } - //both are object - - if ((class_name != StringName()) != (p_type.class_name != StringName())) { - return false; //both need to have class or none - } - - if (class_name != p_type.class_name) { - if (!ClassDB::is_parent_class(p_type.class_name, class_name)) { - return false; - } - } - - if (script.is_null() != p_type.script.is_null()) { + if (class_name == StringName()) { + return true; + } else if (p_type.class_name == StringName()) { + return false; + } else if (class_name != p_type.class_name && !ClassDB::is_parent_class(p_type.class_name, class_name)) { return false; } - if (script != p_type.script) { - if (!p_type.script->inherits_script(script)) { - return false; - } + if (script.is_null()) { + return true; + } else if (p_type.script.is_null()) { + return false; + } else if (script != p_type.script && !p_type.script->inherits_script(script)) { + return false; } return true; } - // Coerces String and StringName into each other when needed. - _FORCE_INLINE_ bool validate(Variant &inout_variant, const char *p_operation = "use") { + _FORCE_INLINE_ bool operator==(const ContainerTypeValidate &p_type) const { + return type == p_type.type && class_name == p_type.class_name && script == p_type.script; + } + _FORCE_INLINE_ bool operator!=(const ContainerTypeValidate &p_type) const { + return type != p_type.type || class_name != p_type.class_name || script != p_type.script; + } + + // Coerces String and StringName into each other and int into float when needed. + _FORCE_INLINE_ bool validate(Variant &inout_variant, const char *p_operation = "use") const { if (type == Variant::NIL) { return true; } @@ -90,6 +89,9 @@ struct ContainerTypeValidate { } else if (type == Variant::STRING_NAME && inout_variant.get_type() == Variant::STRING) { inout_variant = StringName(inout_variant); return true; + } else if (type == Variant::FLOAT && inout_variant.get_type() == Variant::INT) { + inout_variant = (float)inout_variant; + return true; } ERR_FAIL_V_MSG(false, "Attempted to " + String(p_operation) + " a variable of type '" + Variant::get_type_name(inout_variant.get_type()) + "' into a " + where + " of type '" + Variant::get_type_name(type) + "'."); @@ -102,7 +104,7 @@ struct ContainerTypeValidate { return validate_object(inout_variant, p_operation); } - _FORCE_INLINE_ bool validate_object(const Variant &p_variant, const char *p_operation = "use") { + _FORCE_INLINE_ bool validate_object(const Variant &p_variant, const char *p_operation = "use") const { ERR_FAIL_COND_V(p_variant.get_type() != Variant::OBJECT, false); #ifdef DEBUG_ENABLED diff --git a/core/variant/typed_array.h b/core/variant/typed_array.h index 5aeabbacf8..03e557819b 100644 --- a/core/variant/typed_array.h +++ b/core/variant/typed_array.h @@ -40,14 +40,9 @@ template <class T> class TypedArray : public Array { public: - template <class U> - _FORCE_INLINE_ void operator=(const TypedArray<U> &p_array) { - static_assert(__is_base_of(T, U)); - _assign(p_array); - } - _FORCE_INLINE_ void operator=(const Array &p_array) { - _assign(p_array); + ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign an array with a different element type."); + _ref(p_array); } _FORCE_INLINE_ TypedArray(const Variant &p_variant) : Array(Array(p_variant), Variant::OBJECT, T::get_class_static(), Variant()) { @@ -62,22 +57,23 @@ public: //specialization for the rest of variant types -#define MAKE_TYPED_ARRAY(m_type, m_variant_type) \ - template <> \ - class TypedArray<m_type> : public Array { \ - public: \ - _FORCE_INLINE_ void operator=(const Array &p_array) { \ - _assign(p_array); \ - } \ - _FORCE_INLINE_ TypedArray(const Variant &p_variant) : \ - Array(Array(p_variant), m_variant_type, StringName(), Variant()) { \ - } \ - _FORCE_INLINE_ TypedArray(const Array &p_array) : \ - Array(p_array, m_variant_type, StringName(), Variant()) { \ - } \ - _FORCE_INLINE_ TypedArray() { \ - set_typed(m_variant_type, StringName(), Variant()); \ - } \ +#define MAKE_TYPED_ARRAY(m_type, m_variant_type) \ + template <> \ + class TypedArray<m_type> : public Array { \ + public: \ + _FORCE_INLINE_ void operator=(const Array &p_array) { \ + ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign an array with a different element type."); \ + _ref(p_array); \ + } \ + _FORCE_INLINE_ TypedArray(const Variant &p_variant) : \ + Array(Array(p_variant), m_variant_type, StringName(), Variant()) { \ + } \ + _FORCE_INLINE_ TypedArray(const Array &p_array) : \ + Array(p_array, m_variant_type, StringName(), Variant()) { \ + } \ + _FORCE_INLINE_ TypedArray() { \ + set_typed(m_variant_type, StringName(), Variant()); \ + } \ }; MAKE_TYPED_ARRAY(bool, Variant::BOOL) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 672b030806..04e1561a0c 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -3601,15 +3601,6 @@ bool Variant::is_type_shared(Variant::Type p_type) { case OBJECT: case ARRAY: case DICTIONARY: - case PACKED_BYTE_ARRAY: - case PACKED_INT32_ARRAY: - case PACKED_INT64_ARRAY: - case PACKED_FLOAT32_ARRAY: - case PACKED_FLOAT64_ARRAY: - case PACKED_STRING_ARRAY: - case PACKED_VECTOR2_ARRAY: - case PACKED_VECTOR3_ARRAY: - case PACKED_COLOR_ARRAY: return true; default: { } diff --git a/core/variant/variant.h b/core/variant/variant.h index b2f31a6d57..f694e59051 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -346,6 +346,10 @@ public: bool is_one() const; bool is_null() const; + // Make sure Variant is not implicitly cast when accessing it with bracket notation (GH-49469). + Variant &operator[](const Variant &p_key) = delete; + const Variant &operator[](const Variant &p_key) const = delete; + operator bool() const; operator signed int() const; operator unsigned int() const; // this is the real one diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 3b2d29734d..0c0c8f657a 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -2189,6 +2189,7 @@ static void _register_variant_builtin_methods() { bind_method(Array, is_empty, sarray(), varray()); bind_method(Array, clear, sarray(), varray()); bind_method(Array, hash, sarray(), varray()); + bind_method(Array, assign, sarray("array"), varray()); bind_method(Array, push_back, sarray("value"), varray()); bind_method(Array, push_front, sarray("value"), varray()); bind_method(Array, append, sarray("value"), varray()); @@ -2223,9 +2224,8 @@ static void _register_variant_builtin_methods() { bind_method(Array, all, sarray("method"), varray()); bind_method(Array, max, sarray(), varray()); bind_method(Array, min, sarray(), varray()); - bind_method(Array, typed_assign, sarray("array"), varray()); - bind_method(Array, set_typed, sarray("type", "class_name", "script"), varray()); bind_method(Array, is_typed, sarray(), varray()); + bind_method(Array, is_same_typed, sarray("array"), varray()); bind_method(Array, get_typed_builtin, sarray(), varray()); bind_method(Array, get_typed_class_name, sarray(), varray()); bind_method(Array, get_typed_script, sarray(), varray()); @@ -2403,7 +2403,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedStringArray, remove_at, sarray("index"), varray()); bind_method(PackedStringArray, insert, sarray("at_index", "value"), varray()); bind_method(PackedStringArray, fill, sarray("value"), varray()); - bind_method(PackedStringArray, resize, sarray("new_size"), varray()); + bind_methodv(PackedStringArray, resize, &PackedStringArray::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedStringArray, clear, sarray(), varray()); bind_method(PackedStringArray, has, sarray("value"), varray()); bind_method(PackedStringArray, reverse, sarray(), varray()); @@ -2427,7 +2427,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedVector2Array, remove_at, sarray("index"), varray()); bind_method(PackedVector2Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedVector2Array, fill, sarray("value"), varray()); - bind_method(PackedVector2Array, resize, sarray("new_size"), varray()); + bind_methodv(PackedVector2Array, resize, &PackedVector2Array::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedVector2Array, clear, sarray(), varray()); bind_method(PackedVector2Array, has, sarray("value"), varray()); bind_method(PackedVector2Array, reverse, sarray(), varray()); @@ -2451,7 +2451,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedVector3Array, remove_at, sarray("index"), varray()); bind_method(PackedVector3Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedVector3Array, fill, sarray("value"), varray()); - bind_method(PackedVector3Array, resize, sarray("new_size"), varray()); + bind_methodv(PackedVector3Array, resize, &PackedVector3Array::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedVector3Array, clear, sarray(), varray()); bind_method(PackedVector3Array, has, sarray("value"), varray()); bind_method(PackedVector3Array, reverse, sarray(), varray()); @@ -2475,7 +2475,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedColorArray, remove_at, sarray("index"), varray()); bind_method(PackedColorArray, insert, sarray("at_index", "value"), varray()); bind_method(PackedColorArray, fill, sarray("value"), varray()); - bind_method(PackedColorArray, resize, sarray("new_size"), varray()); + bind_methodv(PackedColorArray, resize, &PackedColorArray::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedColorArray, clear, sarray(), varray()); bind_method(PackedColorArray, has, sarray("value"), varray()); bind_method(PackedColorArray, reverse, sarray(), varray()); diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h index 21e1d21342..0d55ee4ae2 100644 --- a/core/variant/variant_internal.h +++ b/core/variant/variant_internal.h @@ -58,7 +58,13 @@ public: init_basis(v); break; case Variant::TRANSFORM3D: - init_transform(v); + init_transform3d(v); + break; + case Variant::PROJECTION: + init_projection(v); + break; + case Variant::COLOR: + init_color(v); break; case Variant::STRING_NAME: init_string_name(v); @@ -209,13 +215,12 @@ public: // Should be in the same order as Variant::Type for consistency. // Those primitive and vector types don't need an `init_` method: - // Nil, bool, float, Vector2/i, Rect2/i, Vector3/i, Plane, Quat, Color, RID. + // Nil, bool, float, Vector2/i, Rect2/i, Vector3/i, Plane, Quat, RID. // Object is a special case, handled via `object_assign_null`. _FORCE_INLINE_ static void init_string(Variant *v) { memnew_placement(v->_data._mem, String); v->type = Variant::STRING; } - _FORCE_INLINE_ static void init_transform2d(Variant *v) { v->_data._transform2d = (Transform2D *)Variant::Pools::_bucket_small.alloc(); memnew_placement(v->_data._transform2d, Transform2D); @@ -231,7 +236,7 @@ public: memnew_placement(v->_data._basis, Basis); v->type = Variant::BASIS; } - _FORCE_INLINE_ static void init_transform(Variant *v) { + _FORCE_INLINE_ static void init_transform3d(Variant *v) { v->_data._transform3d = (Transform3D *)Variant::Pools::_bucket_medium.alloc(); memnew_placement(v->_data._transform3d, Transform3D); v->type = Variant::TRANSFORM3D; @@ -241,6 +246,10 @@ public: memnew_placement(v->_data._projection, Projection); v->type = Variant::PROJECTION; } + _FORCE_INLINE_ static void init_color(Variant *v) { + memnew_placement(v->_data._mem, Color); + v->type = Variant::COLOR; + } _FORCE_INLINE_ static void init_string_name(Variant *v) { memnew_placement(v->_data._mem, StringName); v->type = Variant::STRING_NAME; @@ -1191,7 +1200,7 @@ struct VariantInitializer<Basis> { template <> struct VariantInitializer<Transform3D> { - static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform(v); } + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform3d(v); } }; template <> struct VariantInitializer<Projection> { diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp index 59f562865d..33c285dc6d 100644 --- a/core/variant/variant_op.cpp +++ b/core/variant/variant_op.cpp @@ -1105,8 +1105,11 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { evaluate(OP_IN, p_index, *this, ret, valid); if (r_valid) { *r_valid = valid; + } + if (valid) { + ERR_FAIL_COND_V(ret.type != BOOL, false); + return *VariantGetInternalPtr<bool>::get_ptr(&ret); + } else { return false; } - ERR_FAIL_COND_V(ret.type != BOOL, false); - return *VariantGetInternalPtr<bool>::get_ptr(&ret); } diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index 87874deb8d..a40fcfbd47 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -910,7 +910,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, bool at_key = true; String key; - Token token2; bool need_comma = false; while (true) { @@ -920,18 +919,18 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } if (at_key) { - Error err = get_token(p_stream, token2, line, r_err_str); + Error err = get_token(p_stream, token, line, r_err_str); if (err != OK) { return err; } - if (token2.type == TK_PARENTHESIS_CLOSE) { + if (token.type == TK_PARENTHESIS_CLOSE) { value = ref.is_valid() ? Variant(ref) : Variant(obj); return OK; } if (need_comma) { - if (token2.type != TK_COMMA) { + if (token.type != TK_COMMA) { r_err_str = "Expected '}' or ','"; return ERR_PARSE_ERROR; } else { @@ -940,31 +939,31 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } } - if (token2.type != TK_STRING) { + if (token.type != TK_STRING) { r_err_str = "Expected property name as string"; return ERR_PARSE_ERROR; } - key = token2.value; + key = token.value; - err = get_token(p_stream, token2, line, r_err_str); + err = get_token(p_stream, token, line, r_err_str); if (err != OK) { return err; } - if (token2.type != TK_COLON) { + if (token.type != TK_COLON) { r_err_str = "Expected ':'"; return ERR_PARSE_ERROR; } at_key = false; } else { - Error err = get_token(p_stream, token2, line, r_err_str); + Error err = get_token(p_stream, token, line, r_err_str); if (err != OK) { return err; } Variant v; - err = parse_value(token2, v, p_stream, line, r_err_str, p_res_parser); + err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser); if (err) { return err; } @@ -1026,6 +1025,89 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } } + } else if (id == "Array") { + Error err = OK; + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_BRACKET_OPEN) { + r_err_str = "Expected '['"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_IDENTIFIER) { + r_err_str = "Expected type identifier"; + return ERR_PARSE_ERROR; + } + + static HashMap<StringName, Variant::Type> builtin_types; + if (builtin_types.is_empty()) { + for (int i = 1; i < Variant::VARIANT_MAX; i++) { + builtin_types[Variant::get_type_name((Variant::Type)i)] = (Variant::Type)i; + } + } + + Array array = Array(); + bool got_bracket_token = false; + if (builtin_types.has(token.value)) { + array.set_typed(builtin_types.get(token.value), StringName(), Variant()); + } else if (token.value == "Resource" || token.value == "SubResource" || token.value == "ExtResource") { + Variant resource; + err = parse_value(token, resource, p_stream, line, r_err_str, p_res_parser); + if (err) { + if (token.value == "Resource" && err == ERR_PARSE_ERROR && r_err_str == "Expected '('" && token.type == TK_BRACKET_CLOSE) { + err = OK; + r_err_str = String(); + array.set_typed(Variant::OBJECT, token.value, Variant()); + got_bracket_token = true; + } else { + return err; + } + } else { + Ref<Script> script = resource; + if (script.is_valid() && script->is_valid()) { + array.set_typed(Variant::OBJECT, script->get_instance_base_type(), script); + } + } + } else if (ClassDB::class_exists(token.value)) { + array.set_typed(Variant::OBJECT, token.value, Variant()); + } + + if (!got_bracket_token) { + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_BRACKET_CLOSE) { + r_err_str = "Expected ']'"; + return ERR_PARSE_ERROR; + } + } + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_PARENTHESIS_OPEN) { + r_err_str = "Expected '('"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_BRACKET_OPEN) { + r_err_str = "Expected '['"; + return ERR_PARSE_ERROR; + } + + Array values; + err = _parse_array(values, p_stream, line, r_err_str, p_res_parser); + if (err) { + return err; + } + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_PARENTHESIS_CLOSE) { + r_err_str = "Expected ')'"; + return ERR_PARSE_ERROR; + } + + array.assign(values); + + value = array; } else if (id == "PackedByteArray" || id == "PoolByteArray" || id == "ByteArray") { Vector<uint8_t> args; Error err = _parse_construct<uint8_t>(p_stream, args, line, r_err_str); @@ -1843,6 +1925,38 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::ARRAY: { + Array array = p_variant; + if (array.get_typed_builtin() != Variant::NIL) { + p_store_string_func(p_store_string_ud, "Array["); + + Variant::Type builtin_type = (Variant::Type)array.get_typed_builtin(); + StringName class_name = array.get_typed_class_name(); + Ref<Script> script = array.get_typed_script(); + + if (script.is_valid()) { + String resource_text = String(); + if (p_encode_res_func) { + resource_text = p_encode_res_func(p_encode_res_ud, script); + } + if (resource_text.is_empty() && script->get_path().is_resource_file()) { + resource_text = "Resource(\"" + script->get_path() + "\")"; + } + + if (!resource_text.is_empty()) { + p_store_string_func(p_store_string_ud, resource_text); + } else { + ERR_PRINT("Failed to encode a path to a custom script for an array type."); + p_store_string_func(p_store_string_ud, class_name); + } + } else if (class_name != StringName()) { + p_store_string_func(p_store_string_ud, class_name); + } else { + p_store_string_func(p_store_string_ud, Variant::get_type_name(builtin_type)); + } + + p_store_string_func(p_store_string_ud, "]("); + } + if (recursion_count > MAX_RECURSION) { ERR_PRINT("Max recursion reached"); p_store_string_func(p_store_string_ud, "[]"); @@ -1850,7 +1964,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str recursion_count++; p_store_string_func(p_store_string_ud, "["); - Array array = p_variant; int len = array.size(); for (int i = 0; i < len; i++) { if (i > 0) { @@ -1862,11 +1975,14 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, "]"); } + if (array.get_typed_builtin() != Variant::NIL) { + p_store_string_func(p_store_string_ud, ")"); + } + } break; case Variant::PACKED_BYTE_ARRAY: { p_store_string_func(p_store_string_ud, "PackedByteArray("); - String s; Vector<uint8_t> data = p_variant; int len = data.size(); const uint8_t *ptr = data.ptr(); @@ -1954,15 +2070,11 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str int len = data.size(); const String *ptr = data.ptr(); - String s; - //write_string("\n"); - for (int i = 0; i < len; i++) { if (i > 0) { p_store_string_func(p_store_string_ud, ", "); } - String str = ptr[i]; - p_store_string_func(p_store_string_ud, "\"" + str.c_escape() + "\""); + p_store_string_func(p_store_string_ud, "\"" + ptr[i].c_escape() + "\""); } p_store_string_func(p_store_string_ud, ")"); @@ -2010,9 +2122,9 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str if (i > 0) { p_store_string_func(p_store_string_ud, ", "); } - p_store_string_func(p_store_string_ud, rtos_fix(ptr[i].r) + ", " + rtos_fix(ptr[i].g) + ", " + rtos_fix(ptr[i].b) + ", " + rtos_fix(ptr[i].a)); } + p_store_string_func(p_store_string_ud, ")"); } break; |