summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub1
-rw-r--r--core/config/engine.cpp12
-rw-r--r--core/config/engine.h4
-rw-r--r--core/config/project_settings.cpp225
-rw-r--r--core/config/project_settings.h24
-rw-r--r--core/core_bind.cpp318
-rw-r--r--core/core_bind.h52
-rw-r--r--core/core_builders.py4
-rw-r--r--core/core_constants.cpp735
-rw-r--r--core/core_constants.h4
-rw-r--r--core/core_string_names.cpp4
-rw-r--r--core/core_string_names.h4
-rw-r--r--core/crypto/SCsub1
-rw-r--r--core/crypto/aes_context.cpp4
-rw-r--r--core/crypto/aes_context.h4
-rw-r--r--core/crypto/crypto.cpp4
-rw-r--r--core/crypto/crypto.h4
-rw-r--r--core/crypto/crypto_core.cpp4
-rw-r--r--core/crypto/crypto_core.h4
-rw-r--r--core/crypto/hashing_context.cpp4
-rw-r--r--core/crypto/hashing_context.h4
-rw-r--r--core/debugger/debugger_marshalls.cpp4
-rw-r--r--core/debugger/debugger_marshalls.h4
-rw-r--r--core/debugger/engine_debugger.cpp14
-rw-r--r--core/debugger/engine_debugger.h6
-rw-r--r--core/debugger/local_debugger.cpp16
-rw-r--r--core/debugger/local_debugger.h6
-rw-r--r--core/debugger/remote_debugger.cpp18
-rw-r--r--core/debugger/remote_debugger.h8
-rw-r--r--core/debugger/remote_debugger_peer.cpp4
-rw-r--r--core/debugger/remote_debugger_peer.h4
-rw-r--r--core/debugger/script_debugger.cpp8
-rw-r--r--core/debugger/script_debugger.h6
-rw-r--r--core/doc_data.cpp8
-rw-r--r--core/doc_data.h44
-rw-r--r--core/error/error_list.cpp4
-rw-r--r--core/error/error_list.h4
-rw-r--r--core/error/error_macros.cpp49
-rw-r--r--core/error/error_macros.h426
-rw-r--r--core/extension/extension_api_dump.cpp31
-rw-r--r--core/extension/extension_api_dump.h4
-rw-r--r--core/extension/gdnative_interface.cpp68
-rw-r--r--core/extension/gdnative_interface.h28
-rw-r--r--core/extension/native_extension.cpp32
-rw-r--r--core/extension/native_extension.h8
-rw-r--r--core/extension/native_extension_manager.cpp20
-rw-r--r--core/extension/native_extension_manager.h4
-rw-r--r--core/input/SCsub14
-rw-r--r--core/input/default_controller_mappings.h4
-rw-r--r--core/input/gamecontrollerdb.txt1052
-rw-r--r--core/input/input.cpp309
-rw-r--r--core/input/input.h41
-rw-r--r--core/input/input_enums.h199
-rw-r--r--core/input/input_event.cpp240
-rw-r--r--core/input/input_event.h40
-rw-r--r--core/input/input_map.cpp230
-rw-r--r--core/input/input_map.h10
-rw-r--r--core/input/shortcut.cpp88
-rw-r--r--core/input/shortcut.h16
-rw-r--r--core/io/compression.cpp4
-rw-r--r--core/io/compression.h6
-rw-r--r--core/io/config_file.cpp12
-rw-r--r--core/io/config_file.h4
-rw-r--r--core/io/dir_access.cpp12
-rw-r--r--core/io/dir_access.h4
-rw-r--r--core/io/dtls_server.cpp4
-rw-r--r--core/io/dtls_server.h4
-rw-r--r--core/io/file_access.cpp8
-rw-r--r--core/io/file_access.h4
-rw-r--r--core/io/file_access_compressed.cpp10
-rw-r--r--core/io/file_access_compressed.h4
-rw-r--r--core/io/file_access_encrypted.cpp4
-rw-r--r--core/io/file_access_encrypted.h4
-rw-r--r--core/io/file_access_memory.cpp4
-rw-r--r--core/io/file_access_memory.h4
-rw-r--r--core/io/file_access_network.cpp4
-rw-r--r--core/io/file_access_network.h4
-rw-r--r--core/io/file_access_pack.cpp14
-rw-r--r--core/io/file_access_pack.h4
-rw-r--r--core/io/file_access_zip.cpp8
-rw-r--r--core/io/file_access_zip.h4
-rw-r--r--core/io/http_client.cpp18
-rw-r--r--core/io/http_client.h8
-rw-r--r--core/io/http_client_tcp.cpp97
-rw-r--r--core/io/http_client_tcp.h19
-rw-r--r--core/io/image.cpp86
-rw-r--r--core/io/image.h17
-rw-r--r--core/io/image_loader.cpp4
-rw-r--r--core/io/image_loader.h4
-rw-r--r--core/io/ip.cpp12
-rw-r--r--core/io/ip.h4
-rw-r--r--core/io/ip_address.cpp4
-rw-r--r--core/io/ip_address.h4
-rw-r--r--core/io/json.cpp4
-rw-r--r--core/io/json.h4
-rw-r--r--core/io/logger.cpp20
-rw-r--r--core/io/logger.h9
-rw-r--r--core/io/marshalls.cpp6
-rw-r--r--core/io/marshalls.h10
-rw-r--r--core/io/net_socket.cpp4
-rw-r--r--core/io/net_socket.h4
-rw-r--r--core/io/packed_data_container.cpp8
-rw-r--r--core/io/packed_data_container.h4
-rw-r--r--core/io/packet_peer.cpp50
-rw-r--r--core/io/packet_peer.h27
-rw-r--r--core/io/packet_peer_dtls.cpp4
-rw-r--r--core/io/packet_peer_dtls.h4
-rw-r--r--core/io/packet_peer_udp.cpp4
-rw-r--r--core/io/packet_peer_udp.h4
-rw-r--r--core/io/pck_packer.cpp7
-rw-r--r--core/io/pck_packer.h6
-rw-r--r--core/io/resource.cpp21
-rw-r--r--core/io/resource.h5
-rw-r--r--core/io/resource_format_binary.cpp100
-rw-r--r--core/io/resource_format_binary.h4
-rw-r--r--core/io/resource_importer.cpp20
-rw-r--r--core/io/resource_importer.h8
-rw-r--r--core/io/resource_loader.cpp24
-rw-r--r--core/io/resource_loader.h4
-rw-r--r--core/io/resource_saver.cpp4
-rw-r--r--core/io/resource_saver.h4
-rw-r--r--core/io/resource_uid.cpp24
-rw-r--r--core/io/resource_uid.h6
-rw-r--r--core/io/stream_peer.cpp61
-rw-r--r--core/io/stream_peer.h29
-rw-r--r--core/io/stream_peer_ssl.cpp4
-rw-r--r--core/io/stream_peer_ssl.h4
-rw-r--r--core/io/stream_peer_tcp.cpp4
-rw-r--r--core/io/stream_peer_tcp.h4
-rw-r--r--core/io/tcp_server.cpp4
-rw-r--r--core/io/tcp_server.h4
-rw-r--r--core/io/translation_loader_po.cpp20
-rw-r--r--core/io/translation_loader_po.h4
-rw-r--r--core/io/udp_server.cpp4
-rw-r--r--core/io/udp_server.h4
-rw-r--r--core/io/xml_parser.cpp4
-rw-r--r--core/io/xml_parser.h4
-rw-r--r--core/io/zip_io.cpp6
-rw-r--r--core/io/zip_io.h4
-rw-r--r--core/math/a_star.cpp91
-rw-r--r--core/math/a_star.h12
-rw-r--r--core/math/aabb.cpp46
-rw-r--r--core/math/aabb.h44
-rw-r--r--core/math/audio_frame.h7
-rw-r--r--core/math/basis.cpp593
-rw-r--r--core/math/basis.h63
-rw-r--r--core/math/bvh.h8
-rw-r--r--core/math/bvh_abb.h4
-rw-r--r--core/math/bvh_cull.inc2
-rw-r--r--core/math/bvh_debug.inc27
-rw-r--r--core/math/bvh_logic.inc50
-rw-r--r--core/math/bvh_pair.inc2
-rw-r--r--core/math/bvh_split.inc18
-rw-r--r--core/math/bvh_tree.h4
-rw-r--r--core/math/camera_matrix.cpp26
-rw-r--r--core/math/camera_matrix.h4
-rw-r--r--core/math/color.cpp100
-rw-r--r--core/math/color.h12
-rw-r--r--core/math/convex_hull.cpp40
-rw-r--r--core/math/convex_hull.h4
-rw-r--r--core/math/delaunay_2d.h10
-rw-r--r--core/math/delaunay_3d.h4
-rw-r--r--core/math/disjoint_set.h8
-rw-r--r--core/math/dynamic_bvh.cpp4
-rw-r--r--core/math/dynamic_bvh.h4
-rw-r--r--core/math/expression.cpp18
-rw-r--r--core/math/expression.h4
-rw-r--r--core/math/face3.cpp10
-rw-r--r--core/math/face3.h18
-rw-r--r--core/math/geometry_2d.cpp4
-rw-r--r--core/math/geometry_2d.h9
-rw-r--r--core/math/geometry_3d.cpp49
-rw-r--r--core/math/geometry_3d.h6
-rw-r--r--core/math/math_defs.h57
-rw-r--r--core/math/math_fieldwise.cpp4
-rw-r--r--core/math/math_fieldwise.h4
-rw-r--r--core/math/math_funcs.cpp8
-rw-r--r--core/math/math_funcs.h30
-rw-r--r--core/math/octree.h6
-rw-r--r--core/math/plane.cpp6
-rw-r--r--core/math/plane.h10
-rw-r--r--core/math/quaternion.cpp17
-rw-r--r--core/math/quaternion.h17
-rw-r--r--core/math/quick_hull.cpp28
-rw-r--r--core/math/quick_hull.h4
-rw-r--r--core/math/random_number_generator.cpp4
-rw-r--r--core/math/random_number_generator.h4
-rw-r--r--core/math/random_pcg.cpp4
-rw-r--r--core/math/random_pcg.h4
-rw-r--r--core/math/rect2.cpp14
-rw-r--r--core/math/rect2.h102
-rw-r--r--core/math/static_raycaster.cpp40
-rw-r--r--core/math/static_raycaster.h111
-rw-r--r--core/math/transform_2d.cpp38
-rw-r--r--core/math/transform_2d.h33
-rw-r--r--core/math/transform_3d.cpp34
-rw-r--r--core/math/transform_3d.h7
-rw-r--r--core/math/triangle_mesh.cpp12
-rw-r--r--core/math/triangle_mesh.h4
-rw-r--r--core/math/triangulate.cpp15
-rw-r--r--core/math/triangulate.h4
-rw-r--r--core/math/vector2.cpp25
-rw-r--r--core/math/vector2.h40
-rw-r--r--core/math/vector3.cpp27
-rw-r--r--core/math/vector3.h72
-rw-r--r--core/math/vector3i.cpp12
-rw-r--r--core/math/vector3i.h22
-rw-r--r--core/multiplayer/multiplayer.h10
-rw-r--r--core/multiplayer/multiplayer_api.cpp4
-rw-r--r--core/multiplayer/multiplayer_api.h4
-rw-r--r--core/multiplayer/multiplayer_peer.cpp185
-rw-r--r--core/multiplayer/multiplayer_peer.h84
-rw-r--r--core/multiplayer/multiplayer_replicator.cpp10
-rw-r--r--core/multiplayer/multiplayer_replicator.h4
-rw-r--r--core/multiplayer/rpc_manager.cpp12
-rw-r--r--core/multiplayer/rpc_manager.h4
-rw-r--r--core/object/callable_method_pointer.cpp4
-rw-r--r--core/object/callable_method_pointer.h4
-rw-r--r--core/object/class_db.cpp74
-rw-r--r--core/object/class_db.h37
-rw-r--r--core/object/make_virtuals.py11
-rw-r--r--core/object/message_queue.cpp16
-rw-r--r--core/object/message_queue.h4
-rw-r--r--core/object/method_bind.cpp15
-rw-r--r--core/object/method_bind.h42
-rw-r--r--core/object/object.cpp29
-rw-r--r--core/object/object.h24
-rw-r--r--core/object/object_id.h4
-rw-r--r--core/object/ref_counted.cpp4
-rw-r--r--core/object/ref_counted.h4
-rw-r--r--core/object/script_language.cpp12
-rw-r--r--core/object/script_language.h28
-rw-r--r--core/object/undo_redo.cpp54
-rw-r--r--core/object/undo_redo.h9
-rw-r--r--core/os/keyboard.cpp713
-rw-r--r--core/os/keyboard.h543
-rw-r--r--core/os/main_loop.cpp4
-rw-r--r--core/os/main_loop.h4
-rw-r--r--core/os/memory.cpp4
-rw-r--r--core/os/memory.h5
-rw-r--r--core/os/midi_driver.cpp22
-rw-r--r--core/os/midi_driver.h4
-rw-r--r--core/os/mutex.cpp4
-rw-r--r--core/os/mutex.h4
-rw-r--r--core/os/os.cpp46
-rw-r--r--core/os/os.h35
-rw-r--r--core/os/pool_allocator.cpp4
-rw-r--r--core/os/pool_allocator.h7
-rw-r--r--core/os/rw_lock.h4
-rw-r--r--core/os/semaphore.h4
-rw-r--r--core/os/spin_lock.h4
-rw-r--r--core/os/thread.cpp7
-rw-r--r--core/os/thread.h11
-rw-r--r--core/os/thread_safe.h4
-rw-r--r--core/os/threaded_array_processor.h4
-rw-r--r--core/os/time.cpp4
-rw-r--r--core/os/time.h4
-rw-r--r--core/register_core_types.cpp7
-rw-r--r--core/register_core_types.h4
-rw-r--r--core/string/node_path.cpp12
-rw-r--r--core/string/node_path.h4
-rw-r--r--core/string/optimized_translation.cpp19
-rw-r--r--core/string/optimized_translation.h6
-rw-r--r--core/string/print_string.cpp10
-rw-r--r--core/string/print_string.h16
-rw-r--r--core/string/string_buffer.h4
-rw-r--r--core/string/string_builder.cpp6
-rw-r--r--core/string/string_builder.h4
-rw-r--r--core/string/string_name.cpp8
-rw-r--r--core/string/string_name.h4
-rw-r--r--core/string/translation.cpp52
-rw-r--r--core/string/translation.h9
-rw-r--r--core/string/translation_po.cpp4
-rw-r--r--core/string/translation_po.h4
-rw-r--r--core/string/ucaps.h4
-rw-r--r--core/string/ustring.cpp212
-rw-r--r--core/string/ustring.h43
-rw-r--r--core/templates/bin_sorted_array.h6
-rw-r--r--core/templates/command_queue_mt.cpp4
-rw-r--r--core/templates/command_queue_mt.h4
-rw-r--r--core/templates/cowdata.h6
-rw-r--r--core/templates/hash_map.h32
-rw-r--r--core/templates/hashfuncs.h13
-rw-r--r--core/templates/list.h20
-rw-r--r--core/templates/local_vector.h24
-rw-r--r--core/templates/lru.h4
-rw-r--r--core/templates/map.h4
-rw-r--r--core/templates/oa_hash_map.h7
-rw-r--r--core/templates/ordered_hash_map.h16
-rw-r--r--core/templates/paged_allocator.h4
-rw-r--r--core/templates/paged_array.h4
-rw-r--r--core/templates/pair.h4
-rw-r--r--core/templates/pass_func.h4
-rw-r--r--core/templates/pooled_list.h18
-rw-r--r--core/templates/rid.h4
-rw-r--r--core/templates/rid_owner.cpp4
-rw-r--r--core/templates/rid_owner.h20
-rw-r--r--core/templates/ring_buffer.h4
-rw-r--r--core/templates/safe_list.h4
-rw-r--r--core/templates/safe_refcount.h4
-rw-r--r--core/templates/search_array.h67
-rw-r--r--core/templates/self_list.h4
-rw-r--r--core/templates/set.h7
-rw-r--r--core/templates/simple_type.h4
-rw-r--r--core/templates/sort_array.h4
-rw-r--r--core/templates/thread_work_pool.cpp6
-rw-r--r--core/templates/thread_work_pool.h28
-rw-r--r--core/templates/vector.h64
-rw-r--r--core/templates/vmap.h9
-rw-r--r--core/templates/vset.h6
-rw-r--r--core/typedefs.h15
-rw-r--r--core/variant/array.cpp171
-rw-r--r--core/variant/array.h11
-rw-r--r--core/variant/binder_common.h30
-rw-r--r--core/variant/callable.cpp8
-rw-r--r--core/variant/callable.h6
-rw-r--r--core/variant/callable_bind.cpp4
-rw-r--r--core/variant/callable_bind.h10
-rw-r--r--core/variant/container_type_validate.h4
-rw-r--r--core/variant/dictionary.cpp66
-rw-r--r--core/variant/dictionary.h7
-rw-r--r--core/variant/method_ptrcall.h4
-rw-r--r--core/variant/native_ptr.h7
-rw-r--r--core/variant/type_info.h6
-rw-r--r--core/variant/typed_array.h4
-rw-r--r--core/variant/variant.cpp184
-rw-r--r--core/variant/variant.h30
-rw-r--r--core/variant/variant_call.cpp135
-rw-r--r--core/variant/variant_construct.cpp11
-rw-r--r--core/variant/variant_construct.h4
-rw-r--r--core/variant/variant_destruct.cpp4
-rw-r--r--core/variant/variant_destruct.h4
-rw-r--r--core/variant/variant_internal.h24
-rw-r--r--core/variant/variant_op.cpp145
-rw-r--r--core/variant/variant_op.h32
-rw-r--r--core/variant/variant_parser.cpp157
-rw-r--r--core/variant/variant_parser.h6
-rw-r--r--core/variant/variant_setget.cpp107
-rw-r--r--core/variant/variant_setget.h4
-rw-r--r--core/variant/variant_utility.cpp87
-rw-r--r--core/version.h4
341 files changed, 7320 insertions, 4542 deletions
diff --git a/core/SCsub b/core/SCsub
index 14dfa3487f..c12dd4e60e 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -146,6 +146,7 @@ env.core_sources += thirdparty_obj
# Godot source files
env.add_source_files(env.core_sources, "*.cpp")
+env.add_source_files(env.core_sources, "script_encryption_key.gen.cpp")
# Certificates
env.Depends(
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index d8fbb50a75..0a13becf6d 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -111,7 +111,7 @@ Dictionary Engine::get_version_info() const {
static Array array_from_info(const char *const *info_list) {
Array arr;
for (int i = 0; info_list[i] != nullptr; i++) {
- arr.push_back(info_list[i]);
+ arr.push_back(String::utf8(info_list[i]));
}
return arr;
}
@@ -119,7 +119,7 @@ static Array array_from_info(const char *const *info_list) {
static Array array_from_info_count(const char *const *info_list, int info_count) {
Array arr;
for (int i = 0; i < info_count; i++) {
- arr.push_back(info_list[i]);
+ arr.push_back(String::utf8(info_list[i]));
}
return arr;
}
@@ -140,14 +140,14 @@ Array Engine::get_copyright_info() const {
for (int component_index = 0; component_index < COPYRIGHT_INFO_COUNT; component_index++) {
const ComponentCopyright &cp_info = COPYRIGHT_INFO[component_index];
Dictionary component_dict;
- component_dict["name"] = cp_info.name;
+ component_dict["name"] = String::utf8(cp_info.name);
Array parts;
for (int i = 0; i < cp_info.part_count; i++) {
const ComponentCopyrightPart &cp_part = cp_info.parts[i];
Dictionary part_dict;
part_dict["files"] = array_from_info_count(cp_part.files, cp_part.file_count);
part_dict["copyright"] = array_from_info_count(cp_part.copyright_statements, cp_part.copyright_count);
- part_dict["license"] = cp_part.license;
+ part_dict["license"] = String::utf8(cp_part.license);
parts.push_back(part_dict);
}
component_dict["parts"] = parts;
diff --git a/core/config/engine.h b/core/config/engine.h
index ae33acede2..3ec522eafc 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 03892d1d4f..45776c03e4 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -41,6 +41,11 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
+#include "core/version.h"
+
+#include "modules/modules_enabled.gen.h" // For mono.
+
+const String ProjectSettings::PROJECT_DATA_DIR_NAME_SUFFIX = "godot";
ProjectSettings *ProjectSettings::singleton = nullptr;
@@ -48,18 +53,95 @@ ProjectSettings *ProjectSettings::get_singleton() {
return singleton;
}
+String ProjectSettings::get_project_data_dir_name() const {
+ return project_data_dir_name;
+}
+
+String ProjectSettings::get_project_data_path() const {
+ return "res://" + get_project_data_dir_name();
+}
+
String ProjectSettings::get_resource_path() const {
return resource_path;
}
-const String ProjectSettings::IMPORTED_FILES_PATH("res://.godot/imported");
+String ProjectSettings::get_safe_project_name() const {
+ String safe_name = OS::get_singleton()->get_safe_dir_name(get("application/config/name"));
+ if (safe_name.is_empty()) {
+ safe_name = "UnnamedProject";
+ }
+ return safe_name;
+}
-String ProjectSettings::localize_path(const String &p_path) const {
- if (resource_path == "") {
- return p_path; //not initialized yet
+String ProjectSettings::get_imported_files_path() const {
+ return get_project_data_path().plus_file("imported");
+}
+
+// Returns the features that a project must have when opened with this build of Godot.
+// This is used by the project manager to provide the initial_settings for config/features.
+const PackedStringArray ProjectSettings::get_required_features() {
+ PackedStringArray features = PackedStringArray();
+ features.append(VERSION_BRANCH);
+#ifdef REAL_T_IS_DOUBLE
+ features.append("Double Precision");
+#endif
+ return features;
+}
+
+// Returns the features supported by this build of Godot. Includes all required features.
+const PackedStringArray ProjectSettings::_get_supported_features() {
+ PackedStringArray features = get_required_features();
+#ifdef MODULE_MONO_ENABLED
+ features.append("C#");
+#endif
+ // Allow pinning to a specific patch number or build type by marking
+ // them as supported. They're only used if the user adds them manually.
+ features.append(VERSION_BRANCH "." _MKSTR(VERSION_PATCH));
+ features.append(VERSION_FULL_CONFIG);
+ features.append(VERSION_FULL_BUILD);
+ // For now, assume Vulkan is always supported.
+ // This should be removed if it's possible to build the editor without Vulkan.
+ features.append("Vulkan Clustered");
+ features.append("Vulkan Mobile");
+ return features;
+}
+
+// Returns the features that this project needs but this build of Godot lacks.
+const PackedStringArray ProjectSettings::get_unsupported_features(const PackedStringArray &p_project_features) {
+ PackedStringArray unsupported_features = PackedStringArray();
+ PackedStringArray supported_features = singleton->_get_supported_features();
+ for (int i = 0; i < p_project_features.size(); i++) {
+ if (!supported_features.has(p_project_features[i])) {
+ unsupported_features.append(p_project_features[i]);
+ }
}
+ unsupported_features.sort();
+ return unsupported_features;
+}
- if (p_path.begins_with("res://") || p_path.begins_with("user://") ||
+// Returns the features that both this project has and this build of Godot has, ensuring required features exist.
+const PackedStringArray ProjectSettings::_trim_to_supported_features(const PackedStringArray &p_project_features) {
+ // Remove unsupported features if present.
+ PackedStringArray features = PackedStringArray(p_project_features);
+ PackedStringArray supported_features = _get_supported_features();
+ for (int i = p_project_features.size() - 1; i > -1; i--) {
+ if (!supported_features.has(p_project_features[i])) {
+ features.remove_at(i);
+ }
+ }
+ // Add required features if not present.
+ PackedStringArray required_features = get_required_features();
+ for (int i = 0; i < required_features.size(); i++) {
+ if (!features.has(required_features[i])) {
+ features.append(required_features[i]);
+ }
+ }
+ features.sort();
+ return features;
+}
+
+String ProjectSettings::localize_path(const String &p_path) const {
+ if (resource_path.is_empty() || p_path.begins_with("res://") || p_path.begins_with("user://") ||
(p_path.is_absolute_path() && !p_path.begins_with(resource_path))) {
return p_path.simplify_path();
}
@@ -102,7 +184,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
String parent = path.substr(0, sep);
String plocal = localize_path(parent);
- if (plocal == "") {
+ if (plocal.is_empty()) {
return "";
}
// Only strip the starting '/' from 'path' if its parent ('plocal') ends with '/'
@@ -146,13 +228,13 @@ bool ProjectSettings::get_ignore_value_in_docs(const String &p_name) const {
String ProjectSettings::globalize_path(const String &p_path) const {
if (p_path.begins_with("res://")) {
- if (resource_path != "") {
+ if (!resource_path.is_empty()) {
return p_path.replace("res:/", resource_path);
}
return p_path.replace("res://", "");
} else if (p_path.begins_with("user://")) {
String data_dir = OS::get_singleton()->get_user_data_dir();
- if (data_dir != "") {
+ if (!data_dir.is_empty()) {
return p_path.replace("user:/", data_dir);
}
return p_path.replace("user://", "");
@@ -256,15 +338,15 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const {
Set<_VCSort> vclist;
- for (Map<StringName, VariantContainer>::Element *E = props.front(); E; E = E->next()) {
- const VariantContainer *v = &E->get();
+ for (const KeyValue<StringName, VariantContainer> &E : props) {
+ const VariantContainer *v = &E.value;
if (v->hide_from_editor) {
continue;
}
_VCSort vc;
- vc.name = E->key();
+ vc.name = E.key;
vc.order = v->order;
vc.type = v->variant.get_type();
if (vc.name.begins_with("input/") || vc.name.begins_with("import/") || vc.name.begins_with("export/") || vc.name.begins_with("/remap") || vc.name.begins_with("/locale") || vc.name.begins_with("/autoload")) {
@@ -322,14 +404,14 @@ bool ProjectSettings::_load_resource_pack(const String &p_pack, bool p_replace_f
void ProjectSettings::_convert_to_last_version(int p_from_version) {
if (p_from_version <= 3) {
// Converts the actions from array to dictionary (array of events to dictionary with deadzone + events)
- for (Map<StringName, ProjectSettings::VariantContainer>::Element *E = props.front(); E; E = E->next()) {
- Variant value = E->get().variant;
- if (String(E->key()).begins_with("input/") && value.get_type() == Variant::ARRAY) {
+ for (KeyValue<StringName, ProjectSettings::VariantContainer> &E : props) {
+ Variant value = E.value.variant;
+ if (String(E.key).begins_with("input/") && value.get_type() == Variant::ARRAY) {
Array array = value;
Dictionary action;
action["deadzone"] = Variant(0.5f);
action["events"] = array;
- E->get().variant = action;
+ E.value.variant = action;
}
}
}
@@ -360,12 +442,12 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) {
* If a project file is found, load it or fail.
* If nothing was found, error out.
*/
-Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, bool p_upwards) {
+Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, bool p_upwards, bool p_ignore_override) {
// If looking for files in a network client, use it directly
if (FileAccessNetworkClient::get_singleton()) {
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
- if (err == OK) {
+ if (err == OK && !p_ignore_override) {
// Optional, we don't mind if it fails
_load_settings_text("res://override.cfg");
}
@@ -374,12 +456,12 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
// Attempt with a user-defined main pack first
- if (p_main_pack != "") {
+ if (!p_main_pack.is_empty()) {
bool ok = _load_resource_pack(p_main_pack);
ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, "Cannot open resource pack '" + p_main_pack + "'.");
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
- if (err == OK) {
+ if (err == OK && !p_ignore_override) {
// Load override from location of the main pack
// Optional, we don't mind if it fails
_load_settings_text(p_main_pack.get_base_dir().plus_file("override.cfg"));
@@ -389,7 +471,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
String exec_path = OS::get_singleton()->get_executable_path();
- if (exec_path != "") {
+ if (!exec_path.is_empty()) {
// We do several tests sequentially until one succeeds to find a PCK,
// and if so, we attempt loading it at the end.
@@ -429,7 +511,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
// If we opened our package, try and load our project.
if (found) {
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
- if (err == OK) {
+ if (err == OK && !p_ignore_override) {
// Load override from location of the executable.
// Optional, we don't mind if it fails.
_load_settings_text(exec_path.get_base_dir().plus_file("override.cfg"));
@@ -441,16 +523,16 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
// Try to use the filesystem for files, according to OS.
// (Only Android -when reading from pck- and iOS use this.)
- if (OS::get_singleton()->get_resource_dir() != "") {
+ if (!OS::get_singleton()->get_resource_dir().is_empty()) {
// OS will call ProjectSettings->get_resource_path which will be empty if not overridden!
// If the OS would rather use a specific location, then it will not be empty.
resource_path = OS::get_singleton()->get_resource_dir().replace("\\", "/");
- if (resource_path != "" && resource_path[resource_path.length() - 1] == '/') {
+ if (!resource_path.is_empty() && resource_path[resource_path.length() - 1] == '/') {
resource_path = resource_path.substr(0, resource_path.length() - 1); // Chop end.
}
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
- if (err == OK) {
+ if (err == OK && !p_ignore_override) {
// Optional, we don't mind if it fails.
_load_settings_text("res://override.cfg");
}
@@ -473,7 +555,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
resource_path = current_dir;
resource_path = resource_path.replace("\\", "/"); // Windows path to Unix path just in case.
err = _load_settings_text_or_binary(current_dir.plus_file("project.godot"), current_dir.plus_file("project.binary"));
- if (err == OK) {
+ if (err == OK && !p_ignore_override) {
// Optional, we don't mind if it fails.
_load_settings_text(current_dir.plus_file("override.cfg"));
found = true;
@@ -505,14 +587,19 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
return OK;
}
-Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bool p_upwards) {
- Error err = _setup(p_path, p_main_pack, p_upwards);
+Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bool p_upwards, bool p_ignore_override) {
+ Error err = _setup(p_path, p_main_pack, p_upwards, p_ignore_override);
if (err == OK) {
String custom_settings = GLOBAL_DEF("application/config/project_settings_override", "");
- if (custom_settings != "") {
+ if (!custom_settings.is_empty()) {
_load_settings_text(custom_settings);
}
}
+
+ // Updating the default value after the project settings have loaded.
+ bool use_hidden_directory = GLOBAL_GET("application/config/use_hidden_project_data_directory");
+ project_data_dir_name = (use_hidden_directory ? "." : "") + PROJECT_DATA_DIR_NAME_SUFFIX;
+
// Using GLOBAL_GET on every block for compressing can be slow, so assigning here.
Compression::zstd_long_distance_matching = GLOBAL_GET("compression/formats/zstd/long_distance_matching");
Compression::zstd_level = GLOBAL_GET("compression/formats/zstd/compression_level");
@@ -612,21 +699,21 @@ Error ProjectSettings::_load_settings_text(const String &p_path) {
return err;
}
- if (assign != String()) {
- if (section == String() && assign == "config_version") {
+ if (!assign.is_empty()) {
+ if (section.is_empty() && assign == "config_version") {
config_version = value;
if (config_version > CONFIG_VERSION) {
memdelete(f);
ERR_FAIL_V_MSG(ERR_FILE_CANT_OPEN, vformat("Can't open project at '%s', its `config_version` (%d) is from a more recent and incompatible version of the engine. Expected config version: %d.", p_path, config_version, CONFIG_VERSION));
}
} else {
- if (section == String()) {
+ if (section.is_empty()) {
set(assign, value);
} else {
set(section + "/" + assign, value);
}
}
- } else if (next_tag.name != String()) {
+ } else if (!next_tag.name.is_empty()) {
section = next_tag.name;
}
}
@@ -653,6 +740,13 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path,
return err;
}
+Error ProjectSettings::load_custom(const String &p_path) {
+ if (p_path.ends_with(".binary")) {
+ return _load_settings_binary(p_path);
+ }
+ return _load_settings_text(p_path);
+}
+
int ProjectSettings::get_order(const String &p_name) const {
ERR_FAIL_COND_V_MSG(!props.has(p_name), -1, "Request for nonexistent project setting: " + p_name + ".");
return props[p_name].order;
@@ -699,11 +793,11 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
int count = 0;
- for (Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) {
- count += E->get().size();
+ for (const KeyValue<String, List<String>> &E : props) {
+ count += E.value.size();
}
- if (p_custom_features != String()) {
+ if (!p_custom_features.is_empty()) {
file->store_32(count + 1);
//store how many properties are saved, add one for custom featuers, which must always go first
String key = CoreStringNames::get_singleton()->_custom_features;
@@ -733,7 +827,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
for (Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) {
for (String &key : E->get()) {
- if (E->key() != "") {
+ if (!E->key().is_empty()) {
key = E->key() + "/" + key;
}
Variant value;
@@ -787,22 +881,22 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
file->store_line("");
file->store_string("config_version=" + itos(CONFIG_VERSION) + "\n");
- if (p_custom_features != String()) {
+ if (!p_custom_features.is_empty()) {
file->store_string("custom_features=\"" + p_custom_features + "\"\n");
}
file->store_string("\n");
- for (Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) {
+ for (const Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) {
if (E != props.front()) {
file->store_string("\n");
}
- if (E->key() != "") {
+ if (!E->key().is_empty()) {
file->store_string("[" + E->key() + "]\n\n");
}
for (const String &F : E->get()) {
String key = F;
- if (E->key() != "") {
+ if (!E->key().is_empty()) {
key = E->key() + "/" + key;
}
Variant value;
@@ -830,24 +924,52 @@ Error ProjectSettings::_save_custom_bnd(const String &p_file) { // add other par
}
Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_custom, const Vector<String> &p_custom_features, bool p_merge_with_current) {
- ERR_FAIL_COND_V_MSG(p_path == "", ERR_INVALID_PARAMETER, "Project settings save path cannot be empty.");
+ ERR_FAIL_COND_V_MSG(p_path.is_empty(), ERR_INVALID_PARAMETER, "Project settings save path cannot be empty.");
+
+ PackedStringArray project_features = has_setting("application/config/features") ? (PackedStringArray)get_setting("application/config/features") : PackedStringArray();
+ // If there is no feature list currently present, force one to generate.
+ if (project_features.is_empty()) {
+ project_features = ProjectSettings::get_required_features();
+ }
+ // Check the rendering API.
+ const String rendering_api = has_setting("rendering/quality/driver/driver_name") ? (String)get_setting("rendering/quality/driver/driver_name") : String();
+ if (!rendering_api.is_empty()) {
+ // Add the rendering API as a project feature if it doesn't already exist.
+ if (!project_features.has(rendering_api)) {
+ project_features.append(rendering_api);
+ }
+ }
+ // Check for the existence of a csproj file.
+ if (FileAccess::exists(get_resource_path().plus_file(get_safe_project_name() + ".csproj"))) {
+ // If there is a csproj file, add the C# feature if it doesn't already exist.
+ if (!project_features.has("C#")) {
+ project_features.append("C#");
+ }
+ } else {
+ // If there isn't a csproj file, remove the C# feature if it exists.
+ if (project_features.has("C#")) {
+ project_features.remove_at(project_features.find("C#"));
+ }
+ }
+ project_features = _trim_to_supported_features(project_features);
+ set_setting("application/config/features", project_features);
Set<_VCSort> vclist;
if (p_merge_with_current) {
- for (Map<StringName, VariantContainer>::Element *G = props.front(); G; G = G->next()) {
- const VariantContainer *v = &G->get();
+ for (const KeyValue<StringName, VariantContainer> &G : props) {
+ const VariantContainer *v = &G.value;
if (v->hide_from_editor) {
continue;
}
- if (p_custom.has(G->key())) {
+ if (p_custom.has(G.key)) {
continue;
}
_VCSort vc;
- vc.name = G->key(); //*k;
+ vc.name = G.key; //*k;
vc.order = v->order;
vc.type = v->variant.get_type();
vc.flags = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE;
@@ -859,14 +981,14 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
}
}
- for (const Map<String, Variant>::Element *E = p_custom.front(); E; E = E->next()) {
+ for (const KeyValue<String, Variant> &E : p_custom) {
// Lookup global prop to store in the same order
- Map<StringName, VariantContainer>::Element *global_prop = props.find(E->key());
+ Map<StringName, VariantContainer>::Element *global_prop = props.find(E.key);
_VCSort vc;
- vc.name = E->key();
+ vc.name = E.key;
vc.order = global_prop ? global_prop->get().order : 0xFFFFFFF;
- vc.type = E->get().get_type();
+ vc.type = E.value.get_type();
vc.flags = PROPERTY_USAGE_STORAGE;
vclist.insert(vc);
}
@@ -1084,6 +1206,7 @@ ProjectSettings::ProjectSettings() {
custom_prop_info["application/run/main_scene"] = PropertyInfo(Variant::STRING, "application/run/main_scene", PROPERTY_HINT_FILE, "*.tscn,*.scn,*.res");
GLOBAL_DEF("application/run/disable_stdout", false);
GLOBAL_DEF("application/run/disable_stderr", false);
+ GLOBAL_DEF_RST("application/config/use_hidden_project_data_directory", true);
GLOBAL_DEF("application/config/use_custom_user_dir", false);
GLOBAL_DEF("application/config/custom_user_dir_name", "");
GLOBAL_DEF("application/config/project_settings_override", "");
diff --git a/core/config/project_settings.h b/core/config/project_settings.h
index 7e93f26f0d..614a11f726 100644
--- a/core/config/project_settings.h
+++ b/core/config/project_settings.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,12 +42,14 @@ class ProjectSettings : public Object {
public:
typedef Map<String, Variant> CustomMap;
- static const String IMPORTED_FILES_PATH;
+ static const String PROJECT_DATA_DIR_NAME_SUFFIX;
enum {
//properties that are not for built in values begin from this value, so builtin ones are displayed first
NO_BUILTIN_ORDER_BASE = 1 << 16
};
+ const static PackedStringArray get_required_features();
+ const static PackedStringArray get_unsupported_features(const PackedStringArray &p_project_features);
struct AutoloadInfo {
StringName name;
@@ -94,6 +96,8 @@ protected:
OrderedHashMap<StringName, AutoloadInfo> autoloads;
+ String project_data_dir_name;
+
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
@@ -109,13 +113,16 @@ protected:
Error _save_custom_bnd(const String &p_file);
+ const static PackedStringArray _get_supported_features();
+ const static PackedStringArray _trim_to_supported_features(const PackedStringArray &p_project_features);
+
void _convert_to_last_version(int p_from_version);
bool _load_resource_pack(const String &p_pack, bool p_replace_files = true, int p_offset = 0);
void _add_property_info_bind(const Dictionary &p_info);
- Error _setup(const String &p_path, const String &p_main_pack, bool p_upwards = false);
+ Error _setup(const String &p_path, const String &p_main_pack, bool p_upwards = false, bool p_ignore_override = false);
void _add_builtin_input_map();
@@ -123,7 +130,7 @@ protected:
static void _bind_methods();
public:
- static const int CONFIG_VERSION = 4;
+ static const int CONFIG_VERSION = 5;
void set_setting(const String &p_setting, const Variant &p_value);
Variant get_setting(const String &p_setting) const;
@@ -141,7 +148,11 @@ public:
bool property_can_revert(const String &p_name);
Variant property_get_revert(const String &p_name);
+ String get_project_data_dir_name() const;
+ String get_project_data_path() const;
String get_resource_path() const;
+ String get_safe_project_name() const;
+ String get_imported_files_path() const;
static ProjectSettings *get_singleton();
@@ -151,8 +162,9 @@ public:
void set_builtin_order(const String &p_name);
bool is_builtin_setting(const String &p_name) const;
- Error setup(const String &p_path, const String &p_main_pack, bool p_upwards = false);
+ Error setup(const String &p_path, const String &p_main_pack, bool p_upwards = false, bool p_ignore_override = false);
+ Error load_custom(const String &p_path);
Error save_custom(const String &p_path = "", const CustomMap &p_custom = CustomMap(), const Vector<String> &p_custom_features = Vector<String>(), bool p_merge_with_current = true);
Error save();
void set_custom_property_info(const String &p_prop, const PropertyInfo &p_info);
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index fd5b3bb731..ef28f43f05 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -207,6 +207,10 @@ void OS::alert(const String &p_alert, const String &p_title) {
::OS::get_singleton()->alert(p_alert, p_title);
}
+void OS::crash(const String &p_message) {
+ CRASH_NOW_MSG(p_message);
+}
+
String OS::get_executable_path() const {
return ::OS::get_singleton()->get_executable_path();
}
@@ -235,6 +239,19 @@ int OS::execute(const String &p_path, const Vector<String> &p_arguments, Array r
return exitcode;
}
+int OS::create_instance(const Vector<String> &p_arguments) {
+ List<String> args;
+ for (int i = 0; i < p_arguments.size(); i++) {
+ args.push_back(p_arguments[i]);
+ }
+ ::OS::ProcessID pid = 0;
+ Error err = ::OS::get_singleton()->create_instance(args, &pid);
+ if (err != OK) {
+ return -1;
+ }
+ return pid;
+}
+
int OS::create_process(const String &p_path, const Vector<String> &p_arguments) {
List<String> args;
for (int i = 0; i < p_arguments.size(); i++) {
@@ -286,6 +303,10 @@ String OS::get_locale() const {
return ::OS::get_singleton()->get_locale();
}
+String OS::get_locale_language() const {
+ return ::OS::get_singleton()->get_locale_language();
+}
+
String OS::get_model_name() const {
return ::OS::get_singleton()->get_model_name();
}
@@ -298,6 +319,10 @@ Error OS::set_thread_name(const String &p_name) {
return ::Thread::get_caller_id();
};
+::Thread::ID OS::get_main_thread_id() const {
+ return ::Thread::get_main_id();
+};
+
bool OS::has_feature(const String &p_feature) const {
return ::OS::get_singleton()->has_feature(p_feature);
}
@@ -485,15 +510,15 @@ String OS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
return ::OS::get_singleton()->get_system_dir(::OS::SystemDir(p_dir), p_shared_storage);
}
-String OS::get_keycode_string(uint32_t p_code) const {
+String OS::get_keycode_string(Key p_code) const {
return ::keycode_get_string(p_code);
}
-bool OS::is_keycode_unicode(uint32_t p_unicode) const {
- return ::keycode_has_unicode(p_unicode);
+bool OS::is_keycode_unicode(char32_t p_unicode) const {
+ return ::keycode_has_unicode((Key)p_unicode);
}
-int OS::find_keycode_from_string(const String &p_code) const {
+Key OS::find_keycode_from_string(const String &p_code) const {
return find_keycode(p_code);
}
@@ -521,6 +546,7 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("close_midi_inputs"), &OS::close_midi_inputs);
ClassDB::bind_method(D_METHOD("alert", "text", "title"), &OS::alert, DEFVAL("Alert!"));
+ ClassDB::bind_method(D_METHOD("crash", "message"), &OS::crash);
ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode", "enable"), &OS::set_low_processor_usage_mode);
ClassDB::bind_method(D_METHOD("is_in_low_processor_usage_mode"), &OS::is_in_low_processor_usage_mode);
@@ -533,6 +559,7 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path);
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr"), &OS::execute, DEFVAL(Array()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("create_process", "path", "arguments"), &OS::create_process);
+ ClassDB::bind_method(D_METHOD("create_instance", "arguments"), &OS::create_instance);
ClassDB::bind_method(D_METHOD("kill", "pid"), &OS::kill);
ClassDB::bind_method(D_METHOD("shell_open", "uri"), &OS::shell_open);
ClassDB::bind_method(D_METHOD("get_process_id"), &OS::get_process_id);
@@ -547,6 +574,7 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("delay_usec", "usec"), &OS::delay_usec);
ClassDB::bind_method(D_METHOD("delay_msec", "msec"), &OS::delay_msec);
ClassDB::bind_method(D_METHOD("get_locale"), &OS::get_locale);
+ ClassDB::bind_method(D_METHOD("get_locale_language"), &OS::get_locale_language);
ClassDB::bind_method(D_METHOD("get_model_name"), &OS::get_model_name);
ClassDB::bind_method(D_METHOD("is_userfs_persistent"), &OS::is_userfs_persistent);
@@ -582,6 +610,7 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_thread_name", "name"), &OS::set_thread_name);
ClassDB::bind_method(D_METHOD("get_thread_caller_id"), &OS::get_thread_caller_id);
+ ClassDB::bind_method(D_METHOD("get_main_thread_id"), &OS::get_main_thread_id);
ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &OS::has_feature);
@@ -598,8 +627,8 @@ void OS::_bind_methods() {
ADD_PROPERTY_DEFAULT("low_processor_usage_mode", false);
ADD_PROPERTY_DEFAULT("low_processor_usage_mode_sleep_usec", 6900);
- BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES2);
BIND_ENUM_CONSTANT(VIDEO_DRIVER_VULKAN);
+ BIND_ENUM_CONSTANT(VIDEO_DRIVER_OPENGL_3);
BIND_ENUM_CONSTANT(DAY_SUNDAY);
BIND_ENUM_CONSTANT(DAY_MONDAY);
@@ -669,10 +698,7 @@ Variant Geometry2D::line_intersects_line(const Vector2 &p_from_a, const Vector2
Vector<Vector2> Geometry2D::get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) {
Vector2 r1, r2;
::Geometry2D::get_closest_points_between_segments(p1, q1, p2, q2, r1, r2);
- Vector<Vector2> r;
- r.resize(2);
- r.set(0, r1);
- r.set(1, r2);
+ Vector<Vector2> r = { r1, r2 };
return r;
}
@@ -894,10 +920,7 @@ Vector<Plane> Geometry3D::build_capsule_planes(float p_radius, float p_height, i
Vector<Vector3> Geometry3D::get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2) {
Vector3 r1, r2;
::Geometry3D::get_closest_points_between_segments(p1, p2, q1, q2, r1, r2);
- Vector<Vector3> r;
- r.resize(2);
- r.set(0, r1);
- r.set(1, r2);
+ Vector<Vector3> r = { r1, r2 };
return r;
}
@@ -1072,79 +1095,79 @@ bool File::is_open() const {
}
String File::get_path() const {
- ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
return f->get_path();
}
String File::get_path_absolute() const {
- ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
return f->get_path_absolute();
}
void File::seek(int64_t p_position) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
ERR_FAIL_COND_MSG(p_position < 0, "Seek position must be a positive integer.");
f->seek(p_position);
}
void File::seek_end(int64_t p_position) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->seek_end(p_position);
}
uint64_t File::get_position() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_position();
}
uint64_t File::get_length() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_length();
}
bool File::eof_reached() const {
- ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use, or is lacking read-write permission.");
return f->eof_reached();
}
uint8_t File::get_8() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_8();
}
uint16_t File::get_16() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_16();
}
uint32_t File::get_32() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_32();
}
uint64_t File::get_64() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_64();
}
float File::get_float() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_float();
}
double File::get_double() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_double();
}
real_t File::get_real() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_real();
}
Vector<uint8_t> File::get_buffer(int64_t p_length) const {
Vector<uint8_t> data;
- ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use, or is lacking read-write permission.");
ERR_FAIL_COND_V_MSG(p_length < 0, data, "Length of buffer cannot be smaller than 0.");
if (p_length == 0) {
@@ -1165,7 +1188,7 @@ Vector<uint8_t> File::get_buffer(int64_t p_length) const {
}
String File::get_as_text() const {
- ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use, or is lacking read-write permission.");
String text;
uint64_t original_pos = f->get_position();
@@ -1192,12 +1215,12 @@ String File::get_sha256(const String &p_path) const {
}
String File::get_line() const {
- ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use, or is lacking read-write permission.");
return f->get_line();
}
Vector<String> File::get_csv_line(const String &p_delim) const {
- ERR_FAIL_COND_V_MSG(!f, Vector<String>(), "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, Vector<String>(), "File must be opened before use, or is lacking read-write permission.");
return f->get_csv_line(p_delim);
}
@@ -1225,77 +1248,77 @@ Error File::get_error() const {
}
void File::store_8(uint8_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_8(p_dest);
}
void File::store_16(uint16_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_16(p_dest);
}
void File::store_32(uint32_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_32(p_dest);
}
void File::store_64(uint64_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_64(p_dest);
}
void File::store_float(float p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_float(p_dest);
}
void File::store_double(double p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_double(p_dest);
}
void File::store_real(real_t p_real) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_real(p_real);
}
void File::store_string(const String &p_string) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_string(p_string);
}
void File::store_pascal_string(const String &p_string) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_pascal_string(p_string);
}
String File::get_pascal_string() {
- ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
return f->get_pascal_string();
}
void File::store_line(const String &p_string) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_line(p_string);
}
void File::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
f->store_csv_line(p_values, p_delim);
}
void File::store_buffer(const Vector<uint8_t> &p_buffer) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
uint64_t len = p_buffer.size();
if (len == 0) {
@@ -1312,7 +1335,7 @@ bool File::file_exists(const String &p_name) const {
}
void File::store_var(const Variant &p_var, bool p_full_objects) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
int len;
Error err = encode_variant(p_var, nullptr, len, p_full_objects);
ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant.");
@@ -1329,7 +1352,7 @@ void File::store_var(const Variant &p_var, bool p_full_objects) {
}
Variant File::get_var(bool p_allow_objects) const {
- ERR_FAIL_COND_V_MSG(!f, Variant(), "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(!f, Variant(), "File must be opened before use, or is lacking read-write permission.");
uint32_t len = get_32();
Vector<uint8_t> buff = get_buffer(len);
ERR_FAIL_COND_V((uint32_t)buff.size() != len, Variant());
@@ -1441,12 +1464,8 @@ bool Directory::is_open() const {
return d && dir_open;
}
-Error Directory::list_dir_begin(bool p_show_navigational, bool p_show_hidden) {
+Error Directory::list_dir_begin() {
ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
-
- _list_skip_navigational = !p_show_navigational;
- _list_skip_hidden = !p_show_hidden;
-
return d->list_dir_begin();
}
@@ -1454,7 +1473,7 @@ String Directory::get_next() {
ERR_FAIL_COND_V_MSG(!is_open(), "", "Directory must be opened before use.");
String next = d->get_next();
- while (next != "" && ((_list_skip_navigational && (next == "." || next == "..")) || (_list_skip_hidden && d->current_is_hidden()))) {
+ while (!next.is_empty() && ((!include_navigational && (next == "." || next == "..")) || (!include_hidden && d->current_is_hidden()))) {
next = d->get_next();
}
return next;
@@ -1470,6 +1489,47 @@ void Directory::list_dir_end() {
d->list_dir_end();
}
+PackedStringArray Directory::get_files() {
+ return _get_contents(false);
+}
+
+PackedStringArray Directory::get_directories() {
+ return _get_contents(true);
+}
+
+PackedStringArray Directory::_get_contents(bool p_directories) {
+ PackedStringArray ret;
+ ERR_FAIL_COND_V_MSG(!is_open(), ret, "Directory must be opened before use.");
+
+ list_dir_begin();
+ String s = get_next();
+ while (!s.is_empty()) {
+ if (current_is_dir() == p_directories) {
+ ret.append(s);
+ }
+ s = get_next();
+ }
+
+ ret.sort();
+ return ret;
+}
+
+void Directory::set_include_navigational(bool p_enable) {
+ include_navigational = p_enable;
+}
+
+bool Directory::get_include_navigational() const {
+ return include_navigational;
+}
+
+void Directory::set_include_hidden(bool p_enable) {
+ include_hidden = p_enable;
+}
+
+bool Directory::get_include_hidden() const {
+ return include_hidden;
+}
+
int Directory::get_drive_count() {
ERR_FAIL_COND_V_MSG(!is_open(), 0, "Directory must be opened before use.");
return d->get_drive_count();
@@ -1585,10 +1645,12 @@ Error Directory::remove(String p_name) {
void Directory::_bind_methods() {
ClassDB::bind_method(D_METHOD("open", "path"), &Directory::open);
- ClassDB::bind_method(D_METHOD("list_dir_begin", "show_navigational", "show_hidden"), &Directory::list_dir_begin, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("list_dir_begin"), &Directory::list_dir_begin, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_next"), &Directory::get_next);
ClassDB::bind_method(D_METHOD("current_is_dir"), &Directory::current_is_dir);
ClassDB::bind_method(D_METHOD("list_dir_end"), &Directory::list_dir_end);
+ ClassDB::bind_method(D_METHOD("get_files"), &Directory::get_files);
+ ClassDB::bind_method(D_METHOD("get_directories"), &Directory::get_directories);
ClassDB::bind_method(D_METHOD("get_drive_count"), &Directory::get_drive_count);
ClassDB::bind_method(D_METHOD("get_drive", "idx"), &Directory::get_drive);
ClassDB::bind_method(D_METHOD("get_current_drive"), &Directory::get_current_drive);
@@ -1603,6 +1665,14 @@ void Directory::_bind_methods() {
ClassDB::bind_method(D_METHOD("copy", "from", "to"), &Directory::copy);
ClassDB::bind_method(D_METHOD("rename", "from", "to"), &Directory::rename);
ClassDB::bind_method(D_METHOD("remove", "path"), &Directory::remove);
+
+ ClassDB::bind_method(D_METHOD("set_include_navigational", "enable"), &Directory::set_include_navigational);
+ ClassDB::bind_method(D_METHOD("get_include_navigational"), &Directory::get_include_navigational);
+ ClassDB::bind_method(D_METHOD("set_include_hidden", "enable"), &Directory::set_include_hidden);
+ ClassDB::bind_method(D_METHOD("get_include_hidden"), &Directory::get_include_hidden);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_navigational"), "set_include_navigational", "get_include_navigational");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_hidden"), "set_include_hidden", "get_include_hidden");
}
Directory::Directory() {
@@ -1636,7 +1706,7 @@ String Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects) {
ERR_FAIL_COND_V_MSG(err != OK, "", "Error when trying to encode Variant.");
String ret = CryptoCore::b64_encode_str(&w[0], len);
- ERR_FAIL_COND_V(ret == "", ret);
+ ERR_FAIL_COND_V(ret.is_empty(), ret);
return ret;
}
@@ -1661,7 +1731,7 @@ Variant Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects)
String Marshalls::raw_to_base64(const Vector<uint8_t> &p_arr) {
String ret = CryptoCore::b64_encode_str(p_arr.ptr(), p_arr.size());
- ERR_FAIL_COND_V(ret == "", ret);
+ ERR_FAIL_COND_V(ret.is_empty(), ret);
return ret;
}
@@ -1685,7 +1755,7 @@ Vector<uint8_t> Marshalls::base64_to_raw(const String &p_str) {
String Marshalls::utf8_to_base64(const String &p_str) {
CharString cstr = p_str.utf8();
String ret = CryptoCore::b64_encode_str((unsigned char *)cstr.get_data(), cstr.length());
- ERR_FAIL_COND_V(ret == "", ret);
+ ERR_FAIL_COND_V(ret.is_empty(), ret);
return ret;
}
@@ -1763,6 +1833,13 @@ void Thread::_start_func(void *ud) {
Ref<Thread> *tud = (Ref<Thread> *)ud;
Ref<Thread> t = *tud;
memdelete(tud);
+
+ Object *target_instance = t->target_callable.get_object();
+ if (!target_instance) {
+ t->running.clear();
+ ERR_FAIL_MSG(vformat("Could not call function '%s' on previously freed instance to start thread %s.", t->target_callable.get_method(), t->get_id()));
+ }
+
Callable::CallError ce;
const Variant *arg[1] = { &t->userdata };
int argc = 0;
@@ -1781,58 +1858,43 @@ void Thread::_start_func(void *ud) {
// We must check if we are in case b).
int target_param_count = 0;
int target_default_arg_count = 0;
- Ref<Script> script = t->target_instance->get_script();
+ Ref<Script> script = target_instance->get_script();
if (script.is_valid()) {
- MethodInfo mi = script->get_method_info(t->target_method);
+ MethodInfo mi = script->get_method_info(t->target_callable.get_method());
target_param_count = mi.arguments.size();
target_default_arg_count = mi.default_arguments.size();
} else {
- MethodBind *method = ClassDB::get_method(t->target_instance->get_class_name(), t->target_method);
- target_param_count = method->get_argument_count();
- target_default_arg_count = method->get_default_argument_count();
+ MethodBind *method = ClassDB::get_method(target_instance->get_class_name(), t->target_callable.get_method());
+ if (method) {
+ target_param_count = method->get_argument_count();
+ target_default_arg_count = method->get_default_argument_count();
+ }
}
if (target_param_count >= 1 && target_default_arg_count < target_param_count) {
argc = 1;
}
}
- ::Thread::set_name(t->target_method);
+ ::Thread::set_name(t->target_callable.get_method());
- t->ret = t->target_instance->call(t->target_method, arg, argc, ce);
+ t->target_callable.call(arg, argc, t->ret, ce);
if (ce.error != Callable::CallError::CALL_OK) {
- String reason;
- switch (ce.error) {
- case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: {
- reason = "Invalid Argument #" + itos(ce.argument);
- } break;
- case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: {
- reason = "Too Many Arguments";
- } break;
- case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: {
- reason = "Too Few Arguments";
- } break;
- case Callable::CallError::CALL_ERROR_INVALID_METHOD: {
- reason = "Method Not Found";
- } break;
- default: {
- }
- }
-
- ERR_FAIL_MSG("Could not call function '" + t->target_method.operator String() + "' to start thread " + t->get_id() + ": " + reason + ".");
+ t->running.clear();
+ ERR_FAIL_MSG("Could not call function '" + t->target_callable.get_method().operator String() + "' to start thread " + t->get_id() + ": " + Variant::get_callable_error_text(t->target_callable, arg, argc, ce) + ".");
}
+
+ t->running.clear();
}
-Error Thread::start(Object *p_instance, const StringName &p_method, const Variant &p_userdata, Priority p_priority) {
- ERR_FAIL_COND_V_MSG(active.is_set(), ERR_ALREADY_IN_USE, "Thread already started.");
- ERR_FAIL_COND_V(!p_instance, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(p_method == StringName(), ERR_INVALID_PARAMETER);
+Error Thread::start(const Callable &p_callable, const Variant &p_userdata, Priority p_priority) {
+ ERR_FAIL_COND_V_MSG(is_started(), ERR_ALREADY_IN_USE, "Thread already started.");
+ ERR_FAIL_COND_V(!p_callable.is_valid(), ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_priority, PRIORITY_MAX, ERR_INVALID_PARAMETER);
ret = Variant();
- target_method = p_method;
- target_instance = p_instance;
+ target_callable = p_callable;
userdata = p_userdata;
- active.set();
+ running.set();
Ref<Thread> *ud = memnew(Ref<Thread>(this));
@@ -1847,26 +1909,29 @@ String Thread::get_id() const {
return itos(thread.get_id());
}
-bool Thread::is_active() const {
- return active.is_set();
+bool Thread::is_started() const {
+ return thread.is_started();
+}
+
+bool Thread::is_alive() const {
+ return running.is_set();
}
Variant Thread::wait_to_finish() {
- ERR_FAIL_COND_V_MSG(!active.is_set(), Variant(), "Thread must be active to wait for its completion.");
+ ERR_FAIL_COND_V_MSG(!is_started(), Variant(), "Thread must have been started to wait for its completion.");
thread.wait_to_finish();
Variant r = ret;
- active.clear();
- target_method = StringName();
- target_instance = nullptr;
+ target_callable = Callable();
userdata = Variant();
return r;
}
void Thread::_bind_methods() {
- ClassDB::bind_method(D_METHOD("start", "instance", "method", "userdata", "priority"), &Thread::start, DEFVAL(Variant()), DEFVAL(PRIORITY_NORMAL));
+ ClassDB::bind_method(D_METHOD("start", "callable", "userdata", "priority"), &Thread::start, DEFVAL(Variant()), DEFVAL(PRIORITY_NORMAL));
ClassDB::bind_method(D_METHOD("get_id"), &Thread::get_id);
- ClassDB::bind_method(D_METHOD("is_active"), &Thread::is_active);
+ ClassDB::bind_method(D_METHOD("is_started"), &Thread::is_started);
+ ClassDB::bind_method(D_METHOD("is_alive"), &Thread::is_alive);
ClassDB::bind_method(D_METHOD("wait_to_finish"), &Thread::wait_to_finish);
BIND_ENUM_CONSTANT(PRIORITY_LOW);
@@ -2042,6 +2107,42 @@ StringName ClassDB::get_category(const StringName &p_node) const {
return ::ClassDB::get_category(p_node);
}
+bool ClassDB::has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) const {
+ return ::ClassDB::has_enum(p_class, p_name, p_no_inheritance);
+}
+
+PackedStringArray ClassDB::get_enum_list(const StringName &p_class, bool p_no_inheritance) const {
+ List<StringName> enums;
+ ::ClassDB::get_enum_list(p_class, &enums, p_no_inheritance);
+
+ PackedStringArray ret;
+ ret.resize(enums.size());
+ int idx = 0;
+ for (const StringName &E : enums) {
+ ret.set(idx++, E);
+ }
+
+ return ret;
+}
+
+PackedStringArray ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_enum, bool p_no_inheritance) const {
+ List<StringName> constants;
+ ::ClassDB::get_enum_constants(p_class, p_enum, &constants, p_no_inheritance);
+
+ PackedStringArray ret;
+ ret.resize(constants.size());
+ int idx = 0;
+ for (const StringName &E : constants) {
+ ret.set(idx++, E);
+ }
+
+ return ret;
+}
+
+StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) const {
+ return ::ClassDB::get_integer_constant_enum(p_class, p_name, p_no_inheritance);
+}
+
bool ClassDB::is_class_enabled(StringName p_class) const {
return ::ClassDB::is_class_enabled(p_class);
}
@@ -2072,6 +2173,11 @@ void ClassDB::_bind_methods() {
::ClassDB::bind_method(D_METHOD("class_has_integer_constant", "class", "name"), &ClassDB::has_integer_constant);
::ClassDB::bind_method(D_METHOD("class_get_integer_constant", "class", "name"), &ClassDB::get_integer_constant);
+ ::ClassDB::bind_method(D_METHOD("class_has_enum", "class", "name", "no_inheritance"), &ClassDB::has_enum, DEFVAL(false));
+ ::ClassDB::bind_method(D_METHOD("class_get_enum_list", "class", "no_inheritance"), &ClassDB::get_enum_list, DEFVAL(false));
+ ::ClassDB::bind_method(D_METHOD("class_get_enum_constants", "class", "enum", "no_inheritance"), &ClassDB::get_enum_constants, DEFVAL(false));
+ ::ClassDB::bind_method(D_METHOD("class_get_integer_constant_enum", "class", "name", "no_inheritance"), &ClassDB::get_integer_constant_enum, DEFVAL(false));
+
::ClassDB::bind_method(D_METHOD("class_get_category", "class"), &ClassDB::get_category);
::ClassDB::bind_method(D_METHOD("is_class_enabled", "class"), &ClassDB::is_class_enabled);
}
@@ -2175,7 +2281,7 @@ Object *Engine::get_singleton_object(const StringName &p_name) const {
void Engine::register_singleton(const StringName &p_name, Object *p_object) {
ERR_FAIL_COND_MSG(has_singleton(p_name), "Singleton already registered: " + String(p_name));
- ERR_FAIL_COND_MSG(p_name.operator String().is_valid_identifier(), "Singleton name is not a valid identifier: " + String(p_name));
+ ERR_FAIL_COND_MSG(!String(p_name).is_valid_identifier(), "Singleton name is not a valid identifier: " + p_name);
::Engine::Singleton s;
s.class_name = p_name;
s.name = p_name;
@@ -2185,7 +2291,7 @@ void Engine::register_singleton(const StringName &p_name, Object *p_object) {
;
}
void Engine::unregister_singleton(const StringName &p_name) {
- ERR_FAIL_COND_MSG(!has_singleton(p_name), "Attempt to remove unregisteres singleton: " + String(p_name));
+ ERR_FAIL_COND_MSG(!has_singleton(p_name), "Attempt to remove unregistered singleton: " + String(p_name));
ERR_FAIL_COND_MSG(!::Engine::get_singleton()->is_singleton_user_created(p_name), "Attempt to remove non-user created singleton: " + String(p_name));
::Engine::get_singleton()->remove_singleton(p_name);
}
@@ -2251,13 +2357,11 @@ void Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("unregister_singleton", "name"), &Engine::unregister_singleton);
ClassDB::bind_method(D_METHOD("get_singleton_list"), &Engine::get_singleton_list);
- ClassDB::bind_method(D_METHOD("set_editor_hint", "enabled"), &Engine::set_editor_hint);
ClassDB::bind_method(D_METHOD("is_editor_hint"), &Engine::is_editor_hint);
ClassDB::bind_method(D_METHOD("set_print_error_messages", "enabled"), &Engine::set_print_error_messages);
ClassDB::bind_method(D_METHOD("is_printing_error_messages"), &Engine::is_printing_error_messages);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_hint"), "set_editor_hint", "is_editor_hint");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_error_messages"), "set_print_error_messages", "is_printing_error_messages");
ADD_PROPERTY(PropertyInfo(Variant::INT, "physics_ticks_per_second"), "set_physics_ticks_per_second", "get_physics_ticks_per_second");
ADD_PROPERTY(PropertyInfo(Variant::INT, "target_fps"), "set_target_fps", "get_target_fps");
@@ -2388,12 +2492,12 @@ Error EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Arra
}
EngineDebugger::~EngineDebugger() {
- for (Map<StringName, Callable>::Element *E = captures.front(); E; E = E->next()) {
- ::EngineDebugger::unregister_message_capture(E->key());
+ for (const KeyValue<StringName, Callable> &E : captures) {
+ ::EngineDebugger::unregister_message_capture(E.key);
}
captures.clear();
- for (Map<StringName, ProfilerCallable>::Element *E = profilers.front(); E; E = E->next()) {
- ::EngineDebugger::unregister_profiler(E->key());
+ for (const KeyValue<StringName, ProfilerCallable> &E : profilers) {
+ ::EngineDebugger::unregister_profiler(E.key);
}
profilers.clear();
}
diff --git a/core/core_bind.h b/core/core_bind.h
index a6fac63edd..c7a406b2f3 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -119,8 +119,8 @@ protected:
public:
enum VideoDriver {
- VIDEO_DRIVER_GLES2,
VIDEO_DRIVER_VULKAN,
+ VIDEO_DRIVER_OPENGL_3,
};
enum Weekday {
@@ -161,10 +161,12 @@ public:
int get_low_processor_usage_mode_sleep_usec() const;
void alert(const String &p_alert, const String &p_title = "ALERT!");
+ void crash(const String &p_message);
String get_executable_path() const;
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false);
int create_process(const String &p_path, const Vector<String> &p_arguments);
+ int create_instance(const Vector<String> &p_arguments);
Error kill(int p_pid);
Error shell_open(String p_uri);
@@ -178,6 +180,7 @@ public:
Vector<String> get_cmdline_args();
String get_locale() const;
+ String get_locale_language() const;
String get_model_name() const;
@@ -193,9 +196,9 @@ public:
String get_unique_id() const;
- String get_keycode_string(uint32_t p_code) const;
- bool is_keycode_unicode(uint32_t p_unicode) const;
- int find_keycode_from_string(const String &p_code) const;
+ String get_keycode_string(Key p_code) const;
+ bool is_keycode_unicode(char32_t p_unicode) const;
+ Key find_keycode_from_string(const String &p_code) const;
void set_use_file_access_save_and_swap(bool p_enable);
@@ -204,7 +207,7 @@ public:
void delay_usec(int p_usec) const;
void delay_msec(int p_msec) const;
- uint32_t get_ticks_msec() const;
+ uint64_t get_ticks_msec() const;
uint64_t get_ticks_usec() const;
bool can_use_threads() const;
@@ -235,6 +238,7 @@ public:
Error set_thread_name(const String &p_name);
Thread::ID get_thread_caller_id() const;
+ Thread::ID get_main_thread_id() const;
bool has_feature(const String &p_feature) const;
@@ -440,7 +444,10 @@ public:
class Directory : public RefCounted {
GDCLASS(Directory, RefCounted);
DirAccess *d;
+
bool dir_open = false;
+ bool include_navigational = false;
+ bool include_hidden = false;
protected:
static void _bind_methods();
@@ -450,12 +457,20 @@ public:
bool is_open() const;
- Error list_dir_begin(bool p_show_navigational = false, bool p_show_hidden = false); // This starts dir listing.
+ Error list_dir_begin();
String get_next();
bool current_is_dir() const;
-
void list_dir_end();
+ PackedStringArray get_files();
+ PackedStringArray get_directories();
+ PackedStringArray _get_contents(bool p_directories);
+
+ void set_include_navigational(bool p_enable);
+ bool get_include_navigational() const;
+ void set_include_hidden(bool p_enable);
+ bool get_include_hidden() const;
+
int get_drive_count();
String get_drive(int p_drive);
int get_current_drive();
@@ -477,10 +492,6 @@ public:
Directory();
virtual ~Directory();
-
-private:
- bool _list_skip_navigational = false;
- bool _list_skip_hidden = false;
};
class Marshalls : public Object {
@@ -537,9 +548,8 @@ class Thread : public RefCounted {
protected:
Variant ret;
Variant userdata;
- SafeFlag active;
- Object *target_instance = nullptr;
- StringName target_method;
+ SafeFlag running;
+ Callable target_callable;
::Thread thread;
static void _bind_methods();
static void _start_func(void *ud);
@@ -552,9 +562,10 @@ public:
PRIORITY_MAX
};
- Error start(Object *p_instance, const StringName &p_method, const Variant &p_userdata = Variant(), Priority p_priority = PRIORITY_NORMAL);
+ Error start(const Callable &p_callable, const Variant &p_userdata = Variant(), Priority p_priority = PRIORITY_NORMAL);
String get_id() const;
- bool is_active() const;
+ bool is_started() const;
+ bool is_alive() const;
Variant wait_to_finish();
};
@@ -592,6 +603,11 @@ public:
int get_integer_constant(const StringName &p_class, const StringName &p_name) const;
StringName get_category(const StringName &p_node) const;
+ bool has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false) const;
+ PackedStringArray get_enum_list(const StringName &p_class, bool p_no_inheritance = false) const;
+ PackedStringArray get_enum_constants(const StringName &p_class, const StringName &p_enum, bool p_no_inheritance = false) const;
+ StringName get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false) const;
+
bool is_class_enabled(StringName p_class) const;
ClassDB() {}
diff --git a/core/core_builders.py b/core/core_builders.py
index 004475faa7..b07daa80ae 100644
--- a/core/core_builders.py
+++ b/core/core_builders.py
@@ -35,7 +35,9 @@ def make_certs_header(target, source, env):
decomp_size = len(buf)
import zlib
- buf = zlib.compress(buf)
+ # Use maximum zlib compression level to further reduce file size
+ # (at the cost of initial build times).
+ buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef CERTS_COMPRESSED_GEN_H\n")
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 721e5ae622..6f26288eb7 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -71,6 +71,16 @@ static Vector<_CoreConstant> _global_constants;
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
_global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant));
+// This just binds enum classes as if they were regular enum constants.
+#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
+ _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member), #m_prefix "_" #m_member, (int)m_enum::m_member));
+
+#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
+ _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_name), #m_name, (int)m_enum::m_member));
+
+#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
+ _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member), #m_prefix "_" #m_member, (int)m_enum::m_member, true));
+
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
_global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_constant, #m_constant), m_custom_name, m_constant));
@@ -91,6 +101,16 @@ static Vector<_CoreConstant> _global_constants;
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
_global_constants.push_back(_CoreConstant(#m_constant, m_constant));
+// This just binds enum classes as if they were regular enum constants.
+#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
+ _global_constants.push_back(_CoreConstant(#m_prefix "_" #m_member, (int)m_enum::m_member));
+
+#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
+ _global_constants.push_back(_CoreConstant(#m_name, (int)m_enum::m_member));
+
+#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
+ _global_constants.push_back(_CoreConstant(#m_prefix "_" #m_member, (int)m_enum::m_member));
+
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
_global_constants.push_back(_CoreConstant(m_custom_name, m_constant));
@@ -122,348 +142,351 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(CLOCKWISE);
BIND_CORE_ENUM_CONSTANT(COUNTERCLOCKWISE);
- BIND_CORE_ENUM_CONSTANT(HALIGN_LEFT);
- BIND_CORE_ENUM_CONSTANT(HALIGN_CENTER);
- BIND_CORE_ENUM_CONSTANT(HALIGN_RIGHT);
- BIND_CORE_ENUM_CONSTANT(HALIGN_FILL);
-
- BIND_CORE_ENUM_CONSTANT(VALIGN_TOP);
- BIND_CORE_ENUM_CONSTANT(VALIGN_CENTER);
- BIND_CORE_ENUM_CONSTANT(VALIGN_BOTTOM);
-
- BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TOP_TO);
- BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_CENTER_TO);
- BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_BOTTOM_TO);
-
- BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TO_TOP);
- BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TO_CENTER);
- BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TO_BASELINE);
- BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TO_BOTTOM);
-
- BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TOP);
- BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_CENTER);
- BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_BOTTOM);
-
- // huge list of keys
- BIND_CORE_CONSTANT(SPKEY);
-
- BIND_CORE_ENUM_CONSTANT(KEY_ESCAPE);
- BIND_CORE_ENUM_CONSTANT(KEY_TAB);
- BIND_CORE_ENUM_CONSTANT(KEY_BACKTAB);
- BIND_CORE_ENUM_CONSTANT(KEY_BACKSPACE);
- BIND_CORE_ENUM_CONSTANT(KEY_ENTER);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_ENTER);
- BIND_CORE_ENUM_CONSTANT(KEY_INSERT);
- BIND_CORE_ENUM_CONSTANT(KEY_DELETE);
- BIND_CORE_ENUM_CONSTANT(KEY_PAUSE);
- BIND_CORE_ENUM_CONSTANT(KEY_PRINT);
- BIND_CORE_ENUM_CONSTANT(KEY_SYSREQ);
- BIND_CORE_ENUM_CONSTANT(KEY_CLEAR);
- BIND_CORE_ENUM_CONSTANT(KEY_HOME);
- BIND_CORE_ENUM_CONSTANT(KEY_END);
- BIND_CORE_ENUM_CONSTANT(KEY_LEFT);
- BIND_CORE_ENUM_CONSTANT(KEY_UP);
- BIND_CORE_ENUM_CONSTANT(KEY_RIGHT);
- BIND_CORE_ENUM_CONSTANT(KEY_DOWN);
- BIND_CORE_ENUM_CONSTANT(KEY_PAGEUP);
- BIND_CORE_ENUM_CONSTANT(KEY_PAGEDOWN);
- BIND_CORE_ENUM_CONSTANT(KEY_SHIFT);
- BIND_CORE_ENUM_CONSTANT(KEY_CTRL);
- BIND_CORE_ENUM_CONSTANT(KEY_META);
- BIND_CORE_ENUM_CONSTANT(KEY_ALT);
- BIND_CORE_ENUM_CONSTANT(KEY_CAPSLOCK);
- BIND_CORE_ENUM_CONSTANT(KEY_NUMLOCK);
- BIND_CORE_ENUM_CONSTANT(KEY_SCROLLLOCK);
- BIND_CORE_ENUM_CONSTANT(KEY_F1);
- BIND_CORE_ENUM_CONSTANT(KEY_F2);
- BIND_CORE_ENUM_CONSTANT(KEY_F3);
- BIND_CORE_ENUM_CONSTANT(KEY_F4);
- BIND_CORE_ENUM_CONSTANT(KEY_F5);
- BIND_CORE_ENUM_CONSTANT(KEY_F6);
- BIND_CORE_ENUM_CONSTANT(KEY_F7);
- BIND_CORE_ENUM_CONSTANT(KEY_F8);
- BIND_CORE_ENUM_CONSTANT(KEY_F9);
- BIND_CORE_ENUM_CONSTANT(KEY_F10);
- BIND_CORE_ENUM_CONSTANT(KEY_F11);
- BIND_CORE_ENUM_CONSTANT(KEY_F12);
- BIND_CORE_ENUM_CONSTANT(KEY_F13);
- BIND_CORE_ENUM_CONSTANT(KEY_F14);
- BIND_CORE_ENUM_CONSTANT(KEY_F15);
- BIND_CORE_ENUM_CONSTANT(KEY_F16);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_MULTIPLY);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_DIVIDE);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_SUBTRACT);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_PERIOD);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_ADD);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_0);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_1);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_2);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_3);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_4);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_5);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_6);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_7);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_8);
- BIND_CORE_ENUM_CONSTANT(KEY_KP_9);
- BIND_CORE_ENUM_CONSTANT(KEY_SUPER_L);
- BIND_CORE_ENUM_CONSTANT(KEY_SUPER_R);
- BIND_CORE_ENUM_CONSTANT(KEY_MENU);
- BIND_CORE_ENUM_CONSTANT(KEY_HYPER_L);
- BIND_CORE_ENUM_CONSTANT(KEY_HYPER_R);
- BIND_CORE_ENUM_CONSTANT(KEY_HELP);
- BIND_CORE_ENUM_CONSTANT(KEY_DIRECTION_L);
- BIND_CORE_ENUM_CONSTANT(KEY_DIRECTION_R);
- BIND_CORE_ENUM_CONSTANT(KEY_BACK);
- BIND_CORE_ENUM_CONSTANT(KEY_FORWARD);
- BIND_CORE_ENUM_CONSTANT(KEY_STOP);
- BIND_CORE_ENUM_CONSTANT(KEY_REFRESH);
- BIND_CORE_ENUM_CONSTANT(KEY_VOLUMEDOWN);
- BIND_CORE_ENUM_CONSTANT(KEY_VOLUMEMUTE);
- BIND_CORE_ENUM_CONSTANT(KEY_VOLUMEUP);
- BIND_CORE_ENUM_CONSTANT(KEY_BASSBOOST);
- BIND_CORE_ENUM_CONSTANT(KEY_BASSUP);
- BIND_CORE_ENUM_CONSTANT(KEY_BASSDOWN);
- BIND_CORE_ENUM_CONSTANT(KEY_TREBLEUP);
- BIND_CORE_ENUM_CONSTANT(KEY_TREBLEDOWN);
- BIND_CORE_ENUM_CONSTANT(KEY_MEDIAPLAY);
- BIND_CORE_ENUM_CONSTANT(KEY_MEDIASTOP);
- BIND_CORE_ENUM_CONSTANT(KEY_MEDIAPREVIOUS);
- BIND_CORE_ENUM_CONSTANT(KEY_MEDIANEXT);
- BIND_CORE_ENUM_CONSTANT(KEY_MEDIARECORD);
- BIND_CORE_ENUM_CONSTANT(KEY_HOMEPAGE);
- BIND_CORE_ENUM_CONSTANT(KEY_FAVORITES);
- BIND_CORE_ENUM_CONSTANT(KEY_SEARCH);
- BIND_CORE_ENUM_CONSTANT(KEY_STANDBY);
- BIND_CORE_ENUM_CONSTANT(KEY_OPENURL);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHMAIL);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHMEDIA);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH0);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH1);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH2);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH3);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH4);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH5);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH6);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH7);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH8);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH9);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHA);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHB);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHC);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHD);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHE);
- BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHF);
-
- BIND_CORE_ENUM_CONSTANT(KEY_UNKNOWN);
- BIND_CORE_ENUM_CONSTANT(KEY_SPACE);
- BIND_CORE_ENUM_CONSTANT(KEY_EXCLAM);
- BIND_CORE_ENUM_CONSTANT(KEY_QUOTEDBL);
- BIND_CORE_ENUM_CONSTANT(KEY_NUMBERSIGN);
- BIND_CORE_ENUM_CONSTANT(KEY_DOLLAR);
- BIND_CORE_ENUM_CONSTANT(KEY_PERCENT);
- BIND_CORE_ENUM_CONSTANT(KEY_AMPERSAND);
- BIND_CORE_ENUM_CONSTANT(KEY_APOSTROPHE);
- BIND_CORE_ENUM_CONSTANT(KEY_PARENLEFT);
- BIND_CORE_ENUM_CONSTANT(KEY_PARENRIGHT);
- BIND_CORE_ENUM_CONSTANT(KEY_ASTERISK);
- BIND_CORE_ENUM_CONSTANT(KEY_PLUS);
- BIND_CORE_ENUM_CONSTANT(KEY_COMMA);
- BIND_CORE_ENUM_CONSTANT(KEY_MINUS);
- BIND_CORE_ENUM_CONSTANT(KEY_PERIOD);
- BIND_CORE_ENUM_CONSTANT(KEY_SLASH);
- BIND_CORE_ENUM_CONSTANT(KEY_0);
- BIND_CORE_ENUM_CONSTANT(KEY_1);
- BIND_CORE_ENUM_CONSTANT(KEY_2);
- BIND_CORE_ENUM_CONSTANT(KEY_3);
- BIND_CORE_ENUM_CONSTANT(KEY_4);
- BIND_CORE_ENUM_CONSTANT(KEY_5);
- BIND_CORE_ENUM_CONSTANT(KEY_6);
- BIND_CORE_ENUM_CONSTANT(KEY_7);
- BIND_CORE_ENUM_CONSTANT(KEY_8);
- BIND_CORE_ENUM_CONSTANT(KEY_9);
- BIND_CORE_ENUM_CONSTANT(KEY_COLON);
- BIND_CORE_ENUM_CONSTANT(KEY_SEMICOLON);
- BIND_CORE_ENUM_CONSTANT(KEY_LESS);
- BIND_CORE_ENUM_CONSTANT(KEY_EQUAL);
- BIND_CORE_ENUM_CONSTANT(KEY_GREATER);
- BIND_CORE_ENUM_CONSTANT(KEY_QUESTION);
- BIND_CORE_ENUM_CONSTANT(KEY_AT);
- BIND_CORE_ENUM_CONSTANT(KEY_A);
- BIND_CORE_ENUM_CONSTANT(KEY_B);
- BIND_CORE_ENUM_CONSTANT(KEY_C);
- BIND_CORE_ENUM_CONSTANT(KEY_D);
- BIND_CORE_ENUM_CONSTANT(KEY_E);
- BIND_CORE_ENUM_CONSTANT(KEY_F);
- BIND_CORE_ENUM_CONSTANT(KEY_G);
- BIND_CORE_ENUM_CONSTANT(KEY_H);
- BIND_CORE_ENUM_CONSTANT(KEY_I);
- BIND_CORE_ENUM_CONSTANT(KEY_J);
- BIND_CORE_ENUM_CONSTANT(KEY_K);
- BIND_CORE_ENUM_CONSTANT(KEY_L);
- BIND_CORE_ENUM_CONSTANT(KEY_M);
- BIND_CORE_ENUM_CONSTANT(KEY_N);
- BIND_CORE_ENUM_CONSTANT(KEY_O);
- BIND_CORE_ENUM_CONSTANT(KEY_P);
- BIND_CORE_ENUM_CONSTANT(KEY_Q);
- BIND_CORE_ENUM_CONSTANT(KEY_R);
- BIND_CORE_ENUM_CONSTANT(KEY_S);
- BIND_CORE_ENUM_CONSTANT(KEY_T);
- BIND_CORE_ENUM_CONSTANT(KEY_U);
- BIND_CORE_ENUM_CONSTANT(KEY_V);
- BIND_CORE_ENUM_CONSTANT(KEY_W);
- BIND_CORE_ENUM_CONSTANT(KEY_X);
- BIND_CORE_ENUM_CONSTANT(KEY_Y);
- BIND_CORE_ENUM_CONSTANT(KEY_Z);
- BIND_CORE_ENUM_CONSTANT(KEY_BRACKETLEFT);
- BIND_CORE_ENUM_CONSTANT(KEY_BACKSLASH);
- BIND_CORE_ENUM_CONSTANT(KEY_BRACKETRIGHT);
- BIND_CORE_ENUM_CONSTANT(KEY_ASCIICIRCUM);
- BIND_CORE_ENUM_CONSTANT(KEY_UNDERSCORE);
- BIND_CORE_ENUM_CONSTANT(KEY_QUOTELEFT);
- BIND_CORE_ENUM_CONSTANT(KEY_BRACELEFT);
- BIND_CORE_ENUM_CONSTANT(KEY_BAR);
- BIND_CORE_ENUM_CONSTANT(KEY_BRACERIGHT);
- BIND_CORE_ENUM_CONSTANT(KEY_ASCIITILDE);
- BIND_CORE_ENUM_CONSTANT(KEY_NOBREAKSPACE);
- BIND_CORE_ENUM_CONSTANT(KEY_EXCLAMDOWN);
- BIND_CORE_ENUM_CONSTANT(KEY_CENT);
- BIND_CORE_ENUM_CONSTANT(KEY_STERLING);
- BIND_CORE_ENUM_CONSTANT(KEY_CURRENCY);
- BIND_CORE_ENUM_CONSTANT(KEY_YEN);
- BIND_CORE_ENUM_CONSTANT(KEY_BROKENBAR);
- BIND_CORE_ENUM_CONSTANT(KEY_SECTION);
- BIND_CORE_ENUM_CONSTANT(KEY_DIAERESIS);
- BIND_CORE_ENUM_CONSTANT(KEY_COPYRIGHT);
- BIND_CORE_ENUM_CONSTANT(KEY_ORDFEMININE);
- BIND_CORE_ENUM_CONSTANT(KEY_GUILLEMOTLEFT);
- BIND_CORE_ENUM_CONSTANT(KEY_NOTSIGN);
- BIND_CORE_ENUM_CONSTANT(KEY_HYPHEN);
- BIND_CORE_ENUM_CONSTANT(KEY_REGISTERED);
- BIND_CORE_ENUM_CONSTANT(KEY_MACRON);
- BIND_CORE_ENUM_CONSTANT(KEY_DEGREE);
- BIND_CORE_ENUM_CONSTANT(KEY_PLUSMINUS);
- BIND_CORE_ENUM_CONSTANT(KEY_TWOSUPERIOR);
- BIND_CORE_ENUM_CONSTANT(KEY_THREESUPERIOR);
- BIND_CORE_ENUM_CONSTANT(KEY_ACUTE);
- BIND_CORE_ENUM_CONSTANT(KEY_MU);
- BIND_CORE_ENUM_CONSTANT(KEY_PARAGRAPH);
- BIND_CORE_ENUM_CONSTANT(KEY_PERIODCENTERED);
- BIND_CORE_ENUM_CONSTANT(KEY_CEDILLA);
- BIND_CORE_ENUM_CONSTANT(KEY_ONESUPERIOR);
- BIND_CORE_ENUM_CONSTANT(KEY_MASCULINE);
- BIND_CORE_ENUM_CONSTANT(KEY_GUILLEMOTRIGHT);
- BIND_CORE_ENUM_CONSTANT(KEY_ONEQUARTER);
- BIND_CORE_ENUM_CONSTANT(KEY_ONEHALF);
- BIND_CORE_ENUM_CONSTANT(KEY_THREEQUARTERS);
- BIND_CORE_ENUM_CONSTANT(KEY_QUESTIONDOWN);
- BIND_CORE_ENUM_CONSTANT(KEY_AGRAVE);
- BIND_CORE_ENUM_CONSTANT(KEY_AACUTE);
- BIND_CORE_ENUM_CONSTANT(KEY_ACIRCUMFLEX);
- BIND_CORE_ENUM_CONSTANT(KEY_ATILDE);
- BIND_CORE_ENUM_CONSTANT(KEY_ADIAERESIS);
- BIND_CORE_ENUM_CONSTANT(KEY_ARING);
- BIND_CORE_ENUM_CONSTANT(KEY_AE);
- BIND_CORE_ENUM_CONSTANT(KEY_CCEDILLA);
- BIND_CORE_ENUM_CONSTANT(KEY_EGRAVE);
- BIND_CORE_ENUM_CONSTANT(KEY_EACUTE);
- BIND_CORE_ENUM_CONSTANT(KEY_ECIRCUMFLEX);
- BIND_CORE_ENUM_CONSTANT(KEY_EDIAERESIS);
- BIND_CORE_ENUM_CONSTANT(KEY_IGRAVE);
- BIND_CORE_ENUM_CONSTANT(KEY_IACUTE);
- BIND_CORE_ENUM_CONSTANT(KEY_ICIRCUMFLEX);
- BIND_CORE_ENUM_CONSTANT(KEY_IDIAERESIS);
- BIND_CORE_ENUM_CONSTANT(KEY_ETH);
- BIND_CORE_ENUM_CONSTANT(KEY_NTILDE);
- BIND_CORE_ENUM_CONSTANT(KEY_OGRAVE);
- BIND_CORE_ENUM_CONSTANT(KEY_OACUTE);
- BIND_CORE_ENUM_CONSTANT(KEY_OCIRCUMFLEX);
- BIND_CORE_ENUM_CONSTANT(KEY_OTILDE);
- BIND_CORE_ENUM_CONSTANT(KEY_ODIAERESIS);
- BIND_CORE_ENUM_CONSTANT(KEY_MULTIPLY);
- BIND_CORE_ENUM_CONSTANT(KEY_OOBLIQUE);
- BIND_CORE_ENUM_CONSTANT(KEY_UGRAVE);
- BIND_CORE_ENUM_CONSTANT(KEY_UACUTE);
- BIND_CORE_ENUM_CONSTANT(KEY_UCIRCUMFLEX);
- BIND_CORE_ENUM_CONSTANT(KEY_UDIAERESIS);
- BIND_CORE_ENUM_CONSTANT(KEY_YACUTE);
- BIND_CORE_ENUM_CONSTANT(KEY_THORN);
- BIND_CORE_ENUM_CONSTANT(KEY_SSHARP);
-
- BIND_CORE_ENUM_CONSTANT(KEY_DIVISION);
- BIND_CORE_ENUM_CONSTANT(KEY_YDIAERESIS);
-
- BIND_CORE_ENUM_CONSTANT(KEY_CODE_MASK);
- BIND_CORE_ENUM_CONSTANT(KEY_MODIFIER_MASK);
-
- BIND_CORE_ENUM_CONSTANT(KEY_MASK_SHIFT);
- BIND_CORE_ENUM_CONSTANT(KEY_MASK_ALT);
- BIND_CORE_ENUM_CONSTANT(KEY_MASK_META);
- BIND_CORE_ENUM_CONSTANT(KEY_MASK_CTRL);
- BIND_CORE_ENUM_CONSTANT_NO_VAL(KEY_MASK_CMD);
- BIND_CORE_ENUM_CONSTANT(KEY_MASK_KPAD);
- BIND_CORE_ENUM_CONSTANT(KEY_MASK_GROUP_SWITCH);
-
- // mouse
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_LEFT);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_RIGHT);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MIDDLE);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_XBUTTON1);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_XBUTTON2);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_UP);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_DOWN);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_LEFT);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_RIGHT);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_LEFT);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_RIGHT);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_MIDDLE);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_XBUTTON1);
- BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_XBUTTON2);
-
- // Joypad buttons
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_INVALID);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_A);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_B);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_X);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_Y);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_BACK);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_GUIDE);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_START);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_LEFT_STICK);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_RIGHT_STICK);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_LEFT_SHOULDER);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_RIGHT_SHOULDER);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_UP);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_DOWN);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_LEFT);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_RIGHT);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_MISC1);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE1);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE2);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE3);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE4);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_TOUCHPAD);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_SDL_MAX);
- BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_MAX);
-
- // Joypad axes
- BIND_CORE_ENUM_CONSTANT(JOY_AXIS_INVALID);
- BIND_CORE_ENUM_CONSTANT(JOY_AXIS_LEFT_X);
- BIND_CORE_ENUM_CONSTANT(JOY_AXIS_LEFT_Y);
- BIND_CORE_ENUM_CONSTANT(JOY_AXIS_RIGHT_X);
- BIND_CORE_ENUM_CONSTANT(JOY_AXIS_RIGHT_Y);
- BIND_CORE_ENUM_CONSTANT(JOY_AXIS_TRIGGER_LEFT);
- BIND_CORE_ENUM_CONSTANT(JOY_AXIS_TRIGGER_RIGHT);
- BIND_CORE_ENUM_CONSTANT(JOY_AXIS_SDL_MAX);
- BIND_CORE_ENUM_CONSTANT(JOY_AXIS_MAX);
-
- // midi
- BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_OFF);
- BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_ON);
- BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_AFTERTOUCH);
- BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_CONTROL_CHANGE);
- BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_PROGRAM_CHANGE);
- BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_CHANNEL_PRESSURE);
- BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_PITCH_BEND);
+ BIND_CORE_ENUM_CONSTANT(HORIZONTAL_ALIGNMENT_LEFT);
+ BIND_CORE_ENUM_CONSTANT(HORIZONTAL_ALIGNMENT_CENTER);
+ BIND_CORE_ENUM_CONSTANT(HORIZONTAL_ALIGNMENT_RIGHT);
+ BIND_CORE_ENUM_CONSTANT(HORIZONTAL_ALIGNMENT_FILL);
+
+ BIND_CORE_ENUM_CONSTANT(VERTICAL_ALIGNMENT_TOP);
+ BIND_CORE_ENUM_CONSTANT(VERTICAL_ALIGNMENT_CENTER);
+ BIND_CORE_ENUM_CONSTANT(VERTICAL_ALIGNMENT_BOTTOM);
+ BIND_CORE_ENUM_CONSTANT(VERTICAL_ALIGNMENT_FILL);
+
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TOP_TO);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_CENTER_TO);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_BOTTOM_TO);
+
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TO_TOP);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TO_CENTER);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TO_BASELINE);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TO_BOTTOM);
+
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TOP);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_CENTER);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_BOTTOM);
+
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SPECIAL);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ESCAPE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, TAB);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACKTAB);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACKSPACE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ENTER);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_ENTER);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, INSERT);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_DELETE, KEY_DELETE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PAUSE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PRINT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SYSREQ);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CLEAR);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HOME);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, END);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, RIGHT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DOWN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PAGEUP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PAGEDOWN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SHIFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CTRL);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, META);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ALT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CAPSLOCK);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NUMLOCK);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SCROLLLOCK);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F1);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F2);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F3);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F4);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F5);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F6);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F7);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F8);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F9);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F10);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F11);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F12);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F13);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F14);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F15);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F16);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_MULTIPLY);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_DIVIDE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_SUBTRACT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_PERIOD);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_ADD);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_0);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_1);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_2);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_3);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_4);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_5);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_6);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_7);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_8);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_9);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SUPER_L);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SUPER_R);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MENU);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HYPER_L);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HYPER_R);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HELP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DIRECTION_L);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DIRECTION_R);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACK);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, FORWARD);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, STOP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, REFRESH);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, VOLUMEDOWN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, VOLUMEMUTE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, VOLUMEUP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BASSBOOST);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BASSUP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BASSDOWN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, TREBLEUP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, TREBLEDOWN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIAPLAY);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIASTOP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIAPREVIOUS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIANEXT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIARECORD);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HOMEPAGE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, FAVORITES);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SEARCH);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, STANDBY);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OPENURL);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHMAIL);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHMEDIA);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH0);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH1);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH2);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH3);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH4);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH5);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH6);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH7);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH8);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH9);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHA);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHB);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHC);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHD);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHF);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UNKNOWN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SPACE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EXCLAM);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, QUOTEDBL);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NUMBERSIGN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DOLLAR);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PERCENT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AMPERSAND);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, APOSTROPHE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PARENLEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PARENRIGHT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ASTERISK);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PLUS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, COMMA);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MINUS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PERIOD);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SLASH);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_0, KEY_0);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_1, KEY_1);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_2, KEY_2);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_3, KEY_3);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_4, KEY_4);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_5, KEY_5);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_6, KEY_6);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_7, KEY_7);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_8, KEY_8);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_9, KEY_9);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, COLON);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SEMICOLON);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LESS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EQUAL);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, GREATER);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, QUESTION);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, A);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, B);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, C);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, D);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, E);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, G);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, H);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, I);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, J);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, K);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, L);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, M);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, N);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, O);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, P);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, Q);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, R);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, S);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, T);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, U);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, V);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, W);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, X);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, Y);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, Z);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACKETLEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACKSLASH);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACKETRIGHT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ASCIICIRCUM);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UNDERSCORE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, QUOTELEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACELEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BAR);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACERIGHT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ASCIITILDE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NOBREAKSPACE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EXCLAMDOWN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CENT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, STERLING);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CURRENCY);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, YEN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BROKENBAR);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SECTION);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DIAERESIS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, COPYRIGHT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ORDFEMININE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, GUILLEMOTLEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NOTSIGN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HYPHEN);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_REGISTERED, KEY_REGISTERED);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MACRON);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DEGREE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PLUSMINUS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, TWOSUPERIOR);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, THREESUPERIOR);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ACUTE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MU);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PARAGRAPH);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PERIODCENTERED);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CEDILLA);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ONESUPERIOR);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MASCULINE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, GUILLEMOTRIGHT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ONEQUARTER);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ONEHALF);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, THREEQUARTERS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, QUESTIONDOWN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AGRAVE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AACUTE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ACIRCUMFLEX);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ATILDE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ADIAERESIS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ARING);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CCEDILLA);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EGRAVE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EACUTE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ECIRCUMFLEX);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EDIAERESIS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, IGRAVE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, IACUTE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ICIRCUMFLEX);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, IDIAERESIS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ETH);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NTILDE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OGRAVE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OACUTE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OCIRCUMFLEX);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OTILDE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ODIAERESIS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MULTIPLY);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OOBLIQUE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UGRAVE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UACUTE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UCIRCUMFLEX);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UDIAERESIS);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, YACUTE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, THORN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SSHARP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DIVISION);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, YDIAERESIS);
+
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(KeyModifierMask, KEY_CODE_MASK, CODE_MASK);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(KeyModifierMask, KEY_MODIFIER_MASK, MODIFIER_MASK);
+ BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, SHIFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, ALT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, META);
+ BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, CTRL);
+ BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(KeyModifierMask, KEY_MASK, CMD);
+ BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, KPAD);
+ BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, GROUP_SWITCH);
+
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, LEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, RIGHT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MIDDLE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_UP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_DOWN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_LEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_RIGHT);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(MouseButton, MOUSE_BUTTON_XBUTTON1, MB_XBUTTON1);
+ BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(MouseButton, MOUSE_BUTTON_XBUTTON2, MB_XBUTTON2);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_LEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_RIGHT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_MIDDLE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_XBUTTON1);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_XBUTTON2);
+
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, INVALID);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, A);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, B);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, X);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, Y);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, BACK);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, GUIDE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, START);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, LEFT_STICK);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, RIGHT_STICK);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, LEFT_SHOULDER);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, RIGHT_SHOULDER);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_UP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_DOWN);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_LEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_RIGHT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC1);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE1);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE2);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE3);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE4);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, TOUCHPAD);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, SDL_MAX);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MAX);
+
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, INVALID);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, LEFT_X);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, LEFT_Y);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, RIGHT_X);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, RIGHT_Y);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, TRIGGER_LEFT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, TRIGGER_RIGHT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, SDL_MAX);
+ BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, MAX);
+
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NOTE_OFF);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NOTE_ON);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, AFTERTOUCH);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, CONTROL_CHANGE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, PROGRAM_CHANGE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, CHANNEL_PRESSURE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, PITCH_BEND);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SYSTEM_EXCLUSIVE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, QUARTER_FRAME);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SONG_POSITION_POINTER);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SONG_SELECT);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, TUNE_REQUEST);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, TIMING_CLOCK);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, START);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, CONTINUE);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, STOP);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, ACTIVE_SENSING);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SYSTEM_RESET);
// error list
@@ -598,7 +621,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT_INTL);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NOEDITOR);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NO_EDITOR);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_NORMAL);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_EDITOR);
@@ -613,11 +636,11 @@ void register_global_constants() {
// rpc
BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_DISABLED", Multiplayer::RPC_MODE_DISABLED);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_ANY", Multiplayer::RPC_MODE_ANY);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_ANY_PEER", Multiplayer::RPC_MODE_ANY_PEER);
BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_AUTH", Multiplayer::RPC_MODE_AUTHORITY);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_UNRELIABLE", Multiplayer::TRANSFER_MODE_UNRELIABLE);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_ORDERED", Multiplayer::TRANSFER_MODE_ORDERED);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_UNRELIABLE_ORDERED", Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_RELIABLE", Multiplayer::TRANSFER_MODE_RELIABLE);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL);
@@ -646,15 +669,15 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_SIGNAL", Variant::SIGNAL);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_DICTIONARY", Variant::DICTIONARY);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_ARRAY", Variant::ARRAY);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_RAW_ARRAY", Variant::PACKED_BYTE_ARRAY);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_INT32_ARRAY", Variant::PACKED_INT32_ARRAY);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_INT64_ARRAY", Variant::PACKED_INT64_ARRAY);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_FLOAT32_ARRAY", Variant::PACKED_FLOAT32_ARRAY);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_FLOAT64_ARRAY", Variant::PACKED_FLOAT64_ARRAY);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_STRING_ARRAY", Variant::PACKED_STRING_ARRAY);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR2_ARRAY", Variant::PACKED_VECTOR2_ARRAY);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3_ARRAY", Variant::PACKED_VECTOR3_ARRAY);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_COLOR_ARRAY", Variant::PACKED_COLOR_ARRAY);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_BYTE_ARRAY", Variant::PACKED_BYTE_ARRAY);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_INT32_ARRAY", Variant::PACKED_INT32_ARRAY);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_INT64_ARRAY", Variant::PACKED_INT64_ARRAY);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_FLOAT32_ARRAY", Variant::PACKED_FLOAT32_ARRAY);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_FLOAT64_ARRAY", Variant::PACKED_FLOAT64_ARRAY);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_STRING_ARRAY", Variant::PACKED_STRING_ARRAY);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_VECTOR2_ARRAY", Variant::PACKED_VECTOR2_ARRAY);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_VECTOR3_ARRAY", Variant::PACKED_VECTOR3_ARRAY);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_COLOR_ARRAY", Variant::PACKED_COLOR_ARRAY);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_MAX", Variant::VARIANT_MAX);
//comparison
diff --git a/core/core_constants.h b/core/core_constants.h
index deaf9ec60f..9302c23959 100644
--- a/core/core_constants.h
+++ b/core/core_constants.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/core_string_names.cpp b/core/core_string_names.cpp
index ff8569e45d..5b5bfaecb5 100644
--- a/core/core_string_names.cpp
+++ b/core/core_string_names.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/core_string_names.h b/core/core_string_names.h
index abe751372e..2cd4e335b2 100644
--- a/core/core_string_names.h
+++ b/core/core_string_names.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/crypto/SCsub b/core/crypto/SCsub
index 4f3104d84b..1fe2fa5b23 100644
--- a/core/crypto/SCsub
+++ b/core/crypto/SCsub
@@ -30,6 +30,7 @@ if not has_module:
thirdparty_mbedtls_sources = [
"aes.c",
"base64.c",
+ "constant_time.c",
"md5.c",
"sha1.c",
"sha256.c",
diff --git a/core/crypto/aes_context.cpp b/core/crypto/aes_context.cpp
index b387aeb27d..8ff4f6a34c 100644
--- a/core/crypto/aes_context.cpp
+++ b/core/crypto/aes_context.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/crypto/aes_context.h b/core/crypto/aes_context.h
index 2f8422f537..2121adfcc6 100644
--- a/core/crypto/aes_context.h
+++ b/core/crypto/aes_context.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp
index fe913549c9..f62d2cce1f 100644
--- a/core/crypto/crypto.cpp
+++ b/core/crypto/crypto.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h
index a46f42949d..9de2c16fbc 100644
--- a/core/crypto/crypto.h
+++ b/core/crypto/crypto.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/crypto/crypto_core.cpp b/core/crypto/crypto_core.cpp
index f90092056e..9f000c5aeb 100644
--- a/core/crypto/crypto_core.cpp
+++ b/core/crypto/crypto_core.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/crypto/crypto_core.h b/core/crypto/crypto_core.h
index 7a2f4df589..355f4a2404 100644
--- a/core/crypto/crypto_core.h
+++ b/core/crypto/crypto_core.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/crypto/hashing_context.cpp b/core/crypto/hashing_context.cpp
index 070d2d4dd7..2ff540f798 100644
--- a/core/crypto/hashing_context.cpp
+++ b/core/crypto/hashing_context.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/crypto/hashing_context.h b/core/crypto/hashing_context.h
index 31521a147c..1a7cabf0f1 100644
--- a/core/crypto/hashing_context.h
+++ b/core/crypto/hashing_context.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/debugger/debugger_marshalls.cpp b/core/debugger/debugger_marshalls.cpp
index 2353a6ebf8..1a746d59a3 100644
--- a/core/debugger/debugger_marshalls.cpp
+++ b/core/debugger/debugger_marshalls.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/debugger/debugger_marshalls.h b/core/debugger/debugger_marshalls.h
index 98ad2b98d1..fae766812a 100644
--- a/core/debugger/debugger_marshalls.h
+++ b/core/debugger/debugger_marshalls.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp
index a522b1310f..54760d8d65 100644
--- a/core/debugger/engine_debugger.cpp
+++ b/core/debugger/engine_debugger.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -123,8 +123,8 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks,
physics_time = USEC_TO_SEC(p_physics_ticks);
physics_frame_time = p_physics_frame_time;
// Notify tick to running profilers
- for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) {
- Profiler &p = E->get();
+ for (KeyValue<StringName, Profiler> &E : profilers) {
+ Profiler &p = E.value;
if (!p.active || !p.tick) {
continue;
}
@@ -179,9 +179,9 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Ve
void EngineDebugger::deinitialize() {
if (singleton) {
// Stop all profilers
- for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) {
- if (E->get().active) {
- singleton->profiler_enable(E->key(), false);
+ for (const KeyValue<StringName, Profiler> &E : profilers) {
+ if (E.value.active) {
+ singleton->profiler_enable(E.key, false);
}
}
diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h
index 22c6ef943e..fdfa41c9cc 100644
--- a/core/debugger/engine_debugger.h
+++ b/core/debugger/engine_debugger.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -128,7 +128,7 @@ public:
virtual void poll_events(bool p_is_idle) {}
virtual void send_message(const String &p_msg, const Array &p_data) = 0;
- virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) = 0;
+ virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) = 0;
virtual void debug(bool p_can_continue = true, bool p_is_error_breakpoint = false) = 0;
virtual ~EngineDebugger();
diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp
index b0b3f11424..61d75a6a0d 100644
--- a/core/debugger/local_debugger.cpp
+++ b/core/debugger/local_debugger.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -139,7 +139,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
// Cache options
String variable_prefix = options["variable_prefix"];
- if (line == "") {
+ if (line.is_empty()) {
print_line("\nDebugger Break, Reason: '" + script_lang->debug_get_error() + "'");
print_line("*Frame " + itos(current_frame) + " - " + script_lang->debug_get_stack_level_source(current_frame) + ":" + itos(script_lang->debug_get_stack_level_line(current_frame)) + " in function '" + script_lang->debug_get_stack_level_function(current_frame) + "'");
print_line("Enter \"help\" for assistance.");
@@ -166,8 +166,8 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
} else if (line.begins_with("set")) {
if (line.get_slice_count(" ") == 1) {
- for (Map<String, String>::Element *E = options.front(); E; E = E->next()) {
- print_line("\t" + E->key() + "=" + E->value());
+ for (const KeyValue<String, String> &E : options) {
+ print_line("\t" + E.key + "=" + E.value);
}
} else {
@@ -249,8 +249,8 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
}
print_line("Breakpoint(s): " + itos(breakpoints.size()));
- for (Map<int, Set<StringName>>::Element *E = breakpoints.front(); E; E = E->next()) {
- print_line("\t" + String(E->value().front()->get()) + ":" + itos(E->key()));
+ for (const KeyValue<int, Set<StringName>> &E : breakpoints) {
+ print_line("\t" + String(E.value.front()->get()) + ":" + itos(E.key));
}
} else {
@@ -358,7 +358,7 @@ void LocalDebugger::send_message(const String &p_message, const Array &p_args) {
// print_line("MESSAGE: '" + p_message + "' - " + String(Variant(p_args)));
}
-void LocalDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) {
+void LocalDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) {
print_line("ERROR: '" + (p_descr.is_empty() ? p_err : p_descr) + "'");
}
diff --git a/core/debugger/local_debugger.h b/core/debugger/local_debugger.h
index e793b2a859..ecd805a6cb 100644
--- a/core/debugger/local_debugger.h
+++ b/core/debugger/local_debugger.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -50,7 +50,7 @@ private:
public:
void debug(bool p_can_continue, bool p_is_error_breakpoint);
void send_message(const String &p_message, const Array &p_args);
- void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type);
+ void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type);
LocalDebugger();
~LocalDebugger();
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index f865dfe102..339aa9b61f 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -79,8 +79,8 @@ public:
ERR_FAIL_COND_V(p_buffer.size() == 0, 0);
int total_bandwidth = 0;
- uint32_t timestamp = OS::get_singleton()->get_ticks_msec();
- uint32_t final_timestamp = timestamp - 1000;
+ uint64_t timestamp = OS::get_singleton()->get_ticks_msec();
+ uint64_t final_timestamp = timestamp - 1000;
int i = (p_pointer + p_buffer.size() - 1) % p_buffer.size();
@@ -179,8 +179,8 @@ public:
if (pt - last_profile_time > 100) {
last_profile_time = pt;
DebuggerMarshalls::NetworkProfilerFrame frame;
- for (Map<ObjectID, NodeInfo>::Element *E = multiplayer_node_data.front(); E; E = E->next()) {
- frame.infos.push_back(E->get());
+ for (const KeyValue<ObjectID, NodeInfo> &E : multiplayer_node_data) {
+ frame.infos.push_back(E.value);
}
multiplayer_node_data.clear();
EngineDebugger::get_singleton()->send_message("network:profile_frame", frame.serialize());
@@ -455,7 +455,7 @@ Error RemoteDebugger::_put_msg(String p_message, Array p_data) {
return err;
}
-void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, ErrorHandlerType p_type) {
+void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, bool p_editor_notify, ErrorHandlerType p_type) {
if (p_type == ERR_HANDLER_SCRIPT) {
return; //ignore script errors, those go through debugger
}
@@ -475,7 +475,7 @@ void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *
}
// send_error will lock internally.
- rd->script_debugger->send_error(p_func, p_file, p_line, p_err, p_descr, p_type, si);
+ rd->script_debugger->send_error(String::utf8(p_func), String::utf8(p_file), p_line, String::utf8(p_err), String::utf8(p_descr), p_editor_notify, p_type, si);
}
void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p_error) {
@@ -605,7 +605,7 @@ void RemoteDebugger::send_message(const String &p_message, const Array &p_args)
}
}
-void RemoteDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) {
+void RemoteDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) {
ErrorMessage oe;
oe.error = p_err;
oe.error_descr = p_descr;
diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h
index 28e670747e..bd64955c89 100644
--- a/core/debugger/remote_debugger.h
+++ b/core/debugger/remote_debugger.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -89,7 +89,7 @@ private:
PrintHandlerList phl;
static void _print_handler(void *p_this, const String &p_string, bool p_error);
ErrorHandlerList eh;
- static void _err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, ErrorHandlerType p_type);
+ static void _err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, bool p_editor_notify, ErrorHandlerType p_type);
ErrorMessage _create_overflow_error(const String &p_what, const String &p_descr);
Error _put_msg(String p_message, Array p_data);
@@ -111,7 +111,7 @@ public:
// Overrides
void poll_events(bool p_is_idle);
void send_message(const String &p_message, const Array &p_args);
- void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type);
+ void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type);
void debug(bool p_can_continue = true, bool p_is_error_breakpoint = false);
RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer);
diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp
index ea5e32203c..a45430465f 100644
--- a/core/debugger/remote_debugger_peer.cpp
+++ b/core/debugger/remote_debugger_peer.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/debugger/remote_debugger_peer.h b/core/debugger/remote_debugger_peer.h
index 8cba53a81c..010336ffd3 100644
--- a/core/debugger/remote_debugger_peer.h
+++ b/core/debugger/remote_debugger_peer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/debugger/script_debugger.cpp b/core/debugger/script_debugger.cpp
index 6d1e4ed101..36723e5568 100644
--- a/core/debugger/script_debugger.cpp
+++ b/core/debugger/script_debugger.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -100,10 +100,10 @@ void ScriptDebugger::debug(ScriptLanguage *p_lang, bool p_can_continue, bool p_i
break_lang = prev;
}
-void ScriptDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info) {
+void ScriptDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info) {
// Store stack info, this is ugly, but allows us to separate EngineDebugger and ScriptDebugger. There might be a better way.
error_stack_info.append_array(p_stack_info);
- EngineDebugger::get_singleton()->send_error(p_func, p_file, p_line, p_err, p_descr, p_type);
+ EngineDebugger::get_singleton()->send_error(p_func, p_file, p_line, p_err, p_descr, p_editor_notify, p_type);
error_stack_info.resize(0);
}
diff --git a/core/debugger/script_debugger.h b/core/debugger/script_debugger.h
index 9f034a5e5d..feb6702b54 100644
--- a/core/debugger/script_debugger.h
+++ b/core/debugger/script_debugger.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -71,7 +71,7 @@ public:
void debug(ScriptLanguage *p_lang, bool p_can_continue = true, bool p_is_error_breakpoint = false);
ScriptLanguage *get_break_language() const;
- void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info);
+ void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info);
Vector<StackInfo> get_error_stack_info() const;
ScriptDebugger() {}
};
diff --git a/core/doc_data.cpp b/core/doc_data.cpp
index 4b284a30aa..1e72ad1090 100644
--- a/core/doc_data.cpp
+++ b/core/doc_data.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,7 +33,7 @@
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;
- if (p_method.return_type == "") {
+ if (p_method.return_type.is_empty()) {
p_method.return_type = "void*";
} else {
p_method.return_type += "*";
@@ -64,7 +64,7 @@ void DocData::argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const
if (p_arginfo.type == Variant::INT && p_arginfo.hint == PROPERTY_HINT_INT_IS_POINTER) {
p_argument.type = p_arginfo.hint_string;
- if (p_argument.type == "") {
+ if (p_argument.type.is_empty()) {
p_argument.type = "void*";
} else {
p_argument.type += "*";
diff --git a/core/doc_data.h b/core/doc_data.h
index 19dec71927..9286b843be 100644
--- a/core/doc_data.h
+++ b/core/doc_data.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -70,18 +70,29 @@ public:
Vector<int> errors_returned;
bool operator<(const MethodDoc &p_method) const {
if (name == p_method.name) {
- // Must be a constructor since there is no overloading.
- // We want this arbitrary order for a class "Foo":
- // - 1. Default constructor: Foo()
- // - 2. Copy constructor: Foo(Foo)
- // - 3+. Other constructors Foo(Bar, ...) based on first argument's name
- if (arguments.size() == 0 || p_method.arguments.size() == 0) { // 1.
+ // Must be an operator or a constructor since there is no other overloading
+ if (name.left(8) == "operator") {
+ if (arguments.size() == p_method.arguments.size()) {
+ if (arguments.size() == 0) {
+ return false;
+ }
+ return arguments[0].type < p_method.arguments[0].type;
+ }
return arguments.size() < p_method.arguments.size();
+ } else {
+ // Must be a constructor
+ // We want this arbitrary order for a class "Foo":
+ // - 1. Default constructor: Foo()
+ // - 2. Copy constructor: Foo(Foo)
+ // - 3+. Other constructors Foo(Bar, ...) based on first argument's name
+ if (arguments.size() == 0 || p_method.arguments.size() == 0) { // 1.
+ return arguments.size() < p_method.arguments.size();
+ }
+ if (arguments[0].type == return_type || p_method.arguments[0].type == p_method.return_type) { // 2.
+ return (arguments[0].type == return_type) || (p_method.arguments[0].type != p_method.return_type);
+ }
+ return arguments[0] < p_method.arguments[0];
}
- if (arguments[0].type == return_type || p_method.arguments[0].type == p_method.return_type) { // 2.
- return (arguments[0].type == return_type) || (p_method.arguments[0].type != p_method.return_type);
- }
- return arguments[0] < p_method.arguments[0];
}
return name < p_method.name;
}
@@ -112,6 +123,7 @@ public:
String setter, getter;
String default_value;
bool overridden = false;
+ String overrides;
bool operator<(const PropertyDoc &p_prop) const {
return name < p_prop.name;
}
@@ -124,7 +136,11 @@ public:
String description;
String default_value;
bool operator<(const ThemeItemDoc &p_theme_item) const {
- return name < p_theme_item.name;
+ // First sort by the data type, then by name.
+ if (data_type == p_theme_item.data_type) {
+ return name < p_theme_item.name;
+ }
+ return data_type < p_theme_item.data_type;
}
};
@@ -140,7 +156,9 @@ public:
String brief_description;
String description;
Vector<TutorialDoc> tutorials;
+ Vector<MethodDoc> constructors;
Vector<MethodDoc> methods;
+ Vector<MethodDoc> operators;
Vector<MethodDoc> signals;
Vector<ConstantDoc> constants;
Map<String, String> enums;
diff --git a/core/error/error_list.cpp b/core/error/error_list.cpp
index e1e94dd65d..b669e2c042 100644
--- a/core/error/error_list.cpp
+++ b/core/error/error_list.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/error/error_list.h b/core/error/error_list.h
index 852825dda5..b057ef5941 100644
--- a/core/error/error_list.h
+++ b/core/error/error_list.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/error/error_macros.cpp b/core/error/error_macros.cpp
index 272dda97d8..928ddd3397 100644
--- a/core/error/error_macros.cpp
+++ b/core/error/error_macros.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,9 +37,16 @@
static ErrorHandlerList *error_handler_list = nullptr;
void add_error_handler(ErrorHandlerList *p_handler) {
+ // If p_handler is already in error_handler_list
+ // we'd better remove it first then we can add it.
+ // This prevent cyclic redundancy.
+ remove_error_handler(p_handler);
+
_global_lock();
+
p_handler->next = error_handler_list;
error_handler_list = p_handler;
+
_global_unlock();
}
@@ -65,45 +72,49 @@ void remove_error_handler(ErrorHandlerList *p_handler) {
_global_unlock();
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type) {
- _err_print_error(p_function, p_file, p_line, p_error, "", p_type);
+// Errors without messages.
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify, ErrorHandlerType p_type) {
+ _err_print_error(p_function, p_file, p_line, p_error, "", p_editor_notify, p_type);
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, ErrorHandlerType p_type) {
- _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), "", p_type);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify, ErrorHandlerType p_type) {
+ _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), "", p_editor_notify, p_type);
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, ErrorHandlerType p_type) {
- OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, (Logger::ErrorType)p_type);
+// Main error printing function.
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) {
+ OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, p_editor_notify, (Logger::ErrorType)p_type);
_global_lock();
ErrorHandlerList *l = error_handler_list;
while (l) {
- l->errfunc(l->userdata, p_function, p_file, p_line, p_error, p_message, p_type);
+ l->errfunc(l->userdata, p_function, p_file, p_line, p_error, p_message, p_editor_notify, p_type);
l = l->next;
}
_global_unlock();
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, ErrorHandlerType p_type) {
- _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_type);
+// Errors with message. (All combinations of p_error and p_message as String or char*.)
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) {
+ _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_editor_notify, p_type);
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, ErrorHandlerType p_type) {
- _err_print_error(p_function, p_file, p_line, p_error, p_message.utf8().get_data(), p_type);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify, ErrorHandlerType p_type) {
+ _err_print_error(p_function, p_file, p_line, p_error, p_message.utf8().get_data(), p_editor_notify, p_type);
}
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, ErrorHandlerType p_type) {
- _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message.utf8().get_data(), p_type);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify, ErrorHandlerType p_type) {
+ _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message.utf8().get_data(), p_editor_notify, p_type);
}
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool fatal) {
- String fstr(fatal ? "FATAL: " : "");
+// Index errors. (All combinations of p_message as String or char*.)
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool p_editor_notify, bool p_fatal) {
+ String fstr(p_fatal ? "FATAL: " : "");
String err(fstr + "Index " + p_index_str + " = " + itos(p_index) + " is out of bounds (" + p_size_str + " = " + itos(p_size) + ").");
_err_print_error(p_function, p_file, p_line, err.utf8().get_data(), p_message);
}
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool fatal) {
- _err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), fatal);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify, bool p_fatal) {
+ _err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), p_fatal);
}
diff --git a/core/error/error_macros.h b/core/error/error_macros.h
index f909a67d55..802d7f9ef4 100644
--- a/core/error/error_macros.h
+++ b/core/error/error_macros.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,7 +46,7 @@ enum ErrorHandlerType {
// Pointer to the error handler printing function. Reassign to any function to have errors printed.
// Parameters: userdata, function, file, line, error, explanation, type.
-typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, ErrorHandlerType p_type);
+typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, bool p_editor_notify, ErrorHandlerType p_type);
struct ErrorHandlerList {
ErrorHandlerFunc errfunc = nullptr;
@@ -61,14 +61,14 @@ void add_error_handler(ErrorHandlerList *p_handler);
void remove_error_handler(ErrorHandlerList *p_handler);
// Functions used by the error macros.
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool fatal = false);
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool fatal = false);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool p_editor_notify = false, bool fatal = false);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool fatal = false);
#ifdef __GNUC__
//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
@@ -89,13 +89,6 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
#define GENERATE_TRAP() __builtin_trap()
#endif
-// Used to strip debug messages in release mode
-#ifdef DEBUG_ENABLED
-#define DEBUG_STR(m_msg) m_msg
-#else
-#define DEBUG_STR(m_msg) ""
-#endif
-
/**
* Error macros.
* WARNING: These macros work in the opposite way to assert().
@@ -135,11 +128,22 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
* If not, prints `m_msg` and the current function returns.
*/
-#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \
- if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
- _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
- return; \
- } else \
+#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
+ return; \
+ } else \
+ ((void)0)
+
+/**
+ * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
+ * If not, prints `m_msg`, notifies in the editor, and the current function returns.
+ */
+#define ERR_FAIL_INDEX_EDMSG(m_index, m_size, m_msg) \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+ return; \
+ } else \
((void)0)
/**
@@ -160,11 +164,22 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
* If not, prints `m_msg` and the current function returns `m_retval`.
*/
-#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
- if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
- _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
- return m_retval; \
- } else \
+#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
+ return m_retval; \
+ } else \
+ ((void)0)
+
+/**
+ * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
+ * If not, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+ return m_retval; \
+ } else \
((void)0)
/**
@@ -189,11 +204,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
* If not, prints `m_msg` and the application crashes.
*/
-#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \
- if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
- _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \
- GENERATE_TRAP(); \
- } else \
+#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+ GENERATE_TRAP(); \
+ } else \
((void)0)
// Unsigned integer index out of bounds error macros.
@@ -216,11 +231,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures an unsigned integer index `m_index` is less than `m_size`.
* If not, prints `m_msg` and the current function returns.
*/
-#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
- if (unlikely((m_index) >= (m_size))) { \
- _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
- return; \
- } else \
+#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
+ if (unlikely((m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
+ return; \
+ } else \
+ ((void)0)
+/**
+ * Ensures an unsigned integer index `m_index` is less than `m_size`.
+ * If not, prints `m_msg`, notifies in the editor, and the current function returns.
+ */
+#define ERR_FAIL_UNSIGNED_INDEX_EDMSG(m_index, m_size, m_msg) \
+ if (unlikely((m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+ return; \
+ } else \
((void)0)
/**
@@ -241,11 +266,22 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures an unsigned integer index `m_index` is less than `m_size`.
* If not, prints `m_msg` and the current function returns `m_retval`.
*/
-#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
- if (unlikely((m_index) >= (m_size))) { \
- _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
- return m_retval; \
- } else \
+#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
+ if (unlikely((m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
+ return m_retval; \
+ } else \
+ ((void)0)
+
+/**
+ * Ensures an unsigned integer index `m_index` is less than `m_size`.
+ * If not, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_UNSIGNED_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
+ if (unlikely((m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+ return m_retval; \
+ } else \
((void)0)
/**
@@ -270,11 +306,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures an unsigned integer index `m_index` is less than `m_size`.
* If not, prints `m_msg` and the application crashes.
*/
-#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
- if (unlikely((m_index) >= (m_size))) { \
- _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \
- GENERATE_TRAP(); \
- } else \
+#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
+ if (unlikely((m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+ GENERATE_TRAP(); \
+ } else \
((void)0)
// Null reference error macros.
@@ -297,11 +333,22 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures a pointer `m_param` is not null.
* If it is null, prints `m_msg` and the current function returns.
*/
-#define ERR_FAIL_NULL_MSG(m_param, m_msg) \
- if (unlikely(m_param == nullptr)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \
- return; \
- } else \
+#define ERR_FAIL_NULL_MSG(m_param, m_msg) \
+ if (unlikely(m_param == nullptr)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
+ return; \
+ } else \
+ ((void)0)
+
+/**
+ * Ensures a pointer `m_param` is not null.
+ * If it is null, prints `m_msg`, notifies in the editor, and the current function returns.
+ */
+#define ERR_FAIL_NULL_EDMSG(m_param, m_msg) \
+ if (unlikely(m_param == nullptr)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
+ return; \
+ } else \
((void)0)
/**
@@ -322,11 +369,22 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures a pointer `m_param` is not null.
* If it is null, prints `m_msg` and the current function returns `m_retval`.
*/
-#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \
- if (unlikely(m_param == nullptr)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \
- return m_retval; \
- } else \
+#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \
+ if (unlikely(m_param == nullptr)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
+ return m_retval; \
+ } else \
+ ((void)0)
+
+/**
+ * Ensures a pointer `m_param` is not null.
+ * If it is null, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_NULL_V_EDMSG(m_param, m_retval, m_msg) \
+ if (unlikely(m_param == nullptr)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
+ return m_retval; \
+ } else \
((void)0)
/**
@@ -352,11 +410,25 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* If checking for null use ERR_FAIL_NULL_MSG instead.
* If checking index bounds use ERR_FAIL_INDEX_MSG instead.
*/
-#define ERR_FAIL_COND_MSG(m_cond, m_msg) \
- if (unlikely(m_cond)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \
- return; \
- } else \
+#define ERR_FAIL_COND_MSG(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg); \
+ return; \
+ } else \
+ ((void)0)
+
+/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current function returns.
+ *
+ * If checking for null use ERR_FAIL_NULL_MSG instead.
+ * If checking index bounds use ERR_FAIL_INDEX_MSG instead.
+ */
+#define ERR_FAIL_COND_EDMSG(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg, true); \
+ return; \
+ } else \
((void)0)
/**
@@ -382,11 +454,25 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* If checking for null use ERR_FAIL_NULL_V_MSG instead.
* If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
*/
-#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
- if (unlikely(m_cond)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \
- return m_retval; \
- } else \
+#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg); \
+ return m_retval; \
+ } else \
+ ((void)0)
+
+/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`.
+ *
+ * If checking for null use ERR_FAIL_NULL_V_MSG instead.
+ * If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
+ */
+#define ERR_FAIL_COND_V_EDMSG(m_cond, m_retval, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg, true); \
+ return m_retval; \
+ } else \
((void)0)
/**
@@ -407,11 +493,22 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures `m_cond` is false.
* If `m_cond` is true, prints `m_msg` and the current loop continues.
*/
-#define ERR_CONTINUE_MSG(m_cond, m_msg) \
- if (unlikely(m_cond)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", DEBUG_STR(m_msg)); \
- continue; \
- } else \
+#define ERR_CONTINUE_MSG(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg); \
+ continue; \
+ } else \
+ ((void)0)
+
+/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current loop continues.
+ */
+#define ERR_CONTINUE_EDMSG(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg, true); \
+ continue; \
+ } else \
((void)0)
/**
@@ -432,11 +529,22 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures `m_cond` is false.
* If `m_cond` is true, prints `m_msg` and the current loop breaks.
*/
-#define ERR_BREAK_MSG(m_cond, m_msg) \
- if (unlikely(m_cond)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", DEBUG_STR(m_msg)); \
- break; \
- } else \
+#define ERR_BREAK_MSG(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg); \
+ break; \
+ } else \
+ ((void)0)
+
+/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current loop breaks.
+ */
+#define ERR_BREAK_EDMSG(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg, true); \
+ break; \
+ } else \
((void)0)
/**
@@ -461,11 +569,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures `m_cond` is false.
* If `m_cond` is true, prints `m_msg` and the application crashes.
*/
-#define CRASH_COND_MSG(m_cond, m_msg) \
- if (unlikely(m_cond)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \
- GENERATE_TRAP(); \
- } else \
+#define CRASH_COND_MSG(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", m_msg); \
+ GENERATE_TRAP(); \
+ } else \
((void)0)
// Generic error macros.
@@ -490,11 +598,24 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
*
* Prints `m_msg`, and the current function returns.
*/
-#define ERR_FAIL_MSG(m_msg) \
- if (true) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", DEBUG_STR(m_msg)); \
- return; \
- } else \
+#define ERR_FAIL_MSG(m_msg) \
+ if (true) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg); \
+ return; \
+ } else \
+ ((void)0)
+
+/**
+ * Try using `ERR_FAIL_COND_MSG`.
+ * Only use this macro if more complex error detection or recovery is required.
+ *
+ * Prints `m_msg`, notifies in the editor, and the current function returns.
+ */
+#define ERR_FAIL_EDMSG(m_msg) \
+ if (true) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg, true); \
+ return; \
+ } else \
((void)0)
/**
@@ -517,11 +638,24 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
*
* Prints `m_msg`, and the current function returns `m_retval`.
*/
-#define ERR_FAIL_V_MSG(m_retval, m_msg) \
- if (true) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \
- return m_retval; \
- } else \
+#define ERR_FAIL_V_MSG(m_retval, m_msg) \
+ if (true) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg); \
+ return m_retval; \
+ } else \
+ ((void)0)
+
+/**
+ * Try using `ERR_FAIL_COND_V_MSG`.
+ * Only use this macro if more complex error detection or recovery is required.
+ *
+ * Prints `m_msg`, notifies in the editor, and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_V_EDMSG(m_retval, m_msg) \
+ if (true) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg, true); \
+ return m_retval; \
+ } else \
((void)0)
/**
@@ -535,6 +669,16 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg)
/**
+ * Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or ERR_BREAK_MSG.
+ * Only use this macro at the start of a function that has not been implemented yet, or
+ * if more complex error detection or recovery is required.
+ *
+ * Prints `m_msg` and notifies the editor.
+ */
+#define ERR_PRINT_ED(m_msg) \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, )
+
+/**
* Prints `m_msg` once during the application lifetime.
*/
#define ERR_PRINT_ONCE(m_msg) \
@@ -547,6 +691,19 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
} else \
((void)0)
+/**
+ * Prints `m_msg` and notifies the editor once during the application lifetime.
+ */
+#define ERR_PRINT_ONCE_ED(m_msg) \
+ if (true) { \
+ static bool first_print = true; \
+ if (first_print) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true); \
+ first_print = false; \
+ } \
+ } else \
+ ((void)0)
+
// Print warning message macros.
/**
@@ -555,21 +712,44 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
*/
#define WARN_PRINT(m_msg) \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING)
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING)
+
+/**
+ * Prints `m_msg` and notifies the editor.
+ *
+ * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
+ */
+#define WARN_PRINT_ED(m_msg) \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING)
/**
* Prints `m_msg` once during the application lifetime.
*
* If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
*/
-#define WARN_PRINT_ONCE(m_msg) \
- if (true) { \
- static bool first_print = true; \
- if (first_print) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING); \
- first_print = false; \
- } \
- } else \
+#define WARN_PRINT_ONCE(m_msg) \
+ if (true) { \
+ static bool first_print = true; \
+ if (first_print) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING); \
+ first_print = false; \
+ } \
+ } else \
+ ((void)0)
+
+/**
+ * Prints `m_msg` and notifies the editor once during the application lifetime.
+ *
+ * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
+ */
+#define WARN_PRINT_ONCE_ED(m_msg) \
+ if (true) { \
+ static bool first_print = true; \
+ if (first_print) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING); \
+ first_print = false; \
+ } \
+ } else \
((void)0)
// Print deprecated warning message macros.
@@ -577,27 +757,27 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
/**
* Warns that the current function is deprecated.
*/
-#define WARN_DEPRECATED \
- if (true) { \
- static SafeFlag warning_shown; \
- if (!warning_shown.is_set()) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", ERR_HANDLER_WARNING); \
- warning_shown.set(); \
- } \
- } else \
+#define WARN_DEPRECATED \
+ if (true) { \
+ static SafeFlag warning_shown; \
+ if (!warning_shown.is_set()) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", false, ERR_HANDLER_WARNING); \
+ warning_shown.set(); \
+ } \
+ } else \
((void)0)
/**
* Warns that the current function is deprecated and prints `m_msg`.
*/
-#define WARN_DEPRECATED_MSG(m_msg) \
- if (true) { \
- static SafeFlag warning_shown; \
- if (!warning_shown.is_set()) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", DEBUG_STR(m_msg), ERR_HANDLER_WARNING); \
- warning_shown.set(); \
- } \
- } else \
+#define WARN_DEPRECATED_MSG(m_msg) \
+ if (true) { \
+ static SafeFlag warning_shown; \
+ if (!warning_shown.is_set()) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, false, ERR_HANDLER_WARNING); \
+ warning_shown.set(); \
+ } \
+ } else \
((void)0)
/**
@@ -618,11 +798,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
*
* Prints `m_msg`, and then the application crashes.
*/
-#define CRASH_NOW_MSG(m_msg) \
- if (true) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", DEBUG_STR(m_msg)); \
- GENERATE_TRAP(); \
- } else \
+#define CRASH_NOW_MSG(m_msg) \
+ if (true) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", m_msg); \
+ GENERATE_TRAP(); \
+ } else \
((void)0)
#endif // ERROR_MACROS_H
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index a8547a0090..3687e4f7e5 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -40,7 +40,7 @@
static String get_type_name(const PropertyInfo &p_info) {
if (p_info.type == Variant::INT && (p_info.hint == PROPERTY_HINT_INT_IS_POINTER)) {
- if (p_info.hint_string == "") {
+ if (p_info.hint_string.is_empty()) {
return "void*";
} else {
return p_info.hint_string + "*";
@@ -340,7 +340,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
int value = CoreConstants::get_global_constant_value(i);
String enum_name = CoreConstants::get_global_constant_enum(i);
String name = CoreConstants::get_global_constant_name(i);
- if (enum_name != String()) {
+ if (!enum_name.is_empty()) {
enum_list[enum_name].push_back(Pair<String, int>(name, value));
} else {
Dictionary d;
@@ -353,11 +353,11 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
api_dump["global_constants"] = constants;
Array enums;
- for (Map<String, List<Pair<String, int>>>::Element *E = enum_list.front(); E; E = E->next()) {
+ for (const KeyValue<String, List<Pair<String, int>>> &E : enum_list) {
Dictionary d1;
- d1["name"] = E->key();
+ d1["name"] = E.key;
Array values;
- for (const Pair<String, int> &F : E->get()) {
+ for (const Pair<String, int> &F : E.value) {
Dictionary d2;
d2["name"] = F.first;
d2["value"] = F.second;
@@ -841,6 +841,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
{
Array native_structures;
+ // AudioStream structures
{
Dictionary d;
d["name"] = "AudioFrame";
@@ -849,6 +850,22 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
native_structures.push_back(d);
}
+ // TextServer structures
+ {
+ Dictionary d;
+ d["name"] = "Glyph";
+ d["format"] = "int start,int end,uint8_t count,uint8_t repeat,uint16_t flags,float x_off,float y_off,float advance,RID font_rid,int font_size,int32_t index";
+
+ native_structures.push_back(d);
+ }
+ {
+ Dictionary d;
+ d["name"] = "CaretInfo";
+ d["format"] = "Rect2 leading_caret,Rect2 trailing_caret,TextServer::Direction leading_direction,TextServer::Direction trailing_direction";
+
+ native_structures.push_back(d);
+ }
+
api_dump["native_structures"] = native_structures;
}
diff --git a/core/extension/extension_api_dump.h b/core/extension/extension_api_dump.h
index a7825c10a9..7346e182f1 100644
--- a/core/extension/extension_api_dump.h
+++ b/core/extension/extension_api_dump.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index a65bdd16dc..385117eed1 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -51,13 +51,13 @@ static void gdnative_free(void *p_mem) {
// Helper print functions.
static void gdnative_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, ERR_HANDLER_ERROR);
+ _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_ERROR);
}
static void gdnative_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, ERR_HANDLER_WARNING);
+ _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_WARNING);
}
static void gdnative_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, ERR_HANDLER_SCRIPT);
+ _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT);
}
// Variant functions
@@ -771,6 +771,30 @@ static GDNativeTypePtr gdnative_packed_vector3_array_operator_index_const(const
return (GDNativeTypePtr)&self->ptr()[p_index];
}
+static GDNativeVariantPtr gdnative_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) {
+ Array *self = (Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDNativeVariantPtr)&self->operator[](p_index);
+}
+
+static GDNativeVariantPtr gdnative_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) {
+ const Array *self = (const Array *)p_self;
+ ERR_FAIL_INDEX_V(p_index, self->size(), nullptr);
+ return (GDNativeVariantPtr)&self->operator[](p_index);
+}
+
+/* Dictionary functions */
+
+static GDNativeVariantPtr gdnative_dictionary_operator_index(GDNativeTypePtr p_self, const GDNativeVariantPtr p_key) {
+ Dictionary *self = (Dictionary *)p_self;
+ return (GDNativeVariantPtr)&self->operator[](*(const Variant *)p_key);
+}
+
+static GDNativeVariantPtr gdnative_dictionary_operator_index_const(const GDNativeTypePtr p_self, const GDNativeVariantPtr p_key) {
+ const Dictionary *self = (const Dictionary *)p_self;
+ return (GDNativeVariantPtr)&self->operator[](*(const Variant *)p_key);
+}
+
/* OBJECT API */
static void gdnative_object_method_bind_call(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
@@ -803,16 +827,21 @@ static GDNativeObjectPtr gdnative_global_get_singleton(const char *p_name) {
return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(String(p_name));
}
-static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_instance, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) {
- Object *o = (Object *)p_instance;
+static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_object, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) {
+ Object *o = (Object *)p_object;
return o->get_instance_binding(p_token, p_callbacks);
}
-static void gdnative_object_set_instance_binding(GDNativeObjectPtr p_instance, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) {
- Object *o = (Object *)p_instance;
+static void gdnative_object_set_instance_binding(GDNativeObjectPtr p_object, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) {
+ Object *o = (Object *)p_object;
o->set_instance_binding(p_token, p_binding, p_callbacks);
}
+static void gdnative_object_set_instance(GDNativeObjectPtr p_object, const char *p_classname, GDExtensionClassInstancePtr p_instance) {
+ Object *o = (Object *)p_object;
+ ClassDB::set_object_extension_instance(o, p_classname, p_instance);
+}
+
static GDNativeObjectPtr gdnative_object_get_instance_from_id(GDObjectInstanceID p_instance_id) {
return (GDNativeObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id));
}
@@ -842,12 +871,8 @@ static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const char *p_clas
return (GDNativeMethodBindPtr)mb;
}
-static GDNativeClassConstructor gdnative_classdb_get_constructor(const char *p_classname) {
- ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(StringName(p_classname));
- if (class_info) {
- return (GDNativeClassConstructor)class_info->creation_func;
- }
- return nullptr;
+static GDNativeObjectPtr gdnative_classdb_construct_object(const char *p_classname) {
+ return (GDNativeObjectPtr)ClassDB::instantiate(p_classname);
}
static void *gdnative_classdb_get_class_tag(const char *p_classname) {
@@ -979,6 +1004,14 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
gdni.packed_vector3_array_operator_index = gdnative_packed_vector3_array_operator_index;
gdni.packed_vector3_array_operator_index_const = gdnative_packed_vector3_array_operator_index_const;
+ gdni.array_operator_index = gdnative_array_operator_index;
+ gdni.array_operator_index_const = gdnative_array_operator_index_const;
+
+ /* Dictionary functions */
+
+ gdni.dictionary_operator_index = gdnative_dictionary_operator_index;
+ gdni.dictionary_operator_index_const = gdnative_dictionary_operator_index_const;
+
/* OBJECT */
gdni.object_method_bind_call = gdnative_object_method_bind_call;
@@ -987,6 +1020,7 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
gdni.global_get_singleton = gdnative_global_get_singleton;
gdni.object_get_instance_binding = gdnative_object_get_instance_binding;
gdni.object_set_instance_binding = gdnative_object_set_instance_binding;
+ gdni.object_set_instance = gdnative_object_set_instance;
gdni.object_cast_to = gdnative_object_cast_to;
gdni.object_get_instance_from_id = gdnative_object_get_instance_from_id;
@@ -994,7 +1028,7 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
/* CLASSDB */
- gdni.classdb_get_constructor = gdnative_classdb_get_constructor;
+ gdni.classdb_construct_object = gdnative_classdb_construct_object;
gdni.classdb_get_method_bind = gdnative_classdb_get_method_bind;
gdni.classdb_get_class_tag = gdnative_classdb_get_class_tag;
@@ -1005,6 +1039,8 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
gdni.classdb_register_extension_class_method = nullptr;
gdni.classdb_register_extension_class_integer_constant = nullptr;
gdni.classdb_register_extension_class_property = nullptr;
+ gdni.classdb_register_extension_class_property_group = nullptr;
+ gdni.classdb_register_extension_class_property_subgroup = nullptr;
gdni.classdb_register_extension_class_signal = nullptr;
gdni.classdb_unregister_extension_class = nullptr;
}
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index 30346f233f..a2e0c7cc73 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -137,6 +137,7 @@ typedef void *GDNativeStringNamePtr;
typedef void *GDNativeStringPtr;
typedef void *GDNativeObjectPtr;
typedef void *GDNativeTypePtr;
+typedef void *GDNativeExtensionPtr;
typedef void *GDNativeMethodBindPtr;
typedef int64_t GDNativeInt;
typedef uint8_t GDNativeBool;
@@ -181,11 +182,11 @@ typedef void *(*GDNativeInstanceBindingCreateCallback)(void *p_token, void *p_in
typedef void (*GDNativeInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding);
typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDNativeBool p_reference);
-struct GDNativeInstanceBindingCallbacks {
+typedef struct {
GDNativeInstanceBindingCreateCallback create_callback;
GDNativeInstanceBindingFreeCallback free_callback;
GDNativeInstanceBindingReferenceCallback reference_callback;
-};
+} GDNativeInstanceBindingCallbacks;
/* EXTENSION CLASSES */
@@ -210,7 +211,7 @@ typedef const char *(*GDNativeExtensionClassToString)(GDExtensionClassInstancePt
typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
-typedef GDExtensionClassInstancePtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata);
+typedef GDNativeObjectPtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata);
typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance);
typedef void (*GDNativeExtensionClassObjectInstance)(GDExtensionClassInstancePtr p_instance, GDNativeObjectPtr p_object_instance);
typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name);
@@ -226,7 +227,6 @@ typedef struct {
GDNativeExtensionClassUnreference unreference_func;
GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
- GDNativeExtensionClassObjectInstance object_instance_func; /* this one is mandatory */
GDNativeExtensionClassGetVirtual get_virtual_func;
void *class_userdata;
} GDNativeExtensionClassCreationInfo;
@@ -413,22 +413,32 @@ typedef struct {
GDNativeTypePtr (*packed_vector3_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr
GDNativeTypePtr (*packed_vector3_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr
+ GDNativeVariantPtr (*array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be an Array ptr
+ GDNativeVariantPtr (*array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be an Array ptr
+
+ /* Dictionary functions */
+
+ GDNativeVariantPtr (*dictionary_operator_index)(GDNativeTypePtr p_self, const GDNativeVariantPtr p_key); // p_self should be an Dictionary ptr
+ GDNativeVariantPtr (*dictionary_operator_index_const)(const GDNativeTypePtr p_self, const GDNativeVariantPtr p_key); // p_self should be an Dictionary ptr
+
/* OBJECT */
void (*object_method_bind_call)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_ret, GDNativeCallError *r_error);
void (*object_method_bind_ptrcall)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
void (*object_destroy)(GDNativeObjectPtr p_o);
GDNativeObjectPtr (*global_get_singleton)(const char *p_name);
+
void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks);
void (*object_set_instance_binding)(GDNativeObjectPtr p_o, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks);
+ void (*object_set_instance)(GDNativeObjectPtr p_o, const char *p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */
+
GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag);
GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id);
GDObjectInstanceID (*object_get_instance_id)(const GDNativeObjectPtr p_object);
/* CLASSDB */
-
- GDNativeClassConstructor (*classdb_get_constructor)(const char *p_classname);
+ GDNativeObjectPtr (*classdb_construct_object)(const char *p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */
GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash);
void *(*classdb_get_class_tag)(const char *p_classname);
@@ -438,6 +448,8 @@ typedef struct {
void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value);
void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
+ void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix);
+ void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
} GDNativeInterface;
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index a3cd7ca14c..1512852234 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,7 +35,9 @@
#include "core/object/method_bind.h"
#include "core/os/os.h"
-const char *NativeExtension::EXTENSION_LIST_CONFIG_FILE = "res://.godot/extension_list.cfg";
+String NativeExtension::get_extension_list_config_file() {
+ return ProjectSettings::get_singleton()->get_project_data_path().plus_file("extension_list.cfg");
+}
class NativeExtensionMethodBind : public MethodBind {
GDNativeExtensionClassMethodCall call_func;
@@ -154,7 +156,6 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr
extension->native_extension.unreference = p_extension_funcs->unreference_func;
extension->native_extension.class_userdata = p_extension_funcs->class_userdata;
extension->native_extension.create_instance = p_extension_funcs->create_instance_func;
- extension->native_extension.set_object_instance = p_extension_funcs->object_instance_func;
extension->native_extension.free_instance = p_extension_funcs->free_instance_func;
extension->native_extension.get_virtual = p_extension_funcs->get_virtual_func;
@@ -184,6 +185,7 @@ void NativeExtension::_register_extension_class_integer_constant(const GDNativeE
ClassDB::bind_integer_constant(class_name, p_enum_name, p_constant_name, p_constant_value);
}
+
void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter) {
NativeExtension *self = (NativeExtension *)p_library;
@@ -202,6 +204,24 @@ void NativeExtension::_register_extension_class_property(const GDNativeExtension
ClassDB::add_property(class_name, pinfo, p_setter, p_getter);
}
+void NativeExtension::_register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix) {
+ NativeExtension *self = (NativeExtension *)p_library;
+
+ StringName class_name = p_class_name;
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property group '" + String(p_group_name) + "' for unexisting class '" + class_name + "'.");
+
+ ClassDB::add_property_group(class_name, p_group_name, p_prefix);
+}
+
+void NativeExtension::_register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix) {
+ NativeExtension *self = (NativeExtension *)p_library;
+
+ StringName class_name = p_class_name;
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property subgroup '" + String(p_subgroup_name) + "' for unexisting class '" + class_name + "'.");
+
+ ClassDB::add_property_subgroup(class_name, p_subgroup_name, p_prefix);
+}
+
void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) {
NativeExtension *self = (NativeExtension *)p_library;
@@ -325,6 +345,8 @@ void NativeExtension::initialize_native_extensions() {
gdnative_interface.classdb_register_extension_class_method = _register_extension_class_method;
gdnative_interface.classdb_register_extension_class_integer_constant = _register_extension_class_integer_constant;
gdnative_interface.classdb_register_extension_class_property = _register_extension_class_property;
+ gdnative_interface.classdb_register_extension_class_property_group = _register_extension_class_property_group;
+ gdnative_interface.classdb_register_extension_class_property_subgroup = _register_extension_class_property_subgroup;
gdnative_interface.classdb_register_extension_class_signal = _register_extension_class_signal;
gdnative_interface.classdb_unregister_extension_class = _unregister_extension_class;
}
@@ -375,7 +397,7 @@ RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_or
}
}
- if (library_path == String()) {
+ if (library_path.is_empty()) {
if (r_error) {
*r_error = ERR_FILE_NOT_FOUND;
}
diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h
index 9b1ebe0ed7..b98e4925d2 100644
--- a/core/extension/native_extension.h
+++ b/core/extension/native_extension.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -50,6 +50,8 @@ class NativeExtension : public Resource {
static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value);
static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
+ static void _register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix);
+ static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name);
@@ -60,7 +62,7 @@ protected:
static void _bind_methods();
public:
- static const char *EXTENSION_LIST_CONFIG_FILE;
+ static String get_extension_list_config_file();
Error open_library(const String &p_path, const String &p_entry_symbol);
void close_library();
diff --git a/core/extension/native_extension_manager.cpp b/core/extension/native_extension_manager.cpp
index 8b7a9df4f1..87737858a8 100644
--- a/core/extension/native_extension_manager.cpp
+++ b/core/extension/native_extension_manager.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -84,8 +84,8 @@ bool NativeExtensionManager::is_extension_loaded(const String &p_path) const {
Vector<String> NativeExtensionManager::get_loaded_extensions() const {
Vector<String> ret;
- for (const Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
- ret.push_back(E->key());
+ for (const KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) {
+ ret.push_back(E.key);
}
return ret;
}
@@ -97,25 +97,25 @@ Ref<NativeExtension> NativeExtensionManager::get_extension(const String &p_path)
void NativeExtensionManager::initialize_extensions(NativeExtension::InitializationLevel p_level) {
ERR_FAIL_COND(int32_t(p_level) - 1 != level);
- for (Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
- E->get()->initialize_library(p_level);
+ for (KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) {
+ E.value->initialize_library(p_level);
}
level = p_level;
}
void NativeExtensionManager::deinitialize_extensions(NativeExtension::InitializationLevel p_level) {
ERR_FAIL_COND(int32_t(p_level) != level);
- for (Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
- E->get()->deinitialize_library(p_level);
+ for (KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) {
+ E.value->deinitialize_library(p_level);
}
level = int32_t(p_level) - 1;
}
void NativeExtensionManager::load_extensions() {
- FileAccessRef f = FileAccess::open(NativeExtension::EXTENSION_LIST_CONFIG_FILE, FileAccess::READ);
+ FileAccessRef f = FileAccess::open(NativeExtension::get_extension_list_config_file(), FileAccess::READ);
while (f && !f->eof_reached()) {
String s = f->get_line().strip_edges();
- if (s != String()) {
+ if (!s.is_empty()) {
LoadStatus err = load_extension(s);
ERR_CONTINUE_MSG(err == LOAD_STATUS_FAILED, "Error loading extension: " + s);
}
diff --git a/core/extension/native_extension_manager.h b/core/extension/native_extension_manager.h
index 89ccd155fe..b8339e4817 100644
--- a/core/extension/native_extension_manager.h
+++ b/core/extension/native_extension_manager.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/input/SCsub b/core/input/SCsub
index 740398b266..b12bf561de 100644
--- a/core/input/SCsub
+++ b/core/input/SCsub
@@ -7,19 +7,15 @@ import input_builders
# Order matters here. Higher index controller database files write on top of lower index database files.
controller_databases = [
- "#core/input/gamecontrollerdb.txt",
- "#core/input/godotcontrollerdb.txt",
+ "gamecontrollerdb.txt",
+ "godotcontrollerdb.txt",
]
-env.Depends("#core/input/default_controller_mappings.gen.cpp", controller_databases)
-env.CommandNoCache(
- "#core/input/default_controller_mappings.gen.cpp",
+gensource = env.CommandNoCache(
+ "default_controller_mappings.gen.cpp",
controller_databases,
env.Run(input_builders.make_default_controller_mappings, "Generating default controller mappings."),
)
env.add_source_files(env.core_sources, "*.cpp")
-
-# Don't warn about duplicate entry here, we need it registered manually for first build,
-# even if later builds will pick it up twice due to above *.cpp globbing.
-env.add_source_files(env.core_sources, "#core/input/default_controller_mappings.gen.cpp", warn_duplicates=False)
+env.add_source_files(env.core_sources, gensource)
diff --git a/core/input/default_controller_mappings.h b/core/input/default_controller_mappings.h
index ba5e650226..f0737eea87 100644
--- a/core/input/default_controller_mappings.h
+++ b/core/input/default_controller_mappings.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt
index f136d83496..58014e976e 100644
--- a/core/input/gamecontrollerdb.txt
+++ b/core/input/gamecontrollerdb.txt
@@ -1,25 +1,39 @@
-# Game Controller DB for SDL in 2.0.9 format
+# Game Controller DB for SDL in 2.0.16 format
# Source: https://github.com/gabomdq/SDL_GameControllerDB
# Windows
03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,
-03000000c82d00002038000000000000,8bitdo,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:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000d0160000040d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
+03000000d0160000050d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
+03000000d0160000060d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
+03000000d0160000070d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
+03000000d0160000600a000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,
-03000000c82d000011ab000000000000,8BitDo F30,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:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000008000000210000000000000,8BitDo F30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+030000003512000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000c82d00001028000000000000,8BitDo F30 Arcade Joystick,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d000011ab000000000000,8BitDo F30 Arcade Joystick,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:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001038000000000000,8BitDo F30 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:Windows,
03000000c82d00000090000000000000,8BitDo FC30 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:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
-03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,guide:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00005106000000000000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000151000000000000,8BitDo M30 ModKit,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00002028000000000000,8BitDo N30,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:Windows,
03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d0000e002000000000000,8BitDo N30,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b6,platform:Windows,
03000000c82d00000451000000000000,8BitDo N30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,start:b11,platform:Windows,
03000000c82d00000190000000000000,8BitDo N30 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:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001590000000000000,8BitDo N30 Pro 2,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:Windows,
03000000c82d00006528000000000000,8BitDo N30 Pro 2,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:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000290000000000000,8Bitdo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows,
+03000000c82d00003038000000000000,8Bitdo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows,
+03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Windows,
03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Windows,
+03000000c82d00002038000000000000,8Bitdo NES30 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:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000360000000000000,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00002867000000000000,8BitDo S30 Modkit,a:b0,b:b1,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000130000000000000,8BitDo SF30,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:Windows,
@@ -34,6 +48,7 @@
03000000c82d00004028000000000000,8BitDo SN30,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:Windows,
03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000351000000000000,8BitDo SN30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000021000000000000,8BitDo SN30 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:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000160000000000000,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:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000161000000000000,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:a3,start:b11,x:b4,y:b3,platform:Windows,
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,
@@ -43,12 +58,19 @@
03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000a00500003232000000000000,8Bitdo Zero GamePad,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,
-03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
-03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
-030000008f0e00001200000000000000,Acme GA-02,a:b0,b:b1,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:b2,y:b3,platform:Windows,
-03000000c01100000355000011010000,ACRUX USB GAME PAD,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,
-03000000fa190000f0ff000000000000,Acteck AGJ-3200,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,
+03000000d81d00000e00000000000000,AC02,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
+030000008f0e00001200000000000000,Acme GA02,a:b0,b:b1,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:b2,y:b3,platform:Windows,
+03000000c01100000355000000000000,Acrux,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,
+03000000fa190000f0ff000000000000,Acteck AGJ 3200,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,
+030000006d0400000bc2000000000000,Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows,
+03000000d1180000402c000000000000,ADT1,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a5,x:b3,y:b4,platform:Windows,
+030000006f0e00001301000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00001302000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00001304000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000006f0e00001413000000000000,Afterglow,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,
+030000006f0e00003901000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ab1200000103000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000000f9000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000341a00003608000000000000,Afterglow 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,
030000006f0e00000263000000000000,Afterglow 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,
030000006f0e00001101000000000000,Afterglow 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,
@@ -56,68 +78,135 @@
030000006f0e00001402000000000000,Afterglow 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,
030000006f0e00001901000000000000,Afterglow 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,
030000006f0e00001a01000000000000,Afterglow 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,
-03000000d62000001d57000000000000,Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows,
+03000000830500000160000000000000,Arcade,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b4,platform:Windows,
+03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000ef0500000300000000000000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
+03000000fd0500000230000000000000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows,
03000000d6200000e557000000000000,Batarang,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,
+03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,
030000006f0e00003201000000000000,Battlefield 4 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,
+03000000ad1b000001f9000000000000,BB 070,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000d62000002a79000000000000,BDA PS4 Fightpad,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,
+03000000bc2000005250000000000000,Beitong G3,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a3,righty:a4,start:b15,x:b3,y:b4,platform:Windows,
+030000000d0500000208000000000000,Belkin Nostromo N40,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000bc2000006012000000000000,Betop 2126F,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,
03000000bc2000000055000000000000,Betop BFM Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000bc2000006312000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
-03000000bc2000006321000000000000,BETOP CONTROLLER,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000bc2000006321000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000bc2000006412000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000c01100000555000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000c01100000655000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000790000000700000000000000,Betop 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:a4,start:b9,x:b3,y:b0,platform:Windows,
03000000808300000300000000000000,Betop 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:a4,start:b9,x:b3,y:b0,platform:Windows,
+030000006f0e00006401000000000000,BF One,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,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
+03000000300f00000202000000000000,Bigben,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:a5,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
+030000006b1400000209000000000000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006b1400000055000000000000,Bigben PS3 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:Windows,
030000006b1400000103000000000000,Bigben PS3 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:b3,y:b2,platform:Windows,
-03000000120c0000210e000000000000,Brook Mars,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,
+03000000380700008232000000000000,Brawlpad,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,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000200e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
-03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,
+03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,
+030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000005e040000a102000000000000,Controller (Xbox 360 Wireless Receiver for Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000005e040000ff02000000000000,Controller (Xbox One For Windows) - Wired,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000005e040000ea02000000000000,Controller (Xbox One For Windows) - Wireless,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000b0400003365000000000000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
+030000004c050000c505000000000000,CronusMax Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+03000000d814000007cd000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000d8140000cefa000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,
+030000003807000002cb000000000000,Cyborg,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000f806000000a3000000000000,DA Leader,a:b7,b:b6,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b8,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:b3,rightx:a2,righty:a3,start:b12,x:b4,y:b5,platform:Windows,
+030000001a1c00000001000000000000,Datel,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,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000451300000830000000000000,Defender Game Racer X7,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:Windows,
030000007d0400000840000000000000,Destroyer Tiltpad,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows,
+03000000c0160000e105000000000000,Dual,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+030000007c1800000006000000000000,Dual Compat,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
+030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows,
+030000004f04000012b3000000000000,Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
03000000bd12000002e0000000000000,Dual USB Vibration Joystick,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:a2,start:b11,x:b3,y:b0,platform:Windows,
+03000000ff1100003133000000000000,DualForce,a:b2,b:b3,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:a4,start:b9,x:b0,y:b1,platform:Windows,
030000008f0e00000910000000000000,DualShock 2,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:a2,start:b11,x:b3,y:b0,platform:Windows,
-030000006f0e00003001000000000000,EA SPORTS 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,
+03000000317300000100000000000000,DualShock 3,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:a5,start:b11,x:b3,y:b4,platform:Windows,
+030000006f0e00003001000000000000,EA Sports 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,
+03000000fc0400000250000000000000,Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+030000006e0500000a20000000000000,Elecom DUX60 MMO Gamepad,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows,
03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,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:b1,platform:Windows,
03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,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:b1,platform:Windows,
+030000006e0500000520000000000000,Elecom P301U,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
+03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
+030000006e0500000320000000000000,Elecom U3613M (DInput),a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
+030000006e0500000e20000000000000,Elecom U3912T,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
+030000006e0500000f20000000000000,Elecom U4013S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
+030000006e0500001320000000000000,Elecom U4113,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,
+030000006e0500001020000000000000,Elecom U4113S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
+030000006e0500000720000000000000,Elecom W01U,a:b2,b:b3,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,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,
03000000120c0000f61c000000000000,Elite,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,
+03000000430b00000300000000000000,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows,
+03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
030000008f0e00000f31000000000000,EXEQ,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:b3,y:b2,platform:Windows,
03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
-030000006f0e00008401000000000000,Faceoff Deluxe+ Audio Wired Controller for Nintendo Switch,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,
+03000000790000003018000000000000,F300,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,
+03000000242f00003900000000000000,F300 Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00008401000000000000,Faceoff Deluxe Audio Wired Controller for Nintendo Switch,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,
030000006f0e00008001000000000000,Faceoff Wired Pro Controller for Nintendo Switch,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,
-03000000852100000201000000000000,FF-GP1,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,
+03000000021000000090000000000000,FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+0300000011040000c600000000000000,FC801,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
+030000004f04000008d0000000000000,Ferrari 150,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000852100000201000000000000,FF GP1,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,
030000000d0f00008500000000000000,Fighting Commander 2016 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:Windows,
030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00008700000000000000,Fighting Stick mini 4,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:Windows,
030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
030000000d0f00002700000000000000,FIGHTING STICK V3,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:Windows,
+03000000380700002847000000000000,FightPad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700001847000000000000,FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700008031000000000000,FightStick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+03000000380700008731000000000000,FightStick,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,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000003807000038b7000000000000,FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,
+03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows,
+03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows,
+03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows,
+03000000b40400001024000000000000,Flydigi Apex,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:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000151900004000000000000000,Flydigi Vader 2,a:b11,b:b10,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,leftstick:b1,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b0,righttrigger:b4,rightx:a3,righty:a4,start:b2,x:b9,y:b8,platform:Windows,
+03000000b40400001124000000000000,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:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows,
+030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows,
+03000000ac0500002d02000000000000,G2U,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:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000790000002201000000000000,Game Controller for PC,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,
0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
+03000000341a000005f7000000000000,GameCube,a:b2,b:b3,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b1,y:b0,platform:Windows,
+03000000430b00000500000000000000,GameCube,a:b0,b:b2,dpdown:b10,dpleft:b8,dpright:b9,dpup:b11,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a3,rightx:a5,righty:a2,start:b7,x:b1,y:b3,platform:Windows,
+03000000790000004718000000000000,GameCube,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,
-03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b2,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:b0,y:b3,platform:Windows,
-030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,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,
+03000000790000004618000000000000,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:Windows,
+030000008f0e00000d31000000000000,Gamepad 3 Turbo,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,
03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000ac0500003d03000000000000,GameSir,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,
03000000ac0500004d04000000000000,GameSir,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,
+030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000000d0f00001110000000000000,GameStick Bluetooth Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+0300000047530000616d000000000000,GameStop,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:Windows,
03000000ffff00000000000000000000,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:Windows,
03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-030000009b2800003200000000000000,GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
-030000009b2800006000000000000000,GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
+03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows,
+030000008f0e00001411000000000000,Gamo2 Divaller PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000a857000000000000,Gator Claw,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+03000000c9110000f055000000000000,GC100XF,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:Windows,
030000008305000009a0000000000000,Genius,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:Windows,
030000008305000031b0000000000000,Genius Maxfire Blaze 3,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:Windows,
03000000451300000010000000000000,Genius Maxfire Grandias 12,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:Windows,
@@ -127,72 +216,134 @@
03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000f0250000c383000000000000,Gioteck VX2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000f0250000c483000000000000,Gioteck VX2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000007d0400000540000000000000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000007d0400000340000000000000,Gravis G44011 Xterminator,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a2,start:b9,x:b3,y:b4,platform:Windows,
+030000008f0e00000610000000000000,GreenAsia,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:a5,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
+03000000ac0500006b05000000000000,GT2a,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:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000341a00000302000000000000,Hama Scorpad,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,
+03000000fd0500003902000000000000,Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows,
+03000000fd0500002a26000000000000,Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows,
+03000000fd0500002f26000000000000,Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows,
030000000d0f00004900000000000000,Hatsune Miku Sho 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,
-030000001008000001e1000000000000,Havit HV-G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows,
-03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
-03000000632500002605000000000000,HJD-X,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,
+030000001008000001e1000000000000,Havit HV G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows,
+030000000d0f00000c00000000000000,HEXT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000d81400000862000000000000,HitBox Edition Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
+03000000632500002605000000000000,HJD X,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,
+030000000d0f00000a00000000000000,Hori DOA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f00008600000000000000,Hori Fighting Commander,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f0000ba00000000000000,Hori Fighting Commander,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00005e00000000000000,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:Windows,
+030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00005e00000000000000,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:Windows,
+030000000d0f00005100000000000000,Hori Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00001000000000000000,Hori Fighting Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000f0d00000010000000000000,Hori Fighting Stick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00003200000000000000,Hori Fighting Stick 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000c000000000000000,Hori Fighting Stick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f00000d00000000000000,Hori Fighting Stick EX2,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000000d0f00003701000000000000,Hori Fighting Stick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Windows,
030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00002100000000000000,Hori Fighting Stick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000a000000000000000,Hori Grip TAC4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b13,x:b0,y:b3,platform:Windows,
+030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,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,
030000000d0f00005400000000000000,Hori 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:Windows,
030000000d0f00000900000000000000,Hori Pad 3 Turbo,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,
030000000d0f00004d00000000000000,Hori Pad A,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,
+030000000d0f00003801000000000000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Windows,
030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro Pad,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:Windows,
-030000000d0f00001600000000007803,HORI Real Arcade Pro EX-SE (Xbox 360),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f00001100000000000000,Hori Real Arcade Pro 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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00002600000000000000,Hori Real Arcade Pro 3P,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00004b00000000000000,Hori Real Arcade Pro 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00008a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00008b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006f00000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00007000000000000000,Hori Real Arcade Pro 4 VLX,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:Windows,
+030000000d0f00003d00000000000000,Hori Real Arcade Pro N3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b4,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b6,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000ae00000000000000,Hori Real Arcade Pro N4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f00008c00000000000000,Hori Real Arcade Pro P4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f0000aa00000000000000,Hori Real Arcade Pro S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000d800000000000000,Hori Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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:Windows,
+030000000d0f00002200000000000000,Hori Real Arcade Pro V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00005b00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00005c00000000000000,Hori Real Arcade Pro V4,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,
+030000000d0f0000af00000000000000,Hori Real Arcade Pro VHS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00001b00000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000002f5000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b07,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b08,righttrigger:b11,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Windows,
030000000d0f00009c00000000000000,Hori TAC Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000c900000000000000,Hori Taiko Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00002301000000000000,Hori Wired PS4 Controller Light,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:a5,start:b11,x:b3,y:b4,platform:Windows,
030000000d0f0000c100000000000000,Horipad,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,
-030000000d0f00006e00000000000000,HORIPAD 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00006600000000000000,HORIPAD 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006400000000000000,Horipad 3TP,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00001300000000000000,Horipad 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00005500000000000000,Horipad 4 FPS,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,
-030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,
+030000000d0f00006e00000000000000,Horipad 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006600000000000000,Horipad 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00004200000000000000,Horipad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000ad1b000001f5000000000000,Horipad EXT2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005b1c00002400000000000000,Horipad Mini,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
+030000000d0f0000ee00000000000000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006700000000000000,Horipad One,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:Windows,
+030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows,
03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
-03000000830500006020000000000000,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:Windows,
+030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows,
+03000000696400006964000000000000,iDroidCon Bluetooth Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,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:Windows,
-030000006f0e00002401000000000000,INJUSTICE FightStick PS3 Controller,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:Windows,
-03000000ac0500002c02000000000000,IPEGA,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
-03000000491900000204000000000000,Ipega PG-9023,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,
-03000000491900000304000000000000,Ipega PG-9087 - Bluetooth Gamepad,+righty:+a5,-righty:-a4,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,start:b11,x:b3,y:b4,platform:Windows,
-030000006e0500000a20000000000000,JC-DUX60 ELECOM MMO Gamepad,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows,
-030000006e0500000520000000000000,JC-P301U,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
-030000006e0500000320000000000000,JC-U3613M (DInput),a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
-030000006e0500000720000000000000,JC-W01U,a:b2,b:b3,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,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,
+030000006f0e00002401000000000000,Injustice FightStick PS3 Controller,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:Windows,
+03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows,
+03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000491900000204000000000000,Ipega PG9023,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,
+03000000491900000304000000000000,Ipega PG9087 - Bluetooth Gamepad,+righty:+a5,-righty:-a4,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,start:b11,x:b3,y:b4,platform:Windows,
030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows,
-030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows,
030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
-030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
-03000000bd12000003c0000010010000,Joypad Alpha Shock,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,
-03000000bd12000003c0000000000000,JY-P70UR,a:b1,b:b0,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b4,x:b3,y:b2,platform:Windows,
+03000000bd12000003c0000000000000,Joypad Alpha Shock,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,
+03000000250900000017000000000000,Joypad to USB Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,
+03000000ff1100004033000000000000,JPD FFB,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:a2,start:b15,x:b3,y:b0,platform:Windows,
03000000242f00002d00000000000000,JYS Wireless Adapter,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,
03000000242f00008a00000000000000,JYS Wireless Adapter,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:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
+03000000c4100000c082000000000000,KADE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000828200000180000000000000,Keio,a:b4,b:b5,back:b8,leftshoulder:b2,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b1,platform:Windows,
03000000790000000200000000000000,King 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:a4,start:b9,x:b3,y:b0,platform:Windows,
+03000000bd12000001e0000000000000,Leadership,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,
+030000006f0e00000103000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00000104000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000008f0e00001300000000000000,Logic3,a:b2,b:b1,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,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000006d040000d1ca000000000000,Logitech ChillStream,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,
030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,
030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006d0400001ec2000000000000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000006d04000018c2000000000000,Logitech F510 Gamepad,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,
+030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000006d04000019c2000000000000,Logitech F710 Gamepad,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,
030000006d0400001ac2000000000000,Logitech Precision Gamepad,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000006d04000009c2000000000000,Logitech WingMan,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,
-03000000380700006652000000000000,Mad Catz C.T.R.L.R,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
-03000000380700005032000000000000,Mad Catz FightPad PRO (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:Windows,
-03000000380700005082000000000000,Mad Catz FightPad PRO (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,
-03000000380700008433000000000000,Mad Catz FightStick TE S+ (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:Windows,
-03000000380700008483000000000000,Mad Catz FightStick TE S+ (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,
-03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-03000000380700006252000000000000,Mad Catz Micro C.T.R.L.R,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700005645000000000000,Lynx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,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,
+03000000380700003888000000000000,Mad Catz Arcade Fightstick TE S Plus PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700008532000000000000,Mad Catz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700006352000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700006652000000000000,Mad Catz CTRLR,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700005032000000000000,Mad Catz FightPad Pro 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:Windows,
+03000000380700005082000000000000,Mad Catz FightPad PRO 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,
+03000000380700008433000000000000,Mad Catz FightStick TE S 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:Windows,
+03000000380700008483000000000000,Mad Catz FightStick TE S 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,
+03000000380700008134000000000000,Mad Catz FightStick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700008184000000000000,Mad Catz FightStick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700006252000000000000,Mad Catz Micro CTRLR,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700001888000000000000,Mad Catz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000380700008081000000000000,Mad Catz SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008034000000000000,Mad Catz TE2 PS3 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,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,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:Windows,
-03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
-03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000002a0600001024000000000000,Matricom,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:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,
@@ -205,36 +356,73 @@
0300000025090000e803000000000000,Mayflash Wii Classic Controller,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:Windows,
03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),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,
03000000790000002418000000000000,Mega Drive,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows,
+0300000079000000ae18000000000000,Mega Drive,a:b0,b:b1,back:b7,dpdown:b14,dpleft:b15,dpright:b13,dpup:b2,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000c0160000990a000000000000,Mega Drive,a:b0,b:b1,leftx:a0,lefty:a1,righttrigger:b2,start:b3,platform:Windows,
+030000005e0400000300000000000000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
+030000005e0400000700000000000000,Microsoft SideWinder,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+030000005e0400000e00000000000000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows,
+030000005e0400002700000000000000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Windows,
+03000000280d00000202000000000000,Miller Lite Cantroller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b5,x:b2,y:b3,platform:Windows,
+030000005b1c00002500000000000000,Mini,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
+03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+03000000ad1b00003ef0000000000000,MLG FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03000000380700006382000000000000,MLG GamePad 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,
-03000000c62400002a89000000000000,MOGA XP5-A Plus,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
-03000000c62400002b89000000000000,MOGA XP5-A 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 XP5-X 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 XP5-X 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,
+03000000d6200000e589000000000000,Moga 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
+03000000d62000007162000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
+03000000d6200000ad0d000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c62400002a89000000000000,Moga XP5A Plus,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+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,
-030000006b140000010c000000000000,NACON GC-400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
-03000000921200004b46000000000000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,
-03000000790000004518000000000000,NEXILUX GAMECUBE Controller Adapter,platform:Windows,a:b1,b:b0,x:b2,y:b3,start:b9,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,
+03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows,
+030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000006b140000100d000000000000,Nacon Revolution Infinity PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006b140000080d000000000000,Nacon Revolution Unlimited Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000bd12000001c0000000000000,Nebular,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000eb0300000000000000000000,NeGcon USB Adapter,a:a2,b:b13,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,lefttrigger:a4,leftx:a1,righttrigger:b11,start:b3,x:a3,y:b12,platform:Windows,
+0300000038070000efbe000000000000,NEO SE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000921200004b46000000000000,NES 2 port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,
+03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
+03000000571d00002100000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
+03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
+03000000790000004518000000000000,NEXILUX GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows,
+03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows,
03000000152000000182000000000000,NGDS,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:Windows,
-03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
+030000007e0500001920000000000000,Nintendo Switch N64 Controller,+rightx:b8,+righty:b2,-rightx:b3,-righty:b7,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,rightshoulder:b5,righttrigger:b10,start:b9,platform:Windows,
+030000007e0500001720000000000000,Nintendo Switch Online Controller,a:b0,b:b1,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:b2,y:b3,platform:Windows,
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:Windows,
030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows,
+03000000d620000013a7000000000000,NSW wired controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000550900001472000000000000,NVIDIA Controller v01.04,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows,
-030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows,
+03000000550900001072000000000000,NVIDIA Shield,a:b9,b:b8,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b3,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b2,righttrigger:a4,rightx:a2,righty:a5,start:b0,x:b7,y:b6,platform:Windows,
+030000005509000000b4000000000000,NVIDIA Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000120c00000288000000000000,Nyko Air Flo Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000004b120000014d000000000000,Nyko Airflo,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows,
+03000000d62000001d57000000000000,Nyko Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows,
+030000000d0f00000401000000000000,Onyx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000008916000001fd000000000000,Onza CE,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:a3,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,
03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00008501000000000000,PDP Fightpad Pro,a:b2,b:b3,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:b1,y:b0,platform:Windows,
030000006f0e00000901000000000000,PDP Versus Fighting Pad,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:Windows,
-030000008f0e00000300000000000000,Piranha xtreme,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,
030000004c050000da0c000000000000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000d9040000160f000000000000,Playstation Controller 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:Windows,
030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000d62000006dca000000000000,PowerA Pro Ex,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,
+030000006d04000084ca000000000000,Precision,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000d62000009557000000000000,Pro Elite 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,
+03000000c62400001a53000000000000,Pro Ex Mini,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000d62000009f31000000000000,Pro Ex mini 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,
03000000d6200000c757000000000000,Pro Ex mini 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,
+03000000120c0000110e000000000000,Pro5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
03000000e30500009605000000000000,PS to USB convert cable,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,
03000000100800000100000000000000,PS1 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,
@@ -244,122 +432,271 @@
03000000666600006706000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
030000006b1400000303000000000000,PS2 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:Windows,
030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000250900000088000000000000,PS2 Controller,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,
+03000000250900006888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b6,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000120a00000100000000000000,PS3 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000120c00001307000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+03000000120c0000f90e000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+03000000250900000118000000000000,PS3 Controller,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,
+03000000250900000218000000000000,PS3 Controller,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,
03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,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:b0,y:b3,platform:Windows,
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,
+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,
030000003807000056a8000000000000,PS3 RF pad,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,
-03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+03000000100000008200000000000000,PS360 v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c00000807000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000111e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000121e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000130e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000150e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000180e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000181e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000191e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000f10e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000f51c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000f70e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000160e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000001a1e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000ff000000cb01000000000000,PSP,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
-03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,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:b10,x:b0,y:b3,platform:Windows,
-03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
-03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,
-03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
-03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,
-03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,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,
-03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,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,
+03000000830500005020000000000000,PSX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Windows,
+03000000300f00000111000000000000,Qanba 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+03000000300f00000211000000000000,Qanba 2P,a:b1,b:b0,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:Windows,
+03000000300f00000011000000000000,Qanba Arcade Stick 1008,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:b10,x:b0,y:b3,platform:Windows,
+03000000300f00001611000000000000,Qanba Arcade Stick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
+03000000222c00000020000000000000,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,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000300f00001211000000000000,Qanba Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
+03000000341a00000104000000000000,Qanba Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,
+03000000222c00000223000000000000,Qanba Obsidian Arcade Stick 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:Windows,
+03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,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,
+030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows,
+03000000086700006626000000000000,RadioShack,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,
+030000009b2800002300000000000000,Raphnet Technologies 3DO USB Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows,
+030000009b2800006900000000000000,Raphnet Technologies 3DO USB Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows,
+030000009b2800000800000000000000,Raphnet Technologies Dreamcast USB Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows,
+030000009b2800003200000000000000,Raphnet Technologies GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
+030000009b2800006000000000000000,Raphnet Technologies GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
+030000009b2800001800000000000000,Raphnet Technologies Jaguar USB Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows,
+030000009b2800000200000000000000,Raphnet Technologies NES USB Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows,
+030000009b2800004300000000000000,Raphnet Technologies Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
+030000009b2800000500000000000000,Raphnet Technologies Saturn Adapter 2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
+030000009b2800000300000000000000,Raphnet Technologies SNES USB Adapter,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+030000009b2800005600000000000000,Raphnet Technologies SNES USB Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
+030000009b2800005700000000000000,Raphnet Technologies SNES USB Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
+030000009b2800001e00000000000000,Raphnet Technologies Vectrex USB 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 Technologies Wii Classic USB 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 Technologies Wii Classic USB 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,
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),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,
+03000000321500000204000000000000,Razer Panthera 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: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,
+03000000321500000010000000000000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
03000000321500000507000000000000,Razer Raiju Mobile,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,
03000000321500000707000000000000,Razer Raiju Mobile,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,
+03000000321500000710000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+03000000321500000a10000000000000,Razer Raiju TE,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,
+03000000321500000410000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
03000000321500000011000000000000,Razer Raion Fightpad for 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,
03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000000d0f00001100000000000000,REAL ARCADE PRO.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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,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:Windows,
-030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00005c00000000000000,Real Arcade Pro.V4,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,
-03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
-03000000bd12000013d0000000000000,Retrolink USB SEGA Saturn Classic,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows,
+03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
+03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
+03000000bd12000013d0000000000000,Retrolink USB Sega Saturn Classic,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows,
+03000000bd12000015d0000000000000,Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
+03000000830500000960000000000000,Revenger,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b5,platform:Windows,
030000006b140000010d000000000000,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:Windows,
-030000006b140000020d000000000000,Revolution Pro Controller 2(1/2),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,
+030000006b140000020d000000000000,Revolution Pro Controller 2,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,
030000006b140000130d000000000000,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:Windows,
+030000006f0e00001f01000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00004601000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c6240000fefa000000000000,Rock Candy 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:Windows,
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,
-030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000004f04000001d0000000000000,Rumble Force,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+030000004f04000003d0000000000000,Run N Drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000004f04000009d0000000000000,Run N Drive,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,
+030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,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:Windows,
03000000300f00001201000000000000,Saitek Dual Analog Pad,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:Windows,
03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows,
03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows,
+03000000a30600000d5f000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,
+03000000a30600000dff000000000000,Saitek P2600,a:b1,b:b2,back:b9,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:b8,x:b0,y:b3,platform:Windows,
03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
+03000000a306000018f5000000000000,Saitek P3200,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000300f00001001000000000000,Saitek P480 Rumble Pad,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:Windows,
+03000000a30600000901000000000000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b5,rightx:a3,righty:a2,x:b0,y:b1,platform:Windows,
03000000a30600000b04000000000000,Saitek P990,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:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
-03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,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:a2,start:b8,x:b0,y:b3,platform:Windows,
03000000a30600002106000000000000,Saitek PS1000,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:Windows,
03000000a306000020f6000000000000,Saitek PS2700,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:Windows,
03000000300f00001101000000000000,Saitek Rumble Pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,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:Windows,
+03000000e804000000a0000000000000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c01100000252000000000000,Sanwa Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000c01100004350000000000000,Sanwa Micro Grip P3,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,x:b3,y:b2,platform:Windows,
+03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows,
+03000000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows,
03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
-0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
-030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
-03000000a30c00002500000000000000,Sega Genesis Mini 3B controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows,
-03000000a30c00002400000000000000,Sega Mega Drive Mini 6B controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
-03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
-03000000341a00000908000000000000,SL-6566,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:Windows,
-030000008f0e00000800000000000000,SpeedLink Strike FX,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,
+03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows,
+03000000c01100000051000000000000,Satechi Bluetooth Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows,
+03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
+0300000000050000289b000000000000,Sega Saturn Adapter 2,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
+0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows,
+03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
+030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows,
+03000000120c00001c1e000000000000,SnakeByte GamePad 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+0300000003040000c197000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+03000000571d00002000000000000000,SNES Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
+0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows,
+03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
+03000000341a00000908000000000000,Speedlink 6566,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:Windows,
+030000008f0e00000800000000000000,Speedlink Strike FX,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,
03000000c01100000591000000000000,Speedlink Torid,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,
03000000d11800000094000000000000,Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
+03000000de280000fc11000000000000,Steam Virtual Gamepad,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:Windows,
+03000000de280000ff11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
03000000110100003114000000000000,SteelSeries Stratus Duo,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,
03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows,
-03000000790000001c18000000000000,STK-7024X,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,
-03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows,
+03000000790000001c18000000000000,STK 7024X,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,
+03000000381000003014000000000000,Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000381000003114000000000000,Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700003847000000000000,Street Fighter Fighting Stick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows,
+030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000d620000011a7000000000000,Switch,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,
-03000000457500002211000000000000,SZMY-POWER PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-030000004f04000007d0000000000000,T Mini Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-030000004f0400000ab1000000000000,T.16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows,
+030000000d0f0000f600000000000000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000457500002211000000000000,Szmy Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows,
+030000000d0f00007b00000000000000,TAC GEAR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000d814000001a0000000000000,TE Kitty,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000b50700001203000000000000,Techmobility X6-38V,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:Windows,
+03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows,
+03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,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,x:b3,y:b4,platform:Windows,
+03000000790000002601000000000000,TGZ,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,
030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
-030000004f04000023b3000000000000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000004f04000023b3000000000000,Thrustmaster Dual Trigger 3 in 1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f0400000ed0000000000000,ThrustMaster eSwap 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:Windows,
030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,
030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,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:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+030000004f04000007d0000000000000,TMini Wireless,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,
03000000d62000006000000000000000,Tournament 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,
+03000000c01100000055000000000000,Tronsmart,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,
030000005f140000c501000000000000,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:Windows,
03000000b80500000210000000000000,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:Windows,
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,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,
-030000006e0500001320000000000000,U4113,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,
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,
-03000000300f00000701000000000000,USB 4-Axis 12-Button 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:a2,start:b9,x:b3,y:b0,platform:Windows,
-03000000341a00002308000000000000,USB gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
-030000005509000000b4000000000000,USB gamepad,a:b10,b:b11,back:b5,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,guide:b14,leftshoulder:b8,leftstick:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b4,x:b12,y:b13,platform:Windows,
-030000006b1400000203000000000000,USB gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
-03000000790000000a00000000000000,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:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
-03000000f0250000c183000000000000,USB gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-03000000ff1100004133000000000000,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:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
-03000000632500002305000000000000,USB Vibration Joystick (BM),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 Game 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 Game 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,
+03000000300f00000701000000000000,USB Game 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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000341a00002308000000000000,USB Game 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:Windows,
+03000000666600000188000000000000,USB Game Controller,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,
+03000000666600000288000000000000,USB Game Controller,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,
+030000006b1400000203000000000000,USB Game 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:Windows,
+03000000790000000a00000000000000,USB Game 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:a4,start:b9,x:b3,y:b0,platform:Windows,
+03000000b404000081c6000000000000,USB Game 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,
+03000000b50700001503000000000000,USB Game 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:a5,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
+03000000bd12000012d0000000000000,USB Game Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
+03000000f0250000c183000000000000,USB Game 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,
+03000000ff1100004133000000000000,USB Game 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:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000632500002305000000000000,USB Vibration Joystick,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,
03000000790000001a18000000000000,Venom,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,
03000000790000001b18000000000000,Venom Arcade Joystick,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:Windows,
030000006f0e00000302000000000000,Victrix Pro Fight Stick for PS4,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:Windows,
030000006f0e00000702000000000000,Victrix Pro Fight Stick for 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,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows,
+03000000120c0000ab57000000000000,Warrior Joypad JS083,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+030000007e0500003003000000000000,WiiU Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
+0300000032150000030a000000000000,Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000ff02000000000000,Wired Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000ea02000000000000,Wireless Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+0300000032150000140a000000000000,Wolverine,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000002e160000efbe000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700001647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700002045000000000000,Xbox 360 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700002644000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a5,start:b8,x:b2,y:b3,platform:Windows,
+03000000380700002647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000003807000026b7000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700003647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a7,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400001907000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400009102000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000000fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000001fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000016f0000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b00008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c62400000053000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c6240000fdfa000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000a102000000000000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+03000000120c00001088000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2~,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5~,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows,
+03000000300f00008888000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:b13,dpleft:b10,dpright:b11,dpup:b12,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+03000000380700001645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+03000000380700002645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700003645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+03000000380700008645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400000202000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000005e0400008502000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400008702000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000000d0f00006300000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400000c0b000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000fd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e0000a802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e0000c802000000000000,Xbox One Controller,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:Windows,
+03000000c62400003a54000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e040000130b000000000000,Xbox Series 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:Windows,
03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
-03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,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:Windows,
-03000000ac0500005b05000000000000,Xiaoji 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:Windows,
+03000000450c00002043000000000000,Xeox Gamepad SL6556BK,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:Windows,
+030000006f0e00000300000000000000,XGear,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:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000ac0500005b05000000000000,Xiaoji 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:Windows,
03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000786901006e70000000000000,XInput 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:Windows,
xinput,XInput 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:Windows,
-03000000790000004f18000000000000,ZD-T 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,
-03000000120c0000101e000000000000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000790000004f18000000000000,ZDT Android 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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000120c0000101e000000000000,Zeroplus P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
# Mac OS X
030000008f0e00000300000009010000,2In1 USB Joystick,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:Mac OS X,
@@ -369,13 +706,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001590000001000000,8BitDo N30 Pro 2,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:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00006528000000010000,8BitDo N30 Pro 2,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:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d000012ab000001000000,8BitDo NES30,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,
+03000000c82d00002028000000010000,8BitDo NES30,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,
030000003512000012ab000001000000,8BitDo NES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Mac OS X,
03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Mac OS X,
03000000c82d00000190000001000000,8Bitdo NES30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Mac OS X,
03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001290000001000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
-03000000c82d00004028000000010000,8Bitdo SN30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,platform:Mac OS X,
+03000000c82d00004028000000010000,8Bitdo SN30 GamePad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
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+,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,
@@ -385,42 +724,46 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000a00500003232000008010000,8Bitdo Zero GamePad,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,
03000000a00500003232000009010000,8Bitdo Zero GamePad,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,
+03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X,
+03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000ef0500000300000000020000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X,
-03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X,
-03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
03000000c62400001b89000000010000,BDA MOGA XP5-X 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: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,
03000000d62000002a79000000010000,BDA PS4 Fightpad,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,
-03000000120c0000200e000000010000,Brook Mars,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,
-03000000120c0000210e000000010000,Brook Mars,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,
+03000000120c0000200e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000120c0000210e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008305000031b0000000000000,Cideko AK08b,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,
+03000000d8140000cecf000000000000,Cthulhu,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,
03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00008400000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00008500000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger: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,
+03000000151900004000000001000000,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:Mac OS X,
+03000000b40400001124000000000000,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:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle3:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Mac OS X,
03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
-03000000ad1b000001f9000000000000,Gamestop BB-070 X360 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,
+03000000ad1b000001f9000000000000,Gamestop BB070 X360 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,
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:Mac OS X,
03000000c01100000140000000010000,GameStop PS4 Fun 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,
030000006f0e00000102000000000000,GameStop Xbox 360 Wired 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,
030000007d0400000540000001010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000280400000140000000020000,Gravis Gamepad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
-030000008f0e00000300000007010000,GreenAsia Inc. USB Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X,
+030000008f0e00000300000007010000,GreenAsia USB Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X,
030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
-030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
-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,
-030000000d0f00005f00000000000000,HORI Fighting Commander 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
-030000000d0f00005e00000000000000,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,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,
-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,
+030000000d0f00005f00000000000000,Hori Fighting Commander 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00005f00000000010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00005e00000000000000,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,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,
+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,
+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,
030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro Pad,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,
-030000000d0f00006e00000000010000,HORIPAD 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
-030000000d0f00006600000000010000,HORIPAD 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
-030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
-030000000d0f0000ee00000000010000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00006e00000000010000,Horipad 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00006600000000010000,Horipad 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00006600000000000000,Horipad FPS Plus 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X,
-03000000830500006020000000010000,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:Mac OS X,
-03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,
+03000000830500006020000000000000,iBuffalo Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,
030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X,
030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000242f00002d00000007010000,JYS Wireless Adapter,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,
@@ -429,7 +772,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),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,
030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),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,
-030000006d04000019c2000005030000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000006d04000019c2000005030000,Logitech F710 Gamepad,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,
030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),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,
030000006d04000018c2000000010000,Logitech RumblePad 2 USB,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,
030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),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,
@@ -437,7 +780,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000380700005082000000010000,Mad Catz FightPad PRO (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:Mac OS X,
03000000380700008433000000010000,Mad Catz FightStick TE S+ (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,
03000000380700008483000000010000,Mad Catz FightStick TE S+ (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:Mac OS X,
-03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,
+03000000790000000600000007010000,Marvo GT-004,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:Mac OS X,
03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,
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,
@@ -445,21 +788,20 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
0300000025090000e803000000000000,Mayflash Wii Classic Controller,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,
03000000790000000018000000010000,Mayflash Wii U Pro Controller 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,
03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),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,
-03000000d8140000cecf000000000000,MC Cthulhu,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,
-030000005e0400002700000001010000,Microsoft SideWinder Plug & Play Game Pad,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,leftx:a0,lefty:a1,righttrigger:b5,x:b2,y:b3,platform:Mac OS X,
+030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X,
03000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
-03000000c62400002a89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,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,
-03000000c62400002b89000000010000,MOGA XP5-A 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: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,
+03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,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,
+03000000c62400002b89000000010000,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: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,
03000000632500007505000000020000,NEOGEO mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X,
030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X,
-03000000d620000011a7000000020000,Nintendo Switch Core (Plus) Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger: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,
+03000000d620000011a7000000020000,Nintendo Switch Core Plus Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger: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,
03000000d620000011a7000010050000,Nintendo Switch PowerA Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger: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,
03000000550900001472000025050000,NVIDIA Controller v01.04,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,
030000006f0e00000901000002010000,PDP Versus Fighting Pad,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,
-030000008f0e00000300000000000000,Piranha xtreme,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:Mac OS X,
+030000008f0e00000300000000000000,Piranha Xtreme PS3 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:Mac OS X,
030000004c050000da0c000000010000,Playstation Classic 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:Mac OS X,
030000004c0500003713000000010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000d62000006dca000000010000,PowerA Pro Ex,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,
@@ -472,15 +814,17 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
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,misc1:b13,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,
-03000000321500000204000000010000,Razer Panthera (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,
-03000000321500000104000000010000,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:Mac OS X,
-03000000321500000010000000010000,Razer RAIJU,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,
+03000000321500000204000000010000,Razer Panthera 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,
+03000000321500000104000000010000,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:Mac OS X,
+03000000321500000010000000010000,Razer Raiju,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,
03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,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,
03000000321500000011000000010000,Razer Raion Fightpad for 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:Mac OS X,
03000000321500000009000000020000,Razer Serval,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:Mac OS X,
030000003215000000090000163a0000,Razer Serval,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:Mac OS X,
0300000032150000030a000000000000,Razer Wildcat,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,
-03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,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,
@@ -498,22 +842,24 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X,
03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
+05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,
050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,
+05000000556e6b6e6f776e2048494400,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,
03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,
03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,
-03000000457500002211000000010000,SZMY-POWER PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,
030000004f0400000ed0000000020000,ThrustMaster eSwap 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,
030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,
03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
-03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000bd12000015d0000000010000,Tomee Retro Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform: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,
030000006f0e00000302000025040000,Victrix Pro Fight Stick for PS4,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 Pro Fight Stick for 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,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000791d00000103000009010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,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,
050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,
-030000005e0400008e02000000000000,X360 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,
+030000005e0400008e02000000000000,Xbox 360 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,
030000006f0e00000104000000000000,Xbox 360 Wired 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,
03000000c6240000045d000000000000,Xbox 360 Wired 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,
030000005e0400000a0b000000000000,Xbox Adaptive 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,
@@ -524,28 +870,33 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000e302000000000000,Xbox One Wired 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,
030000005e040000130b000001050000,Xbox Series 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,
030000005e040000130b000005050000,Xbox Series 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,
+030000005e040000130b000009050000,Xbox Series 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 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,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000e002000000000000,Xbox Wireless 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,
-030000005e040000e002000003090000,Xbox Wireless 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,
+030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,x:b3,y:b4,back:b16,guide:b15,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,
030000005e040000ea02000000000000,Xbox Wireless 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,
030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,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:Mac OS X,
03000000172700004431000029010000,XiaoMi Game Controller,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,
-03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger: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,
-03000000120c0000101e000000010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger: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,
+03000000120c0000100e000000010000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger: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,
+03000000120c0000101e000000010000,Zeroplus P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger: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,
# Linux
+03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Linux,
03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00001038000000010000,8Bitdo FC30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Linux,
05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux,
05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux,
+03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,
05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,
03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Linux,
+03000000c82d00000190000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Linux,
05000000c82d00002038000000010000,8Bitdo NES30 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:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
-03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Linux,
05000000c82d00000061000000010000,8Bitdo SF30 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:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+030000003512000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
030000003512000012ab000010010000,8Bitdo SFC30 GamePad,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
@@ -566,12 +917,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005e040000e002000030110000,8BitDo Zero 2 (XInput),a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
05000000a00500003232000008010000,8Bitdo Zero GamePad,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:Linux,
-03000000c01100000355000011010000,ACRUX USB GAME PAD,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,
+03000000c01100000355000011010000,Acrux Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006f0e00001302000000010000,Afterglow,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,
030000006f0e00003901000020060000,Afterglow Controller for 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,
030000006f0e00003901000000430000,Afterglow Prismatic 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,
030000006f0e00003901000013020000,Afterglow Prismatic Wired Controller 048-007-NA,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,
-03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000100000008200000011010000,Akishop Customs PS360 v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000007c1800000006000010010000,Alienware Dual Compatible Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
05000000491900000204000021000000,Amazon Fire Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux,
@@ -579,80 +930,86 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
-05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
-05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
+05000000050b00000045000031000000,Asus Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
+05000000050b00000045000040000000,Asus Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
03000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux,
05000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux,
-03000000503200000210000000000000,Atari Game 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:b3,y:b2,platform:Linux,
+03000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux,
05000000503200000210000000000000,Atari Game 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:b3,y:b2,platform:Linux,
03000000120c00000500000010010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,
03000000ef0500000300000000010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,
-03000000c62400001b89000011010000,BDA MOGA XP5-X 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:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c62400001b89000011010000,BDA 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:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000d62000002a79000011010000,BDA PS4 Fightpad,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,
-03000000c21100000791000011010000,Be1 GC101 Controller 1.03 mode,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
-03000000c31100000791000011010000,Be1 GC101 GAMEPAD 1.03 mode,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-030000005e0400008e02000003030000,Be1 GC101 Xbox 360 Controller mode,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,
-03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,
-03000000120c0000200e000011010000,Brook Mars,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
-03000000120c0000210e000011010000,Brook Mars,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,
+03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000c31100000791000011010000,Be1 GC101 GAMEPAD 1.03,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000005e0400008e02000003030000,Be1 GC101 Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+05000000bc2000000055000001000000,BETOP AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000006b1400000209000011010000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000666600006706000000010000,Boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,
+03000000120c0000200e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000120c0000210e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
-03000000ffff0000ffff000000010000,Chinese-made Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux,
03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,
-03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
-03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,
-03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,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,
+03000000a306000022f6000011010000,Cyborg V3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
030000004f04000004b3000010010000,Dual Power 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
030000006f0e00003001000001010000,EA Sports 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,
-03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
+03000000c11100000191000011010000,EasySMX,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,
+030000006e0500000320000010010000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,
+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,
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,
+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,
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 Co. Ltd PS(R) 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,
-030000006f0e00001304000000010000,Generic X-Box pad,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,
03000000451300000010000010010000,Genius Maxfire Grandias 12,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,
-03000000f0250000c183000010010000,Goodbetterbest Ltd USB 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,
+03000000f0250000c183000010010000,Goodbetterbest 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,
0300000079000000d418000000010000,GPD Win 2 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,
030000007d0400000540000000010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
-03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
-030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,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:a2,start:b11,x:b3,y:b0,platform:Linux,
-030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,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:b2,y:b3,platform:Linux,
+03000000280400000140000000010000,Gravis GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+030000008f0e00000610000000010000,GreenAsia Electronics Controller,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:a2,start:b11,x:b3,y:b0,platform:Linux,
+030000008f0e00001200000010010000,GreenAsia USB Joystick,a:b0,b:b1,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:b2,y:b3,platform:Linux,
0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,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,
03000000f0250000c383000010010000,GT VX2,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,
06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
-03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,
-03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
-03000000632500002605000010010000,HJD-X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,
-030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 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,
-030000000d0f0000c100000011010000,HORI CO. LTD. HORIPAD S,a:b1,b:b2,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:b0,y:b3,platform:Linux,
-030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
-030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
-030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,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,
-030000000d0f00008500000010010000,HORI Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,
+03000000c9110000f055000011010000,HJC Game Gamepqd,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000632500002605000010010000,HJDX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000000d0f00000d00000000010000,Hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,
+030000000d0f00008500000010010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger: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,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,
-030000000d0f00005f00000011010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
-030000000d0f00005e00000011010000,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:Linux,
+030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00005e00000011010000,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:Linux,
+030000000d0f00005001000009040000,Hori Fighting Commander OCTA,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,
+030000000d0f00001000000011010000,Hori Fighting Stick 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,
03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,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,
+030000000d0f00003801000011010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Linux,
030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro Pad,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:Linux,
-030000000d0f0000aa00000011010000,HORI Real Arcade 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,
-030000000d0f0000d800000072056800,HORI Real Arcade Pro S,a:b0,b:b1,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:b2,y:b3,platform:Linux,
-030000000d0f00001600000000010000,Hori Real Arcade Pro.EX-SE (Xbox 360),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
-030000000d0f00006e00000011010000,HORIPAD 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
-030000000d0f00006600000011010000,HORIPAD 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
-030000000d0f0000ee00000011010000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
-030000000d0f00006700000001010000,HORIPAD 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,
+030000000d0f0000aa00000011010000,Hori Real Arcade 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,
+030000000d0f00002200000011010000,Hori Real Arcade Pro 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,
+030000000d0f00006a00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00006b00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00001600000000010000,Hori Real Arcade Pro EXSE,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
+030000000d0f00006e00000011010000,Horipad 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00006600000011010000,Horipad 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00006700000001010000,Horipad 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,
+030000000d0f0000c100000011010000,Horipad S,a:b1,b:b2,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:b0,y:b3,platform:Linux,
+03000000341a000005f7000010010000,HuiJia GameCube Controller Adpater,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,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,
-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,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
-03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
-03000000d80400008200000003000000,IMS PCU#0 Gamepad Interface,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux,
-03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux,
-0500000049190000020400001b010000,Ipega PG-9069 - Bluetooth Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,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,
-03000000632500007505000011010000,Ipega PG-9099 - Bluetooth 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,
-030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,
+050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
+03000000d80400008200000003000000,IMS PCU0 Gamepad,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux,
+03000000fd0500000030000000010000,InterAct GoPad I73000,a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux,
+0500000049190000020400001b010000,Ipega PG 9069 Bluetooth Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,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,
+03000000632500007505000011010000,Ipega PG 9099 Bluetooth 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,
+0500000049190000030400001b010000,Ipega PG9099,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,
+05000000491900000204000000000000,Ipega PG9118,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,
03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,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,
03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil Pad,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:a2,start:b9,x:b3,y:b0,platform:Linux,
03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,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,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
@@ -664,7 +1021,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000242f00002d00000011010000,JYS Wireless Adapter,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,
03000000242f00008a00000011010000,JYS Wireless Adapter,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:Linux,
030000006f0e00000103000000020000,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,
-030000006d040000d1ca000000000000,Logitech ChillStream,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,
+030000006d040000d1ca000000000000,Logitech Chillstream,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,
030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,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,
030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
@@ -673,62 +1030,68 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),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,
030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),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,
030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),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,
-030000006d0400000ac2000010010000,Logitech Inc. WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux,
030000006d04000018c2000010010000,Logitech RumblePad 2,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,
030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,
-050000004d4f435554452d3035305800,M54-PC,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-05000000380700006652000025010000,Mad Catz C.T.R.L.R ,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,
-03000000380700005032000011010000,Mad Catz FightPad PRO (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,
-03000000380700005082000011010000,Mad Catz FightPad PRO (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,
+030000006d0400000ac2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux,
+05000000380700006652000025010000,Mad Catz CTRLR,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,
+03000000380700005032000011010000,Mad Catz FightPad PRO 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,
+03000000380700005082000011010000,Mad Catz FightPad PRO 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,
03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,
-03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
-03000000380700008084000011010000,Mad Catz fightstick (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:Linux,
-03000000380700008433000011010000,Mad Catz FightStick TE S+ (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,
-03000000380700008483000011010000,Mad Catz FightStick TE S+ (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,
+03000000380700008034000011010000,Mad Catz fightstick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000380700008084000011010000,Mad Catz fightstick 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:Linux,
+03000000380700008433000011010000,Mad Catz FightStick TE S 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,
+03000000380700008483000011010000,Mad Catz FightStick TE S 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,
03000000380700001647000010040000,Mad Catz Wired 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,
-03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000ad1b000016f0000090040000,Mad Catz 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,
03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
-03000000242f0000f700000001010000,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,
03000000120c00000500000000010000,Manta Dualshock 2,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:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000790000004318000010010000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
03000000242f00007300000011010000,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:Linux,
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,
0300000025090000e803000001010000,Mayflash Wii Classic Controller,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,
03000000780000000600000010010000,Microntek USB 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,
030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,
-030000005e0400008e02000004010000,Microsoft X-Box 360 pad,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,
-030000005e0400008e02000062230000,Microsoft X-Box 360 pad,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,
-050000005e040000050b000003090000,Microsoft X-Box One Elite 2 pad,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-030000005e040000e302000003020000,Microsoft X-Box One Elite pad,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,
-030000005e040000d102000001010000,Microsoft X-Box One pad,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,
-030000005e040000dd02000003020000,Microsoft X-Box One pad (Firmware 2015),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,
-030000005e040000d102000003020000,Microsoft X-Box One pad v2,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,
-030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
-030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
-030000005e040000000b000008040000,Microsoft Xbox One Elite 2 pad - Wired,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,
-030000005e040000ea02000008040000,Microsoft Xbox One S pad - Wired,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,
-03000000c62400001a53000000010000,Mini PE,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,
+030000005e0400000700000000010000,Microsoft SideWinder Game Pad USB,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux,
+030000005e0400002700000000010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000056210000,Microsoft X-Box 360 pad,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,
+030000005e0400008e02000004010000,Microsoft Xbox 360 pad,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,
+030000005e0400008e02000062230000,Microsoft Xbox 360 pad,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,
+030000005e040000000b000008040000,Microsoft Xbox One Elite 2 pad,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,
+050000005e040000050b000003090000,Microsoft Xbox One Elite 2 pad,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000005e040000e302000003020000,Microsoft Xbox One Elite pad,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,
+030000005e040000d102000001010000,Microsoft Xbox One pad,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,
+030000005e040000dd02000003020000,Microsoft Xbox One pad 2015,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,
+030000005e040000d102000003020000,Microsoft Xbox One pad v2,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,
+030000005e040000ea02000008040000,Microsoft Xbox One S pad,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,
+030000005e0400008502000000010000,Microsoft Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
+030000005e0400008902000021010000,Microsoft Xbox pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
+050000004d4f435554452d3035335800,Mocute 053X,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,
+050000004d4f435554452d3035305800,Mocute 054X,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,
05000000d6200000e589000001000000,Moga 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
05000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
-03000000c62400002b89000011010000,MOGA XP5-A 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:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-05000000c62400002a89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,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,
-05000000c62400001a89000000010000,MOGA XP5-X 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:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-03000000250900006688000000010000,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:Linux,
-030000006b140000010c000010010000,NACON GC-400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000c62400002b89000011010000,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:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,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,
+05000000c62400001a89000000010000,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:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000250900006688000000010000,MP8866 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:Linux,
+030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000000d0f00000900000010010000,Natec Genesis P44,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,
-03000000790000004518000010010000,NEXILUX GAMECUBE Controller Adapter,a:b1,b:b0,x:b2,y:b3,start:b9,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,platform:Linux,
+030000004f1f00000800000011010000,Neogeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000790000004518000010010000,Nexilux GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux,
060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
060000007e0500000820000000000000,Nintendo Combined Joy-Cons (joycond),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,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,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,
+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,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:b9,b:b8,back:b5,leftshoulder:b2,leftstick:b6,leftx:a1,lefty:a0~,rightshoulder:b4,start:b0,x:b7,y:b10,platform:Linux,
+03000000d620000013a7000011010000,Nintendo Switch PowerA Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,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,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,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,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
@@ -741,34 +1104,35 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
05000000550900001472000001000000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
-19000000010000000100000001010000,odroidgo2_joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,
-19000000010000000200000011000000,odroidgo2_joypad_v11,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux,
-030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
+19000000010000000100000001010000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,
+19000000010000000200000011000000,odroidgo2 joypad v11,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux,
03000000c0160000dc27000001010000,OnyxSoft Dual JoyDivision,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:Linux,
05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,
05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,
03000000830500005020000010010000,Padix Co. Ltd. Rockfire PSX/USB Bridge,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Linux,
03000000790000001c18000011010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
-030000006f0e0000b802000001010000,PDP AFTERGLOW Wired 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,
-030000006f0e0000b802000013020000,PDP AFTERGLOW Wired 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,
+030000006f0e0000b802000001010000,PDP Afterglow Wired 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,
+030000006f0e0000b802000013020000,PDP Afterglow Wired 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,
030000006f0e00006401000001010000,PDP Battlefield 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,
-030000006f0e00008001000011010000,PDP CO. LTD. Faceoff Wired Pro Controller for Nintendo Switch,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,
030000006f0e00003101000000010000,PDP EA Sports 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,
+030000006f0e00008001000011010000,PDP Faceoff Wired Pro Controller for Nintendo Switch,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,
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,
030000006f0e00008701000011010000,PDP Rock Candy Wired Controller for Nintendo Switch,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 Pad,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 Wired Controller for Xbox One,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,
030000006f0e00008501000011010000,PDP Wired Fight Pad Pro for Nintendo Switch,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,
-0500000049190000030400001b010000,PG-9099,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,
-05000000491900000204000000000000,PG-9118,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,
+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,
030000004c050000da0c000011010000,Playstation 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,
+03000000d9040000160f000000010000,Playstation Controller 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,
030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000c62400000053000000010000,PowerA,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,
03000000c62400003a54000001010000,PowerA 1428124-01,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,
+03000000c62400001a53000000010000,PowerA Mini Pro Ex,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,
03000000d62000006dca000011010000,PowerA Pro Ex,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,
03000000d62000000228000001010000,PowerA Wired Controller for 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,
-03000000c62400001a58000001010000,PowerA Xbox One Cabled,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,
+03000000d62000000220000001010000,PowerA Wired Controller for Xbox One and Xbox Series S and X,a:b0,b:b1,back:b7,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:b6,x:b2,y:b3,platform:Linux,
+03000000c62400001a58000001010000,PowerA 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,
03000000c62400001a54000001010000,PowerA Xbox One Mini 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,
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,
@@ -802,18 +1166,21 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000ff000000cb01000010010000,PSP,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
-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,
+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,
+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,
030000009b2800004200000001010000,Raphnet Technologies Dual NES to USB v2.0,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux,
030000009b2800003200000001010000,Raphnet Technologies GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
030000009b2800006000000001010000,Raphnet Technologies GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,
030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
030000008916000000fd000024010000,Razer Onza Tournament Edition,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,
-03000000321500000204000011010000,Razer Panthera (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,
-03000000321500000104000011010000,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:Linux,
03000000321500000810000011010000,Razer Panthera Evo Arcade Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,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,
-03000000321500000010000011010000,Razer RAIJU,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,
+03000000321500000204000011010000,Razer Panthera 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,
+03000000321500000104000011010000,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:Linux,
03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,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,
+05000000321500000a10000001000000,Razer Raiju Tournament Edition,a:b1,b:b2,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:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000321500000710000000010000,Razer Raiju Tournament Edition Wired,a:b1,b:b2,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:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000321500000010000011010000,Razer Rainu,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,
03000000321500000011000011010000,Razer Raion Fightpad for 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,
030000008916000000fe000024010000,Razer Sabertooth,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,
03000000c6240000045d000024010000,Razer Sabertooth,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,
@@ -821,36 +1188,39 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000321500000009000011010000,Razer Serval,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,
050000003215000000090000163a0000,Razer Serval,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,
0300000032150000030a000001010000,Razer Wildcat,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,
-03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
+03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux,
0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux,
0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,
030000006b140000010d000011010000,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:Linux,
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,
+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 V.1 Game Pad,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,
03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux,
03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux,
03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b0,y:b1,platform:Linux,
03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,
+03000000a306000018f5000010010000,Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000300f00001201000010010000,Saitek P380,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,
03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,
03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,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:a2,start:b8,x:b0,y:b3,platform:Linux,
-03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000a306000020f6000011010000,Saitek PS2700 Rumble Pad,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,
03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux,
-03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
-03000000632500007505000010010000,SHANWAN PS3/PC Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
-03000000bc2000000055000010010000,ShanWan PS3/PC Wired GamePad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-030000005f140000c501000010010000,SHANWAN 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,
+03000000a30c00002500000011010000,Sega Genesis Mini 3B controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux,
+030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
+03000000f025000021c1000010010000,Shanwan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000632500007505000010010000,Shanwan PS3 PC Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000bc2000000055000010010000,Shanwan PS3 PC Wired GamePad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000005f140000c501000010010000,Shanwan 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,
03000000632500002305000010010000,ShanWan 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:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
-03000000341a00000908000010010000,SL-6566,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,
+03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000004c050000e60c000011810000,Sony DualSense,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
-050000004c050000e60c000000810000,Sony DualSense ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+050000004c050000e60c000000810000,Sony DualSense,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,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:Linux,
-030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,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 Gamepad pad,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,
+030000005e0400008e02000073050000,Speedlink Torid Wireless Gamepad,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 Gamepad pad,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,
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,
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,
@@ -870,13 +1240,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000003b07000004a1000000010000,Suncom SFX Plus for USB,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux,
03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,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:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,
-03000000457500002211000010010000,SZMY-POWER CO. LTD. 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,
-030000008f0e00000d31000010010000,SZMY-POWER CO. LTD. GAMEPAD 3 TURBO,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,
-030000008f0e00001431000010010000,SZMY-POWER CO. LTD. PS3 gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000008f0e00000d31000010010000,SZMY Power 3 Turbo,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,
+03000000457500002211000010010000,SZMY Power Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+030000008f0e00001431000010010000,SZMY Power PS3 gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux,
030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
-030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
-030000004f0400000ed0000011010000,ThrustMaster eSwap 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:Linux,
+030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3 in 1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000004f0400000ed0000011010000,Thrustmaster eSwap 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:Linux,
03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux,
030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux,
030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,
@@ -887,49 +1258,65 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000004f04000007d0000000010000,Thrustmaster T Mini Wireless,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,
030000004f04000012b3000010010000,Thrustmaster vibrating gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
-03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
+03000000d814000007cd000011010000,Toodles 2008 Chimp PC PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
030000005e0400008e02000070050000,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,
03000000c01100000591000011010000,Torid,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,
03000000100800000100000010010000,Twin USB 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,
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 Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,
+03000000790000001100000011010000,USB Saturn Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux,
+03000000790000002201000011010000,USB Saturn Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
+03000000b40400000a01000000010000,USB Saturn Pad,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
030000006f0e00000302000011010000,Victrix Pro Fight Stick for PS4,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,
030000006f0e00000702000011010000,Victrix Pro Fight Stick for 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,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
-05000000ac0500003232000001000000,VR-BOX,a:b0,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:b2,y:b3,platform:Linux,
+05000000ac0500003232000001000000,VR Box Controller,a:b0,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:b2,y:b3,platform:Linux,
03000000791d00000103000010010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
050000000d0f0000f600000001000000,Wireless HORIPAD 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:Linux,
-030000005e0400008e02000010010000,X360 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,
-030000005e0400008e02000014010000,X360 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,
-030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
-030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
-030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
-030000005e040000a102000007010000,X360 Wireless 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,
+030000005e0400008e02000010010000,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,
+030000005e0400008e02000014010000,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,
0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,
-030000005e040000a102000014010000,Xbox 360 Wireless Receiver (XBOX),a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
-0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),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,
+030000005e0400001907000000010000,Xbox 360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
+030000005e0400009102000007010000,Xbox 360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
+030000005e040000a102000000010000,Xbox 360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
+030000005e040000a102000007010000,Xbox 360 Wireless 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,
+030000005e0400008e02000000010000,Xbox 360 Wireless EasySMX,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,
+030000005e040000a102000014010000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
+030000006f0e00001304000000010000,Xbox 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,
+03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
+0000000058626f782047616d65706100,Xbox Gamepad,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,
+030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
030000005e040000d102000002010000,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,
050000005e040000fd02000030110000,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,
+050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000005e040000ea02000000000000,Xbox One Wireless 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,
050000005e040000e002000003090000,Xbox One Wireless 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:Linux,
050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,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,
030000005e040000ea02000001030000,Xbox One Wireless Controller (Model 1708),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,
+060000005e040000120b000007050000,Xbox One Wireless Controller (Model 1914),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,
+030000005e0400000202000000010000,Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
030000005e040000120b000001050000,Xbox Series 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,
+030000005e040000120b000005050000,Xbox Series 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,
030000005e040000130b000005050000,Xbox Series 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:Linux,
050000005e040000130b000001050000,Xbox Series 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:Linux,
050000005e040000130b000005050000,Xbox Series 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:Linux,
-030000005e040000120b000005050000,XBox Series pad,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,
-030000005e0400008e02000000010000,xbox360 Wireless EasySMX,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,
-03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,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,
-03000000ac0500005b05000010010000,Xiaoji 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,
+03000000450c00002043000010010000,XEOX Gamepad SL6556 BK,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,
+03000000ac0500005b05000010010000,Xiaoji 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,
05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,
-03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,
+03000000c0160000e105000001010000,XinMo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,
xinput,XInput 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,
-03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
-03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000120c0000100e000011010000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000120c0000101e000011010000,Zeroplus P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
# Android
+38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android,
+33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android,
+39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android,
+64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android,
+66356438346136366337386437653934,8BitDo M30,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,start:b18,x:b19,y:b2,platform:Android,
+66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android,
05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android,
05000000c82d000051060000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android,
05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
@@ -938,60 +1325,151 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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:Android,
05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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:Android,
+38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android,
+61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android,
05000000c82d000012900000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
05000000c82d000062280000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,
+38303232393133383836366330346462,8BitDo SN30 Pro Plus,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,
+38346630346135363335366265656666,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+66306331643531333230306437353936,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
05000000c82d000002600000ffff0f00,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
050000002028000009000000ffff3f00,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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:Android,
050000003512000020ab000000780f00,8BitDo SNES30 Gamepad,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android,
+33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
-38383337343564366131323064613561,Brook Mars,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
+34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
+63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
+32333634613735616163326165323731,Amazon Luna Game Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,
+38383337343564366131323064613561,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+33323763323132376537376266393366,Dual Strike,a:b24,b:b23,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android,
+30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android,
+05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+34323662653333636330306631326233,Google Nexus,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+35383633353935396534393230616564,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,
0500000031366332860c44aadfff0f00,GS Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
-0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b3,y:b2,platform:Android,
+66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
+35623466343433653739346434636330,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,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,start:b18,x:b0,y:b2,platform:Android,
+65656436646661313232656661616130,Hori PC Engine Mini Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b18,platform:Android,
+31303433326562636431653534636633,Hori Real Arcade Pro 3,a:b1,b:b19,back:b17,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,start:b18,x:b0,y:b2,platform:Android,
+0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,platform:Android,
+64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android,
+65346535636333663931613264643164,Joy Con,a:b21,b:b22,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:b23,y:b24,platform:Android,
+33346566643039343630376565326335,Joy Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android,
+35313531613435623366313835326238,Joy Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android,
+38383665633039363066383334653465,Joy Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
+39363561613936303237333537383931,Joy Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
+39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android,
+64623163333561643339623235373232,Logitech F310,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+64396331333230326333313330336533,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android,
+32303165626138343962363666346165,Mars,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+31323564663862633234646330373138,Mega Drive,a:b23,b:b22,leftx:a0,lefty: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,
+30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,leftshoulder:b20,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android,
64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,
+32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,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,
+33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android,
050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android,
+34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
050000005509000003720000cf7f3f00,NVIDIA Controller v01.01,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,
050000005509000010720000ffff3f00,NVIDIA Controller v01.03,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,
050000005509000014720000df7f3f00,NVIDIA Controller v01.04,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,
+61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android,
+32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android,
+61363034663839376638653463633865,PS3,a:b0,b:b1,back:b15,dpdown:a14,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+66366539656564653432353139356536,PS3,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,
+66383132326164626636313737373037,PS3,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,
050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,
-030000004c050000cc09000000006800,PS4 Controller,a:b0,b:b1,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:b2,y:b3,platform:Android,
+30303839663330346632363232623138,PS4,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
+31326235383662333266633463653332,PS4,a:b1,b:b16,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b17,x:b0,y:b2,platform:Android,
+31663838336334393132303338353963,PS4,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+34613139376634626133336530386430,PS4,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+37626233336235343937333961353732,PS4,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+38393161636261653636653532386639,PS4,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+63313733393535663339656564343962,PS4,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+63393662363836383439353064663939,PS4,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+65366465656364636137653363376531,PS4,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+66613532303965383534396638613230,PS4,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,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:b2,y:b3,platform:Android,
050000004c050000c4050000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,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:b2,y:b3,platform:Android,
050000004c050000cc090000fffe3f00,PS4 Controller,a:b0,b:b1,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:b2,y:b3,platform:Android,
050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,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:b2,y:b3,platform:Android,
+31373231336561636235613666323035,PS4 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,
35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
+62653335326261303663356263626339,PSX,a:b19,b:b1,back:b17,leftshoulder:b9,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android,
+64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,
+36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,
050000003215000007070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,
050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,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,x:b2,y:b3,platform:Android,
+61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android,
+38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b6,platform:Android,
+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 Mobile,a:b21,b:b22,leftshoulder:b23,leftx:a0,lefty:a1,rightshoulder: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,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,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,
+66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,
+66633132393363353531373465633064,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,
+62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
32633532643734376632656664383733,Sony DualSense,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
61303162353165316365336436343139,Sony DualSense,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
+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,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,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,
050000004f0400000ed00000fffe3f00,ThrustMaster eSwap PRO Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,
+30623739343039643830333266346439,Valve Steam 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,leftx:a0,lefty:a1,paddle1:b23,paddle2:b24,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+31643365666432386133346639383937,Valve Steam 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,leftx:a0,lefty:a1,paddle1:b23,paddle2:b24,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+30386438313564306161393537333663,Wii Classic,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android,
+33333034646336346339646538643633,Wii Classic,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android,
30306539356238653637313730656134,Wireless HORIPAD Switch Pro Controller,a:b0,b:b1,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,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,
+30396232393162346330326334636566,Xbox 360,a:b0,b:b1,back:b4,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,
+38313038323730383864666463383533,Xbox 360,a:b0,b:b1,back:b4,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,
+65353331386662343338643939643636,Xbox 360,a:b0,b:b1,back:b4,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,
+65613532386633373963616462363038,Xbox 360,a:b0,b:b1,back:b4,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,
050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,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:b2,y:b3,platform:Android,
+33356661323266333733373865656366,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
+35623965373264386238353433656138,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
050000005e040000000b000000783f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
050000005e040000e002000000783f00,Xbox One S Controller,a:b0,b:b1,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:b2,y:b3,platform:Android,
050000005e040000ea02000000783f00,Xbox One S Controller,a:b0,b:b1,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:b2,y:b3,platform:Android,
050000005e040000fd020000ff7f3f00,Xbox One S Controller,a:b0,b:b1,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:b2,y:b3,platform:Android,
050000005e040000e00200000ffe3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android,
-050000005e040000fd020000ffff3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000fd020000ffff3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,
050000005e040000120b000000783f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,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:b2,y:b3,platform:Android,
65633038363832353634653836396239,Xbox Series 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,
050000005e04000091020000ff073f00,Xbox Wireless Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android,
+36616131643361333337396261666433,Xbox Wireless Controller,a:b0,b:b1,back:b15,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,
050000001727000044310000ffff3f00,XiaoMi Game Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,
# iOS
@@ -1017,5 +1495,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,
050000005e040000050b0000df070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
050000005e040000050b0000ff070001,Xbox Elite Wireless Controller,a:b0,b:b1,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,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
+050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
+050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,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,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
050000005e040000e0020000df070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
050000005e040000e0020000ff070000,Xbox Wireless Controller,a:b0,b:b1,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:b2,y:b3,platform:iOS,
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 9195f7d8b5..26df16792d 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,11 +35,7 @@
#include "core/input/input_map.h"
#include "core/os/os.h"
-#ifdef TOOLS_ENABLED
-#include "editor/editor_settings.h"
-#endif
-
-static const char *_joy_buttons[JOY_BUTTON_SDL_MAX] = {
+static const char *_joy_buttons[(size_t)JoyButton::SDL_MAX] = {
"a",
"b",
"x",
@@ -63,7 +59,7 @@ static const char *_joy_buttons[JOY_BUTTON_SDL_MAX] = {
"touchpad",
};
-static const char *_joy_axes[JOY_AXIS_SDL_MAX] = {
+static const char *_joy_axes[(size_t)JoyAxis::SDL_MAX] = {
"leftx",
"lefty",
"rightx",
@@ -95,6 +91,7 @@ Input::MouseMode Input::get_mouse_mode() const {
void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &Input::is_key_pressed);
+ ClassDB::bind_method(D_METHOD("is_physical_key_pressed", "keycode"), &Input::is_physical_key_pressed);
ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &Input::is_mouse_button_pressed);
ClassDB::bind_method(D_METHOD("is_joy_button_pressed", "device", "button"), &Input::is_joy_button_pressed);
ClassDB::bind_method(D_METHOD("is_action_pressed", "action", "exact_match"), &Input::is_action_pressed, DEFVAL(false));
@@ -106,7 +103,6 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_vector", "negative_x", "positive_x", "negative_y", "positive_y", "deadzone"), &Input::get_vector, DEFVAL(-1.0f));
ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false));
ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &Input::remove_joy_mapping);
- ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &Input::joy_connection_changed);
ClassDB::bind_method(D_METHOD("is_joy_known", "device"), &Input::is_joy_known);
ClassDB::bind_method(D_METHOD("get_joy_axis", "device", "axis"), &Input::get_joy_axis);
ClassDB::bind_method(D_METHOD("get_joy_name", "device"), &Input::get_joy_name);
@@ -121,7 +117,11 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_accelerometer"), &Input::get_accelerometer);
ClassDB::bind_method(D_METHOD("get_magnetometer"), &Input::get_magnetometer);
ClassDB::bind_method(D_METHOD("get_gyroscope"), &Input::get_gyroscope);
- ClassDB::bind_method(D_METHOD("get_last_mouse_speed"), &Input::get_last_mouse_speed);
+ ClassDB::bind_method(D_METHOD("set_gravity", "value"), &Input::set_gravity);
+ ClassDB::bind_method(D_METHOD("set_accelerometer", "value"), &Input::set_accelerometer);
+ ClassDB::bind_method(D_METHOD("set_magnetometer", "value"), &Input::set_magnetometer);
+ ClassDB::bind_method(D_METHOD("set_gyroscope", "value"), &Input::set_gyroscope);
+ ClassDB::bind_method(D_METHOD("get_last_mouse_velocity"), &Input::get_last_mouse_velocity);
ClassDB::bind_method(D_METHOD("get_mouse_button_mask"), &Input::get_mouse_button_mask);
ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &Input::set_mouse_mode);
ClassDB::bind_method(D_METHOD("get_mouse_mode"), &Input::get_mouse_mode);
@@ -133,6 +133,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2()));
ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event);
ClassDB::bind_method(D_METHOD("set_use_accumulated_input", "enable"), &Input::set_use_accumulated_input);
+ ClassDB::bind_method(D_METHOD("flush_buffered_events"), &Input::flush_buffered_events);
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
@@ -162,14 +163,12 @@ void Input::_bind_methods() {
}
void Input::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
-#ifdef TOOLS_ENABLED
- const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\"";
-
String pf = p_function;
- if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" ||
- pf == "is_action_just_pressed" || pf == "is_action_just_released" ||
- pf == "get_action_strength" || pf == "get_action_raw_strength" ||
- pf == "get_axis" || pf == "get_vector")) {
+ if (p_idx == 0 &&
+ (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" ||
+ pf == "is_action_just_pressed" || pf == "is_action_just_released" ||
+ pf == "get_action_strength" || pf == "get_action_raw_strength" ||
+ pf == "get_axis" || pf == "get_vector")) {
List<PropertyInfo> pinfo;
ProjectSettings::get_singleton()->get_property_list(&pinfo);
@@ -179,13 +178,12 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S
}
String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length());
- r_options->push_back(name.quote(quote_style));
+ r_options->push_back(name.quote());
}
}
-#endif
}
-void Input::SpeedTrack::update(const Vector2 &p_delta_p) {
+void Input::VelocityTrack::update(const Vector2 &p_delta_p) {
uint64_t tick = OS::get_singleton()->get_ticks_usec();
uint32_t tdiff = tick - last_tick;
float delta_t = tdiff / 1000000.0;
@@ -204,17 +202,17 @@ void Input::SpeedTrack::update(const Vector2 &p_delta_p) {
accum = accum - slice;
accum_t -= min_ref_frame;
- speed = (slice / min_ref_frame).lerp(speed, min_ref_frame / max_ref_frame);
+ velocity = (slice / min_ref_frame).lerp(velocity, min_ref_frame / max_ref_frame);
}
}
-void Input::SpeedTrack::reset() {
+void Input::VelocityTrack::reset() {
last_tick = OS::get_singleton()->get_ticks_usec();
- speed = Vector2();
+ velocity = Vector2();
accum_t = 0;
}
-Input::SpeedTrack::SpeedTrack() {
+Input::VelocityTrack::VelocityTrack() {
min_ref_frame = 0.1;
max_ref_frame = 0.3;
reset();
@@ -225,13 +223,22 @@ bool Input::is_key_pressed(Key p_keycode) const {
return keys_pressed.has(p_keycode);
}
+bool Input::is_physical_key_pressed(Key p_keycode) const {
+ _THREAD_SAFE_METHOD_
+ return physical_keys_pressed.has(p_keycode);
+}
+
bool Input::is_mouse_button_pressed(MouseButton p_button) const {
_THREAD_SAFE_METHOD_
- return (mouse_button_mask & (1 << (p_button - 1))) != 0;
+ return (mouse_button_mask & mouse_button_to_mask(p_button)) != MouseButton::NONE;
+}
+
+static JoyAxis _combine_device(JoyAxis p_value, int p_device) {
+ return JoyAxis((int)p_value | (p_device << 20));
}
-static int _combine_device(int p_value, int p_device) {
- return p_value | (p_device << 20);
+static JoyButton _combine_device(JoyButton p_value, int p_device) {
+ return JoyButton((int)p_value | (p_device << 20));
}
bool Input::is_joy_button_pressed(int p_device, JoyButton p_button) const {
@@ -318,11 +325,11 @@ Vector2 Input::get_vector(const StringName &p_negative_x, const StringName &p_po
if (p_deadzone < 0.0f) {
// If the deadzone isn't specified, get it from the average of the actions.
- p_deadzone = (InputMap::get_singleton()->action_get_deadzone(p_positive_x) +
- InputMap::get_singleton()->action_get_deadzone(p_negative_x) +
- InputMap::get_singleton()->action_get_deadzone(p_positive_y) +
- InputMap::get_singleton()->action_get_deadzone(p_negative_y)) /
- 4;
+ p_deadzone = 0.25 *
+ (InputMap::get_singleton()->action_get_deadzone(p_positive_x) +
+ InputMap::get_singleton()->action_get_deadzone(p_negative_x) +
+ InputMap::get_singleton()->action_get_deadzone(p_positive_y) +
+ InputMap::get_singleton()->action_get_deadzone(p_negative_y));
}
// Circular length limiting and deadzone.
@@ -340,7 +347,7 @@ Vector2 Input::get_vector(const StringName &p_negative_x, const StringName &p_po
float Input::get_joy_axis(int p_device, JoyAxis p_axis) const {
_THREAD_SAFE_METHOD_
- int c = _combine_device(p_axis, p_device);
+ JoyAxis c = _combine_device(p_axis, p_device);
if (_joy_axis.has(c)) {
return _joy_axis[c];
} else {
@@ -396,7 +403,7 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, S
if (p_connected) {
String uidname = p_guid;
- if (p_guid == "") {
+ if (p_guid.is_empty()) {
int uidlen = MIN(p_name.length(), 16);
for (int i = 0; i < uidlen; i++) {
uidname = uidname + _hex_str(p_name[i]);
@@ -414,11 +421,11 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, S
js.mapping = mapping;
} else {
js.connected = false;
- for (int i = 0; i < JOY_BUTTON_MAX; i++) {
- int c = _combine_device(i, p_idx);
+ for (int i = 0; i < (int)JoyButton::MAX; i++) {
+ JoyButton c = _combine_device((JoyButton)i, p_idx);
joy_buttons_pressed.erase(c);
}
- for (int i = 0; i < JOY_AXIS_MAX; i++) {
+ for (int i = 0; i < (int)JoyAxis::MAX; i++) {
set_joy_axis(p_idx, (JoyAxis)i, 0.0f);
}
}
@@ -456,21 +463,28 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
// require additional handling by this class.
Ref<InputEventKey> k = p_event;
- if (k.is_valid() && !k->is_echo() && k->get_keycode() != 0) {
+ if (k.is_valid() && !k->is_echo() && k->get_keycode() != Key::NONE) {
if (k->is_pressed()) {
keys_pressed.insert(k->get_keycode());
} else {
keys_pressed.erase(k->get_keycode());
}
}
+ if (k.is_valid() && !k->is_echo() && k->get_physical_keycode() != Key::NONE) {
+ if (k->is_pressed()) {
+ physical_keys_pressed.insert(k->get_physical_keycode());
+ } else {
+ physical_keys_pressed.erase(k->get_physical_keycode());
+ }
+ }
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
if (mb->is_pressed()) {
- mouse_button_mask |= (MouseButton)(1 << (mb->get_button_index() - 1));
+ mouse_button_mask |= mouse_button_to_mask(mb->get_button_index());
} else {
- mouse_button_mask &= (MouseButton) ~(1 << (mb->get_button_index() - 1));
+ mouse_button_mask &= ~mouse_button_to_mask(mb->get_button_index());
}
Point2 pos = mb->get_global_position();
@@ -478,7 +492,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
set_mouse_position(pos);
}
- if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && mb->get_button_index() == 1) {
+ if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && mb->get_button_index() == MouseButton::LEFT) {
Ref<InputEventScreenTouch> touch_event;
touch_event.instantiate();
touch_event->set_pressed(mb->is_pressed());
@@ -495,13 +509,13 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
set_mouse_position(pos);
}
- if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && mm->get_button_mask() & 1) {
+ if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && (mm->get_button_mask() & MouseButton::LEFT) != MouseButton::NONE) {
Ref<InputEventScreenDrag> drag_event;
drag_event.instantiate();
drag_event->set_position(mm->get_position());
drag_event->set_relative(mm->get_relative());
- drag_event->set_speed(mm->get_speed());
+ drag_event->set_velocity(mm->get_velocity());
event_dispatch_function(drag_event);
}
@@ -511,12 +525,12 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
if (st.is_valid()) {
if (st->is_pressed()) {
- SpeedTrack &track = touch_speed_track[st->get_index()];
+ VelocityTrack &track = touch_velocity_track[st->get_index()];
track.reset();
} else {
// Since a pointer index may not occur again (OSs may or may not reuse them),
// imperatively remove it from the map to keep no fossil entries in it
- touch_speed_track.erase(st->get_index());
+ touch_velocity_track.erase(st->get_index());
}
if (emulate_mouse_from_touch) {
@@ -541,11 +555,11 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
button_event->set_position(st->get_position());
button_event->set_global_position(st->get_position());
button_event->set_pressed(st->is_pressed());
- button_event->set_button_index(MOUSE_BUTTON_LEFT);
+ button_event->set_button_index(MouseButton::LEFT);
if (st->is_pressed()) {
- button_event->set_button_mask(MouseButton(mouse_button_mask | MOUSE_BUTTON_MASK_LEFT));
+ button_event->set_button_mask(MouseButton(mouse_button_mask | MouseButton::MASK_LEFT));
} else {
- button_event->set_button_mask(MouseButton(mouse_button_mask & ~MOUSE_BUTTON_MASK_LEFT));
+ button_event->set_button_mask(MouseButton(mouse_button_mask & ~MouseButton::MASK_LEFT));
}
_parse_input_event_impl(button_event, true);
@@ -556,9 +570,9 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
Ref<InputEventScreenDrag> sd = p_event;
if (sd.is_valid()) {
- SpeedTrack &track = touch_speed_track[sd->get_index()];
+ VelocityTrack &track = touch_velocity_track[sd->get_index()];
track.update(sd->get_relative());
- sd->set_speed(track.speed);
+ sd->set_velocity(track.velocity);
if (emulate_mouse_from_touch && sd->get_index() == mouse_from_touch_index) {
Ref<InputEventMouseMotion> motion_event;
@@ -568,7 +582,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
motion_event->set_position(sd->get_position());
motion_event->set_global_position(sd->get_position());
motion_event->set_relative(sd->get_relative());
- motion_event->set_speed(sd->get_speed());
+ motion_event->set_velocity(sd->get_velocity());
motion_event->set_button_mask(mouse_button_mask);
_parse_input_event_impl(motion_event, true);
@@ -578,7 +592,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
Ref<InputEventJoypadButton> jb = p_event;
if (jb.is_valid()) {
- int c = _combine_device(jb->get_button_index(), jb->get_device());
+ JoyButton c = _combine_device(jb->get_button_index(), jb->get_device());
if (jb->is_pressed()) {
joy_buttons_pressed.insert(c);
@@ -626,7 +640,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
void Input::set_joy_axis(int p_device, JoyAxis p_axis, float p_value) {
_THREAD_SAFE_METHOD_
- int c = _combine_device(p_axis, p_device);
+ JoyAxis c = _combine_device(p_axis, p_device);
_joy_axis[c] = p_value;
}
@@ -682,7 +696,7 @@ void Input::set_gyroscope(const Vector3 &p_gyroscope) {
}
void Input::set_mouse_position(const Point2 &p_posf) {
- mouse_speed_track.update(p_posf - mouse_pos);
+ mouse_velocity_track.update(p_posf - mouse_pos);
mouse_pos = p_posf;
}
@@ -690,11 +704,11 @@ Point2 Input::get_mouse_position() const {
return mouse_pos;
}
-Point2 Input::get_last_mouse_speed() const {
- return mouse_speed_track.speed;
+Point2 Input::get_last_mouse_velocity() const {
+ return mouse_velocity_track.velocity;
}
-int Input::get_mouse_button_mask() const {
+MouseButton Input::get_mouse_button_mask() const {
return mouse_button_mask; // do not trust OS implementation, should remove it - OS::get_singleton()->get_mouse_button_state();
}
@@ -712,11 +726,11 @@ Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, con
// detect the warp: if the relative distance is greater than the half of the size of the relevant rect
// (checked per each axis), it will be considered as the consequence of a former pointer warp.
- const Point2i rel_sgn(p_motion->get_relative().x >= 0.0f ? 1 : -1, p_motion->get_relative().y >= 0.0 ? 1 : -1);
+ const Point2i rel_sign(p_motion->get_relative().x >= 0.0f ? 1 : -1, p_motion->get_relative().y >= 0.0 ? 1 : -1);
const Size2i warp_margin = p_rect.size * 0.5f;
const Point2i rel_warped(
- Math::fmod(p_motion->get_relative().x + rel_sgn.x * warp_margin.x, p_rect.size.x) - rel_sgn.x * warp_margin.x,
- Math::fmod(p_motion->get_relative().y + rel_sgn.y * warp_margin.y, p_rect.size.y) - rel_sgn.y * warp_margin.y);
+ Math::fmod(p_motion->get_relative().x + rel_sign.x * warp_margin.x, p_rect.size.x) - rel_sign.x * warp_margin.x,
+ Math::fmod(p_motion->get_relative().y + rel_sign.y * warp_margin.y, p_rect.size.y) - rel_sign.y * warp_margin.y);
const Point2i pos_local = p_motion->get_global_position() - p_rect.position;
const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y));
@@ -773,8 +787,8 @@ void Input::ensure_touch_mouse_raised() {
button_event->set_position(mouse_pos);
button_event->set_global_position(mouse_pos);
button_event->set_pressed(false);
- button_event->set_button_index(MOUSE_BUTTON_LEFT);
- button_event->set_button_mask(MouseButton(mouse_button_mask & ~MOUSE_BUTTON_MASK_LEFT));
+ button_event->set_button_index(MouseButton::LEFT);
+ button_event->set_button_mask(MouseButton(mouse_button_mask & ~MouseButton::MASK_LEFT));
_parse_input_event_impl(button_event, true);
}
@@ -860,12 +874,13 @@ void Input::release_pressed_events() {
flush_buffered_events(); // this is needed to release actions strengths
keys_pressed.clear();
+ physical_keys_pressed.clear();
joy_buttons_pressed.clear();
_joy_axis.clear();
- for (Map<StringName, Input::Action>::Element *E = action_state.front(); E; E = E->next()) {
- if (E->get().pressed) {
- action_release(E->key());
+ for (const KeyValue<StringName, Input::Action> &E : action_state) {
+ if (E.value.pressed) {
+ action_release(E.key);
}
}
}
@@ -877,11 +892,12 @@ void Input::set_event_dispatch_function(EventDispatchFunc p_function) {
void Input::joy_button(int p_device, JoyButton p_button, bool p_pressed) {
_THREAD_SAFE_METHOD_;
Joypad &joy = joy_names[p_device];
- //printf("got button %i, mapping is %i\n", p_button, joy.mapping);
- if (joy.last_buttons[p_button] == p_pressed) {
+ ERR_FAIL_INDEX((int)p_button, (int)JoyButton::MAX);
+
+ if (joy.last_buttons[(size_t)p_button] == p_pressed) {
return;
}
- joy.last_buttons[p_button] = p_pressed;
+ joy.last_buttons[(size_t)p_button] = p_pressed;
if (joy.mapping == -1) {
_button_event(p_device, p_button, p_pressed);
return;
@@ -903,16 +919,16 @@ void Input::joy_button(int p_device, JoyButton p_button, bool p_pressed) {
void Input::joy_axis(int p_device, JoyAxis p_axis, const JoyAxisValue &p_value) {
_THREAD_SAFE_METHOD_;
- ERR_FAIL_INDEX(p_axis, JOY_AXIS_MAX);
+ ERR_FAIL_INDEX((int)p_axis, (int)JoyAxis::MAX);
Joypad &joy = joy_names[p_device];
- if (joy.last_axis[p_axis] == p_value.value) {
+ if (joy.last_axis[(size_t)p_axis] == p_value.value) {
return;
}
//when changing direction quickly, insert fake event to release pending inputmap actions
- float last = joy.last_axis[p_axis];
+ float last = joy.last_axis[(size_t)p_axis];
if (p_value.min == 0 && (last < 0.25 || last > 0.75) && (last - 0.5) * (p_value.value - 0.5) < 0) {
JoyAxisValue jx;
jx.min = p_value.min;
@@ -925,7 +941,7 @@ void Input::joy_axis(int p_device, JoyAxis p_axis, const JoyAxisValue &p_value)
joy_axis(p_device, p_axis, jx);
}
- joy.last_axis[p_axis] = p_value.value;
+ joy.last_axis[(size_t)p_axis] = p_value.value;
float val = p_value.min == 0 ? -1.0f + 2.0f * p_value.value : p_value.value;
if (joy.mapping == -1) {
@@ -937,32 +953,32 @@ void Input::joy_axis(int p_device, JoyAxis p_axis, const JoyAxisValue &p_value)
if (map.type == TYPE_BUTTON) {
bool pressed = map.value > 0.5;
- if (pressed == joy_buttons_pressed.has(_combine_device(map.index, p_device))) {
+ if (pressed == joy_buttons_pressed.has(_combine_device((JoyButton)map.index, p_device))) {
// Button already pressed or released; so ignore.
return;
}
_button_event(p_device, (JoyButton)map.index, pressed);
// Ensure opposite D-Pad button is also released.
- switch (map.index) {
- case JOY_BUTTON_DPAD_UP:
- if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_DOWN, p_device))) {
- _button_event(p_device, JOY_BUTTON_DPAD_DOWN, false);
+ switch ((JoyButton)map.index) {
+ case JoyButton::DPAD_UP:
+ if (joy_buttons_pressed.has(_combine_device(JoyButton::DPAD_DOWN, p_device))) {
+ _button_event(p_device, JoyButton::DPAD_DOWN, false);
}
break;
- case JOY_BUTTON_DPAD_DOWN:
- if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_UP, p_device))) {
- _button_event(p_device, JOY_BUTTON_DPAD_UP, false);
+ case JoyButton::DPAD_DOWN:
+ if (joy_buttons_pressed.has(_combine_device(JoyButton::DPAD_UP, p_device))) {
+ _button_event(p_device, JoyButton::DPAD_UP, false);
}
break;
- case JOY_BUTTON_DPAD_LEFT:
- if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_RIGHT, p_device))) {
- _button_event(p_device, JOY_BUTTON_DPAD_RIGHT, false);
+ case JoyButton::DPAD_LEFT:
+ if (joy_buttons_pressed.has(_combine_device(JoyButton::DPAD_RIGHT, p_device))) {
+ _button_event(p_device, JoyButton::DPAD_RIGHT, false);
}
break;
- case JOY_BUTTON_DPAD_RIGHT:
- if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_LEFT, p_device))) {
- _button_event(p_device, JOY_BUTTON_DPAD_LEFT, false);
+ case JoyButton::DPAD_RIGHT:
+ if (joy_buttons_pressed.has(_combine_device(JoyButton::DPAD_LEFT, p_device))) {
+ _button_event(p_device, JoyButton::DPAD_LEFT, false);
}
break;
default:
@@ -979,27 +995,27 @@ void Input::joy_axis(int p_device, JoyAxis p_axis, const JoyAxisValue &p_value)
//printf("invalid mapping\n");
}
-void Input::joy_hat(int p_device, int p_val) {
+void Input::joy_hat(int p_device, HatMask p_val) {
_THREAD_SAFE_METHOD_;
const Joypad &joy = joy_names[p_device];
- JoyEvent map[HAT_MAX];
+ JoyEvent map[(size_t)HatDir::MAX];
- map[HatDir::HAT_UP].type = TYPE_BUTTON;
- map[HatDir::HAT_UP].index = JOY_BUTTON_DPAD_UP;
- map[HatDir::HAT_UP].value = 0;
+ map[(size_t)HatDir::UP].type = TYPE_BUTTON;
+ map[(size_t)HatDir::UP].index = (int)JoyButton::DPAD_UP;
+ map[(size_t)HatDir::UP].value = 0;
- map[HatDir::HAT_RIGHT].type = TYPE_BUTTON;
- map[HatDir::HAT_RIGHT].index = JOY_BUTTON_DPAD_RIGHT;
- map[HatDir::HAT_RIGHT].value = 0;
+ map[(size_t)HatDir::RIGHT].type = TYPE_BUTTON;
+ map[(size_t)HatDir::RIGHT].index = (int)JoyButton::DPAD_RIGHT;
+ map[(size_t)HatDir::RIGHT].value = 0;
- map[HatDir::HAT_DOWN].type = TYPE_BUTTON;
- map[HatDir::HAT_DOWN].index = JOY_BUTTON_DPAD_DOWN;
- map[HatDir::HAT_DOWN].value = 0;
+ map[(size_t)HatDir::DOWN].type = TYPE_BUTTON;
+ map[(size_t)HatDir::DOWN].index = (int)JoyButton::DPAD_DOWN;
+ map[(size_t)HatDir::DOWN].value = 0;
- map[HatDir::HAT_LEFT].type = TYPE_BUTTON;
- map[HatDir::HAT_LEFT].index = JOY_BUTTON_DPAD_LEFT;
- map[HatDir::HAT_LEFT].value = 0;
+ map[(size_t)HatDir::LEFT].type = TYPE_BUTTON;
+ map[(size_t)HatDir::LEFT].index = (int)JoyButton::DPAD_LEFT;
+ map[(size_t)HatDir::LEFT].value = 0;
if (joy.mapping != -1) {
_get_mapped_hat_events(map_db[joy.mapping], (HatDir)0, map);
@@ -1007,18 +1023,18 @@ void Input::joy_hat(int p_device, int p_val) {
int cur_val = joy_names[p_device].hat_current;
- for (int hat_direction = 0, hat_mask = 1; hat_direction < HAT_MAX; hat_direction++, hat_mask <<= 1) {
- if ((p_val & hat_mask) != (cur_val & hat_mask)) {
+ for (int hat_direction = 0, hat_mask = 1; hat_direction < (int)HatDir::MAX; hat_direction++, hat_mask <<= 1) {
+ if (((int)p_val & hat_mask) != (cur_val & hat_mask)) {
if (map[hat_direction].type == TYPE_BUTTON) {
- _button_event(p_device, (JoyButton)map[hat_direction].index, p_val & hat_mask);
+ _button_event(p_device, (JoyButton)map[hat_direction].index, (int)p_val & hat_mask);
}
if (map[hat_direction].type == TYPE_AXIS) {
- _axis_event(p_device, (JoyAxis)map[hat_direction].index, (p_val & hat_mask) ? map[hat_direction].value : 0.0);
+ _axis_event(p_device, (JoyAxis)map[hat_direction].index, ((int)p_val & hat_mask) ? map[hat_direction].value : 0.0);
}
}
}
- joy_names[p_device].hat_current = p_val;
+ joy_names[p_device].hat_current = (int)p_val;
}
void Input::_button_event(int p_device, JoyButton p_index, bool p_pressed) {
@@ -1051,10 +1067,10 @@ Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping,
event.type = binding.outputType;
switch (binding.outputType) {
case TYPE_BUTTON:
- event.index = binding.output.button;
+ event.index = (int)binding.output.button;
return event;
case TYPE_AXIS:
- event.index = binding.output.axis.axis;
+ event.index = (int)binding.output.axis.axis;
switch (binding.output.axis.range) {
case POSITIVE_HALF_AXIS:
event.value = 1;
@@ -1106,7 +1122,7 @@ Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, J
}
switch (binding.outputType) {
case TYPE_BUTTON:
- event.index = binding.output.button;
+ event.index = (int)binding.output.button;
switch (binding.input.axis.range) {
case POSITIVE_HALF_AXIS:
event.value = shifted_positive_value;
@@ -1123,7 +1139,7 @@ Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, J
}
return event;
case TYPE_AXIS:
- event.index = binding.output.axis.axis;
+ event.index = (int)binding.output.axis.axis;
event.value = value;
if (binding.output.axis.range != binding.input.axis.range) {
switch (binding.output.axis.range) {
@@ -1152,43 +1168,43 @@ void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat
for (int i = 0; i < mapping.bindings.size(); i++) {
const JoyBinding binding = mapping.bindings[i];
if (binding.inputType == TYPE_HAT && binding.input.hat.hat == p_hat) {
- int hat_direction;
+ HatDir hat_direction;
switch (binding.input.hat.hat_mask) {
- case HatMask::HAT_MASK_UP:
- hat_direction = HatDir::HAT_UP;
+ case HatMask::UP:
+ hat_direction = HatDir::UP;
break;
- case HatMask::HAT_MASK_RIGHT:
- hat_direction = HatDir::HAT_RIGHT;
+ case HatMask::RIGHT:
+ hat_direction = HatDir::RIGHT;
break;
- case HatMask::HAT_MASK_DOWN:
- hat_direction = HatDir::HAT_DOWN;
+ case HatMask::DOWN:
+ hat_direction = HatDir::DOWN;
break;
- case HatMask::HAT_MASK_LEFT:
- hat_direction = HatDir::HAT_LEFT;
+ case HatMask::LEFT:
+ hat_direction = HatDir::LEFT;
break;
default:
ERR_PRINT_ONCE("Joypad button mapping error.");
continue;
}
- r_events[hat_direction].type = binding.outputType;
+ r_events[(size_t)hat_direction].type = binding.outputType;
switch (binding.outputType) {
case TYPE_BUTTON:
- r_events[hat_direction].index = binding.output.button;
+ r_events[(size_t)hat_direction].index = (int)binding.output.button;
break;
case TYPE_AXIS:
- r_events[hat_direction].index = binding.output.axis.axis;
+ r_events[(size_t)hat_direction].index = (int)binding.output.axis.axis;
switch (binding.output.axis.range) {
case POSITIVE_HALF_AXIS:
- r_events[hat_direction].value = 1;
+ r_events[(size_t)hat_direction].value = 1;
break;
case NEGATIVE_HALF_AXIS:
- r_events[hat_direction].value = -1;
+ r_events[(size_t)hat_direction].value = -1;
break;
case FULL_AXIS:
// It doesn't make sense for a hat direction to map to a full axis,
// but keeping as a default for a trigger with a positive half-axis.
- r_events[hat_direction].value = 1;
+ r_events[(size_t)hat_direction].value = 1;
break;
}
break;
@@ -1200,21 +1216,21 @@ void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat
}
JoyButton Input::_get_output_button(String output) {
- for (int i = 0; i < JOY_BUTTON_SDL_MAX; i++) {
+ for (int i = 0; i < (int)JoyButton::SDL_MAX; i++) {
if (output == _joy_buttons[i]) {
return JoyButton(i);
}
}
- return JoyButton::JOY_BUTTON_INVALID;
+ return JoyButton::INVALID;
}
JoyAxis Input::_get_output_axis(String output) {
- for (int i = 0; i < JOY_AXIS_SDL_MAX; i++) {
+ for (int i = 0; i < (int)JoyAxis::SDL_MAX; i++) {
if (output == _joy_axes[i]) {
return JoyAxis(i);
}
}
- return JoyAxis::JOY_AXIS_INVALID;
+ return JoyAxis::INVALID;
}
void Input::parse_mapping(String p_mapping) {
@@ -1234,14 +1250,14 @@ void Input::parse_mapping(String p_mapping) {
int idx = 1;
while (++idx < entry.size()) {
- if (entry[idx] == "") {
+ if (entry[idx].is_empty()) {
continue;
}
String output = entry[idx].get_slice(":", 0).replace(" ", "");
String input = entry[idx].get_slice(":", 1).replace(" ", "");
ERR_CONTINUE_MSG(output.length() < 1 || input.length() < 2,
- String(entry[idx] + "\nInvalid device mapping entry: " + entry[idx]));
+ vformat("Invalid device mapping entry \"%s\" in mapping:\n%s", entry[idx], p_mapping));
if (output == "platform" || output == "hint") {
continue;
@@ -1249,7 +1265,8 @@ void Input::parse_mapping(String p_mapping) {
JoyAxisRange output_range = FULL_AXIS;
if (output[0] == '+' || output[0] == '-') {
- ERR_CONTINUE_MSG(output.length() < 2, String(entry[idx] + "\nInvalid output: " + entry[idx]));
+ ERR_CONTINUE_MSG(output.length() < 2,
+ vformat("Invalid output entry \"%s\" in mapping:\n%s", entry[idx], p_mapping));
if (output[0] == '+') {
output_range = POSITIVE_HALF_AXIS;
} else if (output[0] == '-') {
@@ -1274,16 +1291,16 @@ 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 == JOY_BUTTON_INVALID && output_axis == JOY_AXIS_INVALID,
- String(entry[idx] + "\nUnrecognised output string: " + output));
- ERR_CONTINUE_MSG(output_button != JOY_BUTTON_INVALID && output_axis != JOY_AXIS_INVALID,
- String("BUG: Output string matched both button and axis: " + output));
+ ERR_CONTINUE_MSG(output_button == JoyButton::INVALID && output_axis == JoyAxis::INVALID,
+ vformat("Unrecognised 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));
JoyBinding binding;
- if (output_button != JOY_BUTTON_INVALID) {
+ if (output_button != JoyButton::INVALID) {
binding.outputType = TYPE_BUTTON;
binding.output.button = output_button;
- } else if (output_axis != JOY_AXIS_INVALID) {
+ } else if (output_axis != JoyAxis::INVALID) {
binding.outputType = TYPE_AXIS;
binding.output.axis.axis = output_axis;
binding.output.axis.range = output_range;
@@ -1302,13 +1319,13 @@ void Input::parse_mapping(String p_mapping) {
break;
case 'h':
ERR_CONTINUE_MSG(input.length() != 4 || input[2] != '.',
- String(entry[idx] + "\nInvalid hat input: " + input));
+ vformat("Invalid had input \"%s\" in mapping:\n%s", input, p_mapping));
binding.inputType = TYPE_HAT;
binding.input.hat.hat = (HatDir)input.substr(1, 1).to_int();
binding.input.hat.hat_mask = static_cast<HatMask>(input.substr(3).to_int());
break;
default:
- ERR_CONTINUE_MSG(true, String(entry[idx] + "\nUnrecognised input string: " + input));
+ ERR_CONTINUE_MSG(true, vformat("Unrecognized input string \"%s\" in mapping:\n%s", input, p_mapping));
}
mapping.bindings.push_back(binding);
@@ -1322,8 +1339,8 @@ void Input::add_joy_mapping(String p_mapping, bool p_update_existing) {
if (p_update_existing) {
Vector<String> entry = p_mapping.split(",");
String uid = entry[0];
- for (Map<int, Joypad>::Element *E = joy_names.front(); E; E = E->next()) {
- Joypad &joy = E->get();
+ for (KeyValue<int, Joypad> &E : joy_names) {
+ Joypad &joy = E.value;
if (joy.uid == uid) {
joy.mapping = map_db.size() - 1;
}
@@ -1334,11 +1351,11 @@ void Input::add_joy_mapping(String p_mapping, bool p_update_existing) {
void Input::remove_joy_mapping(String p_guid) {
for (int i = map_db.size() - 1; i >= 0; i--) {
if (p_guid == map_db[i].uid) {
- map_db.remove(i);
+ map_db.remove_at(i);
}
}
- for (Map<int, Joypad>::Element *E = joy_names.front(); E; E = E->next()) {
- Joypad &joy = E->get();
+ for (KeyValue<int, Joypad> &E : joy_names) {
+ Joypad &joy = E.value;
if (joy.uid == p_guid) {
joy.mapping = -1;
}
@@ -1404,10 +1421,10 @@ Input::Input() {
// If defined, parse SDL_GAMECONTROLLERCONFIG for possible new mappings/overrides.
String env_mapping = OS::get_singleton()->get_environment("SDL_GAMECONTROLLERCONFIG");
- if (env_mapping != "") {
+ if (!env_mapping.is_empty()) {
Vector<String> entries = env_mapping.split("\n");
for (int i = 0; i < entries.size(); i++) {
- if (entries[i] == "") {
+ if (entries[i].is_empty()) {
continue;
}
parse_mapping(entries[i]);
diff --git a/core/input/input.h b/core/input/input.h
index 6819fc8eb0..8b1d7d6161 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -85,11 +85,12 @@ public:
typedef void (*EventDispatchFunc)(const Ref<InputEvent> &p_event);
private:
- int mouse_button_mask = 0;
+ MouseButton mouse_button_mask = MouseButton::NONE;
- Set<int> keys_pressed;
- Set<int> joy_buttons_pressed;
- Map<int, float> _joy_axis;
+ Set<Key> physical_keys_pressed;
+ Set<Key> keys_pressed;
+ Set<JoyButton> joy_buttons_pressed;
+ Map<JoyAxis, float> _joy_axis;
//Map<StringName,int> custom_action_press;
Vector3 gravity;
Vector3 accelerometer;
@@ -116,9 +117,9 @@ private:
int mouse_from_touch_index = -1;
- struct SpeedTrack {
+ struct VelocityTrack {
uint64_t last_tick;
- Vector2 speed;
+ Vector2 velocity;
Vector2 accum;
float accum_t;
float min_ref_frame;
@@ -126,22 +127,22 @@ private:
void update(const Vector2 &p_delta_p);
void reset();
- SpeedTrack();
+ VelocityTrack();
};
struct Joypad {
StringName name;
StringName uid;
bool connected = false;
- bool last_buttons[JOY_BUTTON_MAX] = { false };
- float last_axis[JOY_AXIS_MAX] = { 0.0f };
- int last_hat = HatMask::HAT_MASK_CENTER;
+ bool last_buttons[(size_t)JoyButton::MAX] = { false };
+ float last_axis[(size_t)JoyAxis::MAX] = { 0.0f };
+ HatMask last_hat = HatMask::CENTER;
int mapping = -1;
int hat_current = 0;
};
- SpeedTrack mouse_speed_track;
- Map<int, SpeedTrack> touch_speed_track;
+ VelocityTrack mouse_velocity_track;
+ Map<int, VelocityTrack> touch_velocity_track;
Map<int, Joypad> joy_names;
int fallback_mapping = -1;
@@ -162,7 +163,7 @@ private:
struct JoyEvent {
int type;
- int index;
+ int index; // Can be either JoyAxis or JoyButton.
float value;
};
@@ -206,7 +207,7 @@ private:
JoyEvent _get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button);
JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, JoyAxis p_axis, float p_value);
- void _get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat, JoyEvent r_events[HAT_MAX]);
+ void _get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat, JoyEvent r_events[(size_t)HatDir::MAX]);
JoyButton _get_output_button(String output);
JoyAxis _get_output_axis(String output);
void _button_event(int p_device, JoyButton p_index, bool p_pressed);
@@ -247,6 +248,7 @@ public:
static Input *get_singleton();
bool is_key_pressed(Key p_keycode) const;
+ bool is_physical_key_pressed(Key p_keycode) const;
bool is_mouse_button_pressed(MouseButton p_button) const;
bool is_joy_button_pressed(int p_device, JoyButton p_button) const;
bool is_action_pressed(const StringName &p_action, bool p_exact = false) const;
@@ -265,7 +267,6 @@ public:
float get_joy_vibration_duration(int p_device);
uint64_t get_joy_vibration_timestamp(int p_device);
void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid = "");
- void parse_joypad_mapping(String p_mapping, bool p_update_existing);
Vector3 get_gravity() const;
Vector3 get_accelerometer() const;
@@ -273,8 +274,8 @@ public:
Vector3 get_gyroscope() const;
Point2 get_mouse_position() const;
- Point2 get_last_mouse_speed() const;
- int get_mouse_button_mask() const;
+ Vector2 get_last_mouse_velocity() const;
+ MouseButton get_mouse_button_mask() const;
void warp_mouse_position(const Vector2 &p_to);
Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect);
@@ -313,7 +314,7 @@ public:
void parse_mapping(String p_mapping);
void joy_button(int p_device, JoyButton p_button, bool p_pressed);
void joy_axis(int p_device, JoyAxis p_axis, const JoyAxisValue &p_value);
- void joy_hat(int p_device, int p_val);
+ void joy_hat(int p_device, HatMask p_val);
void add_joy_mapping(String p_mapping, bool p_update_existing = false);
void remove_joy_mapping(String p_guid);
diff --git a/core/input/input_enums.h b/core/input/input_enums.h
index 4479a85bfe..0282de2176 100644
--- a/core/input/input_enums.h
+++ b/core/input/input_enums.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,90 +31,117 @@
#ifndef INPUT_ENUMS_H
#define INPUT_ENUMS_H
-enum HatDir {
- HAT_UP = 0,
- HAT_RIGHT = 1,
- HAT_DOWN = 2,
- HAT_LEFT = 3,
- HAT_MAX = 4,
+enum class HatDir {
+ UP = 0,
+ RIGHT = 1,
+ DOWN = 2,
+ LEFT = 3,
+ MAX = 4,
};
-enum HatMask {
- HAT_MASK_CENTER = 0,
- HAT_MASK_UP = 1,
- HAT_MASK_RIGHT = 2,
- HAT_MASK_DOWN = 4,
- HAT_MASK_LEFT = 8,
+enum class HatMask {
+ CENTER = 0,
+ UP = 1,
+ RIGHT = 2,
+ DOWN = 4,
+ LEFT = 8,
};
-enum JoyAxis {
- JOY_AXIS_INVALID = -1,
- JOY_AXIS_LEFT_X = 0,
- JOY_AXIS_LEFT_Y = 1,
- JOY_AXIS_RIGHT_X = 2,
- JOY_AXIS_RIGHT_Y = 3,
- JOY_AXIS_TRIGGER_LEFT = 4,
- JOY_AXIS_TRIGGER_RIGHT = 5,
- JOY_AXIS_SDL_MAX = 6,
- JOY_AXIS_MAX = 10, // OpenVR supports up to 5 Joysticks making a total of 10 axes.
+enum class JoyAxis {
+ INVALID = -1,
+ LEFT_X = 0,
+ LEFT_Y = 1,
+ RIGHT_X = 2,
+ RIGHT_Y = 3,
+ TRIGGER_LEFT = 4,
+ TRIGGER_RIGHT = 5,
+ SDL_MAX = 6,
+ MAX = 10, // OpenVR supports up to 5 Joysticks making a total of 10 axes.
};
-enum JoyButton {
- JOY_BUTTON_INVALID = -1,
- JOY_BUTTON_A = 0,
- JOY_BUTTON_B = 1,
- JOY_BUTTON_X = 2,
- JOY_BUTTON_Y = 3,
- JOY_BUTTON_BACK = 4,
- JOY_BUTTON_GUIDE = 5,
- JOY_BUTTON_START = 6,
- JOY_BUTTON_LEFT_STICK = 7,
- JOY_BUTTON_RIGHT_STICK = 8,
- JOY_BUTTON_LEFT_SHOULDER = 9,
- JOY_BUTTON_RIGHT_SHOULDER = 10,
- JOY_BUTTON_DPAD_UP = 11,
- JOY_BUTTON_DPAD_DOWN = 12,
- JOY_BUTTON_DPAD_LEFT = 13,
- JOY_BUTTON_DPAD_RIGHT = 14,
- JOY_BUTTON_MISC1 = 15,
- JOY_BUTTON_PADDLE1 = 16,
- JOY_BUTTON_PADDLE2 = 17,
- JOY_BUTTON_PADDLE3 = 18,
- JOY_BUTTON_PADDLE4 = 19,
- JOY_BUTTON_TOUCHPAD = 20,
- JOY_BUTTON_SDL_MAX = 21,
- JOY_BUTTON_MAX = 36, // Android supports up to 36 buttons.
+enum class JoyButton {
+ INVALID = -1,
+ A = 0,
+ B = 1,
+ X = 2,
+ Y = 3,
+ BACK = 4,
+ GUIDE = 5,
+ START = 6,
+ LEFT_STICK = 7,
+ RIGHT_STICK = 8,
+ LEFT_SHOULDER = 9,
+ RIGHT_SHOULDER = 10,
+ DPAD_UP = 11,
+ DPAD_DOWN = 12,
+ DPAD_LEFT = 13,
+ DPAD_RIGHT = 14,
+ MISC1 = 15,
+ PADDLE1 = 16,
+ PADDLE2 = 17,
+ PADDLE3 = 18,
+ PADDLE4 = 19,
+ TOUCHPAD = 20,
+ SDL_MAX = 21,
+ MAX = 128, // Android supports up to 36 buttons. DirectInput supports up to 128 buttons.
};
-enum MIDIMessage {
- MIDI_MESSAGE_NONE = 0,
- MIDI_MESSAGE_NOTE_OFF = 0x8,
- MIDI_MESSAGE_NOTE_ON = 0x9,
- MIDI_MESSAGE_AFTERTOUCH = 0xA,
- MIDI_MESSAGE_CONTROL_CHANGE = 0xB,
- MIDI_MESSAGE_PROGRAM_CHANGE = 0xC,
- MIDI_MESSAGE_CHANNEL_PRESSURE = 0xD,
- MIDI_MESSAGE_PITCH_BEND = 0xE,
+enum class MIDIMessage {
+ NONE = 0,
+ NOTE_OFF = 0x8,
+ NOTE_ON = 0x9,
+ AFTERTOUCH = 0xA,
+ CONTROL_CHANGE = 0xB,
+ PROGRAM_CHANGE = 0xC,
+ CHANNEL_PRESSURE = 0xD,
+ PITCH_BEND = 0xE,
+ SYSTEM_EXCLUSIVE = 0xF0,
+ QUARTER_FRAME = 0xF1,
+ SONG_POSITION_POINTER = 0xF2,
+ SONG_SELECT = 0xF3,
+ TUNE_REQUEST = 0xF6,
+ TIMING_CLOCK = 0xF8,
+ START = 0xFA,
+ CONTINUE = 0xFB,
+ STOP = 0xFC,
+ ACTIVE_SENSING = 0xFE,
+ SYSTEM_RESET = 0xFF,
};
-enum MouseButton {
- MOUSE_BUTTON_NONE = 0,
- MOUSE_BUTTON_LEFT = 1,
- MOUSE_BUTTON_RIGHT = 2,
- MOUSE_BUTTON_MIDDLE = 3,
- MOUSE_BUTTON_WHEEL_UP = 4,
- MOUSE_BUTTON_WHEEL_DOWN = 5,
- MOUSE_BUTTON_WHEEL_LEFT = 6,
- MOUSE_BUTTON_WHEEL_RIGHT = 7,
- MOUSE_BUTTON_XBUTTON1 = 8,
- MOUSE_BUTTON_XBUTTON2 = 9,
- MOUSE_BUTTON_MASK_LEFT = (1 << (MOUSE_BUTTON_LEFT - 1)),
- MOUSE_BUTTON_MASK_RIGHT = (1 << (MOUSE_BUTTON_RIGHT - 1)),
- MOUSE_BUTTON_MASK_MIDDLE = (1 << (MOUSE_BUTTON_MIDDLE - 1)),
- MOUSE_BUTTON_MASK_XBUTTON1 = (1 << (MOUSE_BUTTON_XBUTTON1 - 1)),
- MOUSE_BUTTON_MASK_XBUTTON2 = (1 << (MOUSE_BUTTON_XBUTTON2 - 1)),
+enum class MouseButton {
+ NONE = 0,
+ LEFT = 1,
+ RIGHT = 2,
+ MIDDLE = 3,
+ WHEEL_UP = 4,
+ WHEEL_DOWN = 5,
+ WHEEL_LEFT = 6,
+ WHEEL_RIGHT = 7,
+ MB_XBUTTON1 = 8, // "XBUTTON1" is a reserved word on Windows.
+ MB_XBUTTON2 = 9, // "XBUTTON2" is a reserved word on Windows.
+ MASK_LEFT = (1 << (LEFT - 1)),
+ MASK_RIGHT = (1 << (RIGHT - 1)),
+ MASK_MIDDLE = (1 << (MIDDLE - 1)),
+ MASK_XBUTTON1 = (1 << (MB_XBUTTON1 - 1)),
+ MASK_XBUTTON2 = (1 << (MB_XBUTTON2 - 1)),
};
+inline MouseButton mouse_button_to_mask(MouseButton button) {
+ return MouseButton(1 << ((int)button - 1));
+}
+
+inline MouseButton operator&(MouseButton a, MouseButton b) {
+ return (MouseButton)((int)a & (int)b);
+}
+
+inline MouseButton operator|(MouseButton a, MouseButton b) {
+ return (MouseButton)((int)a | (int)b);
+}
+
+inline MouseButton operator^(MouseButton a, MouseButton b) {
+ return (MouseButton)((int)a ^ (int)b);
+}
+
inline MouseButton &operator|=(MouseButton &a, MouseButton b) {
return (MouseButton &)((int &)a |= (int)b);
}
@@ -123,4 +150,28 @@ inline MouseButton &operator&=(MouseButton &a, MouseButton b) {
return (MouseButton &)((int &)a &= (int)b);
}
+inline MouseButton operator~(MouseButton a) {
+ return (MouseButton)(~(int)a);
+}
+
+inline HatMask operator|(HatMask a, HatMask b) {
+ return (HatMask)((int)a | (int)b);
+}
+
+inline HatMask operator&(HatMask a, HatMask b) {
+ return (HatMask)((int)a & (int)b);
+}
+
+inline HatMask &operator&=(HatMask &a, HatMask b) {
+ return (HatMask &)((int &)a &= (int)b);
+}
+
+inline HatMask &operator|=(HatMask &a, HatMask b) {
+ return (HatMask &)((int &)a |= (int)b);
+}
+
+inline HatMask operator~(HatMask a) {
+ return (HatMask)(~(int)a);
+}
+
#endif // INPUT_ENUMS_H
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 50b2099236..c608076a21 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -203,19 +203,19 @@ void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModif
set_meta_pressed(event->is_meta_pressed());
}
-uint32_t InputEventWithModifiers::get_modifiers_mask() const {
- uint32_t mask = 0;
+Key InputEventWithModifiers::get_modifiers_mask() const {
+ Key mask = Key::NONE;
if (is_ctrl_pressed()) {
- mask |= KEY_MASK_CTRL;
+ mask |= KeyModifierMask::CTRL;
}
if (is_shift_pressed()) {
- mask |= KEY_MASK_SHIFT;
+ mask |= KeyModifierMask::SHIFT;
}
if (is_alt_pressed()) {
- mask |= KEY_MASK_ALT;
+ mask |= KeyModifierMask::ALT;
}
if (is_meta_pressed()) {
- mask |= KEY_MASK_META;
+ mask |= KeyModifierMask::META;
}
return mask;
}
@@ -224,16 +224,16 @@ String InputEventWithModifiers::as_text() const {
Vector<String> mod_names;
if (is_ctrl_pressed()) {
- mod_names.push_back(find_keycode_name(KEY_CTRL));
+ mod_names.push_back(find_keycode_name(Key::CTRL));
}
if (is_shift_pressed()) {
- mod_names.push_back(find_keycode_name(KEY_SHIFT));
+ mod_names.push_back(find_keycode_name(Key::SHIFT));
}
if (is_alt_pressed()) {
- mod_names.push_back(find_keycode_name(KEY_ALT));
+ mod_names.push_back(find_keycode_name(Key::ALT));
}
if (is_meta_pressed()) {
- mod_names.push_back(find_keycode_name(KEY_META));
+ mod_names.push_back(find_keycode_name(Key::META));
}
if (!mod_names.is_empty()) {
@@ -325,12 +325,12 @@ Key InputEventKey::get_physical_keycode() const {
return physical_keycode;
}
-void InputEventKey::set_unicode(uint32_t p_unicode) {
+void InputEventKey::set_unicode(char32_t p_unicode) {
unicode = p_unicode;
emit_changed();
}
-uint32_t InputEventKey::get_unicode() const {
+char32_t InputEventKey::get_unicode() const {
return unicode;
}
@@ -343,29 +343,29 @@ bool InputEventKey::is_echo() const {
return echo;
}
-uint32_t InputEventKey::get_keycode_with_modifiers() const {
+Key InputEventKey::get_keycode_with_modifiers() const {
return keycode | get_modifiers_mask();
}
-uint32_t InputEventKey::get_physical_keycode_with_modifiers() const {
+Key InputEventKey::get_physical_keycode_with_modifiers() const {
return physical_keycode | get_modifiers_mask();
}
String InputEventKey::as_text() const {
String kc;
- if (keycode == 0) {
+ if (keycode == Key::NONE) {
kc = keycode_get_string(physical_keycode) + " (" + RTR("Physical") + ")";
} else {
kc = keycode_get_string(keycode);
}
- if (kc == String()) {
+ if (kc.is_empty()) {
return kc;
}
String mods_text = InputEventWithModifiers::as_text();
- return mods_text == "" ? kc : mods_text + "+" + kc;
+ return mods_text.is_empty() ? kc : mods_text + "+" + kc;
}
String InputEventKey::to_string() {
@@ -374,15 +374,15 @@ String InputEventKey::to_string() {
String kc = "";
String physical = "false";
- if (keycode == 0) {
- kc = itos(physical_keycode) + " (" + keycode_get_string(physical_keycode) + ")";
+ if (keycode == Key::NONE) {
+ kc = itos((int64_t)physical_keycode) + " (" + keycode_get_string(physical_keycode) + ")";
physical = "true";
} else {
- kc = itos(keycode) + " (" + keycode_get_string(keycode) + ")";
+ kc = itos((int64_t)keycode) + " (" + keycode_get_string(keycode) + ")";
}
String mods = InputEventWithModifiers::as_text();
- mods = mods == "" ? TTR("none") : mods;
+ mods = mods.is_empty() ? TTR("none") : mods;
return vformat("InputEventKey: keycode=%s, mods=%s, physical=%s, pressed=%s, echo=%s", kc, mods, physical, p, e);
}
@@ -390,22 +390,22 @@ String InputEventKey::to_string() {
Ref<InputEventKey> InputEventKey::create_reference(Key p_keycode) {
Ref<InputEventKey> ie;
ie.instantiate();
- ie->set_keycode(p_keycode & KEY_CODE_MASK);
- ie->set_unicode(p_keycode & KEY_CODE_MASK);
+ ie->set_keycode(p_keycode & KeyModifierMask::CODE_MASK);
+ ie->set_unicode(char32_t(p_keycode & KeyModifierMask::CODE_MASK));
- if (p_keycode & KEY_MASK_SHIFT) {
+ if ((p_keycode & KeyModifierMask::SHIFT) != Key::NONE) {
ie->set_shift_pressed(true);
}
- if (p_keycode & KEY_MASK_ALT) {
+ if ((p_keycode & KeyModifierMask::ALT) != Key::NONE) {
ie->set_alt_pressed(true);
}
- if (p_keycode & KEY_MASK_CTRL) {
+ if ((p_keycode & KeyModifierMask::CTRL) != Key::NONE) {
ie->set_ctrl_pressed(true);
}
- if (p_keycode & KEY_MASK_CMD) {
+ if ((p_keycode & KeyModifierMask::CMD) != Key::NONE) {
ie->set_command_pressed(true);
}
- if (p_keycode & KEY_MASK_META) {
+ if ((p_keycode & KeyModifierMask::META) != Key::NONE) {
ie->set_meta_pressed(true);
}
@@ -419,14 +419,14 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed
}
bool match = false;
- if (get_keycode() == 0) {
- uint32_t code = get_physical_keycode_with_modifiers();
- uint32_t event_code = key->get_physical_keycode_with_modifiers();
+ if (get_keycode() == Key::NONE) {
+ Key code = get_physical_keycode_with_modifiers();
+ Key event_code = key->get_physical_keycode_with_modifiers();
match = get_physical_keycode() == key->get_physical_keycode() && (!key->is_pressed() || (code & event_code) == code);
} else {
- uint32_t code = get_keycode_with_modifiers();
- uint32_t event_code = key->get_keycode_with_modifiers();
+ Key code = get_keycode_with_modifiers();
+ Key event_code = key->get_keycode_with_modifiers();
match = get_keycode() == key->get_keycode() && (!key->is_pressed() || (code & event_code) == code);
}
@@ -452,8 +452,13 @@ bool InputEventKey::is_match(const Ref<InputEvent> &p_event, bool p_exact_match)
return false;
}
- return keycode == key->keycode &&
- (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask());
+ if (keycode == Key::NONE) {
+ return physical_keycode == key->physical_keycode &&
+ (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask());
+ } else {
+ return keycode == key->keycode &&
+ (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask());
+ }
}
void InputEventKey::_bind_methods() {
@@ -482,12 +487,12 @@ void InputEventKey::_bind_methods() {
///////////////////////////////////
-void InputEventMouse::set_button_mask(int p_mask) {
+void InputEventMouse::set_button_mask(MouseButton p_mask) {
button_mask = p_mask;
emit_changed();
}
-int InputEventMouse::get_button_mask() const {
+MouseButton InputEventMouse::get_button_mask() const {
return button_mask;
}
@@ -611,7 +616,7 @@ bool InputEventMouseButton::is_match(const Ref<InputEvent> &p_event, bool p_exac
}
return button_index == mb->button_index &&
- (!p_exact_match || get_modifiers_mask() == mb->get_modifiers_mask());
+ (!p_exact_match || get_modifiers_mask() == mb->get_modifiers_mask());
}
static const char *_mouse_button_descriptions[9] = {
@@ -629,24 +634,24 @@ static const char *_mouse_button_descriptions[9] = {
String InputEventMouseButton::as_text() const {
// Modifiers
String mods_text = InputEventWithModifiers::as_text();
- String full_string = mods_text == "" ? "" : mods_text + "+";
+ String full_string = mods_text.is_empty() ? "" : mods_text + "+";
// Button
- int idx = get_button_index();
+ MouseButton idx = get_button_index();
switch (idx) {
- case MOUSE_BUTTON_LEFT:
- case MOUSE_BUTTON_RIGHT:
- case MOUSE_BUTTON_MIDDLE:
- case MOUSE_BUTTON_WHEEL_UP:
- case MOUSE_BUTTON_WHEEL_DOWN:
- case MOUSE_BUTTON_WHEEL_LEFT:
- case MOUSE_BUTTON_WHEEL_RIGHT:
- case MOUSE_BUTTON_XBUTTON1:
- case MOUSE_BUTTON_XBUTTON2:
- full_string += RTR(_mouse_button_descriptions[idx - 1]); // button index starts from 1, array index starts from 0, so subtract 1
+ case MouseButton::LEFT:
+ case MouseButton::RIGHT:
+ case MouseButton::MIDDLE:
+ case MouseButton::WHEEL_UP:
+ case MouseButton::WHEEL_DOWN:
+ case MouseButton::WHEEL_LEFT:
+ case MouseButton::WHEEL_RIGHT:
+ case MouseButton::MB_XBUTTON1:
+ case MouseButton::MB_XBUTTON2:
+ full_string += RTR(_mouse_button_descriptions[(size_t)idx - 1]); // button index starts from 1, array index starts from 0, so subtract 1
break;
default:
- full_string += RTR("Button") + " #" + itos(idx);
+ full_string += RTR("Button") + " #" + itos((int64_t)idx);
break;
}
@@ -662,27 +667,27 @@ String InputEventMouseButton::to_string() {
String p = is_pressed() ? "true" : "false";
String d = double_click ? "true" : "false";
- int idx = get_button_index();
- String button_string = itos(idx);
+ MouseButton idx = get_button_index();
+ String button_string = itos((int64_t)idx);
switch (idx) {
- case MOUSE_BUTTON_LEFT:
- case MOUSE_BUTTON_RIGHT:
- case MOUSE_BUTTON_MIDDLE:
- case MOUSE_BUTTON_WHEEL_UP:
- case MOUSE_BUTTON_WHEEL_DOWN:
- case MOUSE_BUTTON_WHEEL_LEFT:
- case MOUSE_BUTTON_WHEEL_RIGHT:
- case MOUSE_BUTTON_XBUTTON1:
- case MOUSE_BUTTON_XBUTTON2:
- button_string += " (" + RTR(_mouse_button_descriptions[idx - 1]) + ")"; // button index starts from 1, array index starts from 0, so subtract 1
+ case MouseButton::LEFT:
+ case MouseButton::RIGHT:
+ case MouseButton::MIDDLE:
+ case MouseButton::WHEEL_UP:
+ case MouseButton::WHEEL_DOWN:
+ case MouseButton::WHEEL_LEFT:
+ case MouseButton::WHEEL_RIGHT:
+ case MouseButton::MB_XBUTTON1:
+ case MouseButton::MB_XBUTTON2:
+ button_string += " (" + RTR(_mouse_button_descriptions[(size_t)idx - 1]) + ")"; // button index starts from 1, array index starts from 0, so subtract 1
break;
default:
break;
}
String mods = InputEventWithModifiers::as_text();
- mods = mods == "" ? TTR("none") : mods;
+ mods = mods.is_empty() ? TTR("none") : mods;
// Work around the fact vformat can only take 5 substitutions but 6 need to be passed.
String index_and_mods = vformat("button_index=%s, mods=%s", button_index, mods);
@@ -734,20 +739,15 @@ Vector2 InputEventMouseMotion::get_relative() const {
return relative;
}
-void InputEventMouseMotion::set_speed(const Vector2 &p_speed) {
- speed = p_speed;
+void InputEventMouseMotion::set_velocity(const Vector2 &p_velocity) {
+ velocity = p_velocity;
}
-Vector2 InputEventMouseMotion::get_speed() const {
- return speed;
+Vector2 InputEventMouseMotion::get_velocity() const {
+ return velocity;
}
Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
- Vector2 g = get_global_position();
- Vector2 l = p_xform.xform(get_position() + p_local_ofs);
- Vector2 r = p_xform.basis_xform(get_relative());
- Vector2 s = p_xform.basis_xform(get_speed());
-
Ref<InputEventMouseMotion> mm;
mm.instantiate();
@@ -756,40 +756,40 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co
mm->set_modifiers_from_event(this);
- mm->set_position(l);
+ mm->set_position(p_xform.xform(get_position() + p_local_ofs));
mm->set_pressure(get_pressure());
mm->set_tilt(get_tilt());
- mm->set_global_position(g);
+ mm->set_global_position(get_global_position());
mm->set_button_mask(get_button_mask());
- mm->set_relative(r);
- mm->set_speed(s);
+ mm->set_relative(p_xform.basis_xform(get_relative()));
+ mm->set_velocity(p_xform.basis_xform(get_velocity()));
return mm;
}
String InputEventMouseMotion::as_text() const {
- return vformat(RTR("Mouse motion at position (%s) with speed (%s)"), String(get_position()), String(get_speed()));
+ return vformat(RTR("Mouse motion at position (%s) with velocity (%s)"), String(get_position()), String(get_velocity()));
}
String InputEventMouseMotion::to_string() {
- int button_mask = get_button_mask();
- String button_mask_string = itos(button_mask);
- switch (get_button_mask()) {
- case MOUSE_BUTTON_MASK_LEFT:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_LEFT - 1]) + ")";
+ MouseButton button_mask = get_button_mask();
+ String button_mask_string = itos((int64_t)button_mask);
+ switch (button_mask) {
+ case MouseButton::MASK_LEFT:
+ button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::LEFT - 1]) + ")";
break;
- case MOUSE_BUTTON_MASK_MIDDLE:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_MIDDLE - 1]) + ")";
+ case MouseButton::MASK_MIDDLE:
+ button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::MIDDLE - 1]) + ")";
break;
- case MOUSE_BUTTON_MASK_RIGHT:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_RIGHT - 1]) + ")";
+ case MouseButton::MASK_RIGHT:
+ button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::RIGHT - 1]) + ")";
break;
- case MOUSE_BUTTON_MASK_XBUTTON1:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_XBUTTON1 - 1]) + ")";
+ case MouseButton::MASK_XBUTTON1:
+ button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON1 - 1]) + ")";
break;
- case MOUSE_BUTTON_MASK_XBUTTON2:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_XBUTTON2 - 1]) + ")";
+ case MouseButton::MASK_XBUTTON2:
+ button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON2 - 1]) + ")";
break;
default:
break;
@@ -797,7 +797,7 @@ String InputEventMouseMotion::to_string() {
// Work around the fact vformat can only take 5 substitutions but 6 need to be passed.
String mask_and_position = vformat("button_mask=%s, position=(%s)", button_mask_string, String(get_position()));
- return vformat("InputEventMouseMotion: %s, relative=(%s), speed=(%s), pressure=%.2f, tilt=(%s)", mask_and_position, String(get_relative()), String(get_speed()), get_pressure(), String(get_tilt()));
+ return vformat("InputEventMouseMotion: %s, relative=(%s), velocity=(%s), pressure=%.2f, tilt=(%s)", mask_and_position, String(get_relative()), String(get_velocity()), get_pressure(), String(get_tilt()));
}
bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) {
@@ -836,7 +836,7 @@ bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) {
set_position(motion->get_position());
set_global_position(motion->get_global_position());
- set_speed(motion->get_speed());
+ set_velocity(motion->get_velocity());
relative += motion->get_relative();
return true;
@@ -852,18 +852,20 @@ void InputEventMouseMotion::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventMouseMotion::set_relative);
ClassDB::bind_method(D_METHOD("get_relative"), &InputEventMouseMotion::get_relative);
- ClassDB::bind_method(D_METHOD("set_speed", "speed"), &InputEventMouseMotion::set_speed);
- ClassDB::bind_method(D_METHOD("get_speed"), &InputEventMouseMotion::get_speed);
+ ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &InputEventMouseMotion::set_velocity);
+ ClassDB::bind_method(D_METHOD("get_velocity"), &InputEventMouseMotion::get_velocity);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure"), "set_pressure", "get_pressure");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative"), "set_relative", "get_relative");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "speed"), "set_speed", "get_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity"), "set_velocity", "get_velocity");
}
///////////////////////////////////
void InputEventJoypadMotion::set_axis(JoyAxis p_axis) {
+ ERR_FAIL_COND(p_axis < JoyAxis::LEFT_X || p_axis > JoyAxis::MAX);
+
axis = p_axis;
emit_changed();
}
@@ -928,10 +930,10 @@ bool InputEventJoypadMotion::is_match(const Ref<InputEvent> &p_event, bool p_exa
}
return axis == jm->axis &&
- (!p_exact_match || ((axis_value < 0) == (jm->axis_value < 0)));
+ (!p_exact_match || ((axis_value < 0) == (jm->axis_value < 0)));
}
-static const char *_joy_axis_descriptions[JOY_AXIS_MAX] = {
+static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX] = {
TTRC("Left Stick X-Axis, Joystick 0 X-Axis"),
TTRC("Left Stick Y-Axis, Joystick 0 Y-Axis"),
TTRC("Right Stick X-Axis, Joystick 1 X-Axis"),
@@ -945,7 +947,7 @@ static const char *_joy_axis_descriptions[JOY_AXIS_MAX] = {
};
String InputEventJoypadMotion::as_text() const {
- String desc = axis < JOY_AXIS_MAX ? RTR(_joy_axis_descriptions[axis]) : TTR("Unknown Joypad Axis");
+ String desc = axis < JoyAxis::MAX ? RTR(_joy_axis_descriptions[(size_t)axis]) : TTR("Unknown Joypad Axis");
return vformat(TTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value);
}
@@ -1025,7 +1027,7 @@ bool InputEventJoypadButton::is_match(const Ref<InputEvent> &p_event, bool p_exa
return button_index == button->button_index;
}
-static const char *_joy_button_descriptions[JOY_BUTTON_SDL_MAX] = {
+static const char *_joy_button_descriptions[(size_t)JoyButton::SDL_MAX] = {
TTRC("Bottom Action, Sony Cross, Xbox A, Nintendo B"),
TTRC("Right Action, Sony Circle, Xbox B, Nintendo A"),
TTRC("Left Action, Sony Square, Xbox X, Nintendo Y"),
@@ -1050,10 +1052,10 @@ static const char *_joy_button_descriptions[JOY_BUTTON_SDL_MAX] = {
};
String InputEventJoypadButton::as_text() const {
- String text = "Joypad Button " + itos(button_index);
+ String text = "Joypad Button " + itos((int64_t)button_index);
- if (button_index >= 0 && button_index < JOY_BUTTON_SDL_MAX) {
- text += vformat(" (%s)", _joy_button_descriptions[button_index]);
+ if (button_index > JoyButton::INVALID && button_index < JoyButton::SDL_MAX) {
+ text += vformat(" (%s)", _joy_button_descriptions[(size_t)button_index]);
}
if (pressure != 0) {
@@ -1181,12 +1183,12 @@ Vector2 InputEventScreenDrag::get_relative() const {
return relative;
}
-void InputEventScreenDrag::set_speed(const Vector2 &p_speed) {
- speed = p_speed;
+void InputEventScreenDrag::set_velocity(const Vector2 &p_velocity) {
+ velocity = p_velocity;
}
-Vector2 InputEventScreenDrag::get_speed() const {
- return speed;
+Vector2 InputEventScreenDrag::get_velocity() const {
+ return velocity;
}
Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
@@ -1200,17 +1202,17 @@ Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, con
sd->set_index(index);
sd->set_position(p_xform.xform(pos + p_local_ofs));
sd->set_relative(p_xform.basis_xform(relative));
- sd->set_speed(p_xform.basis_xform(speed));
+ sd->set_velocity(p_xform.basis_xform(velocity));
return sd;
}
String InputEventScreenDrag::as_text() const {
- return vformat(RTR("Screen dragged with %s touch points at position (%s) with speed of (%s)"), itos(index), String(get_position()), String(get_speed()));
+ return vformat(RTR("Screen dragged with %s touch points at position (%s) with velocity of (%s)"), itos(index), String(get_position()), String(get_velocity()));
}
String InputEventScreenDrag::to_string() {
- return vformat("InputEventScreenDrag: index=%d, position=(%s), relative=(%s), speed=(%s)", index, String(get_position()), String(get_relative()), String(get_speed()));
+ return vformat("InputEventScreenDrag: index=%d, position=(%s), relative=(%s), velocity=(%s)", index, String(get_position()), String(get_relative()), String(get_velocity()));
}
bool InputEventScreenDrag::accumulate(const Ref<InputEvent> &p_event) {
@@ -1223,7 +1225,7 @@ bool InputEventScreenDrag::accumulate(const Ref<InputEvent> &p_event) {
}
set_position(drag->get_position());
- set_speed(drag->get_speed());
+ set_velocity(drag->get_velocity());
relative += drag->get_relative();
return true;
@@ -1239,13 +1241,13 @@ void InputEventScreenDrag::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventScreenDrag::set_relative);
ClassDB::bind_method(D_METHOD("get_relative"), &InputEventScreenDrag::get_relative);
- ClassDB::bind_method(D_METHOD("set_speed", "speed"), &InputEventScreenDrag::set_speed);
- ClassDB::bind_method(D_METHOD("get_speed"), &InputEventScreenDrag::get_speed);
+ ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &InputEventScreenDrag::set_velocity);
+ ClassDB::bind_method(D_METHOD("get_velocity"), &InputEventScreenDrag::get_velocity);
ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative"), "set_relative", "get_relative");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "speed"), "set_speed", "get_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity"), "set_velocity", "get_velocity");
}
///////////////////////////////////
@@ -1499,7 +1501,7 @@ int InputEventMIDI::get_controller_value() const {
}
String InputEventMIDI::as_text() const {
- return vformat(RTR("MIDI Input on Channel=%s Message=%s"), itos(channel), itos(message));
+ return vformat(RTR("MIDI Input on Channel=%s Message=%s"), itos(channel), itos((int64_t)message));
}
String InputEventMIDI::to_string() {
@@ -1557,9 +1559,13 @@ bool InputEventShortcut::is_pressed() const {
}
String InputEventShortcut::as_text() const {
+ ERR_FAIL_COND_V(shortcut.is_null(), "None");
+
return vformat(RTR("Input Event with Shortcut=%s"), shortcut->get_as_text());
}
String InputEventShortcut::to_string() {
+ ERR_FAIL_COND_V(shortcut.is_null(), "None");
+
return vformat("InputEventShortcut: shortcut=%s", shortcut->get_as_text());
}
diff --git a/core/input/input_event.h b/core/input/input_event.h
index 3fc8078a09..29450dfc52 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -151,7 +151,7 @@ public:
void set_modifiers_from_event(const InputEventWithModifiers *event);
- uint32_t get_modifiers_mask() const;
+ Key get_modifiers_mask() const;
virtual String as_text() const override;
virtual String to_string() override;
@@ -164,8 +164,8 @@ class InputEventKey : public InputEventWithModifiers {
bool pressed = false; /// otherwise release
- Key keycode = KEY_NONE; // Key enum, without modifier masks.
- Key physical_keycode = KEY_NONE;
+ Key keycode = Key::NONE; // Key enum, without modifier masks.
+ Key physical_keycode = Key::NONE;
uint32_t unicode = 0; ///unicode
bool echo = false; /// true if this is an echo key
@@ -183,14 +183,14 @@ public:
void set_physical_keycode(Key p_keycode);
Key get_physical_keycode() const;
- void set_unicode(uint32_t p_unicode);
- uint32_t get_unicode() const;
+ void set_unicode(char32_t p_unicode);
+ char32_t get_unicode() const;
void set_echo(bool p_enable);
virtual bool is_echo() const override;
- uint32_t get_keycode_with_modifiers() const;
- uint32_t get_physical_keycode_with_modifiers() const;
+ Key get_keycode_with_modifiers() const;
+ Key get_physical_keycode_with_modifiers() const;
virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override;
@@ -208,7 +208,7 @@ public:
class InputEventMouse : public InputEventWithModifiers {
GDCLASS(InputEventMouse, InputEventWithModifiers);
- int button_mask = 0;
+ MouseButton button_mask = MouseButton::NONE;
Vector2 pos;
Vector2 global_pos;
@@ -217,8 +217,8 @@ protected:
static void _bind_methods();
public:
- void set_button_mask(int p_mask);
- int get_button_mask() const;
+ void set_button_mask(MouseButton p_mask);
+ MouseButton get_button_mask() const;
void set_position(const Vector2 &p_pos);
Vector2 get_position() const;
@@ -233,7 +233,7 @@ class InputEventMouseButton : public InputEventMouse {
GDCLASS(InputEventMouseButton, InputEventMouse);
float factor = 1;
- MouseButton button_index = MOUSE_BUTTON_NONE;
+ MouseButton button_index = MouseButton::NONE;
bool pressed = false; //otherwise released
bool double_click = false; //last even less than double click time
@@ -271,7 +271,7 @@ class InputEventMouseMotion : public InputEventMouse {
Vector2 tilt;
float pressure = 0;
Vector2 relative;
- Vector2 speed;
+ Vector2 velocity;
protected:
static void _bind_methods();
@@ -286,8 +286,8 @@ public:
void set_relative(const Vector2 &p_relative);
Vector2 get_relative() const;
- void set_speed(const Vector2 &p_speed);
- Vector2 get_speed() const;
+ void set_velocity(const Vector2 &p_velocity);
+ Vector2 get_velocity() const;
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
virtual String as_text() const override;
@@ -388,7 +388,7 @@ class InputEventScreenDrag : public InputEventFromWindow {
int index = 0;
Vector2 pos;
Vector2 relative;
- Vector2 speed;
+ Vector2 velocity;
protected:
static void _bind_methods();
@@ -403,8 +403,8 @@ public:
void set_relative(const Vector2 &p_relative);
Vector2 get_relative() const;
- void set_speed(const Vector2 &p_speed);
- Vector2 get_speed() const;
+ void set_velocity(const Vector2 &p_velocity);
+ Vector2 get_velocity() const;
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
virtual String as_text() const override;
@@ -501,7 +501,7 @@ class InputEventMIDI : public InputEvent {
GDCLASS(InputEventMIDI, InputEvent);
int channel = 0;
- MIDIMessage message = MIDI_MESSAGE_NONE;
+ MIDIMessage message = MIDIMessage::NONE;
int pitch = 0;
int velocity = 0;
int instrument = 0;
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index c6db7be53a..753ac72ab6 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "core/os/keyboard.h"
+#include "core/os/os.h"
InputMap *InputMap::singleton = nullptr;
@@ -380,353 +381,376 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
}
List<Ref<InputEvent>> inputs;
- inputs.push_back(InputEventKey::create_reference(KEY_ENTER));
- inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER));
- inputs.push_back(InputEventKey::create_reference(KEY_SPACE));
+ inputs.push_back(InputEventKey::create_reference(Key::ENTER));
+ inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER));
+ inputs.push_back(InputEventKey::create_reference(Key::SPACE));
default_builtin_cache.insert("ui_accept", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_Y));
- inputs.push_back(InputEventKey::create_reference(KEY_SPACE));
+ inputs.push_back(InputEventJoypadButton::create_reference(JoyButton::Y));
+ inputs.push_back(InputEventKey::create_reference(Key::SPACE));
default_builtin_cache.insert("ui_select", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_ESCAPE));
+ inputs.push_back(InputEventKey::create_reference(Key::ESCAPE));
default_builtin_cache.insert("ui_cancel", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_TAB));
+ inputs.push_back(InputEventKey::create_reference(Key::TAB));
default_builtin_cache.insert("ui_focus_next", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_TAB | KEY_MASK_SHIFT));
+ inputs.push_back(InputEventKey::create_reference(Key::TAB | KeyModifierMask::SHIFT));
default_builtin_cache.insert("ui_focus_prev", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_LEFT));
- inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_LEFT));
+ inputs.push_back(InputEventKey::create_reference(Key::LEFT));
+ inputs.push_back(InputEventJoypadButton::create_reference(JoyButton::DPAD_LEFT));
default_builtin_cache.insert("ui_left", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_RIGHT));
- inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_RIGHT));
+ inputs.push_back(InputEventKey::create_reference(Key::RIGHT));
+ inputs.push_back(InputEventJoypadButton::create_reference(JoyButton::DPAD_RIGHT));
default_builtin_cache.insert("ui_right", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_UP));
- inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_UP));
+ inputs.push_back(InputEventKey::create_reference(Key::UP));
+ inputs.push_back(InputEventJoypadButton::create_reference(JoyButton::DPAD_UP));
default_builtin_cache.insert("ui_up", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_DOWN));
- inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_DOWN));
+ inputs.push_back(InputEventKey::create_reference(Key::DOWN));
+ inputs.push_back(InputEventJoypadButton::create_reference(JoyButton::DPAD_DOWN));
default_builtin_cache.insert("ui_down", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_PAGEUP));
+ inputs.push_back(InputEventKey::create_reference(Key::PAGEUP));
default_builtin_cache.insert("ui_page_up", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_PAGEDOWN));
+ inputs.push_back(InputEventKey::create_reference(Key::PAGEDOWN));
default_builtin_cache.insert("ui_page_down", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_HOME));
+ inputs.push_back(InputEventKey::create_reference(Key::HOME));
default_builtin_cache.insert("ui_home", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_END));
+ inputs.push_back(InputEventKey::create_reference(Key::END));
default_builtin_cache.insert("ui_end", inputs);
// ///// UI basic Shortcuts /////
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_X | KEY_MASK_CMD));
- inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_SHIFT));
+ inputs.push_back(InputEventKey::create_reference(Key::X | KeyModifierMask::CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE | KeyModifierMask::SHIFT));
default_builtin_cache.insert("ui_cut", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_C | KEY_MASK_CMD));
- inputs.push_back(InputEventKey::create_reference(KEY_INSERT | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::C | KeyModifierMask::CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::INSERT | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_copy", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_V | KEY_MASK_CMD));
- inputs.push_back(InputEventKey::create_reference(KEY_INSERT | KEY_MASK_SHIFT));
+ inputs.push_back(InputEventKey::create_reference(Key::V | KeyModifierMask::CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::INSERT | KeyModifierMask::SHIFT));
default_builtin_cache.insert("ui_paste", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_Z | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::Z | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_undo", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_Z | KEY_MASK_CMD | KEY_MASK_SHIFT));
- inputs.push_back(InputEventKey::create_reference(KEY_Y | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::Z | KeyModifierMask::CMD | KeyModifierMask::SHIFT));
+ inputs.push_back(InputEventKey::create_reference(Key::Y | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_redo", inputs);
// ///// UI Text Input Shortcuts /////
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_SPACE | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::SPACE | KeyModifierMask::CTRL));
default_builtin_cache.insert("ui_text_completion_query", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_ENTER));
- inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER));
+ inputs.push_back(InputEventKey::create_reference(Key::ENTER));
+ inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER));
default_builtin_cache.insert("ui_text_completion_accept", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_TAB));
+ inputs.push_back(InputEventKey::create_reference(Key::TAB));
default_builtin_cache.insert("ui_text_completion_replace", inputs);
// Newlines
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_ENTER));
- inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER));
+ inputs.push_back(InputEventKey::create_reference(Key::ENTER));
+ inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER));
default_builtin_cache.insert("ui_text_newline", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_ENTER | KEY_MASK_CMD));
- inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::ENTER | KeyModifierMask::CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_newline_blank", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_ENTER | KEY_MASK_SHIFT | KEY_MASK_CMD));
- inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER | KEY_MASK_SHIFT | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::ENTER | KeyModifierMask::SHIFT | KeyModifierMask::CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER | KeyModifierMask::SHIFT | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_newline_above", inputs);
// Indentation
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_TAB));
+ inputs.push_back(InputEventKey::create_reference(Key::TAB));
default_builtin_cache.insert("ui_text_indent", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_TAB | KEY_MASK_SHIFT));
+ inputs.push_back(InputEventKey::create_reference(Key::TAB | KeyModifierMask::SHIFT));
default_builtin_cache.insert("ui_text_dedent", inputs);
// Text Backspace and Delete
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE));
- inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_SHIFT));
+ inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE));
+ inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::SHIFT));
default_builtin_cache.insert("ui_text_backspace", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_backspace_word", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_ALT));
+ inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::ALT));
default_builtin_cache.insert("ui_text_backspace_word.macos", inputs);
inputs = List<Ref<InputEvent>>();
default_builtin_cache.insert("ui_text_backspace_all_to_left", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_backspace_all_to_left.macos", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_DELETE));
+ inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE));
default_builtin_cache.insert("ui_text_delete", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_delete_word", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_ALT));
+ inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE | KeyModifierMask::ALT));
default_builtin_cache.insert("ui_text_delete_word.macos", inputs);
inputs = List<Ref<InputEvent>>();
default_builtin_cache.insert("ui_text_delete_all_to_right", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_delete_all_to_right.macos", inputs);
// Text Caret Movement Left/Right
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_LEFT));
+ inputs.push_back(InputEventKey::create_reference(Key::LEFT));
default_builtin_cache.insert("ui_text_caret_left", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_LEFT | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::LEFT | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_caret_word_left", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_LEFT | KEY_MASK_ALT));
+ inputs.push_back(InputEventKey::create_reference(Key::LEFT | KeyModifierMask::ALT));
default_builtin_cache.insert("ui_text_caret_word_left.macos", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_RIGHT));
+ inputs.push_back(InputEventKey::create_reference(Key::RIGHT));
default_builtin_cache.insert("ui_text_caret_right", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_RIGHT | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::RIGHT | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_caret_word_right", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_RIGHT | KEY_MASK_ALT));
+ inputs.push_back(InputEventKey::create_reference(Key::RIGHT | KeyModifierMask::ALT));
default_builtin_cache.insert("ui_text_caret_word_right.macos", inputs);
// Text Caret Movement Up/Down
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_UP));
+ inputs.push_back(InputEventKey::create_reference(Key::UP));
default_builtin_cache.insert("ui_text_caret_up", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_DOWN));
+ inputs.push_back(InputEventKey::create_reference(Key::DOWN));
default_builtin_cache.insert("ui_text_caret_down", inputs);
// Text Caret Movement Line Start/End
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_HOME));
+ inputs.push_back(InputEventKey::create_reference(Key::HOME));
default_builtin_cache.insert("ui_text_caret_line_start", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_A | KEY_MASK_CTRL));
- inputs.push_back(InputEventKey::create_reference(KEY_LEFT | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::A | KeyModifierMask::CTRL));
+ inputs.push_back(InputEventKey::create_reference(Key::LEFT | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_caret_line_start.macos", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_END));
+ inputs.push_back(InputEventKey::create_reference(Key::END));
default_builtin_cache.insert("ui_text_caret_line_end", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_E | KEY_MASK_CTRL));
- inputs.push_back(InputEventKey::create_reference(KEY_RIGHT | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::E | KeyModifierMask::CTRL));
+ inputs.push_back(InputEventKey::create_reference(Key::RIGHT | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_caret_line_end.macos", inputs);
// Text Caret Movement Page Up/Down
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_PAGEUP));
+ inputs.push_back(InputEventKey::create_reference(Key::PAGEUP));
default_builtin_cache.insert("ui_text_caret_page_up", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_PAGEDOWN));
+ inputs.push_back(InputEventKey::create_reference(Key::PAGEDOWN));
default_builtin_cache.insert("ui_text_caret_page_down", inputs);
// Text Caret Movement Document Start/End
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_HOME | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::HOME | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_caret_document_start", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_UP | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::UP | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_caret_document_start.macos", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_END | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::END | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_caret_document_end", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_DOWN | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::DOWN | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_caret_document_end.macos", inputs);
// Text Scrolling
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_UP | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::UP | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_scroll_up", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_UP | KEY_MASK_CMD | KEY_MASK_ALT));
+ inputs.push_back(InputEventKey::create_reference(Key::UP | KeyModifierMask::CMD | KeyModifierMask::ALT));
default_builtin_cache.insert("ui_text_scroll_up.macos", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_DOWN | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::DOWN | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_scroll_down", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_DOWN | KEY_MASK_CMD | KEY_MASK_ALT));
+ inputs.push_back(InputEventKey::create_reference(Key::DOWN | KeyModifierMask::CMD | KeyModifierMask::ALT));
default_builtin_cache.insert("ui_text_scroll_down.macos", inputs);
// Text Misc
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_A | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::A | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_select_all", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_D | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::D | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_text_select_word_under_caret", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_INSERT));
+ inputs.push_back(InputEventKey::create_reference(Key::INSERT));
default_builtin_cache.insert("ui_text_toggle_insert_mode", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_MENU));
+ inputs.push_back(InputEventKey::create_reference(Key::MENU));
default_builtin_cache.insert("ui_menu", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_ENTER));
- inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER));
+ inputs.push_back(InputEventKey::create_reference(Key::ENTER));
+ inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER));
default_builtin_cache.insert("ui_text_submit", inputs);
// ///// UI Graph Shortcuts /////
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_D | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::D | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_graph_duplicate", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_DELETE));
+ inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE));
default_builtin_cache.insert("ui_graph_delete", inputs);
// ///// UI File Dialog Shortcuts /////
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE));
+ inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE));
default_builtin_cache.insert("ui_filedialog_up_one_level", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_F5));
+ inputs.push_back(InputEventKey::create_reference(Key::F5));
default_builtin_cache.insert("ui_filedialog_refresh", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_H));
+ inputs.push_back(InputEventKey::create_reference(Key::H));
default_builtin_cache.insert("ui_filedialog_show_hidden", inputs);
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_QUOTELEFT | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(Key::QUOTELEFT | KeyModifierMask::CMD));
default_builtin_cache.insert("ui_swap_input_direction", inputs);
return default_builtin_cache;
}
-void InputMap::load_default() {
+const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_feature_overrides_applied() {
+ if (default_builtin_with_overrides_cache.size() > 0) {
+ return default_builtin_with_overrides_cache;
+ }
+
OrderedHashMap<String, List<Ref<InputEvent>>> builtins = get_builtins();
- // List of Builtins which have an override for macOS.
- Vector<String> macos_builtins;
+ // Get a list of all built in inputs which are valid overrides for the OS
+ // Key = builtin name (e.g. ui_accept)
+ // Value = override/feature names (e.g. macos, if it was defined as "ui_accept.macos" and the platform supports that feature)
+ Map<String, Vector<String>> builtins_with_overrides;
for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
- if (String(E.key()).ends_with(".macos")) {
- // Strip .macos from name: some_input_name.macos -> some_input_name
- macos_builtins.push_back(String(E.key()).split(".")[0]);
+ String fullname = E.key();
+
+ Vector<String> split = fullname.split(".");
+ String name = split[0];
+ String override_for = split.size() > 1 ? split[1] : String();
+
+ if (!override_for.is_empty() && OS::get_singleton()->has_feature(override_for)) {
+ builtins_with_overrides[name].push_back(override_for);
}
}
for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
String fullname = E.key();
- String name = fullname.split(".")[0];
- String override_for = fullname.split(".").size() > 1 ? fullname.split(".")[1] : "";
-#ifdef APPLE_STYLE_KEYS
- if (macos_builtins.has(name) && override_for != "macos") {
- // Name has `macos` builtin but this particular one is for non-macOS systems - so skip.
+ Vector<String> split = fullname.split(".");
+ String name = split[0];
+ String override_for = split.size() > 1 ? split[1] : String();
+
+ if (builtins_with_overrides.has(name) && override_for.is_empty()) {
+ // Builtin has an override but this particular one is not an override, so skip.
continue;
}
-#else
- if (override_for == "macos") {
- // Override for macOS - not needed on non-macOS platforms.
+
+ if (!override_for.is_empty() && !OS::get_singleton()->has_feature(override_for)) {
+ // OS does not support this override - skip.
continue;
}
-#endif
+
+ default_builtin_with_overrides_cache.insert(name, E.value());
+ }
+
+ return default_builtin_with_overrides_cache;
+}
+
+void InputMap::load_default() {
+ OrderedHashMap<String, List<Ref<InputEvent>>> builtins = get_builtins_with_feature_overrides_applied();
+
+ for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
+ String name = E.key();
add_action(name);
diff --git a/core/input/input_map.h b/core/input/input_map.h
index c724fdb142..e896d1f679 100644
--- a/core/input/input_map.h
+++ b/core/input/input_map.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -41,8 +41,8 @@ class InputMap : public Object {
public:
/**
- * A special value used to signify that a given Action can be triggered by any device
- */
+ * A special value used to signify that a given Action can be triggered by any device
+ */
static int ALL_DEVICES;
struct Action {
@@ -56,6 +56,7 @@ private:
mutable OrderedHashMap<StringName, Action> input_map;
OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_cache;
+ OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_with_overrides_cache;
List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
@@ -93,6 +94,7 @@ public:
String get_builtin_display_name(const String &p_name) const;
// Use an Ordered Map so insertion order is preserved. We want the elements to be 'grouped' somewhat.
const OrderedHashMap<String, List<Ref<InputEvent>>> &get_builtins();
+ const OrderedHashMap<String, List<Ref<InputEvent>>> &get_builtins_with_feature_overrides_applied();
InputMap();
~InputMap();
diff --git a/core/input/shortcut.cpp b/core/input/shortcut.cpp
index d0cb08724e..9eeeb449ba 100644
--- a/core/input/shortcut.cpp
+++ b/core/input/shortcut.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,14 +31,26 @@
#include "shortcut.h"
#include "core/os/keyboard.h"
-void Shortcut::set_event(const Ref<InputEvent> &p_event) {
- ERR_FAIL_COND_MSG(Object::cast_to<InputEventShortcut>(*p_event), "Cannot set a shortcut event to an instance of InputEventShortcut.");
- event = p_event;
+void Shortcut::set_events(const Array &p_events) {
+ for (int i = 0; i < p_events.size(); i++) {
+ Ref<InputEventShortcut> ies = p_events[i];
+ ERR_FAIL_COND_MSG(ies.is_valid(), "Cannot set a shortcut event to an instance of InputEventShortcut.");
+ }
+
+ events = p_events;
emit_changed();
}
-Ref<InputEvent> Shortcut::get_event() const {
- return event;
+void Shortcut::set_events_list(const List<Ref<InputEvent>> *p_events) {
+ events.clear();
+
+ for (const Ref<InputEvent> &ie : *p_events) {
+ events.push_back(ie);
+ }
+}
+
+Array Shortcut::get_events() const {
+ return events;
}
bool Shortcut::matches_event(const Ref<InputEvent> &p_event) const {
@@ -48,29 +60,73 @@ bool Shortcut::matches_event(const Ref<InputEvent> &p_event) const {
return true;
}
}
- return event.is_valid() && event->is_match(p_event, true);
+
+ for (int i = 0; i < events.size(); i++) {
+ Ref<InputEvent> ie = events[i];
+ bool valid = ie.is_valid() && ie->is_match(p_event);
+
+ // Stop on first valid event - don't need to check further.
+ if (valid) {
+ return true;
+ }
+ }
+
+ return false;
}
String Shortcut::get_as_text() const {
- if (event.is_valid()) {
- return event->as_text();
- } else {
- return "None";
+ for (int i = 0; i < events.size(); i++) {
+ Ref<InputEvent> ie = events[i];
+ // Return first shortcut which is valid
+ if (ie.is_valid()) {
+ return ie->as_text();
+ }
}
+
+ return "None";
}
bool Shortcut::has_valid_event() const {
- return event.is_valid();
+ // Tests if there is ANY input event which is valid.
+ for (int i = 0; i < events.size(); i++) {
+ Ref<InputEvent> ie = events[i];
+ if (ie.is_valid()) {
+ return true;
+ }
+ }
+
+ return false;
}
void Shortcut::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_event", "event"), &Shortcut::set_event);
- ClassDB::bind_method(D_METHOD("get_event"), &Shortcut::get_event);
+ ClassDB::bind_method(D_METHOD("set_events", "events"), &Shortcut::set_events);
+ ClassDB::bind_method(D_METHOD("get_events"), &Shortcut::get_events);
ClassDB::bind_method(D_METHOD("has_valid_event"), &Shortcut::has_valid_event);
ClassDB::bind_method(D_METHOD("matches_event", "event"), &Shortcut::matches_event);
ClassDB::bind_method(D_METHOD("get_as_text"), &Shortcut::get_as_text);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), "set_event", "get_event");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "events", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")), "set_events", "get_events");
+}
+
+bool Shortcut::is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2) {
+ if (p_event_array1.size() != p_event_array2.size()) {
+ return false;
+ }
+
+ bool is_same = true;
+ for (int i = 0; i < p_event_array1.size(); i++) {
+ Ref<InputEvent> ie_1 = p_event_array1[i];
+ Ref<InputEvent> ie_2 = p_event_array2[i];
+
+ is_same = ie_1->is_match(ie_2);
+
+ // Break on the first that doesn't match - don't need to check further.
+ if (!is_same) {
+ break;
+ }
+ }
+
+ return is_same;
}
diff --git a/core/input/shortcut.h b/core/input/shortcut.h
index 249dd1971f..0c9689cdcb 100644
--- a/core/input/shortcut.h
+++ b/core/input/shortcut.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,18 +37,22 @@
class Shortcut : public Resource {
GDCLASS(Shortcut, Resource);
- Ref<InputEvent> event;
+ Array events;
protected:
static void _bind_methods();
public:
- void set_event(const Ref<InputEvent> &p_shortcut);
- Ref<InputEvent> get_event() const;
+ void set_events(const Array &p_events);
+ Array get_events() const;
+
+ void set_events_list(const List<Ref<InputEvent>> *p_events);
+
bool matches_event(const Ref<InputEvent> &p_event) const;
bool has_valid_event() const;
String get_as_text() const;
-};
+ static bool is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2);
+};
#endif // SHORTCUT_H
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index 790b6febc0..d1f915f064 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/compression.h b/core/io/compression.h
index cbfed74124..2e66970a6c 100644
--- a/core/io/compression.h
+++ b/core/io/compression.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -54,8 +54,6 @@ public:
static int get_max_compressed_buffer_size(int p_src_size, Mode p_mode = MODE_ZSTD);
static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD);
static int decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_size, const uint8_t *p_src, int p_src_size, Mode p_mode);
-
- Compression() {}
};
#endif // COMPRESSION_H
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index 49fa73dab2..c942b417e4 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -183,7 +183,9 @@ Error ConfigFile::_internal_save(FileAccess *file) {
if (E != values.front()) {
file->store_string("\n");
}
- file->store_string("[" + E.key() + "]\n\n");
+ if (!E.key().is_empty()) {
+ file->store_string("[" + E.key() + "]\n\n");
+ }
for (OrderedHashMap<String, Variant>::Element F = E.get().front(); F; F = F.next()) {
String vstr;
@@ -285,9 +287,9 @@ Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream)
return err;
}
- if (assign != String()) {
+ if (!assign.is_empty()) {
set_value(section, assign, value);
- } else if (next_tag.name != String()) {
+ } else if (!next_tag.name.is_empty()) {
section = next_tag.name;
}
}
diff --git a/core/io/config_file.h b/core/io/config_file.h
index dbba43ace5..71e9080fb7 100644
--- a/core/io/config_file.h
+++ b/core/io/config_file.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp
index 3bff0a3fd5..3da9288ffd 100644
--- a/core/io/dir_access.cpp
+++ b/core/io/dir_access.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -79,7 +79,7 @@ static Error _erase_recursive(DirAccess *da) {
da->list_dir_begin();
String n = da->get_next();
- while (n != String()) {
+ while (!n.is_empty()) {
if (n != "." && n != "..") {
if (da->current_is_dir()) {
dirs.push_back(n);
@@ -183,7 +183,7 @@ String DirAccess::fix_path(String p_path) const {
if (ProjectSettings::get_singleton()) {
if (p_path.begins_with("res://")) {
String resource_path = ProjectSettings::get_singleton()->get_resource_path();
- if (resource_path != "") {
+ if (!resource_path.is_empty()) {
return p_path.replace_first("res:/", resource_path);
}
return p_path.replace_first("res://", "");
@@ -194,7 +194,7 @@ String DirAccess::fix_path(String p_path) const {
case ACCESS_USERDATA: {
if (p_path.begins_with("user://")) {
String data_dir = OS::get_singleton()->get_user_data_dir();
- if (data_dir != "") {
+ if (!data_dir.is_empty()) {
return p_path.replace_first("user:/", data_dir);
}
return p_path.replace_first("user://", "");
@@ -337,7 +337,7 @@ Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flag
String curdir = get_current_dir();
list_dir_begin();
String n = get_next();
- while (n != String()) {
+ while (!n.is_empty()) {
if (n != "." && n != "..") {
if (p_copy_links && is_link(get_current_dir().plus_file(n))) {
create_link(read_link(get_current_dir().plus_file(n)), p_to + n);
diff --git a/core/io/dir_access.h b/core/io/dir_access.h
index 16154a4850..8154f5366c 100644
--- a/core/io/dir_access.h
+++ b/core/io/dir_access.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/dtls_server.cpp b/core/io/dtls_server.cpp
index 655fb18535..b5c44e1b64 100644
--- a/core/io/dtls_server.cpp
+++ b/core/io/dtls_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/dtls_server.h b/core/io/dtls_server.h
index 02a32533e1..0c9b0149b0 100644
--- a/core/io/dtls_server.h
+++ b/core/io/dtls_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
index e6e79dff8a..bb92648484 100644
--- a/core/io/file_access.cpp
+++ b/core/io/file_access.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -127,7 +127,7 @@ String FileAccess::fix_path(const String &p_path) const {
if (ProjectSettings::get_singleton()) {
if (r_path.begins_with("res://")) {
String resource_path = ProjectSettings::get_singleton()->get_resource_path();
- if (resource_path != "") {
+ if (!resource_path.is_empty()) {
return r_path.replace("res:/", resource_path);
}
return r_path.replace("res://", "");
@@ -138,7 +138,7 @@ String FileAccess::fix_path(const String &p_path) const {
case ACCESS_USERDATA: {
if (r_path.begins_with("user://")) {
String data_dir = OS::get_singleton()->get_user_data_dir();
- if (data_dir != "") {
+ if (!data_dir.is_empty()) {
return r_path.replace("user:/", data_dir);
}
return r_path.replace("user://", "");
diff --git a/core/io/file_access.h b/core/io/file_access.h
index 5804aa2c47..5413665440 100644
--- a/core/io/file_access.h
+++ b/core/io/file_access.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index e54c947340..526952b14f 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -233,7 +233,7 @@ uint64_t FileAccessCompressed::get_position() const {
if (writing) {
return write_pos;
} else {
- return read_block * block_size + read_pos;
+ return (uint64_t)read_block * block_size + read_pos;
}
}
@@ -312,10 +312,10 @@ uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) con
} else {
read_block--;
at_end = true;
- if (i < p_length - 1) {
+ if (i + 1 < p_length) {
read_eof = true;
}
- return i;
+ return i + 1;
}
}
}
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index 3389e020e3..97ef3fbdeb 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 9e316291e8..8ee19d3d06 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index decffae696..be5904c894 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 627fd2bf9c..4aca26b007 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index 14135bd68c..50b23e1f32 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 9ee3876c2f..307004b1c2 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index 1d9d761fbb..6cae49b540 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 7b43daf9c0..3882627103 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -110,8 +110,8 @@ PackedData::PackedData() {
}
void PackedData::_free_packed_dirs(PackedDir *p_dir) {
- for (Map<String, PackedDir *>::Element *E = p_dir->subdirs.front(); E; E = E->next()) {
- _free_packed_dirs(E->get());
+ for (const KeyValue<String, PackedDir *> &E : p_dir->subdirs) {
+ _free_packed_dirs(E.value);
}
memdelete(p_dir);
}
@@ -395,8 +395,8 @@ Error DirAccessPack::list_dir_begin() {
list_dirs.clear();
list_files.clear();
- for (Map<String, PackedData::PackedDir *>::Element *E = current->subdirs.front(); E; E = E->next()) {
- list_dirs.push_back(E->key());
+ for (const KeyValue<String, PackedData::PackedDir *> &E : current->subdirs) {
+ list_dirs.push_back(E.key);
}
for (Set<String>::Element *E = current->files.front(); E; E = E->next()) {
@@ -459,7 +459,7 @@ PackedData::PackedDir *DirAccessPack::_find_dir(String p_dir) {
nd = nd.simplify_path();
- if (nd == "") {
+ if (nd.is_empty()) {
nd = ".";
}
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 2f0ee62723..6eee2f593d 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index b5c882e9ce..6347862775 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -99,7 +99,7 @@ static int godot_testerror(voidpf opaque, voidpf stream) {
}
static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) {
- return memalloc(items * size);
+ return memalloc((size_t)items * size);
}
static void godot_free(voidpf opaque, voidpf address) {
@@ -189,7 +189,7 @@ bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files, uint6
f.package = pkg_num;
unzGetFilePos(zfile, &f.file_pos);
- String fname = String("res://") + filename_inzip;
+ String fname = String("res://") + String::utf8(filename_inzip);
files[fname] = f;
uint8_t md5[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index cca14ded62..7cd5893101 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index 5c1352c1b6..4d0747c591 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -49,6 +49,14 @@ HTTPClient *HTTPClient::create() {
return nullptr;
}
+void HTTPClient::set_http_proxy(const String &p_host, int p_port) {
+ WARN_PRINT("HTTP proxy feature is not available");
+}
+
+void HTTPClient::set_https_proxy(const String &p_host, int p_port) {
+ WARN_PRINT("HTTPS proxy feature is not available");
+}
+
Error HTTPClient::_request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const Vector<uint8_t> &p_body) {
int size = p_body.size();
return request(p_method, p_url, p_headers, size > 0 ? p_body.ptr() : nullptr, size);
@@ -85,8 +93,7 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
}
}
}
- query.erase(0, 1);
- return query;
+ return query.substr(1);
}
Dictionary HTTPClient::_get_response_headers_as_dictionary() {
@@ -143,6 +150,9 @@ void HTTPClient::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_status"), &HTTPClient::get_status);
ClassDB::bind_method(D_METHOD("poll"), &HTTPClient::poll);
+ ClassDB::bind_method(D_METHOD("set_http_proxy", "host", "port"), &HTTPClient::set_http_proxy);
+ ClassDB::bind_method(D_METHOD("set_https_proxy", "host", "port"), &HTTPClient::set_https_proxy);
+
ClassDB::bind_method(D_METHOD("query_string_from_dict", "fields"), &HTTPClient::query_string_from_dict);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "blocking_mode_enabled"), "set_blocking_mode", "is_blocking_mode_enabled");
diff --git a/core/io/http_client.h b/core/io/http_client.h
index 718c3a905e..8be6e6524c 100644
--- a/core/io/http_client.h
+++ b/core/io/http_client.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -192,6 +192,10 @@ public:
virtual Error poll() = 0;
+ // Use empty string or -1 to unset
+ virtual void set_http_proxy(const String &p_host, int p_port);
+ virtual void set_https_proxy(const String &p_host, int p_port);
+
HTTPClient() {}
virtual ~HTTPClient() {}
};
diff --git a/core/io/http_client_tcp.cpp b/core/io/http_client_tcp.cpp
index b3d35b3603..4c27cd1b10 100644
--- a/core/io/http_client_tcp.cpp
+++ b/core/io/http_client_tcp.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -70,9 +70,21 @@ Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, bool p_ss
connection = tcp_connection;
- if (conn_host.is_valid_ip_address()) {
+ if (ssl && https_proxy_port != -1) {
+ proxy_client.instantiate(); // Needs proxy negotiation
+ server_host = https_proxy_host;
+ server_port = https_proxy_port;
+ } else if (!ssl && http_proxy_port != -1) {
+ server_host = http_proxy_host;
+ server_port = http_proxy_port;
+ } else {
+ server_host = conn_host;
+ server_port = conn_port;
+ }
+
+ if (server_host.is_valid_ip_address()) {
// Host contains valid IP
- Error err = tcp_connection->connect_to_host(IPAddress(conn_host), p_port);
+ Error err = tcp_connection->connect_to_host(IPAddress(server_host), server_port);
if (err) {
status = STATUS_CANT_CONNECT;
return err;
@@ -81,7 +93,7 @@ Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, bool p_ss
status = STATUS_CONNECTING;
} else {
// Host contains hostname and needs to be resolved to IP
- resolving = IP::get_singleton()->resolve_hostname_queue_item(conn_host);
+ resolving = IP::get_singleton()->resolve_hostname_queue_item(server_host);
status = STATUS_RESOLVING;
}
@@ -134,7 +146,12 @@ Error HTTPClientTCP::request(Method p_method, const String &p_url, const Vector<
ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);
- String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
+ String uri = p_url;
+ if (!ssl && http_proxy_port != -1) {
+ uri = vformat("http://%s:%d%s", conn_host, conn_port, p_url);
+ }
+
+ String request = String(_methods[p_method]) + " " + uri + " HTTP/1.1\r\n";
bool add_host = true;
bool add_clen = p_body_size > 0;
bool add_uagent = true;
@@ -229,6 +246,7 @@ void HTTPClientTCP::close() {
}
connection.unref();
+ proxy_client.unref();
status = STATUS_DISCONNECTED;
head_request = false;
if (resolving != IP::RESOLVER_INVALID_ID) {
@@ -265,7 +283,7 @@ Error HTTPClientTCP::poll() {
Error err = ERR_BUG; // Should be at least one entry.
while (ip_candidates.size() > 0) {
- err = tcp_connection->connect_to_host(ip_candidates.front(), conn_port);
+ err = tcp_connection->connect_to_host(ip_candidates.pop_front(), server_port);
if (err == OK) {
break;
}
@@ -294,7 +312,48 @@ Error HTTPClientTCP::poll() {
return OK;
} break;
case StreamPeerTCP::STATUS_CONNECTED: {
- if (ssl) {
+ if (ssl && proxy_client.is_valid()) {
+ Error err = proxy_client->poll();
+ if (err == ERR_UNCONFIGURED) {
+ proxy_client->set_connection(tcp_connection);
+ const Vector<String> headers;
+ err = proxy_client->request(METHOD_CONNECT, vformat("%s:%d", conn_host, conn_port), headers, nullptr, 0);
+ if (err != OK) {
+ status = STATUS_CANT_CONNECT;
+ return err;
+ }
+ } else if (err != OK) {
+ status = STATUS_CANT_CONNECT;
+ return err;
+ }
+ switch (proxy_client->get_status()) {
+ case STATUS_REQUESTING: {
+ return OK;
+ } break;
+ case STATUS_BODY: {
+ proxy_client->read_response_body_chunk();
+ return OK;
+ } break;
+ case STATUS_CONNECTED: {
+ if (proxy_client->get_response_code() != RESPONSE_OK) {
+ status = STATUS_CANT_CONNECT;
+ return ERR_CANT_CONNECT;
+ }
+ proxy_client.unref();
+ return OK;
+ }
+ case STATUS_DISCONNECTED:
+ case STATUS_RESOLVING:
+ case STATUS_CONNECTING: {
+ status = STATUS_CANT_CONNECT;
+ ERR_FAIL_V(ERR_BUG);
+ } break;
+ default: {
+ status = STATUS_CANT_CONNECT;
+ return ERR_CANT_CONNECT;
+ } break;
+ }
+ } else if (ssl) {
Ref<StreamPeerSSL> ssl;
if (!handshaking) {
// Connect the StreamPeerSSL and start handshaking
@@ -344,7 +403,7 @@ Error HTTPClientTCP::poll() {
Error err = ERR_CANT_CONNECT;
while (ip_candidates.size() > 0) {
tcp_connection->disconnect_from_host();
- err = tcp_connection->connect_to_host(ip_candidates.pop_front(), conn_port);
+ err = tcp_connection->connect_to_host(ip_candidates.pop_front(), server_port);
if (err == OK) {
return OK;
}
@@ -678,6 +737,26 @@ int HTTPClientTCP::get_read_chunk_size() const {
return read_chunk_size;
}
+void HTTPClientTCP::set_http_proxy(const String &p_host, int p_port) {
+ if (p_host.is_empty() || p_port == -1) {
+ http_proxy_host = "";
+ http_proxy_port = -1;
+ } else {
+ http_proxy_host = p_host;
+ http_proxy_port = p_port;
+ }
+}
+
+void HTTPClientTCP::set_https_proxy(const String &p_host, int p_port) {
+ if (p_host.is_empty() || p_port == -1) {
+ https_proxy_host = "";
+ https_proxy_port = -1;
+ } else {
+ https_proxy_host = p_host;
+ https_proxy_port = p_port;
+ }
+}
+
HTTPClientTCP::HTTPClientTCP() {
tcp_connection.instantiate();
}
diff --git a/core/io/http_client_tcp.h b/core/io/http_client_tcp.h
index 170afb551c..886ad0ef48 100644
--- a/core/io/http_client_tcp.h
+++ b/core/io/http_client_tcp.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,8 +38,14 @@ private:
Status status = STATUS_DISCONNECTED;
IP::ResolverID resolving = IP::RESOLVER_INVALID_ID;
Array ip_candidates;
- int conn_port = -1;
+ int conn_port = -1; // Server to make requests to
String conn_host;
+ int server_port = -1; // Server to connect to (might be a proxy server)
+ String server_host;
+ int http_proxy_port = -1; // Proxy server for http requests
+ String http_proxy_host;
+ int https_proxy_port = -1; // Proxy server for https requests
+ String https_proxy_host;
bool ssl = false;
bool ssl_verify_host = false;
bool blocking = false;
@@ -52,12 +58,13 @@ private:
Vector<uint8_t> chunk;
int chunk_left = 0;
bool chunk_trailer_part = false;
- int body_size = -1;
- int body_left = 0;
+ int64_t body_size = -1;
+ int64_t body_left = 0;
bool read_until_eof = false;
Ref<StreamPeerTCP> tcp_connection;
Ref<StreamPeer> connection;
+ Ref<HTTPClientTCP> proxy_client; // Negotiate with proxy server
int response_num = 0;
Vector<String> response_headers;
@@ -87,6 +94,8 @@ public:
void set_read_chunk_size(int p_size) override;
int get_read_chunk_size() const override;
Error poll() override;
+ void set_http_proxy(const String &p_host, int p_port) override;
+ void set_https_proxy(const String &p_host, int p_port) override;
HTTPClientTCP();
};
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 3112dd217f..4a1f129245 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -86,20 +86,14 @@ SaveEXRFunc Image::save_exr_func = nullptr;
SavePNGBufferFunc Image::save_png_buffer_func = nullptr;
-void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel) {
- uint32_t ofs = (p_y * width + p_x) * p_pixelsize;
-
- for (uint32_t i = 0; i < p_pixelsize; i++) {
- p_data[ofs + i] = p_pixel[i];
- }
+void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixel_size, uint8_t *p_data, const uint8_t *p_pixel) {
+ uint32_t ofs = (p_y * width + p_x) * p_pixel_size;
+ memcpy(p_data + ofs, p_pixel, p_pixel_size);
}
-void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_data, uint8_t *p_pixel) {
- uint32_t ofs = (p_y * width + p_x) * p_pixelsize;
-
- for (uint32_t i = 0; i < p_pixelsize; i++) {
- p_pixel[i] = p_data[ofs + i];
- }
+void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixel_size, const uint8_t *p_data, uint8_t *p_pixel) {
+ uint32_t ofs = (p_y * width + p_x) * p_pixel_size;
+ memcpy(p_pixel, p_data + ofs, p_pixel_size);
}
int Image::get_format_pixel_size(Format p_format) {
@@ -797,7 +791,7 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
uint32_t interp_down = p01 + (((p11 - p01) * src_xofs_frac) >> FRAC_BITS);
uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
interp >>= FRAC_BITS;
- p_dst[i * p_dst_width * CC + j * CC + l] = interp;
+ p_dst[i * p_dst_width * CC + j * CC + l] = uint8_t(interp);
} else if (sizeof(T) == 2) { //half float
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
@@ -2506,7 +2500,7 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
clipped_src_rect.position.y = ABS(p_dest.y);
}
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
+ if (clipped_src_rect.has_no_area()) {
return;
}
@@ -2561,7 +2555,7 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
clipped_src_rect.position.y = ABS(p_dest.y);
}
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
+ if (clipped_src_rect.has_no_area()) {
return;
}
@@ -2615,7 +2609,7 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
clipped_src_rect.position.y = ABS(p_dest.y);
}
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
+ if (clipped_src_rect.has_no_area()) {
return;
}
@@ -2664,7 +2658,7 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
clipped_src_rect.position.y = ABS(p_dest.y);
}
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
+ if (clipped_src_rect.has_no_area()) {
return;
}
@@ -2697,24 +2691,55 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
}
}
-void Image::fill(const Color &c) {
+// Repeats `p_pixel` `p_count` times in consecutive memory.
+// Results in the original pixel and `p_count - 1` subsequent copies of it.
+void Image::_repeat_pixel_over_subsequent_memory(uint8_t *p_pixel, int p_pixel_size, int p_count) {
+ int offset = 1;
+ for (int stride = 1; offset + stride <= p_count; stride *= 2) {
+ memcpy(p_pixel + offset * p_pixel_size, p_pixel, stride * p_pixel_size);
+ offset += stride;
+ }
+ if (offset < p_count) {
+ memcpy(p_pixel + offset * p_pixel_size, p_pixel, (p_count - offset) * p_pixel_size);
+ }
+}
+
+void Image::fill(const Color &p_color) {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill in compressed or custom image formats.");
- uint8_t *wp = data.ptrw();
- uint8_t *dst_data_ptr = wp;
+ uint8_t *dst_data_ptr = data.ptrw();
int pixel_size = get_format_pixel_size(format);
- // put first pixel with the format-aware API
- set_pixel(0, 0, c);
+ // Put first pixel with the format-aware API.
+ _set_color_at_ofs(dst_data_ptr, 0, p_color);
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- uint8_t *dst = &dst_data_ptr[(y * width + x) * pixel_size];
+ _repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, width * height);
+}
- for (int k = 0; k < pixel_size; k++) {
- dst[k] = dst_data_ptr[k];
- }
+void Image::fill_rect(const Rect2 &p_rect, const Color &p_color) {
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill rect in compressed or custom image formats.");
+
+ Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect.abs());
+ if (r.has_no_area()) {
+ return;
+ }
+
+ uint8_t *dst_data_ptr = data.ptrw();
+
+ int pixel_size = get_format_pixel_size(format);
+
+ // Put first pixel with the format-aware API.
+ uint8_t *rect_first_pixel_ptr = &dst_data_ptr[(r.position.y * width + r.position.x) * pixel_size];
+ _set_color_at_ofs(rect_first_pixel_ptr, 0, p_color);
+
+ if (r.size.x == width) {
+ // No need to fill rows separately.
+ _repeat_pixel_over_subsequent_memory(rect_first_pixel_ptr, pixel_size, width * r.size.y);
+ } else {
+ _repeat_pixel_over_subsequent_memory(rect_first_pixel_ptr, pixel_size, r.size.x);
+ for (int y = 1; y < r.size.y; y++) {
+ memcpy(rect_first_pixel_ptr + y * width * pixel_size, rect_first_pixel_ptr, r.size.x * pixel_size);
}
}
}
@@ -3160,6 +3185,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("blend_rect", "src", "src_rect", "dst"), &Image::blend_rect);
ClassDB::bind_method(D_METHOD("blend_rect_mask", "src", "mask", "src_rect", "dst"), &Image::blend_rect_mask);
ClassDB::bind_method(D_METHOD("fill", "color"), &Image::fill);
+ ClassDB::bind_method(D_METHOD("fill_rect", "rect", "color"), &Image::fill_rect);
ClassDB::bind_method(D_METHOD("get_used_rect"), &Image::get_used_rect);
ClassDB::bind_method(D_METHOD("get_rect", "rect"), &Image::get_rect);
diff --git a/core/io/image.h b/core/io/image.h
index 8f1b251ac3..29236a55e5 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,12 +36,10 @@
#include "core/math/rect2.h"
/**
- * @author Juan Linietsky <reduzio@gmail.com>
- *
* Image storage class. This is used to store an image in user memory, as well as
* providing some basic methods for image manipulation.
* Images can be loaded from a file, or registered into the Render object as textures.
-*/
+ */
class Image;
@@ -190,8 +188,10 @@ private:
static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1, int *r_mm_width = nullptr, int *r_mm_height = nullptr);
bool _can_modify(Format p_format) const;
- _FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel);
- _FORCE_INLINE_ void _get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_data, uint8_t *p_pixel);
+ _FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixel_size, uint8_t *p_data, const uint8_t *p_pixel);
+ _FORCE_INLINE_ void _get_pixelb(int p_x, int p_y, uint32_t p_pixel_size, const uint8_t *p_data, uint8_t *p_pixel);
+
+ _FORCE_INLINE_ void _repeat_pixel_over_subsequent_memory(uint8_t *p_pixel, int p_pixel_size, int p_count);
void _set_data(const Dictionary &p_data);
Dictionary _get_data() const;
@@ -362,7 +362,8 @@ public:
void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest);
void blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest);
void blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest);
- void fill(const Color &c);
+ void fill(const Color &p_color);
+ void fill_rect(const Rect2 &p_rect, const Color &p_color);
Rect2 get_used_rect() const;
Ref<Image> get_rect(const Rect2 &p_area) const;
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index b9fc416f65..5518ec8ceb 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index 6d1b1e3646..37d7620f96 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index e3102508a3..4970afc1d3 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -288,8 +288,8 @@ Array IP::_get_local_interfaces() const {
Array results;
Map<String, Interface_Info> interfaces;
get_local_interfaces(&interfaces);
- for (Map<String, Interface_Info>::Element *E = interfaces.front(); E; E = E->next()) {
- Interface_Info &c = E->get();
+ for (KeyValue<String, Interface_Info> &E : interfaces) {
+ Interface_Info &c = E.value;
Dictionary rc;
rc["name"] = c.name;
rc["friendly"] = c.name_friendly;
@@ -310,8 +310,8 @@ Array IP::_get_local_interfaces() const {
void IP::get_local_addresses(List<IPAddress> *r_addresses) const {
Map<String, Interface_Info> interfaces;
get_local_interfaces(&interfaces);
- for (Map<String, Interface_Info>::Element *E = interfaces.front(); E; E = E->next()) {
- for (const IPAddress &F : E->get().ip_addresses) {
+ for (const KeyValue<String, Interface_Info> &E : interfaces) {
+ for (const IPAddress &F : E.value.ip_addresses) {
r_addresses->push_front(F);
}
}
diff --git a/core/io/ip.h b/core/io/ip.h
index 3c6040a1f0..5602710550 100644
--- a/core/io/ip.h
+++ b/core/io/ip.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index 1c1ac8a88f..38f99a08a4 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/ip_address.h b/core/io/ip_address.h
index 05da675704..dc0c19bf48 100644
--- a/core/io/ip_address.h
+++ b/core/io/ip_address.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/json.cpp b/core/io/json.cpp
index 5823afbdcd..7b642f6a59 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/json.h b/core/io/json.h
index f20c97f540..ed251938ec 100644
--- a/core/io/json.h
+++ b/core/io/json.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index 09539f716c..cb6369ae3d 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -50,7 +50,7 @@ void Logger::set_flush_stdout_on_print(bool value) {
_flush_stdout_on_print = value;
}
-void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) {
if (!should_log(true)) {
return;
}
@@ -81,7 +81,11 @@ void Logger::log_error(const char *p_function, const char *p_file, int p_line, c
err_details = p_code;
}
- logf_error("%s: %s\n", err_type, err_details);
+ if (p_editor_notify) {
+ logf_error("%s: %s\n", err_type, err_details);
+ } else {
+ logf_error("USER %s: %s\n", err_type, err_details);
+ }
logf_error(" at: %s (%s:%i) - %s\n", p_function, p_file, p_line, p_code);
}
@@ -132,7 +136,7 @@ void RotatedFileLogger::clear_old_backups() {
da->list_dir_begin();
String f = da->get_next();
Set<String> backups;
- while (f != String()) {
+ while (!f.is_empty()) {
if (!da->current_is_dir() && f.begins_with(basename) && f.get_extension() == extension && f != base_path.get_file()) {
backups.insert(f);
}
@@ -159,7 +163,7 @@ void RotatedFileLogger::rotate_file() {
if (max_files > 1) {
String timestamp = Time::get_singleton()->get_datetime_string_from_system().replace(":", ".");
String backup_name = base_path.get_basename() + timestamp;
- if (base_path.get_extension() != String()) {
+ if (!base_path.get_extension().is_empty()) {
backup_name += "." + base_path.get_extension();
}
@@ -256,13 +260,13 @@ void CompositeLogger::logv(const char *p_format, va_list p_list, bool p_err) {
}
}
-void CompositeLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+void CompositeLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) {
if (!should_log(true)) {
return;
}
for (int i = 0; i < loggers.size(); ++i) {
- loggers[i]->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
+ loggers[i]->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type);
}
}
diff --git a/core/io/logger.h b/core/io/logger.h
index ccf68562d6..047ee3d0f1 100644
--- a/core/io/logger.h
+++ b/core/io/logger.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -54,7 +54,7 @@ public:
static void set_flush_stdout_on_print(bool value);
virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0 = 0;
- virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR);
void logf(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
void logf_error(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
@@ -83,7 +83,6 @@ class RotatedFileLogger : public Logger {
FileAccess *file = nullptr;
- void rotate_file_without_closing();
void close_file();
void clear_old_backups();
void rotate_file();
@@ -103,7 +102,7 @@ public:
CompositeLogger(Vector<Logger *> p_loggers);
virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0;
- virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type = ERR_ERROR);
void add_logger(Logger *p_logger);
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index e7d5b78d14..6a0668f027 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -562,7 +562,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
return err;
}
- if (str == String()) {
+ if (str.is_empty()) {
r_variant = (Object *)nullptr;
} else {
Object *obj = ClassDB::instantiate(str);
diff --git a/core/io/marshalls.h b/core/io/marshalls.h
index 05804d5a46..4d7b98b749 100644
--- a/core/io/marshalls.h
+++ b/core/io/marshalls.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -44,9 +44,9 @@ typedef uint32_t uintr_t;
#endif
/**
- * Miscellaneous helpers for marshalling data types, and encoding
- * in an endian independent way
- */
+ * Miscellaneous helpers for marshalling data types, and encoding
+ * in an endian independent way
+ */
union MarshallFloat {
uint32_t i; ///< int
diff --git a/core/io/net_socket.cpp b/core/io/net_socket.cpp
index b51d26ba83..3e5246a134 100644
--- a/core/io/net_socket.cpp
+++ b/core/io/net_socket.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/net_socket.h b/core/io/net_socket.h
index fd7d50c704..23eff17a61 100644
--- a/core/io/net_socket.h
+++ b/core/io/net_socket.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/packed_data_container.cpp b/core/io/packed_data_container.cpp
index 4a76f0191d..14183b472b 100644
--- a/core/io/packed_data_container.cpp
+++ b/core/io/packed_data_container.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -100,6 +100,7 @@ Variant PackedDataContainer::_iter_get_ofs(const Variant &p_iter, uint32_t p_off
}
Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, bool &err) const {
+ ERR_FAIL_COND_V(p_ofs + 4 > (uint32_t)data.size(), Variant());
uint32_t type = decode_uint32(p_buf + p_ofs);
if (type == TYPE_ARRAY || type == TYPE_DICT) {
@@ -122,6 +123,7 @@ Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, b
}
uint32_t PackedDataContainer::_type_at_ofs(uint32_t p_ofs) const {
+ ERR_FAIL_COND_V(p_ofs + 4 > (uint32_t)data.size(), 0);
const uint8_t *rd = data.ptr();
ERR_FAIL_COND_V(!rd, 0);
const uint8_t *r = &rd[p_ofs];
@@ -131,6 +133,7 @@ uint32_t PackedDataContainer::_type_at_ofs(uint32_t p_ofs) const {
}
int PackedDataContainer::_size(uint32_t p_ofs) const {
+ ERR_FAIL_COND_V(p_ofs + 4 > (uint32_t)data.size(), 0);
const uint8_t *rd = data.ptr();
ERR_FAIL_COND_V(!rd, 0);
const uint8_t *r = &rd[p_ofs];
@@ -149,6 +152,7 @@ int PackedDataContainer::_size(uint32_t p_ofs) const {
}
Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, bool &err) const {
+ ERR_FAIL_COND_V(p_ofs + 4 > (uint32_t)data.size(), Variant());
const uint8_t *rd = data.ptr();
if (!rd) {
err = true;
diff --git a/core/io/packed_data_container.h b/core/io/packed_data_container.h
index 40772bb2bf..f042b364ee 100644
--- a/core/io/packed_data_container.h
+++ b/core/io/packed_data_container.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index 8da44fd290..e90d1695e5 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -138,6 +138,7 @@ Error PacketPeer::_get_packet_error() const {
void PacketPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &PacketPeer::_bnd_get_var, DEFVAL(false));
ClassDB::bind_method(D_METHOD("put_var", "var", "full_objects"), &PacketPeer::put_var, DEFVAL(false));
+
ClassDB::bind_method(D_METHOD("get_packet"), &PacketPeer::_get_packet);
ClassDB::bind_method(D_METHOD("put_packet", "buffer"), &PacketPeer::_put_packet);
ClassDB::bind_method(D_METHOD("get_packet_error"), &PacketPeer::_get_packet_error);
@@ -151,6 +152,51 @@ void PacketPeer::_bind_methods() {
/***************/
+int PacketPeerExtension::get_available_packet_count() const {
+ int count;
+ if (GDVIRTUAL_CALL(_get_available_packet_count, count)) {
+ return count;
+ }
+ WARN_PRINT_ONCE("PacketPeerExtension::_get_available_packet_count is unimplemented!");
+ return -1;
+}
+
+Error PacketPeerExtension::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
+ int err;
+ if (GDVIRTUAL_CALL(_get_packet, r_buffer, &r_buffer_size, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("PacketPeerExtension::_get_packet_native is unimplemented!");
+ return FAILED;
+}
+
+Error PacketPeerExtension::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
+ int err;
+ if (GDVIRTUAL_CALL(_put_packet, p_buffer, p_buffer_size, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("PacketPeerExtension::_put_packet_native is unimplemented!");
+ return FAILED;
+}
+
+int PacketPeerExtension::get_max_packet_size() const {
+ int size;
+ if (GDVIRTUAL_CALL(_get_max_packet_size, size)) {
+ return size;
+ }
+ WARN_PRINT_ONCE("PacketPeerExtension::_get_max_packet_size is unimplemented!");
+ return 0;
+}
+
+void PacketPeerExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_packet, "r_buffer", "r_buffer_size");
+ GDVIRTUAL_BIND(_put_packet, "p_buffer", "p_buffer_size");
+ GDVIRTUAL_BIND(_get_available_packet_count);
+ GDVIRTUAL_BIND(_get_max_packet_size);
+}
+
+/***************/
+
void PacketPeerStream::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_stream_peer", "peer"), &PacketPeerStream::set_stream_peer);
ClassDB::bind_method(D_METHOD("get_stream_peer"), &PacketPeerStream::get_stream_peer);
diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h
index 9a345af3d0..0b12640627 100644
--- a/core/io/packet_peer.h
+++ b/core/io/packet_peer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,6 +35,10 @@
#include "core/object/class_db.h"
#include "core/templates/ring_buffer.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
+
class PacketPeer : public RefCounted {
GDCLASS(PacketPeer, RefCounted);
@@ -73,6 +77,25 @@ public:
~PacketPeer() {}
};
+class PacketPeerExtension : public PacketPeer {
+ GDCLASS(PacketPeerExtension, PacketPeer);
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual int get_available_packet_count() const override;
+ virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; ///< buffer is GONE after next get_packet
+ virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override;
+ virtual int get_max_packet_size() const override;
+
+ /* GDExtension */
+ GDVIRTUAL0RC(int, _get_available_packet_count);
+ GDVIRTUAL2R(int, _get_packet, GDNativeConstPtr<const uint8_t *>, GDNativePtr<int>);
+ GDVIRTUAL2R(int, _put_packet, GDNativeConstPtr<const uint8_t>, int);
+ GDVIRTUAL0RC(int, _get_max_packet_size);
+};
+
class PacketPeerStream : public PacketPeer {
GDCLASS(PacketPeerStream, PacketPeer);
diff --git a/core/io/packet_peer_dtls.cpp b/core/io/packet_peer_dtls.cpp
index a6d220622b..3c7ab28e12 100644
--- a/core/io/packet_peer_dtls.cpp
+++ b/core/io/packet_peer_dtls.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/packet_peer_dtls.h b/core/io/packet_peer_dtls.h
index 31c52f539f..c5443d043e 100644
--- a/core/io/packet_peer_dtls.h
+++ b/core/io/packet_peer_dtls.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp
index f951a5158c..503eb17cae 100644
--- a/core/io/packet_peer_udp.cpp
+++ b/core/io/packet_peer_udp.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h
index 40d3c44e40..444a6dd5ba 100644
--- a/core/io/packet_peer_udp.h
+++ b/core/io/packet_peer_udp.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index 806a95398f..221a680130 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -47,13 +47,14 @@ static int _get_pad(int p_alignment, int p_n) {
}
void PCKPacker::_bind_methods() {
- ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(0), DEFVAL(String()), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path", "encrypt"), &PCKPacker::add_file, DEFVAL(false));
ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false));
}
Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &p_key, bool p_encrypt_directory) {
ERR_FAIL_COND_V_MSG((p_key.is_empty() || !p_key.is_valid_hex_number(false) || p_key.length() != 64), ERR_CANT_CREATE, "Invalid Encryption Key (must be 64 characters long).");
+ ERR_FAIL_COND_V_MSG(p_alignment <= 0, ERR_CANT_CREATE, "Invalid alignment, must be greater then 0.");
String _key = p_key.to_lower();
key.resize(32);
diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h
index 3d2ce8f240..583171a70b 100644
--- a/core/io/pck_packer.h
+++ b/core/io/pck_packer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -58,7 +58,7 @@ class PCKPacker : public RefCounted {
Vector<File> files;
public:
- Error pck_start(const String &p_file, int p_alignment = 0, const String &p_key = String(), bool p_encrypt_directory = false);
+ Error pck_start(const String &p_file, int p_alignment = 32, const String &p_key = "0000000000000000000000000000000000000000000000000000000000000000", bool p_encrypt_directory = false);
Error add_file(const String &p_file, const String &p_src, bool p_encrypt = false);
Error flush(bool p_verbose = false);
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 87b4d7195d..66d5c54b53 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -52,7 +52,7 @@ void Resource::set_path(const String &p_path, bool p_take_over) {
return;
}
- if (path_cache != "") {
+ if (!path_cache.is_empty()) {
ResourceCache::lock.write_lock();
ResourceCache::resources.erase(path_cache);
ResourceCache::lock.write_unlock();
@@ -82,7 +82,7 @@ void Resource::set_path(const String &p_path, bool p_take_over) {
}
path_cache = p_path;
- if (path_cache != "") {
+ if (!path_cache.is_empty()) {
ResourceCache::lock.write_lock();
ResourceCache::resources[path_cache] = this;
ResourceCache::lock.write_unlock();
@@ -136,6 +136,7 @@ String Resource::get_scene_unique_id() const {
void Resource::set_name(const String &p_name) {
name = p_name;
+ emit_changed();
}
String Resource::get_name() const {
@@ -382,7 +383,7 @@ bool Resource::is_translation_remapped() const {
#ifdef TOOLS_ENABLED
//helps keep IDs same number when loading/saving scenes. -1 clears ID and it Returns -1 when no id stored
void Resource::set_id_for_path(const String &p_path, const String &p_id) {
- if (p_id == "") {
+ if (p_id.is_empty()) {
ResourceCache::path_cache_lock.write_lock();
ResourceCache::resource_path_cache[p_path].erase(get_path());
ResourceCache::path_cache_lock.write_unlock();
@@ -433,7 +434,7 @@ Resource::Resource() :
remapped_list(this) {}
Resource::~Resource() {
- if (path_cache != "") {
+ if (!path_cache.is_empty()) {
ResourceCache::lock.write_lock();
ResourceCache::resources.erase(path_cache);
ResourceCache::lock.write_unlock();
@@ -519,8 +520,8 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
FileAccess *f = nullptr;
if (p_file) {
- f = FileAccess::open(p_file, FileAccess::WRITE);
- ERR_FAIL_COND_MSG(!f, "Cannot create file at path '" + String(p_file) + "'.");
+ f = FileAccess::open(String::utf8(p_file), FileAccess::WRITE);
+ ERR_FAIL_COND_MSG(!f, "Cannot create file at path '" + String::utf8(p_file) + "'.");
}
const String *K = nullptr;
@@ -540,9 +541,9 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
}
}
- for (Map<String, int>::Element *E = type_count.front(); E; E = E->next()) {
+ for (const KeyValue<String, int> &E : type_count) {
if (f) {
- f->store_line(E->key() + " count: " + itos(E->get()));
+ f->store_line(E.key + " count: " + itos(E.value));
}
}
if (f) {
diff --git a/core/io/resource.h b/core/io/resource.h
index 9ccc247887..a0800c57cb 100644
--- a/core/io/resource.h
+++ b/core/io/resource.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -103,6 +103,7 @@ public:
virtual void set_path(const String &p_path, bool p_take_over = false);
String get_path() const;
+ _FORCE_INLINE_ bool is_built_in() const { return path_cache.is_empty() || path_cache.find("::") != -1 || path_cache.begins_with("local://"); }
static String generate_scene_unique_id();
void set_scene_unique_id(const String &p_id);
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 84fd6496a7..200d5fafde 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -53,9 +53,9 @@ enum {
VARIANT_PLANE = 13,
VARIANT_QUATERNION = 14,
VARIANT_AABB = 15,
- VARIANT_MATRIX3 = 16,
- VARIANT_TRANSFORM = 17,
- VARIANT_MATRIX32 = 18,
+ VARIANT_BASIS = 16,
+ VARIANT_TRANSFORM3D = 17,
+ VARIANT_TRANSFORM2D = 18,
VARIANT_COLOR = 20,
VARIANT_NODE_PATH = 22,
VARIANT_RID = 23,
@@ -63,13 +63,13 @@ enum {
VARIANT_INPUT_EVENT = 25,
VARIANT_DICTIONARY = 26,
VARIANT_ARRAY = 30,
- VARIANT_RAW_ARRAY = 31,
- VARIANT_INT32_ARRAY = 32,
- VARIANT_FLOAT32_ARRAY = 33,
- VARIANT_STRING_ARRAY = 34,
- VARIANT_VECTOR3_ARRAY = 35,
- VARIANT_COLOR_ARRAY = 36,
- VARIANT_VECTOR2_ARRAY = 37,
+ VARIANT_PACKED_BYTE_ARRAY = 31,
+ VARIANT_PACKED_INT32_ARRAY = 32,
+ VARIANT_PACKED_FLOAT32_ARRAY = 33,
+ VARIANT_PACKED_STRING_ARRAY = 34,
+ VARIANT_PACKED_VECTOR3_ARRAY = 35,
+ VARIANT_PACKED_COLOR_ARRAY = 36,
+ VARIANT_PACKED_VECTOR2_ARRAY = 37,
VARIANT_INT64 = 40,
VARIANT_DOUBLE = 41,
VARIANT_CALLABLE = 42,
@@ -78,8 +78,8 @@ enum {
VARIANT_VECTOR2I = 45,
VARIANT_RECT2I = 46,
VARIANT_VECTOR3I = 47,
- VARIANT_INT64_ARRAY = 48,
- VARIANT_FLOAT64_ARRAY = 49,
+ VARIANT_PACKED_INT64_ARRAY = 48,
+ VARIANT_PACKED_FLOAT64_ARRAY = 49,
OBJECT_EMPTY = 0,
OBJECT_EXTERNAL_RESOURCE = 1,
OBJECT_INTERNAL_RESOURCE = 2,
@@ -220,7 +220,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = v;
} break;
- case VARIANT_MATRIX32: {
+ case VARIANT_TRANSFORM2D: {
Transform2D v;
v.elements[0].x = f->get_real();
v.elements[0].y = f->get_real();
@@ -231,7 +231,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = v;
} break;
- case VARIANT_MATRIX3: {
+ case VARIANT_BASIS: {
Basis v;
v.elements[0].x = f->get_real();
v.elements[0].y = f->get_real();
@@ -245,7 +245,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = v;
} break;
- case VARIANT_TRANSFORM: {
+ case VARIANT_TRANSFORM3D: {
Transform3D v;
v.basis.elements[0].x = f->get_real();
v.basis.elements[0].y = f->get_real();
@@ -422,7 +422,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = a;
} break;
- case VARIANT_RAW_ARRAY: {
+ case VARIANT_PACKED_BYTE_ARRAY: {
uint32_t len = f->get_32();
Vector<uint8_t> array;
@@ -434,7 +434,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = array;
} break;
- case VARIANT_INT32_ARRAY: {
+ case VARIANT_PACKED_INT32_ARRAY: {
uint32_t len = f->get_32();
Vector<int32_t> array;
@@ -453,7 +453,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = array;
} break;
- case VARIANT_INT64_ARRAY: {
+ case VARIANT_PACKED_INT64_ARRAY: {
uint32_t len = f->get_32();
Vector<int64_t> array;
@@ -472,7 +472,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = array;
} break;
- case VARIANT_FLOAT32_ARRAY: {
+ case VARIANT_PACKED_FLOAT32_ARRAY: {
uint32_t len = f->get_32();
Vector<float> array;
@@ -491,7 +491,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = array;
} break;
- case VARIANT_FLOAT64_ARRAY: {
+ case VARIANT_PACKED_FLOAT64_ARRAY: {
uint32_t len = f->get_32();
Vector<double> array;
@@ -510,7 +510,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = array;
} break;
- case VARIANT_STRING_ARRAY: {
+ case VARIANT_PACKED_STRING_ARRAY: {
uint32_t len = f->get_32();
Vector<String> array;
array.resize(len);
@@ -522,7 +522,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = array;
} break;
- case VARIANT_VECTOR2_ARRAY: {
+ case VARIANT_PACKED_VECTOR2_ARRAY: {
uint32_t len = f->get_32();
Vector<Vector2> array;
@@ -547,7 +547,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = array;
} break;
- case VARIANT_VECTOR3_ARRAY: {
+ case VARIANT_PACKED_VECTOR3_ARRAY: {
uint32_t len = f->get_32();
Vector<Vector3> array;
@@ -572,7 +572,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = array;
} break;
- case VARIANT_COLOR_ARRAY: {
+ case VARIANT_PACKED_COLOR_ARRAY: {
uint32_t len = f->get_32();
Vector<Color> array;
@@ -727,7 +727,7 @@ Error ResourceLoaderBinary::load() {
}
res = RES(r);
- if (path != String() && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
+ if (!path.is_empty() && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
r->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE); //if got here because the resource with same path has different type, replace it
}
r->set_scene_unique_id(id);
@@ -829,7 +829,7 @@ void ResourceLoaderBinary::get_dependencies(FileAccess *p_f, List<String> *p_dep
dep = external_resources[i].path;
}
- if (p_add_types && external_resources[i].type != String()) {
+ if (p_add_types && !external_resources[i].type.is_empty()) {
dep += "::" + external_resources[i].type;
}
@@ -1026,7 +1026,7 @@ RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_origi
loader.cache_mode = p_cache_mode;
loader.use_sub_threads = p_use_sub_threads;
loader.progress = r_progress;
- String path = p_original_path != "" ? p_original_path : p_path;
+ String path = !p_original_path.is_empty() ? p_original_path : p_path;
loader.local_path = ProjectSettings::get_singleton()->localize_path(path);
loader.res_path = loader.local_path;
//loader.set_local_path( Globals::get_singleton()->localize_path(p_path) );
@@ -1045,7 +1045,7 @@ RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_origi
}
void ResourceFormatLoaderBinary::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const {
- if (p_type == "") {
+ if (p_type.is_empty()) {
get_recognized_extensions(p_extensions);
return;
}
@@ -1476,7 +1476,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::TRANSFORM2D: {
- f->store_32(VARIANT_MATRIX32);
+ f->store_32(VARIANT_TRANSFORM2D);
Transform2D val = p_property;
f->store_real(val.elements[0].x);
f->store_real(val.elements[0].y);
@@ -1487,7 +1487,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::BASIS: {
- f->store_32(VARIANT_MATRIX3);
+ f->store_32(VARIANT_BASIS);
Basis val = p_property;
f->store_real(val.elements[0].x);
f->store_real(val.elements[0].y);
@@ -1501,7 +1501,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::TRANSFORM3D: {
- f->store_32(VARIANT_TRANSFORM);
+ f->store_32(VARIANT_TRANSFORM3D);
Transform3D val = p_property;
f->store_real(val.basis.elements[0].x);
f->store_real(val.basis.elements[0].y);
@@ -1572,7 +1572,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
return; // don't save it
}
- if (res->get_path().length() && res->get_path().find("::") == -1) {
+ if (!res->is_built_in()) {
f->store_32(OBJECT_EXTERNAL_RESOURCE_INDEX);
f->store_32(external_resources[res]);
} else {
@@ -1625,7 +1625,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::PACKED_BYTE_ARRAY: {
- f->store_32(VARIANT_RAW_ARRAY);
+ f->store_32(VARIANT_PACKED_BYTE_ARRAY);
Vector<uint8_t> arr = p_property;
int len = arr.size();
f->store_32(len);
@@ -1635,7 +1635,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::PACKED_INT32_ARRAY: {
- f->store_32(VARIANT_INT32_ARRAY);
+ f->store_32(VARIANT_PACKED_INT32_ARRAY);
Vector<int32_t> arr = p_property;
int len = arr.size();
f->store_32(len);
@@ -1646,7 +1646,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::PACKED_INT64_ARRAY: {
- f->store_32(VARIANT_INT64_ARRAY);
+ f->store_32(VARIANT_PACKED_INT64_ARRAY);
Vector<int64_t> arr = p_property;
int len = arr.size();
f->store_32(len);
@@ -1657,7 +1657,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::PACKED_FLOAT32_ARRAY: {
- f->store_32(VARIANT_FLOAT32_ARRAY);
+ f->store_32(VARIANT_PACKED_FLOAT32_ARRAY);
Vector<float> arr = p_property;
int len = arr.size();
f->store_32(len);
@@ -1668,7 +1668,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::PACKED_FLOAT64_ARRAY: {
- f->store_32(VARIANT_FLOAT64_ARRAY);
+ f->store_32(VARIANT_PACKED_FLOAT64_ARRAY);
Vector<double> arr = p_property;
int len = arr.size();
f->store_32(len);
@@ -1679,7 +1679,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::PACKED_STRING_ARRAY: {
- f->store_32(VARIANT_STRING_ARRAY);
+ f->store_32(VARIANT_PACKED_STRING_ARRAY);
Vector<String> arr = p_property;
int len = arr.size();
f->store_32(len);
@@ -1690,7 +1690,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::PACKED_VECTOR3_ARRAY: {
- f->store_32(VARIANT_VECTOR3_ARRAY);
+ f->store_32(VARIANT_PACKED_VECTOR3_ARRAY);
Vector<Vector3> arr = p_property;
int len = arr.size();
f->store_32(len);
@@ -1703,7 +1703,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::PACKED_VECTOR2_ARRAY: {
- f->store_32(VARIANT_VECTOR2_ARRAY);
+ f->store_32(VARIANT_PACKED_VECTOR2_ARRAY);
Vector<Vector2> arr = p_property;
int len = arr.size();
f->store_32(len);
@@ -1715,7 +1715,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
} break;
case Variant::PACKED_COLOR_ARRAY: {
- f->store_32(VARIANT_COLOR_ARRAY);
+ f->store_32(VARIANT_PACKED_COLOR_ARRAY);
Vector<Color> arr = p_property;
int len = arr.size();
f->store_32(len);
@@ -1743,7 +1743,7 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
return;
}
- if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) {
+ if (!p_main && (!bundle_resources) && !res->is_built_in()) {
if (res->get_path() == path) {
ERR_PRINT("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded.");
return;
@@ -1960,8 +1960,8 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
Vector<RES> save_order;
save_order.resize(external_resources.size());
- for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
- save_order.write[E->get()] = E->key();
+ for (const KeyValue<RES, int> &E : external_resources) {
+ save_order.write[E.value] = E.key;
}
for (int i = 0; i < save_order.size(); i++) {
@@ -1978,8 +1978,8 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
Set<String> used_unique_ids;
for (RES &r : saved_resources) {
- if (r->get_path() == "" || r->get_path().find("::") != -1) {
- if (r->get_scene_unique_id() != "") {
+ if (r->is_built_in()) {
+ if (!r->get_scene_unique_id().is_empty()) {
if (used_unique_ids.has(r->get_scene_unique_id())) {
r->set_scene_unique_id("");
} else {
@@ -1992,8 +1992,8 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
Map<RES, int> resource_map;
int res_index = 0;
for (RES &r : saved_resources) {
- if (r->get_path() == "" || r->get_path().find("::") != -1) {
- if (r->get_scene_unique_id() == "") {
+ if (r->is_built_in()) {
+ if (r->get_scene_unique_id().is_empty()) {
String new_id;
while (true) {
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index a6e6d1848e..ecc3e95f6b 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp
index 1e166015b0..470fb2d42d 100644
--- a/core/io/resource_importer.cpp
+++ b/core/io/resource_importer.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -78,8 +78,8 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
return err;
}
- if (assign != String()) {
- if (!path_found && assign.begins_with("path.") && r_path_and_type.path == String()) {
+ if (!assign.is_empty()) {
+ if (!path_found && assign.begins_with("path.") && r_path_and_type.path.is_empty()) {
String feature = assign.get_slicec('.', 1);
if (OS::get_singleton()->has_feature(feature)) {
r_path_and_type.path = value;
@@ -112,7 +112,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
memdelete(f);
- if (r_path_and_type.path == String() || r_path_and_type.type == String()) {
+ if (r_path_and_type.path.is_empty() || r_path_and_type.type.is_empty()) {
return ERR_FILE_CORRUPT;
}
return OK;
@@ -158,7 +158,7 @@ void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extension
}
void ResourceFormatImporter::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const {
- if (p_type == "") {
+ if (p_type.is_empty()) {
get_recognized_extensions(p_extensions);
return;
}
@@ -167,7 +167,7 @@ void ResourceFormatImporter::get_recognized_extensions_for_type(const String &p_
for (int i = 0; i < importers.size(); i++) {
String res_type = importers[i]->get_resource_type();
- if (res_type == String()) {
+ if (res_type.is_empty()) {
continue;
}
@@ -246,7 +246,7 @@ int ResourceFormatImporter::get_import_order(const String &p_path) const {
bool ResourceFormatImporter::handles_type(const String &p_type) const {
for (int i = 0; i < importers.size(); i++) {
String res_type = importers[i]->get_resource_type();
- if (res_type == String()) {
+ if (res_type.is_empty()) {
continue;
}
if (ClassDB::is_parent_class(res_type, p_type)) {
@@ -300,7 +300,7 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat
return;
}
- if (assign != String()) {
+ if (!assign.is_empty()) {
if (assign.begins_with("path.")) {
r_paths->push_back(value);
} else if (assign == "path") {
@@ -418,7 +418,7 @@ Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const St
}
String ResourceFormatImporter::get_import_base_path(const String &p_for_file) const {
- return ProjectSettings::IMPORTED_FILES_PATH.plus_file(p_for_file.get_file() + "-" + p_for_file.md5_text());
+ return ProjectSettings::get_singleton()->get_imported_files_path().plus_file(p_for_file.get_file() + "-" + p_for_file.md5_text());
}
bool ResourceFormatImporter::are_import_settings_valid(const String &p_path) const {
diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h
index a1cacbd306..261afbab69 100644
--- a/core/io/resource_importer.h
+++ b/core/io/resource_importer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -134,8 +134,8 @@ public:
virtual int get_preset_count() const { return 0; }
virtual String get_preset_name(int p_idx) const { return String(); }
- virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const = 0;
- virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const = 0;
+ virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const = 0;
+ virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const = 0;
virtual String get_option_group_file() const { return String(); }
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) = 0;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 3026236f07..8fe1ac29b3 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -52,7 +52,7 @@ bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_
String extension = p_path.get_extension();
List<String> extensions;
- if (p_for_type == String()) {
+ if (p_for_type.is_empty()) {
get_recognized_extensions(&extensions);
} else {
get_recognized_extensions_for_type(p_for_type, &extensions);
@@ -96,7 +96,7 @@ ResourceUID::ID ResourceFormatLoader::get_resource_uid(const String &p_path) con
}
void ResourceFormatLoader::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const {
- if (p_type == "" || handles_type(p_type)) {
+ if (p_type.is_empty() || handles_type(p_type)) {
get_recognized_extensions(p_extensions);
}
}
@@ -156,8 +156,8 @@ void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *
Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
Dictionary deps_dict;
- for (Map<String, String>::Element *E = p_map.front(); E; E = E->next()) {
- deps_dict[E->key()] = E->value();
+ for (KeyValue<String, String> E : p_map) {
+ deps_dict[E.key] = E.value;
}
int64_t err;
@@ -194,7 +194,7 @@ RES ResourceLoader::_load(const String &p_path, const String &p_original_path, c
continue;
}
found = true;
- RES res = loader[i]->load(p_path, p_original_path != String() ? p_original_path : p_path, r_error, p_use_sub_threads, r_progress, p_cache_mode);
+ RES res = loader[i]->load(p_path, !p_original_path.is_empty() ? p_original_path : p_path, r_error, p_use_sub_threads, r_progress, p_cache_mode);
if (res.is_null()) {
continue;
}
@@ -289,7 +289,7 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String &
thread_load_mutex->lock();
- if (p_source_resource != String()) {
+ if (!p_source_resource.is_empty()) {
//must be loading from this resource
if (!thread_load_tasks.has(p_source_resource)) {
thread_load_mutex->unlock();
@@ -310,7 +310,7 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String &
if (thread_load_tasks.has(local_path)) {
thread_load_tasks[local_path].requests++;
- if (p_source_resource != String()) {
+ if (!p_source_resource.is_empty()) {
thread_load_tasks[p_source_resource].sub_tasks.insert(local_path);
}
thread_load_mutex->unlock();
@@ -354,7 +354,7 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String &
ResourceCache::lock.read_unlock();
}
- if (p_source_resource != String()) {
+ if (!p_source_resource.is_empty()) {
thread_load_tasks[p_source_resource].sub_tasks.insert(local_path);
}
@@ -574,7 +574,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, Resour
bool xl_remapped = false;
String path = _path_remap(local_path, &xl_remapped);
- if (path == "") {
+ if (path.is_empty()) {
ERR_FAIL_V_MSG(RES(), "Remapping '" + local_path + "' failed.");
}
@@ -776,7 +776,7 @@ String ResourceLoader::get_resource_type(const String &p_path) {
for (int i = 0; i < loader_count; i++) {
String result = loader[i]->get_resource_type(local_path);
- if (result != "") {
+ if (!result.is_empty()) {
return result;
}
}
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index f1d9815635..a3fdefa0f1 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index 823b5f75b1..c883e8502f 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index fcde835dab..2919a4cec0 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp
index 97d683f415..1a16d5b47a 100644
--- a/core/io/resource_uid.cpp
+++ b/core/io/resource_uid.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,8 @@
/*************************************************************************/
#include "resource_uid.h"
+
+#include "core/config/project_settings.h"
#include "core/crypto/crypto.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
@@ -36,7 +38,9 @@
static constexpr uint32_t char_count = ('z' - 'a');
static constexpr uint32_t base = char_count + ('9' - '0');
-const char *ResourceUID::CACHE_FILE = "res://.godot/uid_cache.bin";
+String ResourceUID::get_cache_file() {
+ return ProjectSettings::get_singleton()->get_project_data_path().plus_file("uid_cache.bin");
+}
String ResourceUID::id_to_text(ID p_id) const {
if (p_id < 0) {
@@ -126,8 +130,7 @@ String ResourceUID::get_id_path(ID p_id) const {
MutexLock l(mutex);
ERR_FAIL_COND_V(!unique_ids.has(p_id), String());
const CharString &cs = unique_ids[p_id].cs;
- String s(cs.ptr());
- return s;
+ return String::utf8(cs.ptr());
}
void ResourceUID::remove_id(ID p_id) {
MutexLock l(mutex);
@@ -136,12 +139,13 @@ void ResourceUID::remove_id(ID p_id) {
}
Error ResourceUID::save_to_cache() {
- if (!FileAccess::exists(CACHE_FILE)) {
+ String cache_file = get_cache_file();
+ if (!FileAccess::exists(cache_file)) {
DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- d->make_dir_recursive(String(CACHE_FILE).get_base_dir()); //ensure base dir exists
+ d->make_dir_recursive(String(cache_file).get_base_dir()); //ensure base dir exists
}
- FileAccessRef f = FileAccess::open(CACHE_FILE, FileAccess::WRITE);
+ FileAccessRef f = FileAccess::open(cache_file, FileAccess::WRITE);
if (!f) {
return ERR_CANT_OPEN;
}
@@ -165,7 +169,7 @@ Error ResourceUID::save_to_cache() {
}
Error ResourceUID::load_from_cache() {
- FileAccessRef f = FileAccess::open(CACHE_FILE, FileAccess::READ);
+ FileAccessRef f = FileAccess::open(get_cache_file(), FileAccess::READ);
if (!f) {
return ERR_CANT_OPEN;
}
@@ -207,7 +211,7 @@ Error ResourceUID::update_cache() {
for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
if (!E.get().saved_to_cache) {
if (f == nullptr) {
- f = FileAccess::open(CACHE_FILE, FileAccess::READ_WRITE); //append
+ f = FileAccess::open(get_cache_file(), FileAccess::READ_WRITE); //append
if (!f) {
return ERR_CANT_OPEN;
}
diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h
index b12138425a..9f2ab5245b 100644
--- a/core/io/resource_uid.h
+++ b/core/io/resource_uid.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -44,7 +44,7 @@ public:
INVALID_ID = -1
};
- static const char *CACHE_FILE;
+ static String get_cache_file();
private:
mutable Ref<Crypto> crypto;
diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp
index 27f8d4e88f..28ebe811c9 100644
--- a/core/io/stream_peer.cpp
+++ b/core/io/stream_peer.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -410,6 +410,63 @@ void StreamPeer::_bind_methods() {
////////////////////////////////
+int StreamPeerExtension::get_available_bytes() const {
+ int count;
+ if (GDVIRTUAL_CALL(_get_available_bytes, count)) {
+ return count;
+ }
+ WARN_PRINT_ONCE("StreamPeerExtension::_get_available_bytes is unimplemented!");
+ return -1;
+}
+
+Error StreamPeerExtension::get_data(uint8_t *r_buffer, int p_bytes) {
+ int err;
+ int received = 0;
+ if (GDVIRTUAL_CALL(_get_data, r_buffer, p_bytes, &received, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("StreamPeerExtension::_get_data is unimplemented!");
+ return FAILED;
+}
+
+Error StreamPeerExtension::get_partial_data(uint8_t *r_buffer, int p_bytes, int &r_received) {
+ int err;
+ if (GDVIRTUAL_CALL(_get_partial_data, r_buffer, p_bytes, &r_received, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("StreamPeerExtension::_get_partial_data is unimplemented!");
+ return FAILED;
+}
+
+Error StreamPeerExtension::put_data(const uint8_t *p_data, int p_bytes) {
+ int err;
+ int sent = 0;
+ if (GDVIRTUAL_CALL(_put_data, p_data, p_bytes, &sent, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("StreamPeerExtension::_put_data is unimplemented!");
+ return FAILED;
+}
+
+Error StreamPeerExtension::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
+ int err;
+ if (GDVIRTUAL_CALL(_put_data, p_data, p_bytes, &r_sent, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("StreamPeerExtension::_put_partial_data is unimplemented!");
+ return FAILED;
+}
+
+void StreamPeerExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_data, "r_buffer", "r_bytes", "r_received");
+ GDVIRTUAL_BIND(_get_partial_data, "r_buffer", "r_bytes", "r_received");
+ GDVIRTUAL_BIND(_put_data, "p_data", "p_bytes", "r_sent");
+ GDVIRTUAL_BIND(_put_partial_data, "p_data", "p_bytes", "r_sent");
+ GDVIRTUAL_BIND(_get_available_bytes);
+}
+
+////////////////////////////////
+
void StreamPeerBuffer::_bind_methods() {
ClassDB::bind_method(D_METHOD("seek", "position"), &StreamPeerBuffer::seek);
ClassDB::bind_method(D_METHOD("get_size"), &StreamPeerBuffer::get_size);
diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h
index effc3850af..e71941b7e1 100644
--- a/core/io/stream_peer.h
+++ b/core/io/stream_peer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,6 +33,10 @@
#include "core/object/ref_counted.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
+
class StreamPeer : public RefCounted {
GDCLASS(StreamPeer, RefCounted);
OBJ_CATEGORY("Networking");
@@ -58,6 +62,7 @@ public:
virtual int get_available_bytes() const = 0;
+ /* helpers */
void set_big_endian(bool p_big_endian);
bool is_big_endian_enabled() const;
@@ -92,6 +97,26 @@ public:
StreamPeer() {}
};
+class StreamPeerExtension : public StreamPeer {
+ GDCLASS(StreamPeerExtension, StreamPeer);
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual Error put_data(const uint8_t *p_data, int p_bytes) override;
+ virtual Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) override;
+ virtual Error get_data(uint8_t *p_buffer, int p_bytes) override;
+ virtual Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) override;
+ virtual int get_available_bytes() const override;
+
+ GDVIRTUAL3R(int, _put_data, GDNativeConstPtr<const uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL3R(int, _put_partial_data, GDNativeConstPtr<const uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL3R(int, _get_data, GDNativePtr<uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL3R(int, _get_partial_data, GDNativePtr<uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL0RC(int, _get_available_bytes);
+};
+
class StreamPeerBuffer : public StreamPeer {
GDCLASS(StreamPeerBuffer, StreamPeer);
diff --git a/core/io/stream_peer_ssl.cpp b/core/io/stream_peer_ssl.cpp
index 6f5a06474c..ea8435e587 100644
--- a/core/io/stream_peer_ssl.cpp
+++ b/core/io/stream_peer_ssl.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/stream_peer_ssl.h b/core/io/stream_peer_ssl.h
index 1df9ced08c..15f646d897 100644
--- a/core/io/stream_peer_ssl.h
+++ b/core/io/stream_peer_ssl.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp
index 5b794274ca..6d5784a8ab 100644
--- a/core/io/stream_peer_tcp.cpp
+++ b/core/io/stream_peer_tcp.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h
index a2a7f447d8..f2c47b25cf 100644
--- a/core/io/stream_peer_tcp.h
+++ b/core/io/stream_peer_tcp.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp
index 5e0c0390f9..f1e745cf36 100644
--- a/core/io/tcp_server.cpp
+++ b/core/io/tcp_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h
index 10985a04d5..2d427818a0 100644
--- a/core/io/tcp_server.h
+++ b/core/io/tcp_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index 83d575cee8..2f6742bd7a 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -87,7 +87,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
// In PO file, "msgctxt" appears before "msgid". If we encounter a "msgctxt", we add what we have read
// and set "entered_context" to true to prevent adding twice.
- if (!skip_this && msg_id != "") {
+ if (!skip_this && !msg_id.is_empty()) {
if (status == STATUS_READING_STRING) {
translation->add_message(msg_id, msg_str, msg_context);
} else if (status == STATUS_READING_PLURAL) {
@@ -125,7 +125,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
ERR_FAIL_V_MSG(RES(), "Unexpected 'msgid', was expecting 'msgstr' while parsing: " + path + ":" + itos(line));
}
- if (msg_id != "") {
+ if (!msg_id.is_empty()) {
if (!skip_this && !entered_context) {
if (status == STATUS_READING_STRING) {
translation->add_message(msg_id, msg_str, msg_context);
@@ -137,7 +137,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
translation->add_plural_message(msg_id, msgs_plural, msg_context);
}
}
- } else if (config == "") {
+ } else if (config.is_empty()) {
config = msg_str;
// Record plural rule.
int p_start = config.find("Plural-Forms");
@@ -178,7 +178,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
status = STATUS_READING_STRING;
}
- if (l == "" || l.begins_with("#")) {
+ if (l.is_empty() || l.begins_with("#")) {
if (l.find("fuzzy") != -1) {
skip_next = true;
}
@@ -236,15 +236,15 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
// Add the last set of data from last iteration.
if (status == STATUS_READING_STRING) {
- if (msg_id != "") {
+ if (!msg_id.is_empty()) {
if (!skip_this) {
translation->add_message(msg_id, msg_str, msg_context);
}
- } else if (config == "") {
+ } else if (config.is_empty()) {
config = msg_str;
}
} else if (status == STATUS_READING_PLURAL) {
- if (!skip_this && msg_id != "") {
+ if (!skip_this && !msg_id.is_empty()) {
if (plural_index != plural_forms - 1) {
memdelete(f);
ERR_FAIL_V_MSG(RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
@@ -253,7 +253,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
}
}
- ERR_FAIL_COND_V_MSG(config == "", RES(), "No config found in file: " + path + ".");
+ ERR_FAIL_COND_V_MSG(config.is_empty(), RES(), "No config found in file: " + path + ".");
Vector<String> configs = config.split("\n");
for (int i = 0; i < configs.size(); i++) {
diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h
index c52820e60d..1c58896a00 100644
--- a/core/io/translation_loader_po.h
+++ b/core/io/translation_loader_po.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/udp_server.cpp b/core/io/udp_server.cpp
index 27a1cab721..4934e3a7b6 100644
--- a/core/io/udp_server.cpp
+++ b/core/io/udp_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/udp_server.h b/core/io/udp_server.h
index e49a559c51..4a7546fddf 100644
--- a/core/io/udp_server.h
+++ b/core/io/udp_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 938d93a01b..360da46f96 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h
index 1113cce715..da14ee8eae 100644
--- a/core/io/xml_parser.h
+++ b/core/io/xml_parser.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp
index fb4c76aa7a..2c4f8346ab 100644
--- a/core/io/zip_io.cpp
+++ b/core/io/zip_io.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -100,7 +100,7 @@ int zipio_testerror(voidpf opaque, voidpf stream) {
}
voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) {
- voidpf ptr = memalloc(items * size);
+ voidpf ptr = memalloc((size_t)items * size);
memset(ptr, 0, items * size);
return ptr;
}
diff --git a/core/io/zip_io.h b/core/io/zip_io.h
index 776473bfa1..6a29703449 100644
--- a/core/io/zip_io.h
+++ b/core/io/zip_io.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index b380860522..ce2435216b 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -47,8 +47,8 @@ int AStar::get_available_point_id() const {
}
void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
- ERR_FAIL_COND(p_id < 0);
- ERR_FAIL_COND(p_weight_scale < 1);
+ ERR_FAIL_COND_MSG(p_id < 0, vformat("Can't add a point with negative id: %d.", p_id));
+ ERR_FAIL_COND_MSG(p_weight_scale < 1, vformat("Can't add a point with weight scale less than one: %f.", p_weight_scale));
Point *found_pt;
bool p_exists = points.lookup(p_id, found_pt);
@@ -72,7 +72,7 @@ void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
Vector3 AStar::get_point_position(int p_id) const {
Point *p;
bool p_exists = points.lookup(p_id, p);
- ERR_FAIL_COND_V(!p_exists, Vector3());
+ ERR_FAIL_COND_V_MSG(!p_exists, Vector3(), vformat("Can't get point's position. Point with id: %d doesn't exist.", p_id));
return p->pos;
}
@@ -80,7 +80,7 @@ Vector3 AStar::get_point_position(int p_id) const {
void AStar::set_point_position(int p_id, const Vector3 &p_pos) {
Point *p;
bool p_exists = points.lookup(p_id, p);
- ERR_FAIL_COND(!p_exists);
+ ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's position. Point with id: %d doesn't exist.", p_id));
p->pos = p_pos;
}
@@ -88,7 +88,7 @@ void AStar::set_point_position(int p_id, const Vector3 &p_pos) {
real_t AStar::get_point_weight_scale(int p_id) const {
Point *p;
bool p_exists = points.lookup(p_id, p);
- ERR_FAIL_COND_V(!p_exists, 0);
+ ERR_FAIL_COND_V_MSG(!p_exists, 0, vformat("Can't get point's weight scale. Point with id: %d doesn't exist.", p_id));
return p->weight_scale;
}
@@ -96,8 +96,8 @@ real_t AStar::get_point_weight_scale(int p_id) const {
void AStar::set_point_weight_scale(int p_id, real_t p_weight_scale) {
Point *p;
bool p_exists = points.lookup(p_id, p);
- ERR_FAIL_COND(!p_exists);
- ERR_FAIL_COND(p_weight_scale < 1);
+ ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's weight scale. Point with id: %d doesn't exist.", p_id));
+ ERR_FAIL_COND_MSG(p_weight_scale < 1, vformat("Can't set point's weight scale less than one: %f.", p_weight_scale));
p->weight_scale = p_weight_scale;
}
@@ -105,7 +105,7 @@ void AStar::set_point_weight_scale(int p_id, real_t p_weight_scale) {
void AStar::remove_point(int p_id) {
Point *p;
bool p_exists = points.lookup(p_id, p);
- ERR_FAIL_COND(!p_exists);
+ ERR_FAIL_COND_MSG(!p_exists, vformat("Can't remove point. Point with id: %d doesn't exist.", p_id));
for (OAHashMap<int, Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
Segment s(p_id, (*it.key));
@@ -129,15 +129,15 @@ void AStar::remove_point(int p_id) {
}
void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) {
- ERR_FAIL_COND(p_id == p_with_id);
+ ERR_FAIL_COND_MSG(p_id == p_with_id, vformat("Can't connect point with id: %d to itself.", p_id));
Point *a;
bool from_exists = points.lookup(p_id, a);
- ERR_FAIL_COND(!from_exists);
+ ERR_FAIL_COND_MSG(!from_exists, vformat("Can't connect points. Point with id: %d doesn't exist.", p_id));
Point *b;
bool to_exists = points.lookup(p_with_id, b);
- ERR_FAIL_COND(!to_exists);
+ ERR_FAIL_COND_MSG(!to_exists, vformat("Can't connect points. Point with id: %d doesn't exist.", p_with_id));
a->neighbours.set(b->id, b);
@@ -169,11 +169,11 @@ void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) {
void AStar::disconnect_points(int p_id, int p_with_id, bool bidirectional) {
Point *a;
bool a_exists = points.lookup(p_id, a);
- ERR_FAIL_COND(!a_exists);
+ ERR_FAIL_COND_MSG(!a_exists, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_id));
Point *b;
bool b_exists = points.lookup(p_with_id, b);
- ERR_FAIL_COND(!b_exists);
+ ERR_FAIL_COND_MSG(!b_exists, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_with_id));
Segment s(p_id, p_with_id);
int remove_direction = bidirectional ? (int)Segment::BIDIRECTIONAL : s.direction;
@@ -210,7 +210,7 @@ bool AStar::has_point(int p_id) const {
return points.has(p_id);
}
-Array AStar::get_points() {
+Array AStar::get_point_ids() {
Array point_list;
for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) {
@@ -223,7 +223,7 @@ Array AStar::get_points() {
Vector<int> AStar::get_point_connections(int p_id) {
Point *p;
bool p_exists = points.lookup(p_id, p);
- ERR_FAIL_COND_V(!p_exists, Vector<int>());
+ ERR_FAIL_COND_V_MSG(!p_exists, Vector<int>(), vformat("Can't get point's connections. Point with id: %d doesn't exist.", p_id));
Vector<int> point_list;
@@ -239,7 +239,7 @@ bool AStar::are_points_connected(int p_id, int p_with_id, bool bidirectional) co
const Set<Segment>::Element *element = segments.find(s);
return element != nullptr &&
- (bidirectional || (element->get().direction & s.direction) == s.direction);
+ (bidirectional || (element->get().direction & s.direction) == s.direction);
}
void AStar::clear() {
@@ -260,8 +260,8 @@ int AStar::get_point_capacity() const {
}
void AStar::reserve_space(int p_num_nodes) {
- ERR_FAIL_COND_MSG(p_num_nodes <= 0, "New capacity must be greater than 0, was: " + itos(p_num_nodes) + ".");
- ERR_FAIL_COND_MSG((uint32_t)p_num_nodes < points.get_capacity(), "New capacity must be greater than current capacity: " + itos(points.get_capacity()) + ", new was: " + itos(p_num_nodes) + ".");
+ ERR_FAIL_COND_MSG(p_num_nodes <= 0, vformat("New capacity must be greater than 0, new was: %d.", p_num_nodes));
+ ERR_FAIL_COND_MSG((uint32_t)p_num_nodes < points.get_capacity(), vformat("New capacity must be greater than current capacity: %d, new was: %d.", points.get_capacity(), p_num_nodes));
points.reserve(p_num_nodes);
}
@@ -344,7 +344,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
}
sorter.pop_heap(0, open_list.size(), open_list.ptrw()); // Remove the current point from the open list
- open_list.remove(open_list.size() - 1);
+ open_list.remove_at(open_list.size() - 1);
p->closed_pass = pass; // Mark the point as closed
for (OAHashMap<int, Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
@@ -389,11 +389,11 @@ real_t AStar::_estimate_cost(int p_from_id, int p_to_id) {
Point *from_point;
bool from_exists = points.lookup(p_from_id, from_point);
- ERR_FAIL_COND_V(!from_exists, 0);
+ ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id));
Point *to_point;
bool to_exists = points.lookup(p_to_id, to_point);
- ERR_FAIL_COND_V(!to_exists, 0);
+ ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_to_id));
return from_point->pos.distance_to(to_point->pos);
}
@@ -406,11 +406,11 @@ real_t AStar::_compute_cost(int p_from_id, int p_to_id) {
Point *from_point;
bool from_exists = points.lookup(p_from_id, from_point);
- ERR_FAIL_COND_V(!from_exists, 0);
+ ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id));
Point *to_point;
bool to_exists = points.lookup(p_to_id, to_point);
- ERR_FAIL_COND_V(!to_exists, 0);
+ ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id));
return from_point->pos.distance_to(to_point->pos);
}
@@ -418,11 +418,11 @@ real_t AStar::_compute_cost(int p_from_id, int p_to_id) {
Vector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
Point *a;
bool from_exists = points.lookup(p_from_id, a);
- ERR_FAIL_COND_V(!from_exists, Vector<Vector3>());
+ ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
Point *b;
bool to_exists = points.lookup(p_to_id, b);
- ERR_FAIL_COND_V(!to_exists, Vector<Vector3>());
+ ERR_FAIL_COND_V_MSG(!to_exists, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
if (a == b) {
Vector<Vector3> ret;
@@ -467,11 +467,11 @@ Vector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
Vector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
Point *a;
bool from_exists = points.lookup(p_from_id, a);
- ERR_FAIL_COND_V(!from_exists, Vector<int>());
+ ERR_FAIL_COND_V_MSG(!from_exists, Vector<int>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
Point *b;
bool to_exists = points.lookup(p_to_id, b);
- ERR_FAIL_COND_V(!to_exists, Vector<int>());
+ ERR_FAIL_COND_V_MSG(!to_exists, Vector<int>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
if (a == b) {
Vector<int> ret;
@@ -516,7 +516,7 @@ Vector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
void AStar::set_point_disabled(int p_id, bool p_disabled) {
Point *p;
bool p_exists = points.lookup(p_id, p);
- ERR_FAIL_COND(!p_exists);
+ ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set if point is disabled. Point with id: %d doesn't exist.", p_id));
p->enabled = !p_disabled;
}
@@ -524,7 +524,7 @@ void AStar::set_point_disabled(int p_id, bool p_disabled) {
bool AStar::is_point_disabled(int p_id) const {
Point *p;
bool p_exists = points.lookup(p_id, p);
- ERR_FAIL_COND_V(!p_exists, false);
+ ERR_FAIL_COND_V_MSG(!p_exists, false, vformat("Can't get if point is disabled. Point with id: %d doesn't exist.", p_id));
return !p->enabled;
}
@@ -539,7 +539,7 @@ void AStar::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_point", "id"), &AStar::remove_point);
ClassDB::bind_method(D_METHOD("has_point", "id"), &AStar::has_point);
ClassDB::bind_method(D_METHOD("get_point_connections", "id"), &AStar::get_point_connections);
- ClassDB::bind_method(D_METHOD("get_points"), &AStar::get_points);
+ ClassDB::bind_method(D_METHOD("get_point_ids"), &AStar::get_point_ids);
ClassDB::bind_method(D_METHOD("set_point_disabled", "id", "disabled"), &AStar::set_point_disabled, DEFVAL(true));
ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar::is_point_disabled);
@@ -606,8 +606,8 @@ Vector<int> AStar2D::get_point_connections(int p_id) {
return astar.get_point_connections(p_id);
}
-Array AStar2D::get_points() {
- return astar.get_points();
+Array AStar2D::get_point_ids() {
+ return astar.get_point_ids();
}
void AStar2D::set_point_disabled(int p_id, bool p_disabled) {
@@ -663,11 +663,11 @@ real_t AStar2D::_estimate_cost(int p_from_id, int p_to_id) {
AStar::Point *from_point;
bool from_exists = astar.points.lookup(p_from_id, from_point);
- ERR_FAIL_COND_V(!from_exists, 0);
+ ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id));
AStar::Point *to_point;
bool to_exists = astar.points.lookup(p_to_id, to_point);
- ERR_FAIL_COND_V(!to_exists, 0);
+ ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_to_id));
return from_point->pos.distance_to(to_point->pos);
}
@@ -680,11 +680,11 @@ real_t AStar2D::_compute_cost(int p_from_id, int p_to_id) {
AStar::Point *from_point;
bool from_exists = astar.points.lookup(p_from_id, from_point);
- ERR_FAIL_COND_V(!from_exists, 0);
+ ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id));
AStar::Point *to_point;
bool to_exists = astar.points.lookup(p_to_id, to_point);
- ERR_FAIL_COND_V(!to_exists, 0);
+ ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id));
return from_point->pos.distance_to(to_point->pos);
}
@@ -692,15 +692,14 @@ real_t AStar2D::_compute_cost(int p_from_id, int p_to_id) {
Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) {
AStar::Point *a;
bool from_exists = astar.points.lookup(p_from_id, a);
- ERR_FAIL_COND_V(!from_exists, Vector<Vector2>());
+ ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
AStar::Point *b;
bool to_exists = astar.points.lookup(p_to_id, b);
- ERR_FAIL_COND_V(!to_exists, Vector<Vector2>());
+ ERR_FAIL_COND_V_MSG(!to_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
if (a == b) {
- Vector<Vector2> ret;
- ret.push_back(Vector2(a->pos.x, a->pos.y));
+ Vector<Vector2> ret = { Vector2(a->pos.x, a->pos.y) };
return ret;
}
@@ -741,11 +740,11 @@ Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) {
Vector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) {
AStar::Point *a;
bool from_exists = astar.points.lookup(p_from_id, a);
- ERR_FAIL_COND_V(!from_exists, Vector<int>());
+ ERR_FAIL_COND_V_MSG(!from_exists, Vector<int>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
AStar::Point *b;
bool to_exists = astar.points.lookup(p_to_id, b);
- ERR_FAIL_COND_V(!to_exists, Vector<int>());
+ ERR_FAIL_COND_V_MSG(!to_exists, Vector<int>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
if (a == b) {
Vector<int> ret;
@@ -812,7 +811,7 @@ bool AStar2D::_solve(AStar::Point *begin_point, AStar::Point *end_point) {
}
sorter.pop_heap(0, open_list.size(), open_list.ptrw()); // Remove the current point from the open list
- open_list.remove(open_list.size() - 1);
+ open_list.remove_at(open_list.size() - 1);
p->closed_pass = astar.pass; // Mark the point as closed
for (OAHashMap<int, AStar::Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
@@ -859,7 +858,7 @@ void AStar2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_point", "id"), &AStar2D::remove_point);
ClassDB::bind_method(D_METHOD("has_point", "id"), &AStar2D::has_point);
ClassDB::bind_method(D_METHOD("get_point_connections", "id"), &AStar2D::get_point_connections);
- ClassDB::bind_method(D_METHOD("get_points"), &AStar2D::get_points);
+ ClassDB::bind_method(D_METHOD("get_point_ids"), &AStar2D::get_point_ids);
ClassDB::bind_method(D_METHOD("set_point_disabled", "id", "disabled"), &AStar2D::set_point_disabled, DEFVAL(true));
ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar2D::is_point_disabled);
diff --git a/core/math/a_star.h b/core/math/a_star.h
index 64fa32a325..130c202a61 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,9 +37,7 @@
#include "core/templates/oa_hash_map.h"
/**
- A* pathfinding algorithm
-
- @author Juan Linietsky <reduzio@gmail.com>
+ A* pathfinding algorithm.
*/
class AStar : public RefCounted {
@@ -138,7 +136,7 @@ public:
void remove_point(int p_id);
bool has_point(int p_id) const;
Vector<int> get_point_connections(int p_id);
- Array get_points();
+ Array get_point_ids();
void set_point_disabled(int p_id, bool p_disabled = true);
bool is_point_disabled(int p_id) const;
@@ -188,7 +186,7 @@ public:
void remove_point(int p_id);
bool has_point(int p_id) const;
Vector<int> get_point_connections(int p_id);
- Array get_points();
+ Array get_point_ids();
void set_point_disabled(int p_id, bool p_disabled = true);
bool is_point_disabled(int p_id) const;
diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp
index 33aa65f15d..4c89be7f4d 100644
--- a/core/math/aabb.cpp
+++ b/core/math/aabb.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,7 +33,7 @@
#include "core/string/print_string.h"
#include "core/variant/variant.h"
-real_t AABB::get_area() const {
+real_t AABB::get_volume() const {
return size.x * size.y * size.z;
}
@@ -46,14 +46,19 @@ bool AABB::operator!=(const AABB &p_rval) const {
}
void AABB::merge_with(const AABB &p_aabb) {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
+ ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
+ }
+#endif
Vector3 beg_1, beg_2;
Vector3 end_1, end_2;
Vector3 min, max;
beg_1 = position;
beg_2 = p_aabb.position;
- end_1 = Vector3(size.x, size.y, size.z) + beg_1;
- end_2 = Vector3(p_aabb.size.x, p_aabb.size.y, p_aabb.size.z) + beg_2;
+ end_1 = size + beg_1;
+ end_2 = p_aabb.size + beg_2;
min.x = (beg_1.x < beg_2.x) ? beg_1.x : beg_2.x;
min.y = (beg_1.y < beg_2.y) ? beg_1.y : beg_2.y;
@@ -72,6 +77,11 @@ bool AABB::is_equal_approx(const AABB &p_aabb) const {
}
AABB AABB::intersection(const AABB &p_aabb) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
+ ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
+ }
+#endif
Vector3 src_min = position;
Vector3 src_max = position + size;
Vector3 dst_min = p_aabb.position;
@@ -104,6 +114,11 @@ AABB AABB::intersection(const AABB &p_aabb) const {
}
bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
+ ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
+ }
+#endif
Vector3 c1, c2;
Vector3 end = position + size;
real_t near = -1e20;
@@ -147,6 +162,11 @@ bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *
}
bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
+ ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
+ }
+#endif
real_t min = 0, max = 1;
int axis = 0;
real_t sign = 0;
@@ -266,14 +286,14 @@ int AABB::get_longest_axis_index() const {
Vector3 AABB::get_shortest_axis() const {
Vector3 axis(1, 0, 0);
- real_t max_size = size.x;
+ real_t min_size = size.x;
- if (size.y < max_size) {
+ if (size.y < min_size) {
axis = Vector3(0, 1, 0);
- max_size = size.y;
+ min_size = size.y;
}
- if (size.z < max_size) {
+ if (size.z < min_size) {
axis = Vector3(0, 0, 1);
}
@@ -282,14 +302,14 @@ Vector3 AABB::get_shortest_axis() const {
int AABB::get_shortest_axis_index() const {
int axis = 0;
- real_t max_size = size.x;
+ real_t min_size = size.x;
- if (size.y < max_size) {
+ if (size.y < min_size) {
axis = 1;
- max_size = size.y;
+ min_size = size.y;
}
- if (size.z < max_size) {
+ if (size.z < min_size) {
axis = 2;
}
diff --git a/core/math/aabb.h b/core/math/aabb.h
index e16246902a..2eaaafa27d 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,8 +46,8 @@ public:
Vector3 position;
Vector3 size;
- real_t get_area() const; /// get area
- _FORCE_INLINE_ bool has_no_area() const {
+ real_t get_volume() const;
+ _FORCE_INLINE_ bool has_no_volume() const {
return (size.x <= 0 || size.y <= 0 || size.z <= 0);
}
@@ -118,6 +118,10 @@ public:
return position + size;
}
+ _FORCE_INLINE_ Vector3 get_center() const {
+ return position + (size * 0.5);
+ }
+
operator String() const;
_FORCE_INLINE_ AABB() {}
@@ -128,6 +132,11 @@ public:
};
inline bool AABB::intersects(const AABB &p_aabb) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
+ ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
+ }
+#endif
if (position.x >= (p_aabb.position.x + p_aabb.size.x)) {
return false;
}
@@ -151,6 +160,11 @@ inline bool AABB::intersects(const AABB &p_aabb) const {
}
inline bool AABB::intersects_inclusive(const AABB &p_aabb) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
+ ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
+ }
+#endif
if (position.x > (p_aabb.position.x + p_aabb.size.x)) {
return false;
}
@@ -174,6 +188,11 @@ inline bool AABB::intersects_inclusive(const AABB &p_aabb) const {
}
inline bool AABB::encloses(const AABB &p_aabb) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
+ ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
+ }
+#endif
Vector3 src_min = position;
Vector3 src_max = position + size;
Vector3 dst_min = p_aabb.position;
@@ -196,7 +215,7 @@ Vector3 AABB::get_support(const Vector3 &p_normal) const {
(p_normal.x > 0) ? half_extents.x : -half_extents.x,
(p_normal.y > 0) ? half_extents.y : -half_extents.y,
(p_normal.z > 0) ? half_extents.z : -half_extents.z) +
- ofs;
+ ofs;
}
Vector3 AABB::get_endpoint(int p_point) const {
@@ -284,6 +303,11 @@ bool AABB::inside_convex_shape(const Plane *p_planes, int p_plane_count) const {
}
bool AABB::has_point(const Vector3 &p_point) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
+ ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
+ }
+#endif
if (p_point.x < position.x) {
return false;
}
@@ -307,6 +331,11 @@ bool AABB::has_point(const Vector3 &p_point) const {
}
inline void AABB::expand_to(const Vector3 &p_vector) {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
+ ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
+ }
+#endif
Vector3 begin = position;
Vector3 end = position + size;
@@ -373,6 +402,11 @@ inline real_t AABB::get_shortest_axis_size() const {
}
bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
+ ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
+ }
+#endif
real_t divx = 1.0 / p_dir.x;
real_t divy = 1.0 / p_dir.y;
real_t divz = 1.0 / p_dir.z;
diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h
index a5616b8d79..94fc3de2b1 100644
--- a/core/math/audio_frame.h
+++ b/core/math/audio_frame.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -124,10 +124,9 @@ struct AudioFrame {
r = p_frame.r;
}
- _ALWAYS_INLINE_ AudioFrame &operator=(const AudioFrame &p_frame) {
+ _ALWAYS_INLINE_ void operator=(const AudioFrame &p_frame) {
l = p_frame.l;
r = p_frame.r;
- return *this;
}
_ALWAYS_INLINE_ operator Vector2() const {
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index eec9caf149..a9b4651664 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -58,8 +58,8 @@ void Basis::invert() {
cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)
};
real_t det = elements[0][0] * co[0] +
- elements[0][1] * co[1] +
- elements[0][2] * co[2];
+ elements[0][1] * co[1] +
+ elements[0][2] * co[2];
#ifdef MATH_CHECKS
ERR_FAIL_COND(det == 0);
#endif
@@ -94,6 +94,18 @@ Basis Basis::orthonormalized() const {
return c;
}
+void Basis::orthogonalize() {
+ Vector3 scl = get_scale();
+ orthonormalize();
+ scale_local(scl);
+}
+
+Basis Basis::orthogonalized() const {
+ Basis c = *this;
+ c.orthogonalize();
+ return c;
+}
+
bool Basis::is_orthogonal() const {
Basis identity;
Basis m = (*this) * transposed();
@@ -207,6 +219,10 @@ Basis Basis::transposed() const {
return tr;
}
+Basis Basis::from_scale(const Vector3 &p_scale) {
+ return Basis(p_scale.x, 0, 0, 0, p_scale.y, 0, 0, 0, p_scale.z);
+}
+
// Multiplies the matrix from left by the scaling matrix: M -> S.M
// See the comment for Basis::rotated for further explanation.
void Basis::scale(const Vector3 &p_scale) {
@@ -233,6 +249,24 @@ void Basis::scale_local(const Vector3 &p_scale) {
*this = scaled_local(p_scale);
}
+void Basis::scale_orthogonal(const Vector3 &p_scale) {
+ *this = scaled_orthogonal(p_scale);
+}
+
+Basis Basis::scaled_orthogonal(const Vector3 &p_scale) const {
+ Basis m = *this;
+ Vector3 s = Vector3(-1, -1, -1) + p_scale;
+ 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_axis(i).normalized().dot(b.get_axis(j)));
+ }
+ }
+ m.scale_local(Vector3(1, 1, 1) + dots);
+ return m;
+}
+
float Basis::get_uniform_scale() const {
return (elements[0].length() + elements[1].length() + elements[2].length()) / 3.0;
}
@@ -246,10 +280,7 @@ void Basis::make_scale_uniform() {
}
Basis Basis::scaled_local(const Vector3 &p_scale) const {
- Basis b;
- b.set_diagonal(p_scale);
-
- return (*this) * b;
+ return (*this) * Basis::from_scale(p_scale);
}
Vector3 Basis::get_scale_abs() const {
@@ -260,7 +291,7 @@ Vector3 Basis::get_scale_abs() const {
}
Vector3 Basis::get_scale_local() const {
- real_t det_sign = SGN(determinant());
+ real_t det_sign = SIGN(determinant());
return det_sign * Vector3(elements[0].length(), elements[1].length(), elements[2].length());
}
@@ -286,11 +317,8 @@ Vector3 Basis::get_scale() const {
// matrix elements.
//
// The rotation part of this decomposition is returned by get_rotation* functions.
- real_t det_sign = SGN(determinant());
- return det_sign * Vector3(
- Vector3(elements[0][0], elements[1][0], elements[2][0]).length(),
- Vector3(elements[0][1], elements[1][1], elements[2][1]).length(),
- Vector3(elements[0][2], elements[1][2], elements[2][2]).length());
+ real_t det_sign = SIGN(determinant());
+ return det_sign * get_scale_abs();
}
// Decomposes a Basis into a rotation-reflection matrix (an element of the group O(3)) and a positive scaling matrix as B = O.S.
@@ -353,7 +381,7 @@ void Basis::rotate(const Quaternion &p_quaternion) {
*this = rotated(p_quaternion);
}
-Vector3 Basis::get_rotation_euler() const {
+Vector3 Basis::get_euler_normalized(EulerOrder p_order) const {
// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
// See the comment in get_scale() for further information.
@@ -364,7 +392,7 @@ Vector3 Basis::get_rotation_euler() const {
m.scale(Vector3(-1, -1, -1));
}
- return m.get_euler();
+ return m.get_euler(p_order);
}
Quaternion Basis::get_rotation_quaternion() const {
@@ -423,266 +451,203 @@ void Basis::get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) cons
p_angle = -p_angle;
}
-// get_euler_xyz returns a vector containing the Euler angles in the format
-// (a1,a2,a3), where a3 is the angle of the first rotation, and a1 is the last
-// (following the convention they are commonly defined in the literature).
-//
-// The current implementation uses XYZ convention (Z is the first rotation),
-// so euler.z is the angle of the (first) rotation around Z axis and so on,
-//
-// And thus, assuming the matrix is a rotation matrix, this function returns
-// the angles in the decomposition R = X(a1).Y(a2).Z(a3) where Z(a) rotates
-// around the z-axis by a and so on.
-Vector3 Basis::get_euler_xyz() const {
- // Euler angles in XYZ convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cy*cz -cy*sz sy
- // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
- // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
-
- Vector3 euler;
- real_t sy = elements[0][2];
- if (sy < (1.0 - CMP_EPSILON)) {
- if (sy > -(1.0 - CMP_EPSILON)) {
- // is this a pure Y rotation?
- if (elements[1][0] == 0.0 && elements[0][1] == 0.0 && elements[1][2] == 0 && elements[2][1] == 0 && elements[1][1] == 1) {
- // return the simplest form (human friendlier in editor and scripts)
- euler.x = 0;
- euler.y = atan2(elements[0][2], elements[0][0]);
- euler.z = 0;
+Vector3 Basis::get_euler(EulerOrder p_order) const {
+ switch (p_order) {
+ case EULER_ORDER_XYZ: {
+ // Euler angles in XYZ convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cy*cz -cy*sz sy
+ // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
+ // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
+
+ Vector3 euler;
+ real_t sy = elements[0][2];
+ if (sy < (1.0 - CMP_EPSILON)) {
+ if (sy > -(1.0 - CMP_EPSILON)) {
+ // is this a pure Y rotation?
+ if (elements[1][0] == 0.0 && elements[0][1] == 0.0 && elements[1][2] == 0 && elements[2][1] == 0 && elements[1][1] == 1) {
+ // return the simplest form (human friendlier in editor and scripts)
+ euler.x = 0;
+ euler.y = atan2(elements[0][2], elements[0][0]);
+ euler.z = 0;
+ } else {
+ euler.x = Math::atan2(-elements[1][2], elements[2][2]);
+ euler.y = Math::asin(sy);
+ euler.z = Math::atan2(-elements[0][1], elements[0][0]);
+ }
+ } else {
+ euler.x = Math::atan2(elements[2][1], elements[1][1]);
+ euler.y = -Math_PI / 2.0;
+ euler.z = 0.0;
+ }
} else {
- euler.x = Math::atan2(-elements[1][2], elements[2][2]);
- euler.y = Math::asin(sy);
- euler.z = Math::atan2(-elements[0][1], elements[0][0]);
+ euler.x = Math::atan2(elements[2][1], elements[1][1]);
+ euler.y = Math_PI / 2.0;
+ euler.z = 0.0;
+ }
+ return euler;
+ } break;
+ case EULER_ORDER_XZY: {
+ // Euler angles in XZY convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cz*cy -sz cz*sy
+ // sx*sy+cx*cy*sz cx*cz cx*sz*sy-cy*sx
+ // cy*sx*sz cz*sx cx*cy+sx*sz*sy
+
+ Vector3 euler;
+ real_t sz = elements[0][1];
+ if (sz < (1.0 - CMP_EPSILON)) {
+ if (sz > -(1.0 - CMP_EPSILON)) {
+ euler.x = Math::atan2(elements[2][1], elements[1][1]);
+ euler.y = Math::atan2(elements[0][2], elements[0][0]);
+ euler.z = Math::asin(-sz);
+ } else {
+ // It's -1
+ euler.x = -Math::atan2(elements[1][2], elements[2][2]);
+ euler.y = 0.0;
+ euler.z = Math_PI / 2.0;
+ }
+ } else {
+ // It's 1
+ euler.x = -Math::atan2(elements[1][2], elements[2][2]);
+ euler.y = 0.0;
+ euler.z = -Math_PI / 2.0;
+ }
+ return euler;
+ } break;
+ case EULER_ORDER_YXZ: {
+ // Euler angles in YXZ convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cy*cz+sy*sx*sz cz*sy*sx-cy*sz cx*sy
+ // cx*sz cx*cz -sx
+ // cy*sx*sz-cz*sy cy*cz*sx+sy*sz cy*cx
+
+ Vector3 euler;
+
+ real_t m12 = elements[1][2];
+
+ if (m12 < (1 - CMP_EPSILON)) {
+ if (m12 > -(1 - CMP_EPSILON)) {
+ // is this a pure X rotation?
+ if (elements[1][0] == 0 && elements[0][1] == 0 && elements[0][2] == 0 && elements[2][0] == 0 && elements[0][0] == 1) {
+ // return the simplest form (human friendlier in editor and scripts)
+ euler.x = atan2(-m12, elements[1][1]);
+ euler.y = 0;
+ euler.z = 0;
+ } else {
+ euler.x = asin(-m12);
+ euler.y = atan2(elements[0][2], elements[2][2]);
+ euler.z = atan2(elements[1][0], elements[1][1]);
+ }
+ } else { // m12 == -1
+ euler.x = Math_PI * 0.5;
+ euler.y = atan2(elements[0][1], elements[0][0]);
+ euler.z = 0;
+ }
+ } else { // m12 == 1
+ euler.x = -Math_PI * 0.5;
+ euler.y = -atan2(elements[0][1], elements[0][0]);
+ euler.z = 0;
}
- } else {
- euler.x = Math::atan2(elements[2][1], elements[1][1]);
- euler.y = -Math_PI / 2.0;
- euler.z = 0.0;
- }
- } else {
- euler.x = Math::atan2(elements[2][1], elements[1][1]);
- euler.y = Math_PI / 2.0;
- euler.z = 0.0;
- }
- return euler;
-}
-
-// set_euler_xyz expects a vector containing the Euler angles in the format
-// (ax,ay,az), where ax is the angle of rotation around x axis,
-// and similar for other axes.
-// The current implementation uses XYZ convention (Z is the first rotation).
-void Basis::set_euler_xyz(const Vector3 &p_euler) {
- real_t c, s;
-
- c = Math::cos(p_euler.x);
- s = Math::sin(p_euler.x);
- Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
- c = Math::cos(p_euler.y);
- s = Math::sin(p_euler.y);
- Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
- c = Math::cos(p_euler.z);
- s = Math::sin(p_euler.z);
- Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
- //optimizer will optimize away all this anyway
- *this = xmat * (ymat * zmat);
-}
-
-Vector3 Basis::get_euler_xzy() const {
- // Euler angles in XZY convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cz*cy -sz cz*sy
- // sx*sy+cx*cy*sz cx*cz cx*sz*sy-cy*sx
- // cy*sx*sz cz*sx cx*cy+sx*sz*sy
-
- Vector3 euler;
- real_t sz = elements[0][1];
- if (sz < (1.0 - CMP_EPSILON)) {
- if (sz > -(1.0 - CMP_EPSILON)) {
- euler.x = Math::atan2(elements[2][1], elements[1][1]);
- euler.y = Math::atan2(elements[0][2], elements[0][0]);
- euler.z = Math::asin(-sz);
- } else {
- // It's -1
- euler.x = -Math::atan2(elements[1][2], elements[2][2]);
- euler.y = 0.0;
- euler.z = Math_PI / 2.0;
- }
- } else {
- // It's 1
- euler.x = -Math::atan2(elements[1][2], elements[2][2]);
- euler.y = 0.0;
- euler.z = -Math_PI / 2.0;
- }
- return euler;
-}
-
-void Basis::set_euler_xzy(const Vector3 &p_euler) {
- real_t c, s;
-
- c = Math::cos(p_euler.x);
- s = Math::sin(p_euler.x);
- Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
- c = Math::cos(p_euler.y);
- s = Math::sin(p_euler.y);
- Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
- c = Math::cos(p_euler.z);
- s = Math::sin(p_euler.z);
- Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
- *this = xmat * zmat * ymat;
-}
-
-Vector3 Basis::get_euler_yzx() const {
- // Euler angles in YZX convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cy*cz sy*sx-cy*cx*sz cx*sy+cy*sz*sx
- // sz cz*cx -cz*sx
- // -cz*sy cy*sx+cx*sy*sz cy*cx-sy*sz*sx
-
- Vector3 euler;
- real_t sz = elements[1][0];
- if (sz < (1.0 - CMP_EPSILON)) {
- if (sz > -(1.0 - CMP_EPSILON)) {
- euler.x = Math::atan2(-elements[1][2], elements[1][1]);
- euler.y = Math::atan2(-elements[2][0], elements[0][0]);
- euler.z = Math::asin(sz);
- } else {
- // It's -1
- euler.x = Math::atan2(elements[2][1], elements[2][2]);
- euler.y = 0.0;
- euler.z = -Math_PI / 2.0;
- }
- } else {
- // It's 1
- euler.x = Math::atan2(elements[2][1], elements[2][2]);
- euler.y = 0.0;
- euler.z = Math_PI / 2.0;
- }
- return euler;
-}
-
-void Basis::set_euler_yzx(const Vector3 &p_euler) {
- real_t c, s;
-
- c = Math::cos(p_euler.x);
- s = Math::sin(p_euler.x);
- Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
- c = Math::cos(p_euler.y);
- s = Math::sin(p_euler.y);
- Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
- c = Math::cos(p_euler.z);
- s = Math::sin(p_euler.z);
- Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
- *this = ymat * zmat * xmat;
-}
-
-// get_euler_yxz returns a vector containing the Euler angles in the YXZ convention,
-// as in first-Z, then-X, last-Y. The angles for X, Y, and Z rotations are returned
-// as the x, y, and z components of a Vector3 respectively.
-Vector3 Basis::get_euler_yxz() const {
- // Euler angles in YXZ convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cy*cz+sy*sx*sz cz*sy*sx-cy*sz cx*sy
- // cx*sz cx*cz -sx
- // cy*sx*sz-cz*sy cy*cz*sx+sy*sz cy*cx
-
- Vector3 euler;
-
- real_t m12 = elements[1][2];
- if (m12 < (1 - CMP_EPSILON)) {
- if (m12 > -(1 - CMP_EPSILON)) {
- // is this a pure X rotation?
- if (elements[1][0] == 0 && elements[0][1] == 0 && elements[0][2] == 0 && elements[2][0] == 0 && elements[0][0] == 1) {
- // return the simplest form (human friendlier in editor and scripts)
- euler.x = atan2(-m12, elements[1][1]);
- euler.y = 0;
+ return euler;
+ } break;
+ case EULER_ORDER_YZX: {
+ // Euler angles in YZX convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cy*cz sy*sx-cy*cx*sz cx*sy+cy*sz*sx
+ // sz cz*cx -cz*sx
+ // -cz*sy cy*sx+cx*sy*sz cy*cx-sy*sz*sx
+
+ Vector3 euler;
+ real_t sz = elements[1][0];
+ if (sz < (1.0 - CMP_EPSILON)) {
+ if (sz > -(1.0 - CMP_EPSILON)) {
+ euler.x = Math::atan2(-elements[1][2], elements[1][1]);
+ euler.y = Math::atan2(-elements[2][0], elements[0][0]);
+ euler.z = Math::asin(sz);
+ } else {
+ // It's -1
+ euler.x = Math::atan2(elements[2][1], elements[2][2]);
+ euler.y = 0.0;
+ euler.z = -Math_PI / 2.0;
+ }
+ } else {
+ // It's 1
+ euler.x = Math::atan2(elements[2][1], elements[2][2]);
+ euler.y = 0.0;
+ euler.z = Math_PI / 2.0;
+ }
+ return euler;
+ } break;
+ case EULER_ORDER_ZXY: {
+ // Euler angles in ZXY convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cz*cy-sz*sx*sy -cx*sz cz*sy+cy*sz*sx
+ // cy*sz+cz*sx*sy cz*cx sz*sy-cz*cy*sx
+ // -cx*sy sx cx*cy
+ Vector3 euler;
+ real_t sx = elements[2][1];
+ if (sx < (1.0 - CMP_EPSILON)) {
+ if (sx > -(1.0 - CMP_EPSILON)) {
+ euler.x = Math::asin(sx);
+ euler.y = Math::atan2(-elements[2][0], elements[2][2]);
+ euler.z = Math::atan2(-elements[0][1], elements[1][1]);
+ } else {
+ // It's -1
+ euler.x = -Math_PI / 2.0;
+ euler.y = Math::atan2(elements[0][2], elements[0][0]);
+ euler.z = 0;
+ }
+ } else {
+ // It's 1
+ euler.x = Math_PI / 2.0;
+ euler.y = Math::atan2(elements[0][2], elements[0][0]);
euler.z = 0;
+ }
+ return euler;
+ } break;
+ case EULER_ORDER_ZYX: {
+ // Euler angles in ZYX convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cz*cy cz*sy*sx-cx*sz sz*sx+cz*cx*cy
+ // cy*sz cz*cx+sz*sy*sx cx*sz*sy-cz*sx
+ // -sy cy*sx cy*cx
+ Vector3 euler;
+ real_t sy = elements[2][0];
+ if (sy < (1.0 - CMP_EPSILON)) {
+ if (sy > -(1.0 - CMP_EPSILON)) {
+ euler.x = Math::atan2(elements[2][1], elements[2][2]);
+ euler.y = Math::asin(-sy);
+ euler.z = Math::atan2(elements[1][0], elements[0][0]);
+ } else {
+ // It's -1
+ euler.x = 0;
+ euler.y = Math_PI / 2.0;
+ euler.z = -Math::atan2(elements[0][1], elements[1][1]);
+ }
} else {
- euler.x = asin(-m12);
- euler.y = atan2(elements[0][2], elements[2][2]);
- euler.z = atan2(elements[1][0], elements[1][1]);
+ // It's 1
+ euler.x = 0;
+ euler.y = -Math_PI / 2.0;
+ euler.z = -Math::atan2(elements[0][1], elements[1][1]);
}
- } else { // m12 == -1
- euler.x = Math_PI * 0.5;
- euler.y = atan2(elements[0][1], elements[0][0]);
- euler.z = 0;
- }
- } else { // m12 == 1
- euler.x = -Math_PI * 0.5;
- euler.y = -atan2(elements[0][1], elements[0][0]);
- euler.z = 0;
- }
-
- return euler;
-}
-
-// set_euler_yxz expects a vector containing the Euler angles in the format
-// (ax,ay,az), where ax is the angle of rotation around x axis,
-// and similar for other axes.
-// The current implementation uses YXZ convention (Z is the first rotation).
-void Basis::set_euler_yxz(const Vector3 &p_euler) {
- real_t c, s;
-
- c = Math::cos(p_euler.x);
- s = Math::sin(p_euler.x);
- Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
- c = Math::cos(p_euler.y);
- s = Math::sin(p_euler.y);
- Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
- c = Math::cos(p_euler.z);
- s = Math::sin(p_euler.z);
- Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
- //optimizer will optimize away all this anyway
- *this = ymat * xmat * zmat;
-}
-
-Vector3 Basis::get_euler_zxy() const {
- // Euler angles in ZXY convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cz*cy-sz*sx*sy -cx*sz cz*sy+cy*sz*sx
- // cy*sz+cz*sx*sy cz*cx sz*sy-cz*cy*sx
- // -cx*sy sx cx*cy
- Vector3 euler;
- real_t sx = elements[2][1];
- if (sx < (1.0 - CMP_EPSILON)) {
- if (sx > -(1.0 - CMP_EPSILON)) {
- euler.x = Math::asin(sx);
- euler.y = Math::atan2(-elements[2][0], elements[2][2]);
- euler.z = Math::atan2(-elements[0][1], elements[1][1]);
- } else {
- // It's -1
- euler.x = -Math_PI / 2.0;
- euler.y = Math::atan2(elements[0][2], elements[0][0]);
- euler.z = 0;
+ return euler;
+ } break;
+ default: {
+ ERR_FAIL_V_MSG(Vector3(), "Invalid parameter for get_euler(order)");
}
- } else {
- // It's 1
- euler.x = Math_PI / 2.0;
- euler.y = Math::atan2(elements[0][2], elements[0][0]);
- euler.z = 0;
}
- return euler;
+ return Vector3();
}
-void Basis::set_euler_zxy(const Vector3 &p_euler) {
+void Basis::set_euler(const Vector3 &p_euler, EulerOrder p_order) {
real_t c, s;
c = Math::cos(p_euler.x);
@@ -697,54 +662,29 @@ void Basis::set_euler_zxy(const Vector3 &p_euler) {
s = Math::sin(p_euler.z);
Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
- *this = zmat * xmat * ymat;
-}
-
-Vector3 Basis::get_euler_zyx() const {
- // Euler angles in ZYX convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cz*cy cz*sy*sx-cx*sz sz*sx+cz*cx*cy
- // cy*sz cz*cx+sz*sy*sx cx*sz*sy-cz*sx
- // -sy cy*sx cy*cx
- Vector3 euler;
- real_t sy = elements[2][0];
- if (sy < (1.0 - CMP_EPSILON)) {
- if (sy > -(1.0 - CMP_EPSILON)) {
- euler.x = Math::atan2(elements[2][1], elements[2][2]);
- euler.y = Math::asin(-sy);
- euler.z = Math::atan2(elements[1][0], elements[0][0]);
- } else {
- // It's -1
- euler.x = 0;
- euler.y = Math_PI / 2.0;
- euler.z = -Math::atan2(elements[0][1], elements[1][1]);
+ switch (p_order) {
+ case EULER_ORDER_XYZ: {
+ *this = xmat * (ymat * zmat);
+ } break;
+ case EULER_ORDER_XZY: {
+ *this = xmat * zmat * ymat;
+ } break;
+ case EULER_ORDER_YXZ: {
+ *this = ymat * xmat * zmat;
+ } break;
+ case EULER_ORDER_YZX: {
+ *this = ymat * zmat * xmat;
+ } break;
+ case EULER_ORDER_ZXY: {
+ *this = zmat * xmat * ymat;
+ } break;
+ case EULER_ORDER_ZYX: {
+ *this = zmat * ymat * xmat;
+ } break;
+ default: {
+ ERR_FAIL_MSG("Invalid order parameter for set_euler(vec3,order)");
}
- } else {
- // It's 1
- euler.x = 0;
- euler.y = -Math_PI / 2.0;
- euler.z = -Math::atan2(elements[0][1], elements[1][1]);
}
- return euler;
-}
-
-void Basis::set_euler_zyx(const Vector3 &p_euler) {
- real_t c, s;
-
- c = Math::cos(p_euler.x);
- s = Math::sin(p_euler.x);
- Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
- c = Math::cos(p_euler.y);
- s = Math::sin(p_euler.y);
- Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
- c = Math::cos(p_euler.z);
- s = Math::sin(p_euler.z);
- Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
- *this = zmat * ymat * xmat;
}
bool Basis::is_equal_approx(const Basis &p_basis) const {
@@ -769,8 +709,8 @@ bool Basis::operator!=(const Basis &p_matrix) const {
Basis::operator String() const {
return "[X: " + get_axis(0).operator String() +
- ", Y: " + get_axis(1).operator String() +
- ", Z: " + get_axis(2).operator String() + "]";
+ ", Y: " + get_axis(1).operator String() +
+ ", Z: " + get_axis(2).operator String() + "]";
}
Quaternion Basis::get_quaternion() const {
@@ -791,9 +731,9 @@ Quaternion Basis::get_quaternion() const {
temp[1] = ((m.elements[0][2] - m.elements[2][0]) * s);
temp[2] = ((m.elements[1][0] - m.elements[0][1]) * s);
} else {
- int i = m.elements[0][0] < m.elements[1][1] ?
- (m.elements[1][1] < m.elements[2][2] ? 2 : 1) :
- (m.elements[0][0] < m.elements[2][2] ? 2 : 0);
+ int i = m.elements[0][0] < m.elements[1][1]
+ ? (m.elements[1][1] < m.elements[2][2] ? 2 : 1)
+ : (m.elements[0][0] < m.elements[2][2] ? 2 : 0);
int j = (i + 1) % 3;
int k = (i + 2) % 3;
@@ -991,21 +931,23 @@ void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_phi) {
}
void Basis::set_axis_angle_scale(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale) {
- set_diagonal(p_scale);
+ _set_diagonal(p_scale);
rotate(p_axis, p_phi);
}
void Basis::set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale) {
- set_diagonal(p_scale);
+ _set_diagonal(p_scale);
rotate(p_euler);
}
void Basis::set_quaternion_scale(const Quaternion &p_quaternion, const Vector3 &p_scale) {
- set_diagonal(p_scale);
+ _set_diagonal(p_scale);
rotate(p_quaternion);
}
-void Basis::set_diagonal(const Vector3 &p_diag) {
+// This also sets the non-diagonal elements to 0, which is misleading from the
+// name, so we want this method to be private. Use `from_scale` externally.
+void Basis::_set_diagonal(const Vector3 &p_diag) {
elements[0][0] = p_diag.x;
elements[0][1] = 0;
elements[0][2] = 0;
@@ -1019,6 +961,15 @@ void Basis::set_diagonal(const Vector3 &p_diag) {
elements[2][2] = p_diag.z;
}
+Basis Basis::lerp(const Basis &p_to, const real_t &p_weight) const {
+ Basis b;
+ b.elements[0] = elements[0].lerp(p_to.elements[0], p_weight);
+ b.elements[1] = elements[1].lerp(p_to.elements[1], p_weight);
+ b.elements[2] = elements[2].lerp(p_to.elements[2], p_weight);
+
+ return b;
+}
+
Basis Basis::slerp(const Basis &p_to, const real_t &p_weight) const {
//consider scale
Quaternion from(*this);
diff --git a/core/math/basis.h b/core/math/basis.h
index 9d8ed16e29..709f2cb3cf 100644
--- a/core/math/basis.h
+++ b/core/math/basis.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,6 +35,9 @@
#include "core/math/vector3.h"
class Basis {
+private:
+ void _set_diagonal(const Vector3 &p_diag);
+
public:
Vector3 elements[3] = {
Vector3(1, 0, 0),
@@ -82,40 +85,35 @@ public:
void rotate(const Quaternion &p_quaternion);
Basis rotated(const Quaternion &p_quaternion) const;
- Vector3 get_rotation_euler() const;
+ enum EulerOrder {
+ EULER_ORDER_XYZ,
+ EULER_ORDER_XZY,
+ EULER_ORDER_YXZ,
+ EULER_ORDER_YZX,
+ EULER_ORDER_ZXY,
+ EULER_ORDER_ZYX
+ };
+
+ Vector3 get_euler_normalized(EulerOrder p_order = EULER_ORDER_YXZ) const;
void get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const;
void get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const;
Quaternion get_rotation_quaternion() const;
- Vector3 get_rotation() const { return get_rotation_euler(); };
void rotate_to_align(Vector3 p_start_direction, Vector3 p_end_direction);
Vector3 rotref_posscale_decomposition(Basis &rotref) const;
- Vector3 get_euler_xyz() const;
- void set_euler_xyz(const Vector3 &p_euler);
-
- Vector3 get_euler_xzy() const;
- void set_euler_xzy(const Vector3 &p_euler);
-
- Vector3 get_euler_yzx() const;
- void set_euler_yzx(const Vector3 &p_euler);
-
- Vector3 get_euler_yxz() const;
- void set_euler_yxz(const Vector3 &p_euler);
-
- Vector3 get_euler_zxy() const;
- void set_euler_zxy(const Vector3 &p_euler);
-
- Vector3 get_euler_zyx() const;
- void set_euler_zyx(const Vector3 &p_euler);
+ Vector3 get_euler(EulerOrder p_order = EULER_ORDER_YXZ) const;
+ void set_euler(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ);
+ static Basis from_euler(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ) {
+ Basis b;
+ b.set_euler(p_euler, p_order);
+ return b;
+ }
Quaternion get_quaternion() const;
void set_quaternion(const Quaternion &p_quaternion);
- Vector3 get_euler() const { return get_euler_yxz(); }
- void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); }
-
void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const;
void set_axis_angle(const Vector3 &p_axis, real_t p_phi);
@@ -125,6 +123,9 @@ public:
void scale_local(const Vector3 &p_scale);
Basis scaled_local(const Vector3 &p_scale) const;
+ void scale_orthogonal(const Vector3 &p_scale);
+ Basis scaled_orthogonal(const Vector3 &p_scale) const;
+
void make_scale_uniform();
float get_uniform_scale() const;
@@ -166,12 +167,11 @@ public:
int get_orthogonal_index() const;
void set_orthogonal_index(int p_index);
- void set_diagonal(const Vector3 &p_diag);
-
bool is_orthogonal() const;
bool is_diagonal() const;
bool is_rotation() const;
+ Basis lerp(const Basis &p_to, const real_t &p_weight) const;
Basis slerp(const Basis &p_to, const real_t &p_weight) const;
void rotate_sh(real_t *p_values);
@@ -237,6 +237,9 @@ public:
void orthonormalize();
Basis orthonormalized() const;
+ void orthogonalize();
+ Basis orthogonalized() const;
+
#ifdef MATH_CHECKS
bool is_symmetric() const;
#endif
@@ -249,11 +252,9 @@ public:
Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); };
Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); }
- Basis(const Vector3 &p_euler) { set_euler(p_euler); }
- Basis(const Vector3 &p_euler, const Vector3 &p_scale) { set_euler_scale(p_euler, p_scale); }
-
Basis(const Vector3 &p_axis, real_t p_phi) { set_axis_angle(p_axis, p_phi); }
Basis(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale) { set_axis_angle_scale(p_axis, p_phi, p_scale); }
+ static Basis from_scale(const Vector3 &p_scale);
_FORCE_INLINE_ Basis(const Vector3 &row0, const Vector3 &row1, const Vector3 &row2) {
elements[0] = row0;
@@ -330,7 +331,7 @@ Vector3 Basis::xform_inv(const Vector3 &p_vector) const {
real_t Basis::determinant() const {
return elements[0][0] * (elements[1][1] * elements[2][2] - elements[2][1] * elements[1][2]) -
- elements[1][0] * (elements[0][1] * elements[2][2] - elements[2][1] * elements[0][2]) +
- elements[2][0] * (elements[0][1] * elements[1][2] - elements[1][1] * elements[0][2]);
+ elements[1][0] * (elements[0][1] * elements[2][2] - elements[2][1] * elements[0][2]) +
+ elements[2][0] * (elements[0][1] * elements[1][2] - elements[1][1] * elements[0][2]);
}
#endif // BASIS_H
diff --git a/core/math/bvh.h b/core/math/bvh.h
index cefbc9b0db..a8e3cc7bbe 100644
--- a/core/math/bvh.h
+++ b/core/math/bvh.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -200,7 +200,7 @@ public:
// use in conjunction with activate if you have deferred the collision check, and
// set pairable has never been called.
- // (deferred collision checks are a workaround for visual server for historical reasons)
+ // (deferred collision checks are a workaround for rendering server for historical reasons)
void force_collision_check(BVHHandle p_handle) {
if (USE_PAIRS) {
// the aabb should already be up to date in the BVH
@@ -654,7 +654,7 @@ private:
// remove from changed items (not very efficient yet)
for (int n = 0; n < (int)changed_items.size(); n++) {
if (changed_items[n] == p_handle) {
- changed_items.remove_unordered(n);
+ changed_items.remove_at_unordered(n);
// because we are using an unordered remove,
// the last changed item will now be at spot 'n',
diff --git a/core/math/bvh_abb.h b/core/math/bvh_abb.h
index bd9a01a87e..009032d34d 100644
--- a/core/math/bvh_abb.h
+++ b/core/math/bvh_abb.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/bvh_cull.inc b/core/math/bvh_cull.inc
index cba8ea6cb3..d7edc8a884 100644
--- a/core/math/bvh_cull.inc
+++ b/core/math/bvh_cull.inc
@@ -14,7 +14,7 @@ struct CullParams {
uint32_t pairable_type;
// optional components for different tests
- Vector3 point;
+ Point point;
BVHABB_CLASS abb;
typename BVHABB_CLASS::ConvexHull hull;
typename BVHABB_CLASS::Segment segment;
diff --git a/core/math/bvh_debug.inc b/core/math/bvh_debug.inc
index a97304334c..55db794ee3 100644
--- a/core/math/bvh_debug.inc
+++ b/core/math/bvh_debug.inc
@@ -6,24 +6,21 @@ void _debug_recursive_print_tree(int p_tree_id) const {
}
String _debug_aabb_to_string(const BVHABB_CLASS &aabb) const {
- String sz = "(";
- sz += itos(aabb.min.x);
- sz += " ~ ";
- sz += itos(-aabb.neg_max.x);
- sz += ") (";
+ Point size = aabb.calculate_size();
- sz += itos(aabb.min.y);
- sz += " ~ ";
- sz += itos(-aabb.neg_max.y);
- sz += ") (";
+ String sz;
+ float vol = 0.0;
- sz += itos(aabb.min.z);
- sz += " ~ ";
- sz += itos(-aabb.neg_max.z);
- sz += ") ";
+ for (int i = 0; i < Point::AXES_COUNT; ++i) {
+ sz += "(";
+ sz += itos(aabb.min[i]);
+ sz += " ~ ";
+ sz += itos(-aabb.neg_max[i]);
+ sz += ") ";
+
+ vol += size[i];
+ }
- Vector3 size = aabb.calculate_size();
- float vol = size.x * size.y * size.z;
sz += "vol " + itos(vol);
return sz;
diff --git a/core/math/bvh_logic.inc b/core/math/bvh_logic.inc
index afab08f151..c65002a9fd 100644
--- a/core/math/bvh_logic.inc
+++ b/core/math/bvh_logic.inc
@@ -42,24 +42,24 @@ BVHABB_CLASS _logic_abb_merge(const BVHABB_CLASS &a, const BVHABB_CLASS &b) {
//--------------------------------------------------------------------------------------------------
/**
-@file q3DynamicAABBTree.h
-@author Randy Gaul
-@date 10/10/2014
- Copyright (c) 2014 Randy Gaul http://www.randygaul.net
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not
- be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-*/
+ * @file q3DynamicAABBTree.h
+ * @author Randy Gaul
+ * @date 10/10/2014
+ * Copyright (c) 2014 Randy Gaul http://www.randygaul.net
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
//--------------------------------------------------------------------------------------------------
// This function is based on the 'Balance' function from Randy Gaul's qu3e
@@ -67,7 +67,7 @@ BVHABB_CLASS _logic_abb_merge(const BVHABB_CLASS &a, const BVHABB_CLASS &b) {
// It is MODIFIED from qu3e version.
// This is the only function used (and _logic_abb_merge helper function).
int32_t _logic_balance(int32_t iA, uint32_t p_tree_id) {
- // return iA; // uncomment this to bypass balance
+ //return iA; // uncomment this to bypass balance
TNode *A = &_nodes[iA];
@@ -75,12 +75,12 @@ int32_t _logic_balance(int32_t iA, uint32_t p_tree_id) {
return iA;
}
- /* A
- / \
- B C
- / \ / \
- D E F G
- */
+ /* A
+ * / \
+ * B C
+ * / \ / \
+ * D E F G
+ */
CRASH_COND(A->num_children != 2);
int32_t iB = A->children[0];
diff --git a/core/math/bvh_pair.inc b/core/math/bvh_pair.inc
index 839db59a3a..a12acec2b6 100644
--- a/core/math/bvh_pair.inc
+++ b/core/math/bvh_pair.inc
@@ -51,7 +51,7 @@ struct ItemPairs {
for (int n = 0; n < num_pairs; n++) {
if (extended_pairs[n].handle == h) {
userdata = extended_pairs[n].userdata;
- extended_pairs.remove_unordered(n);
+ extended_pairs.remove_at_unordered(n);
num_pairs--;
break;
}
diff --git a/core/math/bvh_split.inc b/core/math/bvh_split.inc
index 3fcc4c7b10..f19ee8a7da 100644
--- a/core/math/bvh_split.inc
+++ b/core/math/bvh_split.inc
@@ -28,11 +28,15 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
Point centre = full_bound.calculate_centre();
Point size = full_bound.calculate_size();
- int order[3];
+ int order[Point::AXIS_COUNT];
- order[0] = size.min_axis();
- order[2] = size.max_axis();
- order[1] = 3 - (order[0] + order[2]);
+ order[0] = size.min_axis_index();
+ order[Point::AXIS_COUNT - 1] = size.max_axis_index();
+
+ static_assert(Point::AXIS_COUNT <= 3);
+ if (Point::AXIS_COUNT == 3) {
+ order[1] = 3 - (order[0] + order[2]);
+ }
// simplest case, split on the longest axis
int split_axis = order[0];
@@ -54,7 +58,7 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
// detect when split on longest axis failed
int min_threshold = MAX_ITEMS / 4;
- int min_group_size[3];
+ int min_group_size[Point::AXIS_COUNT];
min_group_size[0] = MIN(num_a, num_b);
if (min_group_size[0] < min_threshold) {
// slow but sure .. first move everything back into a
@@ -64,7 +68,7 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
num_b = 0;
// now calculate the best split
- for (int axis = 1; axis < 3; axis++) {
+ for (int axis = 1; axis < Point::AXIS_COUNT; axis++) {
split_axis = order[axis];
int count = 0;
@@ -82,7 +86,7 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
// best axis
int best_axis = 0;
int best_min = min_group_size[0];
- for (int axis = 1; axis < 3; axis++) {
+ for (int axis = 1; axis < Point::AXIS_COUNT; axis++) {
if (min_group_size[axis] > best_min) {
best_min = min_group_size[axis];
best_axis = axis;
diff --git a/core/math/bvh_tree.h b/core/math/bvh_tree.h
index 3169d31ec7..c948d83456 100644
--- a/core/math/bvh_tree.h
+++ b/core/math/bvh_tree.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index 8066a59281..b968156887 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,17 +35,17 @@
float CameraMatrix::determinant() const {
return matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0] - matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0] -
- matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0] + matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0] +
- matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0] - matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0] -
- matrix[0][3] * matrix[1][2] * matrix[2][0] * matrix[3][1] + matrix[0][2] * matrix[1][3] * matrix[2][0] * matrix[3][1] +
- matrix[0][3] * matrix[1][0] * matrix[2][2] * matrix[3][1] - matrix[0][0] * matrix[1][3] * matrix[2][2] * matrix[3][1] -
- matrix[0][2] * matrix[1][0] * matrix[2][3] * matrix[3][1] + matrix[0][0] * matrix[1][2] * matrix[2][3] * matrix[3][1] +
- matrix[0][3] * matrix[1][1] * matrix[2][0] * matrix[3][2] - matrix[0][1] * matrix[1][3] * matrix[2][0] * matrix[3][2] -
- matrix[0][3] * matrix[1][0] * matrix[2][1] * matrix[3][2] + matrix[0][0] * matrix[1][3] * matrix[2][1] * matrix[3][2] +
- matrix[0][1] * matrix[1][0] * matrix[2][3] * matrix[3][2] - matrix[0][0] * matrix[1][1] * matrix[2][3] * matrix[3][2] -
- matrix[0][2] * matrix[1][1] * matrix[2][0] * matrix[3][3] + matrix[0][1] * matrix[1][2] * matrix[2][0] * matrix[3][3] +
- matrix[0][2] * matrix[1][0] * matrix[2][1] * matrix[3][3] - matrix[0][0] * matrix[1][2] * matrix[2][1] * matrix[3][3] -
- matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3] + matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3];
+ matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0] + matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0] +
+ matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0] - matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0] -
+ matrix[0][3] * matrix[1][2] * matrix[2][0] * matrix[3][1] + matrix[0][2] * matrix[1][3] * matrix[2][0] * matrix[3][1] +
+ matrix[0][3] * matrix[1][0] * matrix[2][2] * matrix[3][1] - matrix[0][0] * matrix[1][3] * matrix[2][2] * matrix[3][1] -
+ matrix[0][2] * matrix[1][0] * matrix[2][3] * matrix[3][1] + matrix[0][0] * matrix[1][2] * matrix[2][3] * matrix[3][1] +
+ matrix[0][3] * matrix[1][1] * matrix[2][0] * matrix[3][2] - matrix[0][1] * matrix[1][3] * matrix[2][0] * matrix[3][2] -
+ matrix[0][3] * matrix[1][0] * matrix[2][1] * matrix[3][2] + matrix[0][0] * matrix[1][3] * matrix[2][1] * matrix[3][2] +
+ matrix[0][1] * matrix[1][0] * matrix[2][3] * matrix[3][2] - matrix[0][0] * matrix[1][1] * matrix[2][3] * matrix[3][2] -
+ matrix[0][2] * matrix[1][1] * matrix[2][0] * matrix[3][3] + matrix[0][1] * matrix[1][2] * matrix[2][0] * matrix[3][3] +
+ matrix[0][2] * matrix[1][0] * matrix[2][1] * matrix[3][3] - matrix[0][0] * matrix[1][2] * matrix[2][1] * matrix[3][3] -
+ matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3] + matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3];
}
void CameraMatrix::set_identity() {
diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h
index 786d46055a..da1aba7562 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/camera_matrix.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/color.cpp b/core/math/color.cpp
index dc86cacf8f..b06d20b3d3 100644
--- a/core/math/color.cpp
+++ b/core/math/color.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -107,6 +107,39 @@ uint64_t Color::to_rgba64() const {
return c;
}
+String _to_hex(float p_val) {
+ int v = Math::round(p_val * 255);
+ v = CLAMP(v, 0, 255);
+ String ret;
+
+ for (int i = 0; i < 2; i++) {
+ char32_t c[2] = { 0, 0 };
+ int lv = v & 0xF;
+ if (lv < 10) {
+ c[0] = '0' + lv;
+ } else {
+ c[0] = 'a' + lv - 10;
+ }
+
+ v >>= 4;
+ String cs = (const char32_t *)c;
+ ret = cs + ret;
+ }
+
+ return ret;
+}
+
+String Color::to_html(bool p_alpha) const {
+ String txt;
+ txt += _to_hex(r);
+ txt += _to_hex(g);
+ txt += _to_hex(b);
+ if (p_alpha) {
+ txt += _to_hex(a);
+ }
+ return txt;
+}
+
float Color::get_h() const {
float min = MIN(r, g);
min = MIN(min, b);
@@ -249,20 +282,6 @@ Color Color::hex64(uint64_t p_hex) {
return Color(r, g, b, a);
}
-Color Color::from_rgbe9995(uint32_t p_rgbe) {
- float r = p_rgbe & 0x1ff;
- float g = (p_rgbe >> 9) & 0x1ff;
- float b = (p_rgbe >> 18) & 0x1ff;
- float e = (p_rgbe >> 27);
- float m = Math::pow(2, e - 15.0 - 9.0);
-
- float rd = r * m;
- float gd = g * m;
- float bd = b * m;
-
- return Color(rd, gd, bd, 1.0f);
-}
-
static int _parse_col4(const String &p_str, int p_ofs) {
char character = p_str[p_ofs];
@@ -428,43 +447,24 @@ Color Color::from_string(const String &p_string, const Color &p_default) {
}
}
-String _to_hex(float p_val) {
- int v = Math::round(p_val * 255);
- v = CLAMP(v, 0, 255);
- String ret;
-
- for (int i = 0; i < 2; i++) {
- char32_t c[2] = { 0, 0 };
- int lv = v & 0xF;
- if (lv < 10) {
- c[0] = '0' + lv;
- } else {
- c[0] = 'a' + lv - 10;
- }
-
- v >>= 4;
- String cs = (const char32_t *)c;
- ret = cs + ret;
- }
-
- return ret;
+Color Color::from_hsv(float p_h, float p_s, float p_v, float p_alpha) {
+ Color c;
+ c.set_hsv(p_h, p_s, p_v, p_alpha);
+ return c;
}
-String Color::to_html(bool p_alpha) const {
- String txt;
- txt += _to_hex(r);
- txt += _to_hex(g);
- txt += _to_hex(b);
- if (p_alpha) {
- txt += _to_hex(a);
- }
- return txt;
-}
+Color Color::from_rgbe9995(uint32_t p_rgbe) {
+ float r = p_rgbe & 0x1ff;
+ float g = (p_rgbe >> 9) & 0x1ff;
+ float b = (p_rgbe >> 18) & 0x1ff;
+ float e = (p_rgbe >> 27);
+ float m = Math::pow(2, e - 15.0 - 9.0);
-Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
- Color c;
- c.set_hsv(p_h, p_s, p_v, p_a);
- return c;
+ float rd = r * m;
+ float gd = g * m;
+ float bd = b * m;
+
+ return Color(rd, gd, bd, 1.0f);
}
Color::operator String() const {
diff --git a/core/math/color.h b/core/math/color.h
index a95dbf4f60..6c09f7941c 100644
--- a/core/math/color.h
+++ b/core/math/color.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -51,6 +51,7 @@ struct Color {
uint64_t to_rgba64() const;
uint64_t to_argb64() const;
uint64_t to_abgr64() const;
+ String to_html(bool p_alpha = true) const;
float get_h() const;
float get_s() const;
float get_v() const;
@@ -93,6 +94,10 @@ struct Color {
void invert();
Color inverted() const;
+ _FORCE_INLINE_ float get_luminance() const {
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
+ }
+
_FORCE_INLINE_ Color lerp(const Color &p_to, float p_weight) const {
Color res = *this;
@@ -189,8 +194,7 @@ struct Color {
static String get_named_color_name(int p_idx);
static Color get_named_color(int p_idx);
static Color from_string(const String &p_string, const Color &p_default);
- String to_html(bool p_alpha = true) const;
- Color from_hsv(float p_h, float p_s, float p_v, float p_a) const;
+ static Color from_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0);
static Color from_rgbe9995(uint32_t p_rgbe);
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
diff --git a/core/math/convex_hull.cpp b/core/math/convex_hull.cpp
index f67035c803..912ffb8b16 100644
--- a/core/math/convex_hull.cpp
+++ b/core/math/convex_hull.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -265,8 +265,7 @@ public:
}
int32_t get_sign() const {
- return ((int64_t)high < 0) ? -1 : (high || low) ? 1 :
- 0;
+ return ((int64_t)high < 0) ? -1 : ((high || low) ? 1 : 0);
}
bool operator<(const Int128 &b) const {
@@ -594,8 +593,6 @@ private:
IntermediateHull() {
}
-
- void print();
};
enum Orientation { NONE,
@@ -609,9 +606,9 @@ private:
PagedAllocator<Face> face_pool;
LocalVector<Vertex *> original_vertices;
int32_t merge_stamp = 0;
- int32_t min_axis = 0;
- int32_t med_axis = 0;
- int32_t max_axis = 0;
+ Vector3::Axis min_axis = Vector3::Axis::AXIS_X;
+ Vector3::Axis med_axis = Vector3::Axis::AXIS_X;
+ Vector3::Axis max_axis = Vector3::Axis::AXIS_X;
int32_t used_edge_pairs = 0;
int32_t max_used_edge_pairs = 0;
@@ -737,8 +734,6 @@ int32_t ConvexHullInternal::Rational64::compare(const Rational64 &b) const {
return 0;
}
- // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
-
#ifdef USE_X86_64_ASM
int32_t result;
@@ -759,10 +754,9 @@ int32_t ConvexHullInternal::Rational64::compare(const Rational64 &b) const {
: "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
: "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
: "%rdx", "cc");
- return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
- // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
- :
- 0;
+ // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
+ // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
+ return result ? result ^ sign : 0;
#else
@@ -795,8 +789,7 @@ int32_t ConvexHullInternal::Rational128::compare(const Rational128 &b) const {
int32_t ConvexHullInternal::Rational128::compare(int64_t b) const {
if (is_int_64) {
int64_t a = sign * (int64_t)numerator.low;
- return (a > b) ? 1 : (a < b) ? -1 :
- 0;
+ return (a > b) ? 1 : ((a < b) ? -1 : 0);
}
if (b > 0) {
if (sign <= 0) {
@@ -1448,8 +1441,7 @@ void ConvexHullInternal::merge(IntermediateHull &p_h0, IntermediateHull &p_h1) {
c1->edges = e;
return;
} else {
- int32_t cmp = !min0 ? 1 : !min1 ? -1 :
- min_cot0.compare(min_cot1);
+ int32_t cmp = !min0 ? 1 : (!min1 ? -1 : min_cot0.compare(min_cot1));
#ifdef DEBUG_CONVEX_HULL
printf(" -> Result %d\n", cmp);
#endif
@@ -1593,12 +1585,12 @@ void ConvexHullInternal::compute(const Vector3 *p_coords, int32_t p_count) {
}
Vector3 s = aabb.size;
- max_axis = s.max_axis();
- min_axis = s.min_axis();
+ max_axis = s.max_axis_index();
+ min_axis = s.min_axis_index();
if (min_axis == max_axis) {
- min_axis = (max_axis + 1) % 3;
+ min_axis = Vector3::Axis((max_axis + 1) % 3);
}
- med_axis = 3 - max_axis - min_axis;
+ med_axis = Vector3::Axis(3 - max_axis - min_axis);
s /= real_t(10216);
if (((med_axis + 1) % 3) != max_axis) {
@@ -1696,7 +1688,7 @@ real_t ConvexHullInternal::shrink(real_t p_amount, real_t p_clamp_amount) {
while (stack.size() > 0) {
Vertex *v = stack[stack.size() - 1];
- stack.remove(stack.size() - 1);
+ stack.remove_at(stack.size() - 1);
Edge *e = v->edges;
if (e) {
do {
diff --git a/core/math/convex_hull.h b/core/math/convex_hull.h
index 806c6cc3fb..bd86fe0eba 100644
--- a/core/math/convex_hull.h
+++ b/core/math/convex_hull.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/delaunay_2d.h b/core/math/delaunay_2d.h
index 95064e5700..08f5df8472 100644
--- a/core/math/delaunay_2d.h
+++ b/core/math/delaunay_2d.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -101,7 +101,7 @@ public:
}
float delta_max = MAX(rect.size.width, rect.size.height);
- Vector2 center = rect.position + rect.size * 0.5;
+ Vector2 center = rect.get_center();
points.push_back(Vector2(center.x - 20 * delta_max, center.y - delta_max));
points.push_back(Vector2(center.x, center.y + 20 * delta_max));
@@ -123,7 +123,7 @@ public:
for (int j = 0; j < triangles.size(); j++) {
if (triangles[j].bad) {
- triangles.remove(j);
+ triangles.remove_at(j);
j--;
}
}
@@ -154,7 +154,7 @@ public:
}
}
if (invalid) {
- triangles.remove(i);
+ triangles.remove_at(i);
i--;
}
}
diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h
index 81adf4d19a..7ad5f76645 100644
--- a/core/math/delaunay_3d.h
+++ b/core/math/delaunay_3d.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/disjoint_set.h b/core/math/disjoint_set.h
index b155412f64..8657dc068e 100644
--- a/core/math/disjoint_set.h
+++ b/core/math/disjoint_set.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,10 +34,6 @@
#include "core/templates/map.h"
#include "core/templates/vector.h"
-/**
- @author Marios Staikopoulos <marios@staik.net>
-*/
-
/* This DisjointSet class uses Find with path compression and Union by rank */
template <typename T, class C = Comparator<T>, class AL = DefaultAllocator>
class DisjointSet {
diff --git a/core/math/dynamic_bvh.cpp b/core/math/dynamic_bvh.cpp
index f3fb473981..7aeb2aaaac 100644
--- a/core/math/dynamic_bvh.cpp
+++ b/core/math/dynamic_bvh.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/dynamic_bvh.h b/core/math/dynamic_bvh.h
index 0b6286cd9d..3041cdf268 100644
--- a/core/math/dynamic_bvh.h
+++ b/core/math/dynamic_bvh.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 05f2c8dac9..4f8e79038f 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -410,6 +410,14 @@ Error Expression::_get_token(Token &r_token) {
} else if (id == "self") {
r_token.type = TK_SELF;
} else {
+ for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+ if (id == Variant::get_type_name(Variant::Type(i))) {
+ r_token.type = TK_BASIC_TYPE;
+ r_token.value = i;
+ return OK;
+ }
+ }
+
if (Variant::has_utility_function(id)) {
r_token.type = TK_BUILTIN_FUNC;
r_token.value = id;
@@ -1087,7 +1095,7 @@ Expression::ENode *Expression::_parse_expression() {
op->nodes[1] = nullptr;
expression.write[i].is_op = false;
expression.write[i].node = op;
- expression.remove(i + 1);
+ expression.remove_at(i + 1);
}
} else {
@@ -1119,8 +1127,8 @@ Expression::ENode *Expression::_parse_expression() {
//replace all 3 nodes by this operator and make it an expression
expression.write[next_op - 1].node = op;
- expression.remove(next_op);
- expression.remove(next_op);
+ expression.remove_at(next_op);
+ expression.remove_at(next_op);
}
}
diff --git a/core/math/expression.h b/core/math/expression.h
index aecf662d0a..9b87bdd6ec 100644
--- a/core/math/expression.h
+++ b/core/math/expression.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/face3.cpp b/core/math/face3.cpp
index 9af3f868d2..ba10b50465 100644
--- a/core/math/face3.cpp
+++ b/core/math/face3.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -151,8 +151,8 @@ Face3::Side Face3::get_side_of(const Face3 &p_face, ClockDirection p_clock_dir)
}
Vector3 Face3::get_random_point_inside() const {
- real_t a = Math::random(0, 1);
- real_t b = Math::random(0, 1);
+ real_t a = Math::random(0.0, 1.0);
+ real_t b = Math::random(0.0, 1.0);
if (a > b) {
SWAP(a, b);
}
@@ -229,7 +229,7 @@ bool Face3::intersects_aabb(const AABB &p_aabb) const {
axis.normalize();
real_t minA, maxA, minB, maxB;
- p_aabb.project_range_in_plane(Plane(axis, 0), minA, maxA);
+ p_aabb.project_range_in_plane(Plane(axis), minA, maxA);
project_range(axis, Transform3D(), minB, maxB);
if (maxA < minB || maxB < minA) {
diff --git a/core/math/face3.h b/core/math/face3.h
index 9e9026e54e..5a34858ccb 100644
--- a/core/math/face3.h
+++ b/core/math/face3.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -48,13 +48,13 @@ public:
Vector3 vertex[3];
/**
- *
- * @param p_plane plane used to split the face
- * @param p_res array of at least 3 faces, amount used in function return
- * @param p_is_point_over array of at least 3 booleans, determining which face is over the plane, amount used in function return
- * @param _epsilon constant used for numerical error rounding, to add "thickness" to the plane (so coplanar points can happen)
- * @return amount of faces generated by the split, either 0 (means no split possible), 2 or 3
- */
+ *
+ * @param p_plane plane used to split the face
+ * @param p_res array of at least 3 faces, amount used in function return
+ * @param p_is_point_over array of at least 3 booleans, determining which face is over the plane, amount used in function return
+ * @param _epsilon constant used for numerical error rounding, to add "thickness" to the plane (so coplanar points can happen)
+ * @return amount of faces generated by the split, either 0 (means no split possible), 2 or 3
+ */
int split_by_plane(const Plane &p_plane, Face3 *p_res, bool *p_is_point_over) const;
diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp
index 7b2630b4ff..9fa45a3363 100644
--- a/core/math/geometry_2d.cpp
+++ b/core/math/geometry_2d.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/geometry_2d.h b/core/math/geometry_2d.h
index 8e5830f9b3..7385dba438 100644
--- a/core/math/geometry_2d.h
+++ b/core/math/geometry_2d.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,8 +37,6 @@
#include "core/templates/vector.h"
class Geometry2D {
- Geometry2D();
-
public:
static real_t get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2, Vector2 &c1, Vector2 &c2) {
Vector2 d1 = q1 - p1; // Direction vector of segment S1.
@@ -183,8 +181,7 @@ public:
D = Vector2(D.x * Bn.x + D.y * Bn.y, D.y * Bn.x - D.x * Bn.y);
// Fail if C x B and D x B have the same sign (segments don't intersect).
- // (equivalent to condition (C.y < 0 && D.y < CMP_EPSILON) || (C.y > 0 && D.y > CMP_EPSILON))
- if (C.y * D.y > CMP_EPSILON) {
+ if ((C.y < -CMP_EPSILON && D.y < -CMP_EPSILON) || (C.y > CMP_EPSILON && D.y > CMP_EPSILON)) {
return false;
}
diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp
index 6628b760e0..98a2c27d93 100644
--- a/core/math/geometry_3d.cpp
+++ b/core/math/geometry_3d.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -644,14 +644,15 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes
Vector3 right = p.normal.cross(ref).normalized();
Vector3 up = p.normal.cross(right).normalized();
- Vector<Vector3> vertices;
-
Vector3 center = p.center();
+
// make a quad clockwise
- vertices.push_back(center - up * subplane_size + right * subplane_size);
- vertices.push_back(center - up * subplane_size - right * subplane_size);
- vertices.push_back(center + up * subplane_size - right * subplane_size);
- vertices.push_back(center + up * subplane_size + right * subplane_size);
+ Vector<Vector3> vertices = {
+ center - up * subplane_size + right * subplane_size,
+ center - up * subplane_size - right * subplane_size,
+ center + up * subplane_size - right * subplane_size,
+ center + up * subplane_size + right * subplane_size
+ };
for (int j = 0; j < p_planes.size(); j++) {
if (j == i) {
@@ -762,14 +763,14 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes
}
Vector<Plane> Geometry3D::build_box_planes(const Vector3 &p_extents) {
- Vector<Plane> planes;
-
- planes.push_back(Plane(Vector3(1, 0, 0), p_extents.x));
- planes.push_back(Plane(Vector3(-1, 0, 0), p_extents.x));
- planes.push_back(Plane(Vector3(0, 1, 0), p_extents.y));
- planes.push_back(Plane(Vector3(0, -1, 0), p_extents.y));
- planes.push_back(Plane(Vector3(0, 0, 1), p_extents.z));
- planes.push_back(Plane(Vector3(0, 0, -1), p_extents.z));
+ Vector<Plane> planes = {
+ Plane(Vector3(1, 0, 0), p_extents.x),
+ Plane(Vector3(-1, 0, 0), p_extents.x),
+ Plane(Vector3(0, 1, 0), p_extents.y),
+ Plane(Vector3(0, -1, 0), p_extents.y),
+ Plane(Vector3(0, 0, 1), p_extents.z),
+ Plane(Vector3(0, 0, -1), p_extents.z)
+ };
return planes;
}
@@ -819,11 +820,9 @@ Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p
planes.push_back(Plane(normal, p_radius));
for (int j = 1; j <= p_lats; j++) {
- // FIXME: This is stupid.
- Vector3 angle = normal.lerp(axis, j / (real_t)p_lats).normalized();
- Vector3 pos = angle * p_radius;
- planes.push_back(Plane(pos, angle));
- planes.push_back(Plane(pos * axis_neg, angle * axis_neg));
+ Vector3 plane_normal = normal.lerp(axis, j / (real_t)p_lats).normalized();
+ planes.push_back(Plane(plane_normal, p_radius));
+ planes.push_back(Plane(plane_normal * axis_neg, p_radius));
}
}
@@ -852,10 +851,10 @@ Vector<Plane> Geometry3D::build_capsule_planes(real_t p_radius, real_t p_height,
planes.push_back(Plane(normal, p_radius));
for (int j = 1; j <= p_lats; j++) {
- Vector3 angle = normal.lerp(axis, j / (real_t)p_lats).normalized();
- Vector3 pos = axis * p_height * 0.5 + angle * p_radius;
- planes.push_back(Plane(pos, angle));
- planes.push_back(Plane(pos * axis_neg, angle * axis_neg));
+ Vector3 plane_normal = normal.lerp(axis, j / (real_t)p_lats).normalized();
+ Vector3 position = axis * p_height * 0.5 + plane_normal * p_radius;
+ planes.push_back(Plane(plane_normal, position));
+ planes.push_back(Plane(plane_normal * axis_neg, position * axis_neg));
}
}
diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h
index 766689e222..0f6ab5c716 100644
--- a/core/math/geometry_3d.h
+++ b/core/math/geometry_3d.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,8 +36,6 @@
#include "core/templates/vector.h"
class Geometry3D {
- Geometry3D();
-
public:
static void get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2, Vector3 &c1, Vector3 &c2) {
// Do the function 'd' as defined by pb. I think it's a dot product of some sort.
diff --git a/core/math/math_defs.h b/core/math/math_defs.h
index c3a8f910c0..b8b82f2ff4 100644
--- a/core/math/math_defs.h
+++ b/core/math/math_defs.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,37 +68,38 @@ enum Orientation {
VERTICAL
};
-enum HAlign {
- HALIGN_LEFT,
- HALIGN_CENTER,
- HALIGN_RIGHT,
- HALIGN_FILL,
+enum HorizontalAlignment {
+ HORIZONTAL_ALIGNMENT_LEFT,
+ HORIZONTAL_ALIGNMENT_CENTER,
+ HORIZONTAL_ALIGNMENT_RIGHT,
+ HORIZONTAL_ALIGNMENT_FILL,
};
-enum VAlign {
- VALIGN_TOP,
- VALIGN_CENTER,
- VALIGN_BOTTOM
+enum VerticalAlignment {
+ VERTICAL_ALIGNMENT_TOP,
+ VERTICAL_ALIGNMENT_CENTER,
+ VERTICAL_ALIGNMENT_BOTTOM,
+ VERTICAL_ALIGNMENT_FILL,
};
-enum InlineAlign {
+enum InlineAlignment {
// Image alignment points.
- INLINE_ALIGN_TOP_TO = 0b0000,
- INLINE_ALIGN_CENTER_TO = 0b0001,
- INLINE_ALIGN_BOTTOM_TO = 0b0010,
- INLINE_ALIGN_IMAGE_MASK = 0b0011,
+ INLINE_ALIGNMENT_TOP_TO = 0b0000,
+ INLINE_ALIGNMENT_CENTER_TO = 0b0001,
+ INLINE_ALIGNMENT_BOTTOM_TO = 0b0010,
+ INLINE_ALIGNMENT_IMAGE_MASK = 0b0011,
// Text alignment points.
- INLINE_ALIGN_TO_TOP = 0b0000,
- INLINE_ALIGN_TO_CENTER = 0b0100,
- INLINE_ALIGN_TO_BASELINE = 0b1000,
- INLINE_ALIGN_TO_BOTTOM = 0b1100,
- INLINE_ALIGN_TEXT_MASK = 0b1100,
+ INLINE_ALIGNMENT_TO_TOP = 0b0000,
+ INLINE_ALIGNMENT_TO_CENTER = 0b0100,
+ INLINE_ALIGNMENT_TO_BASELINE = 0b1000,
+ INLINE_ALIGNMENT_TO_BOTTOM = 0b1100,
+ INLINE_ALIGNMENT_TEXT_MASK = 0b1100,
// Presets.
- INLINE_ALIGN_TOP = INLINE_ALIGN_TOP_TO | INLINE_ALIGN_TO_TOP,
- INLINE_ALIGN_CENTER = INLINE_ALIGN_CENTER_TO | INLINE_ALIGN_TO_CENTER,
- INLINE_ALIGN_BOTTOM = INLINE_ALIGN_BOTTOM_TO | INLINE_ALIGN_TO_BOTTOM
+ INLINE_ALIGNMENT_TOP = INLINE_ALIGNMENT_TOP_TO | INLINE_ALIGNMENT_TO_TOP,
+ INLINE_ALIGNMENT_CENTER = INLINE_ALIGNMENT_CENTER_TO | INLINE_ALIGNMENT_TO_CENTER,
+ INLINE_ALIGNMENT_BOTTOM = INLINE_ALIGNMENT_BOTTOM_TO | INLINE_ALIGNMENT_TO_BOTTOM
};
enum Side {
@@ -116,10 +117,10 @@ enum Corner {
};
/**
- * The "Real" type is an abstract type used for real numbers, such as 1.5,
- * in contrast to integer numbers. Precision can be controlled with the
- * presence or absence of the REAL_T_IS_DOUBLE define.
- */
+ * The "Real" type is an abstract type used for real numbers, such as 1.5,
+ * in contrast to integer numbers. Precision can be controlled with the
+ * presence or absence of the REAL_T_IS_DOUBLE define.
+ */
#ifdef REAL_T_IS_DOUBLE
typedef double real_t;
#else
diff --git a/core/math/math_fieldwise.cpp b/core/math/math_fieldwise.cpp
index 570c57e254..1717ecd74b 100644
--- a/core/math/math_fieldwise.cpp
+++ b/core/math/math_fieldwise.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/math_fieldwise.h b/core/math/math_fieldwise.h
index fe44d09900..f8a5b7cbb2 100644
--- a/core/math/math_fieldwise.h
+++ b/core/math/math_fieldwise.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index bbed257f60..614828d7cb 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -53,6 +53,10 @@ uint32_t Math::rand() {
return default_rand.rand();
}
+double Math::randfn(double mean, double deviation) {
+ return default_rand.randfn(mean, deviation);
+}
+
int Math::step_decimals(double p_step) {
static const int maxn = 10;
static const double sd[maxn] = {
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 4e4f566517..f3d10c3f0d 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -159,7 +159,7 @@ public:
} ieee754;
ieee754.f = p_val;
return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000 &&
- ((unsigned)ieee754.u == 0);
+ ((unsigned)ieee754.u == 0);
#else
return isinf(p_val);
#endif
@@ -266,8 +266,8 @@ public:
float s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0f, 1.0f);
return s * s * (3.0f - 2.0f * s);
}
- static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; }
- static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; }
+ static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; }
+ static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; }
static _ALWAYS_INLINE_ double linear2db(double p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; }
static _ALWAYS_INLINE_ float linear2db(float p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; }
@@ -291,6 +291,19 @@ public:
return is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range));
}
+ static _ALWAYS_INLINE_ float fract(float value) {
+ return value - floor(value);
+ }
+ static _ALWAYS_INLINE_ double fract(double value) {
+ return value - floor(value);
+ }
+ static _ALWAYS_INLINE_ float pingpong(float value, float length) {
+ return (length != 0.0f) ? abs(fract((value - length) / (length * 2.0f)) * length * 2.0f - length) : 0.0f;
+ }
+ static _ALWAYS_INLINE_ double pingpong(double value, double length) {
+ return (length != 0.0) ? abs(fract((value - length) / (length * 2.0)) * length * 2.0 - length) : 0.0;
+ }
+
// double only, as these functions are mainly used by the editor and not performance-critical,
static double ease(double p_x, double p_c);
static int step_decimals(double p_step);
@@ -305,6 +318,7 @@ public:
static uint32_t rand();
static _ALWAYS_INLINE_ double randd() { return (double)rand() / (double)Math::RANDOM_32BIT_MAX; }
static _ALWAYS_INLINE_ float randf() { return (float)rand() / (float)Math::RANDOM_32BIT_MAX; }
+ static double randfn(double mean, double deviation);
static double random(double from, double to);
static float random(float from, float to);
@@ -461,7 +475,7 @@ public:
mantissa = 0;
}
hf = (((uint16_t)sign) << 15) | (uint16_t)((0x1F << 10)) |
- (uint16_t)(mantissa >> 13);
+ (uint16_t)(mantissa >> 13);
}
// check if exponent is <= -15
else if (exp <= 0x38000000) {
@@ -474,8 +488,8 @@ public:
hf = 0; //denormals do not work for 3D, convert to zero
} else {
hf = (((uint16_t)sign) << 15) |
- (uint16_t)((exp - 0x38000000) >> 13) |
- (uint16_t)(mantissa >> 13);
+ (uint16_t)((exp - 0x38000000) >> 13) |
+ (uint16_t)(mantissa >> 13);
}
return hf;
diff --git a/core/math/octree.h b/core/math/octree.h
index 493a63aa2e..23ba4c1aa3 100644
--- a/core/math/octree.h
+++ b/core/math/octree.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -103,7 +103,7 @@ private:
Octant *parent = nullptr;
Octant *children[8] = { nullptr };
- int children_count = 0; // cache for amount of childrens (fast check for removal)
+ int children_count = 0; // cache for amount of children (fast check for removal)
int parent_index = -1; // cache for parent index (fast check for removal)
List<Element *, AL> pairable_elements;
diff --git a/core/math/plane.cpp b/core/math/plane.cpp
index 3c78b55b90..8bd4b5ef4f 100644
--- a/core/math/plane.cpp
+++ b/core/math/plane.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -88,7 +88,7 @@ bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r
*r_result = ((vec3_cross(normal1, normal2) * p_plane0.d) +
(vec3_cross(normal2, normal0) * p_plane1.d) +
(vec3_cross(normal0, normal1) * p_plane2.d)) /
- denom;
+ denom;
}
return true;
diff --git a/core/math/plane.h b/core/math/plane.h
index 2267b28c53..bac946502b 100644
--- a/core/math/plane.h
+++ b/core/math/plane.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -85,8 +85,8 @@ public:
normal(p_a, p_b, p_c),
d(p_d) {}
- _FORCE_INLINE_ Plane(const Vector3 &p_normal, real_t p_d);
- _FORCE_INLINE_ Plane(const Vector3 &p_point, const Vector3 &p_normal);
+ _FORCE_INLINE_ Plane(const Vector3 &p_normal, real_t p_d = 0.0);
+ _FORCE_INLINE_ Plane(const Vector3 &p_normal, const Vector3 &p_point);
_FORCE_INLINE_ Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir = CLOCKWISE);
};
@@ -109,7 +109,7 @@ Plane::Plane(const Vector3 &p_normal, real_t p_d) :
d(p_d) {
}
-Plane::Plane(const Vector3 &p_point, const Vector3 &p_normal) :
+Plane::Plane(const Vector3 &p_normal, const Vector3 &p_point) :
normal(p_normal),
d(p_normal.dot(p_point)) {
}
diff --git a/core/math/quaternion.cpp b/core/math/quaternion.cpp
index 3f1d2c58e5..2ce603cb13 100644
--- a/core/math/quaternion.cpp
+++ b/core/math/quaternion.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -44,7 +44,7 @@ real_t Quaternion::angle_to(const Quaternion &p_to) const {
// This implementation uses XYZ convention (Z is the first rotation).
Vector3 Quaternion::get_euler_xyz() const {
Basis m(*this);
- return m.get_euler_xyz();
+ return m.get_euler(Basis::EULER_ORDER_XYZ);
}
// get_euler_yxz returns a vector containing the Euler angles in the format
@@ -56,7 +56,7 @@ Vector3 Quaternion::get_euler_yxz() const {
ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized.");
#endif
Basis m(*this);
- return m.get_euler_yxz();
+ return m.get_euler(Basis::EULER_ORDER_YXZ);
}
void Quaternion::operator*=(const Quaternion &p_q) {
@@ -189,6 +189,15 @@ Quaternion::operator String() const {
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ", " + String::num_real(w, false) + ")";
}
+Vector3 Quaternion::get_axis() const {
+ real_t r = ((real_t)1) / Math::sqrt(1 - w * w);
+ return Vector3(x * r, y * r, z * r);
+}
+
+float Quaternion::get_angle() const {
+ return 2 * Math::acos(w);
+}
+
Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) {
#ifdef MATH_CHECKS
ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
diff --git a/core/math/quaternion.h b/core/math/quaternion.h
index 35324323b3..cf3762e090 100644
--- a/core/math/quaternion.h
+++ b/core/math/quaternion.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -72,6 +72,9 @@ public:
Quaternion slerpni(const Quaternion &p_to, const real_t &p_weight) const;
Quaternion cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
+ Vector3 get_axis() const;
+ float get_angle() const;
+
_FORCE_INLINE_ void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
r_angle = 2 * Math::acos(w);
real_t r = ((real_t)1) / Math::sqrt(1 - w * w);
@@ -83,13 +86,6 @@ public:
void operator*=(const Quaternion &p_q);
Quaternion operator*(const Quaternion &p_q) const;
- Quaternion operator*(const Vector3 &v) const {
- return Quaternion(w * v.x + y * v.z - z * v.y,
- w * v.y + z * v.x - x * v.z,
- w * v.z + x * v.y - y * v.x,
- -x * v.x - y * v.y - z * v.z);
- }
-
_FORCE_INLINE_ Vector3 xform(const Vector3 &v) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized.");
@@ -138,12 +134,11 @@ public:
w(p_q.w) {
}
- Quaternion &operator=(const Quaternion &p_q) {
+ void operator=(const Quaternion &p_q) {
x = p_q.x;
y = p_q.y;
z = p_q.z;
w = p_q.w;
- return *this;
}
Quaternion(const Vector3 &v0, const Vector3 &v1) // shortest arc
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index 0960fe19a6..8e87d44b7f 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -265,8 +265,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
//create new faces from horizon edges
List<List<Face>::Element *> new_faces; //new faces
- for (Map<Edge, FaceConnect>::Element *E = lit_edges.front(); E; E = E->next()) {
- FaceConnect &fc = E->get();
+ for (KeyValue<Edge, FaceConnect> &E : lit_edges) {
+ FaceConnect &fc = E.value;
if (fc.left && fc.right) {
continue; //edge is uninteresting, not on horizon
}
@@ -275,8 +275,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
Face face;
face.vertices[0] = f.points_over[next];
- face.vertices[1] = E->key().vertices[0];
- face.vertices[2] = E->key().vertices[1];
+ face.vertices[1] = E.key.vertices[0];
+ face.vertices[2] = E.key.vertices[1];
Plane p(p_points[face.vertices[0]], p_points[face.vertices[1]], p_points[face.vertices[2]]);
@@ -418,13 +418,13 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
}
// remove all edge connections to this face
- for (Map<Edge, RetFaceConnect>::Element *G = ret_edges.front(); G; G = G->next()) {
- if (G->get().left == O) {
- G->get().left = nullptr;
+ for (KeyValue<Edge, RetFaceConnect> &G : ret_edges) {
+ if (G.value.left == O) {
+ G.value.left = nullptr;
}
- if (G->get().right == O) {
- G->get().right = nullptr;
+ if (G.value.right == O) {
+ G.value.right = nullptr;
}
}
@@ -444,10 +444,10 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
}
r_mesh.edges.resize(ret_edges.size());
idx = 0;
- for (Map<Edge, RetFaceConnect>::Element *E = ret_edges.front(); E; E = E->next()) {
+ for (const KeyValue<Edge, RetFaceConnect> &E : ret_edges) {
Geometry3D::MeshData::Edge e;
- e.a = E->key().vertices[0];
- e.b = E->key().vertices[1];
+ e.a = E.key.vertices[0];
+ e.b = E.key.vertices[1];
r_mesh.edges.write[idx++] = e;
}
diff --git a/core/math/quick_hull.h b/core/math/quick_hull.h
index 48ea139cc9..b8d813c979 100644
--- a/core/math/quick_hull.h
+++ b/core/math/quick_hull.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/random_number_generator.cpp b/core/math/random_number_generator.cpp
index b40d010219..31eeed4399 100644
--- a/core/math/random_number_generator.cpp
+++ b/core/math/random_number_generator.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/random_number_generator.h b/core/math/random_number_generator.h
index 06cd3999f3..9352bae0a6 100644
--- a/core/math/random_number_generator.h
+++ b/core/math/random_number_generator.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/random_pcg.cpp b/core/math/random_pcg.cpp
index 681c2a9717..c69986e6df 100644
--- a/core/math/random_pcg.cpp
+++ b/core/math/random_pcg.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h
index 5a03b758ce..974dbbfc2e 100644
--- a/core/math/random_pcg.h
+++ b/core/math/random_pcg.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/rect2.cpp b/core/math/rect2.cpp
index f64bf560c8..9047c19434 100644
--- a/core/math/rect2.cpp
+++ b/core/math/rect2.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,6 +35,11 @@ bool Rect2::is_equal_approx(const Rect2 &p_rect) const {
}
bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0)) {
+ ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
+ }
+#endif
real_t min = 0, max = 1;
int axis = 0;
real_t sign = 0;
@@ -95,6 +100,11 @@ bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2
}
bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
+ ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
+ }
+#endif
//SAT intersection between local and transformed rect2
Vector2 xf_points[4] = {
diff --git a/core/math/rect2.h b/core/math/rect2.h
index ab0b489b4a..1f14a01103 100644
--- a/core/math/rect2.h
+++ b/core/math/rect2.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,7 +46,14 @@ struct Rect2 {
real_t get_area() const { return size.width * size.height; }
+ _FORCE_INLINE_ Vector2 get_center() const { return position + (size * 0.5); }
+
inline bool intersects(const Rect2 &p_rect, const bool p_include_borders = false) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
+ ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
+ }
+#endif
if (p_include_borders) {
if (position.x > (p_rect.position.x + p_rect.size.width)) {
return false;
@@ -79,6 +86,11 @@ struct Rect2 {
}
inline real_t distance_to(const Vector2 &p_point) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0)) {
+ ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
+ }
+#endif
real_t dist = 0.0;
bool inside = true;
@@ -115,9 +127,14 @@ struct Rect2 {
bool intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos = nullptr, Point2 *r_normal = nullptr) const;
inline bool encloses(const Rect2 &p_rect) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
+ ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
+ }
+#endif
return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
- ((p_rect.position.x + p_rect.size.x) <= (position.x + size.x)) &&
- ((p_rect.position.y + p_rect.size.y) <= (position.y + size.y));
+ ((p_rect.position.x + p_rect.size.x) <= (position.x + size.x)) &&
+ ((p_rect.position.y + p_rect.size.y) <= (position.y + size.y));
}
_FORCE_INLINE_ bool has_no_area() const {
@@ -145,7 +162,11 @@ struct Rect2 {
}
inline Rect2 merge(const Rect2 &p_rect) const { ///< return a merged rect
-
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
+ ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
+ }
+#endif
Rect2 new_rect;
new_rect.position.x = MIN(p_rect.position.x, position.x);
@@ -159,6 +180,11 @@ struct Rect2 {
return new_rect;
}
inline bool has_point(const Point2 &p_point) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0)) {
+ ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
+ }
+#endif
if (p_point.x < position.x) {
return false;
}
@@ -181,6 +207,11 @@ struct Rect2 {
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
inline Rect2 grow(real_t p_amount) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0)) {
+ ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
+ }
+#endif
Rect2 g = *this;
g.grow_by(p_amount);
return g;
@@ -207,6 +238,11 @@ struct Rect2 {
}
inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0)) {
+ ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
+ }
+#endif
Rect2 g = *this;
g.position.x -= p_left;
g.position.y -= p_top;
@@ -223,7 +259,11 @@ struct Rect2 {
}
inline void expand_to(const Vector2 &p_vector) { //in place function for speed
-
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0)) {
+ ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
+ }
+#endif
Vector2 begin = position;
Vector2 end = position + size;
@@ -255,11 +295,11 @@ struct Rect2 {
return Vector2(
(p_normal.x > 0) ? -half_extents.x : half_extents.x,
(p_normal.y > 0) ? -half_extents.y : half_extents.y) +
- ofs;
+ ofs;
}
_FORCE_INLINE_ bool intersects_filled_polygon(const Vector2 *p_points, int p_point_count) const {
- Vector2 center = position + size * 0.5;
+ Vector2 center = get_center();
int side_plus = 0;
int side_minus = 0;
Vector2 end = position + size;
@@ -344,7 +384,14 @@ struct Rect2i {
int get_area() const { return size.width * size.height; }
+ _FORCE_INLINE_ Vector2i get_center() const { return position + (size / 2); }
+
inline bool intersects(const Rect2i &p_rect) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
+ ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
+ }
+#endif
if (position.x > (p_rect.position.x + p_rect.size.width)) {
return false;
}
@@ -362,9 +409,14 @@ struct Rect2i {
}
inline bool encloses(const Rect2i &p_rect) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
+ ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
+ }
+#endif
return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
- ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) &&
- ((p_rect.position.y + p_rect.size.y) < (position.y + size.y));
+ ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) &&
+ ((p_rect.position.y + p_rect.size.y) < (position.y + size.y));
}
_FORCE_INLINE_ bool has_no_area() const {
@@ -385,14 +437,18 @@ struct Rect2i {
Point2i p_rect_end = p_rect.position + p_rect.size;
Point2i end = position + size;
- new_rect.size.x = (int)(MIN(p_rect_end.x, end.x) - new_rect.position.x);
- new_rect.size.y = (int)(MIN(p_rect_end.y, end.y) - new_rect.position.y);
+ new_rect.size.x = MIN(p_rect_end.x, end.x) - new_rect.position.x;
+ new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y;
return new_rect;
}
inline Rect2i merge(const Rect2i &p_rect) const { ///< return a merged rect
-
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
+ ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
+ }
+#endif
Rect2i new_rect;
new_rect.position.x = MIN(p_rect.position.x, position.x);
@@ -406,6 +462,11 @@ struct Rect2i {
return new_rect;
}
bool has_point(const Point2i &p_point) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0)) {
+ ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
+ }
+#endif
if (p_point.x < position.x) {
return false;
}
@@ -427,6 +488,11 @@ struct Rect2i {
bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; }
Rect2i grow(int p_amount) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0)) {
+ ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
+ }
+#endif
Rect2i g = *this;
g.position.x -= p_amount;
g.position.y -= p_amount;
@@ -449,6 +515,11 @@ struct Rect2i {
}
inline Rect2i grow_individual(int p_left, int p_top, int p_right, int p_bottom) const {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0)) {
+ ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
+ }
+#endif
Rect2i g = *this;
g.position.x -= p_left;
g.position.y -= p_top;
@@ -465,6 +536,11 @@ struct Rect2i {
}
inline void expand_to(const Point2i &p_vector) {
+#ifdef MATH_CHECKS
+ if (unlikely(size.x < 0 || size.y < 0)) {
+ ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
+ }
+#endif
Point2i begin = position;
Point2i end = position + size;
diff --git a/core/math/static_raycaster.cpp b/core/math/static_raycaster.cpp
new file mode 100644
index 0000000000..2510138d90
--- /dev/null
+++ b/core/math/static_raycaster.cpp
@@ -0,0 +1,40 @@
+/*************************************************************************/
+/* static_raycaster.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "static_raycaster.h"
+
+StaticRaycaster *(*StaticRaycaster::create_function)() = nullptr;
+
+Ref<StaticRaycaster> StaticRaycaster::create() {
+ if (create_function) {
+ return Ref<StaticRaycaster>(create_function());
+ }
+ return Ref<StaticRaycaster>();
+}
diff --git a/core/math/static_raycaster.h b/core/math/static_raycaster.h
new file mode 100644
index 0000000000..33254399c7
--- /dev/null
+++ b/core/math/static_raycaster.h
@@ -0,0 +1,111 @@
+/*************************************************************************/
+/* static_raycaster.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef STATIC_RAYCASTER_H
+#define STATIC_RAYCASTER_H
+
+#include "core/object/ref_counted.h"
+
+#if !defined(__aligned)
+
+#if defined(_WIN32) && defined(_MSC_VER)
+#define __aligned(...) __declspec(align(__VA_ARGS__))
+#else
+#define __aligned(...) __attribute__((aligned(__VA_ARGS__)))
+#endif
+
+#endif
+
+class StaticRaycaster : public RefCounted {
+ GDCLASS(StaticRaycaster, RefCounted)
+protected:
+ static StaticRaycaster *(*create_function)();
+
+public:
+ // compatible with embree3 rays
+ struct __aligned(16) Ray {
+ const static unsigned int INVALID_GEOMETRY_ID = ((unsigned int)-1); // from rtcore_common.h
+
+ /*! Default construction does nothing. */
+ _FORCE_INLINE_ Ray() :
+ geomID(INVALID_GEOMETRY_ID) {}
+
+ /*! Constructs a ray from origin, direction, and ray segment. Near
+ * has to be smaller than far. */
+ _FORCE_INLINE_ Ray(const Vector3 &org,
+ const Vector3 &dir,
+ float tnear = 0.0f,
+ float tfar = INFINITY) :
+ org(org),
+ tnear(tnear),
+ dir(dir),
+ time(0.0f),
+ tfar(tfar),
+ mask(-1),
+ u(0.0),
+ v(0.0),
+ primID(INVALID_GEOMETRY_ID),
+ geomID(INVALID_GEOMETRY_ID),
+ instID(INVALID_GEOMETRY_ID) {}
+
+ /*! Tests if we hit something. */
+ _FORCE_INLINE_ explicit operator bool() const { return geomID != INVALID_GEOMETRY_ID; }
+
+ public:
+ Vector3 org; //!< Ray origin + tnear
+ float tnear; //!< Start of ray segment
+ Vector3 dir; //!< Ray direction + tfar
+ float time; //!< Time of this ray for motion blur.
+ float tfar; //!< End of ray segment
+ unsigned int mask; //!< used to mask out objects during traversal
+ unsigned int id; //!< ray ID
+ unsigned int flags; //!< ray flags
+
+ Vector3 normal; //!< Not normalized geometry normal
+ float u; //!< Barycentric u coordinate of hit
+ float v; //!< Barycentric v coordinate of hit
+ unsigned int primID; //!< primitive ID
+ unsigned int geomID; //!< geometry ID
+ unsigned int instID; //!< instance ID
+ };
+
+ virtual bool intersect(Ray &p_ray) = 0;
+ virtual void intersect(Vector<Ray> &r_rays) = 0;
+
+ virtual void add_mesh(const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices, unsigned int p_id) = 0;
+ virtual void commit() = 0;
+
+ virtual void set_mesh_filter(const Set<int> &p_mesh_ids) = 0;
+ virtual void clear_mesh_filter() = 0;
+
+ static Ref<StaticRaycaster> create();
+};
+
+#endif // STATIC_RAYCASTER_H
diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp
index 16934d67df..0201cf575c 100644
--- a/core/math/transform_2d.cpp
+++ b/core/math/transform_2d.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -63,25 +63,25 @@ Transform2D Transform2D::affine_inverse() const {
return inv;
}
-void Transform2D::rotate(real_t p_phi) {
+void Transform2D::rotate(const real_t p_phi) {
*this = Transform2D(p_phi, Vector2()) * (*this);
}
real_t Transform2D::get_skew() const {
real_t det = basis_determinant();
- return Math::acos(elements[0].normalized().dot(SGN(det) * elements[1].normalized())) - Math_PI * 0.5;
+ return Math::acos(elements[0].normalized().dot(SIGN(det) * elements[1].normalized())) - Math_PI * 0.5;
}
-void Transform2D::set_skew(float p_angle) {
+void Transform2D::set_skew(const real_t p_angle) {
real_t det = basis_determinant();
- elements[1] = SGN(det) * elements[0].rotated((Math_PI * 0.5 + p_angle)).normalized() * elements[1].length();
+ elements[1] = SIGN(det) * elements[0].rotated((Math_PI * 0.5 + p_angle)).normalized() * elements[1].length();
}
real_t Transform2D::get_rotation() const {
return Math::atan2(elements[0].y, elements[0].x);
}
-void Transform2D::set_rotation(real_t p_rot) {
+void Transform2D::set_rotation(const real_t p_rot) {
Size2 scale = get_scale();
real_t cr = Math::cos(p_rot);
real_t sr = Math::sin(p_rot);
@@ -92,7 +92,7 @@ void Transform2D::set_rotation(real_t p_rot) {
set_scale(scale);
}
-Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) {
+Transform2D::Transform2D(const real_t p_rot, const Vector2 &p_pos) {
real_t cr = Math::cos(p_rot);
real_t sr = Math::sin(p_rot);
elements[0][0] = cr;
@@ -102,8 +102,16 @@ Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) {
elements[2] = p_pos;
}
+Transform2D::Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos) {
+ elements[0][0] = Math::cos(p_rot) * p_scale.x;
+ elements[1][1] = Math::cos(p_rot + p_skew) * p_scale.y;
+ elements[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y;
+ elements[0][1] = Math::sin(p_rot) * p_scale.x;
+ elements[2] = p_pos;
+}
+
Size2 Transform2D::get_scale() const {
- real_t det_sign = SGN(basis_determinant());
+ real_t det_sign = SIGN(basis_determinant());
return Size2(elements[0].length(), det_sign * elements[1].length());
}
@@ -126,7 +134,7 @@ void Transform2D::scale_basis(const Size2 &p_scale) {
elements[1][1] *= p_scale.y;
}
-void Transform2D::translate(real_t p_tx, real_t p_ty) {
+void Transform2D::translate(const real_t p_tx, const real_t p_ty) {
translate(Vector2(p_tx, p_ty));
}
@@ -231,7 +239,7 @@ Transform2D Transform2D::translated(const Vector2 &p_offset) const {
return copy;
}
-Transform2D Transform2D::rotated(real_t p_phi) const {
+Transform2D Transform2D::rotated(const real_t p_phi) const {
Transform2D copy = *this;
copy.rotate(p_phi);
return copy;
@@ -241,7 +249,7 @@ real_t Transform2D::basis_determinant() const {
return elements[0].x * elements[1].y - elements[0].y * elements[1].x;
}
-Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t p_c) const {
+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();
@@ -271,7 +279,7 @@ Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t
}
//construct matrix
- Transform2D res(Math::atan2(v.y, v.x), p1.lerp(p2, p_c));
+ Transform2D res(v.angle(), p1.lerp(p2, p_c));
res.scale_basis(s1.lerp(s2, p_c));
return res;
}
@@ -290,6 +298,6 @@ Transform2D Transform2D::operator*(const real_t p_val) const {
Transform2D::operator String() const {
return "[X: " + elements[0].operator String() +
- ", Y: " + elements[1].operator String() +
- ", O: " + elements[2].operator String() + "]";
+ ", Y: " + elements[1].operator String() +
+ ", O: " + elements[2].operator String() + "]";
}
diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h
index 34cfd0c1a9..752a885eba 100644
--- a/core/math/transform_2d.h
+++ b/core/math/transform_2d.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,17 +68,17 @@ struct Transform2D {
void affine_invert();
Transform2D affine_inverse() const;
- void set_rotation(real_t p_rot);
+ void set_rotation(const real_t p_rot);
real_t get_rotation() const;
real_t get_skew() const;
- void set_skew(float p_angle);
- _FORCE_INLINE_ void set_rotation_and_scale(real_t p_rot, const Size2 &p_scale);
- _FORCE_INLINE_ void set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, float p_skew);
- void rotate(real_t p_phi);
+ void set_skew(const real_t p_angle);
+ _FORCE_INLINE_ void set_rotation_and_scale(const real_t p_rot, const Size2 &p_scale);
+ _FORCE_INLINE_ void set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew);
+ void rotate(const real_t p_phi);
void scale(const Size2 &p_scale);
void scale_basis(const Size2 &p_scale);
- void translate(real_t p_tx, real_t p_ty);
+ void translate(const real_t p_tx, const real_t p_ty);
void translate(const Vector2 &p_translation);
real_t basis_determinant() const;
@@ -92,7 +92,7 @@ struct Transform2D {
Transform2D scaled(const Size2 &p_scale) const;
Transform2D basis_scaled(const Size2 &p_scale) const;
Transform2D translated(const Vector2 &p_offset) const;
- Transform2D rotated(real_t p_phi) const;
+ Transform2D rotated(const real_t p_phi) const;
Transform2D untranslated() const;
@@ -110,7 +110,7 @@ struct Transform2D {
void operator*=(const real_t p_val);
Transform2D operator*(const real_t p_val) const;
- Transform2D interpolate_with(const Transform2D &p_transform, real_t p_c) const;
+ Transform2D interpolate_with(const Transform2D &p_transform, const real_t p_c) const;
_FORCE_INLINE_ Vector2 basis_xform(const Vector2 &p_vec) const;
_FORCE_INLINE_ Vector2 basis_xform_inv(const Vector2 &p_vec) const;
@@ -123,7 +123,7 @@ struct Transform2D {
operator String() const;
- Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) {
+ Transform2D(const real_t xx, const real_t xy, const real_t yx, const real_t yy, const real_t ox, const real_t oy) {
elements[0][0] = xx;
elements[0][1] = xy;
elements[1][0] = yx;
@@ -138,7 +138,10 @@ struct Transform2D {
elements[2] = p_origin;
}
- Transform2D(real_t p_rot, const Vector2 &p_pos);
+ Transform2D(const real_t p_rot, const Vector2 &p_pos);
+
+ Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos);
+
Transform2D() {
elements[0][0] = 1.0;
elements[1][1] = 1.0;
@@ -161,7 +164,7 @@ Vector2 Transform2D::xform(const Vector2 &p_vec) const {
return Vector2(
tdotx(p_vec),
tdoty(p_vec)) +
- elements[2];
+ elements[2];
}
Vector2 Transform2D::xform_inv(const Vector2 &p_vec) const {
@@ -185,14 +188,14 @@ Rect2 Transform2D::xform(const Rect2 &p_rect) const {
return new_rect;
}
-void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) {
+void Transform2D::set_rotation_and_scale(const real_t p_rot, const Size2 &p_scale) {
elements[0][0] = Math::cos(p_rot) * p_scale.x;
elements[1][1] = Math::cos(p_rot) * p_scale.y;
elements[1][0] = -Math::sin(p_rot) * p_scale.y;
elements[0][1] = Math::sin(p_rot) * p_scale.x;
}
-void Transform2D::set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, float p_skew) {
+void Transform2D::set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew) {
elements[0][0] = Math::cos(p_rot) * p_scale.x;
elements[1][1] = Math::cos(p_rot + p_skew) * p_scale.y;
elements[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y;
diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp
index 4f4943c8ef..e5374315e2 100644
--- a/core/math/transform_3d.cpp
+++ b/core/math/transform_3d.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -80,9 +80,11 @@ void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, con
origin = p_eye;
}
-Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const {
+Transform3D Transform3D::sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const {
/* not sure if very "efficient" but good enough? */
+ Transform3D interp;
+
Vector3 src_scale = basis.get_scale();
Quaternion src_rot = basis.get_rotation_quaternion();
Vector3 src_loc = origin;
@@ -91,13 +93,21 @@ Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t
Quaternion dst_rot = p_transform.basis.get_rotation_quaternion();
Vector3 dst_loc = p_transform.origin;
- Transform3D interp;
interp.basis.set_quaternion_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c));
interp.origin = src_loc.lerp(dst_loc, p_c);
return interp;
}
+Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const {
+ Transform3D interp;
+
+ interp.basis = basis.lerp(p_transform.basis, p_c);
+ interp.origin = origin.lerp(p_transform.origin, p_c);
+
+ return interp;
+}
+
void Transform3D::scale(const Vector3 &p_scale) {
basis.scale(p_scale);
origin *= p_scale;
@@ -139,6 +149,16 @@ Transform3D Transform3D::orthonormalized() const {
return _copy;
}
+void Transform3D::orthogonalize() {
+ basis.orthogonalize();
+}
+
+Transform3D Transform3D::orthogonalized() const {
+ Transform3D _copy = *this;
+ _copy.orthogonalize();
+ return _copy;
+}
+
bool Transform3D::is_equal_approx(const Transform3D &p_transform) const {
return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin);
}
@@ -175,9 +195,9 @@ Transform3D Transform3D::operator*(const real_t p_val) const {
Transform3D::operator String() const {
return "[X: " + basis.get_axis(0).operator String() +
- ", Y: " + basis.get_axis(1).operator String() +
- ", Z: " + basis.get_axis(2).operator String() +
- ", O: " + origin.operator String() + "]";
+ ", Y: " + basis.get_axis(1).operator String() +
+ ", Z: " + basis.get_axis(2).operator String() +
+ ", O: " + origin.operator String() + "]";
}
Transform3D::Transform3D(const Basis &p_basis, const Vector3 &p_origin) :
diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h
index 345e0fade0..c0ef2ecfc1 100644
--- a/core/math/transform_3d.h
+++ b/core/math/transform_3d.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -69,6 +69,8 @@ public:
void orthonormalize();
Transform3D orthonormalized() const;
+ void orthogonalize();
+ Transform3D orthogonalized() const;
bool is_equal_approx(const Transform3D &p_transform) const;
bool operator==(const Transform3D &p_transform) const;
@@ -99,6 +101,7 @@ public:
void operator*=(const real_t p_val);
Transform3D operator*(const real_t p_val) const;
+ Transform3D sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const;
Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const;
_FORCE_INLINE_ Transform3D inverse_xform(const Transform3D &t) const {
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index bf06c848c5..debc5cd00d 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -76,7 +76,7 @@ int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, in
int index = r_max_alloc++;
BVH *_new = &p_bvh[index];
_new->aabb = aabb;
- _new->center = aabb.position + aabb.size * 0.5;
+ _new->center = aabb.get_center();
_new->face_index = -1;
_new->left = left;
_new->right = right;
@@ -152,13 +152,13 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces) {
bw[i].left = -1;
bw[i].right = -1;
bw[i].face_index = i;
- bw[i].center = bw[i].aabb.position + bw[i].aabb.size * 0.5;
+ bw[i].center = bw[i].aabb.get_center();
}
vertices.resize(db.size());
Vector3 *vw = vertices.ptrw();
- for (Map<Vector3, int>::Element *E = db.front(); E; E = E->next()) {
- vw[E->get()] = E->key();
+ for (const KeyValue<Vector3, int> &E : db) {
+ vw[E.value] = E.key;
}
}
diff --git a/core/math/triangle_mesh.h b/core/math/triangle_mesh.h
index 2d3b4db4bb..1b99945698 100644
--- a/core/math/triangle_mesh.h
+++ b/core/math/triangle_mesh.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp
index fa1588dbc5..f3e3de5fc2 100644
--- a/core/math/triangulate.cpp
+++ b/core/math/triangulate.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,18 +42,13 @@ real_t Triangulate::get_area(const Vector<Vector2> &contour) {
return A * 0.5;
}
-/*
- is_inside_triangle decides if a point P is Inside of the triangle
- defined by A, B, C.
- */
-
+/* `is_inside_triangle` decides if a point P is inside the triangle
+ * defined by A, B, C. */
bool Triangulate::is_inside_triangle(real_t Ax, real_t Ay,
real_t Bx, real_t By,
real_t Cx, real_t Cy,
real_t Px, real_t Py,
- bool include_edges)
-
-{
+ bool include_edges) {
real_t ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
real_t cCROSSap, bCROSScp, aCROSSbp;
diff --git a/core/math/triangulate.h b/core/math/triangulate.h
index 249ca6238f..d96bdb8cab 100644
--- a/core/math/triangulate.h
+++ b/core/math/triangulate.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp
index b53dc05a00..676a0004ea 100644
--- a/core/math/vector2.cpp
+++ b/core/math/vector2.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -79,7 +79,7 @@ real_t Vector2::angle_to(const Vector2 &p_vector2) const {
}
real_t Vector2::angle_to_point(const Vector2 &p_vector2) const {
- return Math::atan2(y - p_vector2.y, x - p_vector2.x);
+ return (p_vector2 - *this).angle();
}
real_t Vector2::dot(const Vector2 &p_other) const {
@@ -91,7 +91,7 @@ real_t Vector2::cross(const Vector2 &p_other) const {
}
Vector2 Vector2::sign() const {
- return Vector2(SGN(x), SGN(y));
+ return Vector2(SIGN(x), SIGN(y));
}
Vector2 Vector2::floor() const {
@@ -160,10 +160,11 @@ Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, c
real_t t3 = t2 * t;
Vector2 out;
- out = 0.5 * ((p1 * 2.0) +
- (-p0 + p2) * t +
- (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 +
- (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3);
+ out = 0.5 *
+ ((p1 * 2.0) +
+ (-p0 + p2) * t +
+ (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 +
+ (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3);
return out;
}
@@ -209,6 +210,14 @@ Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const {
CLAMP(y, p_min.y, p_max.y));
}
+int64_t Vector2i::length_squared() const {
+ return x * (int64_t)x + y * (int64_t)y;
+}
+
+double Vector2i::length() const {
+ return Math::sqrt((double)length_squared());
+}
+
Vector2i Vector2i::operator+(const Vector2i &p_v) const {
return Vector2i(x + p_v.x, y + p_v.y);
}
diff --git a/core/math/vector2.h b/core/math/vector2.h
index 332c0475fa..a340036ac7 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -70,12 +70,12 @@ struct Vector2 {
x = y = p_value;
}
- _FORCE_INLINE_ int min_axis() const {
- return x < y ? 0 : 1;
+ _FORCE_INLINE_ Vector2::Axis min_axis_index() const {
+ return x < y ? Vector2::AXIS_X : Vector2::AXIS_Y;
}
- _FORCE_INLINE_ int max_axis() const {
- return x < y ? 1 : 0;
+ _FORCE_INLINE_ Vector2::Axis max_axis_index() const {
+ return x < y ? Vector2::AXIS_Y : Vector2::AXIS_X;
}
void normalize();
@@ -261,11 +261,16 @@ Vector2 Vector2::lerp(const Vector2 &p_to, const real_t p_weight) const {
}
Vector2 Vector2::slerp(const Vector2 &p_to, const real_t p_weight) const {
-#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Vector2(), "The start Vector2 must be normalized.");
-#endif
- real_t theta = angle_to(p_to);
- return rotated(theta * p_weight);
+ real_t start_length_sq = length_squared();
+ real_t end_length_sq = p_to.length_squared();
+ if (unlikely(start_length_sq == 0.0 || end_length_sq == 0.0)) {
+ // Zero length vectors have no angle, so the best we can do is either lerp or throw an error.
+ return lerp(p_to, p_weight);
+ }
+ real_t start_length = Math::sqrt(start_length_sq);
+ real_t result_length = Math::lerp(start_length, Math::sqrt(end_length_sq), p_weight);
+ real_t angle = angle_to(p_to);
+ return rotated(angle * p_weight) * (result_length / start_length);
}
Vector2 Vector2::direction_to(const Vector2 &p_to) const {
@@ -301,12 +306,12 @@ struct Vector2i {
return p_idx ? y : x;
}
- _FORCE_INLINE_ int min_axis() const {
- return x < y ? 0 : 1;
+ _FORCE_INLINE_ Vector2i::Axis min_axis_index() const {
+ return x < y ? Vector2i::AXIS_X : Vector2i::AXIS_Y;
}
- _FORCE_INLINE_ int max_axis() const {
- return x < y ? 1 : 0;
+ _FORCE_INLINE_ Vector2i::Axis max_axis_index() const {
+ return x < y ? Vector2i::AXIS_Y : Vector2i::AXIS_X;
}
Vector2i min(const Vector2i &p_vector2i) const {
@@ -344,8 +349,11 @@ struct Vector2i {
bool operator==(const Vector2i &p_vec2) const;
bool operator!=(const Vector2i &p_vec2) const;
+ int64_t length_squared() const;
+ double length() const;
+
real_t aspect() const { return width / (real_t)height; }
- Vector2i sign() const { return Vector2i(SGN(x), SGN(y)); }
+ Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); }
Vector2i abs() const { return Vector2i(ABS(x), ABS(y)); }
Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const;
diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp
index 401c3ccd9c..b6965b3c32 100644
--- a/core/math/vector3.cpp
+++ b/core/math/vector3.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -93,10 +93,11 @@ Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, c
real_t t3 = t2 * t;
Vector3 out;
- out = 0.5 * ((p1 * 2.0) +
- (-p0 + p2) * t +
- (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 +
- (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3);
+ out = 0.5 *
+ ((p1 * 2.0) +
+ (-p0 + p2) * t +
+ (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 +
+ (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3);
return out;
}
@@ -107,20 +108,14 @@ Vector3 Vector3::move_toward(const Vector3 &p_to, const real_t p_delta) const {
return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta;
}
-Basis Vector3::outer(const Vector3 &p_b) const {
- Vector3 row0(x * p_b.x, x * p_b.y, x * p_b.z);
- Vector3 row1(y * p_b.x, y * p_b.y, y * p_b.z);
- Vector3 row2(z * p_b.x, z * p_b.y, z * p_b.z);
+Basis Vector3::outer(const Vector3 &p_with) const {
+ Vector3 row0(x * p_with.x, x * p_with.y, x * p_with.z);
+ Vector3 row1(y * p_with.x, y * p_with.y, y * p_with.z);
+ Vector3 row2(z * p_with.x, z * p_with.y, z * p_with.z);
return Basis(row0, row1, row2);
}
-Basis Vector3::to_diagonal_matrix() const {
- return Basis(x, 0, 0,
- 0, y, 0,
- 0, 0, z);
-}
-
bool Vector3::is_equal_approx(const Vector3 &p_v) const {
return Math::is_equal_approx(x, p_v.x) && Math::is_equal_approx(y, p_v.y) && Math::is_equal_approx(z, p_v.z);
}
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 6a4c42f41b..d7a72b05a8 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,9 +32,9 @@
#define VECTOR3_H
#include "core/math/math_funcs.h"
+#include "core/math/vector2.h"
#include "core/math/vector3i.h"
#include "core/string/ustring.h"
-
class Basis;
struct Vector3 {
@@ -71,12 +71,12 @@ struct Vector3 {
x = y = z = p_value;
}
- _FORCE_INLINE_ int min_axis() const {
- return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2);
+ _FORCE_INLINE_ Vector3::Axis min_axis_index() const {
+ return x < y ? (x < z ? Vector3::AXIS_X : Vector3::AXIS_Z) : (y < z ? Vector3::AXIS_Y : Vector3::AXIS_Z);
}
- _FORCE_INLINE_ int max_axis() const {
- return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0);
+ _FORCE_INLINE_ Vector3::Axis max_axis_index() const {
+ return x < y ? (y < z ? Vector3::AXIS_Z : Vector3::AXIS_Y) : (x < z ? Vector3::AXIS_Z : Vector3::AXIS_X);
}
_FORCE_INLINE_ real_t length() const;
@@ -103,10 +103,34 @@ struct Vector3 {
Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const;
Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const;
- _FORCE_INLINE_ Vector3 cross(const Vector3 &p_b) const;
- _FORCE_INLINE_ real_t dot(const Vector3 &p_b) const;
- Basis outer(const Vector3 &p_b) const;
- Basis to_diagonal_matrix() const;
+ _FORCE_INLINE_ Vector2 octahedron_encode() const {
+ Vector3 n = *this;
+ n /= Math::abs(n.x) + Math::abs(n.y) + Math::abs(n.z);
+ Vector2 o;
+ if (n.z >= 0.0) {
+ o.x = n.x;
+ o.y = n.y;
+ } else {
+ o.x = (1.0 - Math::abs(n.y)) * (n.x >= 0.0 ? 1.0 : -1.0);
+ o.y = (1.0 - Math::abs(n.x)) * (n.y >= 0.0 ? 1.0 : -1.0);
+ }
+ o.x = o.x * 0.5 + 0.5;
+ o.y = o.y * 0.5 + 0.5;
+ return o;
+ }
+
+ static _FORCE_INLINE_ Vector3 octahedron_decode(const Vector2 &p_oct) {
+ Vector2 f(p_oct.x * 2.0 - 1.0, p_oct.y * 2.0 - 1.0);
+ Vector3 n(f.x, f.y, 1.0f - Math::abs(f.x) - Math::abs(f.y));
+ float t = CLAMP(-n.z, 0.0, 1.0);
+ n.x += n.x >= 0 ? -t : t;
+ n.y += n.y >= 0 ? -t : t;
+ return n.normalized();
+ }
+
+ _FORCE_INLINE_ Vector3 cross(const Vector3 &p_with) const;
+ _FORCE_INLINE_ real_t dot(const Vector3 &p_with) const;
+ Basis outer(const Vector3 &p_with) const;
_FORCE_INLINE_ Vector3 abs() const;
_FORCE_INLINE_ Vector3 floor() const;
@@ -175,17 +199,17 @@ struct Vector3 {
}
};
-Vector3 Vector3::cross(const Vector3 &p_b) const {
+Vector3 Vector3::cross(const Vector3 &p_with) const {
Vector3 ret(
- (y * p_b.z) - (z * p_b.y),
- (z * p_b.x) - (x * p_b.z),
- (x * p_b.y) - (y * p_b.x));
+ (y * p_with.z) - (z * p_with.y),
+ (z * p_with.x) - (x * p_with.z),
+ (x * p_with.y) - (y * p_with.x));
return ret;
}
-real_t Vector3::dot(const Vector3 &p_b) const {
- return x * p_b.x + y * p_b.y + z * p_b.z;
+real_t Vector3::dot(const Vector3 &p_with) const {
+ return x * p_with.x + y * p_with.y + z * p_with.z;
}
Vector3 Vector3::abs() const {
@@ -193,7 +217,7 @@ Vector3 Vector3::abs() const {
}
Vector3 Vector3::sign() const {
- return Vector3(SGN(x), SGN(y), SGN(z));
+ return Vector3(SIGN(x), SIGN(y), SIGN(z));
}
Vector3 Vector3::floor() const {
@@ -216,8 +240,16 @@ Vector3 Vector3::lerp(const Vector3 &p_to, const real_t p_weight) const {
}
Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const {
- real_t theta = angle_to(p_to);
- return rotated(cross(p_to).normalized(), theta * p_weight);
+ real_t start_length_sq = length_squared();
+ real_t end_length_sq = p_to.length_squared();
+ if (unlikely(start_length_sq == 0.0 || end_length_sq == 0.0)) {
+ // Zero length vectors have no angle, so the best we can do is either lerp or throw an error.
+ return lerp(p_to, p_weight);
+ }
+ real_t start_length = Math::sqrt(start_length_sq);
+ real_t result_length = Math::lerp(start_length, Math::sqrt(end_length_sq), p_weight);
+ real_t angle = angle_to(p_to);
+ return rotated(cross(p_to).normalized(), angle * p_weight) * (result_length / start_length);
}
real_t Vector3::distance_to(const Vector3 &p_to) const {
diff --git a/core/math/vector3i.cpp b/core/math/vector3i.cpp
index d3a57af77c..ac79b3c7ea 100644
--- a/core/math/vector3i.cpp
+++ b/core/math/vector3i.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -40,12 +40,12 @@ int32_t Vector3i::get_axis(const int p_axis) const {
return operator[](p_axis);
}
-int Vector3i::min_axis() const {
- return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2);
+Vector3i::Axis Vector3i::min_axis_index() const {
+ return x < y ? (x < z ? Vector3i::AXIS_X : Vector3i::AXIS_Z) : (y < z ? Vector3i::AXIS_Y : Vector3i::AXIS_Z);
}
-int Vector3i::max_axis() const {
- return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0);
+Vector3i::Axis Vector3i::max_axis_index() const {
+ return x < y ? (y < z ? Vector3i::AXIS_Z : Vector3i::AXIS_Y) : (x < z ? Vector3i::AXIS_Z : Vector3i::AXIS_X);
}
Vector3i Vector3i::clamp(const Vector3i &p_min, const Vector3i &p_max) const {
diff --git a/core/math/vector3i.h b/core/math/vector3i.h
index 9308d09045..1416c98057 100644
--- a/core/math/vector3i.h
+++ b/core/math/vector3i.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,6 +31,7 @@
#ifndef VECTOR3I_H
#define VECTOR3I_H
+#include "core/math/math_funcs.h"
#include "core/string/ustring.h"
#include "core/typedefs.h"
@@ -62,8 +63,11 @@ struct Vector3i {
void set_axis(const int p_axis, const int32_t p_value);
int32_t get_axis(const int p_axis) const;
- int min_axis() const;
- int max_axis() const;
+ Vector3i::Axis min_axis_index() const;
+ Vector3i::Axis max_axis_index() const;
+
+ _FORCE_INLINE_ int64_t length_squared() const;
+ _FORCE_INLINE_ double length() const;
_FORCE_INLINE_ void zero();
@@ -110,12 +114,20 @@ struct Vector3i {
}
};
+int64_t Vector3i::length_squared() const {
+ return x * (int64_t)x + y * (int64_t)y + z * (int64_t)z;
+}
+
+double Vector3i::length() const {
+ return Math::sqrt((double)length_squared());
+}
+
Vector3i Vector3i::abs() const {
return Vector3i(ABS(x), ABS(y), ABS(z));
}
Vector3i Vector3i::sign() const {
- return Vector3i(SGN(x), SGN(y), SGN(z));
+ return Vector3i(SIGN(x), SIGN(y), SIGN(z));
}
/* Operators */
diff --git a/core/multiplayer/multiplayer.h b/core/multiplayer/multiplayer.h
index 00c81d3c9a..5eb968171a 100644
--- a/core/multiplayer/multiplayer.h
+++ b/core/multiplayer/multiplayer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -39,20 +39,20 @@ namespace Multiplayer {
enum TransferMode {
TRANSFER_MODE_UNRELIABLE,
- TRANSFER_MODE_ORDERED,
+ TRANSFER_MODE_UNRELIABLE_ORDERED,
TRANSFER_MODE_RELIABLE
};
enum RPCMode {
RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
- RPC_MODE_ANY, // Any peer can call this RPC
+ RPC_MODE_ANY_PEER, // Any peer can call this RPC
RPC_MODE_AUTHORITY, // / Only the node's multiplayer authority (server by default) can call this RPC
};
struct RPCConfig {
StringName name;
RPCMode rpc_mode = RPC_MODE_DISABLED;
- bool sync = false;
+ bool call_local = false;
TransferMode transfer_mode = TRANSFER_MODE_RELIABLE;
int channel = 0;
diff --git a/core/multiplayer/multiplayer_api.cpp b/core/multiplayer/multiplayer_api.cpp
index 9543f77c1e..627825246a 100644
--- a/core/multiplayer/multiplayer_api.cpp
+++ b/core/multiplayer/multiplayer_api.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/multiplayer/multiplayer_api.h b/core/multiplayer/multiplayer_api.h
index 1fb0318403..713035428d 100644
--- a/core/multiplayer/multiplayer_api.h
+++ b/core/multiplayer/multiplayer_api.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/multiplayer/multiplayer_peer.cpp b/core/multiplayer/multiplayer_peer.cpp
index 40847102d8..ae3b139bcc 100644
--- a/core/multiplayer/multiplayer_peer.cpp
+++ b/core/multiplayer/multiplayer_peer.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -53,6 +53,30 @@ uint32_t MultiplayerPeer::generate_unique_id() const {
return hash;
}
+void MultiplayerPeer::set_transfer_channel(int p_channel) {
+ transfer_channel = p_channel;
+}
+
+int MultiplayerPeer::get_transfer_channel() const {
+ return transfer_channel;
+}
+
+void MultiplayerPeer::set_transfer_mode(Multiplayer::TransferMode p_mode) {
+ transfer_mode = p_mode;
+}
+
+Multiplayer::TransferMode MultiplayerPeer::get_transfer_mode() const {
+ return transfer_mode;
+}
+
+void MultiplayerPeer::set_refuse_new_connections(bool p_enable) {
+ refuse_connections = p_enable;
+}
+
+bool MultiplayerPeer::is_refusing_new_connections() const {
+ return refuse_connections;
+}
+
void MultiplayerPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transfer_channel", "channel"), &MultiplayerPeer::set_transfer_channel);
ClassDB::bind_method(D_METHOD("get_transfer_channel"), &MultiplayerPeer::get_transfer_channel);
@@ -88,3 +112,160 @@ void MultiplayerPeer::_bind_methods() {
ADD_SIGNAL(MethodInfo("connection_succeeded"));
ADD_SIGNAL(MethodInfo("connection_failed"));
}
+
+/*************/
+
+int MultiplayerPeerExtension::get_available_packet_count() const {
+ int count;
+ if (GDVIRTUAL_CALL(_get_available_packet_count, count)) {
+ return count;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_available_packet_count is unimplemented!");
+ return -1;
+}
+
+Error MultiplayerPeerExtension::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
+ int err;
+ if (GDVIRTUAL_CALL(_get_packet, r_buffer, &r_buffer_size, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_packet_native is unimplemented!");
+ return FAILED;
+}
+
+Error MultiplayerPeerExtension::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
+ int err;
+ if (GDVIRTUAL_CALL(_put_packet, p_buffer, p_buffer_size, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_put_packet_native is unimplemented!");
+ return FAILED;
+}
+
+int MultiplayerPeerExtension::get_max_packet_size() const {
+ int size;
+ if (GDVIRTUAL_CALL(_get_max_packet_size, size)) {
+ return size;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_max_packet_size is unimplemented!");
+ return 0;
+}
+
+void MultiplayerPeerExtension::set_transfer_channel(int p_channel) {
+ if (GDVIRTUAL_CALL(_set_transfer_channel, p_channel)) {
+ return;
+ }
+ MultiplayerPeer::set_transfer_channel(p_channel);
+}
+
+int MultiplayerPeerExtension::get_transfer_channel() const {
+ int channel;
+ if (GDVIRTUAL_CALL(_get_transfer_channel, channel)) {
+ return channel;
+ }
+ return MultiplayerPeer::get_transfer_channel();
+}
+
+void MultiplayerPeerExtension::set_transfer_mode(Multiplayer::TransferMode p_mode) {
+ if (GDVIRTUAL_CALL(_set_transfer_mode, p_mode)) {
+ return;
+ }
+ MultiplayerPeer::set_transfer_mode(p_mode);
+}
+
+Multiplayer::TransferMode MultiplayerPeerExtension::get_transfer_mode() const {
+ int mode;
+ if (GDVIRTUAL_CALL(_get_transfer_mode, mode)) {
+ return (Multiplayer::TransferMode)mode;
+ }
+ return MultiplayerPeer::get_transfer_mode();
+}
+
+void MultiplayerPeerExtension::set_target_peer(int p_peer_id) {
+ if (GDVIRTUAL_CALL(_set_target_peer, p_peer_id)) {
+ return;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_set_target_peer is unimplemented!");
+}
+
+int MultiplayerPeerExtension::get_packet_peer() const {
+ int peer;
+ if (GDVIRTUAL_CALL(_get_packet_peer, peer)) {
+ return peer;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_packet_peer is unimplemented!");
+ return 0;
+}
+
+bool MultiplayerPeerExtension::is_server() const {
+ bool server;
+ if (GDVIRTUAL_CALL(_is_server, server)) {
+ return server;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_is_server is unimplemented!");
+ return false;
+}
+
+void MultiplayerPeerExtension::poll() {
+ int err;
+ if (GDVIRTUAL_CALL(_poll, err)) {
+ return;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_poll is unimplemented!");
+}
+
+int MultiplayerPeerExtension::get_unique_id() const {
+ int id;
+ if (GDVIRTUAL_CALL(_get_unique_id, id)) {
+ return id;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_unique_id is unimplemented!");
+ return 0;
+}
+
+void MultiplayerPeerExtension::set_refuse_new_connections(bool p_enable) {
+ if (GDVIRTUAL_CALL(_set_refuse_new_connections, p_enable)) {
+ return;
+ }
+ MultiplayerPeer::set_refuse_new_connections(p_enable);
+}
+
+bool MultiplayerPeerExtension::is_refusing_new_connections() const {
+ bool refusing;
+ if (GDVIRTUAL_CALL(_is_refusing_new_connections, refusing)) {
+ return refusing;
+ }
+ return MultiplayerPeer::is_refusing_new_connections();
+}
+
+MultiplayerPeer::ConnectionStatus MultiplayerPeerExtension::get_connection_status() const {
+ int status;
+ if (GDVIRTUAL_CALL(_get_connection_status, status)) {
+ return (ConnectionStatus)status;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_connection_status is unimplemented!");
+ return CONNECTION_DISCONNECTED;
+}
+
+void MultiplayerPeerExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_packet, "r_buffer", "r_buffer_size");
+ GDVIRTUAL_BIND(_put_packet, "p_buffer", "p_buffer_size");
+ GDVIRTUAL_BIND(_get_available_packet_count);
+ GDVIRTUAL_BIND(_get_max_packet_size);
+
+ GDVIRTUAL_BIND(_set_transfer_channel, "p_channel");
+ GDVIRTUAL_BIND(_get_transfer_channel);
+
+ GDVIRTUAL_BIND(_set_transfer_mode, "p_mode");
+ GDVIRTUAL_BIND(_get_transfer_mode);
+
+ GDVIRTUAL_BIND(_set_target_peer, "p_peer");
+
+ GDVIRTUAL_BIND(_get_packet_peer);
+ GDVIRTUAL_BIND(_is_server);
+ GDVIRTUAL_BIND(_poll);
+ GDVIRTUAL_BIND(_get_unique_id);
+ GDVIRTUAL_BIND(_set_refuse_new_connections, "p_enable");
+ GDVIRTUAL_BIND(_is_refusing_new_connections);
+ GDVIRTUAL_BIND(_get_connection_status);
+}
diff --git a/core/multiplayer/multiplayer_peer.h b/core/multiplayer/multiplayer_peer.h
index ba00c3b41b..dee2be7b4b 100644
--- a/core/multiplayer/multiplayer_peer.h
+++ b/core/multiplayer/multiplayer_peer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,12 +34,21 @@
#include "core/io/packet_peer.h"
#include "core/multiplayer/multiplayer.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
+
class MultiplayerPeer : public PacketPeer {
GDCLASS(MultiplayerPeer, PacketPeer);
protected:
static void _bind_methods();
+private:
+ int transfer_channel = 0;
+ Multiplayer::TransferMode transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE;
+ bool refuse_connections = false;
+
public:
enum {
TARGET_PEER_BROADCAST = 0,
@@ -52,10 +61,13 @@ public:
CONNECTION_CONNECTED,
};
- virtual void set_transfer_channel(int p_channel) = 0;
- virtual int get_transfer_channel() const = 0;
- virtual void set_transfer_mode(Multiplayer::TransferMode p_mode) = 0;
- virtual Multiplayer::TransferMode get_transfer_mode() const = 0;
+ virtual void set_transfer_channel(int p_channel);
+ virtual int get_transfer_channel() const;
+ virtual void set_transfer_mode(Multiplayer::TransferMode p_mode);
+ virtual Multiplayer::TransferMode get_transfer_mode() const;
+ virtual void set_refuse_new_connections(bool p_enable);
+ virtual bool is_refusing_new_connections() const;
+
virtual void set_target_peer(int p_peer_id) = 0;
virtual int get_packet_peer() const = 0;
@@ -66,15 +78,67 @@ public:
virtual int get_unique_id() const = 0;
- virtual void set_refuse_new_connections(bool p_enable) = 0;
- virtual bool is_refusing_new_connections() const = 0;
-
virtual ConnectionStatus get_connection_status() const = 0;
+
uint32_t generate_unique_id() const;
MultiplayerPeer() {}
};
-VARIANT_ENUM_CAST(MultiplayerPeer::ConnectionStatus)
+VARIANT_ENUM_CAST(MultiplayerPeer::ConnectionStatus);
+
+class MultiplayerPeerExtension : public MultiplayerPeer {
+ GDCLASS(MultiplayerPeerExtension, MultiplayerPeer);
+
+protected:
+ static void _bind_methods();
+
+public:
+ /* PacketPeer */
+ virtual int get_available_packet_count() const override;
+ virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; ///< buffer is GONE after next get_packet
+ virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override;
+ virtual int get_max_packet_size() const override;
+
+ /* MultiplayerPeer */
+ virtual void set_transfer_channel(int p_channel) override;
+ virtual int get_transfer_channel() const override;
+ virtual void set_transfer_mode(Multiplayer::TransferMode p_mode) override;
+ virtual Multiplayer::TransferMode get_transfer_mode() const override;
+ virtual void set_target_peer(int p_peer_id) override;
+
+ virtual int get_packet_peer() const override;
+
+ virtual bool is_server() const override;
+
+ virtual void poll() override;
+
+ virtual int get_unique_id() const override;
+
+ virtual void set_refuse_new_connections(bool p_enable) override;
+ virtual bool is_refusing_new_connections() const override;
+
+ virtual ConnectionStatus get_connection_status() const override;
+
+ /* PacketPeer GDExtension */
+ GDVIRTUAL0RC(int, _get_available_packet_count);
+ GDVIRTUAL2R(int, _get_packet, GDNativeConstPtr<const uint8_t *>, GDNativePtr<int>);
+ GDVIRTUAL2R(int, _put_packet, GDNativeConstPtr<const uint8_t>, int);
+ GDVIRTUAL0RC(int, _get_max_packet_size);
+
+ /* MultiplayerPeer GDExtension */
+ GDVIRTUAL1(_set_transfer_channel, int);
+ GDVIRTUAL0RC(int, _get_transfer_channel);
+ GDVIRTUAL1(_set_transfer_mode, int);
+ GDVIRTUAL0RC(int, _get_transfer_mode);
+ GDVIRTUAL1(_set_target_peer, int);
+ GDVIRTUAL0RC(int, _get_packet_peer);
+ GDVIRTUAL0RC(bool, _is_server);
+ GDVIRTUAL0R(int, _poll);
+ GDVIRTUAL0RC(int, _get_unique_id);
+ GDVIRTUAL1(_set_refuse_new_connections, bool);
+ GDVIRTUAL0RC(bool, _is_refusing_new_connections);
+ GDVIRTUAL0RC(int, _get_connection_status);
+};
#endif // NETWORKED_MULTIPLAYER_PEER_H
diff --git a/core/multiplayer/multiplayer_replicator.cpp b/core/multiplayer/multiplayer_replicator.cpp
index a4ea74327c..e7de8219c7 100644
--- a/core/multiplayer/multiplayer_replicator.cpp
+++ b/core/multiplayer/multiplayer_replicator.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -124,7 +124,7 @@ void MultiplayerReplicator::_process_default_sync(const ResourceUID::ID &p_id, c
ERR_FAIL_COND_MSG(p_packet_len < SYNC_CMD_OFFSET + 5, "Invalid spawn packet received");
ERR_FAIL_COND_MSG(!replications.has(p_id), "Invalid spawn ID received " + itos(p_id));
SceneConfig &cfg = replications[p_id];
- ERR_FAIL_COND_MSG(cfg.mode != REPLICATION_MODE_SERVER || multiplayer->is_server(), "The defualt implementation only allows sync packets from the server");
+ ERR_FAIL_COND_MSG(cfg.mode != REPLICATION_MODE_SERVER || multiplayer->is_server(), "The default implementation only allows sync packets from the server");
const bool same_size = p_packet[0] & BYTE_OR_ZERO_FLAG;
int ofs = SYNC_CMD_OFFSET;
int time = p_packet[ofs];
@@ -207,7 +207,7 @@ Error MultiplayerReplicator::_send_default_spawn_despawn(int p_peer_id, const Re
const Vector<StringName> names = rel_path.get_names();
ERR_FAIL_COND_V(names.size() < 2, ERR_INVALID_PARAMETER);
- NodePath parent = NodePath(names.subarray(0, names.size() - 2), false);
+ NodePath parent = NodePath(names.slice(0, names.size() - 1), false);
ERR_FAIL_COND_V_MSG(!root_node->has_node(parent), ERR_INVALID_PARAMETER, "Path not found: " + parent);
int path_id = 0;
@@ -572,7 +572,7 @@ Error MultiplayerReplicator::_spawn_despawn(ResourceUID::ID p_scene_id, Object *
args[0] = p_peer;
args[1] = p_scene_id;
args[2] = p_obj;
- args[3] = true;
+ args[3] = p_spawn;
const Variant *argp[] = { &args[0], &args[1], &args[2], &args[3] };
Callable::CallError ce;
Variant ret;
diff --git a/core/multiplayer/multiplayer_replicator.h b/core/multiplayer/multiplayer_replicator.h
index 7fa774fdf4..a9cd6e211e 100644
--- a/core/multiplayer/multiplayer_replicator.h
+++ b/core/multiplayer/multiplayer_replicator.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/multiplayer/rpc_manager.cpp b/core/multiplayer/rpc_manager.cpp
index 915571375e..7736637349 100644
--- a/core/multiplayer/rpc_manager.cpp
+++ b/core/multiplayer/rpc_manager.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -99,7 +99,7 @@ _FORCE_INLINE_ bool _can_call_mode(Node *p_node, Multiplayer::RPCMode mode, int
case Multiplayer::RPC_MODE_DISABLED: {
return false;
} break;
- case Multiplayer::RPC_MODE_ANY: {
+ case Multiplayer::RPC_MODE_ANY_PEER: {
return true;
} break;
case Multiplayer::RPC_MODE_AUTHORITY: {
@@ -476,9 +476,9 @@ void RPCManager::rpcp(Node *p_node, int p_peer_id, const StringName &p_method, c
vformat("Unable to get the RPC configuration for the function \"%s\" at path: \"%s\". This happens when the method is not marked for RPCs.", p_method, p_node->get_path()));
if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
if (rpc_id & (1 << 15)) {
- call_local_native = config.sync;
+ call_local_native = config.call_local;
} else {
- call_local_script = config.sync;
+ call_local_script = config.call_local;
}
}
@@ -521,5 +521,5 @@ void RPCManager::rpcp(Node *p_node, int p_peer_id, const StringName &p_method, c
}
}
- ERR_FAIL_COND_MSG(p_peer_id == node_id && !config.sync, "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
+ ERR_FAIL_COND_MSG(p_peer_id == node_id && !config.call_local, "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
}
diff --git a/core/multiplayer/rpc_manager.h b/core/multiplayer/rpc_manager.h
index 7b99dee226..00bd1f9cb0 100644
--- a/core/multiplayer/rpc_manager.h
+++ b/core/multiplayer/rpc_manager.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/object/callable_method_pointer.cpp b/core/object/callable_method_pointer.cpp
index 2bfaef744d..1bf926cafc 100644
--- a/core/object/callable_method_pointer.cpp
+++ b/core/object/callable_method_pointer.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/object/callable_method_pointer.h b/core/object/callable_method_pointer.h
index 8ba01be4e4..53410a9acf 100644
--- a/core/object/callable_method_pointer.h
+++ b/core/object/callable_method_pointer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index 8e92340c1e..03774bc36a 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,8 +37,6 @@
#define OBJTYPE_RLOCK RWLockRead _rw_lockr_(lock);
#define OBJTYPE_WLOCK RWLockWrite _rw_lockw_(lock);
-#ifdef DEBUG_METHODS_ENABLED
-
MethodDefinition D_METHOD(const char *p_name) {
MethodDefinition md;
md.name = StaticCString::create(p_name);
@@ -226,8 +224,6 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
return md;
}
-#endif
-
ClassDB::APIType ClassDB::current_api = API_CORE;
void ClassDB::set_current_api(APIType p_api) {
@@ -501,22 +497,6 @@ void ClassDB::add_compatibility_class(const StringName &p_class, const StringNam
compat_classes[p_class] = p_fallback;
}
-thread_local bool initializing_with_extension = false;
-thread_local ObjectNativeExtension *initializing_extension = nullptr;
-thread_local GDExtensionClassInstancePtr initializing_extension_instance = nullptr;
-
-void ClassDB::instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance, Object *p_base) {
- if (initializing_with_extension) {
- *r_extension = initializing_extension;
- *r_extension_instance = initializing_extension_instance;
- initializing_with_extension = false;
- initializing_extension->set_object_instance(*r_extension_instance, p_base);
- } else {
- *r_extension = nullptr;
- *r_extension_instance = nullptr;
- }
-}
-
Object *ClassDB::instantiate(const StringName &p_class) {
ClassInfo *ti;
{
@@ -529,7 +509,7 @@ Object *ClassDB::instantiate(const StringName &p_class) {
}
ERR_FAIL_COND_V_MSG(!ti, nullptr, "Cannot get class '" + String(p_class) + "'.");
ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, "Class '" + String(p_class) + "' is disabled.");
- ERR_FAIL_COND_V(!ti->creation_func, nullptr);
+ ERR_FAIL_COND_V_MSG(!ti->creation_func, nullptr, "Class '" + String(p_class) + "' or its base class cannot be instantiated.");
}
#ifdef TOOLS_ENABLED
if (ti->api == API_EDITOR && !Engine::get_singleton()->is_editor_hint()) {
@@ -537,12 +517,31 @@ Object *ClassDB::instantiate(const StringName &p_class) {
return nullptr;
}
#endif
- if (ti->native_extension) {
- initializing_with_extension = true;
- initializing_extension = ti->native_extension;
- initializing_extension_instance = ti->native_extension->create_instance(ti->native_extension->class_userdata);
+ if (ti->native_extension && ti->native_extension->create_instance) {
+ return (Object *)ti->native_extension->create_instance(ti->native_extension->class_userdata);
+ } else {
+ return ti->creation_func();
+ }
+}
+
+void ClassDB::set_object_extension_instance(Object *p_object, const StringName &p_class, GDExtensionClassInstancePtr p_instance) {
+ ERR_FAIL_COND(!p_object);
+ ClassInfo *ti;
+ {
+ OBJTYPE_RLOCK;
+ ti = classes.getptr(p_class);
+ if (!ti || ti->disabled || !ti->creation_func || (ti->native_extension && !ti->native_extension->create_instance)) {
+ if (compat_classes.has(p_class)) {
+ ti = classes.getptr(compat_classes[p_class]);
+ }
+ }
+ ERR_FAIL_COND_MSG(!ti, "Cannot get class '" + String(p_class) + "'.");
+ ERR_FAIL_COND_MSG(ti->disabled, "Class '" + String(p_class) + "' is disabled.");
+ ERR_FAIL_COND_MSG(!ti->native_extension, "Class '" + String(p_class) + "' has no native extension.");
}
- return ti->creation_func();
+
+ p_object->_extension = ti->native_extension;
+ p_object->_extension_instance = p_instance;
}
bool ClassDB::can_instantiate(const StringName &p_class) {
@@ -580,7 +579,6 @@ void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherit
}
}
-#ifdef DEBUG_METHODS_ENABLED
static MethodInfo info_from_bind(MethodBind *p_method) {
MethodInfo minfo;
minfo.name = p_method->get_name();
@@ -601,7 +599,6 @@ static MethodInfo info_from_bind(MethodBind *p_method) {
return minfo;
}
-#endif
void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance, bool p_exclude_from_properties) {
OBJTYPE_RLOCK;
@@ -641,9 +638,8 @@ void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_met
while ((K = type->method_map.next(K))) {
MethodBind *m = type->method_map[*K];
- MethodInfo mi;
- mi.name = m->get_name();
- p_methods->push_back(mi);
+ MethodInfo minfo = info_from_bind(m);
+ p_methods->push_back(minfo);
}
#endif
@@ -689,9 +685,8 @@ bool ClassDB::get_method_info(const StringName &p_class, const StringName &p_met
if (type->method_map.has(p_method)) {
if (r_info) {
MethodBind *m = type->method_map[p_method];
- MethodInfo mi;
- mi.name = m->get_name();
- *r_info = mi;
+ MethodInfo minfo = info_from_bind(m);
+ *r_info = minfo;
}
return true;
}
@@ -736,7 +731,7 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName
type->constant_map[p_name] = p_constant;
String enum_name = p_enum;
- if (enum_name != String()) {
+ if (!enum_name.is_empty()) {
if (enum_name.find(".") != -1) {
enum_name = enum_name.get_slicec('.', 1);
}
@@ -1402,13 +1397,8 @@ void ClassDB::bind_method_custom(const StringName &p_class, MethodBind *p_method
type->method_map[p_method->get_name()] = p_method;
}
-#ifdef DEBUG_METHODS_ENABLED
MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) {
StringName mdname = method_name.name;
-#else
-MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount) {
- StringName mdname = StaticCString::create(method_name);
-#endif
OBJTYPE_WLOCK;
ERR_FAIL_COND_V(!p_bind, nullptr);
diff --git a/core/object/class_db.h b/core/object/class_db.h
index e89c7fffd7..5adf1a59a4 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -45,8 +45,6 @@
#define DEFVAL(m_defval) (m_defval)
-#ifdef DEBUG_METHODS_ENABLED
-
struct MethodDefinition {
StringName name;
Vector<StringName> args;
@@ -72,26 +70,6 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12, const char *p_arg13);
-#else
-
-//#define NO_VARIADIC_MACROS
-
-#ifdef NO_VARIADIC_MACROS
-
-static _FORCE_INLINE_ const char *D_METHOD(const char *m_name, ...) {
- return m_name;
-}
-
-#else
-
-// When DEBUG_METHODS_ENABLED is set this will let the engine know
-// the argument names for easier debugging.
-#define D_METHOD(m_c, ...) m_c
-
-#endif
-
-#endif
-
class ClassDB {
public:
enum APIType {
@@ -156,11 +134,7 @@ public:
static HashMap<StringName, StringName> resource_base_extensions;
static HashMap<StringName, StringName> compat_classes;
-#ifdef DEBUG_METHODS_ENABLED
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount);
-#else
- static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount);
-#endif
static APIType current_api;
@@ -190,6 +164,7 @@ public:
t->creation_func = &creator<T>;
t->exposed = true;
t->class_ptr = T::get_class_ptr_static();
+ t->api = current_api;
T::register_custom_data_to_otdb();
}
@@ -201,6 +176,7 @@ public:
ERR_FAIL_COND(!t);
t->exposed = true;
t->class_ptr = T::get_class_ptr_static();
+ t->api = current_api;
//nothing
}
@@ -221,6 +197,7 @@ public:
t->creation_func = &_create_ptr_func<T>;
t->exposed = true;
t->class_ptr = T::get_class_ptr_static();
+ t->api = current_api;
T::register_custom_data_to_otdb();
}
@@ -234,7 +211,7 @@ public:
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
static bool can_instantiate(const StringName &p_class);
static Object *instantiate(const StringName &p_class);
- static void instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance, Object *p_base);
+ static void set_object_extension_instance(Object *p_object, const StringName &p_class, GDExtensionClassInstancePtr p_instance);
static APIType get_api_type(const StringName &p_class);
@@ -353,7 +330,7 @@ public:
static void add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix = "");
static void add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix = "");
- static void add_property_array_count(const StringName &p_class, const String &p_label, const StringName &p_count_property, const StringName &p_count_setter, const StringName &p_count_getter, const String &p_array_element_prefix, uint32_t p_count_usage = PROPERTY_USAGE_EDITOR);
+ static void add_property_array_count(const StringName &p_class, const String &p_label, const StringName &p_count_property, const StringName &p_count_setter, const StringName &p_count_getter, const String &p_array_element_prefix, uint32_t p_count_usage = PROPERTY_USAGE_DEFAULT);
static void add_property_array(const StringName &p_class, const StringName &p_path, const String &p_array_element_prefix);
static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
static void set_property_default_value(const StringName &p_class, const StringName &p_name, const Variant &p_default);
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
index 86c2891e5d..e961745d96 100644
--- a/core/object/make_virtuals.py
+++ b/core/object/make_virtuals.py
@@ -1,7 +1,8 @@
proto = """
#define GDVIRTUAL$VER($RET m_name $ARG) \\
StringName _gdvirtual_##m_name##_sn = #m_name;\\
-GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
+mutable bool _gdvirtual_##m_name##_initialized = false;\\
+mutable GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = nullptr;\\
_FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
if (script_instance) {\\
@@ -13,6 +14,10 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
return true;\\
} \\
}\\
+ if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\
+ _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
+ _gdvirtual_##m_name##_initialized = true;\\
+ }\\
if (_gdvirtual_##m_name) {\\
$CALLPTRARGS\\
$CALLPTRRETDEF\\
@@ -28,6 +33,10 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_overridden() const { \\
if (script_instance) {\\
return script_instance->has_method(_gdvirtual_##m_name##_sn);\\
}\\
+ if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\
+ _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
+ _gdvirtual_##m_name##_initialized = true;\\
+ }\\
if (_gdvirtual_##m_name) {\\
return true;\\
}\\
diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp
index 4751c69f1e..3c828eabd9 100644
--- a/core/object/message_queue.cpp
+++ b/core/object/message_queue.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -227,16 +227,16 @@ void MessageQueue::statistics() {
print_line("TOTAL BYTES: " + itos(buffer_end));
print_line("NULL count: " + itos(null_count));
- for (Map<StringName, int>::Element *E = set_count.front(); E; E = E->next()) {
- print_line("SET " + E->key() + ": " + itos(E->get()));
+ for (const KeyValue<StringName, int> &E : set_count) {
+ print_line("SET " + E.key + ": " + itos(E.value));
}
- for (Map<Callable, int>::Element *E = call_count.front(); E; E = E->next()) {
- print_line("CALL " + E->key() + ": " + itos(E->get()));
+ for (const KeyValue<Callable, int> &E : call_count) {
+ print_line("CALL " + E.key + ": " + itos(E.value));
}
- for (Map<int, int>::Element *E = notify_count.front(); E; E = E->next()) {
- print_line("NOTIFY " + itos(E->key()) + ": " + itos(E->get()));
+ for (const KeyValue<int, int> &E : notify_count) {
+ print_line("NOTIFY " + itos(E.key) + ": " + itos(E.value));
}
}
diff --git a/core/object/message_queue.h b/core/object/message_queue.h
index 1b8def62d3..a4449cf473 100644
--- a/core/object/message_queue.h
+++ b/core/object/message_queue.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/object/method_bind.cpp b/core/object/method_bind.cpp
index c53104fe3f..32269b5f19 100644
--- a/core/object/method_bind.cpp
+++ b/core/object/method_bind.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -63,12 +63,15 @@ uint32_t MethodBind::get_hash() const {
return hash;
}
-#ifdef DEBUG_METHODS_ENABLED
PropertyInfo MethodBind::get_argument_info(int p_argument) const {
ERR_FAIL_INDEX_V(p_argument, get_argument_count(), PropertyInfo());
PropertyInfo info = _gen_argument_type_info(p_argument);
+#ifdef DEBUG_METHODS_ENABLED
info.name = p_argument < arg_names.size() ? String(arg_names[p_argument]) : String("arg" + itos(p_argument));
+#else
+ info.name = String("arg" + itos(p_argument));
+#endif
return info;
}
@@ -76,7 +79,6 @@ PropertyInfo MethodBind::get_return_info() const {
return _gen_argument_type_info(-1);
}
-#endif
void MethodBind::_set_const(bool p_const) {
_const = p_const;
}
@@ -109,7 +111,6 @@ void MethodBind::set_default_arguments(const Vector<Variant> &p_defargs) {
default_argument_count = default_arguments.size();
}
-#ifdef DEBUG_METHODS_ENABLED
void MethodBind::_generate_argument_types(int p_count) {
set_argument_count(p_count);
@@ -123,17 +124,13 @@ void MethodBind::_generate_argument_types(int p_count) {
argument_types = argt;
}
-#endif
-
MethodBind::MethodBind() {
static int last_id = 0;
method_id = last_id++;
}
MethodBind::~MethodBind() {
-#ifdef DEBUG_METHODS_ENABLED
if (argument_types) {
memdelete_arr(argument_types);
}
-#endif
}
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index b0b379873e..02b73fa273 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -64,18 +64,16 @@ class MethodBind {
bool _returns = false;
protected:
-#ifdef DEBUG_METHODS_ENABLED
Variant::Type *argument_types = nullptr;
+#ifdef DEBUG_METHODS_ENABLED
Vector<StringName> arg_names;
#endif
void _set_const(bool p_const);
void _set_returns(bool p_returns);
-#ifdef DEBUG_METHODS_ENABLED
virtual Variant::Type _gen_argument_type(int p_arg) const = 0;
virtual PropertyInfo _gen_argument_type_info(int p_arg) const = 0;
void _generate_argument_types(int p_count);
-#endif
void set_argument_count(int p_count) { argument_count = p_count; }
public:
@@ -102,7 +100,6 @@ public:
}
}
-#ifdef DEBUG_METHODS_ENABLED
_FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const {
ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, Variant::NIL);
return argument_types[p_argument + 1];
@@ -111,6 +108,7 @@ public:
PropertyInfo get_argument_info(int p_argument) const;
PropertyInfo get_return_info() const;
+#ifdef DEBUG_METHODS_ENABLED
void set_argument_names(const Vector<StringName> &p_names); // Set by ClassDB, can't be inferred otherwise.
Vector<StringName> get_argument_names() const;
@@ -149,12 +147,9 @@ public:
protected:
NativeCall call_method = nullptr;
-#ifdef DEBUG_METHODS_ENABLED
MethodInfo arguments;
-#endif
public:
-#ifdef DEBUG_METHODS_ENABLED
virtual PropertyInfo _gen_argument_type_info(int p_arg) const {
if (p_arg < 0) {
return arguments.return_val;
@@ -169,13 +164,10 @@ public:
return _gen_argument_type_info(p_arg).type;
}
+#ifdef DEBUG_METHODS_ENABLED
virtual GodotTypeInfo::Metadata get_argument_meta(int) const {
return GodotTypeInfo::METADATA_NONE;
}
-#else
- virtual Variant::Type _gen_argument_type(int p_arg) const {
- return Variant::NIL;
- }
#endif
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
@@ -185,25 +177,29 @@ public:
void set_method_info(const MethodInfo &p_info, bool p_return_nil_is_variant) {
set_argument_count(p_info.arguments.size());
-#ifdef DEBUG_METHODS_ENABLED
Variant::Type *at = memnew_arr(Variant::Type, p_info.arguments.size() + 1);
at[0] = p_info.return_val.type;
if (p_info.arguments.size()) {
+#ifdef DEBUG_METHODS_ENABLED
Vector<StringName> names;
names.resize(p_info.arguments.size());
+#endif
for (int i = 0; i < p_info.arguments.size(); i++) {
at[i + 1] = p_info.arguments[i].type;
+#ifdef DEBUG_METHODS_ENABLED
names.write[i] = p_info.arguments[i].name;
+#endif
}
+#ifdef DEBUG_METHODS_ENABLED
set_argument_names(names);
+#endif
}
argument_types = at;
arguments = p_info;
if (p_return_nil_is_variant) {
arguments.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
}
-#endif
}
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) {
@@ -248,7 +244,6 @@ class MethodBindT : public MethodBind {
void (MB_T::*method)(P...);
protected:
-#ifdef DEBUG_METHODS_ENABLED
// GCC raises warnings in the case P = {} as the comparison is always false...
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@@ -270,7 +265,6 @@ protected:
call_get_argument_type_info<P...>(p_arg, pi);
return pi;
}
-#endif
public:
#ifdef DEBUG_METHODS_ENABLED
@@ -298,9 +292,7 @@ public:
MethodBindT(void (MB_T::*p_method)(P...)) {
method = p_method;
-#ifdef DEBUG_METHODS_ENABLED
_generate_argument_types(sizeof...(P));
-#endif
set_argument_count(sizeof...(P));
}
};
@@ -327,7 +319,6 @@ class MethodBindTC : public MethodBind {
void (MB_T::*method)(P...) const;
protected:
-#ifdef DEBUG_METHODS_ENABLED
// GCC raises warnings in the case P = {} as the comparison is always false...
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@@ -349,7 +340,6 @@ protected:
call_get_argument_type_info<P...>(p_arg, pi);
return pi;
}
-#endif
public:
#ifdef DEBUG_METHODS_ENABLED
@@ -378,9 +368,7 @@ public:
MethodBindTC(void (MB_T::*p_method)(P...) const) {
method = p_method;
_set_const(true);
-#ifdef DEBUG_METHODS_ENABLED
_generate_argument_types(sizeof...(P));
-#endif
set_argument_count(sizeof...(P));
}
};
@@ -408,7 +396,6 @@ class MethodBindTR : public MethodBind {
(P...);
protected:
-#ifdef DEBUG_METHODS_ENABLED
// GCC raises warnings in the case P = {} as the comparison is always false...
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@@ -434,7 +421,6 @@ protected:
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
-#endif
public:
#ifdef DEBUG_METHODS_ENABLED
@@ -468,9 +454,7 @@ public:
MethodBindTR(R (MB_T::*p_method)(P...)) {
method = p_method;
_set_returns(true);
-#ifdef DEBUG_METHODS_ENABLED
_generate_argument_types(sizeof...(P));
-#endif
set_argument_count(sizeof...(P));
}
};
@@ -499,7 +483,6 @@ class MethodBindTRC : public MethodBind {
(P...) const;
protected:
-#ifdef DEBUG_METHODS_ENABLED
// GCC raises warnings in the case P = {} as the comparison is always false...
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@@ -525,7 +508,6 @@ protected:
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
-#endif
public:
#ifdef DEBUG_METHODS_ENABLED
@@ -560,9 +542,7 @@ public:
method = p_method;
_set_returns(true);
_set_const(true);
-#ifdef DEBUG_METHODS_ENABLED
_generate_argument_types(sizeof...(P));
-#endif
set_argument_count(sizeof...(P));
}
};
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 3335942fb3..f966607e03 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -628,7 +628,10 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
script_instance->get_property_list(p_list);
}
- _get_property_listv(p_list, p_reversed);
+ if (_extension) {
+ p_list->push_back(PropertyInfo(Variant::NIL, _extension->class_name, PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
+ ClassDB::get_property_list(_extension->class_name, p_list, true, this);
+ }
if (_extension && _extension->get_property_list) {
uint32_t pcount;
@@ -641,11 +644,13 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
}
}
+ _get_property_listv(p_list, p_reversed);
+
if (!is_class("Script")) { // can still be set, but this is for user-friendliness
p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
}
if (!metadata.is_empty()) {
- p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
}
if (script_instance && !p_reversed) {
p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
@@ -985,7 +990,7 @@ void Object::get_meta_list(List<StringName> *p_list) const {
}
void Object::add_user_signal(const MethodInfo &p_signal) {
- ERR_FAIL_COND_MSG(p_signal.name == "", "Signal name cannot be empty.");
+ ERR_FAIL_COND_MSG(p_signal.name.is_empty(), "Signal name cannot be empty.");
ERR_FAIL_COND_MSG(ClassDB::has_signal(get_class_name(), p_signal.name), "User signal's name conflicts with a built-in signal of '" + get_class_name() + "'.");
ERR_FAIL_COND_MSG(signal_map.has(p_signal.name), "Trying to add already existing signal '" + p_signal.name + "'.");
SignalData s;
@@ -1248,7 +1253,7 @@ void Object::get_signal_list(List<MethodInfo> *p_signals) const {
const StringName *S = nullptr;
while ((S = signal_map.next(S))) {
- if (signal_map[*S].user.name != "") {
+ if (!signal_map[*S].user.name.is_empty()) {
//user signal
p_signals->push_back(signal_map[*S].user);
}
@@ -1398,18 +1403,18 @@ void Object::_disconnect(const StringName &p_signal, const Callable &p_callable,
SignalData *s = signal_map.getptr(p_signal);
if (!s) {
bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal) ||
- (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal));
+ (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal));
ERR_FAIL_COND_MSG(signal_is_valid, "Attempt to disconnect a nonexistent connection from '" + to_string() + "'. Signal: '" + p_signal + "', callable: '" + p_callable + "'.");
}
ERR_FAIL_COND_MSG(!s, vformat("Disconnecting nonexistent signal '%s' in %s.", p_signal, to_string()));
ERR_FAIL_COND_MSG(!s->slot_map.has(*p_callable.get_base_comparator()), "Disconnecting nonexistent signal '" + p_signal + "', callable: " + p_callable + ".");
- SignalData::Slot *slot = &s->slot_map[p_callable];
+ SignalData::Slot *slot = &s->slot_map[*p_callable.get_base_comparator()];
if (!p_force) {
slot->reference_count--; // by default is zero, if it was not referenced it will go below it
- if (slot->reference_count >= 0) {
+ if (slot->reference_count > 0) {
return;
}
}
@@ -1475,7 +1480,7 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) {
return;
}
- if (!r->get_path().begins_with("res://") || r->get_path().find("::") == -1) {
+ if (!r->is_built_in()) {
return; //not an internal resource
}
@@ -1675,7 +1680,7 @@ void Object::get_translatable_strings(List<String> *p_strings) const {
String text = get(E.name);
- if (text == "") {
+ if (text.is_empty()) {
continue;
}
@@ -1833,8 +1838,6 @@ void Object::_construct_object(bool p_reference) {
type_is_reference = p_reference;
_instance_id = ObjectDB::add_instance(this);
- ClassDB::instance_get_native_extension_data(&_extension, &_extension_instance, this);
-
#ifdef DEBUG_ENABLED
_lock_index.init(1);
#endif
diff --git a/core/object/object.h b/core/object/object.h
index a44d921bff..602bd3cda1 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -52,10 +52,6 @@
#define VARIANT_ARGPTRS_PASS *argptr[0], *argptr[1], *argptr[2], *argptr[3], *argptr[4], *argptr[5], *argptr[6]], *argptr[7]
#define VARIANT_ARGS_FROM_ARRAY(m_arr) m_arr[0], m_arr[1], m_arr[2], m_arr[3], m_arr[4], m_arr[5], m_arr[6], m_arr[7]
-/**
-@author Juan Linietsky <reduzio@gmail.com>
-*/
-
enum PropertyHint {
PROPERTY_HINT_NONE, ///< no hint provided.
PROPERTY_HINT_RANGE, ///< hint_text = "min,max[,step][,or_greater][,or_lesser][,noslider][,radians][,degrees][,exp][,suffix:<keyword>] range.
@@ -137,7 +133,7 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK,
PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED,
- PROPERTY_USAGE_NOEDITOR = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_NETWORK,
+ PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_NETWORK,
};
#define ADD_SIGNAL(m_signal) ::ClassDB::add_signal(get_class_static(), m_signal)
@@ -284,7 +280,6 @@ struct ObjectNativeExtension {
GDNativeExtensionClassCreateInstance create_instance;
GDNativeExtensionClassFreeInstance free_instance;
- GDNativeExtensionClassObjectInstance set_object_instance;
GDNativeExtensionClassGetVirtual get_virtual;
};
@@ -353,16 +348,13 @@ public:
static String get_category_static() { \
String category = m_inherits::get_category_static(); \
if (_get_category != m_inherits::_get_category) { \
- if (category != "") { \
+ if (!category.is_empty()) { \
category += "/"; \
} \
category += _get_category(); \
} \
return category; \
} \
- static String inherits_static() { \
- return String(#m_inherits); \
- } \
virtual bool is_class(const String &p_class) const override { \
if (_get_extension() && _get_extension()->is_class(p_class)) { \
return true; \
@@ -403,7 +395,7 @@ protected:
initialize_class(); \
} \
_FORCE_INLINE_ bool (Object::*_get_get() const)(const StringName &p_name, Variant &) const { \
- return (bool (Object::*)(const StringName &, Variant &) const) & m_class::_get; \
+ return (bool(Object::*)(const StringName &, Variant &) const) & m_class::_get; \
} \
virtual bool _getv(const StringName &p_name, Variant &r_ret) const override { \
if (m_class::_get_get() != m_inherits::_get_get()) { \
@@ -414,7 +406,7 @@ protected:
return m_inherits::_getv(p_name, r_ret); \
} \
_FORCE_INLINE_ bool (Object::*_get_set() const)(const StringName &p_name, const Variant &p_property) { \
- return (bool (Object::*)(const StringName &, const Variant &)) & m_class::_set; \
+ return (bool(Object::*)(const StringName &, const Variant &)) & m_class::_set; \
} \
virtual bool _setv(const StringName &p_name, const Variant &p_property) override { \
if (m_inherits::_setv(p_name, p_property)) { \
@@ -426,7 +418,7 @@ protected:
return false; \
} \
_FORCE_INLINE_ void (Object::*_get_get_property_list() const)(List<PropertyInfo> * p_list) const { \
- return (void (Object::*)(List<PropertyInfo> *) const) & m_class::_get_property_list; \
+ return (void(Object::*)(List<PropertyInfo> *) const) & m_class::_get_property_list; \
} \
virtual void _get_property_listv(List<PropertyInfo> *p_list, bool p_reversed) const override { \
if (!p_reversed) { \
@@ -447,7 +439,7 @@ protected:
} \
} \
_FORCE_INLINE_ void (Object::*_get_notification() const)(int) { \
- return (void (Object::*)(int)) & m_class::_notification; \
+ return (void(Object::*)(int)) & m_class::_notification; \
} \
virtual void _notificationv(int p_notification, bool p_reversed) override { \
if (!p_reversed) { \
diff --git a/core/object/object_id.h b/core/object/object_id.h
index 0666ec0855..a36997630f 100644
--- a/core/object/object_id.h
+++ b/core/object/object_id.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/object/ref_counted.cpp b/core/object/ref_counted.cpp
index 2833f774dc..c9a7b2a608 100644
--- a/core/object/ref_counted.cpp
+++ b/core/object/ref_counted.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h
index f2dd2aa324..8eb1c97cce 100644
--- a/core/object/ref_counted.h
+++ b/core/object/ref_counted.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 0fb8c7350c..9fec7c397d 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -93,8 +93,8 @@ Dictionary Script::_get_script_constant_map() {
Dictionary ret;
Map<StringName, Variant> map;
get_constants(&map);
- for (Map<StringName, Variant>::Element *E = map.front(); E; E = E->next()) {
- ret[E->key()] = E->value();
+ for (const KeyValue<StringName, Variant> &E : map) {
+ ret[E.key] = E.value;
}
return ret;
}
@@ -511,7 +511,7 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c
Variant defval;
if (script->get_property_default_value(E->key(), defval)) {
//remove because it's the same as the default value
- if (defval == E) {
+ if (defval == E->get()) {
to_remove.push_back(E->key());
}
}
@@ -549,7 +549,7 @@ void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name,
}
}
if (!found) {
- properties.push_back(PropertyInfo(p_value.get_type(), p_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_SCRIPT_VARIABLE));
+ properties.push_back(PropertyInfo(p_value.get_type(), p_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_SCRIPT_VARIABLE));
}
}
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 8d76cbf479..4b18d9a5e8 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -227,6 +227,7 @@ struct ScriptCodeCompletionOption {
Color font_color;
RES icon;
Variant default_value;
+ Vector<Pair<int, int>> matches;
ScriptCodeCompletionOption() {}
@@ -274,13 +275,32 @@ public:
String message;
};
+ enum TemplateLocation {
+ TEMPLATE_BUILT_IN,
+ TEMPLATE_EDITOR,
+ TEMPLATE_PROJECT
+ };
+
+ struct ScriptTemplate {
+ String inherit = "Object";
+ String name;
+ String description;
+ String content;
+ int id = 0;
+ TemplateLocation origin = TemplateLocation::TEMPLATE_BUILT_IN;
+
+ String get_hash() const {
+ return itos(origin) + inherit + name;
+ }
+ };
+
void get_core_type_words(List<String> *p_core_type_words) const;
virtual void get_reserved_words(List<String> *p_words) const = 0;
virtual bool is_control_flow_keyword(String p_string) const = 0;
virtual void get_comment_delimiters(List<String> *p_delimiters) const = 0;
virtual void get_string_delimiters(List<String> *p_delimiters) const = 0;
- virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const = 0;
- virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) {}
+ virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const { return Ref<Script>(); }
+ virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) { return Vector<ScriptTemplate>(); }
virtual bool is_using_templates() { return false; }
virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptError> *r_errors = nullptr, List<Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const = 0;
virtual String validate_path(const String &p_path) const { return ""; }
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index b7d2bac96d..f72dec8edf 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,7 @@
#include "core/io/resource.h"
#include "core/os/os.h"
+#include "core/templates/local_vector.h"
void UndoRedo::_discard_redo() {
if (current_action == actions.size() - 1) {
@@ -75,7 +76,7 @@ bool UndoRedo::_redo(bool p_execute) {
}
void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
- uint32_t ticks = OS::get_singleton()->get_ticks_msec();
+ uint64_t ticks = OS::get_singleton()->get_ticks_msec();
if (action_level == 0) {
_discard_redo();
@@ -85,10 +86,17 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
current_action = actions.size() - 2;
if (p_mode == MERGE_ENDS) {
- // Clear all do ops from last action, and delete all object references
- List<Operation>::Element *E = actions.write[current_action + 1].do_ops.front();
+ // Clear all do ops from last action if they are not forced kept
+ LocalVector<List<Operation>::Element *> to_remove;
+ for (List<Operation>::Element *E = actions.write[current_action + 1].do_ops.front(); E; E = E->next()) {
+ if (!E->get().force_keep_in_merge_ends) {
+ to_remove.push_back(E);
+ }
+ }
- while (E) {
+ for (unsigned int i = 0; i < to_remove.size(); i++) {
+ List<Operation>::Element *E = to_remove[i];
+ // Delete all object references
if (E->get().type == Operation::TYPE_REFERENCE) {
Object *obj = ObjectDB::get_instance(E->get().object);
@@ -96,9 +104,7 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
memdelete(obj);
}
}
-
- E = E->next();
- actions.write[current_action + 1].do_ops.pop_front();
+ E->erase();
}
}
@@ -117,6 +123,8 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
}
action_level++;
+
+ force_keep_in_merge_ends = false;
}
void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {
@@ -146,7 +154,7 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR
ERR_FAIL_COND((current_action + 1) >= actions.size());
// No undo if the merge mode is MERGE_ENDS
- if (merge_mode == MERGE_ENDS) {
+ if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) {
return;
}
@@ -157,6 +165,7 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR
}
undo_op.type = Operation::TYPE_METHOD;
+ undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
undo_op.name = p_method;
for (int i = 0; i < VARIANT_ARG_MAX; i++) {
@@ -187,7 +196,7 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property,
ERR_FAIL_COND((current_action + 1) >= actions.size());
// No undo if the merge mode is MERGE_ENDS
- if (merge_mode == MERGE_ENDS) {
+ if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) {
return;
}
@@ -198,6 +207,7 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property,
}
undo_op.type = Operation::TYPE_PROPERTY;
+ undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
undo_op.name = p_property;
undo_op.args[0] = p_value;
actions.write[current_action + 1].undo_ops.push_back(undo_op);
@@ -223,7 +233,7 @@ void UndoRedo::add_undo_reference(Object *p_object) {
ERR_FAIL_COND((current_action + 1) >= actions.size());
// No undo if the merge mode is MERGE_ENDS
- if (merge_mode == MERGE_ENDS) {
+ if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) {
return;
}
@@ -234,9 +244,24 @@ void UndoRedo::add_undo_reference(Object *p_object) {
}
undo_op.type = Operation::TYPE_REFERENCE;
+ undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
actions.write[current_action + 1].undo_ops.push_back(undo_op);
}
+void UndoRedo::start_force_keep_in_merge_ends() {
+ ERR_FAIL_COND(action_level <= 0);
+ ERR_FAIL_COND((current_action + 1) >= actions.size());
+
+ force_keep_in_merge_ends = true;
+}
+
+void UndoRedo::end_force_keep_in_merge_ends() {
+ ERR_FAIL_COND(action_level <= 0);
+ ERR_FAIL_COND((current_action + 1) >= actions.size());
+
+ force_keep_in_merge_ends = false;
+}
+
void UndoRedo::_pop_history_tail() {
_discard_redo();
@@ -257,7 +282,7 @@ void UndoRedo::_pop_history_tail() {
}
}
- actions.remove(0);
+ actions.remove_at(0);
if (current_action >= 0) {
current_action--;
}
@@ -538,6 +563,9 @@ void UndoRedo::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_do_reference", "object"), &UndoRedo::add_do_reference);
ClassDB::bind_method(D_METHOD("add_undo_reference", "object"), &UndoRedo::add_undo_reference);
+ ClassDB::bind_method(D_METHOD("start_force_keep_in_merge_ends"), &UndoRedo::start_force_keep_in_merge_ends);
+ ClassDB::bind_method(D_METHOD("end_force_keep_in_merge_ends"), &UndoRedo::end_force_keep_in_merge_ends);
+
ClassDB::bind_method(D_METHOD("get_history_count"), &UndoRedo::get_history_count);
ClassDB::bind_method(D_METHOD("get_current_action"), &UndoRedo::get_current_action);
ClassDB::bind_method(D_METHOD("get_action_name", "id"), &UndoRedo::get_action_name);
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index d1ce252d86..75639f8abf 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -61,6 +61,7 @@ private:
};
Type type;
+ bool force_keep_in_merge_ends;
Ref<RefCounted> ref;
ObjectID object;
StringName name;
@@ -76,6 +77,7 @@ private:
Vector<Action> actions;
int current_action = -1;
+ bool force_keep_in_merge_ends = false;
int action_level = 0;
MergeMode merge_mode = MERGE_DISABLE;
bool merging = false;
@@ -109,6 +111,9 @@ public:
void add_do_reference(Object *p_object);
void add_undo_reference(Object *p_object);
+ void start_force_keep_in_merge_ends();
+ void end_force_keep_in_merge_ends();
+
bool is_committing_action() const;
void commit_action(bool p_execute = true);
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index 4c5f0b5220..3a03c0a10b 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,400 +33,399 @@
#include "core/os/os.h"
struct _KeyCodeText {
- int code;
+ Key code;
const char *text;
};
static const _KeyCodeText _keycodes[] = {
/* clang-format off */
- {KEY_ESCAPE ,"Escape"},
- {KEY_TAB ,"Tab"},
- {KEY_BACKTAB ,"BackTab"},
- {KEY_BACKSPACE ,"BackSpace"},
- {KEY_ENTER ,"Enter"},
- {KEY_KP_ENTER ,"Kp Enter"},
- {KEY_INSERT ,"Insert"},
- {KEY_DELETE ,"Delete"},
- {KEY_PAUSE ,"Pause"},
- {KEY_PRINT ,"Print"},
- {KEY_SYSREQ ,"SysReq"},
- {KEY_CLEAR ,"Clear"},
- {KEY_HOME ,"Home"},
- {KEY_END ,"End"},
- {KEY_LEFT ,"Left"},
- {KEY_UP ,"Up"},
- {KEY_RIGHT ,"Right"},
- {KEY_DOWN ,"Down"},
- {KEY_PAGEUP ,"PageUp"},
- {KEY_PAGEDOWN ,"PageDown"},
- {KEY_SHIFT ,"Shift"},
- {KEY_CTRL ,"Ctrl"},
+ {Key::ESCAPE ,"Escape"},
+ {Key::TAB ,"Tab"},
+ {Key::BACKTAB ,"BackTab"},
+ {Key::BACKSPACE ,"BackSpace"},
+ {Key::ENTER ,"Enter"},
+ {Key::KP_ENTER ,"Kp Enter"},
+ {Key::INSERT ,"Insert"},
+ {Key::KEY_DELETE ,"Delete"},
+ {Key::PAUSE ,"Pause"},
+ {Key::PRINT ,"Print"},
+ {Key::SYSREQ ,"SysReq"},
+ {Key::CLEAR ,"Clear"},
+ {Key::HOME ,"Home"},
+ {Key::END ,"End"},
+ {Key::LEFT ,"Left"},
+ {Key::UP ,"Up"},
+ {Key::RIGHT ,"Right"},
+ {Key::DOWN ,"Down"},
+ {Key::PAGEUP ,"PageUp"},
+ {Key::PAGEDOWN ,"PageDown"},
+ {Key::SHIFT ,"Shift"},
+ {Key::CTRL ,"Ctrl"},
#ifdef OSX_ENABLED
- {KEY_META ,"Command"},
+ {Key::META ,"Command"},
#else
- {KEY_META ,"Meta"},
+ {Key::META ,"Meta"},
#endif
- {KEY_ALT ,"Alt"},
- {KEY_CAPSLOCK ,"CapsLock"},
- {KEY_NUMLOCK ,"NumLock"},
- {KEY_SCROLLLOCK ,"ScrollLock"},
- {KEY_F1 ,"F1"},
- {KEY_F2 ,"F2"},
- {KEY_F3 ,"F3"},
- {KEY_F4 ,"F4"},
- {KEY_F5 ,"F5"},
- {KEY_F6 ,"F6"},
- {KEY_F7 ,"F7"},
- {KEY_F8 ,"F8"},
- {KEY_F9 ,"F9"},
- {KEY_F10 ,"F10"},
- {KEY_F11 ,"F11"},
- {KEY_F12 ,"F12"},
- {KEY_F13 ,"F13"},
- {KEY_F14 ,"F14"},
- {KEY_F15 ,"F15"},
- {KEY_F16 ,"F16"},
- {KEY_KP_MULTIPLY ,"Kp Multiply"},
- {KEY_KP_DIVIDE ,"Kp Divide"},
- {KEY_KP_SUBTRACT ,"Kp Subtract"},
- {KEY_KP_PERIOD ,"Kp Period"},
- {KEY_KP_ADD ,"Kp Add"},
- {KEY_KP_0 ,"Kp 0"},
- {KEY_KP_1 ,"Kp 1"},
- {KEY_KP_2 ,"Kp 2"},
- {KEY_KP_3 ,"Kp 3"},
- {KEY_KP_4 ,"Kp 4"},
- {KEY_KP_5 ,"Kp 5"},
- {KEY_KP_6 ,"Kp 6"},
- {KEY_KP_7 ,"Kp 7"},
- {KEY_KP_8 ,"Kp 8"},
- {KEY_KP_9 ,"Kp 9"},
- {KEY_SUPER_L ,"Super L"},
- {KEY_SUPER_R ,"Super R"},
- {KEY_MENU ,"Menu"},
- {KEY_HYPER_L ,"Hyper L"},
- {KEY_HYPER_R ,"Hyper R"},
- {KEY_HELP ,"Help"},
- {KEY_DIRECTION_L ,"Direction L"},
- {KEY_DIRECTION_R ,"Direction R"},
- {KEY_BACK ,"Back"},
- {KEY_FORWARD ,"Forward"},
- {KEY_STOP ,"Stop"},
- {KEY_REFRESH ,"Refresh"},
- {KEY_VOLUMEDOWN ,"VolumeDown"},
- {KEY_VOLUMEMUTE ,"VolumeMute"},
- {KEY_VOLUMEUP ,"VolumeUp"},
- {KEY_BASSBOOST ,"BassBoost"},
- {KEY_BASSUP ,"BassUp"},
- {KEY_BASSDOWN ,"BassDown"},
- {KEY_TREBLEUP ,"TrebleUp"},
- {KEY_TREBLEDOWN ,"TrebleDown"},
- {KEY_MEDIAPLAY ,"MediaPlay"},
- {KEY_MEDIASTOP ,"MediaStop"},
- {KEY_MEDIAPREVIOUS ,"MediaPrevious"},
- {KEY_MEDIANEXT ,"MediaNext"},
- {KEY_MEDIARECORD ,"MediaRecord"},
- {KEY_HOMEPAGE ,"HomePage"},
- {KEY_FAVORITES ,"Favorites"},
- {KEY_SEARCH ,"Search"},
- {KEY_STANDBY ,"StandBy"},
- {KEY_LAUNCHMAIL ,"LaunchMail"},
- {KEY_LAUNCHMEDIA ,"LaunchMedia"},
- {KEY_LAUNCH0 ,"Launch0"},
- {KEY_LAUNCH1 ,"Launch1"},
- {KEY_LAUNCH2 ,"Launch2"},
- {KEY_LAUNCH3 ,"Launch3"},
- {KEY_LAUNCH4 ,"Launch4"},
- {KEY_LAUNCH5 ,"Launch5"},
- {KEY_LAUNCH6 ,"Launch6"},
- {KEY_LAUNCH7 ,"Launch7"},
- {KEY_LAUNCH8 ,"Launch8"},
- {KEY_LAUNCH9 ,"Launch9"},
- {KEY_LAUNCHA ,"LaunchA"},
- {KEY_LAUNCHB ,"LaunchB"},
- {KEY_LAUNCHC ,"LaunchC"},
- {KEY_LAUNCHD ,"LaunchD"},
- {KEY_LAUNCHE ,"LaunchE"},
- {KEY_LAUNCHF ,"LaunchF"},
-
- {KEY_UNKNOWN ,"Unknown"},
-
- {KEY_SPACE ,"Space"},
- {KEY_EXCLAM ,"Exclam"},
- {KEY_QUOTEDBL ,"QuoteDbl"},
- {KEY_NUMBERSIGN ,"NumberSign"},
- {KEY_DOLLAR ,"Dollar"},
- {KEY_PERCENT ,"Percent"},
- {KEY_AMPERSAND ,"Ampersand"},
- {KEY_APOSTROPHE ,"Apostrophe"},
- {KEY_PARENLEFT ,"ParenLeft"},
- {KEY_PARENRIGHT ,"ParenRight"},
- {KEY_ASTERISK ,"Asterisk"},
- {KEY_PLUS ,"Plus"},
- {KEY_COMMA ,"Comma"},
- {KEY_MINUS ,"Minus"},
- {KEY_PERIOD ,"Period"},
- {KEY_SLASH ,"Slash"},
- {KEY_0 ,"0"},
- {KEY_1 ,"1"},
- {KEY_2 ,"2"},
- {KEY_3 ,"3"},
- {KEY_4 ,"4"},
- {KEY_5 ,"5"},
- {KEY_6 ,"6"},
- {KEY_7 ,"7"},
- {KEY_8 ,"8"},
- {KEY_9 ,"9"},
- {KEY_COLON ,"Colon"},
- {KEY_SEMICOLON ,"Semicolon"},
- {KEY_LESS ,"Less"},
- {KEY_EQUAL ,"Equal"},
- {KEY_GREATER ,"Greater"},
- {KEY_QUESTION ,"Question"},
- {KEY_AT ,"At"},
- {KEY_A ,"A"},
- {KEY_B ,"B"},
- {KEY_C ,"C"},
- {KEY_D ,"D"},
- {KEY_E ,"E"},
- {KEY_F ,"F"},
- {KEY_G ,"G"},
- {KEY_H ,"H"},
- {KEY_I ,"I"},
- {KEY_J ,"J"},
- {KEY_K ,"K"},
- {KEY_L ,"L"},
- {KEY_M ,"M"},
- {KEY_N ,"N"},
- {KEY_O ,"O"},
- {KEY_P ,"P"},
- {KEY_Q ,"Q"},
- {KEY_R ,"R"},
- {KEY_S ,"S"},
- {KEY_T ,"T"},
- {KEY_U ,"U"},
- {KEY_V ,"V"},
- {KEY_W ,"W"},
- {KEY_X ,"X"},
- {KEY_Y ,"Y"},
- {KEY_Z ,"Z"},
- {KEY_BRACKETLEFT ,"BracketLeft"},
- {KEY_BACKSLASH ,"BackSlash"},
- {KEY_BRACKETRIGHT ,"BracketRight"},
- {KEY_ASCIICIRCUM ,"AsciiCircum"},
- {KEY_UNDERSCORE ,"UnderScore"},
- {KEY_QUOTELEFT ,"QuoteLeft"},
- {KEY_BRACELEFT ,"BraceLeft"},
- {KEY_BAR ,"Bar"},
- {KEY_BRACERIGHT ,"BraceRight"},
- {KEY_ASCIITILDE ,"AsciiTilde"},
- {KEY_NOBREAKSPACE ,"NoBreakSpace"},
- {KEY_EXCLAMDOWN ,"ExclamDown"},
- {KEY_CENT ,"Cent"},
- {KEY_STERLING ,"Sterling"},
- {KEY_CURRENCY ,"Currency"},
- {KEY_YEN ,"Yen"},
- {KEY_BROKENBAR ,"BrokenBar"},
- {KEY_SECTION ,"Section"},
- {KEY_DIAERESIS ,"Diaeresis"},
- {KEY_COPYRIGHT ,"Copyright"},
- {KEY_ORDFEMININE ,"Ordfeminine"},
- {KEY_GUILLEMOTLEFT ,"GuillemotLeft"},
- {KEY_NOTSIGN ,"NotSign"},
- {KEY_HYPHEN ,"Hyphen"},
- {KEY_REGISTERED ,"Registered"},
- {KEY_MACRON ,"Macron"},
- {KEY_DEGREE ,"Degree"},
- {KEY_PLUSMINUS ,"PlusMinus"},
- {KEY_TWOSUPERIOR ,"TwoSuperior"},
- {KEY_THREESUPERIOR ,"ThreeSuperior"},
- {KEY_ACUTE ,"Acute"},
- {KEY_MU ,"Mu"},
- {KEY_PARAGRAPH ,"Paragraph"},
- {KEY_PERIODCENTERED ,"PeriodCentered"},
- {KEY_CEDILLA ,"Cedilla"},
- {KEY_ONESUPERIOR ,"OneSuperior"},
- {KEY_MASCULINE ,"Masculine"},
- {KEY_GUILLEMOTRIGHT ,"GuillemotRight"},
- {KEY_ONEQUARTER ,"OneQuarter"},
- {KEY_ONEHALF ,"OneHalf"},
- {KEY_THREEQUARTERS ,"ThreeQuarters"},
- {KEY_QUESTIONDOWN ,"QuestionDown"},
- {KEY_AGRAVE ,"Agrave"},
- {KEY_AACUTE ,"Aacute"},
- {KEY_ACIRCUMFLEX ,"AcircumFlex"},
- {KEY_ATILDE ,"Atilde"},
- {KEY_ADIAERESIS ,"Adiaeresis"},
- {KEY_ARING ,"Aring"},
- {KEY_AE ,"Ae"},
- {KEY_CCEDILLA ,"Ccedilla"},
- {KEY_EGRAVE ,"Egrave"},
- {KEY_EACUTE ,"Eacute"},
- {KEY_ECIRCUMFLEX ,"Ecircumflex"},
- {KEY_EDIAERESIS ,"Ediaeresis"},
- {KEY_IGRAVE ,"Igrave"},
- {KEY_IACUTE ,"Iacute"},
- {KEY_ICIRCUMFLEX ,"Icircumflex"},
- {KEY_IDIAERESIS ,"Idiaeresis"},
- {KEY_ETH ,"Eth"},
- {KEY_NTILDE ,"Ntilde"},
- {KEY_OGRAVE ,"Ograve"},
- {KEY_OACUTE ,"Oacute"},
- {KEY_OCIRCUMFLEX ,"Ocircumflex"},
- {KEY_OTILDE ,"Otilde"},
- {KEY_ODIAERESIS ,"Odiaeresis"},
- {KEY_MULTIPLY ,"Multiply"},
- {KEY_OOBLIQUE ,"Ooblique"},
- {KEY_UGRAVE ,"Ugrave"},
- {KEY_UACUTE ,"Uacute"},
- {KEY_UCIRCUMFLEX ,"Ucircumflex"},
- {KEY_UDIAERESIS ,"Udiaeresis"},
- {KEY_YACUTE ,"Yacute"},
- {KEY_THORN ,"Thorn"},
- {KEY_SSHARP ,"Ssharp"},
-
- {KEY_DIVISION ,"Division"},
- {KEY_YDIAERESIS ,"Ydiaeresis"},
- {0 ,nullptr}
+ {Key::ALT ,"Alt"},
+ {Key::CAPSLOCK ,"CapsLock"},
+ {Key::NUMLOCK ,"NumLock"},
+ {Key::SCROLLLOCK ,"ScrollLock"},
+ {Key::F1 ,"F1"},
+ {Key::F2 ,"F2"},
+ {Key::F3 ,"F3"},
+ {Key::F4 ,"F4"},
+ {Key::F5 ,"F5"},
+ {Key::F6 ,"F6"},
+ {Key::F7 ,"F7"},
+ {Key::F8 ,"F8"},
+ {Key::F9 ,"F9"},
+ {Key::F10 ,"F10"},
+ {Key::F11 ,"F11"},
+ {Key::F12 ,"F12"},
+ {Key::F13 ,"F13"},
+ {Key::F14 ,"F14"},
+ {Key::F15 ,"F15"},
+ {Key::F16 ,"F16"},
+ {Key::KP_MULTIPLY ,"Kp Multiply"},
+ {Key::KP_DIVIDE ,"Kp Divide"},
+ {Key::KP_SUBTRACT ,"Kp Subtract"},
+ {Key::KP_PERIOD ,"Kp Period"},
+ {Key::KP_ADD ,"Kp Add"},
+ {Key::KP_0 ,"Kp 0"},
+ {Key::KP_1 ,"Kp 1"},
+ {Key::KP_2 ,"Kp 2"},
+ {Key::KP_3 ,"Kp 3"},
+ {Key::KP_4 ,"Kp 4"},
+ {Key::KP_5 ,"Kp 5"},
+ {Key::KP_6 ,"Kp 6"},
+ {Key::KP_7 ,"Kp 7"},
+ {Key::KP_8 ,"Kp 8"},
+ {Key::KP_9 ,"Kp 9"},
+ {Key::SUPER_L ,"Super L"},
+ {Key::SUPER_R ,"Super R"},
+ {Key::MENU ,"Menu"},
+ {Key::HYPER_L ,"Hyper L"},
+ {Key::HYPER_R ,"Hyper R"},
+ {Key::HELP ,"Help"},
+ {Key::DIRECTION_L ,"Direction L"},
+ {Key::DIRECTION_R ,"Direction R"},
+ {Key::BACK ,"Back"},
+ {Key::FORWARD ,"Forward"},
+ {Key::STOP ,"Stop"},
+ {Key::REFRESH ,"Refresh"},
+ {Key::VOLUMEDOWN ,"VolumeDown"},
+ {Key::VOLUMEMUTE ,"VolumeMute"},
+ {Key::VOLUMEUP ,"VolumeUp"},
+ {Key::BASSBOOST ,"BassBoost"},
+ {Key::BASSUP ,"BassUp"},
+ {Key::BASSDOWN ,"BassDown"},
+ {Key::TREBLEUP ,"TrebleUp"},
+ {Key::TREBLEDOWN ,"TrebleDown"},
+ {Key::MEDIAPLAY ,"MediaPlay"},
+ {Key::MEDIASTOP ,"MediaStop"},
+ {Key::MEDIAPREVIOUS ,"MediaPrevious"},
+ {Key::MEDIANEXT ,"MediaNext"},
+ {Key::MEDIARECORD ,"MediaRecord"},
+ {Key::HOMEPAGE ,"HomePage"},
+ {Key::FAVORITES ,"Favorites"},
+ {Key::SEARCH ,"Search"},
+ {Key::STANDBY ,"StandBy"},
+ {Key::LAUNCHMAIL ,"LaunchMail"},
+ {Key::LAUNCHMEDIA ,"LaunchMedia"},
+ {Key::LAUNCH0 ,"Launch0"},
+ {Key::LAUNCH1 ,"Launch1"},
+ {Key::LAUNCH2 ,"Launch2"},
+ {Key::LAUNCH3 ,"Launch3"},
+ {Key::LAUNCH4 ,"Launch4"},
+ {Key::LAUNCH5 ,"Launch5"},
+ {Key::LAUNCH6 ,"Launch6"},
+ {Key::LAUNCH7 ,"Launch7"},
+ {Key::LAUNCH8 ,"Launch8"},
+ {Key::LAUNCH9 ,"Launch9"},
+ {Key::LAUNCHA ,"LaunchA"},
+ {Key::LAUNCHB ,"LaunchB"},
+ {Key::LAUNCHC ,"LaunchC"},
+ {Key::LAUNCHD ,"LaunchD"},
+ {Key::LAUNCHE ,"LaunchE"},
+ {Key::LAUNCHF ,"LaunchF"},
+ {Key::UNKNOWN ,"Unknown"},
+ {Key::SPACE ,"Space"},
+ {Key::EXCLAM ,"Exclam"},
+ {Key::QUOTEDBL ,"QuoteDbl"},
+ {Key::NUMBERSIGN ,"NumberSign"},
+ {Key::DOLLAR ,"Dollar"},
+ {Key::PERCENT ,"Percent"},
+ {Key::AMPERSAND ,"Ampersand"},
+ {Key::APOSTROPHE ,"Apostrophe"},
+ {Key::PARENLEFT ,"ParenLeft"},
+ {Key::PARENRIGHT ,"ParenRight"},
+ {Key::ASTERISK ,"Asterisk"},
+ {Key::PLUS ,"Plus"},
+ {Key::COMMA ,"Comma"},
+ {Key::MINUS ,"Minus"},
+ {Key::PERIOD ,"Period"},
+ {Key::SLASH ,"Slash"},
+ {Key::KEY_0 ,"0"},
+ {Key::KEY_1 ,"1"},
+ {Key::KEY_2 ,"2"},
+ {Key::KEY_3 ,"3"},
+ {Key::KEY_4 ,"4"},
+ {Key::KEY_5 ,"5"},
+ {Key::KEY_6 ,"6"},
+ {Key::KEY_7 ,"7"},
+ {Key::KEY_8 ,"8"},
+ {Key::KEY_9 ,"9"},
+ {Key::COLON ,"Colon"},
+ {Key::SEMICOLON ,"Semicolon"},
+ {Key::LESS ,"Less"},
+ {Key::EQUAL ,"Equal"},
+ {Key::GREATER ,"Greater"},
+ {Key::QUESTION ,"Question"},
+ {Key::AT ,"At"},
+ {Key::A ,"A"},
+ {Key::B ,"B"},
+ {Key::C ,"C"},
+ {Key::D ,"D"},
+ {Key::E ,"E"},
+ {Key::F ,"F"},
+ {Key::G ,"G"},
+ {Key::H ,"H"},
+ {Key::I ,"I"},
+ {Key::J ,"J"},
+ {Key::K ,"K"},
+ {Key::L ,"L"},
+ {Key::M ,"M"},
+ {Key::N ,"N"},
+ {Key::O ,"O"},
+ {Key::P ,"P"},
+ {Key::Q ,"Q"},
+ {Key::R ,"R"},
+ {Key::S ,"S"},
+ {Key::T ,"T"},
+ {Key::U ,"U"},
+ {Key::V ,"V"},
+ {Key::W ,"W"},
+ {Key::X ,"X"},
+ {Key::Y ,"Y"},
+ {Key::Z ,"Z"},
+ {Key::BRACKETLEFT ,"BracketLeft"},
+ {Key::BACKSLASH ,"BackSlash"},
+ {Key::BRACKETRIGHT ,"BracketRight"},
+ {Key::ASCIICIRCUM ,"AsciiCircum"},
+ {Key::UNDERSCORE ,"UnderScore"},
+ {Key::QUOTELEFT ,"QuoteLeft"},
+ {Key::BRACELEFT ,"BraceLeft"},
+ {Key::BAR ,"Bar"},
+ {Key::BRACERIGHT ,"BraceRight"},
+ {Key::ASCIITILDE ,"AsciiTilde"},
+ {Key::NOBREAKSPACE ,"NoBreakSpace"},
+ {Key::EXCLAMDOWN ,"ExclamDown"},
+ {Key::CENT ,"Cent"},
+ {Key::STERLING ,"Sterling"},
+ {Key::CURRENCY ,"Currency"},
+ {Key::YEN ,"Yen"},
+ {Key::BROKENBAR ,"BrokenBar"},
+ {Key::SECTION ,"Section"},
+ {Key::DIAERESIS ,"Diaeresis"},
+ {Key::COPYRIGHT ,"Copyright"},
+ {Key::ORDFEMININE ,"Ordfeminine"},
+ {Key::GUILLEMOTLEFT ,"GuillemotLeft"},
+ {Key::NOTSIGN ,"NotSign"},
+ {Key::HYPHEN ,"Hyphen"},
+ {Key::KEY_REGISTERED ,"Registered"},
+ {Key::MACRON ,"Macron"},
+ {Key::DEGREE ,"Degree"},
+ {Key::PLUSMINUS ,"PlusMinus"},
+ {Key::TWOSUPERIOR ,"TwoSuperior"},
+ {Key::THREESUPERIOR ,"ThreeSuperior"},
+ {Key::ACUTE ,"Acute"},
+ {Key::MU ,"Mu"},
+ {Key::PARAGRAPH ,"Paragraph"},
+ {Key::PERIODCENTERED ,"PeriodCentered"},
+ {Key::CEDILLA ,"Cedilla"},
+ {Key::ONESUPERIOR ,"OneSuperior"},
+ {Key::MASCULINE ,"Masculine"},
+ {Key::GUILLEMOTRIGHT ,"GuillemotRight"},
+ {Key::ONEQUARTER ,"OneQuarter"},
+ {Key::ONEHALF ,"OneHalf"},
+ {Key::THREEQUARTERS ,"ThreeQuarters"},
+ {Key::QUESTIONDOWN ,"QuestionDown"},
+ {Key::AGRAVE ,"Agrave"},
+ {Key::AACUTE ,"Aacute"},
+ {Key::ACIRCUMFLEX ,"AcircumFlex"},
+ {Key::ATILDE ,"Atilde"},
+ {Key::ADIAERESIS ,"Adiaeresis"},
+ {Key::ARING ,"Aring"},
+ {Key::AE ,"Ae"},
+ {Key::CCEDILLA ,"Ccedilla"},
+ {Key::EGRAVE ,"Egrave"},
+ {Key::EACUTE ,"Eacute"},
+ {Key::ECIRCUMFLEX ,"Ecircumflex"},
+ {Key::EDIAERESIS ,"Ediaeresis"},
+ {Key::IGRAVE ,"Igrave"},
+ {Key::IACUTE ,"Iacute"},
+ {Key::ICIRCUMFLEX ,"Icircumflex"},
+ {Key::IDIAERESIS ,"Idiaeresis"},
+ {Key::ETH ,"Eth"},
+ {Key::NTILDE ,"Ntilde"},
+ {Key::OGRAVE ,"Ograve"},
+ {Key::OACUTE ,"Oacute"},
+ {Key::OCIRCUMFLEX ,"Ocircumflex"},
+ {Key::OTILDE ,"Otilde"},
+ {Key::ODIAERESIS ,"Odiaeresis"},
+ {Key::MULTIPLY ,"Multiply"},
+ {Key::OOBLIQUE ,"Ooblique"},
+ {Key::UGRAVE ,"Ugrave"},
+ {Key::UACUTE ,"Uacute"},
+ {Key::UCIRCUMFLEX ,"Ucircumflex"},
+ {Key::UDIAERESIS ,"Udiaeresis"},
+ {Key::YACUTE ,"Yacute"},
+ {Key::THORN ,"Thorn"},
+ {Key::SSHARP ,"Ssharp"},
+ {Key::DIVISION ,"Division"},
+ {Key::YDIAERESIS ,"Ydiaeresis"},
+ {Key::NONE ,nullptr}
/* clang-format on */
};
-bool keycode_has_unicode(uint32_t p_keycode) {
+bool keycode_has_unicode(Key p_keycode) {
switch (p_keycode) {
- case KEY_ESCAPE:
- case KEY_TAB:
- case KEY_BACKTAB:
- case KEY_BACKSPACE:
- case KEY_ENTER:
- case KEY_KP_ENTER:
- case KEY_INSERT:
- case KEY_DELETE:
- case KEY_PAUSE:
- case KEY_PRINT:
- case KEY_SYSREQ:
- case KEY_CLEAR:
- case KEY_HOME:
- case KEY_END:
- case KEY_LEFT:
- case KEY_UP:
- case KEY_RIGHT:
- case KEY_DOWN:
- case KEY_PAGEUP:
- case KEY_PAGEDOWN:
- case KEY_SHIFT:
- case KEY_CTRL:
- case KEY_META:
- case KEY_ALT:
- case KEY_CAPSLOCK:
- case KEY_NUMLOCK:
- case KEY_SCROLLLOCK:
- case KEY_F1:
- case KEY_F2:
- case KEY_F3:
- case KEY_F4:
- case KEY_F5:
- case KEY_F6:
- case KEY_F7:
- case KEY_F8:
- case KEY_F9:
- case KEY_F10:
- case KEY_F11:
- case KEY_F12:
- case KEY_F13:
- case KEY_F14:
- case KEY_F15:
- case KEY_F16:
- case KEY_SUPER_L:
- case KEY_SUPER_R:
- case KEY_MENU:
- case KEY_HYPER_L:
- case KEY_HYPER_R:
- case KEY_HELP:
- case KEY_DIRECTION_L:
- case KEY_DIRECTION_R:
- case KEY_BACK:
- case KEY_FORWARD:
- case KEY_STOP:
- case KEY_REFRESH:
- case KEY_VOLUMEDOWN:
- case KEY_VOLUMEMUTE:
- case KEY_VOLUMEUP:
- case KEY_BASSBOOST:
- case KEY_BASSUP:
- case KEY_BASSDOWN:
- case KEY_TREBLEUP:
- case KEY_TREBLEDOWN:
- case KEY_MEDIAPLAY:
- case KEY_MEDIASTOP:
- case KEY_MEDIAPREVIOUS:
- case KEY_MEDIANEXT:
- case KEY_MEDIARECORD:
- case KEY_HOMEPAGE:
- case KEY_FAVORITES:
- case KEY_SEARCH:
- case KEY_STANDBY:
- case KEY_OPENURL:
- case KEY_LAUNCHMAIL:
- case KEY_LAUNCHMEDIA:
- case KEY_LAUNCH0:
- case KEY_LAUNCH1:
- case KEY_LAUNCH2:
- case KEY_LAUNCH3:
- case KEY_LAUNCH4:
- case KEY_LAUNCH5:
- case KEY_LAUNCH6:
- case KEY_LAUNCH7:
- case KEY_LAUNCH8:
- case KEY_LAUNCH9:
- case KEY_LAUNCHA:
- case KEY_LAUNCHB:
- case KEY_LAUNCHC:
- case KEY_LAUNCHD:
- case KEY_LAUNCHE:
- case KEY_LAUNCHF:
+ case Key::ESCAPE:
+ case Key::TAB:
+ case Key::BACKTAB:
+ case Key::BACKSPACE:
+ case Key::ENTER:
+ case Key::KP_ENTER:
+ case Key::INSERT:
+ case Key::KEY_DELETE:
+ case Key::PAUSE:
+ case Key::PRINT:
+ case Key::SYSREQ:
+ case Key::CLEAR:
+ case Key::HOME:
+ case Key::END:
+ case Key::LEFT:
+ case Key::UP:
+ case Key::RIGHT:
+ case Key::DOWN:
+ case Key::PAGEUP:
+ case Key::PAGEDOWN:
+ case Key::SHIFT:
+ case Key::CTRL:
+ case Key::META:
+ case Key::ALT:
+ case Key::CAPSLOCK:
+ case Key::NUMLOCK:
+ case Key::SCROLLLOCK:
+ case Key::F1:
+ case Key::F2:
+ case Key::F3:
+ case Key::F4:
+ case Key::F5:
+ case Key::F6:
+ case Key::F7:
+ case Key::F8:
+ case Key::F9:
+ case Key::F10:
+ case Key::F11:
+ case Key::F12:
+ case Key::F13:
+ case Key::F14:
+ case Key::F15:
+ case Key::F16:
+ case Key::SUPER_L:
+ case Key::SUPER_R:
+ case Key::MENU:
+ case Key::HYPER_L:
+ case Key::HYPER_R:
+ case Key::HELP:
+ case Key::DIRECTION_L:
+ case Key::DIRECTION_R:
+ case Key::BACK:
+ case Key::FORWARD:
+ case Key::STOP:
+ case Key::REFRESH:
+ case Key::VOLUMEDOWN:
+ case Key::VOLUMEMUTE:
+ case Key::VOLUMEUP:
+ case Key::BASSBOOST:
+ case Key::BASSUP:
+ case Key::BASSDOWN:
+ case Key::TREBLEUP:
+ case Key::TREBLEDOWN:
+ case Key::MEDIAPLAY:
+ case Key::MEDIASTOP:
+ case Key::MEDIAPREVIOUS:
+ case Key::MEDIANEXT:
+ case Key::MEDIARECORD:
+ case Key::HOMEPAGE:
+ case Key::FAVORITES:
+ case Key::SEARCH:
+ case Key::STANDBY:
+ case Key::OPENURL:
+ case Key::LAUNCHMAIL:
+ case Key::LAUNCHMEDIA:
+ case Key::LAUNCH0:
+ case Key::LAUNCH1:
+ case Key::LAUNCH2:
+ case Key::LAUNCH3:
+ case Key::LAUNCH4:
+ case Key::LAUNCH5:
+ case Key::LAUNCH6:
+ case Key::LAUNCH7:
+ case Key::LAUNCH8:
+ case Key::LAUNCH9:
+ case Key::LAUNCHA:
+ case Key::LAUNCHB:
+ case Key::LAUNCHC:
+ case Key::LAUNCHD:
+ case Key::LAUNCHE:
+ case Key::LAUNCHF:
return false;
+ default: {
+ }
}
return true;
}
-String keycode_get_string(uint32_t p_code) {
+String keycode_get_string(Key p_code) {
String codestr;
- if (p_code & KEY_MASK_SHIFT) {
- codestr += find_keycode_name(KEY_SHIFT);
+ if ((p_code & KeyModifierMask::SHIFT) != Key::NONE) {
+ codestr += find_keycode_name(Key::SHIFT);
codestr += "+";
}
- if (p_code & KEY_MASK_ALT) {
- codestr += find_keycode_name(KEY_ALT);
+ if ((p_code & KeyModifierMask::ALT) != Key::NONE) {
+ codestr += find_keycode_name(Key::ALT);
codestr += "+";
}
- if (p_code & KEY_MASK_CTRL) {
- codestr += find_keycode_name(KEY_CTRL);
+ if ((p_code & KeyModifierMask::CTRL) != Key::NONE) {
+ codestr += find_keycode_name(Key::CTRL);
codestr += "+";
}
- if (p_code & KEY_MASK_META) {
- codestr += find_keycode_name(KEY_META);
+ if ((p_code & KeyModifierMask::META) != Key::NONE) {
+ codestr += find_keycode_name(Key::META);
codestr += "+";
}
- p_code &= KEY_CODE_MASK;
+ p_code &= KeyModifierMask::CODE_MASK;
const _KeyCodeText *kct = &_keycodes[0];
while (kct->text) {
- if (kct->code == (int)p_code) {
+ if (kct->code == p_code) {
codestr += kct->text;
return codestr;
}
kct++;
}
- codestr += String::chr(p_code);
+ codestr += String::chr((char32_t)p_code);
return codestr;
}
-int find_keycode(const String &p_code) {
+Key find_keycode(const String &p_code) {
const _KeyCodeText *kct = &_keycodes[0];
while (kct->text) {
@@ -436,10 +435,10 @@ int find_keycode(const String &p_code) {
kct++;
}
- return 0;
+ return Key::NONE;
}
-const char *find_keycode_name(int p_keycode) {
+const char *find_keycode_name(Key p_keycode) {
const _KeyCodeText *kct = &_keycodes[0];
while (kct->text) {
@@ -464,7 +463,7 @@ int keycode_get_count() {
}
int keycode_get_value_by_index(int p_index) {
- return _keycodes[p_index].code;
+ return (int)_keycodes[p_index].code;
}
const char *keycode_get_name_by_index(int p_index) {
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index 52174432d9..a21d81b2e7 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,148 +33,142 @@
#include "core/string/ustring.h"
-/*
- Special Key:
-
- The strategy here is similar to the one used by toolkits,
- which consists in leaving the 24 bits unicode range for printable
- characters, and use the upper 8 bits for special keys and
- modifiers. This way everything (char/keycode) can fit nicely in one 32 bits unsigned integer.
-*/
-enum {
- SPKEY = (1 << 24)
-};
-
-enum Key {
- KEY_NONE = 0,
+enum class Key {
+ NONE = 0,
+ // Special key: The strategy here is similar to the one used by toolkits,
+ // which consists in leaving the 24 bits unicode range for printable
+ // characters, and use the upper 8 bits for special keys and modifiers.
+ // This way everything (char/keycode) can fit nicely in one 32-bit
+ // integer (the enum's underlying type is `int` by default).
+ SPECIAL = (1 << 24),
/* CURSOR/FUNCTION/BROWSER/MULTIMEDIA/MISC KEYS */
- KEY_ESCAPE = SPKEY | 0x01,
- KEY_TAB = SPKEY | 0x02,
- KEY_BACKTAB = SPKEY | 0x03,
- KEY_BACKSPACE = SPKEY | 0x04,
- KEY_ENTER = SPKEY | 0x05,
- KEY_KP_ENTER = SPKEY | 0x06,
- KEY_INSERT = SPKEY | 0x07,
- KEY_DELETE = SPKEY | 0x08,
- KEY_PAUSE = SPKEY | 0x09,
- KEY_PRINT = SPKEY | 0x0A,
- KEY_SYSREQ = SPKEY | 0x0B,
- KEY_CLEAR = SPKEY | 0x0C,
- KEY_HOME = SPKEY | 0x0D,
- KEY_END = SPKEY | 0x0E,
- KEY_LEFT = SPKEY | 0x0F,
- KEY_UP = SPKEY | 0x10,
- KEY_RIGHT = SPKEY | 0x11,
- KEY_DOWN = SPKEY | 0x12,
- KEY_PAGEUP = SPKEY | 0x13,
- KEY_PAGEDOWN = SPKEY | 0x14,
- KEY_SHIFT = SPKEY | 0x15,
- KEY_CTRL = SPKEY | 0x16,
- KEY_META = SPKEY | 0x17,
- KEY_ALT = SPKEY | 0x18,
- KEY_CAPSLOCK = SPKEY | 0x19,
- KEY_NUMLOCK = SPKEY | 0x1A,
- KEY_SCROLLLOCK = SPKEY | 0x1B,
- KEY_F1 = SPKEY | 0x1C,
- KEY_F2 = SPKEY | 0x1D,
- KEY_F3 = SPKEY | 0x1E,
- KEY_F4 = SPKEY | 0x1F,
- KEY_F5 = SPKEY | 0x20,
- KEY_F6 = SPKEY | 0x21,
- KEY_F7 = SPKEY | 0x22,
- KEY_F8 = SPKEY | 0x23,
- KEY_F9 = SPKEY | 0x24,
- KEY_F10 = SPKEY | 0x25,
- KEY_F11 = SPKEY | 0x26,
- KEY_F12 = SPKEY | 0x27,
- KEY_F13 = SPKEY | 0x28,
- KEY_F14 = SPKEY | 0x29,
- KEY_F15 = SPKEY | 0x2A,
- KEY_F16 = SPKEY | 0x2B,
- KEY_KP_MULTIPLY = SPKEY | 0x81,
- KEY_KP_DIVIDE = SPKEY | 0x82,
- KEY_KP_SUBTRACT = SPKEY | 0x83,
- KEY_KP_PERIOD = SPKEY | 0x84,
- KEY_KP_ADD = SPKEY | 0x85,
- KEY_KP_0 = SPKEY | 0x86,
- KEY_KP_1 = SPKEY | 0x87,
- KEY_KP_2 = SPKEY | 0x88,
- KEY_KP_3 = SPKEY | 0x89,
- KEY_KP_4 = SPKEY | 0x8A,
- KEY_KP_5 = SPKEY | 0x8B,
- KEY_KP_6 = SPKEY | 0x8C,
- KEY_KP_7 = SPKEY | 0x8D,
- KEY_KP_8 = SPKEY | 0x8E,
- KEY_KP_9 = SPKEY | 0x8F,
- KEY_SUPER_L = SPKEY | 0x2C,
- KEY_SUPER_R = SPKEY | 0x2D,
- KEY_MENU = SPKEY | 0x2E,
- KEY_HYPER_L = SPKEY | 0x2F,
- KEY_HYPER_R = SPKEY | 0x30,
- KEY_HELP = SPKEY | 0x31,
- KEY_DIRECTION_L = SPKEY | 0x32,
- KEY_DIRECTION_R = SPKEY | 0x33,
- KEY_BACK = SPKEY | 0x40,
- KEY_FORWARD = SPKEY | 0x41,
- KEY_STOP = SPKEY | 0x42,
- KEY_REFRESH = SPKEY | 0x43,
- KEY_VOLUMEDOWN = SPKEY | 0x44,
- KEY_VOLUMEMUTE = SPKEY | 0x45,
- KEY_VOLUMEUP = SPKEY | 0x46,
- KEY_BASSBOOST = SPKEY | 0x47,
- KEY_BASSUP = SPKEY | 0x48,
- KEY_BASSDOWN = SPKEY | 0x49,
- KEY_TREBLEUP = SPKEY | 0x4A,
- KEY_TREBLEDOWN = SPKEY | 0x4B,
- KEY_MEDIAPLAY = SPKEY | 0x4C,
- KEY_MEDIASTOP = SPKEY | 0x4D,
- KEY_MEDIAPREVIOUS = SPKEY | 0x4E,
- KEY_MEDIANEXT = SPKEY | 0x4F,
- KEY_MEDIARECORD = SPKEY | 0x50,
- KEY_HOMEPAGE = SPKEY | 0x51,
- KEY_FAVORITES = SPKEY | 0x52,
- KEY_SEARCH = SPKEY | 0x53,
- KEY_STANDBY = SPKEY | 0x54,
- KEY_OPENURL = SPKEY | 0x55,
- KEY_LAUNCHMAIL = SPKEY | 0x56,
- KEY_LAUNCHMEDIA = SPKEY | 0x57,
- KEY_LAUNCH0 = SPKEY | 0x58,
- KEY_LAUNCH1 = SPKEY | 0x59,
- KEY_LAUNCH2 = SPKEY | 0x5A,
- KEY_LAUNCH3 = SPKEY | 0x5B,
- KEY_LAUNCH4 = SPKEY | 0x5C,
- KEY_LAUNCH5 = SPKEY | 0x5D,
- KEY_LAUNCH6 = SPKEY | 0x5E,
- KEY_LAUNCH7 = SPKEY | 0x5F,
- KEY_LAUNCH8 = SPKEY | 0x60,
- KEY_LAUNCH9 = SPKEY | 0x61,
- KEY_LAUNCHA = SPKEY | 0x62,
- KEY_LAUNCHB = SPKEY | 0x63,
- KEY_LAUNCHC = SPKEY | 0x64,
- KEY_LAUNCHD = SPKEY | 0x65,
- KEY_LAUNCHE = SPKEY | 0x66,
- KEY_LAUNCHF = SPKEY | 0x67,
+ ESCAPE = SPECIAL | 0x01,
+ TAB = SPECIAL | 0x02,
+ BACKTAB = SPECIAL | 0x03,
+ BACKSPACE = SPECIAL | 0x04,
+ ENTER = SPECIAL | 0x05,
+ KP_ENTER = SPECIAL | 0x06,
+ INSERT = SPECIAL | 0x07,
+ KEY_DELETE = SPECIAL | 0x08, // "DELETE" is a reserved word on Windows.
+ PAUSE = SPECIAL | 0x09,
+ PRINT = SPECIAL | 0x0A,
+ SYSREQ = SPECIAL | 0x0B,
+ CLEAR = SPECIAL | 0x0C,
+ HOME = SPECIAL | 0x0D,
+ END = SPECIAL | 0x0E,
+ LEFT = SPECIAL | 0x0F,
+ UP = SPECIAL | 0x10,
+ RIGHT = SPECIAL | 0x11,
+ DOWN = SPECIAL | 0x12,
+ PAGEUP = SPECIAL | 0x13,
+ PAGEDOWN = SPECIAL | 0x14,
+ SHIFT = SPECIAL | 0x15,
+ CTRL = SPECIAL | 0x16,
+ META = SPECIAL | 0x17,
+ ALT = SPECIAL | 0x18,
+ CAPSLOCK = SPECIAL | 0x19,
+ NUMLOCK = SPECIAL | 0x1A,
+ SCROLLLOCK = SPECIAL | 0x1B,
+ F1 = SPECIAL | 0x1C,
+ F2 = SPECIAL | 0x1D,
+ F3 = SPECIAL | 0x1E,
+ F4 = SPECIAL | 0x1F,
+ F5 = SPECIAL | 0x20,
+ F6 = SPECIAL | 0x21,
+ F7 = SPECIAL | 0x22,
+ F8 = SPECIAL | 0x23,
+ F9 = SPECIAL | 0x24,
+ F10 = SPECIAL | 0x25,
+ F11 = SPECIAL | 0x26,
+ F12 = SPECIAL | 0x27,
+ F13 = SPECIAL | 0x28,
+ F14 = SPECIAL | 0x29,
+ F15 = SPECIAL | 0x2A,
+ F16 = SPECIAL | 0x2B,
+ KP_MULTIPLY = SPECIAL | 0x81,
+ KP_DIVIDE = SPECIAL | 0x82,
+ KP_SUBTRACT = SPECIAL | 0x83,
+ KP_PERIOD = SPECIAL | 0x84,
+ KP_ADD = SPECIAL | 0x85,
+ KP_0 = SPECIAL | 0x86,
+ KP_1 = SPECIAL | 0x87,
+ KP_2 = SPECIAL | 0x88,
+ KP_3 = SPECIAL | 0x89,
+ KP_4 = SPECIAL | 0x8A,
+ KP_5 = SPECIAL | 0x8B,
+ KP_6 = SPECIAL | 0x8C,
+ KP_7 = SPECIAL | 0x8D,
+ KP_8 = SPECIAL | 0x8E,
+ KP_9 = SPECIAL | 0x8F,
+ SUPER_L = SPECIAL | 0x2C,
+ SUPER_R = SPECIAL | 0x2D,
+ MENU = SPECIAL | 0x2E,
+ HYPER_L = SPECIAL | 0x2F,
+ HYPER_R = SPECIAL | 0x30,
+ HELP = SPECIAL | 0x31,
+ DIRECTION_L = SPECIAL | 0x32,
+ DIRECTION_R = SPECIAL | 0x33,
+ BACK = SPECIAL | 0x40,
+ FORWARD = SPECIAL | 0x41,
+ STOP = SPECIAL | 0x42,
+ REFRESH = SPECIAL | 0x43,
+ VOLUMEDOWN = SPECIAL | 0x44,
+ VOLUMEMUTE = SPECIAL | 0x45,
+ VOLUMEUP = SPECIAL | 0x46,
+ BASSBOOST = SPECIAL | 0x47,
+ BASSUP = SPECIAL | 0x48,
+ BASSDOWN = SPECIAL | 0x49,
+ TREBLEUP = SPECIAL | 0x4A,
+ TREBLEDOWN = SPECIAL | 0x4B,
+ MEDIAPLAY = SPECIAL | 0x4C,
+ MEDIASTOP = SPECIAL | 0x4D,
+ MEDIAPREVIOUS = SPECIAL | 0x4E,
+ MEDIANEXT = SPECIAL | 0x4F,
+ MEDIARECORD = SPECIAL | 0x50,
+ HOMEPAGE = SPECIAL | 0x51,
+ FAVORITES = SPECIAL | 0x52,
+ SEARCH = SPECIAL | 0x53,
+ STANDBY = SPECIAL | 0x54,
+ OPENURL = SPECIAL | 0x55,
+ LAUNCHMAIL = SPECIAL | 0x56,
+ LAUNCHMEDIA = SPECIAL | 0x57,
+ LAUNCH0 = SPECIAL | 0x58,
+ LAUNCH1 = SPECIAL | 0x59,
+ LAUNCH2 = SPECIAL | 0x5A,
+ LAUNCH3 = SPECIAL | 0x5B,
+ LAUNCH4 = SPECIAL | 0x5C,
+ LAUNCH5 = SPECIAL | 0x5D,
+ LAUNCH6 = SPECIAL | 0x5E,
+ LAUNCH7 = SPECIAL | 0x5F,
+ LAUNCH8 = SPECIAL | 0x60,
+ LAUNCH9 = SPECIAL | 0x61,
+ LAUNCHA = SPECIAL | 0x62,
+ LAUNCHB = SPECIAL | 0x63,
+ LAUNCHC = SPECIAL | 0x64,
+ LAUNCHD = SPECIAL | 0x65,
+ LAUNCHE = SPECIAL | 0x66,
+ LAUNCHF = SPECIAL | 0x67,
- KEY_UNKNOWN = SPKEY | 0xFFFFFF,
+ UNKNOWN = SPECIAL | 0xFFFFFF,
/* PRINTABLE LATIN 1 CODES */
- KEY_SPACE = 0x0020,
- KEY_EXCLAM = 0x0021,
- KEY_QUOTEDBL = 0x0022,
- KEY_NUMBERSIGN = 0x0023,
- KEY_DOLLAR = 0x0024,
- KEY_PERCENT = 0x0025,
- KEY_AMPERSAND = 0x0026,
- KEY_APOSTROPHE = 0x0027,
- KEY_PARENLEFT = 0x0028,
- KEY_PARENRIGHT = 0x0029,
- KEY_ASTERISK = 0x002A,
- KEY_PLUS = 0x002B,
- KEY_COMMA = 0x002C,
- KEY_MINUS = 0x002D,
- KEY_PERIOD = 0x002E,
- KEY_SLASH = 0x002F,
+ SPACE = 0x0020,
+ EXCLAM = 0x0021,
+ QUOTEDBL = 0x0022,
+ NUMBERSIGN = 0x0023,
+ DOLLAR = 0x0024,
+ PERCENT = 0x0025,
+ AMPERSAND = 0x0026,
+ APOSTROPHE = 0x0027,
+ PARENLEFT = 0x0028,
+ PARENRIGHT = 0x0029,
+ ASTERISK = 0x002A,
+ PLUS = 0x002B,
+ COMMA = 0x002C,
+ MINUS = 0x002D,
+ PERIOD = 0x002E,
+ SLASH = 0x002F,
KEY_0 = 0x0030,
KEY_1 = 0x0031,
KEY_2 = 0x0032,
@@ -185,134 +179,133 @@ enum Key {
KEY_7 = 0x0037,
KEY_8 = 0x0038,
KEY_9 = 0x0039,
- KEY_COLON = 0x003A,
- KEY_SEMICOLON = 0x003B,
- KEY_LESS = 0x003C,
- KEY_EQUAL = 0x003D,
- KEY_GREATER = 0x003E,
- KEY_QUESTION = 0x003F,
- KEY_AT = 0x0040,
- KEY_A = 0x0041,
- KEY_B = 0x0042,
- KEY_C = 0x0043,
- KEY_D = 0x0044,
- KEY_E = 0x0045,
- KEY_F = 0x0046,
- KEY_G = 0x0047,
- KEY_H = 0x0048,
- KEY_I = 0x0049,
- KEY_J = 0x004A,
- KEY_K = 0x004B,
- KEY_L = 0x004C,
- KEY_M = 0x004D,
- KEY_N = 0x004E,
- KEY_O = 0x004F,
- KEY_P = 0x0050,
- KEY_Q = 0x0051,
- KEY_R = 0x0052,
- KEY_S = 0x0053,
- KEY_T = 0x0054,
- KEY_U = 0x0055,
- KEY_V = 0x0056,
- KEY_W = 0x0057,
- KEY_X = 0x0058,
- KEY_Y = 0x0059,
- KEY_Z = 0x005A,
- KEY_BRACKETLEFT = 0x005B,
- KEY_BACKSLASH = 0x005C,
- KEY_BRACKETRIGHT = 0x005D,
- KEY_ASCIICIRCUM = 0x005E,
- KEY_UNDERSCORE = 0x005F,
- KEY_QUOTELEFT = 0x0060,
- KEY_BRACELEFT = 0x007B,
- KEY_BAR = 0x007C,
- KEY_BRACERIGHT = 0x007D,
- KEY_ASCIITILDE = 0x007E,
- KEY_NOBREAKSPACE = 0x00A0,
- KEY_EXCLAMDOWN = 0x00A1,
- KEY_CENT = 0x00A2,
- KEY_STERLING = 0x00A3,
- KEY_CURRENCY = 0x00A4,
- KEY_YEN = 0x00A5,
- KEY_BROKENBAR = 0x00A6,
- KEY_SECTION = 0x00A7,
- KEY_DIAERESIS = 0x00A8,
- KEY_COPYRIGHT = 0x00A9,
- KEY_ORDFEMININE = 0x00AA,
- KEY_GUILLEMOTLEFT = 0x00AB,
- KEY_NOTSIGN = 0x00AC,
- KEY_HYPHEN = 0x00AD,
- KEY_REGISTERED = 0x00AE,
- KEY_MACRON = 0x00AF,
- KEY_DEGREE = 0x00B0,
- KEY_PLUSMINUS = 0x00B1,
- KEY_TWOSUPERIOR = 0x00B2,
- KEY_THREESUPERIOR = 0x00B3,
- KEY_ACUTE = 0x00B4,
- KEY_MU = 0x00B5,
- KEY_PARAGRAPH = 0x00B6,
- KEY_PERIODCENTERED = 0x00B7,
- KEY_CEDILLA = 0x00B8,
- KEY_ONESUPERIOR = 0x00B9,
- KEY_MASCULINE = 0x00BA,
- KEY_GUILLEMOTRIGHT = 0x00BB,
- KEY_ONEQUARTER = 0x00BC,
- KEY_ONEHALF = 0x00BD,
- KEY_THREEQUARTERS = 0x00BE,
- KEY_QUESTIONDOWN = 0x00BF,
- KEY_AGRAVE = 0x00C0,
- KEY_AACUTE = 0x00C1,
- KEY_ACIRCUMFLEX = 0x00C2,
- KEY_ATILDE = 0x00C3,
- KEY_ADIAERESIS = 0x00C4,
- KEY_ARING = 0x00C5,
- KEY_AE = 0x00C6,
- KEY_CCEDILLA = 0x00C7,
- KEY_EGRAVE = 0x00C8,
- KEY_EACUTE = 0x00C9,
- KEY_ECIRCUMFLEX = 0x00CA,
- KEY_EDIAERESIS = 0x00CB,
- KEY_IGRAVE = 0x00CC,
- KEY_IACUTE = 0x00CD,
- KEY_ICIRCUMFLEX = 0x00CE,
- KEY_IDIAERESIS = 0x00CF,
- KEY_ETH = 0x00D0,
- KEY_NTILDE = 0x00D1,
- KEY_OGRAVE = 0x00D2,
- KEY_OACUTE = 0x00D3,
- KEY_OCIRCUMFLEX = 0x00D4,
- KEY_OTILDE = 0x00D5,
- KEY_ODIAERESIS = 0x00D6,
- KEY_MULTIPLY = 0x00D7,
- KEY_OOBLIQUE = 0x00D8,
- KEY_UGRAVE = 0x00D9,
- KEY_UACUTE = 0x00DA,
- KEY_UCIRCUMFLEX = 0x00DB,
- KEY_UDIAERESIS = 0x00DC,
- KEY_YACUTE = 0x00DD,
- KEY_THORN = 0x00DE,
- KEY_SSHARP = 0x00DF,
+ COLON = 0x003A,
+ SEMICOLON = 0x003B,
+ LESS = 0x003C,
+ EQUAL = 0x003D,
+ GREATER = 0x003E,
+ QUESTION = 0x003F,
+ AT = 0x0040,
+ A = 0x0041,
+ B = 0x0042,
+ C = 0x0043,
+ D = 0x0044,
+ E = 0x0045,
+ F = 0x0046,
+ G = 0x0047,
+ H = 0x0048,
+ I = 0x0049,
+ J = 0x004A,
+ K = 0x004B,
+ L = 0x004C,
+ M = 0x004D,
+ N = 0x004E,
+ O = 0x004F,
+ P = 0x0050,
+ Q = 0x0051,
+ R = 0x0052,
+ S = 0x0053,
+ T = 0x0054,
+ U = 0x0055,
+ V = 0x0056,
+ W = 0x0057,
+ X = 0x0058,
+ Y = 0x0059,
+ Z = 0x005A,
+ BRACKETLEFT = 0x005B,
+ BACKSLASH = 0x005C,
+ BRACKETRIGHT = 0x005D,
+ ASCIICIRCUM = 0x005E,
+ UNDERSCORE = 0x005F,
+ QUOTELEFT = 0x0060,
+ BRACELEFT = 0x007B,
+ BAR = 0x007C,
+ BRACERIGHT = 0x007D,
+ ASCIITILDE = 0x007E,
+ NOBREAKSPACE = 0x00A0,
+ EXCLAMDOWN = 0x00A1,
+ CENT = 0x00A2,
+ STERLING = 0x00A3,
+ CURRENCY = 0x00A4,
+ YEN = 0x00A5,
+ BROKENBAR = 0x00A6,
+ SECTION = 0x00A7,
+ DIAERESIS = 0x00A8,
+ COPYRIGHT = 0x00A9,
+ ORDFEMININE = 0x00AA,
+ GUILLEMOTLEFT = 0x00AB,
+ NOTSIGN = 0x00AC,
+ HYPHEN = 0x00AD,
+ KEY_REGISTERED = 0x00AE, // "REGISTERED" is a reserved word on Windows.
+ MACRON = 0x00AF,
+ DEGREE = 0x00B0,
+ PLUSMINUS = 0x00B1,
+ TWOSUPERIOR = 0x00B2,
+ THREESUPERIOR = 0x00B3,
+ ACUTE = 0x00B4,
+ MU = 0x00B5,
+ PARAGRAPH = 0x00B6,
+ PERIODCENTERED = 0x00B7,
+ CEDILLA = 0x00B8,
+ ONESUPERIOR = 0x00B9,
+ MASCULINE = 0x00BA,
+ GUILLEMOTRIGHT = 0x00BB,
+ ONEQUARTER = 0x00BC,
+ ONEHALF = 0x00BD,
+ THREEQUARTERS = 0x00BE,
+ QUESTIONDOWN = 0x00BF,
+ AGRAVE = 0x00C0,
+ AACUTE = 0x00C1,
+ ACIRCUMFLEX = 0x00C2,
+ ATILDE = 0x00C3,
+ ADIAERESIS = 0x00C4,
+ ARING = 0x00C5,
+ AE = 0x00C6,
+ CCEDILLA = 0x00C7,
+ EGRAVE = 0x00C8,
+ EACUTE = 0x00C9,
+ ECIRCUMFLEX = 0x00CA,
+ EDIAERESIS = 0x00CB,
+ IGRAVE = 0x00CC,
+ IACUTE = 0x00CD,
+ ICIRCUMFLEX = 0x00CE,
+ IDIAERESIS = 0x00CF,
+ ETH = 0x00D0,
+ NTILDE = 0x00D1,
+ OGRAVE = 0x00D2,
+ OACUTE = 0x00D3,
+ OCIRCUMFLEX = 0x00D4,
+ OTILDE = 0x00D5,
+ ODIAERESIS = 0x00D6,
+ MULTIPLY = 0x00D7,
+ OOBLIQUE = 0x00D8,
+ UGRAVE = 0x00D9,
+ UACUTE = 0x00DA,
+ UCIRCUMFLEX = 0x00DB,
+ UDIAERESIS = 0x00DC,
+ YACUTE = 0x00DD,
+ THORN = 0x00DE,
+ SSHARP = 0x00DF,
- KEY_DIVISION = 0x00F7,
- KEY_YDIAERESIS = 0x00FF,
+ DIVISION = 0x00F7,
+ YDIAERESIS = 0x00FF,
+ END_LATIN1 = 0x0100,
};
-enum KeyModifierMask {
- KEY_CODE_MASK = ((1 << 25) - 1), ///< Apply this mask to any keycode to remove modifiers.
- KEY_MODIFIER_MASK = (0xFF << 24), ///< Apply this mask to isolate modifiers.
- KEY_MASK_SHIFT = (1 << 25),
- KEY_MASK_ALT = (1 << 26),
- KEY_MASK_META = (1 << 27),
- KEY_MASK_CTRL = (1 << 28),
+enum class KeyModifierMask {
+ CODE_MASK = ((1 << 25) - 1), ///< Apply this mask to any keycode to remove modifiers.
+ MODIFIER_MASK = (0xFF << 24), ///< Apply this mask to isolate modifiers.
+ SHIFT = (1 << 25),
+ ALT = (1 << 26),
+ META = (1 << 27),
+ CTRL = (1 << 28),
#ifdef APPLE_STYLE_KEYS
- KEY_MASK_CMD = KEY_MASK_META,
+ CMD = META,
#else
- KEY_MASK_CMD = KEY_MASK_CTRL,
+ CMD = CTRL,
#endif
-
- KEY_MASK_KPAD = (1 << 29),
- KEY_MASK_GROUP_SWITCH = (1 << 30)
- // bit 31 can't be used because variant uses regular 32 bits int as datatype
+ KPAD = (1 << 29),
+ GROUP_SWITCH = (1 << 30)
};
// To avoid having unnecessary operators, only define the ones that are needed.
@@ -325,10 +318,26 @@ inline Key &operator-=(Key &a, int b) {
return (Key &)((int &)a -= b);
}
+inline Key operator+(Key a, int b) {
+ return (Key)((int)a + (int)b);
+}
+
inline Key operator+(Key a, Key b) {
+ return (Key)((int)a + (int)b);
+}
+
+inline Key operator-(Key a, Key b) {
return (Key)((int)a - (int)b);
}
+inline Key operator&(Key a, Key b) {
+ return (Key)((int)a & (int)b);
+}
+
+inline Key operator|(Key a, Key b) {
+ return (Key)((int)a | (int)b);
+}
+
inline Key &operator|=(Key &a, Key b) {
return (Key &)((int &)a |= (int)b);
}
@@ -337,6 +346,10 @@ inline Key &operator|=(Key &a, KeyModifierMask b) {
return (Key &)((int &)a |= (int)b);
}
+inline Key &operator&=(Key &a, KeyModifierMask b) {
+ return (Key &)((int &)a &= (int)b);
+}
+
inline Key operator|(Key a, KeyModifierMask b) {
return (Key)((int)a | (int)b);
}
@@ -361,10 +374,10 @@ inline KeyModifierMask operator|(KeyModifierMask a, KeyModifierMask b) {
return (KeyModifierMask)((int)a | (int)b);
}
-String keycode_get_string(uint32_t p_code);
-bool keycode_has_unicode(uint32_t p_keycode);
-int find_keycode(const String &p_code);
-const char *find_keycode_name(int p_keycode);
+String keycode_get_string(Key p_code);
+bool keycode_has_unicode(Key p_keycode);
+Key find_keycode(const String &p_code);
+const char *find_keycode_name(Key p_keycode);
int keycode_get_count();
int keycode_get_value_by_index(int p_index);
const char *keycode_get_name_by_index(int p_index);
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index 0ba69a8d47..a96e1989f9 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index 4da01d767e..a6a32f0138 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory.cpp b/core/os/memory.cpp
index a756c1d5dd..6ff0f9ae00 100644
--- a/core/os/memory.cpp
+++ b/core/os/memory.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory.h b/core/os/memory.h
index f67384a17e..27eaad5010 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,7 +42,6 @@
#endif
class Memory {
- Memory();
#ifdef DEBUG_ENABLED
static SafeNumeric<uint64_t> mem_usage;
static SafeNumeric<uint64_t> max_usage;
diff --git a/core/os/midi_driver.cpp b/core/os/midi_driver.cpp
index ee87346dfc..8431ceacf9 100644
--- a/core/os/midi_driver.cpp
+++ b/core/os/midi_driver.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,46 +68,46 @@ void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_
}
switch (event->get_message()) {
- case MIDI_MESSAGE_AFTERTOUCH:
+ case MIDIMessage::AFTERTOUCH:
if (length >= 2 + param_position) {
event->set_pitch(data[param_position]);
event->set_pressure(data[param_position + 1]);
}
break;
- case MIDI_MESSAGE_CONTROL_CHANGE:
+ case MIDIMessage::CONTROL_CHANGE:
if (length >= 2 + param_position) {
event->set_controller_number(data[param_position]);
event->set_controller_value(data[param_position + 1]);
}
break;
- case MIDI_MESSAGE_NOTE_ON:
- case MIDI_MESSAGE_NOTE_OFF:
+ case MIDIMessage::NOTE_ON:
+ case MIDIMessage::NOTE_OFF:
if (length >= 2 + param_position) {
event->set_pitch(data[param_position]);
event->set_velocity(data[param_position + 1]);
- if (event->get_message() == MIDI_MESSAGE_NOTE_ON && event->get_velocity() == 0) {
+ if (event->get_message() == MIDIMessage::NOTE_ON && event->get_velocity() == 0) {
// https://www.midi.org/forum/228-writing-midi-software-send-note-off,-or-zero-velocity-note-on
- event->set_message(MIDI_MESSAGE_NOTE_OFF);
+ event->set_message(MIDIMessage::NOTE_OFF);
}
}
break;
- case MIDI_MESSAGE_PITCH_BEND:
+ case MIDIMessage::PITCH_BEND:
if (length >= 2 + param_position) {
event->set_pitch((data[param_position + 1] << 7) | data[param_position]);
}
break;
- case MIDI_MESSAGE_PROGRAM_CHANGE:
+ case MIDIMessage::PROGRAM_CHANGE:
if (length >= 1 + param_position) {
event->set_instrument(data[param_position]);
}
break;
- case MIDI_MESSAGE_CHANNEL_PRESSURE:
+ case MIDIMessage::CHANNEL_PRESSURE:
if (length >= 1 + param_position) {
event->set_pressure(data[param_position]);
}
diff --git a/core/os/midi_driver.h b/core/os/midi_driver.h
index ccf624e07e..c23614af00 100644
--- a/core/os/midi_driver.h
+++ b/core/os/midi_driver.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/mutex.cpp b/core/os/mutex.cpp
index b7d7752d35..1d4400bfc1 100644
--- a/core/os/mutex.cpp
+++ b/core/os/mutex.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/mutex.h b/core/os/mutex.h
index d77ec362a1..a51248807b 100644
--- a/core/os/mutex.h
+++ b/core/os/mutex.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/os.cpp b/core/os/os.cpp
index dc3fe29dca..0032e8e4bc 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,6 @@
#include "core/io/file_access.h"
#include "core/os/midi_driver.h"
#include "core/version_generated.gen.h"
-#include "servers/audio_server.h"
#include <stdarg.h>
@@ -76,12 +75,12 @@ void OS::add_logger(Logger *p_logger) {
}
}
-void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type) {
+void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, Logger::ErrorType p_type) {
if (!_stderr_enabled) {
return;
}
- _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
+ _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type);
}
void OS::print(const char *p_format, ...) {
@@ -191,8 +190,8 @@ static void _OS_printres(Object *p_obj) {
}
void OS::print_all_resources(String p_to_file) {
- ERR_FAIL_COND(p_to_file != "" && _OSPRF);
- if (p_to_file != "") {
+ ERR_FAIL_COND(!p_to_file.is_empty() && _OSPRF);
+ if (!p_to_file.is_empty()) {
Error err;
_OSPRF = FileAccess::open(p_to_file, FileAccess::WRITE, &err);
if (err != OK) {
@@ -203,7 +202,7 @@ void OS::print_all_resources(String p_to_file) {
ObjectDB::debug_objects(_OS_printres);
- if (p_to_file != "") {
+ if (!p_to_file.is_empty()) {
if (_OSPRF) {
memdelete(_OSPRF);
}
@@ -231,6 +230,12 @@ String OS::get_locale() const {
return "en";
}
+// Non-virtual helper to extract the 2 or 3-letter language code from
+// `get_locale()` in a way that's consistent for all platforms.
+String OS::get_locale_language() const {
+ return get_locale().left(3).replace("_", "");
+}
+
// Helper function to ensure that a dir name/path will be valid on the OS
String OS::get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separator) const {
Vector<String> invalid_chars = String(": * ? \" < > |").split(" ");
@@ -276,6 +281,11 @@ String OS::get_bundle_resource_dir() const {
return ".";
}
+// Path to macOS .app bundle embedded icon
+String OS::get_bundle_icon_path() const {
+ return String();
+}
+
// OS specific path for user://
String OS::get_user_data_dir() const {
return ".";
@@ -336,7 +346,7 @@ String OS::get_model_name() const {
}
void OS::set_cmdline(const char *p_execpath, const List<String> &p_args) {
- _execpath = p_execpath;
+ _execpath = String::utf8(p_execpath);
_cmdline = p_args;
}
@@ -421,6 +431,24 @@ bool OS::has_feature(const String &p_feature) {
if (p_feature == "arm") {
return true;
}
+#elif defined(__riscv)
+#if __riscv_xlen == 8
+ if (p_feature == "rv64") {
+ return true;
+ }
+#endif
+ if (p_feature == "riscv") {
+ return true;
+ }
+#elif defined(__powerpc__)
+#if defined(__powerpc64__)
+ if (p_feature == "ppc64") {
+ return true;
+ }
+#endif
+ if (p_feature == "ppc") {
+ return true;
+ }
#endif
if (_check_internal_feature_support(p_feature)) {
diff --git a/core/os/os.h b/core/os/os.h
index f585483300..b4ad2c7345 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,6 +68,11 @@ class OS {
bool restart_on_exit = false;
List<String> restart_commandline;
+ // for the user interface we keep a record of the current display driver
+ // so we can retrieve the rendering drivers available
+ int _display_driver_id = -1;
+ String _current_rendering_driver_name = "";
+
protected:
void _set_logger(CompositeLogger *p_logger);
@@ -81,6 +86,11 @@ public:
RENDER_SEPARATE_THREAD
};
+ enum RenderMainThreadMode {
+ RENDER_MAIN_THREAD_ONLY,
+ RENDER_ANY_THREAD,
+ };
+
protected:
friend class Main;
// Needed by tests to setup command-line args.
@@ -88,6 +98,7 @@ protected:
HasServerFeatureCallback has_server_feature_callback = nullptr;
RenderThreadMode _render_thread_mode = RENDER_THREAD_SAFE;
+ RenderMainThreadMode _render_main_thread_mode = RENDER_ANY_THREAD;
// Functions used by Main to initialize/deinitialize the OS.
void add_logger(Logger *p_logger);
@@ -95,6 +106,9 @@ protected:
virtual void initialize() = 0;
virtual void initialize_joypads() = 0;
+ void set_current_rendering_driver_name(String p_driver_name) { _current_rendering_driver_name = p_driver_name; }
+ void set_display_driver_id(int p_display_driver_id) { _display_driver_id = p_display_driver_id; }
+
virtual void set_main_loop(MainLoop *p_main_loop) = 0;
virtual void delete_main_loop() = 0;
@@ -110,7 +124,10 @@ public:
static OS *get_singleton();
- void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type = Logger::ERR_ERROR);
+ String get_current_rendering_driver_name() const { return _current_rendering_driver_name; }
+ int get_display_driver_id() const { return _display_driver_id; }
+
+ void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, Logger::ErrorType p_type = Logger::ERR_ERROR);
void print(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
void printerr(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
@@ -134,6 +151,7 @@ public:
virtual String get_executable_path() const;
virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr) = 0;
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) = 0;
+ virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) { return create_process(get_executable_path(), p_arguments, r_child_id); };
virtual Error kill(const ProcessID &p_pid) = 0;
virtual int get_process_id() const;
virtual void vibrate_handheld(int p_duration_ms = 500);
@@ -204,8 +222,8 @@ public:
String name;
};
- virtual Date get_date(bool local = false) const = 0;
- virtual Time get_time(bool local = false) const = 0;
+ virtual Date get_date(bool p_utc = false) const = 0;
+ virtual Time get_time(bool p_utc = false) const = 0;
virtual TimeZoneInfo get_time_zone_info() const = 0;
virtual double get_unix_time() const;
@@ -225,7 +243,7 @@ public:
void set_stdout_enabled(bool p_enabled);
void set_stderr_enabled(bool p_enabled);
- bool is_single_window() const;
+ virtual bool is_single_window() const;
virtual void disable_crash_handler() {}
virtual bool is_disable_crash_handler() const { return false; }
@@ -241,8 +259,11 @@ public:
virtual uint64_t get_free_static_memory() const;
RenderThreadMode get_render_thread_mode() const { return _render_thread_mode; }
+ RenderMainThreadMode get_render_main_thread_mode() const { return _render_main_thread_mode; }
+ void set_render_main_thread_mode(RenderMainThreadMode p_thread_mode) { _render_main_thread_mode = p_thread_mode; }
virtual String get_locale() const;
+ String get_locale_language() const;
String get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separator = false) const;
virtual String get_godot_dir_name() const;
@@ -251,6 +272,7 @@ public:
virtual String get_config_path() const;
virtual String get_cache_path() const;
virtual String get_bundle_resource_dir() const;
+ virtual String get_bundle_icon_path() const;
virtual String get_user_data_dir() const;
virtual String get_resource_dir() const;
@@ -276,6 +298,7 @@ public:
virtual void set_exit_code(int p_code);
virtual int get_processor_count() const;
+ virtual int get_default_thread_pool_size() const { return get_processor_count(); }
virtual String get_unique_id() const;
diff --git a/core/os/pool_allocator.cpp b/core/os/pool_allocator.cpp
index 74e9c24e04..190617f967 100644
--- a/core/os/pool_allocator.cpp
+++ b/core/os/pool_allocator.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/pool_allocator.h b/core/os/pool_allocator.h
index 49f433ba97..11a252bc54 100644
--- a/core/os/pool_allocator.h
+++ b/core/os/pool_allocator.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,13 +34,12 @@
#include "core/typedefs.h"
/**
- @author Juan Linietsky <reduzio@gmail.com>
* Generic Pool Allocator.
* This is a generic memory pool allocator, with locking, compacting and alignment. (@TODO alignment)
* It used as a standard way to manage allocation in a specific region of memory, such as texture memory,
* audio sample memory, or just any kind of memory overall.
* (@TODO) abstraction should be greater, because in many platforms, you need to manage a nonreachable memory.
-*/
+ */
enum {
POOL_ALLOCATOR_INVALID_ID = -1 ///< default invalid value. use INVALID_ID( id ) to test
diff --git a/core/os/rw_lock.h b/core/os/rw_lock.h
index 560ec57a5f..a046f474ea 100644
--- a/core/os/rw_lock.h
+++ b/core/os/rw_lock.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/semaphore.h b/core/os/semaphore.h
index 01ae7a3c65..72df52dd34 100644
--- a/core/os/semaphore.h
+++ b/core/os/semaphore.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/spin_lock.h b/core/os/spin_lock.h
index 929e8b9a58..27d915e0ae 100644
--- a/core/os/spin_lock.h
+++ b/core/os/spin_lock.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/thread.cpp b/core/os/thread.cpp
index 73e31bdb3d..f80e8f4bb3 100644
--- a/core/os/thread.cpp
+++ b/core/os/thread.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -28,6 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef PLATFORM_THREAD_OVERRIDE // See details in thread.h
+
#include "thread.h"
#include "core/object/script_language.h"
@@ -126,3 +128,4 @@ Thread::~Thread() {
}
#endif
+#endif // PLATFORM_THREAD_OVERRIDE
diff --git a/core/os/thread.h b/core/os/thread.h
index 17ac82c650..f4e46059ad 100644
--- a/core/os/thread.h
+++ b/core/os/thread.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -28,6 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+// Define PLATFORM_THREAD_OVERRIDE in your platform's `platform_config.h`
+// to use a custom Thread implementation defined in `platform/[your_platform]/platform_thread.h`
+// Overriding the platform implementation is required in some proprietary platforms
+#ifdef PLATFORM_THREAD_OVERRIDE
+#include "platform_thread.h"
+#else
#ifndef THREAD_H
#define THREAD_H
@@ -116,3 +122,4 @@ public:
};
#endif // THREAD_H
+#endif // PLATFORM_THREAD_OVERRIDE
diff --git a/core/os/thread_safe.h b/core/os/thread_safe.h
index 81de079bf3..fa443048e4 100644
--- a/core/os/thread_safe.h
+++ b/core/os/thread_safe.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/threaded_array_processor.h b/core/os/threaded_array_processor.h
index fec6473589..48b86cc1a1 100644
--- a/core/os/threaded_array_processor.h
+++ b/core/os/threaded_array_processor.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/time.cpp b/core/os/time.cpp
index a185029969..5eae94279a 100644
--- a/core/os/time.cpp
+++ b/core/os/time.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/time.h b/core/os/time.h
index 4325f93d56..3f00ba1478 100644
--- a/core/os/time.h
+++ b/core/os/time.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 3a037f9dd1..a18ec4d6ad 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -169,11 +169,13 @@ void register_core_types() {
GDREGISTER_VIRTUAL_CLASS(IP);
GDREGISTER_VIRTUAL_CLASS(StreamPeer);
+ GDREGISTER_CLASS(StreamPeerExtension);
GDREGISTER_CLASS(StreamPeerBuffer);
GDREGISTER_CLASS(StreamPeerTCP);
GDREGISTER_CLASS(TCPServer);
GDREGISTER_VIRTUAL_CLASS(PacketPeer);
+ GDREGISTER_CLASS(PacketPeerExtension);
GDREGISTER_CLASS(PacketPeerStream);
GDREGISTER_CLASS(PacketPeerUDP);
GDREGISTER_CLASS(UDPServer);
@@ -197,6 +199,7 @@ void register_core_types() {
ResourceLoader::add_resource_format_loader(resource_format_loader_crypto);
GDREGISTER_VIRTUAL_CLASS(MultiplayerPeer);
+ GDREGISTER_CLASS(MultiplayerPeerExtension);
GDREGISTER_VIRTUAL_CLASS(MultiplayerReplicator);
GDREGISTER_CLASS(MultiplayerAPI);
GDREGISTER_CLASS(MainLoop);
diff --git a/core/register_core_types.h b/core/register_core_types.h
index 830f05607d..0fd4e73c40 100644
--- a/core/register_core_types.h
+++ b/core/register_core_types.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/string/node_path.cpp b/core/string/node_path.cpp
index 5fae13779e..238897c2b1 100644
--- a/core/string/node_path.cpp
+++ b/core/string/node_path.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -293,12 +293,12 @@ void NodePath::simplify() {
break;
}
if (data->path[i].operator String() == ".") {
- data->path.remove(i);
+ data->path.remove_at(i);
i--;
} else if (i > 0 && data->path[i].operator String() == ".." && data->path[i - 1].operator String() != "." && data->path[i - 1].operator String() != "..") {
//remove both
- data->path.remove(i - 1);
- data->path.remove(i - 1);
+ data->path.remove_at(i - 1);
+ data->path.remove_at(i - 1);
i -= 2;
if (data->path.size() == 0) {
data->path.push_back(".");
@@ -368,7 +368,7 @@ NodePath::NodePath(const String &p_path) {
for (int i = from; i <= path.length(); i++) {
if (path[i] == ':' || path[i] == 0) {
String str = path.substr(from, i - from);
- if (str == "") {
+ if (str.is_empty()) {
if (path[i] == 0) {
continue; // Allow end-of-path :
}
diff --git a/core/string/node_path.h b/core/string/node_path.h
index a277ab26fa..53976bd524 100644
--- a/core/string/node_path.h
+++ b/core/string/node_path.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp
index 5863bd1c46..07b58f2418 100644
--- a/core/string/optimized_translation.cpp
+++ b/core/string/optimized_translation.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -64,7 +64,6 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
int idx = 0;
int total_compression_size = 0;
- int total_string_size = 0;
for (const StringName &E : keys) {
//hash string
@@ -102,7 +101,6 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
compressed.write[idx] = ps;
total_compression_size += ps.compressed.size();
- total_string_size += src_s.size();
idx++;
}
@@ -147,26 +145,23 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
uint32_t *btw = (uint32_t *)&btwb[0];
int btindex = 0;
- int collisions = 0;
for (int i = 0; i < size; i++) {
const Map<uint32_t, int> &t = table[i];
if (t.size() == 0) {
htw[i] = 0xFFFFFFFF; //nothing
continue;
- } else if (t.size() > 1) {
- collisions += t.size() - 1;
}
htw[i] = btindex;
btw[btindex++] = t.size();
btw[btindex++] = hfunc_table[i];
- for (Map<uint32_t, int>::Element *E = t.front(); E; E = E->next()) {
- btw[btindex++] = E->key();
- btw[btindex++] = compressed[E->get()].offset;
- btw[btindex++] = compressed[E->get()].compressed.size();
- btw[btindex++] = compressed[E->get()].orig_len;
+ for (const KeyValue<uint32_t, int> &E : t) {
+ btw[btindex++] = E.key;
+ btw[btindex++] = compressed[E.value].offset;
+ btw[btindex++] = compressed[E.value].compressed.size();
+ btw[btindex++] = compressed[E.value].orig_len;
}
}
diff --git a/core/string/optimized_translation.h b/core/string/optimized_translation.h
index bccf932383..f3dbfe8f5c 100644
--- a/core/string/optimized_translation.h
+++ b/core/string/optimized_translation.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,7 +38,7 @@ class OptimizedTranslation : public Translation {
//this translation uses a sort of modified perfect hash algorithm
//it requires hashing strings twice and then does a binary search,
- //so it's slower, but at the same time it has an extreemly high chance
+ //so it's slower, but at the same time it has an extremely high chance
//of catching untranslated strings
//load/store friendly types
diff --git a/core/string/print_string.cpp b/core/string/print_string.cpp
index 345371d733..97e119bcf6 100644
--- a/core/string/print_string.cpp
+++ b/core/string/print_string.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -69,7 +69,7 @@ void remove_print_handler(PrintHandlerList *p_handler) {
ERR_FAIL_COND(l == nullptr);
}
-void print_line(String p_string) {
+void __print_line(String p_string) {
if (!_print_line_enabled) {
return;
}
@@ -108,3 +108,7 @@ void print_verbose(String p_string) {
print_line(p_string);
}
}
+
+String stringify_variants(Variant p_var) {
+ return p_var.operator String();
+}
diff --git a/core/string/print_string.h b/core/string/print_string.h
index 1a9ff1efd6..669d2ea316 100644
--- a/core/string/print_string.h
+++ b/core/string/print_string.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,7 +31,7 @@
#ifndef PRINT_STRING_H
#define PRINT_STRING_H
-#include "core/string/ustring.h"
+#include "core/variant/variant.h"
extern void (*_print_func)(String);
@@ -46,13 +46,21 @@ struct PrintHandlerList {
PrintHandlerList() {}
};
+String stringify_variants(Variant p_var);
+
+template <typename... Args>
+String stringify_variants(Variant p_var, Args... p_args) {
+ return p_var.operator String() + " " + stringify_variants(p_args...);
+}
+
void add_print_handler(PrintHandlerList *p_handler);
void remove_print_handler(PrintHandlerList *p_handler);
extern bool _print_line_enabled;
extern bool _print_error_enabled;
-extern void print_line(String p_string);
+extern void __print_line(String p_string);
extern void print_error(String p_string);
extern void print_verbose(String p_string);
+#define print_line(...) __print_line(stringify_variants(__VA_ARGS__))
#endif // PRINT_STRING_H
diff --git a/core/string/string_buffer.h b/core/string/string_buffer.h
index 33897c3674..424952f786 100644
--- a/core/string/string_buffer.h
+++ b/core/string/string_buffer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/string/string_builder.cpp b/core/string/string_builder.cpp
index 834c87c845..7359ff59e1 100644
--- a/core/string/string_builder.cpp
+++ b/core/string/string_builder.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,7 +33,7 @@
#include <string.h>
StringBuilder &StringBuilder::append(const String &p_string) {
- if (p_string == String()) {
+ if (p_string.is_empty()) {
return *this;
}
diff --git a/core/string/string_builder.h b/core/string/string_builder.h
index 30ce2a06f7..897efa95ef 100644
--- a/core/string/string_builder.h
+++ b/core/string/string_builder.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp
index 9024f60dae..61742ac582 100644
--- a/core/string/string_name.cpp
+++ b/core/string/string_name.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -310,7 +310,7 @@ StringName::StringName(const String &p_name, bool p_static) {
ERR_FAIL_COND(!configured);
- if (p_name == String()) {
+ if (p_name.is_empty()) {
return;
}
@@ -434,7 +434,7 @@ StringName StringName::search(const char32_t *p_name) {
}
StringName StringName::search(const String &p_name) {
- ERR_FAIL_COND_V(p_name == "", StringName());
+ ERR_FAIL_COND_V(p_name.is_empty(), StringName());
MutexLock lock(mutex);
diff --git a/core/string/string_name.h b/core/string/string_name.h
index ce7988744b..9653d2b4cf 100644
--- a/core/string/string_name.h
+++ b/core/string/string_name.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/string/translation.cpp b/core/string/translation.cpp
index cb7d924556..615ecf2432 100644
--- a/core/string/translation.cpp
+++ b/core/string/translation.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,7 +35,6 @@
#include "core/os/os.h"
#ifdef TOOLS_ENABLED
-#include "editor/editor_settings.h"
#include "main/main.h"
#endif
@@ -810,9 +809,12 @@ static const char *locale_names[] = {
// - https://msdn.microsoft.com/en-us/library/windows/desktop/ms693062(v=vs.85).aspx
static const char *locale_renames[][2] = {
- { "in", "id" }, // Indonesian
- { "iw", "he" }, // Hebrew
- { "no", "nb" }, // Norwegian Bokmål
+ { "in", "id" }, // Indonesian
+ { "iw", "he" }, // Hebrew
+ { "no", "nb" }, // Norwegian Bokmål
+ { "C", "en" }, // "C" is the simple/default/untranslated Computer locale.
+ // ASCII-only, English, no currency symbols. Godot treats this as "en".
+ // See https://unix.stackexchange.com/a/87763/164141 "The C locale is"...
{ nullptr, nullptr }
};
@@ -820,8 +822,8 @@ static const char *locale_renames[][2] = {
Dictionary Translation::_get_messages() const {
Dictionary d;
- for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) {
- d[E->key()] = E->value();
+ for (const KeyValue<StringName, StringName> &E : translation_map) {
+ d[E.key] = E.value;
}
return d;
}
@@ -830,8 +832,8 @@ Vector<String> Translation::_get_message_list() const {
Vector<String> msgs;
msgs.resize(translation_map.size());
int idx = 0;
- for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) {
- msgs.set(idx, E->key());
+ for (const KeyValue<StringName, StringName> &E : translation_map) {
+ msgs.set(idx, E.key);
idx += 1;
}
@@ -875,6 +877,11 @@ void Translation::add_plural_message(const StringName &p_src_text, const Vector<
}
StringName Translation::get_message(const StringName &p_src_text, const StringName &p_context) const {
+ StringName ret;
+ if (GDVIRTUAL_CALL(_get_message, p_src_text, p_context, ret)) {
+ return ret;
+ }
+
if (p_context != StringName()) {
WARN_PRINT("Translation class doesn't handle context. Using context in get_message() on a Translation instance is probably a mistake. \nUse a derived Translation class that handles context, such as TranslationPO class");
}
@@ -888,6 +895,11 @@ StringName Translation::get_message(const StringName &p_src_text, const StringNa
}
StringName Translation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const {
+ StringName ret;
+ if (GDVIRTUAL_CALL(_get_plural_message, p_src_text, p_plural_text, p_n, p_context, ret)) {
+ return ret;
+ }
+
WARN_PRINT("Translation class doesn't handle plural messages. Calling get_plural_message() on a Translation instance is probably a mistake. \nUse a derived Translation class that handles plurals, such as TranslationPO class");
return get_message(p_src_text);
}
@@ -901,8 +913,8 @@ void Translation::erase_message(const StringName &p_src_text, const StringName &
}
void Translation::get_message_list(List<StringName> *r_messages) const {
- for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) {
- r_messages->push_back(E->key());
+ for (const KeyValue<StringName, StringName> &E : translation_map) {
+ r_messages->push_back(E.key);
}
}
@@ -923,7 +935,10 @@ void Translation::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_messages"), &Translation::_set_messages);
ClassDB::bind_method(D_METHOD("_get_messages"), &Translation::_get_messages);
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "messages", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_messages", "_get_messages");
+ GDVIRTUAL_BIND(_get_plural_message, "src_message", "src_plural_message", "n", "context");
+ GDVIRTUAL_BIND(_get_message, "src_message", "context");
+
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "messages", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_messages", "_get_messages");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "locale"), "set_locale", "get_locale");
}
@@ -1077,9 +1092,12 @@ Array TranslationServer::get_loaded_locales() const {
ERR_FAIL_COND_V(t.is_null(), Array());
String l = t->get_locale();
- locales.push_back(l);
+ if (!locales.has(l)) {
+ locales.push_back(l);
+ }
}
+ locales.sort();
return locales;
}
@@ -1272,7 +1290,7 @@ bool TranslationServer::_load_translations(const String &p_from) {
void TranslationServer::setup() {
String test = GLOBAL_DEF("internationalization/locale/test", "");
test = test.strip_edges();
- if (test != "") {
+ if (!test.is_empty()) {
set_locale(test);
} else {
set_locale(OS::get_singleton()->get_locale());
@@ -1548,8 +1566,8 @@ const char32_t *TranslationServer::get_accented_version(char32_t p_character) co
bool TranslationServer::is_placeholder(String &p_message, int p_index) const {
return p_message[p_index] == '%' && p_index < p_message.size() - 1 &&
- (p_message[p_index + 1] == 's' || p_message[p_index + 1] == 'c' || p_message[p_index + 1] == 'd' ||
- p_message[p_index + 1] == 'o' || p_message[p_index + 1] == 'x' || p_message[p_index + 1] == 'X' || p_message[p_index + 1] == 'f');
+ (p_message[p_index + 1] == 's' || p_message[p_index + 1] == 'c' || p_message[p_index + 1] == 'd' ||
+ p_message[p_index + 1] == 'o' || p_message[p_index + 1] == 'x' || p_message[p_index + 1] == 'X' || p_message[p_index + 1] == 'f');
}
void TranslationServer::_bind_methods() {
diff --git a/core/string/translation.h b/core/string/translation.h
index 4f179ac0fe..e95d15e2ab 100644
--- a/core/string/translation.h
+++ b/core/string/translation.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,8 @@
#define TRANSLATION_H
#include "core/io/resource.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
class Translation : public Resource {
GDCLASS(Translation, Resource);
@@ -48,6 +50,9 @@ class Translation : public Resource {
protected:
static void _bind_methods();
+ GDVIRTUAL2RC(StringName, _get_message, StringName, StringName);
+ GDVIRTUAL4RC(StringName, _get_plural_message, StringName, StringName, int, StringName);
+
public:
void set_locale(const String &p_locale);
_FORCE_INLINE_ String get_locale() const { return locale; }
diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp
index 1da00aa54b..1c991ee12d 100644
--- a/core/string/translation_po.cpp
+++ b/core/string/translation_po.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/string/translation_po.h b/core/string/translation_po.h
index 0e1d03d6ca..7d63af2246 100644
--- a/core/string/translation_po.h
+++ b/core/string/translation_po.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/string/ucaps.h b/core/string/ucaps.h
index b785ac7879..357d36e703 100644
--- a/core/string/ucaps.h
+++ b/core/string/ucaps.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 8416ff929e..0949980713 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,6 +38,7 @@
#include "core/string/translation.h"
#include "core/string/ucaps.h"
#include "core/variant/variant.h"
+#include "core/version_generated.gen.h"
#include <stdio.h>
#include <stdlib.h>
@@ -129,9 +130,8 @@ Char16String &Char16String::operator+=(char16_t p_char) {
return *this;
}
-Char16String &Char16String::operator=(const char16_t *p_cstr) {
+void Char16String::operator=(const char16_t *p_cstr) {
copy_from(p_cstr);
- return *this;
}
const char16_t *Char16String::get_data() const {
@@ -185,9 +185,8 @@ CharString &CharString::operator+=(char p_char) {
return *this;
}
-CharString &CharString::operator=(const char *p_cstr) {
+void CharString::operator=(const char *p_cstr) {
copy_from(p_cstr);
- return *this;
}
const char *CharString::get_data() const {
@@ -952,10 +951,6 @@ const char32_t *String::get_data() const {
return size() ? &operator[](0) : &zero;
}
-void String::erase(int p_pos, int p_chars) {
- *this = left(MAX(p_pos, 0)) + substr(p_pos + p_chars, length() - ((p_pos + p_chars)));
-}
-
String String::capitalize() const {
String aux = this->camelcase_to_underscore(true).replace("_", " ").strip_edges();
String cap;
@@ -1551,19 +1546,21 @@ String String::num_real(double p_num, bool p_trailing) {
bool neg = p_num < 0;
p_num = ABS(p_num);
- int intn = (int)p_num;
+ int64_t intn = (int64_t)p_num;
// Decimal part.
if (intn != p_num) {
- double dec = p_num - (double)(intn);
+ double dec = p_num - (double)intn;
int digit = 0;
-#if REAL_T_IS_DOUBLE
+#ifdef REAL_T_IS_DOUBLE
int decimals = 14;
+ double tolerance = 1e-14;
#else
int decimals = 6;
+ double tolerance = 1e-6;
#endif
// We want to align the digits to the above sane default, so we only
// need to subtract log10 for numbers with a positive power of ten.
@@ -1575,16 +1572,21 @@ String String::num_real(double p_num, bool p_trailing) {
decimals = MAX_DECIMALS;
}
- int dec_int = 0;
- int dec_max = 0;
+ // In case the value ends up ending in "99999", we want to add a
+ // tiny bit to the value we're checking when deciding when to stop,
+ // so we multiply by slightly above 1 (1 + 1e-7 or 1e-15).
+ double check_multiplier = 1 + tolerance / 10;
+
+ int64_t dec_int = 0;
+ int64_t dec_max = 0;
while (true) {
dec *= 10.0;
- dec_int = dec_int * 10 + (int)dec % 10;
+ dec_int = dec_int * 10 + (int64_t)dec % 10;
dec_max = dec_max * 10 + 9;
digit++;
- if ((dec - (double)((int)dec)) < 1e-6) {
+ if ((dec - (double)(int64_t)(dec * check_multiplier)) < tolerance) {
break;
}
@@ -1594,7 +1596,7 @@ String String::num_real(double p_num, bool p_trailing) {
}
dec *= 10;
- int last = (int)dec % 10;
+ int last = (int64_t)dec % 10;
if (last > 5) {
if (dec_int == dec_max) {
@@ -2130,7 +2132,7 @@ int64_t String::hex_to_int() const {
s++;
}
- if (len > 2 && s[0] == '0' && s[1] == 'x') {
+ if (len > 2 && s[0] == '0' && lower_case(s[1]) == 'x') {
s += 2;
}
@@ -2144,7 +2146,7 @@ int64_t String::hex_to_int() const {
} else if (c >= 'a' && c <= 'f') {
n = (c - 'a') + 10;
} else {
- return 0;
+ ERR_FAIL_COND_V_MSG(true, 0, "Invalid hexadecimal notation character \"" + chr(*s) + "\" in string \"" + *this + "\".");
}
// Check for overflow/underflow, with special case to ensure INT64_MIN does not result in error
bool overflow = ((hex > INT64_MAX / 16) && (sign == 1 || (sign == -1 && hex != (INT64_MAX >> 4) + 1))) || (sign == -1 && hex == (INT64_MAX >> 4) + 1 && c > '0');
@@ -2171,7 +2173,7 @@ int64_t String::bin_to_int() const {
s++;
}
- if (len > 2 && s[0] == '0' && s[1] == 'b') {
+ if (len > 2 && s[0] == '0' && lower_case(s[1]) == 'b') {
s += 2;
}
@@ -2310,28 +2312,33 @@ bool String::is_numeric() const {
}
template <class C>
-static double built_in_strtod(const C *string, /* A decimal ASCII floating-point number,
- * optionally preceded by white space. Must
- * have form "-I.FE-X", where I is the integer
- * part of the mantissa, F is the fractional
- * part of the mantissa, and X is the
- * exponent. Either of the signs may be "+",
- * "-", or omitted. Either I or F may be
- * omitted, or both. The decimal point isn't
- * necessary unless F is present. The "E" may
- * actually be an "e". E and X may both be
- * omitted (but not just one). */
- C **endPtr = nullptr) /* If non-nullptr, store terminating Cacter's
- * address here. */
-{
- static const int maxExponent = 511; /* Largest possible base 10 exponent. Any
- * exponent larger than this will already
- * produce underflow or overflow, so there's
- * no need to worry about additional digits.
- */
- static const double powersOf10[] = { /* Table giving binary powers of 10. Entry */
- 10., /* is 10^2^i. Used to convert decimal */
- 100., /* exponents into floating-point numbers. */
+static double built_in_strtod(
+ /* A decimal ASCII floating-point number,
+ * optionally preceded by white space. Must
+ * have form "-I.FE-X", where I is the integer
+ * part of the mantissa, F is the fractional
+ * part of the mantissa, and X is the
+ * exponent. Either of the signs may be "+",
+ * "-", or omitted. Either I or F may be
+ * omitted, or both. The decimal point isn't
+ * necessary unless F is present. The "E" may
+ * actually be an "e". E and X may both be
+ * omitted (but not just one). */
+ const C *string,
+ /* If non-nullptr, store terminating Cacter's
+ * address here. */
+ C **endPtr = nullptr) {
+ /* Largest possible base 10 exponent. Any
+ * exponent larger than this will already
+ * produce underflow or overflow, so there's
+ * no need to worry about additional digits. */
+ static const int maxExponent = 511;
+ /* Table giving binary powers of 10. Entry
+ * is 10^2^i. Used to convert decimal
+ * exponents into floating-point numbers. */
+ static const double powersOf10[] = {
+ 10.,
+ 100.,
1.0e4,
1.0e8,
1.0e16,
@@ -2346,25 +2353,28 @@ static double built_in_strtod(const C *string, /* A decimal ASCII floating-point
const double *d;
const C *p;
int c;
- int exp = 0; /* Exponent read from "EX" field. */
- int fracExp = 0; /* Exponent that derives from the fractional
- * part. Under normal circumstances, it is
- * the negative of the number of digits in F.
- * However, if I is very long, the last digits
- * of I get dropped (otherwise a long I with a
- * large negative exponent could cause an
- * unnecessary overflow on I alone). In this
- * case, fracExp is incremented one for each
- * dropped digit. */
- int mantSize; /* Number of digits in mantissa. */
- int decPt; /* Number of mantissa digits BEFORE decimal
- * point. */
- const C *pExp; /* Temporarily holds location of exponent in
- * string. */
+ /* Exponent read from "EX" field. */
+ int exp = 0;
+ /* Exponent that derives from the fractional
+ * part. Under normal circumstances, it is
+ * the negative of the number of digits in F.
+ * However, if I is very long, the last digits
+ * of I get dropped (otherwise a long I with a
+ * large negative exponent could cause an
+ * unnecessary overflow on I alone). In this
+ * case, fracExp is incremented one for each
+ * dropped digit. */
+ int fracExp = 0;
+ /* Number of digits in mantissa. */
+ int mantSize;
+ /* Number of mantissa digits BEFORE decimal point. */
+ int decPt;
+ /* Temporarily holds location of exponent in string. */
+ const C *pExp;
/*
- * Strip off leading blanks and check for a sign.
- */
+ * Strip off leading blanks and check for a sign.
+ */
p = string;
while (*p == ' ' || *p == '\t' || *p == '\n') {
@@ -2381,9 +2391,9 @@ static double built_in_strtod(const C *string, /* A decimal ASCII floating-point
}
/*
- * Count the number of digits in the mantissa (including the decimal
- * point), and also locate the decimal point.
- */
+ * Count the number of digits in the mantissa (including the decimal
+ * point), and also locate the decimal point.
+ */
decPt = -1;
for (mantSize = 0;; mantSize += 1) {
@@ -2398,11 +2408,11 @@ static double built_in_strtod(const C *string, /* A decimal ASCII floating-point
}
/*
- * Now suck up the digits in the mantissa. Use two integers to collect 9
- * digits each (this is faster than using floating-point). If the mantissa
- * has more than 18 digits, ignore the extras, since they can't affect the
- * value anyway.
- */
+ * Now suck up the digits in the mantissa. Use two integers to collect 9
+ * digits each (this is faster than using floating-point). If the mantissa
+ * has more than 18 digits, ignore the extras, since they can't affect the
+ * value anyway.
+ */
pExp = p;
p -= mantSize;
@@ -2448,8 +2458,8 @@ static double built_in_strtod(const C *string, /* A decimal ASCII floating-point
}
/*
- * Skim off the exponent.
- */
+ * Skim off the exponent.
+ */
p = pExp;
if ((*p == 'E') || (*p == 'e')) {
@@ -2479,10 +2489,10 @@ static double built_in_strtod(const C *string, /* A decimal ASCII floating-point
}
/*
- * Generate a floating-point number that represents the exponent. Do this
- * by processing the exponent one bit at a time to combine many powers of
- * 2 of 10. Then combine the exponent with the fraction.
- */
+ * Generate a floating-point number that represents the exponent. Do this
+ * by processing the exponent one bit at a time to combine many powers of
+ * 2 of 10. Then combine the exponent with the fraction.
+ */
if (exp < 0) {
expSign = true;
@@ -3497,6 +3507,27 @@ char32_t String::unicode_at(int p_idx) const {
return operator[](p_idx);
}
+String String::indent(const String &p_prefix) const {
+ String new_string;
+ int line_start = 0;
+
+ for (int i = 0; i < length(); i++) {
+ const char32_t c = operator[](i);
+ if (c == '\n') {
+ if (i == line_start) {
+ new_string += c; // Leave empty lines empty.
+ } else {
+ new_string += p_prefix + substr(line_start, i - line_start + 1);
+ }
+ line_start = i + 1;
+ }
+ }
+ if (line_start != length()) {
+ new_string += p_prefix + substr(line_start);
+ }
+ return new_string;
+}
+
String String::dedent() const {
String new_string;
String indent;
@@ -3555,7 +3586,7 @@ String String::strip_edges(bool left, bool right) const {
}
if (right) {
- for (int i = (int)(len - 1); i >= 0; i--) {
+ for (int i = len - 1; i >= 0; i--) {
if (operator[](i) <= 32) {
end--;
} else {
@@ -3658,15 +3689,15 @@ String String::simplify_path() const {
for (int i = 0; i < dirs.size(); i++) {
String d = dirs[i];
if (d == ".") {
- dirs.remove(i);
+ dirs.remove_at(i);
i--;
} else if (d == "..") {
if (i == 0) {
- dirs.remove(i);
+ dirs.remove_at(i);
i--;
} else {
- dirs.remove(i);
- dirs.remove(i - 1);
+ dirs.remove_at(i);
+ dirs.remove_at(i - 1);
i -= 2;
}
}
@@ -4273,7 +4304,7 @@ bool String::is_valid_filename() const {
return false;
}
- if (stripped == String()) {
+ if (stripped.is_empty()) {
return false;
}
@@ -4405,7 +4436,7 @@ String String::property_name_encode() const {
// as well as '"', '=' or ' ' (32)
const char32_t *cstr = get_data();
for (int i = 0; cstr[i]; i++) {
- if (cstr[i] == '=' || cstr[i] == '"' || cstr[i] < 33 || cstr[i] > 126) {
+ if (cstr[i] == '=' || cstr[i] == '"' || cstr[i] == ';' || cstr[i] == '[' || cstr[i] == ']' || cstr[i] < 33 || cstr[i] > 126) {
return "\"" + c_escape_multiline() + "\"";
}
}
@@ -4857,15 +4888,20 @@ String TTRN(const String &p_text, const String &p_text_plural, int p_n, const St
return p_text_plural;
}
+/* DTR and DTRN are used for the documentation, handling descriptions extracted
+ * from the XML.
+ * They also replace `$DOCS_URL` with the actual URL to the documentation's branch,
+ * to allow dehardcoding it in the XML and doing proper substitutions everywhere.
+ */
String DTR(const String &p_text, const String &p_context) {
// Comes straight from the XML, so remove indentation and any trailing whitespace.
const String text = p_text.dedent().strip_edges();
if (TranslationServer::get_singleton()) {
- return TranslationServer::get_singleton()->doc_translate(text, p_context);
+ return String(TranslationServer::get_singleton()->doc_translate(text, p_context)).replace("$DOCS_URL", VERSION_DOCS_URL);
}
- return text;
+ return text.replace("$DOCS_URL", VERSION_DOCS_URL);
}
String DTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) {
@@ -4873,21 +4909,21 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St
const String text_plural = p_text_plural.dedent().strip_edges();
if (TranslationServer::get_singleton()) {
- return TranslationServer::get_singleton()->doc_translate_plural(text, text_plural, p_n, p_context);
+ return String(TranslationServer::get_singleton()->doc_translate_plural(text, text_plural, p_n, p_context)).replace("$DOCS_URL", VERSION_DOCS_URL);
}
// Return message based on English plural rule if translation is not possible.
if (p_n == 1) {
- return text;
+ return text.replace("$DOCS_URL", VERSION_DOCS_URL);
}
- return text_plural;
+ return text_plural.replace("$DOCS_URL", VERSION_DOCS_URL);
}
#endif
String RTR(const String &p_text, const String &p_context) {
if (TranslationServer::get_singleton()) {
String rtr = TranslationServer::get_singleton()->tool_translate(p_text, p_context);
- if (rtr == String() || rtr == p_text) {
+ if (rtr.is_empty() || rtr == p_text) {
return TranslationServer::get_singleton()->translate(p_text, p_context);
} else {
return rtr;
@@ -4900,7 +4936,7 @@ String RTR(const String &p_text, const String &p_context) {
String RTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) {
if (TranslationServer::get_singleton()) {
String rtr = TranslationServer::get_singleton()->tool_translate_plural(p_text, p_text_plural, p_n, p_context);
- if (rtr == String() || rtr == p_text || rtr == p_text_plural) {
+ if (rtr.is_empty() || rtr == p_text || rtr == p_text_plural) {
return TranslationServer::get_singleton()->translate_plural(p_text, p_text_plural, p_n, p_context);
} else {
return rtr;
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 24da6b82af..4840c236c0 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -51,11 +51,15 @@ class CharProxy {
CowData<T> &_cowdata;
static const T _null = 0;
- _FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &cowdata) :
+ _FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &p_cowdata) :
_index(p_index),
- _cowdata(cowdata) {}
+ _cowdata(p_cowdata) {}
public:
+ _FORCE_INLINE_ CharProxy(const CharProxy<T> &p_other) :
+ _index(p_other._index),
+ _cowdata(p_other._cowdata) {}
+
_FORCE_INLINE_ operator T() const {
if (unlikely(_index == _cowdata.size())) {
return _null;
@@ -68,12 +72,12 @@ public:
return _cowdata.ptr() + _index;
}
- _FORCE_INLINE_ void operator=(const T &other) const {
- _cowdata.set(_index, other);
+ _FORCE_INLINE_ void operator=(const T &p_other) const {
+ _cowdata.set(_index, p_other);
}
- _FORCE_INLINE_ void operator=(const CharProxy<T> &other) const {
- _cowdata.set(_index, other.operator T());
+ _FORCE_INLINE_ void operator=(const CharProxy<T> &p_other) const {
+ _cowdata.set(_index, p_other.operator T());
}
};
@@ -104,13 +108,10 @@ public:
_FORCE_INLINE_ Char16String() {}
_FORCE_INLINE_ Char16String(const Char16String &p_str) { _cowdata._ref(p_str._cowdata); }
- _FORCE_INLINE_ Char16String &operator=(const Char16String &p_str) {
- _cowdata._ref(p_str._cowdata);
- return *this;
- }
+ _FORCE_INLINE_ void operator=(const Char16String &p_str) { _cowdata._ref(p_str._cowdata); }
_FORCE_INLINE_ Char16String(const char16_t *p_cstr) { copy_from(p_cstr); }
- Char16String &operator=(const char16_t *p_cstr);
+ void operator=(const char16_t *p_cstr);
bool operator<(const Char16String &p_right) const;
Char16String &operator+=(char16_t p_char);
int length() const { return size() ? size() - 1 : 0; }
@@ -148,13 +149,10 @@ public:
_FORCE_INLINE_ CharString() {}
_FORCE_INLINE_ CharString(const CharString &p_str) { _cowdata._ref(p_str._cowdata); }
- _FORCE_INLINE_ CharString &operator=(const CharString &p_str) {
- _cowdata._ref(p_str._cowdata);
- return *this;
- }
+ _FORCE_INLINE_ void operator=(const CharString &p_str) { _cowdata._ref(p_str._cowdata); }
_FORCE_INLINE_ CharString(const char *p_cstr) { copy_from(p_cstr); }
- CharString &operator=(const char *p_cstr);
+ void operator=(const char *p_cstr);
bool operator<(const CharString &p_right) const;
CharString &operator+=(char p_char);
int length() const { return size() ? size() - 1 : 0; }
@@ -205,7 +203,7 @@ public:
_FORCE_INLINE_ char32_t *ptrw() { return _cowdata.ptrw(); }
_FORCE_INLINE_ const char32_t *ptr() const { return _cowdata.ptr(); }
- void remove(int p_index) { _cowdata.remove(p_index); }
+ void remove_at(int p_index) { _cowdata.remove_at(p_index); }
_FORCE_INLINE_ void clear() { resize(0); }
@@ -358,6 +356,7 @@ public:
String left(int p_pos) const;
String right(int p_pos) const;
+ String indent(const String &p_prefix) const;
String dedent() const;
String strip_edges(bool left = true, bool right = true) const;
String strip_escapes() const;
@@ -438,11 +437,7 @@ public:
_FORCE_INLINE_ String() {}
_FORCE_INLINE_ String(const String &p_str) { _cowdata._ref(p_str._cowdata); }
-
- String &operator=(const String &p_str) {
- _cowdata._ref(p_str._cowdata);
- return *this;
- }
+ _FORCE_INLINE_ void operator=(const String &p_str) { _cowdata._ref(p_str._cowdata); }
Vector<uint8_t> to_ascii_buffer() const;
Vector<uint8_t> to_utf8_buffer() const;
diff --git a/core/templates/bin_sorted_array.h b/core/templates/bin_sorted_array.h
index be9d0b5475..59ac4cdaa1 100644
--- a/core/templates/bin_sorted_array.h
+++ b/core/templates/bin_sorted_array.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -112,7 +112,7 @@ public:
return current_idx;
}
- void remove(uint64_t p_idx) {
+ void remove_at(uint64_t p_idx) {
ERR_FAIL_COND(p_idx >= array.size());
uint64_t new_idx = move(p_idx, 0);
uint64_t swap_idx = array.size() - 1;
diff --git a/core/templates/command_queue_mt.cpp b/core/templates/command_queue_mt.cpp
index 04a8095f0b..a40ff88a19 100644
--- a/core/templates/command_queue_mt.cpp
+++ b/core/templates/command_queue_mt.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h
index 519a896ffc..1ecb81c2a2 100644
--- a/core/templates/command_queue_mt.h
+++ b/core/templates/command_queue_mt.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h
index 9b8c0eb528..326616b607 100644
--- a/core/templates/cowdata.h
+++ b/core/templates/cowdata.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -167,7 +167,7 @@ public:
Error resize(int p_size);
- _FORCE_INLINE_ void remove(int p_index) {
+ _FORCE_INLINE_ void remove_at(int p_index) {
ERR_FAIL_INDEX(p_index, size());
T *p = ptrw();
int len = size();
diff --git a/core/templates/hash_map.h b/core/templates/hash_map.h
index 1257b54449..fa5677cc70 100644
--- a/core/templates/hash_map.h
+++ b/core/templates/hash_map.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -40,7 +40,6 @@
/**
* @class HashMap
- * @author Juan Linietsky <reduzio@gmail.com>
*
* Implementation of a standard Hashing HashMap, for quick lookups of Data associated with a Key.
* The implementation provides hashers for the default types, if you need a special kind of hasher, provide
@@ -48,12 +47,13 @@
* @param TKey Key, search is based on it, needs to be hasheable. It is unique in this container.
* @param TData Data, data associated with the key
* @param Hasher Hasher object, needs to provide a valid static hash function for TKey
- * @param Comparator comparator object, needs to be able to safely compare two TKey values. It needs to ensure that x == x for any items inserted in the map. Bear in mind that nan != nan when implementing an equality check.
+ * @param Comparator comparator object, needs to be able to safely compare two TKey values.
+ * It needs to ensure that x == x for any items inserted in the map. Bear in mind that nan != nan when implementing an equality check.
* @param MIN_HASH_TABLE_POWER Miminum size of the hash table, as a power of two. You rarely need to change this parameter.
* @param RELATIONSHIP Relationship at which the hash table is resized. if amount of elements is RELATIONSHIP
* times bigger than the hash table, table is resized to solve this condition. if RELATIONSHIP is zero, table is always MIN_HASH_TABLE_POWER.
*
-*/
+ */
template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey>, uint8_t MIN_HASH_TABLE_POWER = 3, uint8_t RELATIONSHIP = 8>
class HashMap {
@@ -62,7 +62,9 @@ public:
TKey key;
TData data;
- Pair() {}
+ Pair(const TKey &p_key) :
+ key(p_key),
+ data() {}
Pair(const TKey &p_key, const TData &p_data) :
key(p_key),
data(p_data) {
@@ -90,6 +92,12 @@ public:
const TData &value() const {
return pair.value();
}
+
+ Element(const TKey &p_key) :
+ pair(p_key) {}
+ Element(const Element &p_other) :
+ hash(p_other.hash),
+ pair(p_other.pair.key, p_other.pair.data) {}
};
private:
@@ -192,14 +200,12 @@ private:
Element *create_element(const TKey &p_key) {
/* if element doesn't exist, create it */
- Element *e = memnew(Element);
+ Element *e = memnew(Element(p_key));
ERR_FAIL_COND_V_MSG(!e, nullptr, "Out of memory.");
uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash & ((1 << hash_table_power) - 1);
e->next = hash_table[index];
e->hash = hash;
- e->pair.key = p_key;
- e->pair.data = TData();
hash_table[index] = e;
elements++;
@@ -228,9 +234,7 @@ private:
const Element *e = p_t.hash_table[i];
while (e) {
- Element *le = memnew(Element); /* local element */
-
- *le = *e; /* copy data */
+ Element *le = memnew(Element(*e)); /* local element */
/* add to list and reassign pointers */
le->next = hash_table[i];
@@ -454,8 +458,8 @@ public:
*
* print( *k );
* }
- *
- */
+ *
+ */
const TKey *next(const TKey *p_key) const {
if (unlikely(!hash_table)) {
return nullptr;
diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h
index 2e932f9f26..2a129f97d5 100644
--- a/core/templates/hashfuncs.h
+++ b/core/templates/hashfuncs.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -74,6 +74,13 @@ static inline uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) {
return ((p_prev << 5) + p_prev) + p_in;
}
+/**
+ * Thomas Wang's 64-bit to 32-bit Hash function:
+ * https://web.archive.org/web/20071223173210/https:/www.concentric.net/~Ttwang/tech/inthash.htm
+ *
+ * @param p_int - 64-bit unsigned integer key to be hashed
+ * @return unsigned 32-bit value representing hashcode
+ */
static inline uint32_t hash_one_uint64(const uint64_t p_int) {
uint64_t v = p_int;
v = (~v) + (v << 18); // v = (v << 18) - v - 1;
@@ -82,7 +89,7 @@ static inline uint32_t hash_one_uint64(const uint64_t p_int) {
v = v ^ (v >> 11);
v = v + (v << 6);
v = v ^ (v >> 22);
- return (int)v;
+ return uint32_t(v);
}
static inline uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381) {
diff --git a/core/templates/list.h b/core/templates/list.h
index c2e17a2f6f..fe14d85d8f 100644
--- a/core/templates/list.h
+++ b/core/templates/list.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -249,29 +249,29 @@ private:
public:
/**
- * return a const iterator to the beginning of the list.
- */
+ * return a const iterator to the beginning of the list.
+ */
_FORCE_INLINE_ const Element *front() const {
return _data ? _data->first : nullptr;
}
/**
- * return an iterator to the beginning of the list.
- */
+ * return an iterator to the beginning of the list.
+ */
_FORCE_INLINE_ Element *front() {
return _data ? _data->first : nullptr;
}
/**
- * return a const iterator to the last member of the list.
- */
+ * return a const iterator to the last member of the list.
+ */
_FORCE_INLINE_ const Element *back() const {
return _data ? _data->last : nullptr;
}
/**
- * return an iterator to the last member of the list.
- */
+ * return an iterator to the last member of the list.
+ */
_FORCE_INLINE_ Element *back() {
return _data ? _data->last : nullptr;
}
diff --git a/core/templates/local_vector.h b/core/templates/local_vector.h
index 5704b8f230..f4e0748c27 100644
--- a/core/templates/local_vector.h
+++ b/core/templates/local_vector.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,6 +36,8 @@
#include "core/templates/sort_array.h"
#include "core/templates/vector.h"
+#include <initializer_list>
+
template <class T, class U = uint32_t, bool force_trivial = false>
class LocalVector {
private:
@@ -70,7 +72,7 @@ public:
}
}
- void remove(U p_index) {
+ void remove_at(U p_index) {
ERR_FAIL_UNSIGNED_INDEX(p_index, count);
count--;
for (U i = p_index; i < count; i++) {
@@ -83,7 +85,7 @@ public:
/// Removes the item copying the last value into the position of the one to
/// remove. It's generally faster than `remove`.
- void remove_unordered(U p_index) {
+ void remove_at_unordered(U p_index) {
ERR_FAIL_INDEX(p_index, count);
count--;
if (count > p_index) {
@@ -97,7 +99,7 @@ public:
void erase(const T &p_val) {
int64_t idx = find(p_val);
if (idx >= 0) {
- remove(idx);
+ remove_at(idx);
}
}
@@ -228,25 +230,29 @@ public:
}
_FORCE_INLINE_ LocalVector() {}
+ _FORCE_INLINE_ LocalVector(std::initializer_list<T> p_init) {
+ reserve(p_init.size());
+ for (const T &element : p_init) {
+ push_back(element);
+ }
+ }
_FORCE_INLINE_ LocalVector(const LocalVector &p_from) {
resize(p_from.size());
for (U i = 0; i < p_from.count; i++) {
data[i] = p_from.data[i];
}
}
- inline LocalVector &operator=(const LocalVector &p_from) {
+ inline void operator=(const LocalVector &p_from) {
resize(p_from.size());
for (U i = 0; i < p_from.count; i++) {
data[i] = p_from.data[i];
}
- return *this;
}
- inline LocalVector &operator=(const Vector<T> &p_from) {
+ inline void operator=(const Vector<T> &p_from) {
resize(p_from.size());
for (U i = 0; i < count; i++) {
data[i] = p_from[i];
}
- return *this;
}
_FORCE_INLINE_ ~LocalVector() {
diff --git a/core/templates/lru.h b/core/templates/lru.h
index e55e40da48..48ba318b12 100644
--- a/core/templates/lru.h
+++ b/core/templates/lru.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/map.h b/core/templates/map.h
index badb407e5d..f228640a1e 100644
--- a/core/templates/map.h
+++ b/core/templates/map.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/oa_hash_map.h b/core/templates/oa_hash_map.h
index 025cc30db4..c91d27ebe1 100644
--- a/core/templates/oa_hash_map.h
+++ b/core/templates/oa_hash_map.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -353,7 +353,7 @@ public:
(*this) = p_other;
}
- OAHashMap &operator=(const OAHashMap &p_other) {
+ void operator=(const OAHashMap &p_other) {
if (capacity != 0) {
clear();
}
@@ -363,7 +363,6 @@ public:
for (Iterator it = p_other.iter(); it.valid; it = p_other.next_iter(it)) {
set(*it.key, *it.value);
}
- return *this;
}
OAHashMap(uint32_t p_initial_capacity = 64) {
diff --git a/core/templates/ordered_hash_map.h b/core/templates/ordered_hash_map.h
index 7a17eeb644..3d1f3a08ec 100644
--- a/core/templates/ordered_hash_map.h
+++ b/core/templates/ordered_hash_map.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -85,11 +85,10 @@ public:
next_element(other.next_element) {
}
- Element &operator=(const Element &other) {
+ void operator=(const Element &other) {
list_element = other.list_element;
next_element = other.next_element;
prev_element = other.prev_element;
- return *this;
}
_FORCE_INLINE_ bool operator==(const Element &p_other) const {
@@ -145,9 +144,8 @@ public:
list_element(other.list_element) {
}
- ConstElement &operator=(const ConstElement &other) {
+ void operator=(const ConstElement &other) {
list_element = other.list_element;
- return *this;
}
ConstElement next() const {
@@ -207,8 +205,12 @@ public:
(*list_element)->get().second = p_value;
return Element(*list_element);
}
- typename InternalList::Element *new_element = list.push_back(Pair<const K *, V>(nullptr, p_value));
+ // Incorrectly set the first value of the pair with a value that will
+ // be invalid as soon as we leave this function...
+ typename InternalList::Element *new_element = list.push_back(Pair<const K *, V>(&p_key, p_value));
+ // ...this is needed here in case the hashmap recursively reference itself...
typename InternalMap::Element *e = map.set(p_key, new_element);
+ // ...now we can set the right value !
new_element->get().first = &e->key();
return Element(new_element);
diff --git a/core/templates/paged_allocator.h b/core/templates/paged_allocator.h
index dfc885c6eb..5bc723787f 100644
--- a/core/templates/paged_allocator.h
+++ b/core/templates/paged_allocator.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/paged_array.h b/core/templates/paged_array.h
index 599d3dde4f..33d2757bec 100644
--- a/core/templates/paged_array.h
+++ b/core/templates/paged_array.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/pair.h b/core/templates/pair.h
index e30ee8bc56..eb86e21b03 100644
--- a/core/templates/pair.h
+++ b/core/templates/pair.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/pass_func.h b/core/templates/pass_func.h
index d2f465e91c..8bd34ddfd6 100644
--- a/core/templates/pass_func.h
+++ b/core/templates/pass_func.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/pooled_list.h b/core/templates/pooled_list.h
index b4a6d2d1dd..360fda81f8 100644
--- a/core/templates/pooled_list.h
+++ b/core/templates/pooled_list.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -28,13 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#pragma once
+#ifndef POOLED_LIST_H
+#define POOLED_LIST_H
+
+#include "core/templates/local_vector.h"
// Simple template to provide a pool with O(1) allocate and free.
// The freelist could alternatively be a linked list placed within the unused elements
// to use less memory, however a separate freelist is probably more cache friendly.
-
-// NOTE : Take great care when using this with non POD types. The construction and destruction
+//
+// NOTE: Take great care when using this with non POD types. The construction and destruction
// is done in the LocalVector, NOT as part of the pool. So requesting a new item does not guarantee
// a constructor is run, and free does not guarantee a destructor.
// You should generally handle clearing
@@ -42,9 +45,6 @@
// This is by design for fastest use in the BVH. If you want a more general pool
// that does call constructors / destructors on request / free, this should probably be
// a separate template.
-
-#include "core/templates/local_vector.h"
-
template <class T, bool force_trivial = false>
class PooledList {
LocalVector<T, uint32_t, force_trivial> list;
@@ -93,3 +93,5 @@ public:
_used_size--;
}
};
+
+#endif // POOLED_LIST_H
diff --git a/core/templates/rid.h b/core/templates/rid.h
index 4c7119b4ea..679c43f906 100644
--- a/core/templates/rid.h
+++ b/core/templates/rid.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/rid_owner.cpp b/core/templates/rid_owner.cpp
index 56f39ab779..7fc819e232 100644
--- a/core/templates/rid_owner.cpp
+++ b/core/templates/rid_owner.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h
index e947d2211c..3ed81e76fd 100644
--- a/core/templates/rid_owner.h
+++ b/core/templates/rid_owner.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -151,7 +151,7 @@ public:
return _allocate_rid();
}
- _FORCE_INLINE_ T *getornull(const RID &p_rid, bool p_initialize = false) {
+ _FORCE_INLINE_ T *get_or_null(const RID &p_rid, bool p_initialize = false) {
if (p_rid == RID()) {
return nullptr;
}
@@ -210,12 +210,12 @@ public:
return ptr;
}
void initialize_rid(RID p_rid) {
- T *mem = getornull(p_rid, true);
+ T *mem = get_or_null(p_rid, true);
ERR_FAIL_COND(!mem);
memnew_placement(mem, T);
}
void initialize_rid(RID p_rid, const T &p_value) {
- T *mem = getornull(p_rid, true);
+ T *mem = get_or_null(p_rid, true);
ERR_FAIL_COND(!mem);
memnew_placement(mem, T(p_value));
}
@@ -399,8 +399,8 @@ public:
alloc.initialize_rid(p_rid, p_ptr);
}
- _FORCE_INLINE_ T *getornull(const RID &p_rid) {
- T **ptr = alloc.getornull(p_rid);
+ _FORCE_INLINE_ T *get_or_null(const RID &p_rid) {
+ T **ptr = alloc.get_or_null(p_rid);
if (unlikely(!ptr)) {
return nullptr;
}
@@ -408,7 +408,7 @@ public:
}
_FORCE_INLINE_ void replace(const RID &p_rid, T *p_new_ptr) {
- T **ptr = alloc.getornull(p_rid);
+ T **ptr = alloc.get_or_null(p_rid);
ERR_FAIL_COND(!ptr);
*ptr = p_new_ptr;
}
@@ -469,8 +469,8 @@ public:
alloc.initialize_rid(p_rid, p_ptr);
}
- _FORCE_INLINE_ T *getornull(const RID &p_rid) {
- return alloc.getornull(p_rid);
+ _FORCE_INLINE_ T *get_or_null(const RID &p_rid) {
+ return alloc.get_or_null(p_rid);
}
_FORCE_INLINE_ bool owns(const RID &p_rid) {
diff --git a/core/templates/ring_buffer.h b/core/templates/ring_buffer.h
index e7b77440f1..742f9462fb 100644
--- a/core/templates/ring_buffer.h
+++ b/core/templates/ring_buffer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/safe_list.h b/core/templates/safe_list.h
index d8f010663b..53fc3fe5f9 100644
--- a/core/templates/safe_list.h
+++ b/core/templates/safe_list.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/safe_refcount.h b/core/templates/safe_refcount.h
index e9e5695f80..76f76be96a 100644
--- a/core/templates/safe_refcount.h
+++ b/core/templates/safe_refcount.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/search_array.h b/core/templates/search_array.h
new file mode 100644
index 0000000000..e717a352d1
--- /dev/null
+++ b/core/templates/search_array.h
@@ -0,0 +1,67 @@
+/*************************************************************************/
+/* search_array.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SEARCH_ARRAY_H
+#define SEARCH_ARRAY_H
+
+#include <core/templates/sort_array.h>
+
+template <class T, class Comparator = _DefaultComparator<T>>
+class SearchArray {
+public:
+ Comparator compare;
+
+ inline int bisect(const T *p_array, int p_len, const T &p_value, bool p_before) const {
+ int lo = 0;
+ int hi = p_len;
+ if (p_before) {
+ while (lo < hi) {
+ const int mid = (lo + hi) / 2;
+ if (compare(p_array[mid], p_value)) {
+ lo = mid + 1;
+ } else {
+ hi = mid;
+ }
+ }
+ } else {
+ while (lo < hi) {
+ const int mid = (lo + hi) / 2;
+ if (compare(p_value, p_array[mid])) {
+ hi = mid;
+ } else {
+ lo = mid + 1;
+ }
+ }
+ }
+ return lo;
+ }
+};
+
+#endif // SEARCH_ARRAY_H
diff --git a/core/templates/self_list.h b/core/templates/self_list.h
index e8d36ea358..7f2236fa3a 100644
--- a/core/templates/self_list.h
+++ b/core/templates/self_list.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/set.h b/core/templates/set.h
index 0a80ceefb5..cdc6e8447d 100644
--- a/core/templates/set.h
+++ b/core/templates/set.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -582,6 +582,9 @@ public:
}
Element *lower_bound(const T &p_value) const {
+ if (!_data._root) {
+ return nullptr;
+ }
return _lower_bound(p_value);
}
diff --git a/core/templates/simple_type.h b/core/templates/simple_type.h
index 80bfa83fde..9352b500a2 100644
--- a/core/templates/simple_type.h
+++ b/core/templates/simple_type.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/sort_array.h b/core/templates/sort_array.h
index 1656d2991d..6cf9368056 100644
--- a/core/templates/sort_array.h
+++ b/core/templates/sort_array.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/templates/thread_work_pool.cpp b/core/templates/thread_work_pool.cpp
index 17969a2c90..a75fd06b9b 100644
--- a/core/templates/thread_work_pool.cpp
+++ b/core/templates/thread_work_pool.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -47,7 +47,7 @@ void ThreadWorkPool::_thread_function(void *p_user) {
void ThreadWorkPool::init(int p_thread_count) {
ERR_FAIL_COND(threads != nullptr);
if (p_thread_count < 0) {
- p_thread_count = OS::get_singleton()->get_processor_count();
+ p_thread_count = OS::get_singleton()->get_default_thread_pool_size();
}
thread_count = p_thread_count;
diff --git a/core/templates/thread_work_pool.h b/core/templates/thread_work_pool.h
index b242648bc8..957af44f48 100644
--- a/core/templates/thread_work_pool.h
+++ b/core/templates/thread_work_pool.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -73,6 +73,7 @@ class ThreadWorkPool {
ThreadData *threads = nullptr;
uint32_t thread_count = 0;
+ uint32_t threads_working = 0;
BaseWork *current_work = nullptr;
static void _thread_function(void *p_user);
@@ -94,7 +95,9 @@ public:
current_work = w;
- for (uint32_t i = 0; i < thread_count; i++) {
+ threads_working = MIN(p_elements, thread_count);
+
+ for (uint32_t i = 0; i < threads_working; i++) {
threads[i].work = w;
threads[i].start.post();
}
@@ -117,19 +120,32 @@ public:
void end_work() {
ERR_FAIL_COND(current_work == nullptr);
- for (uint32_t i = 0; i < thread_count; i++) {
+ for (uint32_t i = 0; i < threads_working; i++) {
threads[i].completed.wait();
threads[i].work = nullptr;
}
+ threads_working = 0;
memdelete(current_work);
current_work = nullptr;
}
template <class C, class M, class U>
void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
- begin_work(p_elements, p_instance, p_method, p_userdata);
- end_work();
+ switch (p_elements) {
+ case 0:
+ // Nothing to do, so do nothing.
+ break;
+ case 1:
+ // No value in pushing the work to another thread if it's a single job
+ // and we're going to wait for it to finish. Just run it right here.
+ (p_instance->*p_method)(0, p_userdata);
+ break;
+ default:
+ // Multiple jobs to do; commence threaded business.
+ begin_work(p_elements, p_instance, p_method, p_userdata);
+ end_work();
+ }
}
_FORCE_INLINE_ int get_thread_count() const { return thread_count; }
diff --git a/core/templates/vector.h b/core/templates/vector.h
index 2600604eb7..e53c502f67 100644
--- a/core/templates/vector.h
+++ b/core/templates/vector.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,15 +33,17 @@
/**
* @class Vector
- * @author Juan Linietsky
* Vector container. Regular Vector Container. Use with care and for smaller arrays when possible. Use Vector for large arrays.
-*/
+ */
#include "core/error/error_macros.h"
#include "core/os/memory.h"
#include "core/templates/cowdata.h"
+#include "core/templates/search_array.h"
#include "core/templates/sort_array.h"
+#include <initializer_list>
+
template <class T>
class VectorWriteProxy {
public:
@@ -67,11 +69,11 @@ public:
_FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } //alias
void fill(T p_elem);
- void remove(int p_index) { _cowdata.remove(p_index); }
+ void remove_at(int p_index) { _cowdata.remove_at(p_index); }
void erase(const T &p_val) {
int idx = find(p_val);
if (idx >= 0) {
- remove(idx);
+ remove_at(idx);
}
}
void reverse();
@@ -112,6 +114,11 @@ public:
sort_custom<_DefaultComparator<T>>();
}
+ int bsearch(const T &p_value, bool p_before) {
+ SearchArray<T> search;
+ return search.bisect(ptrw(), size(), p_value, p_before);
+ }
+
Vector<T> duplicate() {
return *this;
}
@@ -126,9 +133,8 @@ public:
insert(i, p_val);
}
- inline Vector &operator=(const Vector &p_from) {
+ inline void operator=(const Vector &p_from) {
_cowdata._ref(p_from._cowdata);
- return *this;
}
Vector<uint8_t> to_byte_array() const {
@@ -138,27 +144,28 @@ public:
return ret;
}
- Vector<T> subarray(int p_from, int p_to) const {
- if (p_from < 0) {
- p_from = size() + p_from;
- }
- if (p_to < 0) {
- p_to = size() + p_to;
+ Vector<T> slice(int p_begin, int p_end) const {
+ Vector<T> result;
+
+ if (p_end < 0) {
+ p_end += size() + 1;
}
- ERR_FAIL_INDEX_V(p_from, size(), Vector<T>());
- ERR_FAIL_INDEX_V(p_to, size(), Vector<T>());
+ ERR_FAIL_INDEX_V(p_begin, size(), result);
+ ERR_FAIL_INDEX_V(p_end, size() + 1, result);
- Vector<T> slice;
- int span = 1 + p_to - p_from;
- slice.resize(span);
- const T *r = ptr();
- T *w = slice.ptrw();
- for (int i = 0; i < span; ++i) {
- w[i] = r[p_from + i];
+ ERR_FAIL_COND_V(p_begin > p_end, result);
+
+ int result_size = p_end - p_begin;
+ result.resize(result_size);
+
+ const T *const r = ptr();
+ T *const w = result.ptrw();
+ for (int i = 0; i < result_size; ++i) {
+ w[i] = r[p_begin + i];
}
- return slice;
+ return result;
}
bool operator==(const Vector<T> &p_arr) const {
@@ -252,6 +259,15 @@ public:
}
_FORCE_INLINE_ Vector() {}
+ _FORCE_INLINE_ Vector(std::initializer_list<T> p_init) {
+ Error err = _cowdata.resize(p_init.size());
+ ERR_FAIL_COND(err);
+
+ int i = 0;
+ for (const T &element : p_init) {
+ _cowdata.set(i++, element);
+ }
+ }
_FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); }
_FORCE_INLINE_ ~Vector() {}
diff --git a/core/templates/vmap.h b/core/templates/vmap.h
index 520e0b3720..013c4e4262 100644
--- a/core/templates/vmap.h
+++ b/core/templates/vmap.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -134,7 +134,7 @@ public:
if (pos < 0) {
return;
}
- _cowdata.remove(pos);
+ _cowdata.remove_at(pos);
}
int find(const T &p_val) const {
@@ -193,9 +193,8 @@ public:
_FORCE_INLINE_ VMap() {}
_FORCE_INLINE_ VMap(const VMap &p_from) { _cowdata._ref(p_from._cowdata); }
- inline VMap &operator=(const VMap &p_from) {
+ inline void operator=(const VMap &p_from) {
_cowdata._ref(p_from._cowdata);
- return *this;
}
};
diff --git a/core/templates/vset.h b/core/templates/vset.h
index 6665651d42..09bddbbe69 100644
--- a/core/templates/vset.h
+++ b/core/templates/vset.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -119,7 +119,7 @@ public:
if (pos < 0) {
return;
}
- _data.remove(pos);
+ _data.remove_at(pos);
}
int find(const T &p_val) const {
diff --git a/core/typedefs.h b/core/typedefs.h
index dde254af23..e6034eb375 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -62,9 +62,9 @@
#endif
#endif
-// Should always inline, except in debug builds because it makes debugging harder.
+// Should always inline, except in dev builds because it makes debugging harder.
#ifndef _FORCE_INLINE_
-#ifdef DISABLE_FORCED_INLINE
+#ifdef DEV_ENABLED
#define _FORCE_INLINE_ inline
#else
#define _FORCE_INLINE_ _ALWAYS_INLINE_
@@ -91,8 +91,8 @@
#define ABS(m_v) (((m_v) < 0) ? (-(m_v)) : (m_v))
#endif
-#ifndef SGN
-#define SGN(m_v) (((m_v) == 0) ? (0.0) : (((m_v) < 0) ? (-1.0) : (+1.0)))
+#ifndef SIGN
+#define SIGN(m_v) (((m_v) == 0) ? (0.0) : (((m_v) < 0) ? (-1.0) : (+1.0)))
#endif
#ifndef MIN
@@ -277,6 +277,9 @@ struct BuildIndexSequence : BuildIndexSequence<N - 1, N - 1, Is...> {};
template <size_t... Is>
struct BuildIndexSequence<0, Is...> : IndexSequence<Is...> {};
+// Limit the depth of recursive algorithms when dealing with Array/Dictionary
+#define MAX_RECURSION 100
+
#ifdef DEBUG_ENABLED
#define DEBUG_METHODS_ENABLED
#endif
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 8373cbd4e8..8d20b1bc79 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,6 +34,7 @@
#include "core/object/class_db.h"
#include "core/object/script_language.h"
#include "core/templates/hashfuncs.h"
+#include "core/templates/search_array.h"
#include "core/templates/vector.h"
#include "core/variant/callable.h"
#include "core/variant/variant.h"
@@ -96,11 +97,38 @@ void Array::clear() {
}
bool Array::operator==(const Array &p_array) const {
- return _p == p_array._p;
+ return recursive_equal(p_array, 0);
}
bool Array::operator!=(const Array &p_array) const {
- return !operator==(p_array);
+ return !recursive_equal(p_array, 0);
+}
+
+bool Array::recursive_equal(const Array &p_array, int recursion_count) const {
+ // Cheap checks
+ if (_p == p_array._p) {
+ return true;
+ }
+ const Vector<Variant> &a1 = _p->array;
+ const Vector<Variant> &a2 = p_array._p->array;
+ const int size = a1.size();
+ if (size != a2.size()) {
+ return false;
+ }
+
+ // Heavy O(n) check
+ if (recursion_count > MAX_RECURSION) {
+ ERR_PRINT("Max recursion reached");
+ return true;
+ }
+ recursion_count++;
+ for (int i = 0; i < size; i++) {
+ if (!a1[i].hash_compare(a2[i], recursion_count)) {
+ return false;
+ }
+ }
+
+ return true;
}
bool Array::operator<(const Array &p_array) const {
@@ -131,10 +159,20 @@ bool Array::operator>=(const Array &p_array) const {
}
uint32_t Array::hash() const {
- uint32_t h = hash_djb2_one_32(0);
+ return recursive_hash(0);
+}
+uint32_t Array::recursive_hash(int recursion_count) const {
+ if (recursion_count > MAX_RECURSION) {
+ ERR_PRINT("Max recursion reached");
+ return 0;
+ }
+
+ uint32_t h = hash_djb2_one_32(Variant::ARRAY);
+
+ recursion_count++;
for (int i = 0; i < _p->array.size(); i++) {
- h = hash_djb2_one_32(_p->array[i].hash(), h);
+ h = hash_djb2_one_32(_p->array[i].recursive_hash(recursion_count), h);
}
return h;
}
@@ -284,8 +322,8 @@ bool Array::has(const Variant &p_value) const {
return _p->array.find(p_value, 0) != -1;
}
-void Array::remove(int p_pos) {
- _p->array.remove(p_pos);
+void Array::remove_at(int p_pos) {
+ _p->array.remove_at(p_pos);
}
void Array::set(int p_idx, const Variant &p_value) {
@@ -299,66 +337,58 @@ const Variant &Array::get(int p_idx) const {
}
Array Array::duplicate(bool p_deep) const {
+ return recursive_duplicate(p_deep, 0);
+}
+
+Array Array::recursive_duplicate(bool p_deep, int recursion_count) const {
Array new_arr;
+
+ 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;
- for (int i = 0; i < element_count; i++) {
- new_arr[i] = p_deep ? get(i).duplicate(p_deep) : get(i);
+ if (p_deep) {
+ recursion_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);
+ }
}
return new_arr;
}
-int Array::_clamp_slice_index(int p_index) const {
- int arr_size = size();
- int fixed_index = CLAMP(p_index, -arr_size, arr_size - 1);
- if (fixed_index < 0) {
- fixed_index = arr_size + fixed_index;
- }
- return fixed_index;
-}
-
-Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const { // like python, but inclusive on upper bound
-
- Array new_arr;
+Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const {
+ Array result;
- ERR_FAIL_COND_V_MSG(p_step == 0, new_arr, "Array slice step size cannot be zero.");
+ ERR_FAIL_COND_V_MSG(p_step == 0, result, "Slice step cannot be zero.");
- if (is_empty()) { // Don't try to slice empty arrays.
- return new_arr;
- }
- if (p_step > 0) {
- if (p_begin >= size() || p_end < -size()) {
- return new_arr;
- }
- } else { // p_step < 0
- if (p_begin < -size() || p_end >= size()) {
- return new_arr;
- }
+ if (p_end < 0) {
+ p_end += size() + 1;
}
- int begin = _clamp_slice_index(p_begin);
- int end = _clamp_slice_index(p_end);
+ ERR_FAIL_INDEX_V(p_begin, size(), result);
+ ERR_FAIL_INDEX_V(p_end, size() + 1, result);
- int new_arr_size = MAX(((end - begin + p_step) / p_step), 0);
- new_arr.resize(new_arr_size);
+ ERR_FAIL_COND_V_MSG(p_step > 0 && p_begin > p_end, result, "Slice is positive, but bounds is decreasing");
+ ERR_FAIL_COND_V_MSG(p_step < 0 && p_begin < p_end, result, "Slice is negative, but bounds is increasing");
- if (p_step > 0) {
- int dest_idx = 0;
- for (int idx = begin; idx <= end; idx += p_step) {
- ERR_FAIL_COND_V_MSG(dest_idx < 0 || dest_idx >= new_arr_size, Array(), "Bug in Array slice()");
- new_arr[dest_idx++] = p_deep ? get(idx).duplicate(p_deep) : get(idx);
- }
- } else { // p_step < 0
- int dest_idx = 0;
- for (int idx = begin; idx >= end; idx += p_step) {
- ERR_FAIL_COND_V_MSG(dest_idx < 0 || dest_idx >= new_arr_size, Array(), "Bug in Array slice()");
- new_arr[dest_idx++] = p_deep ? get(idx).duplicate(p_deep) : get(idx);
- }
+ int result_size = (p_end - p_begin) / p_step;
+ result.resize(result_size);
+
+ for (int src_idx = p_begin, dest_idx = 0; dest_idx < result_size; ++dest_idx) {
+ result[dest_idx] = p_deep ? get(src_idx).duplicate(true) : get(src_idx);
+ src_idx += p_step;
}
- return new_arr;
+ return result;
}
Array Array::filter(const Callable &p_callable) const {
@@ -484,44 +514,19 @@ void Array::shuffle() {
}
}
-template <typename Less>
-_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {
- int lo = 0;
- int hi = p_array.size();
- if (p_before) {
- while (lo < hi) {
- const int mid = (lo + hi) / 2;
- if (p_less(p_array.get(mid), p_value)) {
- lo = mid + 1;
- } else {
- hi = mid;
- }
- }
- } else {
- while (lo < hi) {
- const int mid = (lo + hi) / 2;
- if (p_less(p_value, p_array.get(mid))) {
- hi = mid;
- } else {
- lo = mid + 1;
- }
- }
- }
- return lo;
-}
-
int Array::bsearch(const Variant &p_value, bool p_before) {
ERR_FAIL_COND_V(!_p->typed.validate(p_value, "binary search"), -1);
- return bisect(_p->array, p_value, p_before, _ArrayVariantSort());
+ SearchArray<Variant, _ArrayVariantSort> avs;
+ return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before);
}
int Array::bsearch_custom(const Variant &p_value, Callable p_callable, bool p_before) {
ERR_FAIL_COND_V(!_p->typed.validate(p_value, "custom binary search"), -1);
- _ArrayVariantSortCustom less;
- less.func = p_callable;
+ SearchArray<Variant, _ArrayVariantSortCustom> avs;
+ avs.compare.func = p_callable;
- return bisect(_p->array, p_value, p_before, less);
+ return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before);
}
void Array::reverse() {
@@ -546,7 +551,7 @@ Variant Array::pop_back() {
Variant Array::pop_front() {
if (!_p->array.is_empty()) {
const Variant ret = _p->array.get(0);
- _p->array.remove(0);
+ _p->array.remove_at(0);
return ret;
}
return Variant();
@@ -573,7 +578,7 @@ Variant Array::pop_at(int p_pos) {
_p->array.size()));
const Variant ret = _p->array.get(p_pos);
- _p->array.remove(p_pos);
+ _p->array.remove_at(p_pos);
return ret;
}
diff --git a/core/variant/array.h b/core/variant/array.h
index 4a1b25c4a9..f48444bb39 100644
--- a/core/variant/array.h
+++ b/core/variant/array.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -44,8 +44,6 @@ class Array {
void _ref(const Array &p_from) const;
void _unref() const;
- inline int _clamp_slice_index(int p_index) const;
-
protected:
Array(const Array &p_base, uint32_t p_type, const StringName &p_class_name, const Variant &p_script);
bool _assign(const Array &p_array);
@@ -63,8 +61,10 @@ public:
bool operator==(const Array &p_array) const;
bool operator!=(const Array &p_array) const;
+ bool recursive_equal(const Array &p_array, int recursion_count) const;
uint32_t hash() const;
+ uint32_t recursive_hash(int recursion_count) const;
void operator=(const Array &p_array);
void push_back(const Variant &p_value);
@@ -73,7 +73,7 @@ public:
Error resize(int p_new_size);
Error insert(int p_pos, const Variant &p_value);
- void remove(int p_pos);
+ void remove_at(int p_pos);
void fill(const Variant &p_value);
Variant front() const;
@@ -100,6 +100,7 @@ public:
Variant pop_at(int p_pos);
Array duplicate(bool p_deep = false) const;
+ Array recursive_duplicate(bool p_deep, int recursion_count) const;
Array slice(int p_begin, int p_end, int p_step = 1, bool p_deep = false) const;
Array filter(const Callable &p_callable) const;
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 3b2c837096..14f49d530c 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -80,14 +80,18 @@ struct VariantCaster<const T &> {
} \
typedef int64_t EncodeT; \
_FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \
- *(int64_t *)p_ptr = p_val; \
+ *(int64_t *)p_ptr = (int64_t)p_val; \
} \
};
// Object enum casts must go here
VARIANT_ENUM_CAST(Object::ConnectFlags);
+VARIANT_ENUM_CAST(Vector2::Axis);
+VARIANT_ENUM_CAST(Vector2i::Axis);
VARIANT_ENUM_CAST(Vector3::Axis);
+VARIANT_ENUM_CAST(Vector3i::Axis);
+VARIANT_ENUM_CAST(Basis::EulerOrder);
VARIANT_ENUM_CAST(Error);
VARIANT_ENUM_CAST(Side);
@@ -102,9 +106,9 @@ VARIANT_ENUM_CAST(KeyModifierMask);
VARIANT_ENUM_CAST(MIDIMessage);
VARIANT_ENUM_CAST(MouseButton);
VARIANT_ENUM_CAST(Orientation);
-VARIANT_ENUM_CAST(HAlign);
-VARIANT_ENUM_CAST(VAlign);
-VARIANT_ENUM_CAST(InlineAlign);
+VARIANT_ENUM_CAST(HorizontalAlignment);
+VARIANT_ENUM_CAST(VerticalAlignment);
+VARIANT_ENUM_CAST(InlineAlignment);
VARIANT_ENUM_CAST(PropertyHint);
VARIANT_ENUM_CAST(PropertyUsageFlags);
VARIANT_ENUM_CAST(Variant::Type);
@@ -563,13 +567,11 @@ void call_with_validated_variant_args_static_method_ret(R (*p_method)(P...), con
// GCC raises "parameter 'p_args' set but not used" when P = {},
// it's not clever enough to treat other P values as making this branch valid.
-#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
+#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#endif
-#ifdef DEBUG_METHODS_ENABLED
-
template <class Q>
void call_get_argument_type_helper(int p_arg, int &index, Variant::Type &type) {
if (p_arg == index) {
@@ -608,6 +610,7 @@ void call_get_argument_type_info(int p_arg, PropertyInfo &info) {
(void)index; // Suppress GCC warning.
}
+#ifdef DEBUG_METHODS_ENABLED
template <class Q>
void call_get_argument_metadata_helper(int p_arg, int &index, GodotTypeInfo::Metadata &md) {
if (p_arg == index) {
@@ -629,13 +632,6 @@ GodotTypeInfo::Metadata call_get_argument_metadata(int p_arg) {
return md;
}
-#else
-
-template <class... P>
-Variant::Type call_get_argument_type(int p_arg) {
- return Variant::NIL;
-}
-
#endif // DEBUG_METHODS_ENABLED
//////////////////////
@@ -915,7 +911,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const Variant **p_
call_with_variant_args_static(p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
-#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
+#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index f487e718f4..c6a67f01d5 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -377,11 +377,11 @@ Error Signal::emit(const Variant **p_arguments, int p_argcount) const {
return obj->emit_signal(name, p_arguments, p_argcount);
}
-Error Signal::connect(const Callable &p_callable, const Vector<Variant> &p_binds, uint32_t p_flags) {
+Error Signal::connect(const Callable &p_callable, uint32_t p_flags) {
Object *object = get_object();
ERR_FAIL_COND_V(!object, ERR_UNCONFIGURED);
- return object->connect(name, p_callable, p_binds, p_flags);
+ return object->connect(name, p_callable, varray(), p_flags);
}
void Signal::disconnect(const Callable &p_callable) {
diff --git a/core/variant/callable.h b/core/variant/callable.h
index 52094af3aa..855ffa9129 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -159,7 +159,7 @@ public:
operator String() const;
Error emit(const Variant **p_arguments, int p_argcount) const;
- Error connect(const Callable &p_callable, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0);
+ Error connect(const Callable &p_callable, uint32_t p_flags = 0);
void disconnect(const Callable &p_callable);
bool is_connected(const Callable &p_callable) const;
diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp
index 56eda6e703..4579621760 100644
--- a/core/variant/callable_bind.cpp
+++ b/core/variant/callable_bind.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/variant/callable_bind.h b/core/variant/callable_bind.h
index feb40d1de9..ac5797e05f 100644
--- a/core/variant/callable_bind.h
+++ b/core/variant/callable_bind.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -51,6 +51,9 @@ public:
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const;
virtual const Callable *get_base_comparator() const;
+ Callable get_callable() { return callable; }
+ Vector<Variant> get_binds() { return binds; }
+
CallableCustomBind(const Callable &p_callable, const Vector<Variant> &p_binds);
virtual ~CallableCustomBind();
};
@@ -72,6 +75,9 @@ public:
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const;
virtual const Callable *get_base_comparator() const;
+ Callable get_callable() { return callable; }
+ int get_unbinds() { return argcount; }
+
CallableCustomUnbind(const Callable &p_callable, int p_argcount);
virtual ~CallableCustomUnbind();
};
diff --git a/core/variant/container_type_validate.h b/core/variant/container_type_validate.h
index f13a37cddd..6171c8c88f 100644
--- a/core/variant/container_type_validate.h
+++ b/core/variant/container_type_validate.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp
index 07b3a9a675..cc04ae712b 100644
--- a/core/variant/dictionary.cpp
+++ b/core/variant/dictionary.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -188,11 +188,35 @@ bool Dictionary::erase(const Variant &p_key) {
}
bool Dictionary::operator==(const Dictionary &p_dictionary) const {
- return _p == p_dictionary._p;
+ return recursive_equal(p_dictionary, 0);
}
bool Dictionary::operator!=(const Dictionary &p_dictionary) const {
- return _p != p_dictionary._p;
+ return !recursive_equal(p_dictionary, 0);
+}
+
+bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_count) const {
+ // Cheap checks
+ if (_p == p_dictionary._p) {
+ return true;
+ }
+ if (_p->variant_map.size() != p_dictionary._p->variant_map.size()) {
+ return false;
+ }
+
+ // Heavy O(n) check
+ if (recursion_count > MAX_RECURSION) {
+ ERR_PRINT("Max recursion reached");
+ return true;
+ }
+ recursion_count++;
+ for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement this_E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->front(); this_E; this_E = this_E.next()) {
+ OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement other_E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&p_dictionary._p->variant_map)->find(this_E.key());
+ if (!other_E || !this_E.value().hash_compare(other_E.value(), recursion_count)) {
+ return false;
+ }
+ }
+ return true;
}
void Dictionary::_ref(const Dictionary &p_from) const {
@@ -225,11 +249,21 @@ void Dictionary::_unref() const {
}
uint32_t Dictionary::hash() const {
+ return recursive_hash(0);
+}
+
+uint32_t Dictionary::recursive_hash(int recursion_count) const {
+ if (recursion_count > MAX_RECURSION) {
+ ERR_PRINT("Max recursion reached");
+ return 0;
+ }
+
uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);
+ recursion_count++;
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- h = hash_djb2_one_32(E.key().hash(), h);
- h = hash_djb2_one_32(E.value().hash(), h);
+ h = hash_djb2_one_32(E.key().recursive_hash(recursion_count), h);
+ h = hash_djb2_one_32(E.value().recursive_hash(recursion_count), h);
}
return h;
@@ -286,10 +320,26 @@ const Variant *Dictionary::next(const Variant *p_key) const {
}
Dictionary Dictionary::duplicate(bool p_deep) const {
+ return recursive_duplicate(p_deep, 0);
+}
+
+Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) const {
Dictionary n;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- n[E.key()] = p_deep ? E.value().duplicate(true) : E.value();
+ if (recursion_count > MAX_RECURSION) {
+ ERR_PRINT("Max recursion reached");
+ return n;
+ }
+
+ if (p_deep) {
+ recursion_count++;
+ for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
+ n[E.key().recursive_duplicate(true, recursion_count)] = E.value().recursive_duplicate(true, recursion_count);
+ }
+ } else {
+ for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
+ n[E.key()] = E.value();
+ }
}
return n;
diff --git a/core/variant/dictionary.h b/core/variant/dictionary.h
index 4067ff9fd9..16cf0c2bf8 100644
--- a/core/variant/dictionary.h
+++ b/core/variant/dictionary.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -70,8 +70,10 @@ public:
bool operator==(const Dictionary &p_dictionary) const;
bool operator!=(const Dictionary &p_dictionary) const;
+ bool recursive_equal(const Dictionary &p_dictionary, int recursion_count) const;
uint32_t hash() const;
+ uint32_t recursive_hash(int recursion_count) const;
void operator=(const Dictionary &p_dictionary);
const Variant *next(const Variant *p_key = nullptr) const;
@@ -80,6 +82,7 @@ public:
Array values() const;
Dictionary duplicate(bool p_deep = false) const;
+ Dictionary recursive_duplicate(bool p_deep, int recursion_count) const;
const void *id() const;
diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h
index 98304621f2..75a93ac4c8 100644
--- a/core/variant/method_ptrcall.h
+++ b/core/variant/method_ptrcall.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/variant/native_ptr.h b/core/variant/native_ptr.h
index b4ec0df7d6..fe541c8d4b 100644
--- a/core/variant/native_ptr.h
+++ b/core/variant/native_ptr.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -55,7 +55,7 @@ struct GDNativePtr {
#define GDVIRTUAL_NATIVE_PTR(m_type) \
template <> \
- struct GDNativeConstPtr<m_type> { \
+ struct GDNativeConstPtr<const m_type> { \
const m_type *data = nullptr; \
GDNativeConstPtr(const m_type *p_assign) { data = p_assign; } \
static const char *get_name() { return "const " #m_type; } \
@@ -117,6 +117,7 @@ GDVIRTUAL_NATIVE_PTR(char16_t)
GDVIRTUAL_NATIVE_PTR(char32_t)
GDVIRTUAL_NATIVE_PTR(wchar_t)
GDVIRTUAL_NATIVE_PTR(uint8_t)
+GDVIRTUAL_NATIVE_PTR(uint8_t *)
GDVIRTUAL_NATIVE_PTR(int8_t)
GDVIRTUAL_NATIVE_PTR(uint16_t)
GDVIRTUAL_NATIVE_PTR(int16_t)
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index b70d29bbac..5ae35c92d3 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -60,7 +60,7 @@ struct TypeInherits {
static char (&test(...))[2];
static bool const value = sizeof(test(get_d())) == sizeof(char) &&
- !TypesAreSame<B volatile const, void volatile const>::value;
+ !TypesAreSame<B volatile const, void volatile const>::value;
};
namespace GodotTypeInfo {
diff --git a/core/variant/typed_array.h b/core/variant/typed_array.h
index 2e96f4e445..50411121bc 100644
--- a/core/variant/typed_array.h
+++ b/core/variant/typed_array.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 0dbeb6e4cb..db198da54a 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -313,7 +313,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
case BASIS: {
static const Type valid[] = {
QUATERNION,
- VECTOR3,
NIL
};
@@ -620,7 +619,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
case BASIS: {
static const Type valid[] = {
QUATERNION,
- VECTOR3,
NIL
};
@@ -786,16 +784,11 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
}
bool Variant::operator==(const Variant &p_variant) const {
- if (type != p_variant.type) { //evaluation of operator== needs to be more strict
- return false;
- }
- bool v;
- Variant r;
- evaluate(OP_EQUAL, *this, p_variant, r, v);
- return r;
+ return hash_compare(p_variant);
}
bool Variant::operator!=(const Variant &p_variant) const {
+ // Don't use `!hash_compare(p_variant)` given it makes use of OP_EQUAL
if (type != p_variant.type) { //evaluation of operator== needs to be more strict
return true;
}
@@ -1619,12 +1612,23 @@ struct _VariantStrPair {
};
Variant::operator String() const {
- List<const void *> stack;
+ return stringify(0);
+}
- return stringify(stack);
+template <class T>
+String stringify_vector(const T &vec, int recursion_count) {
+ String str("[");
+ for (int i = 0; i < vec.size(); i++) {
+ if (i > 0) {
+ str += ", ";
+ }
+ str = str + Variant(vec[i]).stringify(recursion_count);
+ }
+ str += "]";
+ return str;
}
-String Variant::stringify(List<const void *> &stack) const {
+String Variant::stringify(int recursion_count) const {
switch (type) {
case NIL:
return "null";
@@ -1668,23 +1672,22 @@ String Variant::stringify(List<const void *> &stack) const {
return operator Color();
case DICTIONARY: {
const Dictionary &d = *reinterpret_cast<const Dictionary *>(_data._mem);
- if (stack.find(d.id())) {
+ if (recursion_count > MAX_RECURSION) {
+ ERR_PRINT("Max recursion reached");
return "{...}";
}
- stack.push_back(d.id());
-
- //const String *K=nullptr;
String str("{");
List<Variant> keys;
d.get_key_list(&keys);
Vector<_VariantStrPair> pairs;
- for (const Variant &E : keys) {
+ recursion_count++;
+ for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
_VariantStrPair sp;
- sp.key = E.stringify(stack);
- sp.value = d[E].stringify(stack);
+ sp.key = E->get().stringify(recursion_count);
+ sp.value = d[E->get()].stringify(recursion_count);
pairs.push_back(sp);
}
@@ -1699,111 +1702,43 @@ String Variant::stringify(List<const void *> &stack) const {
}
str += "}";
- stack.erase(d.id());
return str;
} break;
case PACKED_VECTOR2_ARRAY: {
- Vector<Vector2> vec = operator Vector<Vector2>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + Variant(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<Vector2>(), recursion_count);
} break;
case PACKED_VECTOR3_ARRAY: {
- Vector<Vector3> vec = operator Vector<Vector3>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + Variant(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<Vector3>(), recursion_count);
+ } break;
+ case PACKED_COLOR_ARRAY: {
+ return stringify_vector(operator Vector<Color>(), recursion_count);
} break;
case PACKED_STRING_ARRAY: {
- Vector<String> vec = operator Vector<String>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + vec[i];
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<String>(), recursion_count);
+ } break;
+ case PACKED_BYTE_ARRAY: {
+ return stringify_vector(operator Vector<uint8_t>(), recursion_count);
} break;
case PACKED_INT32_ARRAY: {
- Vector<int32_t> vec = operator Vector<int32_t>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + itos(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<int32_t>(), recursion_count);
} break;
case PACKED_INT64_ARRAY: {
- Vector<int64_t> vec = operator Vector<int64_t>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + itos(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<int64_t>(), recursion_count);
} break;
case PACKED_FLOAT32_ARRAY: {
- Vector<float> vec = operator Vector<float>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + rtos(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<float>(), recursion_count);
} break;
case PACKED_FLOAT64_ARRAY: {
- Vector<double> vec = operator Vector<double>();
- String str("[");
- for (int i = 0; i < vec.size(); i++) {
- if (i > 0) {
- str += ", ";
- }
- str = str + rtos(vec[i]);
- }
- str += "]";
- return str;
+ return stringify_vector(operator Vector<double>(), recursion_count);
} break;
case ARRAY: {
Array arr = operator Array();
- if (stack.find(arr.id())) {
+ if (recursion_count > MAX_RECURSION) {
+ ERR_PRINT("Max recursion reached");
return "[...]";
}
- stack.push_back(arr.id());
-
- String str("[");
- for (int i = 0; i < arr.size(); i++) {
- if (i) {
- str += ", ";
- }
-
- str += arr[i].stringify(stack);
- }
- str += "]";
- stack.erase(arr.id());
+ String str = stringify_vector(arr, recursion_count);
return str;
} break;
@@ -1941,8 +1876,6 @@ Variant::operator Basis() const {
return *_data._basis;
} else if (type == QUATERNION) {
return *reinterpret_cast<const Quaternion *>(_data._mem);
- } else if (type == VECTOR3) {
- return Basis(*reinterpret_cast<const Vector3 *>(_data._mem));
} else if (type == TRANSFORM3D) { // unexposed in Variant::can_convert?
return _data._transform3d->basis;
} else {
@@ -2824,6 +2757,10 @@ Variant::Variant(const Variant &p_variant) {
}
uint32_t Variant::hash() const {
+ return recursive_hash(0);
+}
+
+uint32_t Variant::recursive_hash(int recursion_count) const {
switch (type) {
case NIL: {
return 0;
@@ -2951,7 +2888,7 @@ uint32_t Variant::hash() const {
return reinterpret_cast<const NodePath *>(_data._mem)->hash();
} break;
case DICTIONARY: {
- return reinterpret_cast<const Dictionary *>(_data._mem)->hash();
+ return reinterpret_cast<const Dictionary *>(_data._mem)->recursive_hash(recursion_count);
} break;
case CALLABLE: {
@@ -2965,7 +2902,7 @@ uint32_t Variant::hash() const {
} break;
case ARRAY: {
const Array &arr = *reinterpret_cast<const Array *>(_data._mem);
- return arr.hash();
+ return arr.recursive_hash(recursion_count);
} break;
case PACKED_BYTE_ARRAY: {
@@ -3139,16 +3076,24 @@ uint32_t Variant::hash() const {
\
return true
-bool Variant::hash_compare(const Variant &p_variant) const {
+bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const {
if (type != p_variant.type) {
return false;
}
switch (type) {
+ case INT: {
+ return _data._int == p_variant._data._int;
+ } break;
+
case FLOAT: {
return hash_compare_scalar(_data._float, p_variant._data._float);
} break;
+ case STRING: {
+ return *reinterpret_cast<const String *>(_data._mem) == *reinterpret_cast<const String *>(p_variant._data._mem);
+ } break;
+
case VECTOR2: {
const Vector2 *l = reinterpret_cast<const Vector2 *>(_data._mem);
const Vector2 *r = reinterpret_cast<const Vector2 *>(p_variant._data._mem);
@@ -3166,7 +3111,7 @@ bool Variant::hash_compare(const Variant &p_variant) const {
const Rect2 *r = reinterpret_cast<const Rect2 *>(p_variant._data._mem);
return (hash_compare_vector2(l->position, r->position)) &&
- (hash_compare_vector2(l->size, r->size));
+ (hash_compare_vector2(l->size, r->size));
} break;
case RECT2I: {
const Rect2i *l = reinterpret_cast<const Rect2i *>(_data._mem);
@@ -3206,7 +3151,7 @@ bool Variant::hash_compare(const Variant &p_variant) const {
const Plane *r = reinterpret_cast<const Plane *>(p_variant._data._mem);
return (hash_compare_vector3(l->normal, r->normal)) &&
- (hash_compare_scalar(l->d, r->d));
+ (hash_compare_scalar(l->d, r->d));
} break;
case AABB: {
@@ -3262,14 +3207,19 @@ bool Variant::hash_compare(const Variant &p_variant) const {
const Array &l = *(reinterpret_cast<const Array *>(_data._mem));
const Array &r = *(reinterpret_cast<const Array *>(p_variant._data._mem));
- if (l.size() != r.size()) {
+ if (!l.recursive_equal(r, recursion_count + 1)) {
return false;
}
- for (int i = 0; i < l.size(); ++i) {
- if (!l[i].hash_compare(r[i])) {
- return false;
- }
+ return true;
+ } break;
+
+ case DICTIONARY: {
+ const Dictionary &l = *(reinterpret_cast<const Dictionary *>(_data._mem));
+ const Dictionary &r = *(reinterpret_cast<const Dictionary *>(p_variant._data._mem));
+
+ if (!l.recursive_equal(r, recursion_count + 1)) {
+ return false;
}
return true;
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 9ec131a1b8..0860e7fdc3 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,6 +31,7 @@
#ifndef VARIANT_H
#define VARIANT_H
+#include "core/input/input_enums.h"
#include "core/io/ip_address.h"
#include "core/math/aabb.h"
#include "core/math/basis.h"
@@ -43,6 +44,7 @@
#include "core/math/vector3.h"
#include "core/math/vector3i.h"
#include "core/object/object_id.h"
+#include "core/os/keyboard.h"
#include "core/string/node_path.h"
#include "core/string/ustring.h"
#include "core/templates/rid.h"
@@ -430,6 +432,21 @@ public:
Variant(const IPAddress &p_address);
+#define VARIANT_ENUM_CLASS_CONSTRUCTOR(m_enum) \
+ Variant(const m_enum &p_value) { \
+ type = INT; \
+ _data._int = (int64_t)p_value; \
+ }
+
+ // Only enum classes that need to be bound need this to be defined.
+ VARIANT_ENUM_CLASS_CONSTRUCTOR(JoyAxis)
+ VARIANT_ENUM_CLASS_CONSTRUCTOR(JoyButton)
+ VARIANT_ENUM_CLASS_CONSTRUCTOR(Key)
+ VARIANT_ENUM_CLASS_CONSTRUCTOR(MIDIMessage)
+ VARIANT_ENUM_CLASS_CONSTRUCTOR(MouseButton)
+
+#undef VARIANT_ENUM_CLASS_CONSTRUCTOR
+
// If this changes the table in variant_op must be updated
enum Operator {
//comparison
@@ -481,7 +498,8 @@ public:
static PTROperatorEvaluator get_ptr_operator_evaluator(Operator p_operator, Type p_type_a, Type p_type_b);
void zero();
- Variant duplicate(bool deep = false) const;
+ Variant duplicate(bool p_deep = false) const;
+ Variant recursive_duplicate(bool p_deep, int recursion_count) const;
static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst);
static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst);
@@ -641,6 +659,7 @@ public:
static UtilityFunctionType get_utility_function_type(const StringName &p_name);
+ static MethodInfo get_utility_function_info(const StringName &p_name);
static int get_utility_function_argument_count(const StringName &p_name);
static Variant::Type get_utility_function_argument_type(const StringName &p_name, int p_arg);
static String get_utility_function_argument_name(const StringName &p_name, int p_arg);
@@ -658,10 +677,11 @@ public:
bool operator!=(const Variant &p_variant) const;
bool operator<(const Variant &p_variant) const;
uint32_t hash() const;
+ uint32_t recursive_hash(int recursion_count) const;
- bool hash_compare(const Variant &p_variant) const;
+ bool hash_compare(const Variant &p_variant, int recursion_count = 0) const;
bool booleanize() const;
- String stringify(List<const void *> &stack) const;
+ String stringify(int recursion_count = 0) const;
String to_json_string() const;
void static_assign(const Variant &p_variant);
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 39207df9e7..ecf5009fb6 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -752,8 +752,9 @@ struct _VariantCall {
static PackedInt32Array func_PackedByteArray_decode_s32_array(PackedByteArray *p_instance) {
uint64_t size = p_instance->size();
- const uint8_t *r = p_instance->ptr();
PackedInt32Array dest;
+ ERR_FAIL_COND_V_MSG(size < sizeof(int32_t), dest, "Size didn't match array of size int32_t, maybe you are trying to convert to the wrong type?");
+ const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(int32_t));
memcpy(dest.ptrw(), r, size);
return dest;
@@ -761,8 +762,9 @@ struct _VariantCall {
static PackedInt64Array func_PackedByteArray_decode_s64_array(PackedByteArray *p_instance) {
uint64_t size = p_instance->size();
- const uint8_t *r = p_instance->ptr();
PackedInt64Array dest;
+ ERR_FAIL_COND_V_MSG(size < sizeof(int64_t), dest, "Size didn't match array of size int64_t, maybe you are trying to convert to the wrong type?");
+ const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(int64_t));
memcpy(dest.ptrw(), r, size);
return dest;
@@ -770,8 +772,9 @@ struct _VariantCall {
static PackedFloat32Array func_PackedByteArray_decode_float_array(PackedByteArray *p_instance) {
uint64_t size = p_instance->size();
- const uint8_t *r = p_instance->ptr();
PackedFloat32Array dest;
+ ERR_FAIL_COND_V_MSG(size < sizeof(float), dest, "Size didn't match array of size float, maybe you are trying to convert to the wrong type?");
+ const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(float));
memcpy(dest.ptrw(), r, size);
return dest;
@@ -779,8 +782,9 @@ struct _VariantCall {
static PackedFloat64Array func_PackedByteArray_decode_double_array(PackedByteArray *p_instance) {
uint64_t size = p_instance->size();
- const uint8_t *r = p_instance->ptr();
PackedFloat64Array dest;
+ ERR_FAIL_COND_V_MSG(size < sizeof(double), dest, "Size didn't match array of size double, maybe you are trying to convert to the wrong type?");
+ const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(double));
memcpy(dest.ptrw(), r, size);
return dest;
@@ -1241,8 +1245,8 @@ void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_c
for (List<StringName>::Element *E = cd.value_ordered.front(); E; E = E->next()) {
p_constants->push_back(E->get());
#else
- for (Map<StringName, int>::Element *E = cd.value.front(); E; E = E->next()) {
- p_constants->push_back(E->key());
+ for (const KeyValue<StringName, int> &E : cd.value) {
+ p_constants->push_back(E.key);
#endif
}
@@ -1250,8 +1254,8 @@ void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_c
for (List<StringName>::Element *E = cd.variant_value_ordered.front(); E; E = E->next()) {
p_constants->push_back(E->get());
#else
- for (Map<StringName, Variant>::Element *E = cd.variant_value.front(); E; E = E->next()) {
- p_constants->push_back(E->key());
+ for (const KeyValue<StringName, Variant> &E : cd.variant_value) {
+ p_constants->push_back(E.key);
#endif
}
}
@@ -1366,6 +1370,7 @@ static void _register_variant_builtin_methods() {
bind_method(String, naturalnocasecmp_to, sarray("to"), varray());
bind_method(String, length, sarray(), varray());
bind_method(String, substr, sarray("from", "len"), varray(-1));
+ bind_method(String, get_slice, sarray("delimiter", "slice"), varray());
bind_methodv(String, find, static_cast<int (String::*)(const String &, int) const>(&String::find), sarray("what", "from"), varray(0));
bind_method(String, count, sarray("what", "from", "to"), varray(0, 0));
bind_method(String, countn, sarray("what", "from", "to"), varray(0, 0));
@@ -1406,9 +1411,8 @@ static void _register_variant_builtin_methods() {
bind_method(String, get_basename, sarray(), varray());
bind_method(String, plus_file, sarray("file"), varray());
bind_method(String, unicode_at, sarray("at"), varray());
+ bind_method(String, indent, sarray("prefix"), varray());
bind_method(String, dedent, sarray(), varray());
- // FIXME: String needs to be immutable when binding
- //bind_method(String, erase, sarray("position", "chars"), varray());
bind_method(String, hash, sarray(), varray());
bind_method(String, md5_text, sarray(), varray());
bind_method(String, sha1_text, sarray(), varray());
@@ -1417,8 +1421,6 @@ static void _register_variant_builtin_methods() {
bind_method(String, sha1_buffer, sarray(), varray());
bind_method(String, sha256_buffer, sarray(), varray());
bind_method(String, is_empty, sarray(), varray());
- // FIXME: Static function, not sure how to bind
- //bind_method(String, humanize_size, sarray("size"), varray());
bind_method(String, is_absolute_path, sarray(), varray());
bind_method(String, is_relative_path, sarray(), varray());
@@ -1470,7 +1472,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector2, angle, sarray(), varray());
bind_method(Vector2, angle_to, sarray("to"), varray());
bind_method(Vector2, angle_to_point, sarray("to"), varray());
- bind_method(Vector2, direction_to, sarray("b"), varray());
+ bind_method(Vector2, direction_to, sarray("to"), varray());
bind_method(Vector2, distance_to, sarray("to"), varray());
bind_method(Vector2, distance_squared_to, sarray("to"), varray());
bind_method(Vector2, length, sarray(), varray());
@@ -1485,6 +1487,8 @@ static void _register_variant_builtin_methods() {
bind_method(Vector2, lerp, sarray("to", "weight"), varray());
bind_method(Vector2, slerp, sarray("to", "weight"), varray());
bind_method(Vector2, cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray());
+ bind_method(Vector2, max_axis_index, sarray(), varray());
+ bind_method(Vector2, min_axis_index, sarray(), varray());
bind_method(Vector2, move_toward, sarray("to", "delta"), varray());
bind_method(Vector2, rotated, sarray("phi"), varray());
bind_method(Vector2, orthogonal, sarray(), varray());
@@ -1507,12 +1511,17 @@ static void _register_variant_builtin_methods() {
/* Vector2i */
bind_method(Vector2i, aspect, sarray(), varray());
+ bind_method(Vector2i, max_axis_index, sarray(), varray());
+ bind_method(Vector2i, min_axis_index, sarray(), varray());
+ bind_method(Vector2i, length, sarray(), varray());
+ bind_method(Vector2i, length_squared, sarray(), varray());
bind_method(Vector2i, sign, sarray(), varray());
bind_method(Vector2i, abs, sarray(), varray());
bind_method(Vector2i, clamp, sarray("min", "max"), varray());
/* Rect2 */
+ bind_method(Rect2, get_center, sarray(), varray());
bind_method(Rect2, get_area, sarray(), varray());
bind_method(Rect2, has_no_area, sarray(), varray());
bind_method(Rect2, has_point, sarray("point"), varray());
@@ -1529,6 +1538,7 @@ static void _register_variant_builtin_methods() {
/* Rect2i */
+ bind_method(Rect2i, get_center, sarray(), varray());
bind_method(Rect2i, get_area, sarray(), varray());
bind_method(Rect2i, has_no_area, sarray(), varray());
bind_method(Rect2i, has_point, sarray("point"), varray());
@@ -1544,13 +1554,13 @@ static void _register_variant_builtin_methods() {
/* Vector3 */
- bind_method(Vector3, min_axis, sarray(), varray());
- bind_method(Vector3, max_axis, sarray(), varray());
+ bind_method(Vector3, min_axis_index, sarray(), varray());
+ bind_method(Vector3, max_axis_index, sarray(), varray());
bind_method(Vector3, angle_to, sarray("to"), varray());
bind_method(Vector3, signed_angle_to, sarray("to", "axis"), varray());
- bind_method(Vector3, direction_to, sarray("b"), varray());
- bind_method(Vector3, distance_to, sarray("b"), varray());
- bind_method(Vector3, distance_squared_to, sarray("b"), varray());
+ bind_method(Vector3, direction_to, sarray("to"), varray());
+ bind_method(Vector3, distance_to, sarray("to"), varray());
+ bind_method(Vector3, distance_squared_to, sarray("to"), varray());
bind_method(Vector3, length, sarray(), varray());
bind_method(Vector3, length_squared, sarray(), varray());
bind_method(Vector3, limit_length, sarray("length"), varray(1.0));
@@ -1568,7 +1578,6 @@ static void _register_variant_builtin_methods() {
bind_method(Vector3, dot, sarray("with"), varray());
bind_method(Vector3, cross, sarray("with"), varray());
bind_method(Vector3, outer, sarray("with"), varray());
- bind_method(Vector3, to_diagonal_matrix, sarray(), varray());
bind_method(Vector3, abs, sarray(), varray());
bind_method(Vector3, floor, sarray(), varray());
bind_method(Vector3, ceil, sarray(), varray());
@@ -1580,11 +1589,15 @@ static void _register_variant_builtin_methods() {
bind_method(Vector3, bounce, sarray("n"), varray());
bind_method(Vector3, reflect, sarray("n"), varray());
bind_method(Vector3, sign, sarray(), varray());
+ bind_method(Vector3, octahedron_encode, sarray(), varray());
+ bind_static_method(Vector3, octahedron_decode, sarray("uv"), varray());
/* Vector3i */
- bind_method(Vector3i, min_axis, sarray(), varray());
- bind_method(Vector3i, max_axis, sarray(), varray());
+ bind_method(Vector3i, min_axis_index, sarray(), varray());
+ bind_method(Vector3i, max_axis_index, sarray(), varray());
+ bind_method(Vector3i, length, sarray(), varray());
+ bind_method(Vector3i, length_squared, sarray(), varray());
bind_method(Vector3i, sign, sarray(), varray());
bind_method(Vector3i, abs, sarray(), varray());
bind_method(Vector3i, clamp, sarray("min", "max"), varray());
@@ -1616,6 +1629,8 @@ static void _register_variant_builtin_methods() {
bind_method(Quaternion, slerpni, sarray("to", "weight"), varray());
bind_method(Quaternion, cubic_slerp, sarray("b", "pre_a", "post_b", "weight"), varray());
bind_method(Quaternion, get_euler, sarray(), varray());
+ bind_method(Quaternion, get_axis, sarray(), varray());
+ bind_method(Quaternion, get_angle, sarray(), varray());
/* Color */
@@ -1625,17 +1640,16 @@ static void _register_variant_builtin_methods() {
bind_method(Color, to_argb64, sarray(), varray());
bind_method(Color, to_abgr64, sarray(), varray());
bind_method(Color, to_rgba64, sarray(), varray());
+ bind_method(Color, to_html, sarray("with_alpha"), varray(true));
bind_method(Color, clamp, sarray("min", "max"), varray(Color(0, 0, 0, 0), Color(1, 1, 1, 1)));
bind_method(Color, inverted, sarray(), varray());
bind_method(Color, lerp, sarray("to", "weight"), varray());
bind_method(Color, lightened, sarray("amount"), varray());
bind_method(Color, darkened, sarray("amount"), varray());
- bind_method(Color, to_html, sarray("with_alpha"), varray(true));
bind_method(Color, blend, sarray("over"), varray());
+ bind_method(Color, get_luminance, sarray(), varray());
- // FIXME: Color is immutable, need to probably find a way to do this via constructor
- //ADDFUNC4R(COLOR, COLOR, Color, from_hsv, FLOAT, "h", FLOAT, "s", FLOAT, "v", FLOAT, "a", varray(1.0));
bind_method(Color, is_equal_approx, sarray("to"), varray());
bind_static_method(Color, hex, sarray("hex"), varray());
@@ -1647,6 +1661,7 @@ static void _register_variant_builtin_methods() {
bind_static_method(Color, get_named_color_name, sarray("idx"), varray());
bind_static_method(Color, get_named_color, sarray("idx"), varray());
bind_static_method(Color, from_string, sarray("str", "default"), varray());
+ bind_static_method(Color, from_hsv, sarray("h", "s", "v", "alpha"), varray(1.0));
bind_static_method(Color, from_rgbe9995, sarray("rgbe"), varray());
/* RID */
@@ -1689,7 +1704,7 @@ static void _register_variant_builtin_methods() {
bind_method(Signal, get_object_id, sarray(), varray());
bind_method(Signal, get_name, sarray(), varray());
- bind_method(Signal, connect, sarray("callable", "binds", "flags"), varray(Array(), 0));
+ bind_method(Signal, connect, sarray("callable", "flags"), varray(0));
bind_method(Signal, disconnect, sarray("callable"), varray());
bind_method(Signal, is_connected, sarray("callable"), varray());
bind_method(Signal, get_connections, sarray(), varray());
@@ -1703,6 +1718,7 @@ static void _register_variant_builtin_methods() {
bind_method(Transform2D, get_rotation, sarray(), varray());
bind_method(Transform2D, get_origin, sarray(), varray());
bind_method(Transform2D, get_scale, sarray(), varray());
+ bind_method(Transform2D, get_skew, sarray(), varray());
bind_method(Transform2D, orthonormalized, sarray(), varray());
bind_method(Transform2D, rotated, sarray("phi"), varray());
bind_method(Transform2D, scaled, sarray("scale"), varray());
@@ -1712,6 +1728,8 @@ static void _register_variant_builtin_methods() {
bind_method(Transform2D, interpolate_with, sarray("xform", "weight"), varray());
bind_method(Transform2D, is_equal_approx, sarray("xform"), varray());
bind_method(Transform2D, set_rotation, sarray("rotation"), varray());
+ bind_method(Transform2D, set_scale, sarray("scale"), varray());
+ bind_method(Transform2D, set_skew, sarray("skew"), varray());
bind_method(Transform2D, looking_at, sarray("target"), varray(Vector2()));
/* Basis */
@@ -1723,7 +1741,7 @@ static void _register_variant_builtin_methods() {
bind_methodv(Basis, rotated, static_cast<Basis (Basis::*)(const Vector3 &, real_t) const>(&Basis::rotated), sarray("axis", "phi"), varray());
bind_method(Basis, scaled, sarray("scale"), varray());
bind_method(Basis, get_scale, sarray(), varray());
- bind_method(Basis, get_euler, sarray(), varray());
+ bind_method(Basis, get_euler, sarray("order"), varray(Basis::EULER_ORDER_YXZ));
bind_method(Basis, tdotx, sarray("with"), varray());
bind_method(Basis, tdoty, sarray("with"), varray());
bind_method(Basis, tdotz, sarray("with"), varray());
@@ -1732,12 +1750,15 @@ static void _register_variant_builtin_methods() {
bind_method(Basis, is_equal_approx, sarray("b"), varray());
bind_method(Basis, get_rotation_quaternion, sarray(), varray());
bind_static_method(Basis, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0)));
+ bind_static_method(Basis, from_scale, sarray("scale"), varray());
+ bind_static_method(Basis, from_euler, sarray("euler", "order"), varray(Basis::EULER_ORDER_YXZ));
/* AABB */
bind_method(AABB, abs, sarray(), varray());
- bind_method(AABB, get_area, sarray(), varray());
- bind_method(AABB, has_no_area, sarray(), varray());
+ bind_method(AABB, get_center, sarray(), varray());
+ bind_method(AABB, get_volume, sarray(), varray());
+ bind_method(AABB, has_no_volume, sarray(), varray());
bind_method(AABB, has_no_surface, sarray(), varray());
bind_method(AABB, has_point, sarray("point"), varray());
bind_method(AABB, is_equal_approx, sarray("aabb"), varray());
@@ -1797,7 +1818,7 @@ static void _register_variant_builtin_methods() {
bind_method(Array, append_array, sarray("array"), varray());
bind_method(Array, resize, sarray("size"), varray());
bind_method(Array, insert, sarray("position", "value"), varray());
- bind_method(Array, remove, sarray("position"), varray());
+ bind_method(Array, remove_at, sarray("position"), varray());
bind_method(Array, fill, sarray("value"), varray());
bind_method(Array, erase, sarray("value"), varray());
bind_method(Array, front, sarray(), varray());
@@ -1831,14 +1852,15 @@ static void _register_variant_builtin_methods() {
bind_method(PackedByteArray, push_back, sarray("value"), varray());
bind_method(PackedByteArray, append, sarray("value"), varray());
bind_method(PackedByteArray, append_array, sarray("array"), varray());
- bind_method(PackedByteArray, remove, sarray("index"), varray());
+ bind_method(PackedByteArray, remove_at, sarray("index"), varray());
bind_method(PackedByteArray, insert, sarray("at_index", "value"), varray());
bind_method(PackedByteArray, fill, sarray("value"), varray());
bind_method(PackedByteArray, resize, sarray("new_size"), varray());
bind_method(PackedByteArray, has, sarray("value"), varray());
bind_method(PackedByteArray, reverse, sarray(), varray());
- bind_method(PackedByteArray, subarray, sarray("from", "to"), varray());
+ bind_method(PackedByteArray, slice, sarray("begin", "end"), varray());
bind_method(PackedByteArray, sort, sarray(), varray());
+ bind_method(PackedByteArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedByteArray, duplicate, sarray(), varray());
bind_function(PackedByteArray, get_string_from_ascii, _VariantCall::func_PackedByteArray_get_string_from_ascii, sarray(), varray());
@@ -1891,15 +1913,16 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt32Array, push_back, sarray("value"), varray());
bind_method(PackedInt32Array, append, sarray("value"), varray());
bind_method(PackedInt32Array, append_array, sarray("array"), varray());
- bind_method(PackedInt32Array, remove, sarray("index"), varray());
+ bind_method(PackedInt32Array, remove_at, sarray("index"), varray());
bind_method(PackedInt32Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedInt32Array, fill, sarray("value"), varray());
bind_method(PackedInt32Array, resize, sarray("new_size"), varray());
bind_method(PackedInt32Array, has, sarray("value"), varray());
bind_method(PackedInt32Array, reverse, sarray(), varray());
- bind_method(PackedInt32Array, subarray, sarray("from", "to"), varray());
+ bind_method(PackedInt32Array, slice, sarray("begin", "end"), varray());
bind_method(PackedInt32Array, to_byte_array, sarray(), varray());
bind_method(PackedInt32Array, sort, sarray(), varray());
+ bind_method(PackedInt32Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedInt32Array, duplicate, sarray(), varray());
/* Int64 Array */
@@ -1910,15 +1933,16 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt64Array, push_back, sarray("value"), varray());
bind_method(PackedInt64Array, append, sarray("value"), varray());
bind_method(PackedInt64Array, append_array, sarray("array"), varray());
- bind_method(PackedInt64Array, remove, sarray("index"), varray());
+ bind_method(PackedInt64Array, remove_at, sarray("index"), varray());
bind_method(PackedInt64Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedInt64Array, fill, sarray("value"), varray());
bind_method(PackedInt64Array, resize, sarray("new_size"), varray());
bind_method(PackedInt64Array, has, sarray("value"), varray());
bind_method(PackedInt64Array, reverse, sarray(), varray());
- bind_method(PackedInt64Array, subarray, sarray("from", "to"), varray());
+ bind_method(PackedInt64Array, slice, sarray("begin", "end"), varray());
bind_method(PackedInt64Array, to_byte_array, sarray(), varray());
bind_method(PackedInt64Array, sort, sarray(), varray());
+ bind_method(PackedInt64Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedInt64Array, duplicate, sarray(), varray());
/* Float32 Array */
@@ -1929,15 +1953,16 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat32Array, push_back, sarray("value"), varray());
bind_method(PackedFloat32Array, append, sarray("value"), varray());
bind_method(PackedFloat32Array, append_array, sarray("array"), varray());
- bind_method(PackedFloat32Array, remove, sarray("index"), varray());
+ bind_method(PackedFloat32Array, remove_at, sarray("index"), varray());
bind_method(PackedFloat32Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedFloat32Array, fill, sarray("value"), varray());
bind_method(PackedFloat32Array, resize, sarray("new_size"), varray());
bind_method(PackedFloat32Array, has, sarray("value"), varray());
bind_method(PackedFloat32Array, reverse, sarray(), varray());
- bind_method(PackedFloat32Array, subarray, sarray("from", "to"), varray());
+ bind_method(PackedFloat32Array, slice, sarray("begin", "end"), varray());
bind_method(PackedFloat32Array, to_byte_array, sarray(), varray());
bind_method(PackedFloat32Array, sort, sarray(), varray());
+ bind_method(PackedFloat32Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedFloat32Array, duplicate, sarray(), varray());
/* Float64 Array */
@@ -1948,15 +1973,16 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat64Array, push_back, sarray("value"), varray());
bind_method(PackedFloat64Array, append, sarray("value"), varray());
bind_method(PackedFloat64Array, append_array, sarray("array"), varray());
- bind_method(PackedFloat64Array, remove, sarray("index"), varray());
+ bind_method(PackedFloat64Array, remove_at, sarray("index"), varray());
bind_method(PackedFloat64Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedFloat64Array, fill, sarray("value"), varray());
bind_method(PackedFloat64Array, resize, sarray("new_size"), varray());
bind_method(PackedFloat64Array, has, sarray("value"), varray());
bind_method(PackedFloat64Array, reverse, sarray(), varray());
- bind_method(PackedFloat64Array, subarray, sarray("from", "to"), varray());
+ bind_method(PackedFloat64Array, slice, sarray("begin", "end"), varray());
bind_method(PackedFloat64Array, to_byte_array, sarray(), varray());
bind_method(PackedFloat64Array, sort, sarray(), varray());
+ bind_method(PackedFloat64Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedFloat64Array, duplicate, sarray(), varray());
/* String Array */
@@ -1967,15 +1993,16 @@ static void _register_variant_builtin_methods() {
bind_method(PackedStringArray, push_back, sarray("value"), varray());
bind_method(PackedStringArray, append, sarray("value"), varray());
bind_method(PackedStringArray, append_array, sarray("array"), varray());
- bind_method(PackedStringArray, remove, sarray("index"), varray());
+ 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_method(PackedStringArray, has, sarray("value"), varray());
bind_method(PackedStringArray, reverse, sarray(), varray());
- bind_method(PackedStringArray, subarray, sarray("from", "to"), varray());
+ bind_method(PackedStringArray, slice, sarray("begin", "end"), varray());
bind_method(PackedStringArray, to_byte_array, sarray(), varray());
bind_method(PackedStringArray, sort, sarray(), varray());
+ bind_method(PackedStringArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedStringArray, duplicate, sarray(), varray());
/* Vector2 Array */
@@ -1986,15 +2013,16 @@ static void _register_variant_builtin_methods() {
bind_method(PackedVector2Array, push_back, sarray("value"), varray());
bind_method(PackedVector2Array, append, sarray("value"), varray());
bind_method(PackedVector2Array, append_array, sarray("array"), varray());
- bind_method(PackedVector2Array, remove, sarray("index"), varray());
+ 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_method(PackedVector2Array, has, sarray("value"), varray());
bind_method(PackedVector2Array, reverse, sarray(), varray());
- bind_method(PackedVector2Array, subarray, sarray("from", "to"), varray());
+ bind_method(PackedVector2Array, slice, sarray("begin", "end"), varray());
bind_method(PackedVector2Array, to_byte_array, sarray(), varray());
bind_method(PackedVector2Array, sort, sarray(), varray());
+ bind_method(PackedVector2Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedVector2Array, duplicate, sarray(), varray());
/* Vector3 Array */
@@ -2005,15 +2033,16 @@ static void _register_variant_builtin_methods() {
bind_method(PackedVector3Array, push_back, sarray("value"), varray());
bind_method(PackedVector3Array, append, sarray("value"), varray());
bind_method(PackedVector3Array, append_array, sarray("array"), varray());
- bind_method(PackedVector3Array, remove, sarray("index"), varray());
+ 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_method(PackedVector3Array, has, sarray("value"), varray());
bind_method(PackedVector3Array, reverse, sarray(), varray());
- bind_method(PackedVector3Array, subarray, sarray("from", "to"), varray());
+ bind_method(PackedVector3Array, slice, sarray("begin", "end"), varray());
bind_method(PackedVector3Array, to_byte_array, sarray(), varray());
bind_method(PackedVector3Array, sort, sarray(), varray());
+ bind_method(PackedVector3Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedVector3Array, duplicate, sarray(), varray());
/* Color Array */
@@ -2024,15 +2053,16 @@ static void _register_variant_builtin_methods() {
bind_method(PackedColorArray, push_back, sarray("value"), varray());
bind_method(PackedColorArray, append, sarray("value"), varray());
bind_method(PackedColorArray, append_array, sarray("array"), varray());
- bind_method(PackedColorArray, remove, sarray("index"), varray());
+ 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_method(PackedColorArray, has, sarray("value"), varray());
bind_method(PackedColorArray, reverse, sarray(), varray());
- bind_method(PackedColorArray, subarray, sarray("from", "to"), varray());
+ bind_method(PackedColorArray, slice, sarray("begin", "end"), varray());
bind_method(PackedColorArray, to_byte_array, sarray(), varray());
bind_method(PackedColorArray, sort, sarray(), varray());
+ bind_method(PackedColorArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedColorArray, duplicate, sarray(), varray());
/* Register constants */
@@ -2090,6 +2120,13 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::VECTOR2I, "UP", Vector2i(0, -1));
_VariantCall::add_variant_constant(Variant::VECTOR2I, "DOWN", Vector2i(0, 1));
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_XYZ", Basis::EULER_ORDER_XYZ);
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_XZY", Basis::EULER_ORDER_XZY);
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_YXZ", Basis::EULER_ORDER_YXZ);
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_YZX", Basis::EULER_ORDER_YZX);
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_ZXY", Basis::EULER_ORDER_ZXY);
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_ZYX", Basis::EULER_ORDER_ZYX);
+
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "IDENTITY", Transform2D());
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_X", Transform2D(-1, 0, 0, 1, 0, 0));
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_Y", Transform2D(1, 0, 0, -1, 0, 0));
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index a1a2bec369..351f4ae253 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -114,22 +114,24 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructNoArgs<Transform2D>>(sarray());
add_constructor<VariantConstructor<Transform2D, Transform2D>>(sarray("from"));
add_constructor<VariantConstructor<Transform2D, float, Vector2>>(sarray("rotation", "position"));
+ add_constructor<VariantConstructor<Transform2D, float, Size2, float, Vector2>>(sarray("rotation", "scale", "skew", "position"));
add_constructor<VariantConstructor<Transform2D, Vector2, Vector2, Vector2>>(sarray("x_axis", "y_axis", "origin"));
add_constructor<VariantConstructNoArgs<Plane>>(sarray());
add_constructor<VariantConstructor<Plane, Plane>>(sarray("from"));
+ add_constructor<VariantConstructor<Plane, Vector3>>(sarray("normal"));
add_constructor<VariantConstructor<Plane, Vector3, double>>(sarray("normal", "d"));
- add_constructor<VariantConstructor<Plane, Vector3, Vector3>>(sarray("point", "normal"));
+ add_constructor<VariantConstructor<Plane, Vector3, Vector3>>(sarray("normal", "point"));
add_constructor<VariantConstructor<Plane, Vector3, Vector3, Vector3>>(sarray("point1", "point2", "point3"));
add_constructor<VariantConstructor<Plane, double, double, double, double>>(sarray("a", "b", "c", "d"));
add_constructor<VariantConstructNoArgs<Quaternion>>(sarray());
add_constructor<VariantConstructor<Quaternion, Quaternion>>(sarray("from"));
add_constructor<VariantConstructor<Quaternion, Basis>>(sarray("from"));
- add_constructor<VariantConstructor<Quaternion, Vector3>>(sarray("euler"));
add_constructor<VariantConstructor<Quaternion, Vector3, double>>(sarray("axis", "angle"));
add_constructor<VariantConstructor<Quaternion, Vector3, Vector3>>(sarray("arc_from", "arc_to"));
add_constructor<VariantConstructor<Quaternion, double, double, double, double>>(sarray("x", "y", "z", "w"));
+ add_constructor<VariantConstructor<Quaternion, Vector3>>(sarray("euler_yxz"));
add_constructor<VariantConstructNoArgs<::AABB>>(sarray());
add_constructor<VariantConstructor<::AABB, ::AABB>>(sarray("from"));
@@ -138,7 +140,6 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructNoArgs<Basis>>(sarray());
add_constructor<VariantConstructor<Basis, Basis>>(sarray("from"));
add_constructor<VariantConstructor<Basis, Quaternion>>(sarray("from"));
- add_constructor<VariantConstructor<Basis, Vector3>>(sarray("euler"));
add_constructor<VariantConstructor<Basis, Vector3, double>>(sarray("axis", "phi"));
add_constructor<VariantConstructor<Basis, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis"));
diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h
index b03f4a8d3b..6027cb027e 100644
--- a/core/variant/variant_construct.h
+++ b/core/variant/variant_construct.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/variant/variant_destruct.cpp b/core/variant/variant_destruct.cpp
index 366b71df3a..ab8303f3ae 100644
--- a/core/variant/variant_destruct.cpp
+++ b/core/variant/variant_destruct.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/variant/variant_destruct.h b/core/variant/variant_destruct.h
index 7356e42201..5e3478635d 100644
--- a/core/variant/variant_destruct.h
+++ b/core/variant/variant_destruct.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h
index 40c8a1bfde..aaafa2f6b6 100644
--- a/core/variant/variant_internal.h
+++ b/core/variant/variant_internal.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -753,8 +753,20 @@ VARIANT_ACCESSOR_NUMBER(uint32_t)
VARIANT_ACCESSOR_NUMBER(int64_t)
VARIANT_ACCESSOR_NUMBER(uint64_t)
VARIANT_ACCESSOR_NUMBER(char32_t)
+
+// Bind enums to allow using them as return types.
VARIANT_ACCESSOR_NUMBER(Error)
VARIANT_ACCESSOR_NUMBER(Side)
+VARIANT_ACCESSOR_NUMBER(Vector2::Axis)
+VARIANT_ACCESSOR_NUMBER(Vector2i::Axis)
+VARIANT_ACCESSOR_NUMBER(Vector3::Axis)
+VARIANT_ACCESSOR_NUMBER(Vector3i::Axis)
+
+template <>
+struct VariantInternalAccessor<Basis::EulerOrder> {
+ static _FORCE_INLINE_ Basis::EulerOrder get(const Variant *v) { return Basis::EulerOrder(*VariantInternal::get_int(v)); }
+ static _FORCE_INLINE_ void set(Variant *v, Basis::EulerOrder p_value) { *VariantInternal::get_int(v) = p_value; }
+};
template <>
struct VariantInternalAccessor<ObjectID> {
@@ -1014,6 +1026,10 @@ INITIALIZER_INT(int64_t)
INITIALIZER_INT(char32_t)
INITIALIZER_INT(Error)
INITIALIZER_INT(ObjectID)
+INITIALIZER_INT(Vector2::Axis)
+INITIALIZER_INT(Vector2i::Axis)
+INITIALIZER_INT(Vector3::Axis)
+INITIALIZER_INT(Vector3i::Axis)
template <>
struct VariantInitializer<double> {
@@ -1301,12 +1317,12 @@ struct VariantZeroAssigner<Signal> {
template <>
struct VariantZeroAssigner<Dictionary> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_dictionary(v) = Dictionary(); }
};
template <>
struct VariantZeroAssigner<Array> {
- static _FORCE_INLINE_ void zero(Variant *v) {}
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_array(v) = Array(); }
};
template <>
diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp
index a245aff35b..e0ffcc9d11 100644
--- a/core/variant/variant_op.cpp
+++ b/core/variant/variant_op.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -314,6 +314,74 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorEqual<PackedVector3Array, PackedVector3Array>>(Variant::OP_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::PACKED_VECTOR3_ARRAY);
register_op<OperatorEvaluatorEqual<PackedColorArray, PackedColorArray>>(Variant::OP_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::PACKED_COLOR_ARRAY);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::BOOL, Variant::NIL>>(Variant::OP_EQUAL, Variant::BOOL, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::INT, Variant::NIL>>(Variant::OP_EQUAL, Variant::INT, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::FLOAT, Variant::NIL>>(Variant::OP_EQUAL, Variant::FLOAT, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::STRING, Variant::NIL>>(Variant::OP_EQUAL, Variant::STRING, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR2, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR2, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR2I, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR2I, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::RECT2, Variant::NIL>>(Variant::OP_EQUAL, Variant::RECT2, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::RECT2I, Variant::NIL>>(Variant::OP_EQUAL, Variant::RECT2I, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR3, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR3, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR3I, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR3I, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::NIL>>(Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PLANE, Variant::NIL>>(Variant::OP_EQUAL, Variant::PLANE, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::QUATERNION, Variant::NIL>>(Variant::OP_EQUAL, Variant::QUATERNION, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::AABB, Variant::NIL>>(Variant::OP_EQUAL, Variant::AABB, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::BASIS, Variant::NIL>>(Variant::OP_EQUAL, Variant::BASIS, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::TRANSFORM3D, Variant::NIL>>(Variant::OP_EQUAL, Variant::TRANSFORM3D, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::COLOR, Variant::NIL>>(Variant::OP_EQUAL, Variant::COLOR, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::STRING_NAME, Variant::NIL>>(Variant::OP_EQUAL, Variant::STRING_NAME, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NODE_PATH, Variant::NIL>>(Variant::OP_EQUAL, Variant::NODE_PATH, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::RID, Variant::NIL>>(Variant::OP_EQUAL, Variant::RID, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::CALLABLE, Variant::NIL>>(Variant::OP_EQUAL, Variant::CALLABLE, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::SIGNAL, Variant::NIL>>(Variant::OP_EQUAL, Variant::SIGNAL, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::DICTIONARY, Variant::NIL>>(Variant::OP_EQUAL, Variant::DICTIONARY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_BYTE_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_BYTE_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_INT32_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_INT32_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_INT64_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_INT64_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_FLOAT32_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_FLOAT32_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_FLOAT64_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_FLOAT64_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_STRING_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_STRING_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::NIL);
+
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::BOOL>>(Variant::OP_EQUAL, Variant::NIL, Variant::BOOL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::INT>>(Variant::OP_EQUAL, Variant::NIL, Variant::INT);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::FLOAT>>(Variant::OP_EQUAL, Variant::NIL, Variant::FLOAT);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::STRING>>(Variant::OP_EQUAL, Variant::NIL, Variant::STRING);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR2>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR2);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR2I>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR2I);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::RECT2>>(Variant::OP_EQUAL, Variant::NIL, Variant::RECT2);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::RECT2I>>(Variant::OP_EQUAL, Variant::NIL, Variant::RECT2I);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3I>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::TRANSFORM2D>>(Variant::OP_EQUAL, Variant::NIL, Variant::TRANSFORM2D);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PLANE>>(Variant::OP_EQUAL, Variant::NIL, Variant::PLANE);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::QUATERNION>>(Variant::OP_EQUAL, Variant::NIL, Variant::QUATERNION);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::AABB>>(Variant::OP_EQUAL, Variant::NIL, Variant::AABB);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::BASIS>>(Variant::OP_EQUAL, Variant::NIL, Variant::BASIS);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::TRANSFORM3D>>(Variant::OP_EQUAL, Variant::NIL, Variant::TRANSFORM3D);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::COLOR>>(Variant::OP_EQUAL, Variant::NIL, Variant::COLOR);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::STRING_NAME>>(Variant::OP_EQUAL, Variant::NIL, Variant::STRING_NAME);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::NODE_PATH>>(Variant::OP_EQUAL, Variant::NIL, Variant::NODE_PATH);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::RID>>(Variant::OP_EQUAL, Variant::NIL, Variant::RID);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::CALLABLE>>(Variant::OP_EQUAL, Variant::NIL, Variant::CALLABLE);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::SIGNAL>>(Variant::OP_EQUAL, Variant::NIL, Variant::SIGNAL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::DICTIONARY>>(Variant::OP_EQUAL, Variant::NIL, Variant::DICTIONARY);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::ARRAY);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_BYTE_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_BYTE_ARRAY);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_INT32_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_INT32_ARRAY);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_INT64_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_INT64_ARRAY);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_FLOAT32_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_FLOAT32_ARRAY);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_FLOAT64_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_FLOAT64_ARRAY);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_STRING_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_STRING_ARRAY);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_VECTOR2_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_VECTOR2_ARRAY);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_VECTOR3_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_VECTOR3_ARRAY);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_COLOR_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_COLOR_ARRAY);
+
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::NIL);
register_op<OperatorEvaluatorNotEqual<bool, bool>>(Variant::OP_NOT_EQUAL, Variant::BOOL, Variant::BOOL);
register_op<OperatorEvaluatorNotEqual<int64_t, int64_t>>(Variant::OP_NOT_EQUAL, Variant::INT, Variant::INT);
@@ -360,6 +428,74 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorNotEqual<PackedVector3Array, PackedVector3Array>>(Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::PACKED_VECTOR3_ARRAY);
register_op<OperatorEvaluatorNotEqual<PackedColorArray, PackedColorArray>>(Variant::OP_NOT_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::PACKED_COLOR_ARRAY);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::BOOL, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::BOOL, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::INT, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::INT, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::FLOAT, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::FLOAT, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::STRING, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::STRING, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR2, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR2, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR2I, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR2I, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::RECT2, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::RECT2, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::RECT2I, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::RECT2I, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR3, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR3I, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3I, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::QUATERNION, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::QUATERNION, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::AABB, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::AABB, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::BASIS, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::BASIS, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::TRANSFORM3D, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM3D, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::COLOR, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::COLOR, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::STRING_NAME, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::STRING_NAME, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NODE_PATH, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::NODE_PATH, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::RID, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::RID, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::CALLABLE, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::CALLABLE, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::SIGNAL, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::SIGNAL, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::DICTIONARY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::DICTIONARY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_BYTE_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_BYTE_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_INT32_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_INT32_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_INT64_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_INT64_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_FLOAT32_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_FLOAT32_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_FLOAT64_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_FLOAT64_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_STRING_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_STRING_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::NIL);
+
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::BOOL>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::BOOL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::INT>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::INT);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::FLOAT>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::FLOAT);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::STRING>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::STRING);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR2>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR2);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR2I>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR2I);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::RECT2>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::RECT2);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::RECT2I>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::RECT2I);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3I>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::TRANSFORM2D>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::TRANSFORM2D);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PLANE>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PLANE);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::QUATERNION>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::QUATERNION);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::AABB>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::AABB);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::BASIS>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::BASIS);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::TRANSFORM3D>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::TRANSFORM3D);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::COLOR>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::COLOR);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::STRING_NAME>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::STRING_NAME);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::NODE_PATH>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::NODE_PATH);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::RID>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::RID);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::CALLABLE>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::CALLABLE);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::SIGNAL>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::SIGNAL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::DICTIONARY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::DICTIONARY);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::ARRAY);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_BYTE_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_BYTE_ARRAY);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_INT32_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_INT32_ARRAY);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_INT64_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_INT64_ARRAY);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_FLOAT32_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_FLOAT32_ARRAY);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_FLOAT64_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_FLOAT64_ARRAY);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_STRING_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_STRING_ARRAY);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_VECTOR2_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_VECTOR2_ARRAY);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_VECTOR3_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_VECTOR3_ARRAY);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_COLOR_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_COLOR_ARRAY);
+
register_op<OperatorEvaluatorLess<bool, bool>>(Variant::OP_LESS, Variant::BOOL, Variant::BOOL);
register_op<OperatorEvaluatorLess<int64_t, int64_t>>(Variant::OP_LESS, Variant::INT, Variant::INT);
register_op<OperatorEvaluatorLess<int64_t, double>>(Variant::OP_LESS, Variant::INT, Variant::FLOAT);
@@ -505,7 +641,10 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorNotFloat>(Variant::OP_NOT, Variant::FLOAT, Variant::NIL);
register_op<OperatorEvaluatorNotObject>(Variant::OP_NOT, Variant::OBJECT, Variant::NIL);
- register_op<OperatorEvaluatorInStringFind>(Variant::OP_IN, Variant::STRING, Variant::STRING);
+ register_op<OperatorEvaluatorInStringFind<String>>(Variant::OP_IN, Variant::STRING, Variant::STRING);
+ register_op<OperatorEvaluatorInStringFind<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::STRING);
+ register_op<OperatorEvaluatorInStringNameFind<String>>(Variant::OP_IN, Variant::STRING, Variant::STRING_NAME);
+ register_op<OperatorEvaluatorInStringNameFind<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::STRING_NAME);
register_op<OperatorEvaluatorInDictionaryHasNil>(Variant::OP_IN, Variant::NIL, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<bool>>(Variant::OP_IN, Variant::BOOL, Variant::DICTIONARY);
diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h
index 3c9f849a4f..9791cb67b3 100644
--- a/core/variant/variant_op.h
+++ b/core/variant/variant_op.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1213,22 +1213,44 @@ public:
////
+template <class Left>
class OperatorEvaluatorInStringFind {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
- const String &str_a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
+ const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(&p_left);
const String &str_b = *VariantGetInternalPtr<String>::get_ptr(&p_right);
*r_ret = str_b.find(str_a) != -1;
r_valid = true;
}
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
- const String &str_a = *VariantGetInternalPtr<String>::get_ptr(left);
+ const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(left);
const String &str_b = *VariantGetInternalPtr<String>::get_ptr(right);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1;
}
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
- PtrToArg<bool>::encode(PtrToArg<String>::convert(right).find(PtrToArg<String>::convert(left)) != -1, r_ret);
+ PtrToArg<bool>::encode(PtrToArg<String>::convert(right).find(PtrToArg<Left>::convert(left)) != -1, r_ret);
+ }
+ static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class Left>
+class OperatorEvaluatorInStringNameFind {
+public:
+ static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+ const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(&p_left);
+ const String str_b = VariantGetInternalPtr<StringName>::get_ptr(&p_right)->operator String();
+
+ *r_ret = str_b.find(str_a) != -1;
+ r_valid = true;
+ }
+ static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(left);
+ const String str_b = VariantGetInternalPtr<StringName>::get_ptr(right)->operator String();
+ *VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1;
+ }
+ static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+ PtrToArg<bool>::encode(PtrToArg<StringName>::convert(right).operator String().find(PtrToArg<Left>::convert(left)) != -1, r_ret);
}
static Variant::Type get_return_type() { return Variant::BOOL; }
};
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index a214a238a6..571181f665 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -90,6 +90,17 @@ const char *VariantParser::tk_name[TK_MAX] = {
"ERROR"
};
+static double stor_fix(const String &p_str) {
+ if (p_str == "inf") {
+ return INFINITY;
+ } else if (p_str == "inf_neg") {
+ return -INFINITY;
+ } else if (p_str == "nan") {
+ return NAN;
+ }
+ return -1;
+}
+
Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, String &r_err_str) {
bool string_name = false;
@@ -469,8 +480,19 @@ Error VariantParser::_parse_construct(Stream *p_stream, Vector<T> &r_construct,
if (first && token.type == TK_PARENTHESIS_CLOSE) {
break;
} else if (token.type != TK_NUMBER) {
- r_err_str = "Expected float in constructor";
- return ERR_PARSE_ERROR;
+ bool valid = false;
+ if (token.type == TK_IDENTIFIER) {
+ double real = stor_fix(token.value);
+ if (real != -1) {
+ token.type = TK_NUMBER;
+ token.value = real;
+ valid = true;
+ }
+ }
+ if (!valid) {
+ r_err_str = "Expected float in constructor";
+ return ERR_PARSE_ERROR;
+ }
}
r_construct.push_back(token.value);
@@ -507,6 +529,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Variant();
} else if (id == "inf") {
value = INFINITY;
+ } else if (id == "inf_neg") {
+ value = -INFINITY;
} else if (id == "nan") {
value = NAN;
} else if (id == "Vector2") {
@@ -1401,17 +1425,25 @@ Error VariantParser::parse(Stream *p_stream, Variant &r_ret, String &r_err_str,
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////
-static String rtosfix(double p_value) {
+static String rtos_fix(double p_value) {
if (p_value == 0.0) {
return "0"; //avoid negative zero (-0) being written, which may annoy git, svn, etc. for changes when they don't exist.
+ } else if (isnan(p_value)) {
+ return "nan";
+ } else if (isinf(p_value)) {
+ if (p_value > 0) {
+ return "inf";
+ } else {
+ return "inf_neg";
+ }
} else {
return rtoss(p_value);
}
}
-Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud) {
+Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int recursion_count) {
switch (p_variant.get_type()) {
case Variant::NIL: {
p_store_string_func(p_store_string_ud, "null");
@@ -1423,8 +1455,8 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, itos(p_variant.operator int64_t()));
} break;
case Variant::FLOAT: {
- String s = rtosfix(p_variant.operator double());
- if (s != "inf" && s != "nan") {
+ String s = rtos_fix(p_variant.operator double());
+ if (s != "inf" && s != "inf_neg" && s != "nan") {
if (s.find(".") == -1 && s.find("e") == -1) {
s += ".0";
}
@@ -1439,7 +1471,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
case Variant::VECTOR2: {
Vector2 v = p_variant;
- p_store_string_func(p_store_string_ud, "Vector2(" + rtosfix(v.x) + ", " + rtosfix(v.y) + ")");
+ p_store_string_func(p_store_string_ud, "Vector2(" + rtos_fix(v.x) + ", " + rtos_fix(v.y) + ")");
} break;
case Variant::VECTOR2I: {
Vector2i v = p_variant;
@@ -1447,7 +1479,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
case Variant::RECT2: {
Rect2 aabb = p_variant;
- p_store_string_func(p_store_string_ud, "Rect2(" + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + ")");
+ p_store_string_func(p_store_string_ud, "Rect2(" + rtos_fix(aabb.position.x) + ", " + rtos_fix(aabb.position.y) + ", " + rtos_fix(aabb.size.x) + ", " + rtos_fix(aabb.size.y) + ")");
} break;
case Variant::RECT2I: {
@@ -1457,7 +1489,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
case Variant::VECTOR3: {
Vector3 v = p_variant;
- p_store_string_func(p_store_string_ud, "Vector3(" + rtosfix(v.x) + ", " + rtosfix(v.y) + ", " + rtosfix(v.z) + ")");
+ p_store_string_func(p_store_string_ud, "Vector3(" + rtos_fix(v.x) + ", " + rtos_fix(v.y) + ", " + rtos_fix(v.z) + ")");
} break;
case Variant::VECTOR3I: {
Vector3i v = p_variant;
@@ -1465,17 +1497,17 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
case Variant::PLANE: {
Plane p = p_variant;
- p_store_string_func(p_store_string_ud, "Plane(" + rtosfix(p.normal.x) + ", " + rtosfix(p.normal.y) + ", " + rtosfix(p.normal.z) + ", " + rtosfix(p.d) + ")");
+ p_store_string_func(p_store_string_ud, "Plane(" + rtos_fix(p.normal.x) + ", " + rtos_fix(p.normal.y) + ", " + rtos_fix(p.normal.z) + ", " + rtos_fix(p.d) + ")");
} break;
case Variant::AABB: {
AABB aabb = p_variant;
- p_store_string_func(p_store_string_ud, "AABB(" + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.position.z) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + ", " + rtosfix(aabb.size.z) + ")");
+ p_store_string_func(p_store_string_ud, "AABB(" + rtos_fix(aabb.position.x) + ", " + rtos_fix(aabb.position.y) + ", " + rtos_fix(aabb.position.z) + ", " + rtos_fix(aabb.size.x) + ", " + rtos_fix(aabb.size.y) + ", " + rtos_fix(aabb.size.z) + ")");
} break;
case Variant::QUATERNION: {
Quaternion quaternion = p_variant;
- p_store_string_func(p_store_string_ud, "Quaternion(" + rtosfix(quaternion.x) + ", " + rtosfix(quaternion.y) + ", " + rtosfix(quaternion.z) + ", " + rtosfix(quaternion.w) + ")");
+ p_store_string_func(p_store_string_ud, "Quaternion(" + rtos_fix(quaternion.x) + ", " + rtos_fix(quaternion.y) + ", " + rtos_fix(quaternion.z) + ", " + rtos_fix(quaternion.w) + ")");
} break;
case Variant::TRANSFORM2D: {
@@ -1486,7 +1518,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i != 0 || j != 0) {
s += ", ";
}
- s += rtosfix(m3.elements[i][j]);
+ s += rtos_fix(m3.elements[i][j]);
}
}
@@ -1501,7 +1533,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i != 0 || j != 0) {
s += ", ";
}
- s += rtosfix(m3.elements[i][j]);
+ s += rtos_fix(m3.elements[i][j]);
}
}
@@ -1517,11 +1549,11 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i != 0 || j != 0) {
s += ", ";
}
- s += rtosfix(m3.elements[i][j]);
+ s += rtos_fix(m3.elements[i][j]);
}
}
- s = s + ", " + rtosfix(t.origin.x) + ", " + rtosfix(t.origin.y) + ", " + rtosfix(t.origin.z);
+ s = s + ", " + rtos_fix(t.origin.x) + ", " + rtos_fix(t.origin.y) + ", " + rtos_fix(t.origin.z);
p_store_string_func(p_store_string_ud, s + ")");
} break;
@@ -1529,7 +1561,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
// misc types
case Variant::COLOR: {
Color c = p_variant;
- p_store_string_func(p_store_string_ud, "Color(" + rtosfix(c.r) + ", " + rtosfix(c.g) + ", " + rtosfix(c.b) + ", " + rtosfix(c.a) + ")");
+ p_store_string_func(p_store_string_ud, "Color(" + rtos_fix(c.r) + ", " + rtos_fix(c.g) + ", " + rtos_fix(c.b) + ", " + rtos_fix(c.a) + ")");
} break;
case Variant::STRING_NAME: {
@@ -1566,14 +1598,14 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
//try path because it's a file
- if (res_text == String() && res->get_path().is_resource_file()) {
+ if (res_text.is_empty() && res->get_path().is_resource_file()) {
//external resource
String path = res->get_path();
res_text = "Resource(\"" + path + "\")";
}
//could come up with some sort of text
- if (res_text != String()) {
+ if (!res_text.is_empty()) {
p_store_string_func(p_store_string_ud, res_text);
break;
}
@@ -1607,41 +1639,56 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
case Variant::DICTIONARY: {
Dictionary dict = p_variant;
-
- List<Variant> keys;
- dict.get_key_list(&keys);
- keys.sort();
-
- p_store_string_func(p_store_string_ud, "{\n");
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- /*
- if (!_check_type(dict[E]))
- continue;
- */
- write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
- p_store_string_func(p_store_string_ud, ": ");
- write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
- if (E->next()) {
- p_store_string_func(p_store_string_ud, ",\n");
- } else {
- p_store_string_func(p_store_string_ud, "\n");
+ if (recursion_count > MAX_RECURSION) {
+ ERR_PRINT("Max recursion reached");
+ p_store_string_func(p_store_string_ud, "{}");
+ } else {
+ recursion_count++;
+
+ List<Variant> keys;
+ dict.get_key_list(&keys);
+ keys.sort();
+
+ p_store_string_func(p_store_string_ud, "{\n");
+ for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ /*
+ if (!_check_type(dict[E->get()]))
+ continue;
+ */
+ write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, recursion_count);
+ p_store_string_func(p_store_string_ud, ": ");
+ write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, recursion_count);
+ if (E->next()) {
+ p_store_string_func(p_store_string_ud, ",\n");
+ } else {
+ p_store_string_func(p_store_string_ud, "\n");
+ }
}
- }
- p_store_string_func(p_store_string_ud, "}");
+ p_store_string_func(p_store_string_ud, "}");
+ }
} break;
+
case Variant::ARRAY: {
- 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) {
- 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, "[]");
+ } else {
+ 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) {
+ p_store_string_func(p_store_string_ud, ", ");
+ }
+ write(array[i], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, recursion_count);
}
- write(array[i], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
+
+ p_store_string_func(p_store_string_ud, "]");
}
- p_store_string_func(p_store_string_ud, "]");
} break;
@@ -1707,7 +1754,7 @@ 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, rtosfix(ptr[i]));
+ p_store_string_func(p_store_string_ud, rtos_fix(ptr[i]));
}
p_store_string_func(p_store_string_ud, ")");
@@ -1723,7 +1770,7 @@ 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, rtosfix(ptr[i]));
+ p_store_string_func(p_store_string_ud, rtos_fix(ptr[i]));
}
p_store_string_func(p_store_string_ud, ")");
@@ -1759,7 +1806,7 @@ 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, rtosfix(ptr[i].x) + ", " + rtosfix(ptr[i].y));
+ p_store_string_func(p_store_string_ud, rtos_fix(ptr[i].x) + ", " + rtos_fix(ptr[i].y));
}
p_store_string_func(p_store_string_ud, ")");
@@ -1775,7 +1822,7 @@ 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, rtosfix(ptr[i].x) + ", " + rtosfix(ptr[i].y) + ", " + rtosfix(ptr[i].z));
+ p_store_string_func(p_store_string_ud, rtos_fix(ptr[i].x) + ", " + rtos_fix(ptr[i].y) + ", " + rtos_fix(ptr[i].z));
}
p_store_string_func(p_store_string_ud, ")");
@@ -1792,7 +1839,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, ", ");
}
- p_store_string_func(p_store_string_ud, rtosfix(ptr[i].r) + ", " + rtosfix(ptr[i].g) + ", " + rtosfix(ptr[i].b) + ", " + rtosfix(ptr[i].a));
+ 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, ")");
diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h
index 1ba26db6ed..e5585076c2 100644
--- a/core/variant/variant_parser.h
+++ b/core/variant/variant_parser.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -140,7 +140,7 @@ public:
typedef Error (*StoreStringFunc)(void *ud, const String &p_string);
typedef String (*EncodeResourceFunc)(void *ud, const RES &p_resource);
- static Error write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud);
+ static Error write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int recursion_count = 0);
static Error write_to_string(const Variant &p_variant, String &r_string, EncodeResourceFunc p_encode_res_func = nullptr, void *p_encode_res_ud = nullptr);
};
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index ae3c7685fd..fa8d26a72b 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -239,7 +239,8 @@ void Variant::set_named(const StringName &p_member, const Variant &p_value, bool
*v = p_value;
r_valid = true;
} else {
- r_valid = false;
+ VariantGetInternalPtr<Dictionary>::get_ptr(this)->operator[](p_member) = p_value;
+ r_valid = true;
}
} else {
@@ -661,6 +662,91 @@ struct VariantIndexedSetGet_Array {
static uint64_t get_indexed_size(const Variant *base) { return 0; }
};
+struct VariantIndexedSetGet_String {
+ static void get(const Variant *base, int64_t index, Variant *value, bool *oob) {
+ int64_t length = VariantGetInternalPtr<String>::get_ptr(base)->length();
+ if (index < 0) {
+ index += length;
+ }
+ if (index < 0 || index >= length) {
+ *oob = true;
+ return;
+ }
+ char32_t result = (*VariantGetInternalPtr<String>::get_ptr(base))[index];
+ *value = String(&result, 1);
+ *oob = false;
+ }
+ static void ptr_get(const void *base, int64_t index, void *member) {
+ /* avoid ptrconvert for performance*/
+ const String &v = *reinterpret_cast<const String *>(base);
+ if (index < 0) {
+ index += v.length();
+ }
+ OOB_TEST(index, v.length());
+ char32_t c = v[index];
+ PtrToArg<String>::encode(String(&c, 1), member);
+ }
+ static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) {
+ if (value->get_type() != Variant::STRING) {
+ *oob = false;
+ *valid = false;
+ return;
+ }
+ int64_t length = VariantGetInternalPtr<String>::get_ptr(base)->length();
+ if (index < 0) {
+ index += length;
+ }
+ if (index < 0 || index >= length) {
+ *oob = true;
+ *valid = false;
+ return;
+ }
+ String *b = VariantGetInternalPtr<String>::get_ptr(base);
+ const String *v = VariantInternal::get_string(value);
+ if (v->length() == 0) {
+ b->remove_at(index);
+ } else {
+ b->set(index, v->get(0));
+ }
+ *oob = false;
+ *valid = true;
+ }
+ static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) {
+ int64_t length = VariantGetInternalPtr<String>::get_ptr(base)->length();
+ if (index < 0) {
+ index += length;
+ }
+ if (index < 0 || index >= length) {
+ *oob = true;
+ return;
+ }
+ String *b = VariantGetInternalPtr<String>::get_ptr(base);
+ const String *v = VariantInternal::get_string(value);
+ if (v->length() == 0) {
+ b->remove_at(index);
+ } else {
+ b->set(index, v->get(0));
+ }
+ *oob = false;
+ }
+ static void ptr_set(void *base, int64_t index, const void *member) {
+ /* avoid ptrconvert for performance*/
+ String &v = *reinterpret_cast<String *>(base);
+ if (index < 0) {
+ index += v.length();
+ }
+ OOB_TEST(index, v.length());
+ const String &m = *reinterpret_cast<const String *>(member);
+ if (unlikely(m.length() == 0)) {
+ v.remove_at(index);
+ } else {
+ v.set(index, m.unicode_at(0));
+ }
+ }
+ static Variant::Type get_index_type() { return Variant::STRING; }
+ static uint64_t get_indexed_size(const Variant *base) { return VariantInternal::get_string(base)->length(); }
+};
+
#define INDEXED_SETGET_STRUCT_DICT(m_base_type) \
struct VariantIndexedSetGet_##m_base_type { \
static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \
@@ -758,6 +844,7 @@ static void register_indexed_member(Variant::Type p_type) {
void register_indexed_setters_getters() {
#define REGISTER_INDEXED_MEMBER(m_base_type) register_indexed_member<VariantIndexedSetGet_##m_base_type>(GetTypeInfo<m_base_type>::VARIANT_TYPE)
+ REGISTER_INDEXED_MEMBER(String);
REGISTER_INDEXED_MEMBER(Vector2);
REGISTER_INDEXED_MEMBER(Vector2i);
REGISTER_INDEXED_MEMBER(Vector3);
@@ -1737,11 +1824,15 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
return Variant();
}
-Variant Variant::duplicate(bool deep) const {
+Variant Variant::duplicate(bool p_deep) const {
+ return recursive_duplicate(p_deep, 0);
+}
+
+Variant Variant::recursive_duplicate(bool p_deep, int recursion_count) const {
switch (type) {
case OBJECT: {
/* breaks stuff :(
- if (deep && !_get_obj().ref.is_null()) {
+ if (p_deep && !_get_obj().ref.is_null()) {
Ref<Resource> resource = _get_obj().ref;
if (resource.is_valid()) {
return resource->duplicate(true);
@@ -1751,9 +1842,9 @@ Variant Variant::duplicate(bool deep) const {
return *this;
} break;
case DICTIONARY:
- return operator Dictionary().duplicate(deep);
+ return operator Dictionary().recursive_duplicate(p_deep, recursion_count);
case ARRAY:
- return operator Array().duplicate(deep);
+ return operator Array().recursive_duplicate(p_deep, recursion_count);
case PACKED_BYTE_ARRAY:
return operator Vector<uint8_t>().duplicate();
case PACKED_INT32_ARRAY:
@@ -2029,7 +2120,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
}
return;
case BASIS: {
- r_dst = Transform3D(*a._data._basis).interpolate_with(Transform3D(*b._data._basis), c).basis;
+ r_dst = a._data._basis->lerp(*b._data._basis, c);
}
return;
case TRANSFORM3D: {
diff --git a/core/variant/variant_setget.h b/core/variant/variant_setget.h
index dbf24ab3e3..28277fa5d0 100644
--- a/core/variant/variant_setget.h
+++ b/core/variant/variant_setget.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 232054d0ca..3fd8eb5474 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -151,10 +151,10 @@ struct VariantUtilityFunctions {
r_error.error = Callable::CallError::CALL_OK;
switch (x.get_type()) {
case Variant::INT: {
- return SGN(VariantInternalAccessor<int64_t>::get(&x));
+ return SIGN(VariantInternalAccessor<int64_t>::get(&x));
} break;
case Variant::FLOAT: {
- return SGN(VariantInternalAccessor<double>::get(&x));
+ return SIGN(VariantInternalAccessor<double>::get(&x));
} break;
case Variant::VECTOR2: {
return VariantInternalAccessor<Vector2>::get(&x).sign();
@@ -176,11 +176,11 @@ struct VariantUtilityFunctions {
}
static inline double signf(double x) {
- return SGN(x);
+ return SIGN(x);
}
static inline int64_t signi(int64_t x) {
- return SGN(x);
+ return SIGN(x);
}
static inline double pow(double x, double y) {
@@ -275,6 +275,10 @@ struct VariantUtilityFunctions {
return Math::wrapf(value, min, max);
}
+ static inline double pingpong(double value, double length) {
+ return Math::pingpong(value, length);
+ }
+
static inline Variant max(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 2) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
@@ -399,6 +403,10 @@ struct VariantUtilityFunctions {
return Math::randf();
}
+ static inline double randfn(double mean, double deviation) {
+ return Math::randfn(mean, deviation);
+ }
+
static inline int64_t randi_range(int64_t from, int64_t to) {
return Math::random((int32_t)from, (int32_t)to);
}
@@ -487,10 +495,6 @@ struct VariantUtilityFunctions {
}
static inline void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- if (p_arg_count < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
- }
String str;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
@@ -506,11 +510,29 @@ struct VariantUtilityFunctions {
r_error.error = Callable::CallError::CALL_OK;
}
- static inline void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- if (p_arg_count < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
+ static inline void print_verbose(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ // No need to use `print_verbose()` as this call already only happens
+ // when verbose mode is enabled. This avoids performing string argument concatenation
+ // when not needed.
+ print_line(str);
}
+
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
String str;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
@@ -527,10 +549,6 @@ struct VariantUtilityFunctions {
}
static inline void printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- if (p_arg_count < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
- }
String str;
for (int i = 0; i < p_arg_count; i++) {
if (i) {
@@ -544,10 +562,6 @@ struct VariantUtilityFunctions {
}
static inline void prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- if (p_arg_count < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
- }
String str;
for (int i = 0; i < p_arg_count; i++) {
if (i) {
@@ -561,10 +575,6 @@ struct VariantUtilityFunctions {
}
static inline void printraw(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- if (p_arg_count < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
- }
String str;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
@@ -1224,6 +1234,7 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(clampf, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(nearest_po2, sarray("value"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(pingpong, sarray("value", "length"), Variant::UTILITY_FUNC_TYPE_MATH);
// Random
@@ -1232,6 +1243,7 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(randf, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM);
FUNCBINDR(randi_range, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_RANDOM);
FUNCBINDR(randf_range, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_RANDOM);
+ FUNCBINDR(randfn, sarray("mean", "deviation"), Variant::UTILITY_FUNC_TYPE_RANDOM);
FUNCBIND(seed, sarray("base"), Variant::UTILITY_FUNC_TYPE_RANDOM);
FUNCBINDR(rand_from_seed, sarray("seed"), Variant::UTILITY_FUNC_TYPE_RANDOM);
@@ -1246,6 +1258,7 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDVARARGV(printt, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGV(prints, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGV(printraw, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDVARARGV(print_verbose, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGV(push_error, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGV(push_warning, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
@@ -1330,6 +1343,28 @@ Variant::UtilityFunctionType Variant::get_utility_function_type(const StringName
return bfi->type;
}
+MethodInfo Variant::get_utility_function_info(const StringName &p_name) {
+ MethodInfo info;
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (bfi) {
+ info.name = p_name;
+ if (bfi->returns_value && bfi->return_type == Variant::NIL) {
+ info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ }
+ info.return_val.type = bfi->return_type;
+ if (bfi->is_vararg) {
+ info.flags |= METHOD_FLAG_VARARG;
+ }
+ for (int i = 0; i < bfi->argnames.size(); ++i) {
+ PropertyInfo arg;
+ arg.type = bfi->get_arg_type(i);
+ arg.name = bfi->argnames[i];
+ info.arguments.push_back(arg);
+ }
+ }
+ return info;
+}
+
int Variant::get_utility_function_argument_count(const StringName &p_name) {
const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
if (!bfi) {
diff --git a/core/version.h b/core/version.h
index 2a4fa9cfd4..c718d0f4d7 100644
--- a/core/version.h
+++ b/core/version.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */