diff options
Diffstat (limited to 'core')
97 files changed, 3873 insertions, 2835 deletions
diff --git a/core/config/engine.cpp b/core/config/engine.cpp index 21e910be5b..7aa5f4d06d 100644 --- a/core/config/engine.cpp +++ b/core/config/engine.cpp @@ -48,6 +48,15 @@ int Engine::get_physics_ticks_per_second() const { return ips; } +void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) { + ERR_FAIL_COND_MSG(p_max_physics_steps <= 0, "Maximum number of physics steps per frame must be greater than 0."); + max_physics_steps_per_frame = p_max_physics_steps; +} + +int Engine::get_max_physics_steps_per_frame() const { + return max_physics_steps_per_frame; +} + void Engine::set_physics_jitter_fix(double p_threshold) { if (p_threshold < 0) { p_threshold = 0; diff --git a/core/config/engine.h b/core/config/engine.h index 21517e46b7..1b179c5727 100644 --- a/core/config/engine.h +++ b/core/config/engine.h @@ -63,6 +63,7 @@ private: int _max_fps = 0; double _time_scale = 1.0; uint64_t _physics_frames = 0; + int max_physics_steps_per_frame = 8; double _physics_interpolation_fraction = 0.0f; bool abort_on_gpu_errors = false; bool use_validation_layers = false; @@ -93,6 +94,9 @@ public: virtual void set_physics_ticks_per_second(int p_ips); virtual int get_physics_ticks_per_second() const; + virtual void set_max_physics_steps_per_frame(int p_max_physics_steps); + virtual int get_max_physics_steps_per_frame() const; + void set_physics_jitter_fix(double p_threshold); double get_physics_jitter_fix() const; diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 4d2006d42a..385cd2b2fd 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -82,7 +82,7 @@ String ProjectSettings::get_imported_files_path() const { // 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(); + PackedStringArray features; features.append(VERSION_BRANCH); #ifdef REAL_T_IS_DOUBLE features.append("Double Precision"); @@ -115,7 +115,7 @@ const PackedStringArray ProjectSettings::_get_supported_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 unsupported_features; 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])) { @@ -1124,8 +1124,12 @@ void ProjectSettings::set_setting(const String &p_setting, const Variant &p_valu set(p_setting, p_value); } -Variant ProjectSettings::get_setting(const String &p_setting) const { - return get(p_setting); +Variant ProjectSettings::get_setting(const String &p_setting, const Variant &p_default_value) const { + if (has_setting(p_setting)) { + return get(p_setting); + } else { + return p_default_value; + } } bool ProjectSettings::has_custom_feature(const String &p_feature) const { @@ -1158,7 +1162,7 @@ ProjectSettings::AutoloadInfo ProjectSettings::get_autoload(const StringName &p_ void ProjectSettings::_bind_methods() { ClassDB::bind_method(D_METHOD("has_setting", "name"), &ProjectSettings::has_setting); ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &ProjectSettings::set_setting); - ClassDB::bind_method(D_METHOD("get_setting", "name"), &ProjectSettings::get_setting); + ClassDB::bind_method(D_METHOD("get_setting", "name", "default_value"), &ProjectSettings::get_setting, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("set_order", "name", "position"), &ProjectSettings::set_order); ClassDB::bind_method(D_METHOD("get_order", "name"), &ProjectSettings::get_order); ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &ProjectSettings::set_initial_value); @@ -1200,6 +1204,7 @@ ProjectSettings::ProjectSettings() { // Initialization of engine variables should be done in the setup() method, // so that the values can be overridden from project.godot or project.binary. + CRASH_COND_MSG(singleton != nullptr, "Instantiating a new ProjectSettings singleton is not supported."); singleton = this; GLOBAL_DEF_BASIC("application/config/name", ""); @@ -1246,12 +1251,12 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF_BASIC("audio/buses/default_bus_layout", "res://default_bus_layout.tres"); custom_prop_info["audio/buses/default_bus_layout"] = PropertyInfo(Variant::STRING, "audio/buses/default_bus_layout", PROPERTY_HINT_FILE, "*.tres"); - GLOBAL_DEF_RST("audio/general/2d_panning_strength", 1.0f); - custom_prop_info["audio/general/2d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/2d_panning_strength", PROPERTY_HINT_RANGE, "0,4,0.01"); - GLOBAL_DEF_RST("audio/general/3d_panning_strength", 1.0f); - custom_prop_info["audio/general/3d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/3d_panning_strength", PROPERTY_HINT_RANGE, "0,4,0.01"); + GLOBAL_DEF_RST("audio/general/2d_panning_strength", 0.5f); + custom_prop_info["audio/general/2d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/2d_panning_strength", PROPERTY_HINT_RANGE, "0,2,0.01"); + GLOBAL_DEF_RST("audio/general/3d_panning_strength", 0.5f); + custom_prop_info["audio/general/3d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/3d_panning_strength", PROPERTY_HINT_RANGE, "0,2,0.01"); - PackedStringArray extensions = PackedStringArray(); + PackedStringArray extensions; extensions.push_back("gd"); if (Engine::get_singleton()->has_singleton("GodotSharp")) { extensions.push_back("cs"); @@ -1276,7 +1281,6 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("physics/2d/run_on_separate_thread", false); GLOBAL_DEF("physics/3d/run_on_separate_thread", false); - GLOBAL_DEF("debug/disable_touch", false); GLOBAL_DEF("debug/settings/profiler/max_functions", 16384); custom_prop_info["debug/settings/profiler/max_functions"] = PropertyInfo(Variant::INT, "debug/settings/profiler/max_functions", PROPERTY_HINT_RANGE, "128,65535,1"); diff --git a/core/config/project_settings.h b/core/config/project_settings.h index 960dfe0395..2ffbda9cea 100644 --- a/core/config/project_settings.h +++ b/core/config/project_settings.h @@ -141,7 +141,7 @@ public: 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; + Variant get_setting(const String &p_setting, const Variant &p_default_value = Variant()) const; bool has_setting(String p_var) const; String localize_path(const String &p_path) const; diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 87b36f7a21..9503bd2575 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -236,8 +236,12 @@ Vector<String> OS::get_system_fonts() const { return ::OS::get_singleton()->get_system_fonts(); } -String OS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const { - return ::OS::get_singleton()->get_system_font_path(p_font_name, p_bold, p_italic); +String OS::get_system_font_path(const String &p_font_name, int p_weight, int p_stretch, bool p_italic) const { + return ::OS::get_singleton()->get_system_font_path(p_font_name, p_weight, p_stretch, p_italic); +} + +Vector<String> OS::get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale, const String &p_script, int p_weight, int p_stretch, bool p_italic) const { + return ::OS::get_singleton()->get_system_font_path_for_text(p_font_name, p_text, p_locale, p_script, p_weight, p_stretch, p_italic); } String OS::get_executable_path() const { @@ -532,7 +536,8 @@ void OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_processor_name"), &OS::get_processor_name); ClassDB::bind_method(D_METHOD("get_system_fonts"), &OS::get_system_fonts); - ClassDB::bind_method(D_METHOD("get_system_font_path", "font_name", "bold", "italic"), &OS::get_system_font_path, DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_system_font_path", "font_name", "weight", "stretch", "italic"), &OS::get_system_font_path, DEFVAL(400), DEFVAL(100), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_system_font_path_for_text", "font_name", "text", "locale", "script", "weight", "stretch", "italic"), &OS::get_system_font_path_for_text, DEFVAL(String()), DEFVAL(String()), DEFVAL(400), DEFVAL(100), DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path); ClassDB::bind_method(D_METHOD("read_string_from_stdin", "block"), &OS::read_string_from_stdin, DEFVAL(true)); ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL(Array()), DEFVAL(false), DEFVAL(false)); @@ -1477,6 +1482,14 @@ int Engine::get_physics_ticks_per_second() const { return ::Engine::get_singleton()->get_physics_ticks_per_second(); } +void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) { + ::Engine::get_singleton()->set_max_physics_steps_per_frame(p_max_physics_steps); +} + +int Engine::get_max_physics_steps_per_frame() const { + return ::Engine::get_singleton()->get_max_physics_steps_per_frame(); +} + void Engine::set_physics_jitter_fix(double p_threshold) { ::Engine::get_singleton()->set_physics_jitter_fix(p_threshold); } @@ -1628,6 +1641,8 @@ bool Engine::is_printing_error_messages() const { void Engine::_bind_methods() { ClassDB::bind_method(D_METHOD("set_physics_ticks_per_second", "physics_ticks_per_second"), &Engine::set_physics_ticks_per_second); ClassDB::bind_method(D_METHOD("get_physics_ticks_per_second"), &Engine::get_physics_ticks_per_second); + ClassDB::bind_method(D_METHOD("set_max_physics_steps_per_frame", "max_physics_steps"), &Engine::set_max_physics_steps_per_frame); + ClassDB::bind_method(D_METHOD("get_max_physics_steps_per_frame"), &Engine::get_max_physics_steps_per_frame); ClassDB::bind_method(D_METHOD("set_physics_jitter_fix", "physics_jitter_fix"), &Engine::set_physics_jitter_fix); ClassDB::bind_method(D_METHOD("get_physics_jitter_fix"), &Engine::get_physics_jitter_fix); ClassDB::bind_method(D_METHOD("get_physics_interpolation_fraction"), &Engine::get_physics_interpolation_fraction); @@ -1675,6 +1690,7 @@ void Engine::_bind_methods() { 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, "max_physics_steps_per_frame"), "set_max_physics_steps_per_frame", "get_max_physics_steps_per_frame"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_fps"), "set_max_fps", "get_max_fps"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_scale"), "set_time_scale", "get_time_scale"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "physics_jitter_fix"), "set_physics_jitter_fix", "get_physics_jitter_fix"); diff --git a/core/core_bind.h b/core/core_bind.h index 784f3e63b1..c863a8094c 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -170,7 +170,8 @@ public: void crash(const String &p_message); Vector<String> get_system_fonts() const; - String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const; + String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const; + Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const; String get_executable_path() const; String read_string_from_stdin(bool p_block = true); int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false, bool p_open_console = false); @@ -486,6 +487,9 @@ public: void set_physics_ticks_per_second(int p_ips); int get_physics_ticks_per_second() const; + void set_max_physics_steps_per_frame(int p_max_physics_steps); + int get_max_physics_steps_per_frame() const; + void set_physics_jitter_fix(double p_threshold); double get_physics_jitter_fix() const; double get_physics_interpolation_fraction() const; diff --git a/core/core_constants.cpp b/core/core_constants.cpp index 0e8532a327..c72b6212d7 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -153,6 +153,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TOP_TO); BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_CENTER_TO); + BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_BASELINE_TO); BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_BOTTOM_TO); BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TO_TOP); @@ -595,8 +596,6 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXPRESSION); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PLACEHOLDER_TEXT); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_COLOR_NO_ALPHA); - BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSY); - BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_OBJECT_ID); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_TYPE_STRING); @@ -639,7 +638,6 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NULL); - BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_ANIMATE_AS_TRIGGER); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CLASS_IS_ENUM); diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 23ee977df4..a2e3fab82c 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -39,89 +39,6 @@ #include "core/object/script_language.h" #include "core/os/os.h" -class RemoteDebugger::MultiplayerProfiler : public EngineProfiler { - struct BandwidthFrame { - uint32_t timestamp; - int packet_size; - }; - - int bandwidth_in_ptr = 0; - Vector<BandwidthFrame> bandwidth_in; - int bandwidth_out_ptr = 0; - Vector<BandwidthFrame> bandwidth_out; - uint64_t last_bandwidth_time = 0; - - int bandwidth_usage(const Vector<BandwidthFrame> &p_buffer, int p_pointer) { - ERR_FAIL_COND_V(p_buffer.size() == 0, 0); - int total_bandwidth = 0; - - 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(); - - while (i != p_pointer && p_buffer[i].packet_size > 0) { - if (p_buffer[i].timestamp < final_timestamp) { - return total_bandwidth; - } - total_bandwidth += p_buffer[i].packet_size; - i = (i + p_buffer.size() - 1) % p_buffer.size(); - } - - ERR_FAIL_COND_V_MSG(i == p_pointer, total_bandwidth, "Reached the end of the bandwidth profiler buffer, values might be inaccurate."); - return total_bandwidth; - } - -public: - void toggle(bool p_enable, const Array &p_opts) { - if (!p_enable) { - bandwidth_in.clear(); - bandwidth_out.clear(); - } else { - bandwidth_in_ptr = 0; - bandwidth_in.resize(16384); // ~128kB - for (int i = 0; i < bandwidth_in.size(); ++i) { - bandwidth_in.write[i].packet_size = -1; - } - bandwidth_out_ptr = 0; - bandwidth_out.resize(16384); // ~128kB - for (int i = 0; i < bandwidth_out.size(); ++i) { - bandwidth_out.write[i].packet_size = -1; - } - } - } - - void add(const Array &p_data) { - ERR_FAIL_COND(p_data.size() < 3); - const String inout = p_data[0]; - int time = p_data[1]; - int size = p_data[2]; - if (inout == "in") { - bandwidth_in.write[bandwidth_in_ptr].timestamp = time; - bandwidth_in.write[bandwidth_in_ptr].packet_size = size; - bandwidth_in_ptr = (bandwidth_in_ptr + 1) % bandwidth_in.size(); - } else if (inout == "out") { - bandwidth_out.write[bandwidth_out_ptr].timestamp = time; - bandwidth_out.write[bandwidth_out_ptr].packet_size = size; - bandwidth_out_ptr = (bandwidth_out_ptr + 1) % bandwidth_out.size(); - } - } - - void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) { - uint64_t pt = OS::get_singleton()->get_ticks_msec(); - if (pt - last_bandwidth_time > 200) { - last_bandwidth_time = pt; - int incoming_bandwidth = bandwidth_usage(bandwidth_in, bandwidth_in_ptr); - int outgoing_bandwidth = bandwidth_usage(bandwidth_out, bandwidth_out_ptr); - - Array arr; - arr.push_back(incoming_bandwidth); - arr.push_back(outgoing_bandwidth); - EngineDebugger::get_singleton()->send_message("multiplayer:bandwidth", arr); - } - } -}; - class RemoteDebugger::PerformanceProfiler : public EngineProfiler { Object *performance = nullptr; int last_perf_time = 0; @@ -659,10 +576,6 @@ RemoteDebugger::RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer) { max_errors_per_second = GLOBAL_GET("network/limits/debugger/max_errors_per_second"); max_warnings_per_second = GLOBAL_GET("network/limits/debugger/max_warnings_per_second"); - // Multiplayer Profiler - multiplayer_profiler.instantiate(); - multiplayer_profiler->bind("multiplayer"); - // Performance Profiler Object *perf = Engine::get_singleton()->get_singleton_object("Performance"); if (perf) { diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h index fe4bbe86ea..944229d361 100644 --- a/core/debugger/remote_debugger.h +++ b/core/debugger/remote_debugger.h @@ -50,10 +50,8 @@ public: private: typedef DebuggerMarshalls::OutputError ErrorMessage; - class MultiplayerProfiler; class PerformanceProfiler; - Ref<MultiplayerProfiler> multiplayer_profiler; Ref<PerformanceProfiler> performance_profiler; Ref<RemoteDebuggerPeer> peer; diff --git a/core/extension/SCsub b/core/extension/SCsub index a8f68a1533..361ce43a2c 100644 --- a/core/extension/SCsub +++ b/core/extension/SCsub @@ -8,8 +8,8 @@ from platform_methods import run_in_subprocess env.CommandNoCache(["ext_wrappers.gen.inc"], "make_wrappers.py", run_in_subprocess(make_wrappers.run)) env.CommandNoCache( - "gdnative_interface_dump.gen.h", - ["gdnative_interface.h", "make_interface_dumper.py"], + "gdextension_interface_dump.gen.h", + ["gdextension_interface.h", "make_interface_dumper.py"], run_in_subprocess(make_interface_dumper.run), ) diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index a2c507e350..a0e3778dcc 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -82,7 +82,7 @@ static String get_property_info_type_name(const PropertyInfo &p_info) { return get_builtin_or_variant_type_name(p_info.type); } -Dictionary NativeExtensionAPIDump::generate_extension_api() { +Dictionary GDExtensionAPIDump::generate_extension_api() { Dictionary api_dump; { @@ -177,8 +177,8 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { }; // Validate sizes at compile time for the current build configuration. - static_assert(type_size_array[Variant::BOOL][sizeof(void *)] == sizeof(GDNativeBool), "Size of bool mismatch"); - static_assert(type_size_array[Variant::INT][sizeof(void *)] == sizeof(GDNativeInt), "Size of int mismatch"); + static_assert(type_size_array[Variant::BOOL][sizeof(void *)] == sizeof(GDExtensionBool), "Size of bool mismatch"); + static_assert(type_size_array[Variant::INT][sizeof(void *)] == sizeof(GDExtensionInt), "Size of int mismatch"); static_assert(type_size_array[Variant::FLOAT][sizeof(void *)] == sizeof(double), "Size of float mismatch"); static_assert(type_size_array[Variant::STRING][sizeof(void *)] == sizeof(String), "Size of String mismatch"); static_assert(type_size_array[Variant::VECTOR2][sizeof(void *)] == sizeof(Vector2), "Size of Vector2 mismatch"); @@ -252,63 +252,140 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { } { - // Member offsets sizes. + // Member offsets, meta types and sizes. + +#define REAL_MEMBER_OFFSET(type, member) \ + { \ + type, \ + member, \ + "float", \ + sizeof(float), \ + "float", \ + sizeof(float), \ + "double", \ + sizeof(double), \ + "double", \ + sizeof(double), \ + } + +#define INT32_MEMBER_OFFSET(type, member) \ + { \ + type, \ + member, \ + "int32", \ + sizeof(int32_t), \ + "int32", \ + sizeof(int32_t), \ + "int32", \ + sizeof(int32_t), \ + "int32", \ + sizeof(int32_t), \ + } + +#define INT32_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \ + { \ + type, \ + member, \ + member_type, \ + sizeof(int32_t) * member_elems, \ + member_type, \ + sizeof(int32_t) * member_elems, \ + member_type, \ + sizeof(int32_t) * member_elems, \ + member_type, \ + sizeof(int32_t) * member_elems, \ + } + +#define REAL_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \ + { \ + type, \ + member, \ + member_type, \ + sizeof(float) * member_elems, \ + member_type, \ + sizeof(float) * member_elems, \ + member_type, \ + sizeof(double) * member_elems, \ + member_type, \ + sizeof(double) * member_elems, \ + } + struct { Variant::Type type; const char *member; - uint32_t offset_32_bits_real_float; - uint32_t offset_64_bits_real_float; - uint32_t offset_32_bits_real_double; - uint32_t offset_64_bits_real_double; + const char *member_meta_32_bits_real_float; + const uint32_t member_size_32_bits_real_float; + const char *member_meta_64_bits_real_float; + const uint32_t member_size_64_bits_real_float; + const char *member_meta_32_bits_real_double; + const uint32_t member_size_32_bits_real_double; + const char *member_meta_64_bits_real_double; + const uint32_t member_size_64_bits_real_double; } member_offset_array[] = { - { Variant::VECTOR2, "x", 0, 0, 0, 0 }, - { Variant::VECTOR2, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) }, - { Variant::VECTOR2I, "x", 0, 0, 0, 0 }, - { Variant::VECTOR2I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) }, - { Variant::RECT2, "position", 0, 0, 0, 0 }, - { Variant::RECT2, "size", 2 * sizeof(Vector2), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, - { Variant::RECT2I, "position", 0, 0, 0, 0 }, - { Variant::RECT2I, "size", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) }, - { Variant::VECTOR3, "x", 0, 0, 0, 0 }, - { Variant::VECTOR3, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) }, - { Variant::VECTOR3, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, - { Variant::VECTOR3I, "x", 0, 0, 0, 0 }, - { Variant::VECTOR3I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) }, - { Variant::VECTOR3I, "z", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) }, - { Variant::TRANSFORM2D, "x", 0, 0, 0, 0 }, - { Variant::TRANSFORM2D, "y", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, - { Variant::TRANSFORM2D, "origin", 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) }, - { Variant::VECTOR4, "x", 0, 0, 0, 0 }, - { Variant::VECTOR4, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) }, - { Variant::VECTOR4, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, - { Variant::VECTOR4, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) }, - { Variant::VECTOR4I, "x", 0, 0, 0, 0 }, - { Variant::VECTOR4I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) }, - { Variant::VECTOR4I, "z", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) }, - { Variant::VECTOR4I, "w", 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t) }, - { Variant::PLANE, "normal", 0, 0, 0, 0 }, - { Variant::PLANE, "d", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) }, - { Variant::QUATERNION, "x", 0, 0, 0, 0 }, - { Variant::QUATERNION, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) }, - { Variant::QUATERNION, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, - { Variant::QUATERNION, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) }, - { Variant::AABB, "position", 0, 0, 0, 0 }, - { Variant::AABB, "size", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) }, - // Remember that basis vectors are flipped! - { Variant::BASIS, "x", 0, 0, 0, 0 }, - { Variant::BASIS, "y", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) }, - { Variant::BASIS, "z", vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(double), vec3_elems * 2 * sizeof(double) }, - { Variant::TRANSFORM3D, "basis", 0, 0, 0, 0 }, - { Variant::TRANSFORM3D, "origin", (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) }, - { Variant::PROJECTION, "x", 0, 0, 0, 0 }, - { Variant::PROJECTION, "y", vec4_elems * sizeof(float), vec4_elems * sizeof(float), vec4_elems * sizeof(double), vec4_elems * sizeof(double) }, - { Variant::PROJECTION, "z", vec4_elems * 2 * sizeof(float), vec4_elems * 2 * sizeof(float), vec4_elems * 2 * sizeof(double), vec4_elems * 2 * sizeof(double) }, - { Variant::PROJECTION, "w", vec4_elems * 3 * sizeof(float), vec4_elems * 3 * sizeof(float), vec4_elems * 3 * sizeof(double), vec4_elems * 3 * sizeof(double) }, - { Variant::COLOR, "r", 0, 0, 0, 0 }, - { Variant::COLOR, "g", sizeof(float), sizeof(float), sizeof(float), sizeof(float) }, - { Variant::COLOR, "b", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float) }, - { Variant::COLOR, "a", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float) }, - { Variant::NIL, nullptr, 0, 0, 0, 0 }, + // Vector2 + REAL_MEMBER_OFFSET(Variant::VECTOR2, "x"), + REAL_MEMBER_OFFSET(Variant::VECTOR2, "y"), + // Vector2i + INT32_MEMBER_OFFSET(Variant::VECTOR2I, "x"), + INT32_MEMBER_OFFSET(Variant::VECTOR2I, "y"), + // Rect2 + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2, "position", "Vector2", 2), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2, "size", "Vector2", 2), + // Rect2i + INT32_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2I, "position", "Vector2i", 2), + INT32_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2I, "size", "Vector2i", 2), + // Vector3 + REAL_MEMBER_OFFSET(Variant::VECTOR3, "x"), + REAL_MEMBER_OFFSET(Variant::VECTOR3, "y"), + REAL_MEMBER_OFFSET(Variant::VECTOR3, "z"), + // Vector3i + INT32_MEMBER_OFFSET(Variant::VECTOR3I, "x"), + INT32_MEMBER_OFFSET(Variant::VECTOR3I, "y"), + INT32_MEMBER_OFFSET(Variant::VECTOR3I, "z"), + // Transform2D + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "x", "Vector2", 2), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "y", "Vector2", 2), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "origin", "Vector2", 2), + // Vector4 + REAL_MEMBER_OFFSET(Variant::VECTOR4, "x"), + REAL_MEMBER_OFFSET(Variant::VECTOR4, "y"), + REAL_MEMBER_OFFSET(Variant::VECTOR4, "z"), + REAL_MEMBER_OFFSET(Variant::VECTOR4, "w"), + // Vector4i + INT32_MEMBER_OFFSET(Variant::VECTOR4I, "x"), + INT32_MEMBER_OFFSET(Variant::VECTOR4I, "y"), + INT32_MEMBER_OFFSET(Variant::VECTOR4I, "z"), + INT32_MEMBER_OFFSET(Variant::VECTOR4I, "w"), + // Plane + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PLANE, "normal", "Vector3", vec3_elems), + REAL_MEMBER_OFFSET(Variant::PLANE, "d"), + // Quaternion + REAL_MEMBER_OFFSET(Variant::QUATERNION, "x"), + REAL_MEMBER_OFFSET(Variant::QUATERNION, "y"), + REAL_MEMBER_OFFSET(Variant::QUATERNION, "z"), + REAL_MEMBER_OFFSET(Variant::QUATERNION, "w"), + // AABB + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::AABB, "position", "Vector3", vec3_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::AABB, "size", "Vector3", vec3_elems), + // Basis (remember that basis vectors are flipped!) + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "x", "Vector3", vec3_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "y", "Vector3", vec3_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "z", "Vector3", vec3_elems), + // Transform3D + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM3D, "basis", "Basis", vec3_elems * 3), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM3D, "origin", "Vector3", vec3_elems), + // Projection + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "x", "Vector4", vec4_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "y", "Vector4", vec4_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "z", "Vector4", vec4_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "w", "Vector4", vec4_elems), + // Color (always composed of 4bytes floats) + { Variant::COLOR, "r", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) }, + { Variant::COLOR, "g", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) }, + { Variant::COLOR, "b", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) }, + { Variant::COLOR, "a", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) }, + // End marker, must stay last + { Variant::NIL, nullptr, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0 }, }; Array core_type_member_offsets; @@ -319,15 +396,16 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { Array type_offsets; uint32_t idx = 0; - Variant::Type last_type = Variant::NIL; + Variant::Type previous_type = Variant::NIL; Dictionary d2; Array members; + uint32_t offset = 0; while (true) { Variant::Type t = member_offset_array[idx].type; - if (t != last_type) { - if (last_type != Variant::NIL) { + if (t != previous_type) { + if (previous_type != Variant::NIL) { d2["members"] = members; type_offsets.push_back(d2); } @@ -338,27 +416,35 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t); d2 = Dictionary(); members = Array(); + offset = 0; d2["name"] = name; - last_type = t; + previous_type = t; } Dictionary d3; - uint32_t offset = 0; + const char *member_meta = nullptr; + uint32_t member_size = 0; switch (i) { case 0: - offset = member_offset_array[idx].offset_32_bits_real_float; + member_meta = member_offset_array[idx].member_meta_32_bits_real_float; + member_size = member_offset_array[idx].member_size_32_bits_real_float; break; case 1: - offset = member_offset_array[idx].offset_64_bits_real_float; + member_meta = member_offset_array[idx].member_meta_64_bits_real_float; + member_size = member_offset_array[idx].member_size_64_bits_real_float; break; case 2: - offset = member_offset_array[idx].offset_32_bits_real_double; + member_meta = member_offset_array[idx].member_meta_32_bits_real_double; + member_size = member_offset_array[idx].member_size_32_bits_real_double; break; case 3: - offset = member_offset_array[idx].offset_64_bits_real_double; + member_meta = member_offset_array[idx].member_meta_64_bits_real_double; + member_size = member_offset_array[idx].member_size_64_bits_real_double; break; } d3["member"] = member_offset_array[idx].member; d3["offset"] = offset; + d3["meta"] = member_meta; + offset += member_size; members.push_back(d3); idx++; } @@ -871,9 +957,18 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { Dictionary d2; d2["type"] = get_property_info_type_name(F); d2["name"] = String(property_name); - d2["setter"] = ClassDB::get_property_setter(class_name, F.name); - d2["getter"] = ClassDB::get_property_getter(class_name, F.name); - d2["index"] = ClassDB::get_property_index(class_name, F.name); + StringName setter = ClassDB::get_property_setter(class_name, F.name); + if (!(setter == "")) { + d2["setter"] = setter; + } + StringName getter = ClassDB::get_property_getter(class_name, F.name); + if (!(getter == "")) { + d2["getter"] = getter; + } + int index = ClassDB::get_property_index(class_name, F.name); + if (index != -1) { + d2["index"] = index; + } properties.push_back(d2); } @@ -934,7 +1029,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { return api_dump; } -void NativeExtensionAPIDump::generate_extension_json_file(const String &p_path) { +void GDExtensionAPIDump::generate_extension_json_file(const String &p_path) { Dictionary api = generate_extension_api(); Ref<JSON> json; json.instantiate(); diff --git a/core/extension/extension_api_dump.h b/core/extension/extension_api_dump.h index 1bc455ea67..e488d8a086 100644 --- a/core/extension/extension_api_dump.h +++ b/core/extension/extension_api_dump.h @@ -31,11 +31,11 @@ #ifndef EXTENSION_API_DUMP_H #define EXTENSION_API_DUMP_H -#include "core/extension/native_extension.h" +#include "core/extension/gdextension.h" #ifdef TOOLS_ENABLED -class NativeExtensionAPIDump { +class GDExtensionAPIDump { public: static Dictionary generate_extension_api(); static void generate_extension_json_file(const String &p_path); diff --git a/core/extension/native_extension.cpp b/core/extension/gdextension.cpp index 8bbb72fd82..0c5c736efe 100644 --- a/core/extension/native_extension.cpp +++ b/core/extension/gdextension.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* native_extension.cpp */ +/* gdextension.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,20 +28,125 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "native_extension.h" +#include "gdextension.h" #include "core/config/project_settings.h" -#include "core/io/config_file.h" +#include "core/io/dir_access.h" #include "core/object/class_db.h" #include "core/object/method_bind.h" #include "core/os/os.h" -String NativeExtension::get_extension_list_config_file() { +String GDExtension::get_extension_list_config_file() { return ProjectSettings::get_singleton()->get_project_data_path().path_join("extension_list.cfg"); } -class NativeExtensionMethodBind : public MethodBind { - GDNativeExtensionClassMethodCall call_func; - GDNativeExtensionClassMethodPtrCall ptrcall_func; +String GDExtension::find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags) { + // First, check the explicit libraries. + if (p_config->has_section("libraries")) { + List<String> libraries; + p_config->get_section_keys("libraries", &libraries); + + // Iterate the libraries, finding the best matching tags. + String best_library_path; + Vector<String> best_library_tags; + for (const String &E : libraries) { + Vector<String> tags = E.split("."); + bool all_tags_met = true; + for (int i = 0; i < tags.size(); i++) { + String tag = tags[i].strip_edges(); + if (!p_has_feature(tag)) { + all_tags_met = false; + break; + } + } + + if (all_tags_met && tags.size() > best_library_tags.size()) { + best_library_path = p_config->get_value("libraries", E); + best_library_tags = tags; + } + } + + if (!best_library_path.is_empty()) { + if (best_library_path.is_relative_path()) { + best_library_path = p_path.get_base_dir().path_join(best_library_path); + } + if (r_tags != nullptr) { + r_tags->append_array(best_library_tags); + } + return best_library_path; + } + } + + // Second, try to autodetect + String autodetect_library_prefix; + if (p_config->has_section_key("configuration", "autodetect_library_prefix")) { + autodetect_library_prefix = p_config->get_value("configuration", "autodetect_library_prefix"); + } + if (!autodetect_library_prefix.is_empty()) { + String autodetect_path = autodetect_library_prefix; + if (autodetect_path.is_relative_path()) { + autodetect_path = p_path.get_base_dir().path_join(autodetect_path); + } + + // Find the folder and file parts of the prefix. + String folder; + String file_prefix; + if (DirAccess::dir_exists_absolute(autodetect_path)) { + folder = autodetect_path; + } else if (DirAccess::dir_exists_absolute(autodetect_path.get_base_dir())) { + folder = autodetect_path.get_base_dir(); + file_prefix = autodetect_path.get_file(); + } else { + ERR_FAIL_V_MSG(String(), vformat("Error in extension: %s. Could not find folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix)); + } + + // Open the folder. + Ref<DirAccess> dir = DirAccess::open(folder); + ERR_FAIL_COND_V_MSG(!dir.is_valid(), String(), vformat("Error in extension: %s. Could not open folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix)); + + // Iterate the files and check the prefixes, finding the best matching file. + String best_file; + Vector<String> best_file_tags; + dir->list_dir_begin(); + String file_name = dir->_get_next(); + while (file_name != "") { + if (!dir->current_is_dir() && file_name.begins_with(file_prefix)) { + // Check if the files matches all requested feature tags. + String tags_str = file_name.trim_prefix(file_prefix); + tags_str = tags_str.trim_suffix(tags_str.get_extension()); + + Vector<String> tags = tags_str.split(".", false); + bool all_tags_met = true; + for (int i = 0; i < tags.size(); i++) { + String tag = tags[i].strip_edges(); + if (!p_has_feature(tag)) { + all_tags_met = false; + break; + } + } + + // If all tags are found in the feature list, and we found more tags than before, use this file. + if (all_tags_met && tags.size() > best_file_tags.size()) { + best_file_tags = tags; + best_file = file_name; + } + } + file_name = dir->_get_next(); + } + + if (!best_file.is_empty()) { + String library_path = folder.path_join(best_file); + if (r_tags != nullptr) { + r_tags->append_array(best_file_tags); + } + return library_path; + } + } + return String(); +} + +class GDExtensionMethodBind : public MethodBind { + GDExtensionClassMethodCall call_func; + GDExtensionClassMethodPtrCall ptrcall_func; void *method_userdata; bool vararg; PropertyInfo return_value_info; @@ -76,27 +181,27 @@ public: } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { Variant ret; GDExtensionClassInstancePtr extension_instance = is_static() ? nullptr : p_object->_get_extension_instance(); - GDNativeCallError ce{ GDNATIVE_CALL_OK, 0, 0 }; - call_func(method_userdata, extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce); + GDExtensionCallError ce{ GDEXTENSION_CALL_OK, 0, 0 }; + call_func(method_userdata, extension_instance, reinterpret_cast<GDExtensionConstVariantPtr *>(p_args), p_arg_count, (GDExtensionVariantPtr)&ret, &ce); r_error.error = Callable::CallError::Error(ce.error); r_error.argument = ce.argument; r_error.expected = ce.expected; return ret; } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug."); GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance(); - ptrcall_func(method_userdata, extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret); + ptrcall_func(method_userdata, extension_instance, reinterpret_cast<GDExtensionConstTypePtr *>(p_args), (GDExtensionTypePtr)r_ret); } virtual bool is_vararg() const override { return false; } - explicit NativeExtensionMethodBind(const GDNativeExtensionClassMethodInfo *p_method_info) { + explicit GDExtensionMethodBind(const GDExtensionClassMethodInfo *p_method_info) { method_userdata = p_method_info->method_userdata; call_func = p_method_info->call_func; ptrcall_func = p_method_info->ptrcall_func; @@ -108,16 +213,16 @@ public: } for (uint32_t i = 0; i < p_method_info->argument_count; i++) { - arguments_info.push_back(PropertyInfo(p_method_info->aguments_info[i])); - arguments_metadata.push_back(GodotTypeInfo::Metadata(p_method_info->aguments_metadata[i])); + arguments_info.push_back(PropertyInfo(p_method_info->arguments_info[i])); + arguments_metadata.push_back(GodotTypeInfo::Metadata(p_method_info->arguments_metadata[i])); } set_hint_flags(p_method_info->method_flags); - vararg = p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_VARARG; + vararg = p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_VARARG; _set_returns(p_method_info->has_return_value); - _set_const(p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_CONST); - _set_static(p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_STATIC); + _set_const(p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_CONST); + _set_static(p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_STATIC); #ifdef DEBUG_METHODS_ENABLED _generate_argument_types(p_method_info->argument_count); #endif @@ -133,13 +238,13 @@ public: } }; -static GDNativeInterface gdnative_interface; +static GDExtensionInterface gdextension_interface; -void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); +void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); - StringName class_name = *reinterpret_cast<StringName *>(p_class_name); - StringName parent_class_name = *reinterpret_cast<StringName *>(p_parent_class_name); + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + StringName parent_class_name = *reinterpret_cast<const StringName *>(p_parent_class_name); ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier."); ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered."); @@ -163,35 +268,35 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr Extension *extension = &self->extension_classes[class_name]; if (parent_extension) { - extension->native_extension.parent = &parent_extension->native_extension; - parent_extension->native_extension.children.push_back(&extension->native_extension); + extension->gdextension.parent = &parent_extension->gdextension; + parent_extension->gdextension.children.push_back(&extension->gdextension); } - extension->native_extension.parent_class_name = parent_class_name; - extension->native_extension.class_name = class_name; - extension->native_extension.editor_class = self->level_initialized == INITIALIZATION_LEVEL_EDITOR; - extension->native_extension.is_virtual = p_extension_funcs->is_virtual; - extension->native_extension.is_abstract = p_extension_funcs->is_abstract; - extension->native_extension.set = p_extension_funcs->set_func; - extension->native_extension.get = p_extension_funcs->get_func; - extension->native_extension.get_property_list = p_extension_funcs->get_property_list_func; - extension->native_extension.free_property_list = p_extension_funcs->free_property_list_func; - extension->native_extension.property_can_revert = p_extension_funcs->property_can_revert_func; - extension->native_extension.property_get_revert = p_extension_funcs->property_get_revert_func; - extension->native_extension.notification = p_extension_funcs->notification_func; - extension->native_extension.to_string = p_extension_funcs->to_string_func; - extension->native_extension.reference = p_extension_funcs->reference_func; - 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.free_instance = p_extension_funcs->free_instance_func; - extension->native_extension.get_virtual = p_extension_funcs->get_virtual_func; - extension->native_extension.get_rid = p_extension_funcs->get_rid_func; - - ClassDB::register_extension_class(&extension->native_extension); + extension->gdextension.parent_class_name = parent_class_name; + extension->gdextension.class_name = class_name; + extension->gdextension.editor_class = self->level_initialized == INITIALIZATION_LEVEL_EDITOR; + extension->gdextension.is_virtual = p_extension_funcs->is_virtual; + extension->gdextension.is_abstract = p_extension_funcs->is_abstract; + extension->gdextension.set = p_extension_funcs->set_func; + extension->gdextension.get = p_extension_funcs->get_func; + extension->gdextension.get_property_list = p_extension_funcs->get_property_list_func; + extension->gdextension.free_property_list = p_extension_funcs->free_property_list_func; + extension->gdextension.property_can_revert = p_extension_funcs->property_can_revert_func; + extension->gdextension.property_get_revert = p_extension_funcs->property_get_revert_func; + extension->gdextension.notification = p_extension_funcs->notification_func; + extension->gdextension.to_string = p_extension_funcs->to_string_func; + extension->gdextension.reference = p_extension_funcs->reference_func; + extension->gdextension.unreference = p_extension_funcs->unreference_func; + extension->gdextension.class_userdata = p_extension_funcs->class_userdata; + extension->gdextension.create_instance = p_extension_funcs->create_instance_func; + extension->gdextension.free_instance = p_extension_funcs->free_instance_func; + extension->gdextension.get_virtual = p_extension_funcs->get_virtual_func; + extension->gdextension.get_rid = p_extension_funcs->get_rid_func; + + ClassDB::register_extension_class(&extension->gdextension); } -void NativeExtension::_register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); +void GDExtension::_register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); StringName method_name = *reinterpret_cast<const StringName *>(p_method_info->name); @@ -199,13 +304,13 @@ void NativeExtension::_register_extension_class_method(const GDNativeExtensionCl //Extension *extension = &self->extension_classes[class_name]; - NativeExtensionMethodBind *method = memnew(NativeExtensionMethodBind(p_method_info)); + GDExtensionMethodBind *method = memnew(GDExtensionMethodBind(p_method_info)); method->set_instance_class(class_name); ClassDB::bind_method_custom(class_name, method); } -void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); +void GDExtension::_register_extension_class_integer_constant(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); StringName enum_name = *reinterpret_cast<const StringName *>(p_enum_name); @@ -215,8 +320,8 @@ void NativeExtension::_register_extension_class_integer_constant(const GDNativeE ClassDB::bind_integer_constant(class_name, enum_name, constant_name, p_constant_value, p_is_bitfield); } -void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); +void GDExtension::_register_extension_class_property(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); StringName setter = *reinterpret_cast<const StringName *>(p_setter); @@ -230,8 +335,8 @@ void NativeExtension::_register_extension_class_property(const GDNativeExtension ClassDB::add_property(class_name, pinfo, setter, getter); } -void NativeExtension::_register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_group_name, const GDNativeStringPtr p_prefix) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); +void GDExtension::_register_extension_class_property_group(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_group_name, GDExtensionConstStringPtr p_prefix) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); String group_name = *reinterpret_cast<const String *>(p_group_name); @@ -241,8 +346,8 @@ void NativeExtension::_register_extension_class_property_group(const GDNativeExt ClassDB::add_property_group(class_name, group_name, prefix); } -void NativeExtension::_register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_subgroup_name, const GDNativeStringPtr p_prefix) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); +void GDExtension::_register_extension_class_property_subgroup(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_subgroup_name, GDExtensionConstStringPtr p_prefix) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); String subgroup_name = *reinterpret_cast<const String *>(p_subgroup_name); @@ -252,8 +357,8 @@ void NativeExtension::_register_extension_class_property_subgroup(const GDNative ClassDB::add_property_subgroup(class_name, subgroup_name, prefix); } -void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); +void GDExtension::_register_extension_class_signal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); StringName signal_name = *reinterpret_cast<const StringName *>(p_signal_name); @@ -268,28 +373,28 @@ void NativeExtension::_register_extension_class_signal(const GDNativeExtensionCl ClassDB::add_signal(class_name, s); } -void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); +void GDExtension::_unregister_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'."); Extension *ext = &self->extension_classes[class_name]; - ERR_FAIL_COND_MSG(ext->native_extension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it."); + ERR_FAIL_COND_MSG(ext->gdextension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it."); ClassDB::unregister_extension_class(class_name); - if (ext->native_extension.parent != nullptr) { - ext->native_extension.parent->children.erase(&ext->native_extension); + if (ext->gdextension.parent != nullptr) { + ext->gdextension.parent->children.erase(&ext->gdextension); } self->extension_classes.erase(class_name); } -void NativeExtension::_get_library_path(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); +void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); *(String *)r_path = self->library_path; } -Error NativeExtension::open_library(const String &p_path, const String &p_entry_symbol) { +Error GDExtension::open_library(const String &p_path, const String &p_entry_symbol) { Error err = OS::get_singleton()->open_dynamic_library(p_path, library, true, &library_path); if (err != OK) { ERR_PRINT("GDExtension dynamic library not found: " + p_path); @@ -306,9 +411,9 @@ Error NativeExtension::open_library(const String &p_path, const String &p_entry_ return err; } - GDNativeInitializationFunction initialization_function = (GDNativeInitializationFunction)entry_funcptr; + GDExtensionInitializationFunction initialization_function = (GDExtensionInitializationFunction)entry_funcptr; - if (initialization_function(&gdnative_interface, this, &initialization)) { + if (initialization_function(&gdextension_interface, this, &initialization)) { level_initialized = -1; return OK; } else { @@ -317,23 +422,23 @@ Error NativeExtension::open_library(const String &p_path, const String &p_entry_ } } -void NativeExtension::close_library() { +void GDExtension::close_library() { ERR_FAIL_COND(library == nullptr); OS::get_singleton()->close_dynamic_library(library); library = nullptr; } -bool NativeExtension::is_library_open() const { +bool GDExtension::is_library_open() const { return library != nullptr; } -NativeExtension::InitializationLevel NativeExtension::get_minimum_library_initialization_level() const { +GDExtension::InitializationLevel GDExtension::get_minimum_library_initialization_level() const { ERR_FAIL_COND_V(library == nullptr, INITIALIZATION_LEVEL_CORE); return InitializationLevel(initialization.minimum_initialization_level); } -void NativeExtension::initialize_library(InitializationLevel p_level) { +void GDExtension::initialize_library(InitializationLevel p_level) { ERR_FAIL_COND(library == nullptr); ERR_FAIL_COND_MSG(p_level <= int32_t(level_initialized), vformat("Level '%d' must be higher than the current level '%d'", p_level, level_initialized)); @@ -341,23 +446,23 @@ void NativeExtension::initialize_library(InitializationLevel p_level) { ERR_FAIL_COND(initialization.initialize == nullptr); - initialization.initialize(initialization.userdata, GDNativeInitializationLevel(p_level)); + initialization.initialize(initialization.userdata, GDExtensionInitializationLevel(p_level)); } -void NativeExtension::deinitialize_library(InitializationLevel p_level) { +void GDExtension::deinitialize_library(InitializationLevel p_level) { ERR_FAIL_COND(library == nullptr); ERR_FAIL_COND(p_level > int32_t(level_initialized)); level_initialized = int32_t(p_level) - 1; - initialization.deinitialize(initialization.userdata, GDNativeInitializationLevel(p_level)); + initialization.deinitialize(initialization.userdata, GDExtensionInitializationLevel(p_level)); } -void NativeExtension::_bind_methods() { - ClassDB::bind_method(D_METHOD("open_library", "path", "entry_symbol"), &NativeExtension::open_library); - ClassDB::bind_method(D_METHOD("close_library"), &NativeExtension::close_library); - ClassDB::bind_method(D_METHOD("is_library_open"), &NativeExtension::is_library_open); +void GDExtension::_bind_methods() { + ClassDB::bind_method(D_METHOD("open_library", "path", "entry_symbol"), &GDExtension::open_library); + ClassDB::bind_method(D_METHOD("close_library"), &GDExtension::close_library); + ClassDB::bind_method(D_METHOD("is_library_open"), &GDExtension::is_library_open); - ClassDB::bind_method(D_METHOD("get_minimum_library_initialization_level"), &NativeExtension::get_minimum_library_initialization_level); - ClassDB::bind_method(D_METHOD("initialize_library", "level"), &NativeExtension::initialize_library); + ClassDB::bind_method(D_METHOD("get_minimum_library_initialization_level"), &GDExtension::get_minimum_library_initialization_level); + ClassDB::bind_method(D_METHOD("initialize_library", "level"), &GDExtension::initialize_library); BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_CORE); BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_SERVERS); @@ -365,32 +470,32 @@ void NativeExtension::_bind_methods() { BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_EDITOR); } -NativeExtension::NativeExtension() { +GDExtension::GDExtension() { } -NativeExtension::~NativeExtension() { +GDExtension::~GDExtension() { if (library != nullptr) { close_library(); } } -extern void gdnative_setup_interface(GDNativeInterface *p_interface); +extern void gdextension_setup_interface(GDExtensionInterface *p_interface); -void NativeExtension::initialize_native_extensions() { - gdnative_setup_interface(&gdnative_interface); +void GDExtension::initialize_gdextensions() { + gdextension_setup_interface(&gdextension_interface); - gdnative_interface.classdb_register_extension_class = _register_extension_class; - 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; - gdnative_interface.get_library_path = _get_library_path; + gdextension_interface.classdb_register_extension_class = _register_extension_class; + gdextension_interface.classdb_register_extension_class_method = _register_extension_class_method; + gdextension_interface.classdb_register_extension_class_integer_constant = _register_extension_class_integer_constant; + gdextension_interface.classdb_register_extension_class_property = _register_extension_class_property; + gdextension_interface.classdb_register_extension_class_property_group = _register_extension_class_property_group; + gdextension_interface.classdb_register_extension_class_property_subgroup = _register_extension_class_property_subgroup; + gdextension_interface.classdb_register_extension_class_signal = _register_extension_class_signal; + gdextension_interface.classdb_unregister_extension_class = _unregister_extension_class; + gdextension_interface.get_library_path = _get_library_path; } -Ref<Resource> NativeExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { +Ref<Resource> GDExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { Ref<ConfigFile> config; config.instantiate(); @@ -415,28 +520,7 @@ Ref<Resource> NativeExtensionResourceLoader::load(const String &p_path, const St String entry_symbol = config->get_value("configuration", "entry_symbol"); - List<String> libraries; - - config->get_section_keys("libraries", &libraries); - - String library_path; - - for (const String &E : libraries) { - Vector<String> tags = E.split("."); - bool all_tags_met = true; - for (int i = 0; i < tags.size(); i++) { - String tag = tags[i].strip_edges(); - if (!OS::get_singleton()->has_feature(tag)) { - all_tags_met = false; - break; - } - } - - if (all_tags_met) { - library_path = config->get_value("libraries", E); - break; - } - } + String library_path = GDExtension::find_extension_library(p_path, config, [](String p_feature) { return OS::get_singleton()->has_feature(p_feature); }); if (library_path.is_empty()) { if (r_error) { @@ -451,7 +535,7 @@ Ref<Resource> NativeExtensionResourceLoader::load(const String &p_path, const St library_path = p_path.get_base_dir().path_join(library_path); } - Ref<NativeExtension> lib; + Ref<GDExtension> lib; lib.instantiate(); String abs_path = ProjectSettings::get_singleton()->globalize_path(library_path); err = lib->open_library(abs_path, entry_symbol); @@ -468,18 +552,18 @@ Ref<Resource> NativeExtensionResourceLoader::load(const String &p_path, const St return lib; } -void NativeExtensionResourceLoader::get_recognized_extensions(List<String> *p_extensions) const { +void GDExtensionResourceLoader::get_recognized_extensions(List<String> *p_extensions) const { p_extensions->push_back("gdextension"); } -bool NativeExtensionResourceLoader::handles_type(const String &p_type) const { - return p_type == "NativeExtension"; +bool GDExtensionResourceLoader::handles_type(const String &p_type) const { + return p_type == "GDExtension"; } -String NativeExtensionResourceLoader::get_resource_type(const String &p_path) const { +String GDExtensionResourceLoader::get_resource_type(const String &p_path) const { String el = p_path.get_extension().to_lower(); if (el == "gdextension") { - return "NativeExtension"; + return "GDExtension"; } return ""; } diff --git a/core/extension/native_extension.h b/core/extension/gdextension.h index 70f6f9f039..26ebdc9a08 100644 --- a/core/extension/native_extension.h +++ b/core/extension/gdextension.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* native_extension.h */ +/* gdextension.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,36 +28,39 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NATIVE_EXTENSION_H -#define NATIVE_EXTENSION_H +#ifndef GDEXTENSION_H +#define GDEXTENSION_H -#include "core/extension/gdnative_interface.h" +#include <functional> + +#include "core/extension/gdextension_interface.h" +#include "core/io/config_file.h" #include "core/io/resource_loader.h" #include "core/object/ref_counted.h" -class NativeExtension : public Resource { - GDCLASS(NativeExtension, Resource) +class GDExtension : public Resource { + GDCLASS(GDExtension, Resource) void *library = nullptr; // pointer if valid, String library_path; struct Extension { - ObjectNativeExtension native_extension; + ObjectGDExtension gdextension; }; HashMap<StringName, Extension> extension_classes; - static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); - static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); - static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); - static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter); - static void _register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_group_name, const GDNativeStringNamePtr p_prefix); - static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_subgroup_name, const GDNativeStringNamePtr p_prefix); - static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count); - static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name); - static void _get_library_path(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path); - - GDNativeInitialization initialization; + static void _register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs); + static void _register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info); + static void _register_extension_class_integer_constant(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield); + static void _register_extension_class_property(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter); + static void _register_extension_class_property_group(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_group_name, GDExtensionConstStringNamePtr p_prefix); + static void _register_extension_class_property_subgroup(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_subgroup_name, GDExtensionConstStringNamePtr p_prefix); + static void _register_extension_class_signal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count); + static void _unregister_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name); + static void _get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path); + + GDExtensionInitialization initialization; int32_t level_initialized = -1; protected: @@ -65,15 +68,16 @@ protected: public: static String get_extension_list_config_file(); + static String find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags = nullptr); Error open_library(const String &p_path, const String &p_entry_symbol); void close_library(); enum InitializationLevel { - INITIALIZATION_LEVEL_CORE = GDNATIVE_INITIALIZATION_CORE, - INITIALIZATION_LEVEL_SERVERS = GDNATIVE_INITIALIZATION_SERVERS, - INITIALIZATION_LEVEL_SCENE = GDNATIVE_INITIALIZATION_SCENE, - INITIALIZATION_LEVEL_EDITOR = GDNATIVE_INITIALIZATION_EDITOR + INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE, + INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS, + INITIALIZATION_LEVEL_SCENE = GDEXTENSION_INITIALIZATION_SCENE, + INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR }; bool is_library_open() const; @@ -82,14 +86,14 @@ public: void initialize_library(InitializationLevel p_level); void deinitialize_library(InitializationLevel p_level); - static void initialize_native_extensions(); - NativeExtension(); - ~NativeExtension(); + static void initialize_gdextensions(); + GDExtension(); + ~GDExtension(); }; -VARIANT_ENUM_CAST(NativeExtension::InitializationLevel) +VARIANT_ENUM_CAST(GDExtension::InitializationLevel) -class NativeExtensionResourceLoader : public ResourceFormatLoader { +class GDExtensionResourceLoader : public ResourceFormatLoader { public: virtual Ref<Resource> load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); virtual void get_recognized_extensions(List<String> *p_extensions) const; @@ -97,4 +101,4 @@ public: virtual String get_resource_type(const String &p_path) const; }; -#endif // NATIVE_EXTENSION_H +#endif // GDEXTENSION_H diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp new file mode 100644 index 0000000000..2074495aa9 --- /dev/null +++ b/core/extension/gdextension_interface.cpp @@ -0,0 +1,1105 @@ +/*************************************************************************/ +/* gdextension_interface.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 "gdextension_interface.h" + +#include "core/config/engine.h" +#include "core/object/class_db.h" +#include "core/object/script_language_extension.h" +#include "core/os/memory.h" +#include "core/variant/variant.h" +#include "core/version.h" + +// Memory Functions +static void *gdextension_alloc(size_t p_size) { + return memalloc(p_size); +} + +static void *gdextension_realloc(void *p_mem, size_t p_size) { + return memrealloc(p_mem, p_size); +} + +static void gdextension_free(void *p_mem) { + memfree(p_mem); +} + +// Helper print functions. +static void gdextension_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { + _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_ERROR); +} +static void gdextension_print_warning(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { + _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_WARNING); +} +static void gdextension_print_script_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { + _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT); +} + +uint64_t gdextension_get_native_struct_size(GDExtensionConstStringNamePtr p_name) { + const StringName name = *reinterpret_cast<const StringName *>(p_name); + return ClassDB::get_native_struct_size(name); +} + +// Variant functions + +static void gdextension_variant_new_copy(GDExtensionVariantPtr r_dest, GDExtensionConstVariantPtr p_src) { + memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant(*reinterpret_cast<const Variant *>(p_src))); +} +static void gdextension_variant_new_nil(GDExtensionVariantPtr r_dest) { + memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant); +} +static void gdextension_variant_destroy(GDExtensionVariantPtr p_self) { + reinterpret_cast<Variant *>(p_self)->~Variant(); +} + +// variant type + +static void gdextension_variant_call(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argcount, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) { + Variant *self = (Variant *)p_self; + const StringName method = *reinterpret_cast<const StringName *>(p_method); + const Variant **args = (const Variant **)p_args; + Variant ret; + Callable::CallError error; + self->callp(method, args, p_argcount, ret, error); + memnew_placement(r_return, Variant(ret)); + + if (r_error) { + r_error->error = (GDExtensionCallErrorType)(error.error); + r_error->argument = error.argument; + r_error->expected = error.expected; + } +} + +static void gdextension_variant_call_static(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argcount, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) { + Variant::Type type = (Variant::Type)p_type; + const StringName method = *reinterpret_cast<const StringName *>(p_method); + const Variant **args = (const Variant **)p_args; + Variant ret; + Callable::CallError error; + Variant::call_static(type, method, args, p_argcount, ret, error); + memnew_placement(r_return, Variant(ret)); + + if (r_error) { + r_error->error = (GDExtensionCallErrorType)error.error; + r_error->argument = error.argument; + r_error->expected = error.expected; + } +} + +static void gdextension_variant_evaluate(GDExtensionVariantOperator p_op, GDExtensionConstVariantPtr p_a, GDExtensionConstVariantPtr p_b, GDExtensionVariantPtr r_return, GDExtensionBool *r_valid) { + Variant::Operator op = (Variant::Operator)p_op; + const Variant *a = (const Variant *)p_a; + const Variant *b = (const Variant *)p_b; + Variant *ret = (Variant *)r_return; + bool valid; + Variant::evaluate(op, *a, *b, *ret, valid); + *r_valid = valid; +} + +static void gdextension_variant_set(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid) { + Variant *self = (Variant *)p_self; + const Variant *key = (const Variant *)p_key; + const Variant *value = (const Variant *)p_value; + + bool valid; + self->set(*key, *value, &valid); + *r_valid = valid; +} + +static void gdextension_variant_set_named(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid) { + Variant *self = (Variant *)p_self; + const StringName *key = (const StringName *)p_key; + const Variant *value = (const Variant *)p_value; + + bool valid; + self->set_named(*key, *value, valid); + *r_valid = valid; +} + +static void gdextension_variant_set_keyed(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid) { + Variant *self = (Variant *)p_self; + const Variant *key = (const Variant *)p_key; + const Variant *value = (const Variant *)p_value; + + bool valid; + self->set_keyed(*key, *value, valid); + *r_valid = valid; +} + +static void gdextension_variant_set_indexed(GDExtensionVariantPtr p_self, GDExtensionInt p_index, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid, GDExtensionBool *r_oob) { + Variant *self = (Variant *)p_self; + const Variant *value = (const Variant *)p_value; + + bool valid; + bool oob; + self->set_indexed(p_index, *value, valid, oob); + *r_valid = valid; + *r_oob = oob; +} + +static void gdextension_variant_get(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + const Variant *key = (const Variant *)p_key; + + bool valid; + memnew_placement(r_ret, Variant(self->get(*key, &valid))); + *r_valid = valid; +} + +static void gdextension_variant_get_named(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + const StringName *key = (const StringName *)p_key; + + bool valid; + memnew_placement(r_ret, Variant(self->get_named(*key, valid))); + *r_valid = valid; +} + +static void gdextension_variant_get_keyed(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + const Variant *key = (const Variant *)p_key; + + bool valid; + memnew_placement(r_ret, Variant(self->get_keyed(*key, valid))); + *r_valid = valid; +} + +static void gdextension_variant_get_indexed(GDExtensionConstVariantPtr p_self, GDExtensionInt p_index, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid, GDExtensionBool *r_oob) { + const Variant *self = (const Variant *)p_self; + + bool valid; + bool oob; + memnew_placement(r_ret, Variant(self->get_indexed(p_index, valid, oob))); + *r_valid = valid; + *r_oob = oob; +} + +/// Iteration. +static GDExtensionBool gdextension_variant_iter_init(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + Variant *iter = (Variant *)r_iter; + + bool valid; + bool ret = self->iter_init(*iter, valid); + *r_valid = valid; + return ret; +} + +static GDExtensionBool gdextension_variant_iter_next(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + Variant *iter = (Variant *)r_iter; + + bool valid; + bool ret = self->iter_next(*iter, valid); + *r_valid = valid; + return ret; +} + +static void gdextension_variant_iter_get(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + Variant *iter = (Variant *)r_iter; + + bool valid; + memnew_placement(r_ret, Variant(self->iter_next(*iter, valid))); + *r_valid = valid; +} + +/// Variant functions. +static GDExtensionInt gdextension_variant_hash(GDExtensionConstVariantPtr p_self) { + const Variant *self = (const Variant *)p_self; + return self->hash(); +} + +static GDExtensionInt gdextension_variant_recursive_hash(GDExtensionConstVariantPtr p_self, GDExtensionInt p_recursion_count) { + const Variant *self = (const Variant *)p_self; + return self->recursive_hash(p_recursion_count); +} + +static GDExtensionBool gdextension_variant_hash_compare(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_other) { + const Variant *self = (const Variant *)p_self; + const Variant *other = (const Variant *)p_other; + return self->hash_compare(*other); +} + +static GDExtensionBool gdextension_variant_booleanize(GDExtensionConstVariantPtr p_self) { + const Variant *self = (const Variant *)p_self; + return self->booleanize(); +} + +static void gdextension_variant_duplicate(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_ret, GDExtensionBool p_deep) { + const Variant *self = (const Variant *)p_self; + memnew_placement(r_ret, Variant(self->duplicate(p_deep))); +} + +static void gdextension_variant_stringify(GDExtensionConstVariantPtr p_self, GDExtensionStringPtr r_ret) { + const Variant *self = (const Variant *)p_self; + memnew_placement(r_ret, String(*self)); +} + +static GDExtensionVariantType gdextension_variant_get_type(GDExtensionConstVariantPtr p_self) { + const Variant *self = (const Variant *)p_self; + return (GDExtensionVariantType)self->get_type(); +} + +static GDExtensionBool gdextension_variant_has_method(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_method) { + const Variant *self = (const Variant *)p_self; + const StringName *method = (const StringName *)p_method; + return self->has_method(*method); +} + +static GDExtensionBool gdextension_variant_has_member(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member) { + return Variant::has_member((Variant::Type)p_type, *((const StringName *)p_member)); +} + +static GDExtensionBool gdextension_variant_has_key(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + const Variant *key = (const Variant *)p_key; + bool valid; + bool ret = self->has_key(*key, valid); + *r_valid = valid; + return ret; +} + +static void gdextension_variant_get_type_name(GDExtensionVariantType p_type, GDExtensionStringPtr r_ret) { + String name = Variant::get_type_name((Variant::Type)p_type); + memnew_placement(r_ret, String(name)); +} + +static GDExtensionBool gdextension_variant_can_convert(GDExtensionVariantType p_from, GDExtensionVariantType p_to) { + return Variant::can_convert((Variant::Type)p_from, (Variant::Type)p_to); +} + +static GDExtensionBool gdextension_variant_can_convert_strict(GDExtensionVariantType p_from, GDExtensionVariantType p_to) { + return Variant::can_convert_strict((Variant::Type)p_from, (Variant::Type)p_to); +} + +// Variant interaction. +static GDExtensionVariantFromTypeConstructorFunc gdextension_get_variant_from_type_constructor(GDExtensionVariantType p_type) { + switch (p_type) { + case GDEXTENSION_VARIANT_TYPE_BOOL: + return VariantTypeConstructor<bool>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_INT: + return VariantTypeConstructor<int64_t>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_FLOAT: + return VariantTypeConstructor<double>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_STRING: + return VariantTypeConstructor<String>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR2: + return VariantTypeConstructor<Vector2>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR2I: + return VariantTypeConstructor<Vector2i>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_RECT2: + return VariantTypeConstructor<Rect2>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_RECT2I: + return VariantTypeConstructor<Rect2i>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR3: + return VariantTypeConstructor<Vector3>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR3I: + return VariantTypeConstructor<Vector3i>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_TRANSFORM2D: + return VariantTypeConstructor<Transform2D>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR4: + return VariantTypeConstructor<Vector4>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR4I: + return VariantTypeConstructor<Vector4i>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PLANE: + return VariantTypeConstructor<Plane>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_QUATERNION: + return VariantTypeConstructor<Quaternion>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_AABB: + return VariantTypeConstructor<AABB>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_BASIS: + return VariantTypeConstructor<Basis>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_TRANSFORM3D: + return VariantTypeConstructor<Transform3D>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PROJECTION: + return VariantTypeConstructor<Projection>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_COLOR: + return VariantTypeConstructor<Color>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_STRING_NAME: + return VariantTypeConstructor<StringName>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_NODE_PATH: + return VariantTypeConstructor<NodePath>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_RID: + return VariantTypeConstructor<RID>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_OBJECT: + return VariantTypeConstructor<Object *>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_CALLABLE: + return VariantTypeConstructor<Callable>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_SIGNAL: + return VariantTypeConstructor<Signal>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_DICTIONARY: + return VariantTypeConstructor<Dictionary>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_ARRAY: + return VariantTypeConstructor<Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_BYTE_ARRAY: + return VariantTypeConstructor<PackedByteArray>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_INT32_ARRAY: + return VariantTypeConstructor<PackedInt32Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_INT64_ARRAY: + return VariantTypeConstructor<PackedInt64Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT32_ARRAY: + return VariantTypeConstructor<PackedFloat32Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT64_ARRAY: + return VariantTypeConstructor<PackedFloat64Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_STRING_ARRAY: + return VariantTypeConstructor<PackedStringArray>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY: + return VariantTypeConstructor<PackedVector2Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: + return VariantTypeConstructor<PackedVector3Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY: + return VariantTypeConstructor<PackedColorArray>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_NIL: + case GDEXTENSION_VARIANT_TYPE_VARIANT_MAX: + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); + } + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); +} + +static GDExtensionTypeFromVariantConstructorFunc gdextension_get_type_from_variant_constructor(GDExtensionVariantType p_type) { + switch (p_type) { + case GDEXTENSION_VARIANT_TYPE_BOOL: + return VariantTypeConstructor<bool>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_INT: + return VariantTypeConstructor<int64_t>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_FLOAT: + return VariantTypeConstructor<double>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_STRING: + return VariantTypeConstructor<String>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR2: + return VariantTypeConstructor<Vector2>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR2I: + return VariantTypeConstructor<Vector2i>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_RECT2: + return VariantTypeConstructor<Rect2>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_RECT2I: + return VariantTypeConstructor<Rect2i>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR3: + return VariantTypeConstructor<Vector3>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR3I: + return VariantTypeConstructor<Vector3i>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_TRANSFORM2D: + return VariantTypeConstructor<Transform2D>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR4: + return VariantTypeConstructor<Vector4>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR4I: + return VariantTypeConstructor<Vector4i>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PLANE: + return VariantTypeConstructor<Plane>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_QUATERNION: + return VariantTypeConstructor<Quaternion>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_AABB: + return VariantTypeConstructor<AABB>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_BASIS: + return VariantTypeConstructor<Basis>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_TRANSFORM3D: + return VariantTypeConstructor<Transform3D>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PROJECTION: + return VariantTypeConstructor<Projection>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_COLOR: + return VariantTypeConstructor<Color>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_STRING_NAME: + return VariantTypeConstructor<StringName>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_NODE_PATH: + return VariantTypeConstructor<NodePath>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_RID: + return VariantTypeConstructor<RID>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_OBJECT: + return VariantTypeConstructor<Object *>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_CALLABLE: + return VariantTypeConstructor<Callable>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_SIGNAL: + return VariantTypeConstructor<Signal>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_DICTIONARY: + return VariantTypeConstructor<Dictionary>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_ARRAY: + return VariantTypeConstructor<Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_BYTE_ARRAY: + return VariantTypeConstructor<PackedByteArray>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_INT32_ARRAY: + return VariantTypeConstructor<PackedInt32Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_INT64_ARRAY: + return VariantTypeConstructor<PackedInt64Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT32_ARRAY: + return VariantTypeConstructor<PackedFloat32Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT64_ARRAY: + return VariantTypeConstructor<PackedFloat64Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_STRING_ARRAY: + return VariantTypeConstructor<PackedStringArray>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY: + return VariantTypeConstructor<PackedVector2Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: + return VariantTypeConstructor<PackedVector3Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY: + return VariantTypeConstructor<PackedColorArray>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_NIL: + case GDEXTENSION_VARIANT_TYPE_VARIANT_MAX: + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); + } + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); +} + +// ptrcalls +static GDExtensionPtrOperatorEvaluator gdextension_variant_get_ptr_operator_evaluator(GDExtensionVariantOperator p_operator, GDExtensionVariantType p_type_a, GDExtensionVariantType p_type_b) { + return (GDExtensionPtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b)); +} +static GDExtensionPtrBuiltInMethod gdextension_variant_get_ptr_builtin_method(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, GDExtensionInt p_hash) { + const StringName method = *reinterpret_cast<const StringName *>(p_method); + uint32_t hash = Variant::get_builtin_method_hash(Variant::Type(p_type), method); + if (hash != p_hash) { + ERR_PRINT_ONCE("Error getting method " + method + ", hash mismatch."); + return nullptr; + } + + return (GDExtensionPtrBuiltInMethod)Variant::get_ptr_builtin_method(Variant::Type(p_type), method); +} +static GDExtensionPtrConstructor gdextension_variant_get_ptr_constructor(GDExtensionVariantType p_type, int32_t p_constructor) { + return (GDExtensionPtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor); +} +static GDExtensionPtrDestructor gdextension_variant_get_ptr_destructor(GDExtensionVariantType p_type) { + return (GDExtensionPtrDestructor)Variant::get_ptr_destructor(Variant::Type(p_type)); +} +static void gdextension_variant_construct(GDExtensionVariantType p_type, GDExtensionVariantPtr p_base, const GDExtensionConstVariantPtr *p_args, int32_t p_argument_count, GDExtensionCallError *r_error) { + memnew_placement(p_base, Variant); + + Callable::CallError error; + Variant::construct(Variant::Type(p_type), *(Variant *)p_base, (const Variant **)p_args, p_argument_count, error); + + if (r_error) { + r_error->error = (GDExtensionCallErrorType)(error.error); + r_error->argument = error.argument; + r_error->expected = error.expected; + } +} +static GDExtensionPtrSetter gdextension_variant_get_ptr_setter(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member) { + const StringName member = *reinterpret_cast<const StringName *>(p_member); + return (GDExtensionPtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), member); +} +static GDExtensionPtrGetter gdextension_variant_get_ptr_getter(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member) { + const StringName member = *reinterpret_cast<const StringName *>(p_member); + return (GDExtensionPtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), member); +} +static GDExtensionPtrIndexedSetter gdextension_variant_get_ptr_indexed_setter(GDExtensionVariantType p_type) { + return (GDExtensionPtrIndexedSetter)Variant::get_member_ptr_indexed_setter(Variant::Type(p_type)); +} +static GDExtensionPtrIndexedGetter gdextension_variant_get_ptr_indexed_getter(GDExtensionVariantType p_type) { + return (GDExtensionPtrIndexedGetter)Variant::get_member_ptr_indexed_getter(Variant::Type(p_type)); +} +static GDExtensionPtrKeyedSetter gdextension_variant_get_ptr_keyed_setter(GDExtensionVariantType p_type) { + return (GDExtensionPtrKeyedSetter)Variant::get_member_ptr_keyed_setter(Variant::Type(p_type)); +} +static GDExtensionPtrKeyedGetter gdextension_variant_get_ptr_keyed_getter(GDExtensionVariantType p_type) { + return (GDExtensionPtrKeyedGetter)Variant::get_member_ptr_keyed_getter(Variant::Type(p_type)); +} +static GDExtensionPtrKeyedChecker gdextension_variant_get_ptr_keyed_checker(GDExtensionVariantType p_type) { + return (GDExtensionPtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type)); +} +static void gdextension_variant_get_constant_value(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_constant, GDExtensionVariantPtr r_ret) { + StringName constant = *reinterpret_cast<const StringName *>(p_constant); + memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), constant))); +} +static GDExtensionPtrUtilityFunction gdextension_variant_get_ptr_utility_function(GDExtensionConstStringNamePtr p_function, GDExtensionInt p_hash) { + StringName function = *reinterpret_cast<const StringName *>(p_function); + uint32_t hash = Variant::get_utility_function_hash(function); + if (hash != p_hash) { + ERR_PRINT_ONCE("Error getting utility function " + function + ", hash mismatch."); + return nullptr; + } + return (GDExtensionPtrUtilityFunction)Variant::get_ptr_utility_function(function); +} + +//string helpers + +static void gdextension_string_new_with_latin1_chars(GDExtensionStringPtr r_dest, const char *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String(p_contents); +} + +static void gdextension_string_new_with_utf8_chars(GDExtensionStringPtr r_dest, const char *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf8(p_contents); +} + +static void gdextension_string_new_with_utf16_chars(GDExtensionStringPtr r_dest, const char16_t *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf16(p_contents); +} + +static void gdextension_string_new_with_utf32_chars(GDExtensionStringPtr r_dest, const char32_t *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents); +} + +static void gdextension_string_new_with_wide_chars(GDExtensionStringPtr r_dest, const wchar_t *p_contents) { + String *dest = (String *)r_dest; + if constexpr (sizeof(wchar_t) == 2) { + // wchar_t is 16 bit, parse. + memnew_placement(dest, String); + dest->parse_utf16((const char16_t *)p_contents); + } else { + // wchar_t is 32 bit, copy. + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents); + } +} + +static void gdextension_string_new_with_latin1_chars_and_len(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String(p_contents, p_size); +} + +static void gdextension_string_new_with_utf8_chars_and_len(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf8(p_contents, p_size); +} + +static void gdextension_string_new_with_utf16_chars_and_len(GDExtensionStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf16(p_contents, p_size); +} + +static void gdextension_string_new_with_utf32_chars_and_len(GDExtensionStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents, p_size); +} + +static void gdextension_string_new_with_wide_chars_and_len(GDExtensionStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_size) { + String *dest = (String *)r_dest; + if constexpr (sizeof(wchar_t) == 2) { + // wchar_t is 16 bit, parse. + memnew_placement(dest, String); + dest->parse_utf16((const char16_t *)p_contents, p_size); + } else { + // wchar_t is 32 bit, copy. + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents, p_size); + } +} + +static GDExtensionInt gdextension_string_to_latin1_chars(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length) { + String *self = (String *)p_self; + CharString cs = self->ascii(true); + GDExtensionInt len = cs.length(); + if (r_text) { + const char *s_text = cs.ptr(); + for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) { + r_text[i] = s_text[i]; + } + } + return len; +} +static GDExtensionInt gdextension_string_to_utf8_chars(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length) { + String *self = (String *)p_self; + CharString cs = self->utf8(); + GDExtensionInt len = cs.length(); + if (r_text) { + const char *s_text = cs.ptr(); + for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) { + r_text[i] = s_text[i]; + } + } + return len; +} +static GDExtensionInt gdextension_string_to_utf16_chars(GDExtensionConstStringPtr p_self, char16_t *r_text, GDExtensionInt p_max_write_length) { + String *self = (String *)p_self; + Char16String cs = self->utf16(); + GDExtensionInt len = cs.length(); + if (r_text) { + const char16_t *s_text = cs.ptr(); + for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) { + r_text[i] = s_text[i]; + } + } + return len; +} +static GDExtensionInt gdextension_string_to_utf32_chars(GDExtensionConstStringPtr p_self, char32_t *r_text, GDExtensionInt p_max_write_length) { + String *self = (String *)p_self; + GDExtensionInt len = self->length(); + if (r_text) { + const char32_t *s_text = self->ptr(); + for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) { + r_text[i] = s_text[i]; + } + } + return len; +} +static GDExtensionInt gdextension_string_to_wide_chars(GDExtensionConstStringPtr p_self, wchar_t *r_text, GDExtensionInt p_max_write_length) { + if constexpr (sizeof(wchar_t) == 4) { + return gdextension_string_to_utf32_chars(p_self, (char32_t *)r_text, p_max_write_length); + } else { + return gdextension_string_to_utf16_chars(p_self, (char16_t *)r_text, p_max_write_length); + } +} + +static char32_t *gdextension_string_operator_index(GDExtensionStringPtr p_self, GDExtensionInt p_index) { + String *self = (String *)p_self; + ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr); + return &self->ptrw()[p_index]; +} + +static const char32_t *gdextension_string_operator_index_const(GDExtensionConstStringPtr p_self, GDExtensionInt p_index) { + const String *self = (const String *)p_self; + ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr); + return &self->ptr()[p_index]; +} + +/* Packed array functions */ + +static uint8_t *gdextension_packed_byte_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedByteArray *self = (PackedByteArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptrw()[p_index]; +} + +static const uint8_t *gdextension_packed_byte_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedByteArray *self = (const PackedByteArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptr()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_color_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedColorArray *self = (PackedColorArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptrw()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_color_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedColorArray *self = (const PackedColorArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptr()[p_index]; +} + +static float *gdextension_packed_float32_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedFloat32Array *self = (PackedFloat32Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptrw()[p_index]; +} + +static const float *gdextension_packed_float32_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedFloat32Array *self = (const PackedFloat32Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptr()[p_index]; +} + +static double *gdextension_packed_float64_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedFloat64Array *self = (PackedFloat64Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptrw()[p_index]; +} + +static const double *gdextension_packed_float64_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedFloat64Array *self = (const PackedFloat64Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptr()[p_index]; +} + +static int32_t *gdextension_packed_int32_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedInt32Array *self = (PackedInt32Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptrw()[p_index]; +} + +static const int32_t *gdextension_packed_int32_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedInt32Array *self = (const PackedInt32Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptr()[p_index]; +} + +static int64_t *gdextension_packed_int64_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedInt64Array *self = (PackedInt64Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptrw()[p_index]; +} + +static const int64_t *gdextension_packed_int64_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedInt64Array *self = (const PackedInt64Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptr()[p_index]; +} + +static GDExtensionStringPtr gdextension_packed_string_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedStringArray *self = (PackedStringArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionStringPtr)&self->ptrw()[p_index]; +} + +static GDExtensionStringPtr gdextension_packed_string_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedStringArray *self = (const PackedStringArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionStringPtr)&self->ptr()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_vector2_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedVector2Array *self = (PackedVector2Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptrw()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_vector2_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedVector2Array *self = (const PackedVector2Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptr()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_vector3_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedVector3Array *self = (PackedVector3Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptrw()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_vector3_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedVector3Array *self = (const PackedVector3Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptr()[p_index]; +} + +static GDExtensionVariantPtr gdextension_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + Array *self = (Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionVariantPtr)&self->operator[](p_index); +} + +static GDExtensionVariantPtr gdextension_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const Array *self = (const Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionVariantPtr)&self->operator[](p_index); +} + +/* Dictionary functions */ + +static GDExtensionVariantPtr gdextension_dictionary_operator_index(GDExtensionTypePtr p_self, GDExtensionConstVariantPtr p_key) { + Dictionary *self = (Dictionary *)p_self; + return (GDExtensionVariantPtr)&self->operator[](*(const Variant *)p_key); +} + +static GDExtensionVariantPtr gdextension_dictionary_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionConstVariantPtr p_key) { + const Dictionary *self = (const Dictionary *)p_self; + return (GDExtensionVariantPtr)&self->operator[](*(const Variant *)p_key); +} + +/* OBJECT API */ + +static void gdextension_object_method_bind_call(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) { + const MethodBind *mb = reinterpret_cast<const MethodBind *>(p_method_bind); + Object *o = (Object *)p_instance; + const Variant **args = (const Variant **)p_args; + Callable::CallError error; + + Variant ret = mb->call(o, args, p_arg_count, error); + memnew_placement(r_return, Variant(ret)); + + if (r_error) { + r_error->error = (GDExtensionCallErrorType)(error.error); + r_error->argument = error.argument; + r_error->expected = error.expected; + } +} + +static void gdextension_object_method_bind_ptrcall(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr p_ret) { + const MethodBind *mb = reinterpret_cast<const MethodBind *>(p_method_bind); + Object *o = (Object *)p_instance; + mb->ptrcall(o, (const void **)p_args, p_ret); +} + +static void gdextension_object_destroy(GDExtensionObjectPtr p_o) { + memdelete((Object *)p_o); +} + +static GDExtensionObjectPtr gdextension_global_get_singleton(GDExtensionConstStringNamePtr p_name) { + const StringName name = *reinterpret_cast<const StringName *>(p_name); + return (GDExtensionObjectPtr)Engine::get_singleton()->get_singleton_object(name); +} + +static void *gdextension_object_get_instance_binding(GDExtensionObjectPtr p_object, void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks) { + Object *o = (Object *)p_object; + return o->get_instance_binding(p_token, p_callbacks); +} + +static void gdextension_object_set_instance_binding(GDExtensionObjectPtr p_object, void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks) { + Object *o = (Object *)p_object; + o->set_instance_binding(p_token, p_binding, p_callbacks); +} + +static void gdextension_object_set_instance(GDExtensionObjectPtr p_object, GDExtensionConstStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); + Object *o = (Object *)p_object; + ClassDB::set_object_extension_instance(o, classname, p_instance); +} + +static GDExtensionObjectPtr gdextension_object_get_instance_from_id(GDObjectInstanceID p_instance_id) { + return (GDExtensionObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id)); +} + +static GDExtensionObjectPtr gdextension_object_cast_to(GDExtensionConstObjectPtr p_object, void *p_class_tag) { + if (!p_object) { + return nullptr; + } + Object *o = (Object *)p_object; + + return o->is_class_ptr(p_class_tag) ? (GDExtensionObjectPtr)o : (GDExtensionObjectPtr) nullptr; +} + +static GDObjectInstanceID gdextension_object_get_instance_id(GDExtensionConstObjectPtr p_object) { + const Object *o = (const Object *)p_object; + return (GDObjectInstanceID)o->get_instance_id(); +} + +static GDExtensionObjectPtr gdextension_ref_get_object(GDExtensionConstRefPtr p_ref) { + const Ref<RefCounted> *ref = (const Ref<RefCounted> *)p_ref; + if (ref == nullptr || ref->is_null()) { + return (GDExtensionObjectPtr) nullptr; + } else { + return (GDExtensionObjectPtr)ref->ptr(); + } +} + +static void gdextension_ref_set_object(GDExtensionRefPtr p_ref, GDExtensionObjectPtr p_object) { + Ref<RefCounted> *ref = (Ref<RefCounted> *)p_ref; + ERR_FAIL_NULL(ref); + + Object *o = (RefCounted *)p_object; + ref->reference_ptr(o); +} + +static GDExtensionScriptInstancePtr gdextension_script_instance_create(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data) { + ScriptInstanceExtension *script_instance_extension = memnew(ScriptInstanceExtension); + script_instance_extension->instance = p_instance_data; + script_instance_extension->native_info = p_info; + return reinterpret_cast<GDExtensionScriptInstancePtr>(script_instance_extension); +} + +static GDExtensionMethodBindPtr gdextension_classdb_get_method_bind(GDExtensionConstStringNamePtr p_classname, GDExtensionConstStringNamePtr p_methodname, GDExtensionInt p_hash) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); + const StringName methodname = *reinterpret_cast<const StringName *>(p_methodname); + MethodBind *mb = ClassDB::get_method(classname, methodname); + ERR_FAIL_COND_V(!mb, nullptr); + if (mb->get_hash() != p_hash) { + ERR_PRINT("Hash mismatch for method '" + classname + "." + methodname + "'."); + return nullptr; + } + return (GDExtensionMethodBindPtr)mb; +} + +static GDExtensionObjectPtr gdextension_classdb_construct_object(GDExtensionConstStringNamePtr p_classname) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); + return (GDExtensionObjectPtr)ClassDB::instantiate(classname); +} + +static void *gdextension_classdb_get_class_tag(GDExtensionConstStringNamePtr p_classname) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); + ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(classname); + return class_info ? class_info->class_ptr : nullptr; +} + +void gdextension_setup_interface(GDExtensionInterface *p_interface) { + GDExtensionInterface &gde_interface = *p_interface; + + gde_interface.version_major = VERSION_MAJOR; + gde_interface.version_minor = VERSION_MINOR; +#if VERSION_PATCH + gde_interface.version_patch = VERSION_PATCH; +#else + gde_interface.version_patch = 0; +#endif + gde_interface.version_string = VERSION_FULL_NAME; + + /* GODOT CORE */ + + gde_interface.mem_alloc = gdextension_alloc; + gde_interface.mem_realloc = gdextension_realloc; + gde_interface.mem_free = gdextension_free; + + gde_interface.print_error = gdextension_print_error; + gde_interface.print_warning = gdextension_print_warning; + gde_interface.print_script_error = gdextension_print_script_error; + + gde_interface.get_native_struct_size = gdextension_get_native_struct_size; + + /* GODOT VARIANT */ + + // variant general + gde_interface.variant_new_copy = gdextension_variant_new_copy; + gde_interface.variant_new_nil = gdextension_variant_new_nil; + gde_interface.variant_destroy = gdextension_variant_destroy; + + gde_interface.variant_call = gdextension_variant_call; + gde_interface.variant_call_static = gdextension_variant_call_static; + gde_interface.variant_evaluate = gdextension_variant_evaluate; + gde_interface.variant_set = gdextension_variant_set; + gde_interface.variant_set_named = gdextension_variant_set_named; + gde_interface.variant_set_keyed = gdextension_variant_set_keyed; + gde_interface.variant_set_indexed = gdextension_variant_set_indexed; + gde_interface.variant_get = gdextension_variant_get; + gde_interface.variant_get_named = gdextension_variant_get_named; + gde_interface.variant_get_keyed = gdextension_variant_get_keyed; + gde_interface.variant_get_indexed = gdextension_variant_get_indexed; + gde_interface.variant_iter_init = gdextension_variant_iter_init; + gde_interface.variant_iter_next = gdextension_variant_iter_next; + gde_interface.variant_iter_get = gdextension_variant_iter_get; + gde_interface.variant_hash = gdextension_variant_hash; + gde_interface.variant_recursive_hash = gdextension_variant_recursive_hash; + gde_interface.variant_hash_compare = gdextension_variant_hash_compare; + gde_interface.variant_booleanize = gdextension_variant_booleanize; + gde_interface.variant_duplicate = gdextension_variant_duplicate; + gde_interface.variant_stringify = gdextension_variant_stringify; + + gde_interface.variant_get_type = gdextension_variant_get_type; + gde_interface.variant_has_method = gdextension_variant_has_method; + gde_interface.variant_has_member = gdextension_variant_has_member; + gde_interface.variant_has_key = gdextension_variant_has_key; + gde_interface.variant_get_type_name = gdextension_variant_get_type_name; + gde_interface.variant_can_convert = gdextension_variant_can_convert; + gde_interface.variant_can_convert_strict = gdextension_variant_can_convert_strict; + + gde_interface.get_variant_from_type_constructor = gdextension_get_variant_from_type_constructor; + gde_interface.get_variant_to_type_constructor = gdextension_get_type_from_variant_constructor; + + // ptrcalls. + + gde_interface.variant_get_ptr_operator_evaluator = gdextension_variant_get_ptr_operator_evaluator; + gde_interface.variant_get_ptr_builtin_method = gdextension_variant_get_ptr_builtin_method; + gde_interface.variant_get_ptr_constructor = gdextension_variant_get_ptr_constructor; + gde_interface.variant_get_ptr_destructor = gdextension_variant_get_ptr_destructor; + gde_interface.variant_construct = gdextension_variant_construct; + gde_interface.variant_get_ptr_setter = gdextension_variant_get_ptr_setter; + gde_interface.variant_get_ptr_getter = gdextension_variant_get_ptr_getter; + gde_interface.variant_get_ptr_indexed_setter = gdextension_variant_get_ptr_indexed_setter; + gde_interface.variant_get_ptr_indexed_getter = gdextension_variant_get_ptr_indexed_getter; + gde_interface.variant_get_ptr_keyed_setter = gdextension_variant_get_ptr_keyed_setter; + gde_interface.variant_get_ptr_keyed_getter = gdextension_variant_get_ptr_keyed_getter; + gde_interface.variant_get_ptr_keyed_checker = gdextension_variant_get_ptr_keyed_checker; + gde_interface.variant_get_constant_value = gdextension_variant_get_constant_value; + gde_interface.variant_get_ptr_utility_function = gdextension_variant_get_ptr_utility_function; + + // extra utilities + + gde_interface.string_new_with_latin1_chars = gdextension_string_new_with_latin1_chars; + gde_interface.string_new_with_utf8_chars = gdextension_string_new_with_utf8_chars; + gde_interface.string_new_with_utf16_chars = gdextension_string_new_with_utf16_chars; + gde_interface.string_new_with_utf32_chars = gdextension_string_new_with_utf32_chars; + gde_interface.string_new_with_wide_chars = gdextension_string_new_with_wide_chars; + gde_interface.string_new_with_latin1_chars_and_len = gdextension_string_new_with_latin1_chars_and_len; + gde_interface.string_new_with_utf8_chars_and_len = gdextension_string_new_with_utf8_chars_and_len; + gde_interface.string_new_with_utf16_chars_and_len = gdextension_string_new_with_utf16_chars_and_len; + gde_interface.string_new_with_utf32_chars_and_len = gdextension_string_new_with_utf32_chars_and_len; + gde_interface.string_new_with_wide_chars_and_len = gdextension_string_new_with_wide_chars_and_len; + gde_interface.string_to_latin1_chars = gdextension_string_to_latin1_chars; + gde_interface.string_to_utf8_chars = gdextension_string_to_utf8_chars; + gde_interface.string_to_utf16_chars = gdextension_string_to_utf16_chars; + gde_interface.string_to_utf32_chars = gdextension_string_to_utf32_chars; + gde_interface.string_to_wide_chars = gdextension_string_to_wide_chars; + gde_interface.string_operator_index = gdextension_string_operator_index; + gde_interface.string_operator_index_const = gdextension_string_operator_index_const; + + /* Packed array functions */ + + gde_interface.packed_byte_array_operator_index = gdextension_packed_byte_array_operator_index; + gde_interface.packed_byte_array_operator_index_const = gdextension_packed_byte_array_operator_index_const; + + gde_interface.packed_color_array_operator_index = gdextension_packed_color_array_operator_index; + gde_interface.packed_color_array_operator_index_const = gdextension_packed_color_array_operator_index_const; + + gde_interface.packed_float32_array_operator_index = gdextension_packed_float32_array_operator_index; + gde_interface.packed_float32_array_operator_index_const = gdextension_packed_float32_array_operator_index_const; + gde_interface.packed_float64_array_operator_index = gdextension_packed_float64_array_operator_index; + gde_interface.packed_float64_array_operator_index_const = gdextension_packed_float64_array_operator_index_const; + + gde_interface.packed_int32_array_operator_index = gdextension_packed_int32_array_operator_index; + gde_interface.packed_int32_array_operator_index_const = gdextension_packed_int32_array_operator_index_const; + gde_interface.packed_int64_array_operator_index = gdextension_packed_int64_array_operator_index; + gde_interface.packed_int64_array_operator_index_const = gdextension_packed_int64_array_operator_index_const; + + gde_interface.packed_string_array_operator_index = gdextension_packed_string_array_operator_index; + gde_interface.packed_string_array_operator_index_const = gdextension_packed_string_array_operator_index_const; + + gde_interface.packed_vector2_array_operator_index = gdextension_packed_vector2_array_operator_index; + gde_interface.packed_vector2_array_operator_index_const = gdextension_packed_vector2_array_operator_index_const; + gde_interface.packed_vector3_array_operator_index = gdextension_packed_vector3_array_operator_index; + gde_interface.packed_vector3_array_operator_index_const = gdextension_packed_vector3_array_operator_index_const; + + gde_interface.array_operator_index = gdextension_array_operator_index; + gde_interface.array_operator_index_const = gdextension_array_operator_index_const; + + /* Dictionary functions */ + + gde_interface.dictionary_operator_index = gdextension_dictionary_operator_index; + gde_interface.dictionary_operator_index_const = gdextension_dictionary_operator_index_const; + + /* OBJECT */ + + gde_interface.object_method_bind_call = gdextension_object_method_bind_call; + gde_interface.object_method_bind_ptrcall = gdextension_object_method_bind_ptrcall; + gde_interface.object_destroy = gdextension_object_destroy; + gde_interface.global_get_singleton = gdextension_global_get_singleton; + gde_interface.object_get_instance_binding = gdextension_object_get_instance_binding; + gde_interface.object_set_instance_binding = gdextension_object_set_instance_binding; + gde_interface.object_set_instance = gdextension_object_set_instance; + + gde_interface.object_cast_to = gdextension_object_cast_to; + gde_interface.object_get_instance_from_id = gdextension_object_get_instance_from_id; + gde_interface.object_get_instance_id = gdextension_object_get_instance_id; + + /* REFERENCE */ + + gde_interface.ref_get_object = gdextension_ref_get_object; + gde_interface.ref_set_object = gdextension_ref_set_object; + + /* SCRIPT INSTANCE */ + + gde_interface.script_instance_create = gdextension_script_instance_create; + + /* CLASSDB */ + + gde_interface.classdb_construct_object = gdextension_classdb_construct_object; + gde_interface.classdb_get_method_bind = gdextension_classdb_get_method_bind; + gde_interface.classdb_get_class_tag = gdextension_classdb_get_class_tag; + + /* CLASSDB EXTENSION */ + + //these are filled by implementation, since it will want to keep track of registered classes + gde_interface.classdb_register_extension_class = nullptr; + gde_interface.classdb_register_extension_class_method = nullptr; + gde_interface.classdb_register_extension_class_integer_constant = nullptr; + gde_interface.classdb_register_extension_class_property = nullptr; + gde_interface.classdb_register_extension_class_property_group = nullptr; + gde_interface.classdb_register_extension_class_property_subgroup = nullptr; + gde_interface.classdb_register_extension_class_signal = nullptr; + gde_interface.classdb_unregister_extension_class = nullptr; + + gde_interface.get_library_path = nullptr; +} diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h new file mode 100644 index 0000000000..0b7615ffdd --- /dev/null +++ b/core/extension/gdextension_interface.h @@ -0,0 +1,619 @@ +/*************************************************************************/ +/* gdextension_interface.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 GDEXTENSION_INTERFACE_H +#define GDEXTENSION_INTERFACE_H + +/* This is a C class header, you can copy it and use it directly in your own binders. + * Together with the JSON file, you should be able to generate any binder. + */ + +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> + +#ifndef __cplusplus +typedef uint32_t char32_t; +typedef uint16_t char16_t; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* VARIANT TYPES */ + +typedef enum { + GDEXTENSION_VARIANT_TYPE_NIL, + + /* atomic types */ + GDEXTENSION_VARIANT_TYPE_BOOL, + GDEXTENSION_VARIANT_TYPE_INT, + GDEXTENSION_VARIANT_TYPE_FLOAT, + GDEXTENSION_VARIANT_TYPE_STRING, + + /* math types */ + GDEXTENSION_VARIANT_TYPE_VECTOR2, + GDEXTENSION_VARIANT_TYPE_VECTOR2I, + GDEXTENSION_VARIANT_TYPE_RECT2, + GDEXTENSION_VARIANT_TYPE_RECT2I, + GDEXTENSION_VARIANT_TYPE_VECTOR3, + GDEXTENSION_VARIANT_TYPE_VECTOR3I, + GDEXTENSION_VARIANT_TYPE_TRANSFORM2D, + GDEXTENSION_VARIANT_TYPE_VECTOR4, + GDEXTENSION_VARIANT_TYPE_VECTOR4I, + GDEXTENSION_VARIANT_TYPE_PLANE, + GDEXTENSION_VARIANT_TYPE_QUATERNION, + GDEXTENSION_VARIANT_TYPE_AABB, + GDEXTENSION_VARIANT_TYPE_BASIS, + GDEXTENSION_VARIANT_TYPE_TRANSFORM3D, + GDEXTENSION_VARIANT_TYPE_PROJECTION, + + /* misc types */ + GDEXTENSION_VARIANT_TYPE_COLOR, + GDEXTENSION_VARIANT_TYPE_STRING_NAME, + GDEXTENSION_VARIANT_TYPE_NODE_PATH, + GDEXTENSION_VARIANT_TYPE_RID, + GDEXTENSION_VARIANT_TYPE_OBJECT, + GDEXTENSION_VARIANT_TYPE_CALLABLE, + GDEXTENSION_VARIANT_TYPE_SIGNAL, + GDEXTENSION_VARIANT_TYPE_DICTIONARY, + GDEXTENSION_VARIANT_TYPE_ARRAY, + + /* typed arrays */ + GDEXTENSION_VARIANT_TYPE_PACKED_BYTE_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_INT32_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_INT64_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT32_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT64_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_STRING_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY, + + GDEXTENSION_VARIANT_TYPE_VARIANT_MAX +} GDExtensionVariantType; + +typedef enum { + /* comparison */ + GDEXTENSION_VARIANT_OP_EQUAL, + GDEXTENSION_VARIANT_OP_NOT_EQUAL, + GDEXTENSION_VARIANT_OP_LESS, + GDEXTENSION_VARIANT_OP_LESS_EQUAL, + GDEXTENSION_VARIANT_OP_GREATER, + GDEXTENSION_VARIANT_OP_GREATER_EQUAL, + + /* mathematic */ + GDEXTENSION_VARIANT_OP_ADD, + GDEXTENSION_VARIANT_OP_SUBTRACT, + GDEXTENSION_VARIANT_OP_MULTIPLY, + GDEXTENSION_VARIANT_OP_DIVIDE, + GDEXTENSION_VARIANT_OP_NEGATE, + GDEXTENSION_VARIANT_OP_POSITIVE, + GDEXTENSION_VARIANT_OP_MODULE, + GDEXTENSION_VARIANT_OP_POWER, + + /* bitwise */ + GDEXTENSION_VARIANT_OP_SHIFT_LEFT, + GDEXTENSION_VARIANT_OP_SHIFT_RIGHT, + GDEXTENSION_VARIANT_OP_BIT_AND, + GDEXTENSION_VARIANT_OP_BIT_OR, + GDEXTENSION_VARIANT_OP_BIT_XOR, + GDEXTENSION_VARIANT_OP_BIT_NEGATE, + + /* logic */ + GDEXTENSION_VARIANT_OP_AND, + GDEXTENSION_VARIANT_OP_OR, + GDEXTENSION_VARIANT_OP_XOR, + GDEXTENSION_VARIANT_OP_NOT, + + /* containment */ + GDEXTENSION_VARIANT_OP_IN, + GDEXTENSION_VARIANT_OP_MAX + +} GDExtensionVariantOperator; + +typedef void *GDExtensionVariantPtr; +typedef const void *GDExtensionConstVariantPtr; +typedef void *GDExtensionStringNamePtr; +typedef const void *GDExtensionConstStringNamePtr; +typedef void *GDExtensionStringPtr; +typedef const void *GDExtensionConstStringPtr; +typedef void *GDExtensionObjectPtr; +typedef const void *GDExtensionConstObjectPtr; +typedef void *GDExtensionTypePtr; +typedef const void *GDExtensionConstTypePtr; +typedef const void *GDExtensionMethodBindPtr; +typedef int64_t GDExtensionInt; +typedef uint8_t GDExtensionBool; +typedef uint64_t GDObjectInstanceID; +typedef void *GDExtensionRefPtr; +typedef const void *GDExtensionConstRefPtr; + +/* VARIANT DATA I/O */ + +typedef enum { + GDEXTENSION_CALL_OK, + GDEXTENSION_CALL_ERROR_INVALID_METHOD, + GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT, // Expected a different variant type. + GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS, // Expected lower number of arguments. + GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS, // Expected higher number of arguments. + GDEXTENSION_CALL_ERROR_INSTANCE_IS_NULL, + GDEXTENSION_CALL_ERROR_METHOD_NOT_CONST, // Used for const call. +} GDExtensionCallErrorType; + +typedef struct { + GDExtensionCallErrorType error; + int32_t argument; + int32_t expected; +} GDExtensionCallError; + +typedef void (*GDExtensionVariantFromTypeConstructorFunc)(GDExtensionVariantPtr, GDExtensionTypePtr); +typedef void (*GDExtensionTypeFromVariantConstructorFunc)(GDExtensionTypePtr, GDExtensionVariantPtr); +typedef void (*GDExtensionPtrOperatorEvaluator)(GDExtensionConstTypePtr p_left, GDExtensionConstTypePtr p_right, GDExtensionTypePtr r_result); +typedef void (*GDExtensionPtrBuiltInMethod)(GDExtensionTypePtr p_base, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return, int p_argument_count); +typedef void (*GDExtensionPtrConstructor)(GDExtensionTypePtr p_base, const GDExtensionConstTypePtr *p_args); +typedef void (*GDExtensionPtrDestructor)(GDExtensionTypePtr p_base); +typedef void (*GDExtensionPtrSetter)(GDExtensionTypePtr p_base, GDExtensionConstTypePtr p_value); +typedef void (*GDExtensionPtrGetter)(GDExtensionConstTypePtr p_base, GDExtensionTypePtr r_value); +typedef void (*GDExtensionPtrIndexedSetter)(GDExtensionTypePtr p_base, GDExtensionInt p_index, GDExtensionConstTypePtr p_value); +typedef void (*GDExtensionPtrIndexedGetter)(GDExtensionConstTypePtr p_base, GDExtensionInt p_index, GDExtensionTypePtr r_value); +typedef void (*GDExtensionPtrKeyedSetter)(GDExtensionTypePtr p_base, GDExtensionConstTypePtr p_key, GDExtensionConstTypePtr p_value); +typedef void (*GDExtensionPtrKeyedGetter)(GDExtensionConstTypePtr p_base, GDExtensionConstTypePtr p_key, GDExtensionTypePtr r_value); +typedef uint32_t (*GDExtensionPtrKeyedChecker)(GDExtensionConstVariantPtr p_base, GDExtensionConstVariantPtr p_key); +typedef void (*GDExtensionPtrUtilityFunction)(GDExtensionTypePtr r_return, const GDExtensionConstTypePtr *p_args, int p_argument_count); + +typedef GDExtensionObjectPtr (*GDExtensionClassConstructor)(); + +typedef void *(*GDExtensionInstanceBindingCreateCallback)(void *p_token, void *p_instance); +typedef void (*GDExtensionInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding); +typedef GDExtensionBool (*GDExtensionInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDExtensionBool p_reference); + +typedef struct { + GDExtensionInstanceBindingCreateCallback create_callback; + GDExtensionInstanceBindingFreeCallback free_callback; + GDExtensionInstanceBindingReferenceCallback reference_callback; +} GDExtensionInstanceBindingCallbacks; + +/* EXTENSION CLASSES */ + +typedef void *GDExtensionClassInstancePtr; + +typedef GDExtensionBool (*GDExtensionClassSet)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value); +typedef GDExtensionBool (*GDExtensionClassGet)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret); +typedef uint64_t (*GDExtensionClassGetRID)(GDExtensionClassInstancePtr p_instance); + +typedef struct { + GDExtensionVariantType type; + GDExtensionStringNamePtr name; + GDExtensionStringNamePtr class_name; + uint32_t hint; // Bitfield of `PropertyHint` (defined in `extension_api.json`). + GDExtensionStringPtr hint_string; + uint32_t usage; // Bitfield of `PropertyUsageFlags` (defined in `extension_api.json`). +} GDExtensionPropertyInfo; + +typedef struct { + GDExtensionStringNamePtr name; + GDExtensionPropertyInfo return_value; + uint32_t flags; // Bitfield of `GDExtensionClassMethodFlags`. + int32_t id; + + /* Arguments: `default_arguments` is an array of size `argument_count`. */ + uint32_t argument_count; + GDExtensionPropertyInfo *arguments; + + /* Default arguments: `default_arguments` is an array of size `default_argument_count`. */ + uint32_t default_argument_count; + GDExtensionVariantPtr *default_arguments; +} GDExtensionMethodInfo; + +typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count); +typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list); +typedef GDExtensionBool (*GDExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name); +typedef GDExtensionBool (*GDExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret); +typedef void (*GDExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what); +typedef void (*GDExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr p_out); +typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance); +typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance); +typedef void (*GDExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret); +typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_userdata); +typedef void (*GDExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance); +typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_userdata, GDExtensionConstStringNamePtr p_name); + +typedef struct { + GDExtensionBool is_virtual; + GDExtensionBool is_abstract; + GDExtensionClassSet set_func; + GDExtensionClassGet get_func; + GDExtensionClassGetPropertyList get_property_list_func; + GDExtensionClassFreePropertyList free_property_list_func; + GDExtensionClassPropertyCanRevert property_can_revert_func; + GDExtensionClassPropertyGetRevert property_get_revert_func; + GDExtensionClassNotification notification_func; + GDExtensionClassToString to_string_func; + GDExtensionClassReference reference_func; + GDExtensionClassUnreference unreference_func; + GDExtensionClassCreateInstance create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract. + GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory. + GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function. + GDExtensionClassGetRID get_rid_func; + void *class_userdata; // Per-class user data, later accessible in instance bindings. +} GDExtensionClassCreationInfo; + +typedef void *GDExtensionClassLibraryPtr; + +/* Method */ + +typedef enum { + GDEXTENSION_METHOD_FLAG_NORMAL = 1, + GDEXTENSION_METHOD_FLAG_EDITOR = 2, + GDEXTENSION_METHOD_FLAG_CONST = 4, + GDEXTENSION_METHOD_FLAG_VIRTUAL = 8, + GDEXTENSION_METHOD_FLAG_VARARG = 16, + GDEXTENSION_METHOD_FLAG_STATIC = 32, + GDEXTENSION_METHOD_FLAGS_DEFAULT = GDEXTENSION_METHOD_FLAG_NORMAL, +} GDExtensionClassMethodFlags; + +typedef enum { + GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT8, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT16, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT8, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT16, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64, + GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT, + GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE +} GDExtensionClassMethodArgumentMetadata; + +typedef void (*GDExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error); +typedef void (*GDExtensionClassMethodPtrCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret); + +typedef struct { + GDExtensionStringNamePtr name; + void *method_userdata; + GDExtensionClassMethodCall call_func; + GDExtensionClassMethodPtrCall ptrcall_func; + uint32_t method_flags; // Bitfield of `GDExtensionClassMethodFlags`. + + /* If `has_return_value` is false, `return_value_info` and `return_value_metadata` are ignored. */ + GDExtensionBool has_return_value; + GDExtensionPropertyInfo *return_value_info; + GDExtensionClassMethodArgumentMetadata return_value_metadata; + + /* Arguments: `arguments_info` and `arguments_metadata` are array of size `argument_count`. + * Name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. + */ + uint32_t argument_count; + GDExtensionPropertyInfo *arguments_info; + GDExtensionClassMethodArgumentMetadata *arguments_metadata; + + /* Default arguments: `default_arguments` is an array of size `default_argument_count`. */ + uint32_t default_argument_count; + GDExtensionVariantPtr *default_arguments; +} GDExtensionClassMethodInfo; + +/* SCRIPT INSTANCE EXTENSION */ + +typedef void *GDExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation. + +typedef GDExtensionBool (*GDExtensionScriptInstanceSet)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value); +typedef GDExtensionBool (*GDExtensionScriptInstanceGet)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret); +typedef const GDExtensionPropertyInfo *(*GDExtensionScriptInstanceGetPropertyList)(GDExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count); +typedef void (*GDExtensionScriptInstanceFreePropertyList)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionPropertyInfo *p_list); +typedef GDExtensionVariantType (*GDExtensionScriptInstanceGetPropertyType)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionBool *r_is_valid); + +typedef GDExtensionBool (*GDExtensionScriptInstancePropertyCanRevert)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name); +typedef GDExtensionBool (*GDExtensionScriptInstancePropertyGetRevert)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret); + +typedef GDExtensionObjectPtr (*GDExtensionScriptInstanceGetOwner)(GDExtensionScriptInstanceDataPtr p_instance); +typedef void (*GDExtensionScriptInstancePropertyStateAdd)(GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value, void *p_userdata); +typedef void (*GDExtensionScriptInstanceGetPropertyState)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionScriptInstancePropertyStateAdd p_add_func, void *p_userdata); + +typedef const GDExtensionMethodInfo *(*GDExtensionScriptInstanceGetMethodList)(GDExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count); +typedef void (*GDExtensionScriptInstanceFreeMethodList)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionMethodInfo *p_list); + +typedef GDExtensionBool (*GDExtensionScriptInstanceHasMethod)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name); + +typedef void (*GDExtensionScriptInstanceCall)(GDExtensionScriptInstanceDataPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error); +typedef void (*GDExtensionScriptInstanceNotification)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what); +typedef void (*GDExtensionScriptInstanceToString)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out); + +typedef void (*GDExtensionScriptInstanceRefCountIncremented)(GDExtensionScriptInstanceDataPtr p_instance); +typedef GDExtensionBool (*GDExtensionScriptInstanceRefCountDecremented)(GDExtensionScriptInstanceDataPtr p_instance); + +typedef GDExtensionObjectPtr (*GDExtensionScriptInstanceGetScript)(GDExtensionScriptInstanceDataPtr p_instance); +typedef GDExtensionBool (*GDExtensionScriptInstanceIsPlaceholder)(GDExtensionScriptInstanceDataPtr p_instance); + +typedef void *GDExtensionScriptLanguagePtr; + +typedef GDExtensionScriptLanguagePtr (*GDExtensionScriptInstanceGetLanguage)(GDExtensionScriptInstanceDataPtr p_instance); + +typedef void (*GDExtensionScriptInstanceFree)(GDExtensionScriptInstanceDataPtr p_instance); + +typedef void *GDExtensionScriptInstancePtr; // Pointer to ScriptInstance. + +typedef struct { + GDExtensionScriptInstanceSet set_func; + GDExtensionScriptInstanceGet get_func; + GDExtensionScriptInstanceGetPropertyList get_property_list_func; + GDExtensionScriptInstanceFreePropertyList free_property_list_func; + + GDExtensionScriptInstancePropertyCanRevert property_can_revert_func; + GDExtensionScriptInstancePropertyGetRevert property_get_revert_func; + + GDExtensionScriptInstanceGetOwner get_owner_func; + GDExtensionScriptInstanceGetPropertyState get_property_state_func; + + GDExtensionScriptInstanceGetMethodList get_method_list_func; + GDExtensionScriptInstanceFreeMethodList free_method_list_func; + GDExtensionScriptInstanceGetPropertyType get_property_type_func; + + GDExtensionScriptInstanceHasMethod has_method_func; + + GDExtensionScriptInstanceCall call_func; + GDExtensionScriptInstanceNotification notification_func; + + GDExtensionScriptInstanceToString to_string_func; + + GDExtensionScriptInstanceRefCountIncremented refcount_incremented_func; + GDExtensionScriptInstanceRefCountDecremented refcount_decremented_func; + + GDExtensionScriptInstanceGetScript get_script_func; + + GDExtensionScriptInstanceIsPlaceholder is_placeholder_func; + + GDExtensionScriptInstanceSet set_fallback_func; + GDExtensionScriptInstanceGet get_fallback_func; + + GDExtensionScriptInstanceGetLanguage get_language_func; + + GDExtensionScriptInstanceFree free_func; + +} GDExtensionScriptInstanceInfo; + +/* INTERFACE */ + +typedef struct { + uint32_t version_major; + uint32_t version_minor; + uint32_t version_patch; + const char *version_string; + + /* GODOT CORE */ + + void *(*mem_alloc)(size_t p_bytes); + void *(*mem_realloc)(void *p_ptr, size_t p_bytes); + void (*mem_free)(void *p_ptr); + + void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); + void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); + void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); + + uint64_t (*get_native_struct_size)(GDExtensionConstStringNamePtr p_name); + + /* GODOT VARIANT */ + + /* variant general */ + void (*variant_new_copy)(GDExtensionVariantPtr r_dest, GDExtensionConstVariantPtr p_src); + void (*variant_new_nil)(GDExtensionVariantPtr r_dest); + void (*variant_destroy)(GDExtensionVariantPtr p_self); + + /* variant type */ + void (*variant_call)(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error); + void (*variant_call_static)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error); + void (*variant_evaluate)(GDExtensionVariantOperator p_op, GDExtensionConstVariantPtr p_a, GDExtensionConstVariantPtr p_b, GDExtensionVariantPtr r_return, GDExtensionBool *r_valid); + void (*variant_set)(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid); + void (*variant_set_named)(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid); + void (*variant_set_keyed)(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid); + void (*variant_set_indexed)(GDExtensionVariantPtr p_self, GDExtensionInt p_index, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid, GDExtensionBool *r_oob); + void (*variant_get)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid); + void (*variant_get_named)(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid); + void (*variant_get_keyed)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid); + void (*variant_get_indexed)(GDExtensionConstVariantPtr p_self, GDExtensionInt p_index, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid, GDExtensionBool *r_oob); + GDExtensionBool (*variant_iter_init)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid); + GDExtensionBool (*variant_iter_next)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid); + void (*variant_iter_get)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid); + GDExtensionInt (*variant_hash)(GDExtensionConstVariantPtr p_self); + GDExtensionInt (*variant_recursive_hash)(GDExtensionConstVariantPtr p_self, GDExtensionInt p_recursion_count); + GDExtensionBool (*variant_hash_compare)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_other); + GDExtensionBool (*variant_booleanize)(GDExtensionConstVariantPtr p_self); + void (*variant_duplicate)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_ret, GDExtensionBool p_deep); + void (*variant_stringify)(GDExtensionConstVariantPtr p_self, GDExtensionStringPtr r_ret); + + GDExtensionVariantType (*variant_get_type)(GDExtensionConstVariantPtr p_self); + GDExtensionBool (*variant_has_method)(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_method); + GDExtensionBool (*variant_has_member)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member); + GDExtensionBool (*variant_has_key)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionBool *r_valid); + void (*variant_get_type_name)(GDExtensionVariantType p_type, GDExtensionStringPtr r_name); + GDExtensionBool (*variant_can_convert)(GDExtensionVariantType p_from, GDExtensionVariantType p_to); + GDExtensionBool (*variant_can_convert_strict)(GDExtensionVariantType p_from, GDExtensionVariantType p_to); + + /* ptrcalls */ + GDExtensionVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDExtensionVariantType p_type); + GDExtensionTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDExtensionVariantType p_type); + GDExtensionPtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDExtensionVariantOperator p_operator, GDExtensionVariantType p_type_a, GDExtensionVariantType p_type_b); + GDExtensionPtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, GDExtensionInt p_hash); + GDExtensionPtrConstructor (*variant_get_ptr_constructor)(GDExtensionVariantType p_type, int32_t p_constructor); + GDExtensionPtrDestructor (*variant_get_ptr_destructor)(GDExtensionVariantType p_type); + void (*variant_construct)(GDExtensionVariantType p_type, GDExtensionVariantPtr p_base, const GDExtensionConstVariantPtr *p_args, int32_t p_argument_count, GDExtensionCallError *r_error); + GDExtensionPtrSetter (*variant_get_ptr_setter)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member); + GDExtensionPtrGetter (*variant_get_ptr_getter)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member); + GDExtensionPtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDExtensionVariantType p_type); + GDExtensionPtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDExtensionVariantType p_type); + GDExtensionPtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDExtensionVariantType p_type); + GDExtensionPtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDExtensionVariantType p_type); + GDExtensionPtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDExtensionVariantType p_type); + void (*variant_get_constant_value)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_constant, GDExtensionVariantPtr r_ret); + GDExtensionPtrUtilityFunction (*variant_get_ptr_utility_function)(GDExtensionConstStringNamePtr p_function, GDExtensionInt p_hash); + + /* extra utilities */ + void (*string_new_with_latin1_chars)(GDExtensionStringPtr r_dest, const char *p_contents); + void (*string_new_with_utf8_chars)(GDExtensionStringPtr r_dest, const char *p_contents); + void (*string_new_with_utf16_chars)(GDExtensionStringPtr r_dest, const char16_t *p_contents); + void (*string_new_with_utf32_chars)(GDExtensionStringPtr r_dest, const char32_t *p_contents); + void (*string_new_with_wide_chars)(GDExtensionStringPtr r_dest, const wchar_t *p_contents); + void (*string_new_with_latin1_chars_and_len)(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size); + void (*string_new_with_utf8_chars_and_len)(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size); + void (*string_new_with_utf16_chars_and_len)(GDExtensionStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_size); + void (*string_new_with_utf32_chars_and_len)(GDExtensionStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_size); + void (*string_new_with_wide_chars_and_len)(GDExtensionStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_size); + /* Information about the following functions: + * - The return value is the resulting encoded string length. + * - The length returned is in characters, not in bytes. It also does not include a trailing zero. + * - These functions also do not write trailing zero, If you need it, write it yourself at the position indicated by the length (and make sure to allocate it). + * - Passing NULL in r_text means only the length is computed (again, without including trailing zero). + * - p_max_write_length argument is in characters, not bytes. It will be ignored if r_text is NULL. + * - p_max_write_length argument does not affect the return value, it's only to cap write length. + */ + GDExtensionInt (*string_to_latin1_chars)(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length); + GDExtensionInt (*string_to_utf8_chars)(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length); + GDExtensionInt (*string_to_utf16_chars)(GDExtensionConstStringPtr p_self, char16_t *r_text, GDExtensionInt p_max_write_length); + GDExtensionInt (*string_to_utf32_chars)(GDExtensionConstStringPtr p_self, char32_t *r_text, GDExtensionInt p_max_write_length); + GDExtensionInt (*string_to_wide_chars)(GDExtensionConstStringPtr p_self, wchar_t *r_text, GDExtensionInt p_max_write_length); + char32_t *(*string_operator_index)(GDExtensionStringPtr p_self, GDExtensionInt p_index); + const char32_t *(*string_operator_index_const)(GDExtensionConstStringPtr p_self, GDExtensionInt p_index); + + /* Packed array functions */ + + uint8_t *(*packed_byte_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedByteArray + const uint8_t *(*packed_byte_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedByteArray + + GDExtensionTypePtr (*packed_color_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedColorArray, returns Color ptr + GDExtensionTypePtr (*packed_color_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedColorArray, returns Color ptr + + float *(*packed_float32_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat32Array + const float *(*packed_float32_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat32Array + double *(*packed_float64_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat64Array + const double *(*packed_float64_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat64Array + + int32_t *(*packed_int32_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array + const int32_t *(*packed_int32_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array + int64_t *(*packed_int64_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array + const int64_t *(*packed_int64_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array + + GDExtensionStringPtr (*packed_string_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedStringArray + GDExtensionStringPtr (*packed_string_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedStringArray + + GDExtensionTypePtr (*packed_vector2_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr + GDExtensionTypePtr (*packed_vector2_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr + GDExtensionTypePtr (*packed_vector3_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr + GDExtensionTypePtr (*packed_vector3_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr + + GDExtensionVariantPtr (*array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr + GDExtensionVariantPtr (*array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr + + /* Dictionary functions */ + + GDExtensionVariantPtr (*dictionary_operator_index)(GDExtensionTypePtr p_self, GDExtensionConstVariantPtr p_key); // p_self should be an Dictionary ptr + GDExtensionVariantPtr (*dictionary_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionConstVariantPtr p_key); // p_self should be an Dictionary ptr + + /* OBJECT */ + + void (*object_method_bind_call)(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionVariantPtr r_ret, GDExtensionCallError *r_error); + void (*object_method_bind_ptrcall)(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret); + void (*object_destroy)(GDExtensionObjectPtr p_o); + GDExtensionObjectPtr (*global_get_singleton)(GDExtensionConstStringNamePtr p_name); + + void *(*object_get_instance_binding)(GDExtensionObjectPtr p_o, void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks); + void (*object_set_instance_binding)(GDExtensionObjectPtr p_o, void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks); + + void (*object_set_instance)(GDExtensionObjectPtr p_o, GDExtensionConstStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */ + + GDExtensionObjectPtr (*object_cast_to)(GDExtensionConstObjectPtr p_object, void *p_class_tag); + GDExtensionObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id); + GDObjectInstanceID (*object_get_instance_id)(GDExtensionConstObjectPtr p_object); + + /* REFERENCE */ + + GDExtensionObjectPtr (*ref_get_object)(GDExtensionConstRefPtr p_ref); + void (*ref_set_object)(GDExtensionRefPtr p_ref, GDExtensionObjectPtr p_object); + + /* SCRIPT INSTANCE */ + + GDExtensionScriptInstancePtr (*script_instance_create)(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data); + + /* CLASSDB */ + + GDExtensionObjectPtr (*classdb_construct_object)(GDExtensionConstStringNamePtr 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. */ + GDExtensionMethodBindPtr (*classdb_get_method_bind)(GDExtensionConstStringNamePtr p_classname, GDExtensionConstStringNamePtr p_methodname, GDExtensionInt p_hash); + void *(*classdb_get_class_tag)(GDExtensionConstStringNamePtr p_classname); + + /* CLASSDB EXTENSION */ + + /* Provided parameters for `classdb_register_extension_*` can be safely freed once the function returns. */ + void (*classdb_register_extension_class)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs); + void (*classdb_register_extension_class_method)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info); + void (*classdb_register_extension_class_integer_constant)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield); + void (*classdb_register_extension_class_property)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter); + void (*classdb_register_extension_class_property_group)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_group_name, GDExtensionConstStringPtr p_prefix); + void (*classdb_register_extension_class_property_subgroup)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_subgroup_name, GDExtensionConstStringPtr p_prefix); + void (*classdb_register_extension_class_signal)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count); + void (*classdb_unregister_extension_class)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */ + + void (*get_library_path)(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path); + +} GDExtensionInterface; + +/* INITIALIZATION */ + +typedef enum { + GDEXTENSION_INITIALIZATION_CORE, + GDEXTENSION_INITIALIZATION_SERVERS, + GDEXTENSION_INITIALIZATION_SCENE, + GDEXTENSION_INITIALIZATION_EDITOR, + GDEXTENSION_MAX_INITIALIZATION_LEVEL, +} GDExtensionInitializationLevel; + +typedef struct { + /* Minimum initialization level required. + * If Core or Servers, the extension needs editor or game restart to take effect */ + GDExtensionInitializationLevel minimum_initialization_level; + /* Up to the user to supply when initializing */ + void *userdata; + /* This function will be called multiple times for each initialization level. */ + void (*initialize)(void *userdata, GDExtensionInitializationLevel p_level); + void (*deinitialize)(void *userdata, GDExtensionInitializationLevel p_level); +} GDExtensionInitialization; + +/* Define a C function prototype that implements the function below and expose it to dlopen() (or similar). + * This is the entry point of the GDExtension library and will be called on initialization. + * It can be used to set up different init levels, which are called during various stages of initialization/shutdown. + * The function name must be a unique one specified in the .gdextension config file. + */ +typedef GDExtensionBool (*GDExtensionInitializationFunction)(const GDExtensionInterface *p_interface, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization); + +#ifdef __cplusplus +} +#endif + +#endif // GDEXTENSION_INTERFACE_H diff --git a/core/extension/native_extension_manager.cpp b/core/extension/gdextension_manager.cpp index 186fcc44f6..5bdde78793 100644 --- a/core/extension/native_extension_manager.cpp +++ b/core/extension/gdextension_manager.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* native_extension_manager.cpp */ +/* gdextension_manager.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,91 +28,91 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "native_extension_manager.h" +#include "gdextension_manager.h" #include "core/io/file_access.h" -NativeExtensionManager::LoadStatus NativeExtensionManager::load_extension(const String &p_path) { - if (native_extension_map.has(p_path)) { +GDExtensionManager::LoadStatus GDExtensionManager::load_extension(const String &p_path) { + if (gdextension_map.has(p_path)) { return LOAD_STATUS_ALREADY_LOADED; } - Ref<NativeExtension> extension = ResourceLoader::load(p_path); + Ref<GDExtension> extension = ResourceLoader::load(p_path); if (extension.is_null()) { return LOAD_STATUS_FAILED; } if (level >= 0) { // Already initialized up to some level. int32_t minimum_level = extension->get_minimum_library_initialization_level(); - if (minimum_level < MIN(level, NativeExtension::INITIALIZATION_LEVEL_SCENE)) { + if (minimum_level < MIN(level, GDExtension::INITIALIZATION_LEVEL_SCENE)) { return LOAD_STATUS_NEEDS_RESTART; } // Initialize up to current level. for (int32_t i = minimum_level; i <= level; i++) { - extension->initialize_library(NativeExtension::InitializationLevel(i)); + extension->initialize_library(GDExtension::InitializationLevel(i)); } } - native_extension_map[p_path] = extension; + gdextension_map[p_path] = extension; return LOAD_STATUS_OK; } -NativeExtensionManager::LoadStatus NativeExtensionManager::reload_extension(const String &p_path) { +GDExtensionManager::LoadStatus GDExtensionManager::reload_extension(const String &p_path) { return LOAD_STATUS_OK; //TODO } -NativeExtensionManager::LoadStatus NativeExtensionManager::unload_extension(const String &p_path) { - if (!native_extension_map.has(p_path)) { +GDExtensionManager::LoadStatus GDExtensionManager::unload_extension(const String &p_path) { + if (!gdextension_map.has(p_path)) { return LOAD_STATUS_NOT_LOADED; } - Ref<NativeExtension> extension = native_extension_map[p_path]; + Ref<GDExtension> extension = gdextension_map[p_path]; if (level >= 0) { // Already initialized up to some level. int32_t minimum_level = extension->get_minimum_library_initialization_level(); - if (minimum_level < MIN(level, NativeExtension::INITIALIZATION_LEVEL_SCENE)) { + if (minimum_level < MIN(level, GDExtension::INITIALIZATION_LEVEL_SCENE)) { return LOAD_STATUS_NEEDS_RESTART; } // Deinitialize down to current level. for (int32_t i = level; i >= minimum_level; i--) { - extension->deinitialize_library(NativeExtension::InitializationLevel(i)); + extension->deinitialize_library(GDExtension::InitializationLevel(i)); } } - native_extension_map.erase(p_path); + gdextension_map.erase(p_path); return LOAD_STATUS_OK; } -bool NativeExtensionManager::is_extension_loaded(const String &p_path) const { - return native_extension_map.has(p_path); +bool GDExtensionManager::is_extension_loaded(const String &p_path) const { + return gdextension_map.has(p_path); } -Vector<String> NativeExtensionManager::get_loaded_extensions() const { +Vector<String> GDExtensionManager::get_loaded_extensions() const { Vector<String> ret; - for (const KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) { + for (const KeyValue<String, Ref<GDExtension>> &E : gdextension_map) { ret.push_back(E.key); } return ret; } -Ref<NativeExtension> NativeExtensionManager::get_extension(const String &p_path) { - HashMap<String, Ref<NativeExtension>>::Iterator E = native_extension_map.find(p_path); - ERR_FAIL_COND_V(!E, Ref<NativeExtension>()); +Ref<GDExtension> GDExtensionManager::get_extension(const String &p_path) { + HashMap<String, Ref<GDExtension>>::Iterator E = gdextension_map.find(p_path); + ERR_FAIL_COND_V(!E, Ref<GDExtension>()); return E->value; } -void NativeExtensionManager::initialize_extensions(NativeExtension::InitializationLevel p_level) { +void GDExtensionManager::initialize_extensions(GDExtension::InitializationLevel p_level) { ERR_FAIL_COND(int32_t(p_level) - 1 != level); - for (KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) { + for (KeyValue<String, Ref<GDExtension>> &E : gdextension_map) { E.value->initialize_library(p_level); } level = p_level; } -void NativeExtensionManager::deinitialize_extensions(NativeExtension::InitializationLevel p_level) { +void GDExtensionManager::deinitialize_extensions(GDExtension::InitializationLevel p_level) { ERR_FAIL_COND(int32_t(p_level) != level); - for (KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) { + for (KeyValue<String, Ref<GDExtension>> &E : gdextension_map) { E.value->deinitialize_library(p_level); } level = int32_t(p_level) - 1; } -void NativeExtensionManager::load_extensions() { - Ref<FileAccess> f = FileAccess::open(NativeExtension::get_extension_list_config_file(), FileAccess::READ); +void GDExtensionManager::load_extensions() { + Ref<FileAccess> f = FileAccess::open(GDExtension::get_extension_list_config_file(), FileAccess::READ); while (f.is_valid() && !f->eof_reached()) { String s = f->get_line().strip_edges(); if (!s.is_empty()) { @@ -122,17 +122,17 @@ void NativeExtensionManager::load_extensions() { } } -NativeExtensionManager *NativeExtensionManager::get_singleton() { +GDExtensionManager *GDExtensionManager::get_singleton() { return singleton; } -void NativeExtensionManager::_bind_methods() { - ClassDB::bind_method(D_METHOD("load_extension", "path"), &NativeExtensionManager::load_extension); - ClassDB::bind_method(D_METHOD("reload_extension", "path"), &NativeExtensionManager::reload_extension); - ClassDB::bind_method(D_METHOD("unload_extension", "path"), &NativeExtensionManager::unload_extension); - ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &NativeExtensionManager::is_extension_loaded); +void GDExtensionManager::_bind_methods() { + ClassDB::bind_method(D_METHOD("load_extension", "path"), &GDExtensionManager::load_extension); + ClassDB::bind_method(D_METHOD("reload_extension", "path"), &GDExtensionManager::reload_extension); + ClassDB::bind_method(D_METHOD("unload_extension", "path"), &GDExtensionManager::unload_extension); + ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &GDExtensionManager::is_extension_loaded); - ClassDB::bind_method(D_METHOD("get_loaded_extensions"), &NativeExtensionManager::get_loaded_extensions); - ClassDB::bind_method(D_METHOD("get_extension", "path"), &NativeExtensionManager::get_extension); + ClassDB::bind_method(D_METHOD("get_loaded_extensions"), &GDExtensionManager::get_loaded_extensions); + ClassDB::bind_method(D_METHOD("get_extension", "path"), &GDExtensionManager::get_extension); BIND_ENUM_CONSTANT(LOAD_STATUS_OK); BIND_ENUM_CONSTANT(LOAD_STATUS_FAILED); @@ -141,9 +141,9 @@ void NativeExtensionManager::_bind_methods() { BIND_ENUM_CONSTANT(LOAD_STATUS_NEEDS_RESTART); } -NativeExtensionManager *NativeExtensionManager::singleton = nullptr; +GDExtensionManager *GDExtensionManager::singleton = nullptr; -NativeExtensionManager::NativeExtensionManager() { +GDExtensionManager::GDExtensionManager() { ERR_FAIL_COND(singleton != nullptr); singleton = this; } diff --git a/core/extension/native_extension_manager.h b/core/extension/gdextension_manager.h index ed80cd6b7a..2f2aa0e0d4 100644 --- a/core/extension/native_extension_manager.h +++ b/core/extension/gdextension_manager.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* native_extension_manager.h */ +/* gdextension_manager.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,20 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NATIVE_EXTENSION_MANAGER_H -#define NATIVE_EXTENSION_MANAGER_H +#ifndef GDEXTENSION_MANAGER_H +#define GDEXTENSION_MANAGER_H -#include "core/extension/native_extension.h" +#include "core/extension/gdextension.h" -class NativeExtensionManager : public Object { - GDCLASS(NativeExtensionManager, Object); +class GDExtensionManager : public Object { + GDCLASS(GDExtensionManager, Object); int32_t level = -1; - HashMap<String, Ref<NativeExtension>> native_extension_map; + HashMap<String, Ref<GDExtension>> gdextension_map; static void _bind_methods(); - static NativeExtensionManager *singleton; + static GDExtensionManager *singleton; public: enum LoadStatus { @@ -57,18 +57,18 @@ public: LoadStatus unload_extension(const String &p_path); bool is_extension_loaded(const String &p_path) const; Vector<String> get_loaded_extensions() const; - Ref<NativeExtension> get_extension(const String &p_path); + Ref<GDExtension> get_extension(const String &p_path); - void initialize_extensions(NativeExtension::InitializationLevel p_level); - void deinitialize_extensions(NativeExtension::InitializationLevel p_level); + void initialize_extensions(GDExtension::InitializationLevel p_level); + void deinitialize_extensions(GDExtension::InitializationLevel p_level); - static NativeExtensionManager *get_singleton(); + static GDExtensionManager *get_singleton(); void load_extensions(); - NativeExtensionManager(); + GDExtensionManager(); }; -VARIANT_ENUM_CAST(NativeExtensionManager::LoadStatus) +VARIANT_ENUM_CAST(GDExtensionManager::LoadStatus) -#endif // NATIVE_EXTENSION_MANAGER_H +#endif // GDEXTENSION_MANAGER_H diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp deleted file mode 100644 index 864f2fa86b..0000000000 --- a/core/extension/gdnative_interface.cpp +++ /dev/null @@ -1,1083 +0,0 @@ -/*************************************************************************/ -/* gdnative_interface.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 "gdnative_interface.h" - -#include "core/config/engine.h" -#include "core/object/class_db.h" -#include "core/object/script_language_extension.h" -#include "core/os/memory.h" -#include "core/variant/variant.h" -#include "core/version.h" - -// Memory Functions -static void *gdnative_alloc(size_t p_size) { - return memalloc(p_size); -} - -static void *gdnative_realloc(void *p_mem, size_t p_size) { - return memrealloc(p_mem, p_size); -} - -static void gdnative_free(void *p_mem) { - memfree(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, 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, 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, false, ERR_HANDLER_SCRIPT); -} - -uint64_t gdnative_get_native_struct_size(const GDNativeStringNamePtr p_name) { - const StringName name = *reinterpret_cast<const StringName *>(p_name); - return ClassDB::get_native_struct_size(name); -} - -// Variant functions - -static void gdnative_variant_new_copy(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src) { - memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant(*reinterpret_cast<Variant *>(p_src))); -} -static void gdnative_variant_new_nil(GDNativeVariantPtr r_dest) { - memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant); -} -static void gdnative_variant_destroy(GDNativeVariantPtr p_self) { - reinterpret_cast<Variant *>(p_self)->~Variant(); -} - -// variant type - -static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) { - Variant *self = (Variant *)p_self; - const StringName method = *reinterpret_cast<const StringName *>(p_method); - const Variant **args = (const Variant **)p_args; - Variant ret; - Callable::CallError error; - self->callp(method, args, p_argcount, ret, error); - memnew_placement(r_return, Variant(ret)); - - if (r_error) { - r_error->error = (GDNativeCallErrorType)(error.error); - r_error->argument = error.argument; - r_error->expected = error.expected; - } -} - -static void gdnative_variant_call_static(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) { - Variant::Type type = (Variant::Type)p_type; - const StringName method = *reinterpret_cast<const StringName *>(p_method); - const Variant **args = (const Variant **)p_args; - Variant ret; - Callable::CallError error; - Variant::call_static(type, method, args, p_argcount, ret, error); - memnew_placement(r_return, Variant(ret)); - - if (r_error) { - r_error->error = (GDNativeCallErrorType)error.error; - r_error->argument = error.argument; - r_error->expected = error.expected; - } -} - -static void gdnative_variant_evaluate(GDNativeVariantOperator p_op, const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_return, GDNativeBool *r_valid) { - Variant::Operator op = (Variant::Operator)p_op; - const Variant *a = (const Variant *)p_a; - const Variant *b = (const Variant *)p_b; - Variant *ret = (Variant *)r_return; - bool valid; - Variant::evaluate(op, *a, *b, *ret, valid); - *r_valid = valid; -} - -static void gdnative_variant_set(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) { - Variant *self = (Variant *)p_self; - const Variant *key = (const Variant *)p_key; - const Variant *value = (const Variant *)p_value; - - bool valid; - self->set(*key, *value, &valid); - *r_valid = valid; -} - -static void gdnative_variant_set_named(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) { - Variant *self = (Variant *)p_self; - const StringName *key = (const StringName *)p_key; - const Variant *value = (const Variant *)p_value; - - bool valid; - self->set_named(*key, *value, valid); - *r_valid = valid; -} - -static void gdnative_variant_set_keyed(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) { - Variant *self = (Variant *)p_self; - const Variant *key = (const Variant *)p_key; - const Variant *value = (const Variant *)p_value; - - bool valid; - self->set_keyed(*key, *value, valid); - *r_valid = valid; -} - -static void gdnative_variant_set_indexed(GDNativeVariantPtr p_self, GDNativeInt p_index, const GDNativeVariantPtr p_value, GDNativeBool *r_valid, GDNativeBool *r_oob) { - Variant *self = (Variant *)p_self; - const Variant *value = (const Variant *)p_value; - - bool valid; - bool oob; - self->set_indexed(p_index, *value, valid, oob); - *r_valid = valid; - *r_oob = oob; -} - -static void gdnative_variant_get(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - const Variant *key = (const Variant *)p_key; - - bool valid; - memnew_placement(r_ret, Variant(self->get(*key, &valid))); - *r_valid = valid; -} - -static void gdnative_variant_get_named(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - const StringName *key = (const StringName *)p_key; - - bool valid; - memnew_placement(r_ret, Variant(self->get_named(*key, valid))); - *r_valid = valid; -} - -static void gdnative_variant_get_keyed(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - const Variant *key = (const Variant *)p_key; - - bool valid; - memnew_placement(r_ret, Variant(self->get_keyed(*key, valid))); - *r_valid = valid; -} - -static void gdnative_variant_get_indexed(const GDNativeVariantPtr p_self, GDNativeInt p_index, GDNativeVariantPtr r_ret, GDNativeBool *r_valid, GDNativeBool *r_oob) { - const Variant *self = (const Variant *)p_self; - - bool valid; - bool oob; - memnew_placement(r_ret, Variant(self->get_indexed(p_index, valid, oob))); - *r_valid = valid; - *r_oob = oob; -} - -/// Iteration. -static GDNativeBool gdnative_variant_iter_init(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - Variant *iter = (Variant *)r_iter; - - bool valid; - bool ret = self->iter_init(*iter, valid); - *r_valid = valid; - return ret; -} - -static GDNativeBool gdnative_variant_iter_next(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - Variant *iter = (Variant *)r_iter; - - bool valid; - bool ret = self->iter_next(*iter, valid); - *r_valid = valid; - return ret; -} - -static void gdnative_variant_iter_get(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - Variant *iter = (Variant *)r_iter; - - bool valid; - memnew_placement(r_ret, Variant(self->iter_next(*iter, valid))); - *r_valid = valid; -} - -/// Variant functions. -static GDNativeInt gdnative_variant_hash(const GDNativeVariantPtr p_self) { - const Variant *self = (const Variant *)p_self; - return self->hash(); -} - -static GDNativeInt gdnative_variant_recursive_hash(const GDNativeVariantPtr p_self, GDNativeInt p_recursion_count) { - const Variant *self = (const Variant *)p_self; - return self->recursive_hash(p_recursion_count); -} - -static GDNativeBool gdnative_variant_hash_compare(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other) { - const Variant *self = (const Variant *)p_self; - const Variant *other = (const Variant *)p_other; - return self->hash_compare(*other); -} - -static GDNativeBool gdnative_variant_booleanize(const GDNativeVariantPtr p_self) { - const Variant *self = (const Variant *)p_self; - return self->booleanize(); -} - -static void gdnative_variant_duplicate(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep) { - const Variant *self = (const Variant *)p_self; - memnew_placement(r_ret, Variant(self->duplicate(p_deep))); -} - -static void gdnative_variant_stringify(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret) { - const Variant *self = (const Variant *)p_self; - memnew_placement(r_ret, String(*self)); -} - -static GDNativeVariantType gdnative_variant_get_type(const GDNativeVariantPtr p_self) { - const Variant *self = (const Variant *)p_self; - return (GDNativeVariantType)self->get_type(); -} - -static GDNativeBool gdnative_variant_has_method(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method) { - const Variant *self = (const Variant *)p_self; - const StringName *method = (const StringName *)p_method; - return self->has_method(*method); -} - -static GDNativeBool gdnative_variant_has_member(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) { - return Variant::has_member((Variant::Type)p_type, *((const StringName *)p_member)); -} - -static GDNativeBool gdnative_variant_has_key(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - const Variant *key = (const Variant *)p_key; - bool valid; - bool ret = self->has_key(*key, valid); - *r_valid = valid; - return ret; -} - -static void gdnative_variant_get_type_name(GDNativeVariantType p_type, GDNativeStringPtr r_ret) { - String name = Variant::get_type_name((Variant::Type)p_type); - memnew_placement(r_ret, String(name)); -} - -static GDNativeBool gdnative_variant_can_convert(GDNativeVariantType p_from, GDNativeVariantType p_to) { - return Variant::can_convert((Variant::Type)p_from, (Variant::Type)p_to); -} - -static GDNativeBool gdnative_variant_can_convert_strict(GDNativeVariantType p_from, GDNativeVariantType p_to) { - return Variant::can_convert_strict((Variant::Type)p_from, (Variant::Type)p_to); -} - -// Variant interaction. -static GDNativeVariantFromTypeConstructorFunc gdnative_get_variant_from_type_constructor(GDNativeVariantType p_type) { - switch (p_type) { - case GDNATIVE_VARIANT_TYPE_BOOL: - return VariantTypeConstructor<bool>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_INT: - return VariantTypeConstructor<int64_t>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_FLOAT: - return VariantTypeConstructor<double>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_STRING: - return VariantTypeConstructor<String>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR2: - return VariantTypeConstructor<Vector2>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR2I: - return VariantTypeConstructor<Vector2i>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_RECT2: - return VariantTypeConstructor<Rect2>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_RECT2I: - return VariantTypeConstructor<Rect2i>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR3: - return VariantTypeConstructor<Vector3>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR3I: - return VariantTypeConstructor<Vector3i>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_TRANSFORM2D: - return VariantTypeConstructor<Transform2D>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR4: - return VariantTypeConstructor<Vector4>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR4I: - return VariantTypeConstructor<Vector4i>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PLANE: - return VariantTypeConstructor<Plane>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_QUATERNION: - return VariantTypeConstructor<Quaternion>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_AABB: - return VariantTypeConstructor<AABB>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_BASIS: - return VariantTypeConstructor<Basis>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_TRANSFORM3D: - return VariantTypeConstructor<Transform3D>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PROJECTION: - return VariantTypeConstructor<Projection>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_COLOR: - return VariantTypeConstructor<Color>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_STRING_NAME: - return VariantTypeConstructor<StringName>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_NODE_PATH: - return VariantTypeConstructor<NodePath>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_RID: - return VariantTypeConstructor<RID>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_OBJECT: - return VariantTypeConstructor<Object *>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_CALLABLE: - return VariantTypeConstructor<Callable>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_SIGNAL: - return VariantTypeConstructor<Signal>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_DICTIONARY: - return VariantTypeConstructor<Dictionary>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_ARRAY: - return VariantTypeConstructor<Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY: - return VariantTypeConstructor<PackedByteArray>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY: - return VariantTypeConstructor<PackedInt32Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY: - return VariantTypeConstructor<PackedInt64Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY: - return VariantTypeConstructor<PackedFloat32Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY: - return VariantTypeConstructor<PackedFloat64Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY: - return VariantTypeConstructor<PackedStringArray>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY: - return VariantTypeConstructor<PackedVector2Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: - return VariantTypeConstructor<PackedVector3Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY: - return VariantTypeConstructor<PackedColorArray>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_NIL: - case GDNATIVE_VARIANT_TYPE_VARIANT_MAX: - ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); - } - ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); -} - -static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_constructor(GDNativeVariantType p_type) { - switch (p_type) { - case GDNATIVE_VARIANT_TYPE_BOOL: - return VariantTypeConstructor<bool>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_INT: - return VariantTypeConstructor<int64_t>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_FLOAT: - return VariantTypeConstructor<double>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_STRING: - return VariantTypeConstructor<String>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR2: - return VariantTypeConstructor<Vector2>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR2I: - return VariantTypeConstructor<Vector2i>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_RECT2: - return VariantTypeConstructor<Rect2>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_RECT2I: - return VariantTypeConstructor<Rect2i>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR3: - return VariantTypeConstructor<Vector3>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR3I: - return VariantTypeConstructor<Vector3i>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_TRANSFORM2D: - return VariantTypeConstructor<Transform2D>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR4: - return VariantTypeConstructor<Vector4>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR4I: - return VariantTypeConstructor<Vector4i>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PLANE: - return VariantTypeConstructor<Plane>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_QUATERNION: - return VariantTypeConstructor<Quaternion>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_AABB: - return VariantTypeConstructor<AABB>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_BASIS: - return VariantTypeConstructor<Basis>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_TRANSFORM3D: - return VariantTypeConstructor<Transform3D>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PROJECTION: - return VariantTypeConstructor<Projection>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_COLOR: - return VariantTypeConstructor<Color>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_STRING_NAME: - return VariantTypeConstructor<StringName>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_NODE_PATH: - return VariantTypeConstructor<NodePath>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_RID: - return VariantTypeConstructor<RID>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_OBJECT: - return VariantTypeConstructor<Object *>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_CALLABLE: - return VariantTypeConstructor<Callable>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_SIGNAL: - return VariantTypeConstructor<Signal>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_DICTIONARY: - return VariantTypeConstructor<Dictionary>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_ARRAY: - return VariantTypeConstructor<Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY: - return VariantTypeConstructor<PackedByteArray>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY: - return VariantTypeConstructor<PackedInt32Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY: - return VariantTypeConstructor<PackedInt64Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY: - return VariantTypeConstructor<PackedFloat32Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY: - return VariantTypeConstructor<PackedFloat64Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY: - return VariantTypeConstructor<PackedStringArray>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY: - return VariantTypeConstructor<PackedVector2Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: - return VariantTypeConstructor<PackedVector3Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY: - return VariantTypeConstructor<PackedColorArray>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_NIL: - case GDNATIVE_VARIANT_TYPE_VARIANT_MAX: - ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); - } - ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); -} - -// ptrcalls -static GDNativePtrOperatorEvaluator gdnative_variant_get_ptr_operator_evaluator(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b) { - return (GDNativePtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b)); -} -static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, GDNativeInt p_hash) { - const StringName method = *reinterpret_cast<const StringName *>(p_method); - uint32_t hash = Variant::get_builtin_method_hash(Variant::Type(p_type), method); - if (hash != p_hash) { - ERR_PRINT_ONCE("Error getting method " + method + ", hash mismatch."); - return nullptr; - } - - return (GDNativePtrBuiltInMethod)Variant::get_ptr_builtin_method(Variant::Type(p_type), method); -} -static GDNativePtrConstructor gdnative_variant_get_ptr_constructor(GDNativeVariantType p_type, int32_t p_constructor) { - return (GDNativePtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor); -} -static GDNativePtrDestructor gdnative_variant_get_ptr_destructor(GDNativeVariantType p_type) { - return (GDNativePtrDestructor)Variant::get_ptr_destructor(Variant::Type(p_type)); -} -static void gdnative_variant_construct(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error) { - memnew_placement(p_base, Variant); - - Callable::CallError error; - Variant::construct(Variant::Type(p_type), *(Variant *)p_base, (const Variant **)p_args, p_argument_count, error); - - if (r_error) { - r_error->error = (GDNativeCallErrorType)(error.error); - r_error->argument = error.argument; - r_error->expected = error.expected; - } -} -static GDNativePtrSetter gdnative_variant_get_ptr_setter(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) { - const StringName member = *reinterpret_cast<const StringName *>(p_member); - return (GDNativePtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), member); -} -static GDNativePtrGetter gdnative_variant_get_ptr_getter(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) { - const StringName member = *reinterpret_cast<const StringName *>(p_member); - return (GDNativePtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), member); -} -static GDNativePtrIndexedSetter gdnative_variant_get_ptr_indexed_setter(GDNativeVariantType p_type) { - return (GDNativePtrIndexedSetter)Variant::get_member_ptr_indexed_setter(Variant::Type(p_type)); -} -static GDNativePtrIndexedGetter gdnative_variant_get_ptr_indexed_getter(GDNativeVariantType p_type) { - return (GDNativePtrIndexedGetter)Variant::get_member_ptr_indexed_getter(Variant::Type(p_type)); -} -static GDNativePtrKeyedSetter gdnative_variant_get_ptr_keyed_setter(GDNativeVariantType p_type) { - return (GDNativePtrKeyedSetter)Variant::get_member_ptr_keyed_setter(Variant::Type(p_type)); -} -static GDNativePtrKeyedGetter gdnative_variant_get_ptr_keyed_getter(GDNativeVariantType p_type) { - return (GDNativePtrKeyedGetter)Variant::get_member_ptr_keyed_getter(Variant::Type(p_type)); -} -static GDNativePtrKeyedChecker gdnative_variant_get_ptr_keyed_checker(GDNativeVariantType p_type) { - return (GDNativePtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type)); -} -static void gdnative_variant_get_constant_value(GDNativeVariantType p_type, const GDNativeStringNamePtr p_constant, GDNativeVariantPtr r_ret) { - StringName constant = *reinterpret_cast<const StringName *>(p_constant); - memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), constant))); -} -static GDNativePtrUtilityFunction gdnative_variant_get_ptr_utility_function(const GDNativeStringNamePtr p_function, GDNativeInt p_hash) { - StringName function = *reinterpret_cast<const StringName *>(p_function); - uint32_t hash = Variant::get_utility_function_hash(function); - if (hash != p_hash) { - ERR_PRINT_ONCE("Error getting utility function " + function + ", hash mismatch."); - return nullptr; - } - return (GDNativePtrUtilityFunction)Variant::get_ptr_utility_function(function); -} - -//string helpers - -static void gdnative_string_new_with_latin1_chars(GDNativeStringPtr r_dest, const char *p_contents) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - *dest = String(p_contents); -} - -static void gdnative_string_new_with_utf8_chars(GDNativeStringPtr r_dest, const char *p_contents) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - dest->parse_utf8(p_contents); -} - -static void gdnative_string_new_with_utf16_chars(GDNativeStringPtr r_dest, const char16_t *p_contents) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - dest->parse_utf16(p_contents); -} - -static void gdnative_string_new_with_utf32_chars(GDNativeStringPtr r_dest, const char32_t *p_contents) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - *dest = String((const char32_t *)p_contents); -} - -static void gdnative_string_new_with_wide_chars(GDNativeStringPtr r_dest, const wchar_t *p_contents) { - String *dest = (String *)r_dest; - if constexpr (sizeof(wchar_t) == 2) { - // wchar_t is 16 bit, parse. - memnew_placement(dest, String); - dest->parse_utf16((const char16_t *)p_contents); - } else { - // wchar_t is 32 bit, copy. - memnew_placement(dest, String); - *dest = String((const char32_t *)p_contents); - } -} - -static void gdnative_string_new_with_latin1_chars_and_len(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - *dest = String(p_contents, p_size); -} - -static void gdnative_string_new_with_utf8_chars_and_len(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - dest->parse_utf8(p_contents, p_size); -} - -static void gdnative_string_new_with_utf16_chars_and_len(GDNativeStringPtr r_dest, const char16_t *p_contents, const GDNativeInt p_size) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - dest->parse_utf16(p_contents, p_size); -} - -static void gdnative_string_new_with_utf32_chars_and_len(GDNativeStringPtr r_dest, const char32_t *p_contents, const GDNativeInt p_size) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - *dest = String((const char32_t *)p_contents, p_size); -} - -static void gdnative_string_new_with_wide_chars_and_len(GDNativeStringPtr r_dest, const wchar_t *p_contents, const GDNativeInt p_size) { - String *dest = (String *)r_dest; - if constexpr (sizeof(wchar_t) == 2) { - // wchar_t is 16 bit, parse. - memnew_placement(dest, String); - dest->parse_utf16((const char16_t *)p_contents, p_size); - } else { - // wchar_t is 32 bit, copy. - memnew_placement(dest, String); - *dest = String((const char32_t *)p_contents, p_size); - } -} - -static GDNativeInt gdnative_string_to_latin1_chars(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length) { - String *self = (String *)p_self; - CharString cs = self->ascii(true); - GDNativeInt len = cs.length(); - if (r_text) { - const char *s_text = cs.ptr(); - for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) { - r_text[i] = s_text[i]; - } - } - return len; -} -static GDNativeInt gdnative_string_to_utf8_chars(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length) { - String *self = (String *)p_self; - CharString cs = self->utf8(); - GDNativeInt len = cs.length(); - if (r_text) { - const char *s_text = cs.ptr(); - for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) { - r_text[i] = s_text[i]; - } - } - return len; -} -static GDNativeInt gdnative_string_to_utf16_chars(const GDNativeStringPtr p_self, char16_t *r_text, GDNativeInt p_max_write_length) { - String *self = (String *)p_self; - Char16String cs = self->utf16(); - GDNativeInt len = cs.length(); - if (r_text) { - const char16_t *s_text = cs.ptr(); - for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) { - r_text[i] = s_text[i]; - } - } - return len; -} -static GDNativeInt gdnative_string_to_utf32_chars(const GDNativeStringPtr p_self, char32_t *r_text, GDNativeInt p_max_write_length) { - String *self = (String *)p_self; - GDNativeInt len = self->length(); - if (r_text) { - const char32_t *s_text = self->ptr(); - for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) { - r_text[i] = s_text[i]; - } - } - return len; -} -static GDNativeInt gdnative_string_to_wide_chars(const GDNativeStringPtr p_self, wchar_t *r_text, GDNativeInt p_max_write_length) { - if constexpr (sizeof(wchar_t) == 4) { - return gdnative_string_to_utf32_chars(p_self, (char32_t *)r_text, p_max_write_length); - } else { - return gdnative_string_to_utf16_chars(p_self, (char16_t *)r_text, p_max_write_length); - } -} - -static char32_t *gdnative_string_operator_index(GDNativeStringPtr p_self, GDNativeInt p_index) { - String *self = (String *)p_self; - ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr); - return &self->ptrw()[p_index]; -} - -static const char32_t *gdnative_string_operator_index_const(const GDNativeStringPtr p_self, GDNativeInt p_index) { - const String *self = (const String *)p_self; - ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr); - return &self->ptr()[p_index]; -} - -/* Packed array functions */ - -static uint8_t *gdnative_packed_byte_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedByteArray *self = (PackedByteArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptrw()[p_index]; -} - -static const uint8_t *gdnative_packed_byte_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedByteArray *self = (const PackedByteArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptr()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_color_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedColorArray *self = (PackedColorArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self->ptrw()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_color_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedColorArray *self = (const PackedColorArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self->ptr()[p_index]; -} - -static float *gdnative_packed_float32_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedFloat32Array *self = (PackedFloat32Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptrw()[p_index]; -} - -static const float *gdnative_packed_float32_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedFloat32Array *self = (const PackedFloat32Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptr()[p_index]; -} - -static double *gdnative_packed_float64_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedFloat64Array *self = (PackedFloat64Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptrw()[p_index]; -} - -static const double *gdnative_packed_float64_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedFloat64Array *self = (const PackedFloat64Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptr()[p_index]; -} - -static int32_t *gdnative_packed_int32_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedInt32Array *self = (PackedInt32Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptrw()[p_index]; -} - -static const int32_t *gdnative_packed_int32_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedInt32Array *self = (const PackedInt32Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptr()[p_index]; -} - -static int64_t *gdnative_packed_int64_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedInt64Array *self = (PackedInt64Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptrw()[p_index]; -} - -static const int64_t *gdnative_packed_int64_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedInt64Array *self = (const PackedInt64Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptr()[p_index]; -} - -static GDNativeStringPtr gdnative_packed_string_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedStringArray *self = (PackedStringArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeStringPtr)&self->ptrw()[p_index]; -} - -static GDNativeStringPtr gdnative_packed_string_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedStringArray *self = (const PackedStringArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeStringPtr)&self->ptr()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_vector2_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedVector2Array *self = (PackedVector2Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self->ptrw()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_vector2_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedVector2Array *self = (const PackedVector2Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self->ptr()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_vector3_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedVector3Array *self = (PackedVector3Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self->ptrw()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_vector3_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedVector3Array *self = (const PackedVector3Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - 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) { - MethodBind *mb = (MethodBind *)p_method_bind; - Object *o = (Object *)p_instance; - const Variant **args = (const Variant **)p_args; - Callable::CallError error; - - Variant ret = mb->call(o, args, p_arg_count, error); - memnew_placement(r_return, Variant(ret)); - - if (r_error) { - r_error->error = (GDNativeCallErrorType)(error.error); - r_error->argument = error.argument; - r_error->expected = error.expected; - } -} - -static void gdnative_object_method_bind_ptrcall(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) { - MethodBind *mb = (MethodBind *)p_method_bind; - Object *o = (Object *)p_instance; - mb->ptrcall(o, (const void **)p_args, p_ret); -} - -static void gdnative_object_destroy(GDNativeObjectPtr p_o) { - memdelete((Object *)p_o); -} - -static GDNativeObjectPtr gdnative_global_get_singleton(const GDNativeStringNamePtr p_name) { - const StringName name = *reinterpret_cast<const StringName *>(p_name); - return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(name); -} - -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_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 GDNativeStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance) { - const StringName classname = *reinterpret_cast<const StringName *>(p_classname); - Object *o = (Object *)p_object; - ClassDB::set_object_extension_instance(o, classname, p_instance); -} - -static GDNativeObjectPtr gdnative_object_get_instance_from_id(GDObjectInstanceID p_instance_id) { - return (GDNativeObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id)); -} - -static GDNativeObjectPtr gdnative_object_cast_to(const GDNativeObjectPtr p_object, void *p_class_tag) { - if (!p_object) { - return nullptr; - } - Object *o = (Object *)p_object; - - return o->is_class_ptr(p_class_tag) ? (GDNativeObjectPtr)o : (GDNativeObjectPtr) nullptr; -} - -static GDObjectInstanceID gdnative_object_get_instance_id(const GDNativeObjectPtr p_object) { - const Object *o = (const Object *)p_object; - return (GDObjectInstanceID)o->get_instance_id(); -} - -static GDNativeScriptInstancePtr gdnative_script_instance_create(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data) { - ScriptInstanceExtension *script_instance_extension = memnew(ScriptInstanceExtension); - script_instance_extension->instance = p_instance_data; - script_instance_extension->native_info = p_info; - return reinterpret_cast<GDNativeScriptInstancePtr>(script_instance_extension); -} - -static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const GDNativeStringNamePtr p_classname, const GDNativeStringNamePtr p_methodname, GDNativeInt p_hash) { - const StringName classname = *reinterpret_cast<const StringName *>(p_classname); - const StringName methodname = *reinterpret_cast<const StringName *>(p_methodname); - MethodBind *mb = ClassDB::get_method(classname, methodname); - ERR_FAIL_COND_V(!mb, nullptr); - if (mb->get_hash() != p_hash) { - ERR_PRINT("Hash mismatch for method '" + classname + "." + methodname + "'."); - return nullptr; - } - return (GDNativeMethodBindPtr)mb; -} - -static GDNativeObjectPtr gdnative_classdb_construct_object(const GDNativeStringNamePtr p_classname) { - const StringName classname = *reinterpret_cast<const StringName *>(p_classname); - return (GDNativeObjectPtr)ClassDB::instantiate(classname); -} - -static void *gdnative_classdb_get_class_tag(const GDNativeStringNamePtr p_classname) { - const StringName classname = *reinterpret_cast<const StringName *>(p_classname); - ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(classname); - return class_info ? class_info->class_ptr : nullptr; -} - -void gdnative_setup_interface(GDNativeInterface *p_interface) { - GDNativeInterface &gdni = *p_interface; - - gdni.version_major = VERSION_MAJOR; - gdni.version_minor = VERSION_MINOR; -#if VERSION_PATCH - gdni.version_patch = VERSION_PATCH; -#else - gdni.version_patch = 0; -#endif - gdni.version_string = VERSION_FULL_NAME; - - /* GODOT CORE */ - - gdni.mem_alloc = gdnative_alloc; - gdni.mem_realloc = gdnative_realloc; - gdni.mem_free = gdnative_free; - - gdni.print_error = gdnative_print_error; - gdni.print_warning = gdnative_print_warning; - gdni.print_script_error = gdnative_print_script_error; - - gdni.get_native_struct_size = gdnative_get_native_struct_size; - - /* GODOT VARIANT */ - - // variant general - gdni.variant_new_copy = gdnative_variant_new_copy; - gdni.variant_new_nil = gdnative_variant_new_nil; - gdni.variant_destroy = gdnative_variant_destroy; - - gdni.variant_call = gdnative_variant_call; - gdni.variant_call_static = gdnative_variant_call_static; - gdni.variant_evaluate = gdnative_variant_evaluate; - gdni.variant_set = gdnative_variant_set; - gdni.variant_set_named = gdnative_variant_set_named; - gdni.variant_set_keyed = gdnative_variant_set_keyed; - gdni.variant_set_indexed = gdnative_variant_set_indexed; - gdni.variant_get = gdnative_variant_get; - gdni.variant_get_named = gdnative_variant_get_named; - gdni.variant_get_keyed = gdnative_variant_get_keyed; - gdni.variant_get_indexed = gdnative_variant_get_indexed; - gdni.variant_iter_init = gdnative_variant_iter_init; - gdni.variant_iter_next = gdnative_variant_iter_next; - gdni.variant_iter_get = gdnative_variant_iter_get; - gdni.variant_hash = gdnative_variant_hash; - gdni.variant_recursive_hash = gdnative_variant_recursive_hash; - gdni.variant_hash_compare = gdnative_variant_hash_compare; - gdni.variant_booleanize = gdnative_variant_booleanize; - gdni.variant_duplicate = gdnative_variant_duplicate; - gdni.variant_stringify = gdnative_variant_stringify; - - gdni.variant_get_type = gdnative_variant_get_type; - gdni.variant_has_method = gdnative_variant_has_method; - gdni.variant_has_member = gdnative_variant_has_member; - gdni.variant_has_key = gdnative_variant_has_key; - gdni.variant_get_type_name = gdnative_variant_get_type_name; - gdni.variant_can_convert = gdnative_variant_can_convert; - gdni.variant_can_convert_strict = gdnative_variant_can_convert_strict; - - gdni.get_variant_from_type_constructor = gdnative_get_variant_from_type_constructor; - gdni.get_variant_to_type_constructor = gdnative_get_type_from_variant_constructor; - - // ptrcalls. - - gdni.variant_get_ptr_operator_evaluator = gdnative_variant_get_ptr_operator_evaluator; - gdni.variant_get_ptr_builtin_method = gdnative_variant_get_ptr_builtin_method; - gdni.variant_get_ptr_constructor = gdnative_variant_get_ptr_constructor; - gdni.variant_get_ptr_destructor = gdnative_variant_get_ptr_destructor; - gdni.variant_construct = gdnative_variant_construct; - gdni.variant_get_ptr_setter = gdnative_variant_get_ptr_setter; - gdni.variant_get_ptr_getter = gdnative_variant_get_ptr_getter; - gdni.variant_get_ptr_indexed_setter = gdnative_variant_get_ptr_indexed_setter; - gdni.variant_get_ptr_indexed_getter = gdnative_variant_get_ptr_indexed_getter; - gdni.variant_get_ptr_keyed_setter = gdnative_variant_get_ptr_keyed_setter; - gdni.variant_get_ptr_keyed_getter = gdnative_variant_get_ptr_keyed_getter; - gdni.variant_get_ptr_keyed_checker = gdnative_variant_get_ptr_keyed_checker; - gdni.variant_get_constant_value = gdnative_variant_get_constant_value; - gdni.variant_get_ptr_utility_function = gdnative_variant_get_ptr_utility_function; - - // extra utilities - - gdni.string_new_with_latin1_chars = gdnative_string_new_with_latin1_chars; - gdni.string_new_with_utf8_chars = gdnative_string_new_with_utf8_chars; - gdni.string_new_with_utf16_chars = gdnative_string_new_with_utf16_chars; - gdni.string_new_with_utf32_chars = gdnative_string_new_with_utf32_chars; - gdni.string_new_with_wide_chars = gdnative_string_new_with_wide_chars; - gdni.string_new_with_latin1_chars_and_len = gdnative_string_new_with_latin1_chars_and_len; - gdni.string_new_with_utf8_chars_and_len = gdnative_string_new_with_utf8_chars_and_len; - gdni.string_new_with_utf16_chars_and_len = gdnative_string_new_with_utf16_chars_and_len; - gdni.string_new_with_utf32_chars_and_len = gdnative_string_new_with_utf32_chars_and_len; - gdni.string_new_with_wide_chars_and_len = gdnative_string_new_with_wide_chars_and_len; - gdni.string_to_latin1_chars = gdnative_string_to_latin1_chars; - gdni.string_to_utf8_chars = gdnative_string_to_utf8_chars; - gdni.string_to_utf16_chars = gdnative_string_to_utf16_chars; - gdni.string_to_utf32_chars = gdnative_string_to_utf32_chars; - gdni.string_to_wide_chars = gdnative_string_to_wide_chars; - gdni.string_operator_index = gdnative_string_operator_index; - gdni.string_operator_index_const = gdnative_string_operator_index_const; - - /* Packed array functions */ - - gdni.packed_byte_array_operator_index = gdnative_packed_byte_array_operator_index; - gdni.packed_byte_array_operator_index_const = gdnative_packed_byte_array_operator_index_const; - - gdni.packed_color_array_operator_index = gdnative_packed_color_array_operator_index; - gdni.packed_color_array_operator_index_const = gdnative_packed_color_array_operator_index_const; - - gdni.packed_float32_array_operator_index = gdnative_packed_float32_array_operator_index; - gdni.packed_float32_array_operator_index_const = gdnative_packed_float32_array_operator_index_const; - gdni.packed_float64_array_operator_index = gdnative_packed_float64_array_operator_index; - gdni.packed_float64_array_operator_index_const = gdnative_packed_float64_array_operator_index_const; - - gdni.packed_int32_array_operator_index = gdnative_packed_int32_array_operator_index; - gdni.packed_int32_array_operator_index_const = gdnative_packed_int32_array_operator_index_const; - gdni.packed_int64_array_operator_index = gdnative_packed_int64_array_operator_index; - gdni.packed_int64_array_operator_index_const = gdnative_packed_int64_array_operator_index_const; - - gdni.packed_string_array_operator_index = gdnative_packed_string_array_operator_index; - gdni.packed_string_array_operator_index_const = gdnative_packed_string_array_operator_index_const; - - gdni.packed_vector2_array_operator_index = gdnative_packed_vector2_array_operator_index; - gdni.packed_vector2_array_operator_index_const = gdnative_packed_vector2_array_operator_index_const; - 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; - gdni.object_method_bind_ptrcall = gdnative_object_method_bind_ptrcall; - gdni.object_destroy = gdnative_object_destroy; - 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; - gdni.object_get_instance_id = gdnative_object_get_instance_id; - - /* SCRIPT INSTANCE */ - - gdni.script_instance_create = gdnative_script_instance_create; - - /* CLASSDB */ - - 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; - - /* CLASSDB EXTENSION */ - - //these are filled by implementation, since it will want to keep track of registered classes - gdni.classdb_register_extension_class = nullptr; - 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; - - gdni.get_library_path = nullptr; -} diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h deleted file mode 100644 index 68eed5a161..0000000000 --- a/core/extension/gdnative_interface.h +++ /dev/null @@ -1,589 +0,0 @@ -/*************************************************************************/ -/* gdnative_interface.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 GDNATIVE_INTERFACE_H -#define GDNATIVE_INTERFACE_H - -/* This is a C class header, you can copy it and use it directly in your own binders. - * Together with the JSON file, you should be able to generate any binder. - */ - -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> - -#ifndef __cplusplus -typedef uint32_t char32_t; -typedef uint16_t char16_t; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* VARIANT TYPES */ - -typedef enum { - GDNATIVE_VARIANT_TYPE_NIL, - - /* atomic types */ - GDNATIVE_VARIANT_TYPE_BOOL, - GDNATIVE_VARIANT_TYPE_INT, - GDNATIVE_VARIANT_TYPE_FLOAT, - GDNATIVE_VARIANT_TYPE_STRING, - - /* math types */ - GDNATIVE_VARIANT_TYPE_VECTOR2, - GDNATIVE_VARIANT_TYPE_VECTOR2I, - GDNATIVE_VARIANT_TYPE_RECT2, - GDNATIVE_VARIANT_TYPE_RECT2I, - GDNATIVE_VARIANT_TYPE_VECTOR3, - GDNATIVE_VARIANT_TYPE_VECTOR3I, - GDNATIVE_VARIANT_TYPE_TRANSFORM2D, - GDNATIVE_VARIANT_TYPE_VECTOR4, - GDNATIVE_VARIANT_TYPE_VECTOR4I, - GDNATIVE_VARIANT_TYPE_PLANE, - GDNATIVE_VARIANT_TYPE_QUATERNION, - GDNATIVE_VARIANT_TYPE_AABB, - GDNATIVE_VARIANT_TYPE_BASIS, - GDNATIVE_VARIANT_TYPE_TRANSFORM3D, - GDNATIVE_VARIANT_TYPE_PROJECTION, - - /* misc types */ - GDNATIVE_VARIANT_TYPE_COLOR, - GDNATIVE_VARIANT_TYPE_STRING_NAME, - GDNATIVE_VARIANT_TYPE_NODE_PATH, - GDNATIVE_VARIANT_TYPE_RID, - GDNATIVE_VARIANT_TYPE_OBJECT, - GDNATIVE_VARIANT_TYPE_CALLABLE, - GDNATIVE_VARIANT_TYPE_SIGNAL, - GDNATIVE_VARIANT_TYPE_DICTIONARY, - GDNATIVE_VARIANT_TYPE_ARRAY, - - /* typed arrays */ - GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY, - - GDNATIVE_VARIANT_TYPE_VARIANT_MAX -} GDNativeVariantType; - -typedef enum { - /* comparison */ - GDNATIVE_VARIANT_OP_EQUAL, - GDNATIVE_VARIANT_OP_NOT_EQUAL, - GDNATIVE_VARIANT_OP_LESS, - GDNATIVE_VARIANT_OP_LESS_EQUAL, - GDNATIVE_VARIANT_OP_GREATER, - GDNATIVE_VARIANT_OP_GREATER_EQUAL, - /* mathematic */ - GDNATIVE_VARIANT_OP_ADD, - GDNATIVE_VARIANT_OP_SUBTRACT, - GDNATIVE_VARIANT_OP_MULTIPLY, - GDNATIVE_VARIANT_OP_DIVIDE, - GDNATIVE_VARIANT_OP_NEGATE, - GDNATIVE_VARIANT_OP_POSITIVE, - GDNATIVE_VARIANT_OP_MODULE, - GDNATIVE_VARIANT_OP_POWER, - /* bitwise */ - GDNATIVE_VARIANT_OP_SHIFT_LEFT, - GDNATIVE_VARIANT_OP_SHIFT_RIGHT, - GDNATIVE_VARIANT_OP_BIT_AND, - GDNATIVE_VARIANT_OP_BIT_OR, - GDNATIVE_VARIANT_OP_BIT_XOR, - GDNATIVE_VARIANT_OP_BIT_NEGATE, - /* logic */ - GDNATIVE_VARIANT_OP_AND, - GDNATIVE_VARIANT_OP_OR, - GDNATIVE_VARIANT_OP_XOR, - GDNATIVE_VARIANT_OP_NOT, - /* containment */ - GDNATIVE_VARIANT_OP_IN, - GDNATIVE_VARIANT_OP_MAX - -} GDNativeVariantOperator; - -typedef void *GDNativeVariantPtr; -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; -typedef uint64_t GDObjectInstanceID; - -/* VARIANT DATA I/O */ - -typedef enum { - GDNATIVE_CALL_OK, - GDNATIVE_CALL_ERROR_INVALID_METHOD, - GDNATIVE_CALL_ERROR_INVALID_ARGUMENT, /* expected is variant type */ - GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS, /* expected is number of arguments */ - GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS, /* expected is number of arguments */ - GDNATIVE_CALL_ERROR_INSTANCE_IS_NULL, - GDNATIVE_CALL_ERROR_METHOD_NOT_CONST, /* used for const call */ -} GDNativeCallErrorType; - -typedef struct { - GDNativeCallErrorType error; - int32_t argument; - int32_t expected; -} GDNativeCallError; - -typedef void (*GDNativeVariantFromTypeConstructorFunc)(GDNativeVariantPtr, GDNativeTypePtr); -typedef void (*GDNativeTypeFromVariantConstructorFunc)(GDNativeTypePtr, GDNativeVariantPtr); -typedef void (*GDNativePtrOperatorEvaluator)(const GDNativeTypePtr p_left, const GDNativeTypePtr p_right, GDNativeTypePtr r_result); -typedef void (*GDNativePtrBuiltInMethod)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return, int p_argument_count); -typedef void (*GDNativePtrConstructor)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args); -typedef void (*GDNativePtrDestructor)(GDNativeTypePtr p_base); -typedef void (*GDNativePtrSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_value); -typedef void (*GDNativePtrGetter)(const GDNativeTypePtr p_base, GDNativeTypePtr r_value); -typedef void (*GDNativePtrIndexedSetter)(GDNativeTypePtr p_base, GDNativeInt p_index, const GDNativeTypePtr p_value); -typedef void (*GDNativePtrIndexedGetter)(const GDNativeTypePtr p_base, GDNativeInt p_index, GDNativeTypePtr r_value); -typedef void (*GDNativePtrKeyedSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_key, const GDNativeTypePtr p_value); -typedef void (*GDNativePtrKeyedGetter)(const GDNativeTypePtr p_base, const GDNativeTypePtr p_key, GDNativeTypePtr r_value); -typedef uint32_t (*GDNativePtrKeyedChecker)(const GDNativeVariantPtr p_base, const GDNativeVariantPtr p_key); -typedef void (*GDNativePtrUtilityFunction)(GDNativeTypePtr r_return, const GDNativeTypePtr *p_arguments, int p_argument_count); - -typedef GDNativeObjectPtr (*GDNativeClassConstructor)(); - -typedef void *(*GDNativeInstanceBindingCreateCallback)(void *p_token, void *p_instance); -typedef void (*GDNativeInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding); -typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDNativeBool p_reference); - -typedef struct { - GDNativeInstanceBindingCreateCallback create_callback; - GDNativeInstanceBindingFreeCallback free_callback; - GDNativeInstanceBindingReferenceCallback reference_callback; -} GDNativeInstanceBindingCallbacks; - -/* EXTENSION CLASSES */ - -typedef void *GDExtensionClassInstancePtr; - -typedef GDNativeBool (*GDNativeExtensionClassSet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value); -typedef GDNativeBool (*GDNativeExtensionClassGet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); -typedef uint64_t (*GDNativeExtensionClassGetRID)(GDExtensionClassInstancePtr p_instance); - -typedef struct { - GDNativeVariantType type; - GDNativeStringNamePtr name; - GDNativeStringNamePtr class_name; - uint32_t hint; // Bitfield of `PropertyHint` (defined in `extension_api.json`) - GDNativeStringPtr hint_string; - uint32_t usage; // Bitfield of `PropertyUsageFlags` (defined in `extension_api.json`) -} GDNativePropertyInfo; - -typedef struct { - GDNativeStringNamePtr name; - GDNativePropertyInfo return_value; - uint32_t flags; // Bitfield of `GDNativeExtensionClassMethodFlags` - int32_t id; - GDNativePropertyInfo *arguments; // array of `argument_count` size - uint32_t argument_count; - GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size - uint32_t default_argument_count; -} GDNativeMethodInfo; - -typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count); -typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list); -typedef GDNativeBool (*GDNativeExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name); -typedef GDNativeBool (*GDNativeExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); -typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what); -typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr p_out); -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 GDNativeObjectPtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata); -typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance); -typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const GDNativeStringNamePtr p_name); - -typedef struct { - GDNativeBool is_virtual; - GDNativeBool is_abstract; - GDNativeExtensionClassSet set_func; - GDNativeExtensionClassGet get_func; - GDNativeExtensionClassGetPropertyList get_property_list_func; - GDNativeExtensionClassFreePropertyList free_property_list_func; - GDNativeExtensionClassPropertyCanRevert property_can_revert_func; - GDNativeExtensionClassPropertyGetRevert property_get_revert_func; - GDNativeExtensionClassNotification notification_func; - GDNativeExtensionClassToString to_string_func; - GDNativeExtensionClassReference reference_func; - GDNativeExtensionClassUnreference unreference_func; - GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */ - GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */ - GDNativeExtensionClassGetVirtual get_virtual_func; - GDNativeExtensionClassGetRID get_rid_func; - void *class_userdata; -} GDNativeExtensionClassCreationInfo; - -typedef void *GDNativeExtensionClassLibraryPtr; - -/* Method */ - -typedef enum { - GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL = 1, - GDNATIVE_EXTENSION_METHOD_FLAG_EDITOR = 2, - GDNATIVE_EXTENSION_METHOD_FLAG_CONST = 4, - GDNATIVE_EXTENSION_METHOD_FLAG_VIRTUAL = 8, - GDNATIVE_EXTENSION_METHOD_FLAG_VARARG = 16, - GDNATIVE_EXTENSION_METHOD_FLAG_STATIC = 32, - GDNATIVE_EXTENSION_METHOD_FLAGS_DEFAULT = GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL, -} GDNativeExtensionClassMethodFlags; - -typedef enum { - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT8, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT16, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT8, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT16, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE -} GDNativeExtensionClassMethodArgumentMetadata; - -typedef void (*GDNativeExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); -typedef void (*GDNativeExtensionClassMethodPtrCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); - -typedef struct { - GDNativeStringNamePtr name; - void *method_userdata; - GDNativeExtensionClassMethodCall call_func; - GDNativeExtensionClassMethodPtrCall ptrcall_func; - uint32_t method_flags; // Bitfield of `GDNativeExtensionClassMethodFlags` - uint32_t argument_count; - GDNativeBool has_return_value; - GDNativePropertyInfo *return_value_info; // Ignored if `has_return_value` is false - GDNativeExtensionClassMethodArgumentMetadata return_value_metadata; // Ignored if `has_return_value` is false - /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */ - GDNativePropertyInfo *aguments_info; // array of `argument_count` size - GDNativeExtensionClassMethodArgumentMetadata *aguments_metadata; // array of `argument_count` size - uint32_t default_argument_count; - GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size -} GDNativeExtensionClassMethodInfo; - -/* SCRIPT INSTANCE EXTENSION */ - -typedef void *GDNativeExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation - -typedef GDNativeBool (*GDNativeExtensionScriptInstanceSet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value); -typedef GDNativeBool (*GDNativeExtensionScriptInstanceGet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); -typedef const GDNativePropertyInfo *(*GDNativeExtensionScriptInstanceGetPropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count); -typedef void (*GDNativeExtensionScriptInstanceFreePropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativePropertyInfo *p_list); - -typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyCanRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name); -typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyGetRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); - -typedef GDNativeObjectPtr (*GDNativeExtensionScriptInstanceGetOwner)(GDNativeExtensionScriptInstanceDataPtr p_instance); -typedef void (*GDNativeExtensionScriptInstancePropertyStateAdd)(const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value, void *p_userdata); -typedef void (*GDNativeExtensionScriptInstanceGetPropertyState)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeExtensionScriptInstancePropertyStateAdd p_add_func, void *p_userdata); - -typedef const GDNativeMethodInfo *(*GDNativeExtensionScriptInstanceGetMethodList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count); -typedef void (*GDNativeExtensionScriptInstanceFreeMethodList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeMethodInfo *p_list); - -typedef GDNativeBool (*GDNativeExtensionScriptInstanceHasMethod)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name); - -typedef void (*GDNativeExtensionScriptInstanceCall)(GDNativeExtensionScriptInstanceDataPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); -typedef void (*GDNativeExtensionScriptInstanceNotification)(GDNativeExtensionScriptInstanceDataPtr p_instance, int32_t p_what); -typedef void (*GDNativeExtensionScriptInstanceToString)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr r_out); - -typedef void (*GDNativeExtensionScriptInstanceRefCountIncremented)(GDNativeExtensionScriptInstanceDataPtr p_instance); -typedef GDNativeBool (*GDNativeExtensionScriptInstanceRefCountDecremented)(GDNativeExtensionScriptInstanceDataPtr p_instance); - -typedef GDNativeObjectPtr (*GDNativeExtensionScriptInstanceGetScript)(GDNativeExtensionScriptInstanceDataPtr p_instance); -typedef GDNativeBool (*GDNativeExtensionScriptInstanceIsPlaceholder)(GDNativeExtensionScriptInstanceDataPtr p_instance); - -typedef void *GDNativeExtensionScriptLanguagePtr; - -typedef GDNativeExtensionScriptLanguagePtr (*GDNativeExtensionScriptInstanceGetLanguage)(GDNativeExtensionScriptInstanceDataPtr p_instance); - -typedef void (*GDNativeExtensionScriptInstanceFree)(GDNativeExtensionScriptInstanceDataPtr p_instance); - -typedef void *GDNativeScriptInstancePtr; // Pointer to ScriptInstance. - -typedef struct { - GDNativeExtensionScriptInstanceSet set_func; - GDNativeExtensionScriptInstanceGet get_func; - GDNativeExtensionScriptInstanceGetPropertyList get_property_list_func; - GDNativeExtensionScriptInstanceFreePropertyList free_property_list_func; - - GDNativeExtensionScriptInstancePropertyCanRevert property_can_revert_func; - GDNativeExtensionScriptInstancePropertyGetRevert property_get_revert_func; - - GDNativeExtensionScriptInstanceGetOwner get_owner_func; - GDNativeExtensionScriptInstanceGetPropertyState get_property_state_func; - - GDNativeExtensionScriptInstanceGetMethodList get_method_list_func; - GDNativeExtensionScriptInstanceFreeMethodList free_method_list_func; - - GDNativeExtensionScriptInstanceHasMethod has_method_func; - - GDNativeExtensionScriptInstanceCall call_func; - GDNativeExtensionScriptInstanceNotification notification_func; - - GDNativeExtensionScriptInstanceToString to_string_func; - - GDNativeExtensionScriptInstanceRefCountIncremented refcount_incremented_func; - GDNativeExtensionScriptInstanceRefCountDecremented refcount_decremented_func; - - GDNativeExtensionScriptInstanceGetScript get_script_func; - - GDNativeExtensionScriptInstanceIsPlaceholder is_placeholder_func; - - GDNativeExtensionScriptInstanceSet set_fallback_func; - GDNativeExtensionScriptInstanceGet get_fallback_func; - - GDNativeExtensionScriptInstanceGetLanguage get_language_func; - - GDNativeExtensionScriptInstanceFree free_func; - -} GDNativeExtensionScriptInstanceInfo; - -/* INTERFACE */ - -typedef struct { - uint32_t version_major; - uint32_t version_minor; - uint32_t version_patch; - const char *version_string; - - /* GODOT CORE */ - void *(*mem_alloc)(size_t p_bytes); - void *(*mem_realloc)(void *p_ptr, size_t p_bytes); - void (*mem_free)(void *p_ptr); - - void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); - void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); - void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); - - uint64_t (*get_native_struct_size)(const GDNativeStringNamePtr p_name); - - /* GODOT VARIANT */ - - /* variant general */ - void (*variant_new_copy)(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src); - void (*variant_new_nil)(GDNativeVariantPtr r_dest); - void (*variant_destroy)(GDNativeVariantPtr p_self); - - /* variant type */ - void (*variant_call)(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); - void (*variant_call_static)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); - void (*variant_evaluate)(GDNativeVariantOperator p_op, const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_return, GDNativeBool *r_valid); - void (*variant_set)(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid); - void (*variant_set_named)(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid); - void (*variant_set_keyed)(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid); - void (*variant_set_indexed)(GDNativeVariantPtr p_self, GDNativeInt p_index, const GDNativeVariantPtr p_value, GDNativeBool *r_valid, GDNativeBool *r_oob); - void (*variant_get)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid); - void (*variant_get_named)(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid); - void (*variant_get_keyed)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid); - void (*variant_get_indexed)(const GDNativeVariantPtr p_self, GDNativeInt p_index, GDNativeVariantPtr r_ret, GDNativeBool *r_valid, GDNativeBool *r_oob); - GDNativeBool (*variant_iter_init)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid); - GDNativeBool (*variant_iter_next)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid); - void (*variant_iter_get)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid); - GDNativeInt (*variant_hash)(const GDNativeVariantPtr p_self); - GDNativeInt (*variant_recursive_hash)(const GDNativeVariantPtr p_self, GDNativeInt p_recursion_count); - GDNativeBool (*variant_hash_compare)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other); - GDNativeBool (*variant_booleanize)(const GDNativeVariantPtr p_self); - void (*variant_duplicate)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep); - void (*variant_stringify)(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret); - - GDNativeVariantType (*variant_get_type)(const GDNativeVariantPtr p_self); - GDNativeBool (*variant_has_method)(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method); - GDNativeBool (*variant_has_member)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member); - GDNativeBool (*variant_has_key)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeBool *r_valid); - void (*variant_get_type_name)(GDNativeVariantType p_type, GDNativeStringPtr r_name); - GDNativeBool (*variant_can_convert)(GDNativeVariantType p_from, GDNativeVariantType p_to); - GDNativeBool (*variant_can_convert_strict)(GDNativeVariantType p_from, GDNativeVariantType p_to); - - /* ptrcalls */ - GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type); - GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type); - GDNativePtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b); - GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, GDNativeInt p_hash); - GDNativePtrConstructor (*variant_get_ptr_constructor)(GDNativeVariantType p_type, int32_t p_constructor); - GDNativePtrDestructor (*variant_get_ptr_destructor)(GDNativeVariantType p_type); - void (*variant_construct)(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error); - GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member); - GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member); - GDNativePtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDNativeVariantType p_type); - GDNativePtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDNativeVariantType p_type); - GDNativePtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDNativeVariantType p_type); - GDNativePtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDNativeVariantType p_type); - GDNativePtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDNativeVariantType p_type); - void (*variant_get_constant_value)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_constant, GDNativeVariantPtr r_ret); - GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const GDNativeStringNamePtr p_function, GDNativeInt p_hash); - - /* extra utilities */ - - void (*string_new_with_latin1_chars)(GDNativeStringPtr r_dest, const char *p_contents); - void (*string_new_with_utf8_chars)(GDNativeStringPtr r_dest, const char *p_contents); - void (*string_new_with_utf16_chars)(GDNativeStringPtr r_dest, const char16_t *p_contents); - void (*string_new_with_utf32_chars)(GDNativeStringPtr r_dest, const char32_t *p_contents); - void (*string_new_with_wide_chars)(GDNativeStringPtr r_dest, const wchar_t *p_contents); - void (*string_new_with_latin1_chars_and_len)(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size); - void (*string_new_with_utf8_chars_and_len)(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size); - void (*string_new_with_utf16_chars_and_len)(GDNativeStringPtr r_dest, const char16_t *p_contents, const GDNativeInt p_size); - void (*string_new_with_utf32_chars_and_len)(GDNativeStringPtr r_dest, const char32_t *p_contents, const GDNativeInt p_size); - void (*string_new_with_wide_chars_and_len)(GDNativeStringPtr r_dest, const wchar_t *p_contents, const GDNativeInt p_size); - /* Information about the following functions: - * - The return value is the resulting encoded string length. - * - The length returned is in characters, not in bytes. It also does not include a trailing zero. - * - These functions also do not write trailing zero, If you need it, write it yourself at the position indicated by the length (and make sure to allocate it). - * - Passing NULL in r_text means only the length is computed (again, without including trailing zero). - * - p_max_write_length argument is in characters, not bytes. It will be ignored if r_text is NULL. - * - p_max_write_length argument does not affect the return value, it's only to cap write length. - */ - GDNativeInt (*string_to_latin1_chars)(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length); - GDNativeInt (*string_to_utf8_chars)(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length); - GDNativeInt (*string_to_utf16_chars)(const GDNativeStringPtr p_self, char16_t *r_text, GDNativeInt p_max_write_length); - GDNativeInt (*string_to_utf32_chars)(const GDNativeStringPtr p_self, char32_t *r_text, GDNativeInt p_max_write_length); - GDNativeInt (*string_to_wide_chars)(const GDNativeStringPtr p_self, wchar_t *r_text, GDNativeInt p_max_write_length); - char32_t *(*string_operator_index)(GDNativeStringPtr p_self, GDNativeInt p_index); - const char32_t *(*string_operator_index_const)(const GDNativeStringPtr p_self, GDNativeInt p_index); - - /* Packed array functions */ - - uint8_t *(*packed_byte_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedByteArray - const uint8_t *(*packed_byte_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedByteArray - - GDNativeTypePtr (*packed_color_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedColorArray, returns Color ptr - GDNativeTypePtr (*packed_color_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedColorArray, returns Color ptr - - float *(*packed_float32_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat32Array - const float *(*packed_float32_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat32Array - double *(*packed_float64_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat64Array - const double *(*packed_float64_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat64Array - - int32_t *(*packed_int32_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array - const int32_t *(*packed_int32_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array - int64_t *(*packed_int64_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array - const int64_t *(*packed_int64_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array - - GDNativeStringPtr (*packed_string_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedStringArray - GDNativeStringPtr (*packed_string_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedStringArray - - GDNativeTypePtr (*packed_vector2_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr - GDNativeTypePtr (*packed_vector2_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr - 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 GDNativeStringNamePtr 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 GDNativeStringNamePtr 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); - - /* SCRIPT INSTANCE */ - - GDNativeScriptInstancePtr (*script_instance_create)(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data); - - /* CLASSDB */ - GDNativeObjectPtr (*classdb_construct_object)(const GDNativeStringNamePtr 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 GDNativeStringNamePtr p_classname, const GDNativeStringNamePtr p_methodname, GDNativeInt p_hash); - void *(*classdb_get_class_tag)(const GDNativeStringNamePtr p_classname); - - /* CLASSDB EXTENSION */ - - // Provided parameters for `classdb_register_extension_*` can be safely freed once the function returns - void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); - void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); - void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); - void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter); - void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_group_name, const GDNativeStringPtr p_prefix); - void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_subgroup_name, const GDNativeStringPtr p_prefix); - void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count); - void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */ - - void (*get_library_path)(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path); - -} GDNativeInterface; - -/* INITIALIZATION */ - -typedef enum { - GDNATIVE_INITIALIZATION_CORE, - GDNATIVE_INITIALIZATION_SERVERS, - GDNATIVE_INITIALIZATION_SCENE, - GDNATIVE_INITIALIZATION_EDITOR, - GDNATIVE_MAX_INITIALIZATION_LEVEL, -} GDNativeInitializationLevel; - -typedef struct { - /* Minimum initialization level required. - * If Core or Servers, the extension needs editor or game restart to take effect */ - GDNativeInitializationLevel minimum_initialization_level; - /* Up to the user to supply when initializing */ - void *userdata; - /* This function will be called multiple times for each initialization level. */ - void (*initialize)(void *userdata, GDNativeInitializationLevel p_level); - void (*deinitialize)(void *userdata, GDNativeInitializationLevel p_level); -} GDNativeInitialization; - -/* Define a C function prototype that implements the function below and expose it to dlopen() (or similar). - * It will be called on initialization. The name must be an unique one specified in the .gdextension config file. - */ - -typedef GDNativeBool (*GDNativeInitializationFunction)(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization); - -#ifdef __cplusplus -} -#endif - -#endif // GDNATIVE_INTERFACE_H diff --git a/core/extension/make_interface_dumper.py b/core/extension/make_interface_dumper.py index cc85c728d5..a8af0e9ff6 100644 --- a/core/extension/make_interface_dumper.py +++ b/core/extension/make_interface_dumper.py @@ -6,17 +6,17 @@ def run(target, source, env): g.write( """/* THIS FILE IS GENERATED DO NOT EDIT */ -#ifndef GDNATIVE_INTERFACE_DUMP_H -#define GDNATIVE_INTERFACE_DUMP_H +#ifndef GDEXTENSION_INTERFACE_DUMP_H +#define GDEXTENSION_INTERFACE_DUMP_H #ifdef TOOLS_ENABLED #include "core/io/file_access.h" #include "core/string/ustring.h" -class GDNativeInterfaceDump { +class GDExtensionInterfaceDump { private: - static constexpr char const *gdnative_interface_dump =""" + static constexpr char const *gdextension_interface_dump =""" ) for line in f: g.write('"' + line.rstrip().replace('"', '\\"') + '\\n"\n') @@ -25,16 +25,16 @@ class GDNativeInterfaceDump { g.write( """ public: - static void generate_gdnative_interface_file(const String &p_path) { + static void generate_gdextension_interface_file(const String &p_path) { Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE); - CharString cs(gdnative_interface_dump); + CharString cs(gdextension_interface_dump); fa->store_buffer((const uint8_t *)cs.ptr(), cs.length()); }; }; #endif // TOOLS_ENABLED -#endif // GDNATIVE_INTERFACE_DUMP_H +#endif // GDEXTENSION_INTERFACE_DUMP_H """ ) g.close() diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt index 774d1be6b5..dcb6aefb00 100644 --- a/core/input/gamecontrollerdb.txt +++ b/core/input/gamecontrollerdb.txt @@ -67,9 +67,11 @@ 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, -03000000c82d00000260000000000000,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, -03000000c82d00000261000000000000,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, -03000000c82d00001330000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,paddle1:b23,paddle2:b19,platform:Windows, +03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001130000000000000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001230000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001330000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, 03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00001890000000000000,8BitDo Zero 2,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, 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, @@ -201,6 +203,7 @@ 03000000ac0500005b05000000000000,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, 03000000ac0500002d02000000000000,GameSir G4,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, 03000000ac0500004d04000000000000,GameSir G4,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, +03000000ac0500001a06000000000000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger: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 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, @@ -296,7 +299,8 @@ 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, +03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows, +03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows, 03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows, 03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows, 03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, @@ -369,6 +373,7 @@ 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, +030000008f0e00001330000000000000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Windows, 03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,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, 03000000790000003018000000000000,Mayflash F300 Arcade Joystick,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,Mayflash F300 Elite 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, @@ -377,8 +382,9 @@ 03000000242f00007300000000000000,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:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, 0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows, 030000008f0e00001030000000000000,Mayflash Sega Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows, -0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, 03000000790000000318000000000000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, 03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000790000002418000000000000,Mega Drive Controller,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, @@ -443,6 +449,7 @@ 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,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, 030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows, +03000000666600006706000000000000,PlayStation Adapter,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, 03000000e30500009605000000000000,PlayStation 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: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, 03000000632500002306000000000000,PlayStation 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, @@ -464,7 +471,6 @@ 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, 03000000250900008888000000000000,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, -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, 03000000151a00006222000000000000,PS2 Dual Plus 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, @@ -505,7 +511,8 @@ 030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -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,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +030000004c050000f20d000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000830500005020000000000000,PSX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Windows, 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, @@ -554,6 +561,7 @@ 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 Sega Saturn Classic Controller,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 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:Windows, +03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Windows, 0300000000f000000300000000000000,RetroUSB RetroPad,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, 0300000000f00000f100000000000000,RetroUSB Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,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, @@ -741,9 +749,8 @@ 03000000450c00002043000000000000,Xeox 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, 03000000172700004431000000000000,Xiaomi 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, -03000000bc2000005060000000000000,Xiaomi XMGP01YM,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,-lefty:-a1,+lefty:+a2,rightx:a3,-righty:-a4,+righty:+a5,lefttrigger:b8,righttrigger:b9,platform:Windows, -03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,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, +03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000bc2000005060000000000000,Xiaomi XMGP01YM,+lefty:+a2,+righty:+a5,-lefty:-a1,-righty:-a4,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,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,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, 030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,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, @@ -789,8 +796,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00004028000000010000,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: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, -03000000c82d00000261000000010000,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, +03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001130000000020000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001330000001000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001330000000020000,8BitDo Ultimate Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000a00500003232000009010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000c82d00001890000001000000,8BitDo Zero 2,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, @@ -817,10 +827,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, +03000000ac0500001a06000002020000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform: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 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, +03000000ff1100003133000007010000,GameWare PC Control Pad,a:b2,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:a3,righty:a4,start:b11,x:b3,y:b0,platform:Mac OS X, 030000007d0400000540000001010000,Gravis Eliminator 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, 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 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, @@ -836,11 +848,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 030000000d0f00003801000008010000,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:Mac OS X, 030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro,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, +030000000d0f0000aa00000072050000,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: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, +03000000242e0000ff0b000000010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Mac OS X, 03000000790000004e95000000010000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Mac OS X, 03000000830500006020000000000000,iBuffalo Gamepad,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, 03000000ef0500000300000000020000,InterAct 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, @@ -858,10 +871,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006d0400001fc2000000000000,Logitech F710,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,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, 03000000380700005032000000010000,Mad Catz PS3 Fightpad 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: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, -03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S+,a: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, +03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,a: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, 03000000380700005082000000010000,Mad Catz PS4 Fightpad 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:Mac OS X, -03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S+,a: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, +03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,a: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,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, +030000008f0e00001330000011010000,Mayflash Controller Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,platform:Mac OS X, 03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,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, @@ -886,8 +900,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Mac OS X, 030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X, +030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X, 030000006f0e00000901000002010000,PDP Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform: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, +03000000666600006706000088020000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X, 030000004c050000da0c000000010000,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: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, @@ -899,8 +915,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +030000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 03000000222c00000225000000010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000222c00000020000000010000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, @@ -919,6 +937,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, +03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Mac OS X, 030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000c6240000fefa000000000000,Rock Candy PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, @@ -937,14 +956,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, -050000004e696d6275732b008b000000,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, 03000000381000003014000000000000,SteelSeries Stratus Duo,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, 03000000381000003114000000000000,SteelSeries Stratus Duo,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, 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, 030000000d0f0000f600000000010000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 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, @@ -954,6 +972,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000571d00002000000021000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X, 030000005f140000c501000000020000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, +03000000632500002605000000010000,Uberwith Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, @@ -965,6 +984,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000050b000003090000,Xbox Elite Controller Series 2,a:b0,b:b1,back:b31,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b53,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:Mac OS X, 030000005e040000130b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000005e040000200b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000200b000013050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, @@ -975,8 +995,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c62400003a54000000000000,Xbox One PowerA 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, +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,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000005e040000130b000013050000,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, +030000005e040000130b000015050000,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, 03000000172700004431000029010000,XiaoMi 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,a: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,a: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, @@ -1008,6 +1029,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001030000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000231000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, @@ -1028,9 +1050,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00001290000011010000,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00000161000000010000,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:Linux, 05000000c82d00006228000000010000,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000260000011010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001130000011010000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001230000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00001330000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, 05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00001890000011010000,8BitDo Zero 2,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:Linux, @@ -1069,10 +1095,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000c31100000791000011010000,Be1 GC101 Controller 1.03,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000005e0400008e02000003030000,Be1 GC101 Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000bc2000004d50000011010000,BEITONG A1T2 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000bc2000000055000001000000,BETOP AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 030000006b1400000209000011010000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -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, @@ -1090,6 +1116,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 03000000ac0500005b05000010010000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, @@ -1099,6 +1126,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000008f0e00000800000010010000,Gasia PlayStation Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 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, +190000004b4800000010000000010000,GO-Advance Controller,a:b1,b:b0,back:b10,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,leftshoulder:b4,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b13,start:b15,x:b2,y:b3,platform:Linux, +190000004b4800000010000001010000,GO-Advance Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b13,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b16,righttrigger:b15,start:b17,x:b2,y:b3,platform:Linux, +190000004b4800000011000000010000,GO-Super Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b2,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 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:Linux, @@ -1113,6 +1143,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000632500002605000010010000,HJDX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000000d0f00000d00000000010000,Hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, 030000000d0f00006d00000020010000,Hori EDGE 301,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00008400000011010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 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 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, @@ -1139,7 +1170,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 050000000d0f0000f600000001000000,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, 03000000341a000005f7000010010000,HuiJia GameCube Controller Adapter,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, +05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux, +03000000242e0000ff0b000011010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Linux, 03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, 050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -1191,6 +1223,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000380700003847000090040000,Mad Catz 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, 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, +030000008f0e00001330000010010000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Linux, 03000000790000004318000010010000,Mayflash GameCube 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, 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, 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, @@ -1240,6 +1273,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, +030000009b2800008000000020020000,Nintendo Classic Controller,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux, 030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux, 03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux, 060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, @@ -1268,7 +1302,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000362800000100000003010000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, 05000000362800000100000004010000,OUYA Controller,a:b0,b:b3,back:b14,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b16,x:b1,y:b2,platform:Linux, 03000000830500005020000010010000,Padix Rockfire PlayStation 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 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 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 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 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, @@ -1283,6 +1316,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e00000901000011010000,PDP Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e0000a802000023020000,PDP Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 030000006f0e0000a702000023020000,PDP Xbox One Raven Black,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000666600006706000000010000,PlayStation Adapter,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, 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, @@ -1326,10 +1360,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -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,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000f20d000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform: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, 03000000222c00000225000011010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000222c00000025000011010000,Qanba Dragon Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, @@ -1341,7 +1377,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000009b2800003200000001010000,Raphnet GC and N64 Adapter,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 GC and N64 Adapter,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, 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 PS4 Evo Arcade Stick,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, @@ -1356,9 +1391,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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,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, +190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,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, 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, 00000000526574726f53746f6e653200,RetroStone 2 Controller,a:b1,b:b0,back:b10,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,platform:Linux, +03000000341200000400000000010000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform: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, @@ -1414,9 +1451,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,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, +03000000457500000401000011010000,SZMY Power DS4 Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 03000000457500002211000010010000,SZMY Power Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 030000008f0e00001431000010010000,SZMY Power PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux, +03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000004f04000015b3000001010000,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: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, 030000004f04000020b3000010010000,Thrustmaster 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:Linux, @@ -1449,6 +1488,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e00000302000011010000,Victrix Pro 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:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e00000702000011010000,Victrix Pro Fightstick 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 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, +05000000434f4d4d414e440000000000,VX Gaming Command Series,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, 0000000058626f782033363020576900,Xbox 360 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, 030000005e0400001907000000010000,Xbox 360 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, 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, @@ -1486,8 +1526,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000005e040000130b000013050000,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,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 060000005e040000120b00000b050000,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, 030000005e040000120b000007050000,Xbox Series X 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,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000130b000007050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000130b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000005e040000130b000007050000,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:Linux, 050000005e040000200b000013050000,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:Linux, 03000000450c00002043000010010000,XEOX 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, 05000000172700004431000029010000,XiaoMi 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, @@ -1551,13 +1591,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 65323563303231646531383162646335,8BitDo SN30,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,rightx:a2,righty:a3,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, +05000000c82d000002600000ffff0f00,8BitDo SN30 Pro Plus,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, 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, 38426974446f20534e33302050726f2b,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,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, 536f6e7920436f6d707574657220456e,8BitDo SN30 Pro Plus,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, 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,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,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,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, @@ -1580,7 +1620,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 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, 484f524920434f2e2c4c54442e203130,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, @@ -1588,6 +1627,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 30306539356238653637313730656134,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, +48797065726b696e2050616400000000,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android, +62333331353131353034386136626636,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android, +31306635363562663834633739396333,Hyperkin N64 Adapter,a:b1,b:b19,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +5368616e57616e202020202048797065,Hyperkin N64 Adapter,a:b1,b:b19,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,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, 532e542e442e20496e74657261637420,InterAct HammerHead FX,a:b23,b:b24,back:b30,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b22,lefttrigger:b28,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b25,righttrigger:b29,rightx:a2,righty:a3,start:b31,x:b20,y:b21,platform:Android, @@ -1604,6 +1647,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 4c6f6769746563682047616d65706164,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, 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, +39653365373864633935383236363438,Logitech G Cloud,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, 416d617a6f6e2047616d6520436f6e74,Luna 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:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, 4c756e612047616d6570616400000000,Luna 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, 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, @@ -1642,6 +1686,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 4f5559412047616d6520436f6e74726f,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b6,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b19,platform:Android, 506572666f726d616e63652044657369,PDP PS3 Rock Candy Controller,a:b1,b:b17,back:h0.2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android, 62653335326261303663356263626339,PlayStation Classic Controller,a:b19,b:b1,back:b17,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android, +536f6e7920496e746572616374697665,PlayStation 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,misc1:b8,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +576972656c65737320436f6e74726f6c,PlayStation 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, 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, 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, @@ -1661,20 +1707,21 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 34613139376634626133336530386430,PS4 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, 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, 37626233336235343937333961353732,PS4 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, +37626464343430636562316661643863,PS4 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, 38393161636261653636653532386639,PS4 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, -536f6e7920496e746572616374697665,PS4 Controller,a:b0,b:b0,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, -576972656c65737320436f6e74726f6c,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, 63313733393535663339656564343962,PS4 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, 63393662363836383439353064663939,PS4 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, 65366465656364636137653363376531,PS4 Controller,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 Controller,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, 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, +050000004c050000e60c0000ffff3f00,PS5 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, 32346465346533616263386539323932,PS5 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, 32633532643734376632656664383733,PS5 Controller,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, 37363764353731323963323639666565,PS5 Controller,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,PS5 Controller,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,PS5 Controller,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,misc1:b8,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,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, +05000000f8270000bf0b0000ffff3f00,Razer Kishi,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, 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, @@ -1686,6 +1733,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b6,platform:Android, +37393234373533633333323633646531,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android, +5365616c6965436f6d707574696e6720,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android, +526574726f5553422e636f6d20534e45,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android, +64643037633038386238303966376137,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android, 33373336396634316434323337666361,RumblePad 2,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android, 66386565396238363534313863353065,Sanwa PlayOnline Mobile,a:b21,b:b22,back:b23,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b24,platform:Android, 32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, @@ -1706,6 +1757,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, 0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android, 35306436396437373135383665646464,SteelSeries Nimbus Plus,a:b0,b:b1,leftshoulder:b3,leftstick:b17,lefttrigger:b9,leftx:a0,rightshoulder:b20,rightstick:b18,righttrigger:b10,rightx:a2,x:b19,y:b2,platform:Android, +54475a20436f6e74726f6c6c65720000,TGZ Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +62363434353532386238336663643836,TGZ Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 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 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:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, @@ -1749,9 +1802,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, 4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, 4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS, +050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,platform:iOS, 050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.1,+lefty:h0.2,-leftx:h0.4,-lefty:h0.8,dpdown:b2,dpleft:b0,dpright:b3,dpup:b1,leftshoulder:b4,misc1:b6,rightshoulder:b5,platform:iOS, +050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),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, 050000007e0500000e200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,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:b3,y:b2,platform:iOS, 050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+rightx:h0.4,+righty:h0.8,-rightx:h0.1,-righty:h0.2,a:b1,b:b0,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b3,y:b2,platform:iOS, +050000007e05000009200000df870000,Nintendo Switch Pro Controller,a:b1,b:b0,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:b3,y:b2,platform:iOS, 050000007e05000009200000ff870000,Nintendo Switch Pro 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, 050000004c050000cc090000df070000,PS4 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, 050000004c050000cc090000df870001,PS4 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, diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 9dc071de9c..0a32b4bf68 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -1562,7 +1562,7 @@ String InputEventMIDI::as_text() const { } String InputEventMIDI::to_string() { - return vformat("InputEventMIDI: channel=%d, message=%d, pitch=%d, velocity=%d, pressure=%d", channel, message, pitch, velocity, pressure); + return vformat("InputEventMIDI: channel=%d, message=%d, pitch=%d, velocity=%d, pressure=%d, controller_number=%d, controller_value=%d", channel, message, pitch, velocity, pressure, controller_number, controller_value); } void InputEventMIDI::_bind_methods() { diff --git a/core/input/shortcut.cpp b/core/input/shortcut.cpp index 9eeeb449ba..e74ccb11bb 100644 --- a/core/input/shortcut.cpp +++ b/core/input/shortcut.cpp @@ -107,7 +107,7 @@ void Shortcut::_bind_methods() { 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::ARRAY, "events", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")), "set_events", "get_events"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "events", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("InputEvent")), "set_events", "get_events"); } bool Shortcut::is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2) { diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index cb25564342..0ceb300f97 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -690,7 +690,7 @@ void FileAccess::store_var(const Variant &p_var, bool p_full_objects) { _store_buffer(buff); } -Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_error) { +Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_error) { Ref<FileAccess> f = FileAccess::open(p_path, READ, r_error); if (f.is_null()) { if (r_error) { // if error requested, do not throw error @@ -706,7 +706,7 @@ Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_err String FileAccess::get_file_as_string(const String &p_path, Error *r_error) { Error err; - Vector<uint8_t> array = get_file_as_array(p_path, &err); + Vector<uint8_t> array = get_file_as_bytes(p_path, &err); if (r_error) { *r_error = err; } @@ -810,6 +810,9 @@ void FileAccess::_bind_methods() { ClassDB::bind_static_method("FileAccess", D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &FileAccess::open_compressed, DEFVAL(0)); ClassDB::bind_static_method("FileAccess", D_METHOD("get_open_error"), &FileAccess::get_open_error); + ClassDB::bind_static_method("FileAccess", D_METHOD("get_file_as_bytes", "path"), &FileAccess::_get_file_as_bytes); + ClassDB::bind_static_method("FileAccess", D_METHOD("get_file_as_string", "path"), &FileAccess::_get_file_as_string); + ClassDB::bind_method(D_METHOD("flush"), &FileAccess::flush); ClassDB::bind_method(D_METHOD("get_path"), &FileAccess::get_path); ClassDB::bind_method(D_METHOD("get_path_absolute"), &FileAccess::get_path_absolute); diff --git a/core/io/file_access.h b/core/io/file_access.h index 8ca44306a0..54a0235333 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -192,9 +192,12 @@ public: static String get_sha256(const String &p_file); static String get_multiple_md5(const Vector<String> &p_file); - static Vector<uint8_t> get_file_as_array(const String &p_path, Error *r_error = nullptr); + static Vector<uint8_t> get_file_as_bytes(const String &p_path, Error *r_error = nullptr); static String get_file_as_string(const String &p_path, Error *r_error = nullptr); + static PackedByteArray _get_file_as_bytes(const String &p_path) { return get_file_as_bytes(p_path); } + static String _get_file_as_string(const String &p_path) { return get_file_as_string(p_path); }; + template <class T> static void make_default(AccessType p_access) { create_func[p_access] = _create_builtin<T>; diff --git a/core/io/image.cpp b/core/io/image.cpp index 65addaf964..a2e1bc22be 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -173,6 +173,14 @@ int Image::get_format_pixel_size(Format p_format) { return 1; case FORMAT_DXT5_RA_AS_RG: return 1; + case FORMAT_ASTC_4x4: + return 1; + case FORMAT_ASTC_4x4_HDR: + return 1; + case FORMAT_ASTC_8x8: + return 1; + case FORMAT_ASTC_8x8_HDR: + return 1; case FORMAT_MAX: { } } @@ -213,7 +221,18 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { r_h = 4; } break; + case FORMAT_ASTC_4x4: + case FORMAT_ASTC_4x4_HDR: { + r_w = 4; + r_h = 4; + + } break; + case FORMAT_ASTC_8x8: + case FORMAT_ASTC_8x8_HDR: { + r_w = 8; + r_h = 8; + } break; default: { r_w = 1; r_h = 1; @@ -222,7 +241,9 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { } int Image::get_format_pixel_rshift(Format p_format) { - if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) { + if (p_format == FORMAT_ASTC_8x8) { + return 2; + } else if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) { return 1; } else { return 0; @@ -260,6 +281,14 @@ int Image::get_format_block_size(Format p_format) { { return 4; } + case FORMAT_ASTC_4x4: + case FORMAT_ASTC_4x4_HDR: { + return 4; + } + case FORMAT_ASTC_8x8: + case FORMAT_ASTC_8x8_HDR: { + return 8; + } default: { } } @@ -1341,78 +1370,126 @@ void Image::crop(int p_width, int p_height) { void Image::rotate_90(ClockDirection p_direction) { ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats."); - ERR_FAIL_COND_MSG(width <= 1, "The Image width specified (" + itos(width) + " pixels) must be greater than 1 pixels."); - ERR_FAIL_COND_MSG(height <= 1, "The Image height specified (" + itos(height) + " pixels) must be greater than 1 pixels."); - - int saved_width = height; - int saved_height = width; - - if (width != height) { - int n = MAX(width, height); - resize(n, n, INTERPOLATE_NEAREST); - } + ERR_FAIL_COND_MSG(width <= 0, "The Image width specified (" + itos(width) + " pixels) must be greater than 0 pixels."); + ERR_FAIL_COND_MSG(height <= 0, "The Image height specified (" + itos(height) + " pixels) must be greater than 0 pixels."); bool used_mipmaps = has_mipmaps(); if (used_mipmaps) { clear_mipmaps(); } + // In-place 90 degrees rotation by following the permutation cycles. { - uint8_t *w = data.ptrw(); - uint8_t src[16]; - uint8_t dst[16]; + // Explanation by example (clockwise): + // + // abc da + // def -> eb + // fc + // + // In memory: + // 012345 012345 + // abcdef -> daebfc + // + // Permutation cycles: + // (0 --a--> 1 --b--> 3 --d--> 0) + // (2 --c--> 5 --f--> 4 --e--> 2) + // + // Applying cycles (backwards): + // 0->s s=a (store) + // 3->0 abcdef -> dbcdef + // 1->3 dbcdef -> dbcbef + // s->1 dbcbef -> dacbef + // + // 2->s s=c + // 4->2 dacbef -> daebef + // 5->4 daebef -> daebff + // s->5 daebff -> daebfc + + const int w = width; + const int h = height; + const int size = w * h; + + uint8_t *data_ptr = data.ptrw(); uint32_t pixel_size = get_format_pixel_size(format); - // Flip. + uint8_t single_pixel_buffer[16]; - if (p_direction == CLOCKWISE) { - for (int y = 0; y < height / 2; y++) { - for (int x = 0; x < width; x++) { - _get_pixelb(x, y, pixel_size, w, src); - _get_pixelb(x, height - y - 1, pixel_size, w, dst); +#define PREV_INDEX_IN_CYCLE(index) (p_direction == CLOCKWISE) ? ((h - 1 - (index % h)) * w + (index / h)) : ((index % h) * w + (w - 1 - (index / h))) - _put_pixelb(x, height - y - 1, pixel_size, w, src); - _put_pixelb(x, y, pixel_size, w, dst); + if (w == h) { // Square case, 4-length cycles only (plus irrelevant thus skipped 1-length cycle in the middle for odd-sized squares). + for (int y = 0; y < h / 2; y++) { + for (int x = 0; x < (w + 1) / 2; x++) { + int current = y * w + x; + memcpy(single_pixel_buffer, data_ptr + current * pixel_size, pixel_size); + for (int i = 0; i < 3; i++) { + int prev = PREV_INDEX_IN_CYCLE(current); + memcpy(data_ptr + current * pixel_size, data_ptr + prev * pixel_size, pixel_size); + current = prev; + } + memcpy(data_ptr + current * pixel_size, single_pixel_buffer, pixel_size); } } - } else { - for (int y = 0; y < height; y++) { - for (int x = 0; x < width / 2; x++) { - _get_pixelb(x, y, pixel_size, w, src); - _get_pixelb(width - x - 1, y, pixel_size, w, dst); + } else { // Rectangular case (w != h), kinda unpredictable cycles. + int permuted_pixels_count = 0; + + for (int i = 0; i < size; i++) { + int prev = PREV_INDEX_IN_CYCLE(i); + if (prev == i) { + // 1-length cycle, pixel remains at the same index. + permuted_pixels_count++; + continue; + } - _put_pixelb(width - x - 1, y, pixel_size, w, src); - _put_pixelb(x, y, pixel_size, w, dst); + // Check whether we already processed this cycle. + // We iterate over it and if we'll find an index smaller than `i` then we already + // processed this cycle because we always start at the smallest index in the cycle. + // TODO: Improve this naive approach, can be done better. + while (prev > i) { + prev = PREV_INDEX_IN_CYCLE(prev); + } + if (prev < i) { + continue; } - } - } - // Transpose. + // Save the in-cycle pixel with the smallest index (`i`). + memcpy(single_pixel_buffer, data_ptr + i * pixel_size, pixel_size); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - if (x < y) { - _get_pixelb(x, y, pixel_size, w, src); - _get_pixelb(y, x, pixel_size, w, dst); + // Overwrite pixels one by one by the preceding pixel in the cycle. + int current = i; + prev = PREV_INDEX_IN_CYCLE(current); + while (prev != i) { + memcpy(data_ptr + current * pixel_size, data_ptr + prev * pixel_size, pixel_size); + permuted_pixels_count++; - _put_pixelb(y, x, pixel_size, w, src); - _put_pixelb(x, y, pixel_size, w, dst); + current = prev; + prev = PREV_INDEX_IN_CYCLE(current); + }; + + // Overwrite the remaining pixel in the cycle by the saved pixel with the smallest index. + memcpy(data_ptr + current * pixel_size, single_pixel_buffer, pixel_size); + permuted_pixels_count++; + + if (permuted_pixels_count == size) { + break; } } + + width = h; + height = w; } + +#undef PREV_INDEX_IN_CYCLE } - if (saved_width != saved_height) { - resize(saved_width, saved_height, INTERPOLATE_NEAREST); - } else if (used_mipmaps) { + if (used_mipmaps) { generate_mipmaps(); } } void Image::rotate_180() { ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats."); - ERR_FAIL_COND_MSG(width <= 1, "The Image width specified (" + itos(width) + " pixels) must be greater than 1 pixels."); - ERR_FAIL_COND_MSG(height <= 1, "The Image height specified (" + itos(height) + " pixels) must be greater than 1 pixels."); + ERR_FAIL_COND_MSG(width <= 0, "The Image width specified (" + itos(width) + " pixels) must be greater than 0 pixels."); + ERR_FAIL_COND_MSG(height <= 0, "The Image height specified (" + itos(height) + " pixels) must be greater than 0 pixels."); bool used_mipmaps = has_mipmaps(); if (used_mipmaps) { @@ -1420,19 +1497,21 @@ void Image::rotate_180() { } { - uint8_t *w = data.ptrw(); - uint8_t src[16]; - uint8_t dst[16]; + uint8_t *data_ptr = data.ptrw(); uint32_t pixel_size = get_format_pixel_size(format); - for (int y = 0; y < height / 2; y++) { - for (int x = 0; x < width; x++) { - _get_pixelb(x, y, pixel_size, w, src); - _get_pixelb(width - x - 1, height - y - 1, pixel_size, w, dst); + uint8_t single_pixel_buffer[16]; - _put_pixelb(width - x - 1, height - y - 1, pixel_size, w, src); - _put_pixelb(x, y, pixel_size, w, dst); - } + uint8_t *from_begin_ptr = data_ptr; + uint8_t *from_end_ptr = data_ptr + (width * height - 1) * pixel_size; + + while (from_begin_ptr < from_end_ptr) { + memcpy(single_pixel_buffer, from_begin_ptr, pixel_size); + memcpy(from_begin_ptr, from_end_ptr, pixel_size); + memcpy(from_end_ptr, single_pixel_buffer, pixel_size); + + from_begin_ptr += pixel_size; + from_end_ptr -= pixel_size; } } @@ -2531,19 +2610,23 @@ Error Image::decompress() { _image_decompress_etc1(this); } else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RA_AS_RG && _image_decompress_etc2) { _image_decompress_etc2(this); + } else if (format >= FORMAT_ASTC_4x4 && format <= FORMAT_ASTC_8x8_HDR && _image_decompress_astc) { + _image_decompress_astc(this); } else { return ERR_UNAVAILABLE; } return OK; } -Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality) { +Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality, ASTCFormat p_astc_format) { ERR_FAIL_INDEX_V_MSG(p_mode, COMPRESS_MAX, ERR_INVALID_PARAMETER, "Invalid compress mode."); ERR_FAIL_INDEX_V_MSG(p_source, COMPRESS_SOURCE_MAX, ERR_INVALID_PARAMETER, "Invalid compress source."); - return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality); + return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality, p_astc_format); } -Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality) { +Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality, ASTCFormat p_astc_format) { + ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA); + switch (p_mode) { case COMPRESS_S3TC: { ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE); @@ -2561,6 +2644,10 @@ Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE); _image_compress_bptc_func(this, p_lossy_quality, p_channels); } break; + case COMPRESS_ASTC: { + ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE); + _image_compress_astc_func(this, p_lossy_quality, p_astc_format); + } break; case COMPRESS_MAX: { ERR_FAIL_V(ERR_INVALID_PARAMETER); } break; @@ -2917,10 +3004,12 @@ void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = nu void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = nullptr; void (*Image::_image_compress_etc1_func)(Image *, float) = nullptr; void (*Image::_image_compress_etc2_func)(Image *, float, Image::UsedChannels) = nullptr; +void (*Image::_image_compress_astc_func)(Image *, float, Image::ASTCFormat) = nullptr; void (*Image::_image_decompress_bc)(Image *) = nullptr; void (*Image::_image_decompress_bptc)(Image *) = nullptr; void (*Image::_image_decompress_etc1)(Image *) = nullptr; void (*Image::_image_decompress_etc2)(Image *) = nullptr; +void (*Image::_image_decompress_astc)(Image *) = nullptr; Vector<uint8_t> (*Image::webp_lossy_packer)(const Ref<Image> &, float) = nullptr; Vector<uint8_t> (*Image::webp_lossless_packer)(const Ref<Image> &) = nullptr; @@ -3337,8 +3426,8 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible); ClassDB::bind_method(D_METHOD("detect_used_channels", "source"), &Image::detect_used_channels, DEFVAL(COMPRESS_SOURCE_GENERIC)); - ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(0.7)); - ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "lossy_quality"), &Image::compress_from_channels, DEFVAL(0.7)); + ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality", "astc_format"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(0.7), DEFVAL(ASTC_FORMAT_4x4)); + ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "lossy_quality", "astc_format"), &Image::compress_from_channels, DEFVAL(0.7), DEFVAL(ASTC_FORMAT_4x4)); ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress); ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed); @@ -3422,6 +3511,10 @@ void Image::_bind_methods() { BIND_ENUM_CONSTANT(FORMAT_ETC2_RGB8A1); BIND_ENUM_CONSTANT(FORMAT_ETC2_RA_AS_RG); BIND_ENUM_CONSTANT(FORMAT_DXT5_RA_AS_RG); + BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4); + BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4_HDR); + BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8); + BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8_HDR); BIND_ENUM_CONSTANT(FORMAT_MAX); BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST); @@ -3449,6 +3542,9 @@ void Image::_bind_methods() { BIND_ENUM_CONSTANT(COMPRESS_SOURCE_GENERIC); BIND_ENUM_CONSTANT(COMPRESS_SOURCE_SRGB); BIND_ENUM_CONSTANT(COMPRESS_SOURCE_NORMAL); + + BIND_ENUM_CONSTANT(ASTC_FORMAT_4x4); + BIND_ENUM_CONSTANT(ASTC_FORMAT_8x8); } void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)) { @@ -3748,6 +3844,19 @@ void Image::convert_ra_rgba8_to_rg() { } } +void Image::convert_rgba8_to_bgra8() { + ERR_FAIL_COND(format != FORMAT_RGBA8); + ERR_FAIL_COND(!data.size()); + + int s = data.size(); + uint8_t *w = data.ptrw(); + for (int i = 0; i < s; i += 4) { + uint8_t r = w[i]; + w[i] = w[i + 2]; // Swap R to B + w[i + 2] = r; // Swap B to R + } +} + Error Image::_load_from_buffer(const Vector<uint8_t> &p_array, ImageMemLoadFunc p_loader) { int buffer_size = p_array.size(); diff --git a/core/io/image.h b/core/io/image.h index 62df81e7c8..8bcee4404b 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -109,6 +109,10 @@ public: FORMAT_ETC2_RGB8A1, FORMAT_ETC2_RA_AS_RG, //used to make basis universal happy FORMAT_DXT5_RA_AS_RG, //used to make basis universal happy + FORMAT_ASTC_4x4, + FORMAT_ASTC_4x4_HDR, + FORMAT_ASTC_8x8, + FORMAT_ASTC_8x8_HDR, FORMAT_MAX }; @@ -134,6 +138,11 @@ public: }; //some functions provided by something else + enum ASTCFormat { + ASTC_FORMAT_4x4, + ASTC_FORMAT_8x8, + }; + static ImageMemLoadFunc _png_mem_loader_func; static ImageMemLoadFunc _jpg_mem_loader_func; static ImageMemLoadFunc _webp_mem_loader_func; @@ -144,11 +153,13 @@ public: static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, UsedChannels p_channels); static void (*_image_compress_etc1_func)(Image *, float); static void (*_image_compress_etc2_func)(Image *, float, UsedChannels p_channels); + static void (*_image_compress_astc_func)(Image *, float, ASTCFormat p_format); static void (*_image_decompress_bc)(Image *); static void (*_image_decompress_bptc)(Image *); static void (*_image_decompress_etc1)(Image *); static void (*_image_decompress_etc2)(Image *); + static void (*_image_decompress_astc)(Image *); static Vector<uint8_t> (*webp_lossy_packer)(const Ref<Image> &p_image, float p_quality); static Vector<uint8_t> (*webp_lossless_packer)(const Ref<Image> &p_image); @@ -347,6 +358,7 @@ public: COMPRESS_ETC, COMPRESS_ETC2, COMPRESS_BPTC, + COMPRESS_ASTC, COMPRESS_MAX, }; enum CompressSource { @@ -356,8 +368,8 @@ public: COMPRESS_SOURCE_MAX, }; - Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7); - Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality = 0.7); + Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); + Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality = 0.7, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); Error decompress(); bool is_compressed() const; @@ -391,6 +403,7 @@ public: void convert_rg_to_ra_rgba8(); void convert_ra_rgba8_to_rg(); + void convert_rgba8_to_bgra8(); Image(const uint8_t *p_mem_png_jpg, int p_len = -1); Image(const char **p_xpm); @@ -428,5 +441,6 @@ VARIANT_ENUM_CAST(Image::CompressSource) VARIANT_ENUM_CAST(Image::UsedChannels) VARIANT_ENUM_CAST(Image::AlphaMode) VARIANT_ENUM_CAST(Image::RoughnessChannel) +VARIANT_ENUM_CAST(Image::ASTCFormat) #endif // IMAGE_H diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h index 07045e62a6..4a5f244911 100644 --- a/core/io/packet_peer.h +++ b/core/io/packet_peer.h @@ -86,10 +86,10 @@ protected: public: virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; ///< buffer is GONE after next get_packet - GDVIRTUAL2R(Error, _get_packet, GDNativeConstPtr<const uint8_t *>, GDNativePtr<int>); + GDVIRTUAL2R(Error, _get_packet, GDExtensionConstPtr<const uint8_t *>, GDExtensionPtr<int>); virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override; - GDVIRTUAL2R(Error, _put_packet, GDNativeConstPtr<const uint8_t>, int); + GDVIRTUAL2R(Error, _put_packet, GDExtensionConstPtr<const uint8_t>, int); EXBIND0RC(int, get_available_packet_count); EXBIND0RC(int, get_max_packet_size); diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index aa1b323db2..0556f45b0c 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -107,6 +107,8 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String & } Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encrypt) { + ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use."); + Ref<FileAccess> f = FileAccess::open(p_src, FileAccess::READ); if (f.is_null()) { return ERR_FILE_CANT_OPEN; @@ -118,7 +120,7 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encr pf.ofs = ofs; pf.size = f->get_length(); - Vector<uint8_t> data = FileAccess::get_file_as_array(p_src); + Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_src); { unsigned char hash[16]; CryptoCore::md5(data.ptr(), data.size(), hash); diff --git a/core/io/resource.cpp b/core/io/resource.cpp index ab30fb1ca3..be75ad7e25 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -436,7 +436,7 @@ void Resource::_bind_methods() { ADD_GROUP("Resource", "resource_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resource_local_to_scene"), "set_local_to_scene", "is_local_to_scene"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_path", "get_path"); - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "resource_name"), "set_name", "get_name"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_name"), "set_name", "get_name"); MethodInfo get_rid_bind("_get_rid"); get_rid_bind.return_val.type = Variant::RID; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 6219ea70e4..20445a8b03 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -923,6 +923,35 @@ void ResourceLoader::clear_translation_remaps() { } } +void ResourceLoader::clear_thread_load_tasks() { + thread_load_mutex->lock(); + + for (KeyValue<String, ResourceLoader::ThreadLoadTask> &E : thread_load_tasks) { + switch (E.value.status) { + case ResourceLoader::ThreadLoadStatus::THREAD_LOAD_LOADED: { + E.value.resource = Ref<Resource>(); + } break; + + case ResourceLoader::ThreadLoadStatus::THREAD_LOAD_IN_PROGRESS: { + if (E.value.thread != nullptr) { + E.value.thread->wait_to_finish(); + memdelete(E.value.thread); + E.value.thread = nullptr; + } + E.value.resource = Ref<Resource>(); + } break; + + case ResourceLoader::ThreadLoadStatus::THREAD_LOAD_FAILED: + default: { + // do nothing + } + } + } + thread_load_tasks.clear(); + + thread_load_mutex->unlock(); +} + void ResourceLoader::load_path_remaps() { if (!ProjectSettings::get_singleton()->has_setting("path_remap/remapped_paths")) { return; diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 243670b2d0..af10098bd8 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -219,6 +219,8 @@ public: static void load_translation_remaps(); static void clear_translation_remaps(); + static void clear_thread_load_tasks(); + static void set_load_callback(ResourceLoadedCallback p_callback); static ResourceLoaderImport import; diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h index 108a8ce9d9..95cc655b45 100644 --- a/core/io/stream_peer.h +++ b/core/io/stream_peer.h @@ -105,16 +105,16 @@ protected: public: virtual Error put_data(const uint8_t *p_data, int p_bytes) override; - GDVIRTUAL3R(Error, _put_data, GDNativeConstPtr<const uint8_t>, int, GDNativePtr<int>); + GDVIRTUAL3R(Error, _put_data, GDExtensionConstPtr<const uint8_t>, int, GDExtensionPtr<int>); virtual Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) override; - GDVIRTUAL3R(Error, _put_partial_data, GDNativeConstPtr<const uint8_t>, int, GDNativePtr<int>); + GDVIRTUAL3R(Error, _put_partial_data, GDExtensionConstPtr<const uint8_t>, int, GDExtensionPtr<int>); virtual Error get_data(uint8_t *p_buffer, int p_bytes) override; - GDVIRTUAL3R(Error, _get_data, GDNativePtr<uint8_t>, int, GDNativePtr<int>); + GDVIRTUAL3R(Error, _get_data, GDExtensionPtr<uint8_t>, int, GDExtensionPtr<int>); virtual Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) override; - GDVIRTUAL3R(Error, _get_partial_data, GDNativePtr<uint8_t>, int, GDNativePtr<int>); + GDVIRTUAL3R(Error, _get_partial_data, GDExtensionPtr<uint8_t>, int, GDExtensionPtr<int>); EXBIND0RC(int, get_available_bytes); }; diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index abae48fdd8..16b7f3a1f6 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -41,11 +41,11 @@ static inline bool _is_white_space(char c) { } //! sets the state that text was found. Returns true if set should be set -bool XMLParser::_set_text(char *start, char *end) { +bool XMLParser::_set_text(const char *start, const char *end) { // check if text is more than 2 characters, and if not, check if there is // only white space, so that this text won't be reported if (end - start < 3) { - char *p = start; + const char *p = start; for (; p != end; ++p) { if (!_is_white_space(*p)) { break; @@ -92,7 +92,7 @@ void XMLParser::_parse_closing_xml_element() { void XMLParser::_ignore_definition() { node_type = NODE_UNKNOWN; - char *F = P; + const char *F = P; // move until end marked with '>' reached while (*P && *P != '>') { next_char(); @@ -123,8 +123,8 @@ bool XMLParser::_parse_cdata() { return true; } - char *cDataBegin = P; - char *cDataEnd = nullptr; + const char *cDataBegin = P; + const char *cDataEnd = nullptr; // find end of CDATA while (*P && !cDataEnd) { @@ -152,9 +152,9 @@ void XMLParser::_parse_comment() { node_type = NODE_COMMENT; P += 1; - char *pEndOfInput = data + length; - char *pCommentBegin; - char *pCommentEnd; + const char *pEndOfInput = data + length; + const char *pCommentBegin; + const char *pCommentEnd; if (P + 1 < pEndOfInput && P[0] == '-' && P[1] == '-') { // Comment, use '-->' as end. @@ -293,7 +293,7 @@ void XMLParser::_parse_opening_xml_element() { } void XMLParser::_parse_current_node() { - char *start = P; + const char *start = P; node_offset = P - data; // more forward until '<' found @@ -458,15 +458,36 @@ bool XMLParser::is_empty() const { Error XMLParser::open_buffer(const Vector<uint8_t> &p_buffer) { ERR_FAIL_COND_V(p_buffer.size() == 0, ERR_INVALID_DATA); - if (data) { - memdelete_arr(data); + if (data_copy) { + memdelete_arr(data_copy); + data_copy = nullptr; } length = p_buffer.size(); - data = memnew_arr(char, length + 1); - memcpy(data, p_buffer.ptr(), length); - data[length] = 0; + data_copy = memnew_arr(char, length + 1); + memcpy(data_copy, p_buffer.ptr(), length); + data_copy[length] = 0; + data = data_copy; + P = data; + current_line = 0; + + return OK; +} + +Error XMLParser::_open_buffer(const uint8_t *p_buffer, size_t p_size) { + ERR_FAIL_COND_V(p_size == 0, ERR_INVALID_DATA); + ERR_FAIL_COND_V(!p_buffer, ERR_INVALID_DATA); + + if (data_copy) { + memdelete_arr(data_copy); + data_copy = nullptr; + } + + length = p_size; + data = (const char *)p_buffer; P = data; + current_line = 0; + return OK; } @@ -479,13 +500,15 @@ Error XMLParser::open(const String &p_path) { length = file->get_length(); ERR_FAIL_COND_V(length < 1, ERR_FILE_CORRUPT); - if (data) { - memdelete_arr(data); + if (data_copy) { + memdelete_arr(data_copy); + data_copy = nullptr; } - data = memnew_arr(char, length + 1); - file->get_buffer((uint8_t *)data, length); - data[length] = 0; + data_copy = memnew_arr(char, length + 1); + file->get_buffer((uint8_t *)data_copy, length); + data_copy[length] = 0; + data = data_copy; P = data; current_line = 0; @@ -512,8 +535,9 @@ void XMLParser::skip_section() { } void XMLParser::close() { - if (data) { + if (data_copy) { memdelete_arr(data); + data_copy = nullptr; } data = nullptr; length = 0; @@ -528,7 +552,8 @@ int XMLParser::get_current_line() const { } XMLParser::~XMLParser() { - if (data) { - memdelete_arr(data); + if (data_copy) { + memdelete_arr(data_copy); + data_copy = nullptr; } } diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h index aea252ddc7..be44f771dc 100644 --- a/core/io/xml_parser.h +++ b/core/io/xml_parser.h @@ -65,8 +65,9 @@ public: }; private: - char *data = nullptr; - char *P = nullptr; + char *data_copy = nullptr; + const char *data = nullptr; + const char *P = nullptr; uint64_t length = 0; uint64_t current_line = 0; String node_name; @@ -81,7 +82,7 @@ private: Vector<Attribute> attributes; - bool _set_text(char *start, char *end); + bool _set_text(const char *start, const char *end); void _parse_closing_xml_element(); void _ignore_definition(); bool _parse_cdata(); @@ -118,6 +119,7 @@ public: Error open(const String &p_path); Error open_buffer(const Vector<uint8_t> &p_buffer); + Error _open_buffer(const uint8_t *p_buffer, size_t p_size); void close(); diff --git a/core/math/a_star_grid_2d.cpp b/core/math/a_star_grid_2d.cpp index c30acf32bb..cdcd0ed747 100644 --- a/core/math/a_star_grid_2d.cpp +++ b/core/math/a_star_grid_2d.cpp @@ -134,13 +134,22 @@ AStarGrid2D::DiagonalMode AStarGrid2D::get_diagonal_mode() const { return diagonal_mode; } -void AStarGrid2D::set_default_heuristic(Heuristic p_heuristic) { +void AStarGrid2D::set_default_compute_heuristic(Heuristic p_heuristic) { ERR_FAIL_INDEX((int)p_heuristic, (int)HEURISTIC_MAX); - default_heuristic = p_heuristic; + default_compute_heuristic = p_heuristic; } -AStarGrid2D::Heuristic AStarGrid2D::get_default_heuristic() const { - return default_heuristic; +AStarGrid2D::Heuristic AStarGrid2D::get_default_compute_heuristic() const { + return default_compute_heuristic; +} + +void AStarGrid2D::set_default_estimate_heuristic(Heuristic p_heuristic) { + ERR_FAIL_INDEX((int)p_heuristic, (int)HEURISTIC_MAX); + default_estimate_heuristic = p_heuristic; +} + +AStarGrid2D::Heuristic AStarGrid2D::get_default_estimate_heuristic() const { + return default_estimate_heuristic; } void AStarGrid2D::set_point_solid(const Vector2i &p_id, bool p_solid) { @@ -155,6 +164,19 @@ bool AStarGrid2D::is_point_solid(const Vector2i &p_id) const { return points[p_id.y][p_id.x].solid; } +void AStarGrid2D::set_point_weight_scale(const Vector2i &p_id, real_t p_weight_scale) { + ERR_FAIL_COND_MSG(dirty, "Grid is not initialized. Call the update method."); + ERR_FAIL_COND_MSG(!is_in_boundsv(p_id), vformat("Can't set point's weight scale. Point out of bounds (%s/%s, %s/%s).", p_id.x, size.width, p_id.y, size.height)); + ERR_FAIL_COND_MSG(p_weight_scale < 0.0, vformat("Can't set point's weight scale less than 0.0: %f.", p_weight_scale)); + points[p_id.y][p_id.x].weight_scale = p_weight_scale; +} + +real_t AStarGrid2D::get_point_weight_scale(const Vector2i &p_id) const { + ERR_FAIL_COND_V_MSG(dirty, 0, "Grid is not initialized. Call the update method."); + ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_id), 0, vformat("Can't get point's weight scale. Point out of bounds (%s/%s, %s/%s).", p_id.x, size.width, p_id.y, size.height)); + return points[p_id.y][p_id.x].weight_scale; +} + AStarGrid2D::Point *AStarGrid2D::_jump(Point *p_from, Point *p_to) { if (!p_to || p_to->solid) { return nullptr; @@ -388,7 +410,10 @@ bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point) { _get_nbors(p, nbors); for (List<Point *>::Element *E = nbors.front(); E; E = E->next()) { Point *e = E->get(); // The neighbour point. + real_t weight_scale = 1.0; + if (jumping_enabled) { + // TODO: Make it works with weight_scale. e = _jump(p, e); if (!e || e->closed_pass == pass) { continue; @@ -397,9 +422,10 @@ bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point) { if (e->solid || e->closed_pass == pass) { continue; } + weight_scale = e->weight_scale; } - real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id); + real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id) * weight_scale; bool new_point = false; if (e->open_pass != pass) { // The point wasn't inside the open list. @@ -430,7 +456,7 @@ real_t AStarGrid2D::_estimate_cost(const Vector2i &p_from_id, const Vector2i &p_ if (GDVIRTUAL_CALL(_estimate_cost, p_from_id, p_to_id, scost)) { return scost; } - return heuristics[default_heuristic](p_from_id, p_to_id); + return heuristics[default_estimate_heuristic](p_from_id, p_to_id); } real_t AStarGrid2D::_compute_cost(const Vector2i &p_from_id, const Vector2i &p_to_id) { @@ -438,7 +464,7 @@ real_t AStarGrid2D::_compute_cost(const Vector2i &p_from_id, const Vector2i &p_t if (GDVIRTUAL_CALL(_compute_cost, p_from_id, p_to_id, scost)) { return scost; } - return heuristics[default_heuristic](p_from_id, p_to_id); + return heuristics[default_compute_heuristic](p_from_id, p_to_id); } void AStarGrid2D::clear() { @@ -446,6 +472,12 @@ void AStarGrid2D::clear() { size = Vector2i(); } +Vector2 AStarGrid2D::get_point_position(const Vector2i &p_id) const { + ERR_FAIL_COND_V_MSG(dirty, Vector2(), "Grid is not initialized. Call the update method."); + ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_id), Vector2(), vformat("Can't get point's position. Point out of bounds (%s/%s, %s/%s).", p_id.x, size.width, p_id.y, size.height)); + return points[p_id.y][p_id.x].pos; +} + Vector<Vector2> AStarGrid2D::get_point_path(const Vector2i &p_from_id, const Vector2i &p_to_id) { ERR_FAIL_COND_V_MSG(dirty, Vector<Vector2>(), "Grid is not initialized. Call the update method."); ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_from_id), Vector<Vector2>(), vformat("Can't get id path. Point out of bounds (%s/%s, %s/%s)", p_from_id.x, size.width, p_from_id.y, size.height)); @@ -555,12 +587,17 @@ void AStarGrid2D::_bind_methods() { ClassDB::bind_method(D_METHOD("is_jumping_enabled"), &AStarGrid2D::is_jumping_enabled); ClassDB::bind_method(D_METHOD("set_diagonal_mode", "mode"), &AStarGrid2D::set_diagonal_mode); ClassDB::bind_method(D_METHOD("get_diagonal_mode"), &AStarGrid2D::get_diagonal_mode); - ClassDB::bind_method(D_METHOD("set_default_heuristic", "heuristic"), &AStarGrid2D::set_default_heuristic); - ClassDB::bind_method(D_METHOD("get_default_heuristic"), &AStarGrid2D::get_default_heuristic); + ClassDB::bind_method(D_METHOD("set_default_compute_heuristic", "heuristic"), &AStarGrid2D::set_default_compute_heuristic); + ClassDB::bind_method(D_METHOD("get_default_compute_heuristic"), &AStarGrid2D::get_default_compute_heuristic); + ClassDB::bind_method(D_METHOD("set_default_estimate_heuristic", "heuristic"), &AStarGrid2D::set_default_estimate_heuristic); + ClassDB::bind_method(D_METHOD("get_default_estimate_heuristic"), &AStarGrid2D::get_default_estimate_heuristic); ClassDB::bind_method(D_METHOD("set_point_solid", "id", "solid"), &AStarGrid2D::set_point_solid, DEFVAL(true)); ClassDB::bind_method(D_METHOD("is_point_solid", "id"), &AStarGrid2D::is_point_solid); + ClassDB::bind_method(D_METHOD("set_point_weight_scale", "id", "weight_scale"), &AStarGrid2D::set_point_weight_scale); + ClassDB::bind_method(D_METHOD("get_point_weight_scale", "id"), &AStarGrid2D::get_point_weight_scale); ClassDB::bind_method(D_METHOD("clear"), &AStarGrid2D::clear); + ClassDB::bind_method(D_METHOD("get_point_position", "id"), &AStarGrid2D::get_point_position); ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStarGrid2D::get_point_path); ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id"), &AStarGrid2D::get_id_path); @@ -572,8 +609,9 @@ void AStarGrid2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "cell_size"), "set_cell_size", "get_cell_size"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "jumping_enabled"), "set_jumping_enabled", "is_jumping_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "default_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev,Max"), "set_default_heuristic", "get_default_heuristic"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "diagonal_mode", PROPERTY_HINT_ENUM, "Never,Always,At Least One Walkable,Only If No Obstacles,Max"), "set_diagonal_mode", "get_diagonal_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "default_compute_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev"), "set_default_compute_heuristic", "get_default_compute_heuristic"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "default_estimate_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev"), "set_default_estimate_heuristic", "get_default_estimate_heuristic"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "diagonal_mode", PROPERTY_HINT_ENUM, "Never,Always,At Least One Walkable,Only If No Obstacles"), "set_diagonal_mode", "get_diagonal_mode"); BIND_ENUM_CONSTANT(HEURISTIC_EUCLIDEAN); BIND_ENUM_CONSTANT(HEURISTIC_MANHATTAN); diff --git a/core/math/a_star_grid_2d.h b/core/math/a_star_grid_2d.h index 1002f18738..ca36013b61 100644 --- a/core/math/a_star_grid_2d.h +++ b/core/math/a_star_grid_2d.h @@ -65,13 +65,15 @@ private: bool jumping_enabled = false; DiagonalMode diagonal_mode = DIAGONAL_MODE_ALWAYS; - Heuristic default_heuristic = HEURISTIC_EUCLIDEAN; + Heuristic default_compute_heuristic = HEURISTIC_EUCLIDEAN; + Heuristic default_estimate_heuristic = HEURISTIC_EUCLIDEAN; struct Point { Vector2i id; bool solid = false; Vector2 pos; + real_t weight_scale = 1.0; // Used for pathfinding. Point *prev_point = nullptr; @@ -160,14 +162,21 @@ public: void set_diagonal_mode(DiagonalMode p_diagonal_mode); DiagonalMode get_diagonal_mode() const; - void set_default_heuristic(Heuristic p_heuristic); - Heuristic get_default_heuristic() const; + void set_default_compute_heuristic(Heuristic p_heuristic); + Heuristic get_default_compute_heuristic() const; + + void set_default_estimate_heuristic(Heuristic p_heuristic); + Heuristic get_default_estimate_heuristic() const; void set_point_solid(const Vector2i &p_id, bool p_solid = true); bool is_point_solid(const Vector2i &p_id) const; + void set_point_weight_scale(const Vector2i &p_id, real_t p_weight_scale); + real_t get_point_weight_scale(const Vector2i &p_id) const; + void clear(); + Vector2 get_point_position(const Vector2i &p_id) const; Vector<Vector2> get_point_path(const Vector2i &p_from, const Vector2i &p_to); TypedArray<Vector2i> get_id_path(const Vector2i &p_from, const Vector2i &p_to); }; diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 41ec6d8ce3..d7bb025b69 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -487,7 +487,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { euler.z = 0.0f; } return euler; - } break; + } case EulerOrder::XZY: { // Euler angles in XZY convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix @@ -516,7 +516,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { euler.z = -Math_PI / 2.0f; } return euler; - } break; + } case EulerOrder::YXZ: { // Euler angles in YXZ convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix @@ -554,7 +554,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { } return euler; - } break; + } case EulerOrder::YZX: { // Euler angles in YZX convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix @@ -639,7 +639,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { euler.z = -Math::atan2(rows[0][1], rows[1][1]); } return euler; - } break; + } default: { ERR_FAIL_V_MSG(Vector3(), "Invalid parameter for get_euler(order)"); } diff --git a/core/math/color.h b/core/math/color.h index a23a4953ce..5630539aa7 100644 --- a/core/math/color.h +++ b/core/math/color.h @@ -105,12 +105,10 @@ struct _NO_DISCARD_ Color { _FORCE_INLINE_ Color lerp(const Color &p_to, float p_weight) const { Color res = *this; - - res.r += (p_weight * (p_to.r - r)); - res.g += (p_weight * (p_to.g - g)); - res.b += (p_weight * (p_to.b - b)); - res.a += (p_weight * (p_to.a - a)); - + res.r = Math::lerp(res.r, p_to.r, p_weight); + res.g = Math::lerp(res.g, p_to.g, p_weight); + res.b = Math::lerp(res.b, p_to.b, p_weight); + res.a = Math::lerp(res.a, p_to.a, p_weight); return res; } diff --git a/core/math/convex_hull.cpp b/core/math/convex_hull.cpp index 561970d2ee..51d88d8ea0 100644 --- a/core/math/convex_hull.cpp +++ b/core/math/convex_hull.cpp @@ -2274,8 +2274,7 @@ Error ConvexHullComputer::convex_hull(const Vector<Vector3> &p_points, Geometry3 // Copy the edges over. There's two "half-edges" for every edge, so we pick only one of them. r_mesh.edges.resize(ch.edges.size() / 2); - OAHashMap<uint64_t, int32_t> edge_map; - edge_map.reserve(ch.edges.size() * 4); // The higher the capacity, the faster the insert + OAHashMap<uint64_t, int32_t> edge_map(ch.edges.size() * 4); // The higher the capacity, the faster the insert uint32_t edges_copied = 0; for (uint32_t i = 0; i < ch.edges.size(); i++) { diff --git a/core/math/expression.cpp b/core/math/expression.cpp index dcec3929fe..26b809e7f2 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -1420,7 +1420,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: Callable::CallError ce; Variant::call_utility_function(bifunc->func, &r_ret, (const Variant **)argp.ptr(), argp.size(), ce); if (ce.error != Callable::CallError::CALL_OK) { - r_error_str = "Builtin Call Failed. " + Variant::get_call_error_text(bifunc->func, (const Variant **)argp.ptr(), argp.size(), ce); + r_error_str = "Builtin call failed: " + Variant::get_call_error_text(bifunc->func, (const Variant **)argp.ptr(), argp.size(), ce); return true; } diff --git a/core/math/math_defs.h b/core/math/math_defs.h index 759667e2d5..1058a47c1a 100644 --- a/core/math/math_defs.h +++ b/core/math/math_defs.h @@ -86,6 +86,7 @@ enum InlineAlignment { // Image alignment points. INLINE_ALIGNMENT_TOP_TO = 0b0000, INLINE_ALIGNMENT_CENTER_TO = 0b0001, + INLINE_ALIGNMENT_BASELINE_TO = 0b0011, INLINE_ALIGNMENT_BOTTOM_TO = 0b0010, INLINE_ALIGNMENT_IMAGE_MASK = 0b0011, diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 0af529ad98..a998dece2a 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -364,6 +364,26 @@ public: return p_start * omt3 + p_control_1 * omt2 * p_t * 3.0f + p_control_2 * omt * t2 * 3.0f + p_end * t3; } + static _ALWAYS_INLINE_ double bezier_derivative(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) { + /* Formula from Wikipedia article on Bezier curves. */ + double omt = (1.0 - p_t); + double omt2 = omt * omt; + double t2 = p_t * p_t; + + double d = (p_control_1 - p_start) * 3.0 * omt2 + (p_control_2 - p_control_1) * 6.0 * omt * p_t + (p_end - p_control_2) * 3.0 * t2; + return d; + } + + static _ALWAYS_INLINE_ float bezier_derivative(float p_start, float p_control_1, float p_control_2, float p_end, float p_t) { + /* Formula from Wikipedia article on Bezier curves. */ + float omt = (1.0f - p_t); + float omt2 = omt * omt; + float t2 = p_t * p_t; + + float d = (p_control_1 - p_start) * 3.0f * omt2 + (p_control_2 - p_control_1) * 6.0f * omt * p_t + (p_end - p_control_2) * 3.0f * t2; + return d; + } + static _ALWAYS_INLINE_ double lerp_angle(double p_from, double p_to, double p_weight) { double difference = fmod(p_to - p_from, Math_TAU); double distance = fmod(2.0 * difference, Math_TAU) - difference; @@ -433,7 +453,10 @@ public: } static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) { double range = max - min; - double result = is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range)); + if (is_zero_approx(range)) { + return min; + } + double result = value - (range * Math::floor((value - min) / range)); if (is_equal_approx(result, max)) { return min; } @@ -441,7 +464,10 @@ public: } static _ALWAYS_INLINE_ float wrapf(float value, float min, float max) { float range = max - min; - float result = is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range)); + if (is_zero_approx(range)) { + return min; + } + float result = value - (range * Math::floor((value - min) / range)); if (is_equal_approx(result, max)) { return min; } diff --git a/core/math/projection.cpp b/core/math/projection.cpp index 70cc9b5f7c..c135e1946a 100644 --- a/core/math/projection.cpp +++ b/core/math/projection.cpp @@ -134,7 +134,7 @@ Projection Projection::create_for_hmd(int p_eye, real_t p_aspect, real_t p_intra Projection Projection::create_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) { Projection proj; - proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_zfar, p_zfar); + proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_znear, p_zfar); return proj; } @@ -181,7 +181,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); return new_plane; - } break; + } case PLANE_FAR: { Plane new_plane = Plane(matrix[3] - matrix[2], matrix[7] - matrix[6], @@ -191,7 +191,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); return new_plane; - } break; + } case PLANE_LEFT: { Plane new_plane = Plane(matrix[3] + matrix[0], matrix[7] + matrix[4], @@ -201,7 +201,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); return new_plane; - } break; + } case PLANE_TOP: { Plane new_plane = Plane(matrix[3] - matrix[1], matrix[7] - matrix[5], @@ -211,7 +211,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); return new_plane; - } break; + } case PLANE_RIGHT: { Plane new_plane = Plane(matrix[3] - matrix[0], matrix[7] - matrix[4], @@ -221,7 +221,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); return new_plane; - } break; + } case PLANE_BOTTOM: { Plane new_plane = Plane(matrix[3] + matrix[1], matrix[7] + matrix[5], @@ -231,7 +231,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); return new_plane; - } break; + } } return Plane(); diff --git a/core/math/vector2.h b/core/math/vector2.h index 5775d8e735..835c3d1ba6 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -112,6 +112,7 @@ struct _NO_DISCARD_ Vector2 { _FORCE_INLINE_ Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight) const; _FORCE_INLINE_ Vector2 cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const; _FORCE_INLINE_ Vector2 bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const; + _FORCE_INLINE_ Vector2 bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const; Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const; @@ -242,10 +243,8 @@ _FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const { Vector2 Vector2::lerp(const Vector2 &p_to, const real_t p_weight) const { Vector2 res = *this; - - res.x += (p_weight * (p_to.x - x)); - res.y += (p_weight * (p_to.y - y)); - + res.x = Math::lerp(res.x, p_to.x, p_weight); + res.y = Math::lerp(res.y, p_to.y, p_weight); return res; } @@ -278,15 +277,16 @@ Vector2 Vector2::cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_ Vector2 Vector2::bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const { Vector2 res = *this; + res.x = Math::bezier_interpolate(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_interpolate(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + return res; +} - /* Formula from Wikipedia article on Bezier curves. */ - real_t omt = (1.0 - p_t); - real_t omt2 = omt * omt; - real_t omt3 = omt2 * omt; - real_t t2 = p_t * p_t; - real_t t3 = t2 * p_t; - - return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3; +Vector2 Vector2::bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const { + Vector2 res = *this; + res.x = Math::bezier_derivative(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_derivative(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + return res; } Vector2 Vector2::direction_to(const Vector2 &p_to) const { diff --git a/core/math/vector2i.cpp b/core/math/vector2i.cpp index dfed42e4d6..ff8693ee5b 100644 --- a/core/math/vector2i.cpp +++ b/core/math/vector2i.cpp @@ -39,6 +39,12 @@ Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const { CLAMP(y, p_min.y, p_max.y)); } +Vector2i Vector2i::snapped(const Vector2i &p_step) const { + return Vector2i( + Math::snapped(x, p_step.x), + Math::snapped(y, p_step.y)); +} + int64_t Vector2i::length_squared() const { return x * (int64_t)x + y * (int64_t)y; } diff --git a/core/math/vector2i.h b/core/math/vector2i.h index e131bdea94..927be11030 100644 --- a/core/math/vector2i.h +++ b/core/math/vector2i.h @@ -119,6 +119,7 @@ struct _NO_DISCARD_ Vector2i { Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); } Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); } Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const; + Vector2i snapped(const Vector2i &p_step) const; operator String() const; operator Vector2() const; diff --git a/core/math/vector3.h b/core/math/vector3.h index 19771eb312..dc74096690 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -100,6 +100,7 @@ struct _NO_DISCARD_ Vector3 { _FORCE_INLINE_ Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const; _FORCE_INLINE_ Vector3 cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const; _FORCE_INLINE_ Vector3 bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const; + _FORCE_INLINE_ Vector3 bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const; Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const; @@ -208,10 +209,11 @@ Vector3 Vector3::round() const { } Vector3 Vector3::lerp(const Vector3 &p_to, const real_t p_weight) const { - return Vector3( - x + (p_weight * (p_to.x - x)), - y + (p_weight * (p_to.y - y)), - z + (p_weight * (p_to.z - z))); + Vector3 res = *this; + res.x = Math::lerp(res.x, p_to.x, p_weight); + res.y = Math::lerp(res.y, p_to.y, p_weight); + res.z = Math::lerp(res.z, p_to.z, p_weight); + return res; } Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const { @@ -254,15 +256,18 @@ Vector3 Vector3::cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_ Vector3 Vector3::bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const { Vector3 res = *this; + res.x = Math::bezier_interpolate(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_interpolate(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + res.z = Math::bezier_interpolate(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t); + return res; +} - /* Formula from Wikipedia article on Bezier curves. */ - real_t omt = (1.0 - p_t); - real_t omt2 = omt * omt; - real_t omt3 = omt2 * omt; - real_t t2 = p_t * p_t; - real_t t3 = t2 * p_t; - - return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3; +Vector3 Vector3::bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const { + Vector3 res = *this; + res.x = Math::bezier_derivative(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_derivative(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + res.z = Math::bezier_derivative(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t); + return res; } real_t Vector3::distance_to(const Vector3 &p_to) const { diff --git a/core/math/vector3i.cpp b/core/math/vector3i.cpp index b248f35035..901f2b5a64 100644 --- a/core/math/vector3i.cpp +++ b/core/math/vector3i.cpp @@ -48,6 +48,13 @@ Vector3i Vector3i::clamp(const Vector3i &p_min, const Vector3i &p_max) const { CLAMP(z, p_min.z, p_max.z)); } +Vector3i Vector3i::snapped(const Vector3i &p_step) const { + return Vector3i( + Math::snapped(x, p_step.x), + Math::snapped(y, p_step.y), + Math::snapped(z, p_step.z)); +} + Vector3i::operator String() const { return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")"; } diff --git a/core/math/vector3i.h b/core/math/vector3i.h index 710fd96376..36bac3d8ae 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -77,6 +77,7 @@ struct _NO_DISCARD_ Vector3i { _FORCE_INLINE_ Vector3i abs() const; _FORCE_INLINE_ Vector3i sign() const; Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const; + Vector3i snapped(const Vector3i &p_step) const; /* Operators */ diff --git a/core/math/vector4.cpp b/core/math/vector4.cpp index 3b189f7ed4..5ddf2bb6f6 100644 --- a/core/math/vector4.cpp +++ b/core/math/vector4.cpp @@ -130,11 +130,12 @@ Vector4 Vector4::round() const { } Vector4 Vector4::lerp(const Vector4 &p_to, const real_t p_weight) const { - return Vector4( - x + (p_weight * (p_to.x - x)), - y + (p_weight * (p_to.y - y)), - z + (p_weight * (p_to.z - z)), - w + (p_weight * (p_to.w - w))); + Vector4 res = *this; + res.x = Math::lerp(res.x, p_to.x, p_weight); + res.y = Math::lerp(res.y, p_to.y, p_weight); + res.z = Math::lerp(res.z, p_to.z, p_weight); + res.w = Math::lerp(res.w, p_to.w, p_weight); + return res; } Vector4 Vector4::cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const { diff --git a/core/math/vector4i.cpp b/core/math/vector4i.cpp index 77f6fbd5b7..e906ab45ad 100644 --- a/core/math/vector4i.cpp +++ b/core/math/vector4i.cpp @@ -65,6 +65,14 @@ Vector4i Vector4i::clamp(const Vector4i &p_min, const Vector4i &p_max) const { CLAMP(w, p_min.w, p_max.w)); } +Vector4i Vector4i::snapped(const Vector4i &p_step) const { + return Vector4i( + Math::snapped(x, p_step.x), + Math::snapped(y, p_step.y), + Math::snapped(z, p_step.z), + Math::snapped(w, p_step.w)); +} + Vector4i::operator String() const { return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")"; } diff --git a/core/math/vector4i.h b/core/math/vector4i.h index a32414bb18..cb5a48daf9 100644 --- a/core/math/vector4i.h +++ b/core/math/vector4i.h @@ -79,6 +79,7 @@ struct _NO_DISCARD_ Vector4i { _FORCE_INLINE_ Vector4i abs() const; _FORCE_INLINE_ Vector4i sign() const; Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const; + Vector4i snapped(const Vector4i &p_step) const; /* Operators */ diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index ac6ad0fdd2..529d99ec9a 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -318,7 +318,7 @@ Object *ClassDB::instantiate(const StringName &p_class) { { OBJTYPE_RLOCK; ti = classes.getptr(p_class); - if (!ti || ti->disabled || !ti->creation_func || (ti->native_extension && !ti->native_extension->create_instance)) { + if (!ti || ti->disabled || !ti->creation_func || (ti->gdextension && !ti->gdextension->create_instance)) { if (compat_classes.has(p_class)) { ti = classes.getptr(compat_classes[p_class]); } @@ -333,8 +333,8 @@ Object *ClassDB::instantiate(const StringName &p_class) { return nullptr; } #endif - if (ti->native_extension && ti->native_extension->create_instance) { - return (Object *)ti->native_extension->create_instance(ti->native_extension->class_userdata); + if (ti->gdextension && ti->gdextension->create_instance) { + return (Object *)ti->gdextension->create_instance(ti->gdextension->class_userdata); } else { return ti->creation_func(); } @@ -346,17 +346,17 @@ void ClassDB::set_object_extension_instance(Object *p_object, const StringName & { OBJTYPE_RLOCK; ti = classes.getptr(p_class); - if (!ti || ti->disabled || !ti->creation_func || (ti->native_extension && !ti->native_extension->create_instance)) { + if (!ti || ti->disabled || !ti->creation_func || (ti->gdextension && !ti->gdextension->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."); + ERR_FAIL_COND_MSG(!ti->gdextension, "Class '" + String(p_class) + "' has no native extension."); } - p_object->_extension = ti->native_extension; + p_object->_extension = ti->gdextension; p_object->_extension_instance = p_instance; } @@ -370,7 +370,7 @@ bool ClassDB::can_instantiate(const StringName &p_class) { return false; } #endif - return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance)); + return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance)); } bool ClassDB::is_virtual(const StringName &p_class) { @@ -388,7 +388,7 @@ bool ClassDB::is_virtual(const StringName &p_class) { return false; } #endif - return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance) && ti->is_virtual); + return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance) && ti->is_virtual); } void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) { @@ -1522,7 +1522,7 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con return var; } -void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) { +void ClassDB::register_extension_class(ObjectGDExtension *p_extension) { GLOBAL_LOCK_FUNCTION; ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), "Class already registered: " + String(p_extension->class_name)); @@ -1532,7 +1532,7 @@ void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) { ClassInfo c; c.api = p_extension->editor_class ? API_EDITOR_EXTENSION : API_EXTENSION; - c.native_extension = p_extension; + c.gdextension = p_extension; c.name = p_extension->class_name; c.is_virtual = p_extension->is_virtual; if (!p_extension->is_abstract) { diff --git a/core/object/class_db.h b/core/object/class_db.h index 5fba52e23e..4b60079298 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -100,7 +100,7 @@ public: ClassInfo *inherits_ptr = nullptr; void *class_ptr = nullptr; - ObjectNativeExtension *native_extension = nullptr; + ObjectGDExtension *gdextension = nullptr; HashMap<StringName, MethodBind *> method_map; HashMap<StringName, int64_t> constant_map; @@ -203,7 +203,7 @@ public: //nothing } - static void register_extension_class(ObjectNativeExtension *p_extension); + static void register_extension_class(ObjectGDExtension *p_extension); static void unregister_extension_class(const StringName &p_class); template <class T> diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py index 61bf6d900a..0ee95835a6 100644 --- a/core/object/make_virtuals.py +++ b/core/object/make_virtuals.py @@ -2,7 +2,7 @@ proto = """ #define GDVIRTUAL$VER($RET m_name $ARG) \\ StringName _gdvirtual_##m_name##_sn = #m_name;\\ mutable bool _gdvirtual_##m_name##_initialized = false;\\ -mutable GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = nullptr;\\ +mutable GDExtensionClassCallVirtual _gdvirtual_##m_name = nullptr;\\ template<bool required>\\ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\ ScriptInstance *_script_instance = ((Object*)(this))->get_script_instance();\\ @@ -16,8 +16,8 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\ } \\ }\\ if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\ - /* TODO: C-style cast because GDNativeStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\ - _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDNativeStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDNativeExtensionClassCallVirtual) nullptr;\\ + /* TODO: C-style cast because GDExtensionStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\ + _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDExtensionStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDExtensionClassCallVirtual) nullptr;\\ _gdvirtual_##m_name##_initialized = true;\\ }\\ if (_gdvirtual_##m_name) {\\ @@ -41,8 +41,8 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_overridden() const { \\ return _script_instance->has_method(_gdvirtual_##m_name##_sn);\\ }\\ if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\ - /* TODO: C-style cast because GDNativeStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\ - _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDNativeStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDNativeExtensionClassCallVirtual) nullptr;\\ + /* TODO: C-style cast because GDExtensionStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\ + _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDExtensionStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDExtensionClassCallVirtual) nullptr;\\ _gdvirtual_##m_name##_initialized = true;\\ }\\ if (_gdvirtual_##m_name) {\\ @@ -94,7 +94,7 @@ def generate_version(argcount, const=False, returns=False): argtext += ", " callsiargs = "Variant vargs[" + str(argcount) + "]={" callsiargptrs = "\t\tconst Variant *vargptrs[" + str(argcount) + "]={" - callptrargsptr = "\t\tconst GDNativeTypePtr argptrs[" + str(argcount) + "]={" + callptrargsptr = "\t\tGDExtensionConstTypePtr argptrs[" + str(argcount) + "]={" callptrargs = "" for i in range(argcount): if i > 0: @@ -121,7 +121,7 @@ def generate_version(argcount, const=False, returns=False): s = s.replace("$CALLSIARGPASS", "(const Variant **)vargptrs," + str(argcount)) callptrargsptr += "};\\\n" s = s.replace("$CALLPTRARGS", callptrargs + callptrargsptr) - s = s.replace("$CALLPTRARGPASS", "(const GDNativeTypePtr*)argptrs") + s = s.replace("$CALLPTRARGPASS", "reinterpret_cast<GDExtensionConstTypePtr*>(argptrs)") else: s = s.replace("$CALLSIARGS", "") s = s.replace("$CALLSIARGPASS", "nullptr, 0") diff --git a/core/object/method_bind.h b/core/object/method_bind.h index 598e8a224d..0f1366aefd 100644 --- a/core/object/method_bind.h +++ b/core/object/method_bind.h @@ -110,8 +110,8 @@ public: _FORCE_INLINE_ int get_argument_count() const { return argument_count; }; - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) = 0; - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) = 0; + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const = 0; + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const = 0; StringName get_name() const; void set_name(const StringName &p_name); @@ -158,7 +158,7 @@ public: } #endif - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { ERR_FAIL(); // Can't call. } @@ -210,7 +210,7 @@ class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, v friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>; public: - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>::method)(p_args, p_arg_count, r_error); return {}; } @@ -246,7 +246,7 @@ public: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { return (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>::method)(p_args, p_arg_count, r_error); } #if defined(SANITIZERS_ENABLED) && defined(__GNUC__) && !defined(__clang__) @@ -313,7 +313,7 @@ public: } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { #ifdef TYPED_METHOD_BIND call_with_variant_args_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); #else @@ -322,7 +322,7 @@ public: return Variant(); } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { #ifdef TYPED_METHOD_BIND call_with_ptr_args<T, P...>(static_cast<T *>(p_object), method, p_args); #else @@ -380,7 +380,7 @@ public: } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { #ifdef TYPED_METHOD_BIND call_with_variant_argsc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); #else @@ -389,7 +389,7 @@ public: return Variant(); } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { #ifdef TYPED_METHOD_BIND call_with_ptr_argsc<T, P...>(static_cast<T *>(p_object), method, p_args); #else @@ -457,7 +457,7 @@ public: } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { Variant ret; #ifdef TYPED_METHOD_BIND call_with_variant_args_ret_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); @@ -467,7 +467,7 @@ public: return ret; } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { #ifdef TYPED_METHOD_BIND call_with_ptr_args_ret<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret); #else @@ -536,7 +536,7 @@ public: } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { Variant ret; #ifdef TYPED_METHOD_BIND call_with_variant_args_retc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); @@ -546,7 +546,7 @@ public: return ret; } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { #ifdef TYPED_METHOD_BIND call_with_ptr_args_retc<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret); #else @@ -604,13 +604,13 @@ public: } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { (void)p_object; // unused call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments()); return Variant(); } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { (void)p_object; (void)r_ret; call_with_ptr_args_static_method(function, p_args); @@ -667,13 +667,13 @@ public: } #endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { Variant ret; call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments()); return ret; } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { (void)p_object; call_with_ptr_args_static_method_ret(function, p_args, r_ret); } diff --git a/core/object/object.cpp b/core/object/object.cpp index d27e0d7621..cfac36127c 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -233,7 +233,7 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wignored-qualifiers" #endif - if (_extension->set(_extension_instance, (const GDNativeStringNamePtr)&p_name, (const GDNativeVariantPtr)&p_value)) { + if (_extension->set(_extension_instance, (const GDExtensionStringNamePtr)&p_name, (const GDExtensionVariantPtr)&p_value)) { if (r_valid) { *r_valid = true; } @@ -321,7 +321,7 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { #pragma GCC diagnostic ignored "-Wignored-qualifiers" #endif - if (_extension->get(_extension_instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&ret)) { + if (_extension->get(_extension_instance, (const GDExtensionStringNamePtr)&p_name, (GDExtensionVariantPtr)&ret)) { if (r_valid) { *r_valid = true; } @@ -477,7 +477,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons } if (_extension) { - const ObjectNativeExtension *current_extension = _extension; + const ObjectGDExtension *current_extension = _extension; while (current_extension) { p_list->push_back(PropertyInfo(Variant::NIL, current_extension->class_name, PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); ClassDB::get_property_list(current_extension->class_name, p_list, true, this); @@ -487,7 +487,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons if (_extension && _extension->get_property_list) { uint32_t pcount; - const GDNativePropertyInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount); + const GDExtensionPropertyInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount); for (uint32_t i = 0; i < pcount; i++) { p_list->push_back(PropertyInfo(pinfo[i])); } @@ -533,7 +533,7 @@ bool Object::property_can_revert(const StringName &p_name) const { #pragma GCC diagnostic ignored "-Wignored-qualifiers" #endif if (_extension && _extension->property_can_revert) { - if (_extension->property_can_revert(_extension_instance, (const GDNativeStringNamePtr)&p_name)) { + if (_extension->property_can_revert(_extension_instance, (const GDExtensionStringNamePtr)&p_name)) { return true; } } @@ -559,7 +559,7 @@ Variant Object::property_get_revert(const StringName &p_name) const { #pragma GCC diagnostic ignored "-Wignored-qualifiers" #endif if (_extension && _extension->property_get_revert) { - if (_extension->property_get_revert(_extension_instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&ret)) { + if (_extension->property_get_revert(_extension_instance, (const GDExtensionStringNamePtr)&p_name, (GDExtensionVariantPtr)&ret)) { return ret; } } @@ -808,7 +808,7 @@ String Object::to_string() { } if (_extension && _extension->to_string) { String ret; - GDNativeBool is_valid; + GDExtensionBool is_valid; _extension->to_string(_extension_instance, &is_valid, &ret); return ret; } @@ -1473,6 +1473,8 @@ void Object::_bind_methods() { ClassDB::bind_method(D_METHOD("get_indexed", "property_path"), &Object::_get_indexed_bind); ClassDB::bind_method(D_METHOD("get_property_list"), &Object::_get_property_list_bind); ClassDB::bind_method(D_METHOD("get_method_list"), &Object::_get_method_list_bind); + ClassDB::bind_method(D_METHOD("property_can_revert", "property"), &Object::property_can_revert); + ClassDB::bind_method(D_METHOD("property_get_revert", "property"), &Object::property_get_revert); ClassDB::bind_method(D_METHOD("notification", "what", "reversed"), &Object::notification, DEFVAL(false)); ClassDB::bind_method(D_METHOD("to_string"), &Object::to_string); ClassDB::bind_method(D_METHOD("get_instance_id"), &Object::get_instance_id); @@ -1699,7 +1701,7 @@ uint32_t Object::get_edited_version() const { } #endif -void Object::set_instance_binding(void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) { +void Object::set_instance_binding(void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks) { // This is only meant to be used on creation by the binder. ERR_FAIL_COND(_instance_bindings != nullptr); _instance_bindings = (InstanceBinding *)memalloc(sizeof(InstanceBinding)); @@ -1710,7 +1712,7 @@ void Object::set_instance_binding(void *p_token, void *p_binding, const GDNative _instance_binding_count = 1; } -void *Object::get_instance_binding(void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) { +void *Object::get_instance_binding(void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks) { void *binding = nullptr; _instance_binding_mutex.lock(); for (uint32_t i = 0; i < _instance_binding_count; i++) { diff --git a/core/object/object.h b/core/object/object.h index 7bb88998a2..d52cf7d62e 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -31,7 +31,7 @@ #ifndef OBJECT_H #define OBJECT_H -#include "core/extension/gdnative_interface.h" +#include "core/extension/gdextension_interface.h" #include "core/object/message_queue.h" #include "core/object/object_id.h" #include "core/os/rw_lock.h" @@ -71,8 +71,6 @@ enum PropertyHint { PROPERTY_HINT_EXPRESSION, ///< used for string properties that can contain multiple lines PROPERTY_HINT_PLACEHOLDER_TEXT, ///< used to set a placeholder text for string properties PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color - PROPERTY_HINT_IMAGE_COMPRESS_LOSSY, - PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS, PROPERTY_HINT_OBJECT_ID, PROPERTY_HINT_TYPE_STRING, ///< a type string, the hint is the base type to choose PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE, ///< so something else can provide this (used in scripts) @@ -115,22 +113,21 @@ enum PropertyUsageFlags { PROPERTY_USAGE_RESTART_IF_CHANGED = 1 << 11, PROPERTY_USAGE_SCRIPT_VARIABLE = 1 << 12, PROPERTY_USAGE_STORE_IF_NULL = 1 << 13, - PROPERTY_USAGE_ANIMATE_AS_TRIGGER = 1 << 14, - PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED = 1 << 15, - PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 16, - PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 17, - PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 18, - PROPERTY_USAGE_INTERNAL = 1 << 19, - PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 20, // If the object is duplicated also this property will be duplicated. - PROPERTY_USAGE_HIGH_END_GFX = 1 << 21, - PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 22, - PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 23, - PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 24, // Used in inspector to increment property when keyed in animation player. - PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 25, // when loading, the resource for this property can be set at the end of loading. - PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 26, // For Object properties, instantiate them when creating in editor. - PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 27, //for project or editor settings, show when basic settings are selected. - PROPERTY_USAGE_READ_ONLY = 1 << 28, // Mark a property as read-only in the inspector. - PROPERTY_USAGE_ARRAY = 1 << 29, // Used in the inspector to group properties as elements of an array. + PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED = 1 << 14, + PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 15, + PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 16, + PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 17, + PROPERTY_USAGE_INTERNAL = 1 << 18, + PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 19, // If the object is duplicated also this property will be duplicated. + PROPERTY_USAGE_HIGH_END_GFX = 1 << 20, + PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 21, + PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 22, + PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 23, // Used in inspector to increment property when keyed in animation player. + PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 24, // when loading, the resource for this property can be set at the end of loading. + PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 25, // For Object properties, instantiate them when creating in editor. + PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 26, //for project or editor settings, show when basic settings are selected. + PROPERTY_USAGE_READ_ONLY = 1 << 27, // Mark a property as read-only in the inspector. + PROPERTY_USAGE_ARRAY = 1 << 28, // Used in the inspector to group properties as elements of an array. PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR, PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNATIONALIZED, @@ -151,6 +148,10 @@ enum PropertyUsageFlags { #define ADD_ARRAY_COUNT_WITH_USAGE_FLAGS(m_label, m_count_property, m_count_property_setter, m_count_property_getter, m_prefix, m_property_usage_flags) ClassDB::add_property_array_count(get_class_static(), m_label, m_count_property, _scs_create(m_count_property_setter), _scs_create(m_count_property_getter), m_prefix, m_property_usage_flags) #define ADD_ARRAY(m_array_path, m_prefix) ClassDB::add_property_array(get_class_static(), m_array_path, m_prefix) +// Helper macro to use with PROPERTY_HINT_ARRAY_TYPE for arrays of specific resources: +// PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font") +#define MAKE_RESOURCE_TYPE_HINT(m_type) vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, m_type) + struct PropertyInfo { Variant::Type type = Variant::NIL; String name; @@ -190,7 +191,7 @@ struct PropertyInfo { type(Variant::OBJECT), class_name(p_class_name) {} - explicit PropertyInfo(const GDNativePropertyInfo &pinfo) : + explicit PropertyInfo(const GDExtensionPropertyInfo &pinfo) : type((Variant::Type)pinfo.type), name(*reinterpret_cast<StringName *>(pinfo.name)), class_name(*reinterpret_cast<StringName *>(pinfo.class_name)), @@ -242,7 +243,7 @@ struct MethodInfo { MethodInfo() {} - explicit MethodInfo(const GDNativeMethodInfo &pinfo) : + explicit MethodInfo(const GDExtensionMethodInfo &pinfo) : name(*reinterpret_cast<StringName *>(pinfo.name)), return_val(PropertyInfo(pinfo.return_value)), flags(pinfo.flags), @@ -300,31 +301,31 @@ struct MethodInfo { } }; -// API used to extend in GDNative and other C compatible compiled languages. +// API used to extend in GDExtension and other C compatible compiled languages. class MethodBind; -struct ObjectNativeExtension { - ObjectNativeExtension *parent = nullptr; - List<ObjectNativeExtension *> children; +struct ObjectGDExtension { + ObjectGDExtension *parent = nullptr; + List<ObjectGDExtension *> children; StringName parent_class_name; StringName class_name; bool editor_class = false; bool is_virtual = false; bool is_abstract = false; - GDNativeExtensionClassSet set; - GDNativeExtensionClassGet get; - GDNativeExtensionClassGetPropertyList get_property_list; - GDNativeExtensionClassFreePropertyList free_property_list; - GDNativeExtensionClassPropertyCanRevert property_can_revert; - GDNativeExtensionClassPropertyGetRevert property_get_revert; - GDNativeExtensionClassNotification notification; - GDNativeExtensionClassToString to_string; - GDNativeExtensionClassReference reference; - GDNativeExtensionClassReference unreference; - GDNativeExtensionClassGetRID get_rid; + GDExtensionClassSet set; + GDExtensionClassGet get; + GDExtensionClassGetPropertyList get_property_list; + GDExtensionClassFreePropertyList free_property_list; + GDExtensionClassPropertyCanRevert property_can_revert; + GDExtensionClassPropertyGetRevert property_get_revert; + GDExtensionClassNotification notification; + GDExtensionClassToString to_string; + GDExtensionClassReference reference; + GDExtensionClassReference unreference; + GDExtensionClassGetRID get_rid; _FORCE_INLINE_ bool is_class(const String &p_class) const { - const ObjectNativeExtension *e = this; + const ObjectGDExtension *e = this; while (e) { if (p_class == e->class_name.operator String()) { return true; @@ -335,9 +336,9 @@ struct ObjectNativeExtension { } void *class_userdata = nullptr; - GDNativeExtensionClassCreateInstance create_instance; - GDNativeExtensionClassFreeInstance free_instance; - GDNativeExtensionClassGetVirtual get_virtual; + GDExtensionClassCreateInstance create_instance; + GDExtensionClassFreeInstance free_instance; + GDExtensionClassGetVirtual get_virtual; }; #define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call<false>(__VA_ARGS__) @@ -555,6 +556,7 @@ public: CONNECT_PERSIST = 2, // hint for scene to save this connection CONNECT_ONE_SHOT = 4, CONNECT_REFERENCE_COUNTED = 8, + CONNECT_INHERITED = 16, // Used in editor builds. }; struct Connection { @@ -577,7 +579,7 @@ private: friend bool predelete_handler(Object *); friend void postinitialize_handler(Object *); - ObjectNativeExtension *_extension = nullptr; + ObjectGDExtension *_extension = nullptr; GDExtensionClassInstancePtr _extension_instance = nullptr; struct SignalData { @@ -635,8 +637,8 @@ private: struct InstanceBinding { void *binding = nullptr; void *token = nullptr; - GDNativeInstanceBindingFreeCallback free_callback = nullptr; - GDNativeInstanceBindingReferenceCallback reference_callback = nullptr; + GDExtensionInstanceBindingFreeCallback free_callback = nullptr; + GDExtensionInstanceBindingReferenceCallback reference_callback = nullptr; }; InstanceBinding *_instance_bindings = nullptr; uint32_t _instance_binding_count = 0; @@ -660,8 +662,8 @@ protected: return can_die; } - friend class NativeExtensionMethodBind; - _ALWAYS_INLINE_ const ObjectNativeExtension *_get_extension() const { return _extension; } + friend class GDExtensionMethodBind; + _ALWAYS_INLINE_ const ObjectGDExtension *_get_extension() const { return _extension; } _ALWAYS_INLINE_ GDExtensionClassInstancePtr _get_extension_instance() const { return _extension_instance; } virtual void _initialize_classv() { initialize_class(); } virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; }; @@ -915,9 +917,9 @@ public: #endif // Used by script languages to store binding data. - void *get_instance_binding(void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks); + void *get_instance_binding(void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks); // Used on creation by binding only. - void set_instance_binding(void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks); + void set_instance_binding(void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks); bool has_instance_binding(void *p_token); void clear_internal_resource_paths(); diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h index 71790fb825..411c589739 100644 --- a/core/object/ref_counted.h +++ b/core/object/ref_counted.h @@ -253,12 +253,14 @@ public: template <class T> struct PtrToArg<Ref<T>> { _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { + // p_ptr points to a RefCounted object return Ref<T>(const_cast<T *>(reinterpret_cast<const T *>(p_ptr))); } typedef Ref<T> EncodeT; _FORCE_INLINE_ static void encode(Ref<T> p_val, const void *p_ptr) { + // p_ptr points to an EncodeT object which is a Ref<T> object. *(const_cast<Ref<RefCounted> *>(reinterpret_cast<const Ref<RefCounted> *>(p_ptr))) = p_val; } }; @@ -268,6 +270,7 @@ struct PtrToArg<const Ref<T> &> { typedef Ref<T> EncodeT; _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { + // p_ptr points to a RefCounted object return Ref<T>((T *)p_ptr); } }; diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index 056c57a5f1..36a0d03aaf 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -409,7 +409,9 @@ bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_v if (values.has(p_name)) { Variant defval; if (script->get_property_default_value(p_name, defval)) { - if (defval == p_value) { + // The evaluate function ensures that a NIL variant is equal to e.g. an empty Resource. + // Simply doing defval == p_value does not do this. + if (Variant::evaluate(Variant::OP_EQUAL, defval, p_value)) { values.erase(p_name); return true; } @@ -419,7 +421,7 @@ bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_v } else { Variant defval; if (script->get_property_default_value(p_name, defval)) { - if (defval != p_value) { + if (Variant::evaluate(Variant::OP_NOT_EQUAL, defval, p_value)) { values[p_name] = p_value; } return true; diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index c287a6f71a..0ecd98152a 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -43,7 +43,7 @@ class ScriptExtension : public Script { protected: EXBIND0R(bool, editor_can_reload_from_file) - GDVIRTUAL1(_placeholder_erased, GDNativePtr<void>) + GDVIRTUAL1(_placeholder_erased, GDExtensionPtr<void>) virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override { GDVIRTUAL_CALL(_placeholder_erased, p_placeholder); } @@ -56,15 +56,15 @@ public: EXBIND1RC(bool, inherits_script, const Ref<Script> &) EXBIND0RC(StringName, get_instance_base_type) - GDVIRTUAL1RC(GDNativePtr<void>, _instance_create, Object *) + GDVIRTUAL1RC(GDExtensionPtr<void>, _instance_create, Object *) virtual ScriptInstance *instance_create(Object *p_this) override { - GDNativePtr<void> ret = nullptr; + GDExtensionPtr<void> ret = nullptr; GDVIRTUAL_REQUIRED_CALL(_instance_create, p_this, ret); return reinterpret_cast<ScriptInstance *>(ret.operator void *()); } - GDVIRTUAL1RC(GDNativePtr<void>, _placeholder_instance_create, Object *) + GDVIRTUAL1RC(GDExtensionPtr<void>, _placeholder_instance_create, Object *) PlaceHolderScriptInstance *placeholder_instance_create(Object *p_this) override { - GDNativePtr<void> ret = nullptr; + GDExtensionPtr<void> ret = nullptr; GDVIRTUAL_REQUIRED_CALL(_placeholder_instance_create, p_this, ret); return reinterpret_cast<PlaceHolderScriptInstance *>(ret.operator void *()); } @@ -482,10 +482,10 @@ public: } } } - GDVIRTUAL1R(GDNativePtr<void>, _debug_get_stack_level_instance, int) + GDVIRTUAL1R(GDExtensionPtr<void>, _debug_get_stack_level_instance, int) virtual ScriptInstance *debug_get_stack_level_instance(int p_level) override { - GDNativePtr<void> ret = nullptr; + GDExtensionPtr<void> ret = nullptr; GDVIRTUAL_REQUIRED_CALL(_debug_get_stack_level_instance, p_level, ret); return reinterpret_cast<ScriptInstance *>(ret.operator void *()); } @@ -578,7 +578,7 @@ public: EXBIND0(profiling_start) EXBIND0(profiling_stop) - GDVIRTUAL2R(int, _profiling_get_accumulated_data, GDNativePtr<ScriptLanguageExtensionProfilingInfo>, int) + GDVIRTUAL2R(int, _profiling_get_accumulated_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int) virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) override { int ret = 0; @@ -586,7 +586,7 @@ public: return ret; } - GDVIRTUAL2R(int, _profiling_get_frame_data, GDNativePtr<ScriptLanguageExtensionProfilingInfo>, int) + GDVIRTUAL2R(int, _profiling_get_frame_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int) virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) override { int ret = 0; @@ -594,15 +594,15 @@ public: return ret; } - GDVIRTUAL1R(GDNativePtr<void>, _alloc_instance_binding_data, Object *) + GDVIRTUAL1R(GDExtensionPtr<void>, _alloc_instance_binding_data, Object *) virtual void *alloc_instance_binding_data(Object *p_object) override { - GDNativePtr<void> ret = nullptr; + GDExtensionPtr<void> ret = nullptr; GDVIRTUAL_REQUIRED_CALL(_alloc_instance_binding_data, p_object, ret); return ret.operator void *(); } - GDVIRTUAL1(_free_instance_binding_data, GDNativePtr<void>) + GDVIRTUAL1(_free_instance_binding_data, GDExtensionPtr<void>) virtual void free_instance_binding_data(void *p_data) override { GDVIRTUAL_REQUIRED_CALL(_free_instance_binding_data, p_data); @@ -639,8 +639,8 @@ VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionLocation) class ScriptInstanceExtension : public ScriptInstance { public: - const GDNativeExtensionScriptInstanceInfo *native_info; - GDNativeExtensionScriptInstanceDataPtr instance = nullptr; + const GDExtensionScriptInstanceInfo *native_info; + GDExtensionScriptInstanceDataPtr instance = nullptr; // There should not be warnings on explicit casts. #if defined(__GNUC__) && !defined(__clang__) @@ -650,20 +650,20 @@ public: virtual bool set(const StringName &p_name, const Variant &p_value) override { if (native_info->set_func) { - return native_info->set_func(instance, (const GDNativeStringNamePtr)&p_name, (const GDNativeVariantPtr)&p_value); + return native_info->set_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionConstVariantPtr)&p_value); } return false; } virtual bool get(const StringName &p_name, Variant &r_ret) const override { if (native_info->get_func) { - return native_info->get_func(instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&r_ret); + return native_info->get_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionVariantPtr)&r_ret); } return false; } virtual void get_property_list(List<PropertyInfo> *p_list) const override { if (native_info->get_property_list_func) { uint32_t pcount; - const GDNativePropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount); + const GDExtensionPropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount); #ifdef TOOLS_ENABLED Ref<Script> script = get_script(); @@ -681,32 +681,26 @@ public: } } virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const override { - Variant::Type type = Variant::Type::NIL; - if (native_info->get_property_list_func) { - uint32_t pcount; - const GDNativePropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount); - for (uint32_t i = 0; i < pcount; i++) { - if (p_name == *reinterpret_cast<StringName *>(pinfo->name)) { - type = Variant::Type(pinfo->type); - break; - } - } - if (native_info->free_property_list_func) { - native_info->free_property_list_func(instance, pinfo); + if (native_info->get_property_type_func) { + GDExtensionBool is_valid = 0; + GDExtensionVariantType type = native_info->get_property_type_func(instance, (GDExtensionConstStringNamePtr)&p_name, &is_valid); + if (r_is_valid) { + *r_is_valid = is_valid != 0; } + return Variant::Type(type); } - return type; + return Variant::NIL; } virtual bool property_can_revert(const StringName &p_name) const override { if (native_info->property_can_revert_func) { - return native_info->property_can_revert_func(instance, (const GDNativeStringNamePtr)&p_name); + return native_info->property_can_revert_func(instance, (GDExtensionConstStringNamePtr)&p_name); } return false; } virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const override { if (native_info->property_get_revert_func) { - return native_info->property_get_revert_func(instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&r_ret); + return native_info->property_get_revert_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionVariantPtr)&r_ret); } return false; } @@ -717,7 +711,7 @@ public: } return nullptr; } - static void _add_property_with_state(const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value, void *p_userdata) { + static void _add_property_with_state(GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value, void *p_userdata) { List<Pair<StringName, Variant>> *state = (List<Pair<StringName, Variant>> *)p_userdata; state->push_back(Pair<StringName, Variant>(*(const StringName *)p_name, *(const Variant *)p_value)); } @@ -730,7 +724,7 @@ public: virtual void get_method_list(List<MethodInfo> *p_list) const override { if (native_info->get_method_list_func) { uint32_t mcount; - const GDNativeMethodInfo *minfo = native_info->get_method_list_func(instance, &mcount); + const GDExtensionMethodInfo *minfo = native_info->get_method_list_func(instance, &mcount); for (uint32_t i = 0; i < mcount; i++) { p_list->push_back(MethodInfo(minfo[i])); } @@ -741,7 +735,7 @@ public: } virtual bool has_method(const StringName &p_method) const override { if (native_info->has_method_func) { - return native_info->has_method_func(instance, (GDNativeStringNamePtr)&p_method); + return native_info->has_method_func(instance, (GDExtensionStringNamePtr)&p_method); } return false; } @@ -749,8 +743,8 @@ public: virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override { Variant ret; if (native_info->call_func) { - GDNativeCallError ce; - native_info->call_func(instance, (const GDNativeStringNamePtr)&p_method, (const GDNativeVariantPtr *)p_args, p_argcount, (GDNativeVariantPtr)&ret, &ce); + GDExtensionCallError ce; + native_info->call_func(instance, (GDExtensionConstStringNamePtr)&p_method, (GDExtensionConstVariantPtr *)p_args, p_argcount, (GDExtensionVariantPtr)&ret, &ce); r_error.error = Callable::CallError::Error(ce.error); r_error.argument = ce.argument; r_error.expected = ce.expected; @@ -765,9 +759,9 @@ public: } virtual String to_string(bool *r_valid) override { if (native_info->to_string_func) { - GDNativeBool valid; + GDExtensionBool valid; String ret; - native_info->to_string_func(instance, &valid, reinterpret_cast<GDNativeStringPtr>(&ret)); + native_info->to_string_func(instance, &valid, reinterpret_cast<GDExtensionStringPtr>(&ret)); if (r_valid) { *r_valid = valid != 0; } @@ -790,7 +784,7 @@ public: virtual Ref<Script> get_script() const override { if (native_info->get_script_func) { - GDNativeObjectPtr script = native_info->get_script_func(instance); + GDExtensionObjectPtr script = native_info->get_script_func(instance); return Ref<Script>(reinterpret_cast<Script *>(script)); } return Ref<Script>(); @@ -805,7 +799,7 @@ public: virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid) override { if (native_info->set_fallback_func) { - bool ret = native_info->set_fallback_func(instance, (const GDNativeStringNamePtr)&p_name, (const GDNativeVariantPtr)&p_value); + bool ret = native_info->set_fallback_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionConstVariantPtr)&p_value); if (r_valid) { *r_valid = ret; } @@ -814,7 +808,7 @@ public: virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid) override { Variant ret; if (native_info->get_fallback_func) { - bool valid = native_info->get_fallback_func(instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&ret); + bool valid = native_info->get_fallback_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionVariantPtr)&ret); if (r_valid) { *r_valid = valid; } @@ -824,7 +818,7 @@ public: virtual ScriptLanguage *get_language() override { if (native_info->get_language_func) { - GDNativeExtensionScriptLanguagePtr lang = native_info->get_language_func(instance); + GDExtensionScriptLanguagePtr lang = native_info->get_language_func(instance); return reinterpret_cast<ScriptLanguage *>(lang); } return nullptr; diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp index aa66e86bc0..9f8a1de697 100644 --- a/core/object/undo_redo.cpp +++ b/core/object/undo_redo.cpp @@ -423,6 +423,10 @@ String UndoRedo::get_current_action_name() const { return actions[current_action].name; } +int UndoRedo::get_action_level() const { + return action_level; +} + bool UndoRedo::has_undo() const { return current_action >= 0; } diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h index c7c58697c3..9c6d2d10ed 100644 --- a/core/object/undo_redo.h +++ b/core/object/undo_redo.h @@ -120,6 +120,7 @@ public: bool redo(); bool undo(); String get_current_action_name() const; + int get_action_level() const; int get_history_count(); int get_current_action(); diff --git a/core/object/worker_thread_pool.cpp b/core/object/worker_thread_pool.cpp index 9b3dc6833e..0218a4c8f6 100644 --- a/core/object/worker_thread_pool.cpp +++ b/core/object/worker_thread_pool.cpp @@ -402,7 +402,9 @@ void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) { } } - groups.erase(p_group); // Threads do not access this, so safe to erase here. + task_mutex.lock(); // This mutex is needed when Physics 2D and/or 3D is selected to run on a separate thread. + groups.erase(p_group); + task_mutex.unlock(); } void WorkerThreadPool::init(int p_thread_count, bool p_use_native_threads_low_priority, float p_low_priority_task_ratio) { diff --git a/core/os/os.cpp b/core/os/os.cpp index bbb2a94fe7..6b199e883f 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -155,10 +155,6 @@ int OS::get_process_id() const { return -1; } -void OS::vibrate_handheld(int p_duration_ms) { - WARN_PRINT("vibrate_handheld() only works with Android, iOS and Web"); -} - bool OS::is_stdout_verbose() const { return _verbose_stdout; } @@ -353,20 +349,36 @@ bool OS::has_feature(const String &p_feature) { if (p_feature == "debug") { return true; } +#endif // DEBUG_ENABLED + +#ifdef TOOLS_ENABLED + if (p_feature == "editor") { + return true; + } #else - if (p_feature == "release") { + if (p_feature == "template") { return true; } -#endif -#ifdef TOOLS_ENABLED - if (p_feature == "editor") { +#ifdef DEBUG_ENABLED + if (p_feature == "template_debug") { return true; } #else - if (p_feature == "standalone") { + if (p_feature == "template_release" || p_feature == "release") { return true; } -#endif +#endif // DEBUG_ENABLED +#endif // TOOLS_ENABLED + +#ifdef REAL_T_IS_DOUBLE + if (p_feature == "double") { + return true; + } +#else + if (p_feature == "single") { + return true; + } +#endif // REAL_T_IS_DOUBLE if (sizeof(void *) == 8 && p_feature == "64") { return true; diff --git a/core/os/os.h b/core/os/os.h index af7b40f3ec..07e9020a51 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -150,7 +150,8 @@ public: virtual int get_low_processor_usage_mode_sleep_usec() const; virtual Vector<String> get_system_fonts() const { return Vector<String>(); }; - virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const { return String(); }; + virtual String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return String(); }; + virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return Vector<String>(); }; 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, bool p_open_console = false) = 0; virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) = 0; @@ -158,7 +159,7 @@ public: virtual Error kill(const ProcessID &p_pid) = 0; virtual int get_process_id() const; virtual bool is_process_running(const ProcessID &p_pid) const = 0; - virtual void vibrate_handheld(int p_duration_ms = 500); + virtual void vibrate_handheld(int p_duration_ms = 500) {} virtual Error shell_open(String p_uri); virtual Error set_cwd(const String &p_cwd); diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 2e144a4c9a..7a7e45f752 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -38,8 +38,8 @@ #include "core/crypto/crypto.h" #include "core/crypto/hashing_context.h" #include "core/debugger/engine_profiler.h" -#include "core/extension/native_extension.h" -#include "core/extension/native_extension_manager.h" +#include "core/extension/gdextension.h" +#include "core/extension/gdextension_manager.h" #include "core/input/input.h" #include "core/input/input_map.h" #include "core/input/shortcut.h" @@ -88,7 +88,7 @@ static Ref<ResourceFormatLoaderImage> resource_format_image; static Ref<TranslationLoaderPO> resource_format_po; static Ref<ResourceFormatSaverCrypto> resource_format_saver_crypto; static Ref<ResourceFormatLoaderCrypto> resource_format_loader_crypto; -static Ref<NativeExtensionResourceLoader> resource_loader_native_extension; +static Ref<GDExtensionResourceLoader> resource_loader_gdextension; static Ref<ResourceFormatSaverJSON> resource_saver_json; static Ref<ResourceFormatLoaderJSON> resource_loader_json; @@ -109,7 +109,7 @@ static WorkerThreadPool *worker_thread_pool = nullptr; extern Mutex _global_mutex; -static NativeExtensionManager *native_extension_manager = nullptr; +static GDExtensionManager *gdextension_manager = nullptr; extern void register_global_constants(); extern void unregister_global_constants(); @@ -256,9 +256,9 @@ void register_core_types() { GDREGISTER_CLASS(ImageFormatLoaderExtension); GDREGISTER_ABSTRACT_CLASS(ResourceImporter); - GDREGISTER_CLASS(NativeExtension); + GDREGISTER_CLASS(GDExtension); - GDREGISTER_ABSTRACT_CLASS(NativeExtensionManager); + GDREGISTER_ABSTRACT_CLASS(GDExtensionManager); GDREGISTER_ABSTRACT_CLASS(ResourceUID); @@ -266,10 +266,10 @@ void register_core_types() { resource_uid = memnew(ResourceUID); - native_extension_manager = memnew(NativeExtensionManager); + gdextension_manager = memnew(GDExtensionManager); - resource_loader_native_extension.instantiate(); - ResourceLoader::add_resource_format_loader(resource_loader_native_extension); + resource_loader_gdextension.instantiate(); + ResourceLoader::add_resource_format_loader(resource_loader_gdextension); ip = IP::create(); @@ -344,27 +344,27 @@ void register_core_singletons() { Engine::get_singleton()->add_singleton(Engine::Singleton("InputMap", InputMap::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("EngineDebugger", core_bind::EngineDebugger::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("Time", Time::get_singleton())); - Engine::get_singleton()->add_singleton(Engine::Singleton("NativeExtensionManager", NativeExtensionManager::get_singleton())); + Engine::get_singleton()->add_singleton(Engine::Singleton("GDExtensionManager", GDExtensionManager::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceUID", ResourceUID::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("WorkerThreadPool", worker_thread_pool)); } void register_core_extensions() { // Hardcoded for now. - NativeExtension::initialize_native_extensions(); - native_extension_manager->load_extensions(); - native_extension_manager->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_CORE); + GDExtension::initialize_gdextensions(); + gdextension_manager->load_extensions(); + gdextension_manager->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_CORE); _is_core_extensions_registered = true; } void unregister_core_extensions() { if (_is_core_extensions_registered) { - native_extension_manager->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_CORE); + gdextension_manager->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_CORE); } } void unregister_core_types() { - memdelete(native_extension_manager); + memdelete(gdextension_manager); memdelete(resource_uid); memdelete(_resource_loader); @@ -410,8 +410,8 @@ void unregister_core_types() { memdelete(ip); } - ResourceLoader::remove_resource_format_loader(resource_loader_native_extension); - resource_loader_native_extension.unref(); + ResourceLoader::remove_resource_format_loader(resource_loader_gdextension); + resource_loader_gdextension.unref(); ResourceLoader::finalize(); diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp index b130c2fc79..2fb3b54e27 100644 --- a/core/string/optimized_translation.cpp +++ b/core/string/optimized_translation.cpp @@ -267,6 +267,39 @@ StringName OptimizedTranslation::get_message(const StringName &p_src_text, const } } +Vector<String> OptimizedTranslation::get_translated_message_list() const { + Vector<String> msgs; + + const int *htr = hash_table.ptr(); + const uint32_t *htptr = (const uint32_t *)&htr[0]; + const int *btr = bucket_table.ptr(); + const uint32_t *btptr = (const uint32_t *)&btr[0]; + const uint8_t *sr = strings.ptr(); + const char *sptr = (const char *)&sr[0]; + + for (int i = 0; i < hash_table.size(); i++) { + uint32_t p = htptr[i]; + if (p != 0xFFFFFFFF) { + const Bucket &bucket = *(const Bucket *)&btptr[p]; + for (int j = 0; j < bucket.size; j++) { + if (bucket.elem[j].comp_size == bucket.elem[j].uncomp_size) { + String rstr; + rstr.parse_utf8(&sptr[bucket.elem[j].str_offset], bucket.elem[j].uncomp_size); + msgs.push_back(rstr); + } else { + CharString uncomp; + uncomp.resize(bucket.elem[j].uncomp_size + 1); + smaz_decompress(&sptr[bucket.elem[j].str_offset], bucket.elem[j].comp_size, uncomp.ptrw(), bucket.elem[j].uncomp_size); + String rstr; + rstr.parse_utf8(uncomp.get_data()); + msgs.push_back(rstr); + } + } + } + } + return msgs; +} + StringName OptimizedTranslation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const { // The use of plurals translation is not yet supported in OptimizedTranslation. return get_message(p_src_text, p_context); diff --git a/core/string/optimized_translation.h b/core/string/optimized_translation.h index f3dbfe8f5c..1cd12782d0 100644 --- a/core/string/optimized_translation.h +++ b/core/string/optimized_translation.h @@ -81,6 +81,7 @@ protected: public: virtual StringName get_message(const StringName &p_src_text, const StringName &p_context = "") const override; //overridable for other implementations virtual StringName get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context = "") const override; + virtual Vector<String> get_translated_message_list() const override; void generate(const Ref<Translation> &p_from); OptimizedTranslation() {} diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp index 9c4fc4e1b7..64d49b8b93 100644 --- a/core/string/string_name.cpp +++ b/core/string/string_name.cpp @@ -169,6 +169,10 @@ bool StringName::operator!=(const String &p_name) const { return !(operator==(p_name)); } +bool StringName::operator!=(const char *p_name) const { + return !(operator==(p_name)); +} + bool StringName::operator!=(const StringName &p_name) const { // the real magic of all this mess happens here. // this is why path comparisons are very fast diff --git a/core/string/string_name.h b/core/string/string_name.h index ff4c41af94..6a2420e02a 100644 --- a/core/string/string_name.h +++ b/core/string/string_name.h @@ -102,6 +102,7 @@ public: bool operator==(const String &p_name) const; bool operator==(const char *p_name) const; bool operator!=(const String &p_name) const; + bool operator!=(const char *p_name) const; _FORCE_INLINE_ bool is_node_unique_name() const { if (!_data) { diff --git a/core/string/translation.cpp b/core/string/translation.cpp index 2bed3543dc..d1ac91957a 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -59,6 +59,18 @@ Vector<String> Translation::_get_message_list() const { return msgs; } +Vector<String> Translation::get_translated_message_list() const { + Vector<String> msgs; + msgs.resize(translation_map.size()); + int idx = 0; + for (const KeyValue<StringName, StringName> &E : translation_map) { + msgs.set(idx, E.value); + idx += 1; + } + + return msgs; +} + void Translation::_set_messages(const Dictionary &p_messages) { List<Variant> keys; p_messages.get_key_list(&keys); @@ -140,6 +152,7 @@ void Translation::_bind_methods() { ClassDB::bind_method(D_METHOD("get_plural_message", "src_message", "src_plural_message", "n", "context"), &Translation::get_plural_message, DEFVAL("")); ClassDB::bind_method(D_METHOD("erase_message", "src_message", "context"), &Translation::erase_message, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_message_list"), &Translation::_get_message_list); + ClassDB::bind_method(D_METHOD("get_translated_message_list"), &Translation::get_translated_message_list); ClassDB::bind_method(D_METHOD("get_message_count"), &Translation::get_message_count); ClassDB::bind_method(D_METHOD("_set_messages", "messages"), &Translation::_set_messages); ClassDB::bind_method(D_METHOD("_get_messages"), &Translation::_get_messages); diff --git a/core/string/translation.h b/core/string/translation.h index 9a369b0b05..5e8344baac 100644 --- a/core/string/translation.h +++ b/core/string/translation.h @@ -64,6 +64,7 @@ public: virtual void erase_message(const StringName &p_src_text, const StringName &p_context = ""); virtual void get_message_list(List<StringName> *r_messages) const; virtual int get_message_count() const; + virtual Vector<String> get_translated_message_list() const; Translation() {} }; diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp index fa656b634d..724c1d42bc 100644 --- a/core/string/translation_po.cpp +++ b/core/string/translation_po.cpp @@ -103,6 +103,23 @@ void TranslationPO::_set_messages(const Dictionary &p_messages) { } } +Vector<String> TranslationPO::get_translated_message_list() const { + Vector<String> msgs; + for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) { + if (E.key != StringName()) { + continue; + } + + for (const KeyValue<StringName, Vector<StringName>> &E2 : E.value) { + for (const StringName &E3 : E2.value) { + msgs.push_back(E3); + } + } + } + + return msgs; +} + Vector<String> TranslationPO::_get_message_list() const { // Return all keys in translation_map. diff --git a/core/string/translation_po.h b/core/string/translation_po.h index 7d63af2246..c50ea85744 100644 --- a/core/string/translation_po.h +++ b/core/string/translation_po.h @@ -70,6 +70,7 @@ protected: static void _bind_methods(); public: + Vector<String> get_translated_message_list() const override; void get_message_list(List<StringName> *r_messages) const override; int get_message_count() const override; void add_message(const StringName &p_src_text, const StringName &p_xlated_text, const StringName &p_context = "") override; diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 2ba389fc4d..adab6d07c7 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -161,6 +161,18 @@ bool CharString::operator<(const CharString &p_right) const { return is_str_less(get_data(), p_right.get_data()); } +bool CharString::operator==(const CharString &p_right) const { + if (length() == 0) { + // True if both have length 0, false if only p_right has a length + return p_right.length() == 0; + } else if (p_right.length() == 0) { + // False due to unequal length + return false; + } + + return strcmp(ptr(), p_right.ptr()) == 0; +} + CharString &CharString::operator+=(char p_char) { const int lhs_len = length(); resize(lhs_len + 2); @@ -208,37 +220,6 @@ void CharString::copy_from(const char *p_cstr) { /* String */ /*************************************************************************/ -//kind of poor should be rewritten properly -String String::word_wrap(int p_chars_per_line) const { - int from = 0; - int last_space = 0; - String ret; - for (int i = 0; i < length(); i++) { - if (i - from >= p_chars_per_line) { - if (last_space == -1) { - ret += substr(from, i - from + 1) + "\n"; - } else { - ret += substr(from, last_space - from) + "\n"; - i = last_space; //rewind - } - from = i + 1; - last_space = -1; - } else if (operator[](i) == ' ' || operator[](i) == '\t') { - last_space = i; - } else if (operator[](i) == '\n') { - ret += substr(from, i - from) + "\n"; - from = i + 1; - last_space = -1; - } - } - - if (from < length()) { - ret += substr(from, length()); - } - - return ret; -} - Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const { // Splits the URL into scheme, host, port, path. Strip credentials when present. String base = *this; @@ -1256,8 +1237,8 @@ Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int return ret; } -Vector<float> String::split_floats(const String &p_splitter, bool p_allow_empty) const { - Vector<float> ret; +Vector<double> String::split_floats(const String &p_splitter, bool p_allow_empty) const { + Vector<double> ret; int from = 0; int len = length(); @@ -2839,7 +2820,7 @@ String String::substr(int p_from, int p_chars) const { return String(*this); } - String s = String(); + String s; s.copy_from_unchecked(&get_data()[p_from], p_chars); return s; } @@ -3922,7 +3903,6 @@ String String::c_unescape() const { escaped = escaped.replace("\\v", "\v"); escaped = escaped.replace("\\'", "\'"); escaped = escaped.replace("\\\"", "\""); - escaped = escaped.replace("\\?", "\?"); escaped = escaped.replace("\\\\", "\\"); return escaped; @@ -3939,7 +3919,6 @@ String String::c_escape() const { escaped = escaped.replace("\t", "\\t"); escaped = escaped.replace("\v", "\\v"); escaped = escaped.replace("\'", "\\'"); - escaped = escaped.replace("\?", "\\?"); escaped = escaped.replace("\"", "\\\""); return escaped; diff --git a/core/string/ustring.h b/core/string/ustring.h index 8af74584f3..559f679f0f 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -156,6 +156,7 @@ public: void operator=(const char *p_cstr); bool operator<(const CharString &p_right) const; + bool operator==(const CharString &p_right) const; CharString &operator+=(char p_char); int length() const { return size() ? size() - 1 : 0; } const char *get_data() const; @@ -348,7 +349,7 @@ public: Vector<String> split(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; Vector<String> rsplit(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; Vector<String> split_spaces() const; - Vector<float> split_floats(const String &p_splitter, bool p_allow_empty = true) const; + Vector<double> split_floats(const String &p_splitter, bool p_allow_empty = true) const; Vector<float> split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const; Vector<int> split_ints(const String &p_splitter, bool p_allow_empty = true) const; Vector<int> split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const; @@ -424,7 +425,6 @@ public: String c_escape_multiline() const; String c_unescape() const; String json_escape() const; - String word_wrap(int p_chars_per_line) const; Error parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const; String property_name_encode() const; diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h index 456a7b01ed..059f30df38 100644 --- a/core/templates/hashfuncs.h +++ b/core/templates/hashfuncs.h @@ -310,6 +310,7 @@ struct HashMapHasherDefault { static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); } static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); } static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); } + static _FORCE_INLINE_ uint32_t hash(const CharString &p_char_string) { return hash_djb2(p_char_string.ptr()); } static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); } static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); } static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); } diff --git a/core/variant/array.cpp b/core/variant/array.cpp index c6bbd43dc4..53891a9823 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -38,6 +38,7 @@ #include "core/templates/search_array.h" #include "core/templates/vector.h" #include "core/variant/callable.h" +#include "core/variant/dictionary.h" #include "core/variant/variant.h" class ArrayPrivate { @@ -201,16 +202,21 @@ uint32_t Array::recursive_hash(int recursion_count) const { } bool Array::_assign(const Array &p_array) { + bool can_convert = p_array._p->typed.type == Variant::NIL; + can_convert |= _p->typed.type == Variant::STRING && p_array._p->typed.type == Variant::STRING_NAME; + can_convert |= _p->typed.type == Variant::STRING_NAME && p_array._p->typed.type == Variant::STRING; + if (_p->typed.type != Variant::OBJECT && _p->typed.type == p_array._p->typed.type) { //same type or untyped, just reference, should be fine _ref(p_array); } else if (_p->typed.type == Variant::NIL) { //from typed to untyped, must copy, but this is cheap anyway _p->array = p_array._p->array; - } else if (p_array._p->typed.type == Variant::NIL) { //from untyped to typed, must try to check if they are all valid + } else if (can_convert) { //from untyped to typed, must try to check if they are all valid if (_p->typed.type == Variant::OBJECT) { //for objects, it needs full validation, either can be converted or fail for (int i = 0; i < p_array._p->array.size(); i++) { - if (!_p->typed.validate(p_array._p->array[i], "assign")) { + const Variant &element = p_array._p->array[i]; + if (element.get_type() != Variant::OBJECT || !_p->typed.validate_object(element, "assign")) { return false; } } @@ -255,16 +261,20 @@ void Array::operator=(const Array &p_array) { void Array::push_back(const Variant &p_value) { ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state."); - ERR_FAIL_COND(!_p->typed.validate(p_value, "push_back")); - _p->array.push_back(p_value); + Variant value = p_value; + ERR_FAIL_COND(!_p->typed.validate(value, "push_back")); + _p->array.push_back(value); } void Array::append_array(const Array &p_array) { ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state."); - for (int i = 0; i < p_array.size(); ++i) { - ERR_FAIL_COND(!_p->typed.validate(p_array[i], "append_array")); + + Vector<Variant> validated_array = p_array._p->array; + for (int i = 0; i < validated_array.size(); ++i) { + ERR_FAIL_COND(!_p->typed.validate(validated_array.write[i], "append_array")); } - _p->array.append_array(p_array._p->array); + + _p->array.append_array(validated_array); } Error Array::resize(int p_new_size) { @@ -274,20 +284,23 @@ Error Array::resize(int p_new_size) { Error Array::insert(int p_pos, const Variant &p_value) { ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state."); - ERR_FAIL_COND_V(!_p->typed.validate(p_value, "insert"), ERR_INVALID_PARAMETER); - return _p->array.insert(p_pos, p_value); + Variant value = p_value; + ERR_FAIL_COND_V(!_p->typed.validate(value, "insert"), ERR_INVALID_PARAMETER); + return _p->array.insert(p_pos, value); } void Array::fill(const Variant &p_value) { ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state."); - ERR_FAIL_COND(!_p->typed.validate(p_value, "fill")); - _p->array.fill(p_value); + Variant value = p_value; + ERR_FAIL_COND(!_p->typed.validate(value, "fill")); + _p->array.fill(value); } void Array::erase(const Variant &p_value) { ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state."); - ERR_FAIL_COND(!_p->typed.validate(p_value, "erase")); - _p->array.erase(p_value); + Variant value = p_value; + ERR_FAIL_COND(!_p->typed.validate(value, "erase")); + _p->array.erase(value); } Variant Array::front() const { @@ -306,15 +319,34 @@ Variant Array::pick_random() const { } int Array::find(const Variant &p_value, int p_from) const { - ERR_FAIL_COND_V(!_p->typed.validate(p_value, "find"), -1); - return _p->array.find(p_value, p_from); + if (_p->array.size() == 0) { + return -1; + } + Variant value = p_value; + ERR_FAIL_COND_V(!_p->typed.validate(value, "find"), -1); + + int ret = -1; + + if (p_from < 0 || size() == 0) { + return ret; + } + + for (int i = p_from; i < size(); i++) { + if (StringLikeVariantComparator::compare(_p->array[i], value)) { + ret = i; + break; + } + } + + return ret; } int Array::rfind(const Variant &p_value, int p_from) const { if (_p->array.size() == 0) { return -1; } - ERR_FAIL_COND_V(!_p->typed.validate(p_value, "rfind"), -1); + Variant value = p_value; + ERR_FAIL_COND_V(!_p->typed.validate(value, "rfind"), -1); if (p_from < 0) { // Relative offset from the end @@ -326,7 +358,7 @@ int Array::rfind(const Variant &p_value, int p_from) const { } for (int i = p_from; i >= 0; i--) { - if (_p->array[i] == p_value) { + if (StringLikeVariantComparator::compare(_p->array[i], value)) { return i; } } @@ -334,20 +366,16 @@ int Array::rfind(const Variant &p_value, int p_from) const { return -1; } -int Array::find_last(const Variant &p_value) const { - ERR_FAIL_COND_V(!_p->typed.validate(p_value, "find_last"), -1); - return rfind(p_value); -} - int Array::count(const Variant &p_value) const { - ERR_FAIL_COND_V(!_p->typed.validate(p_value, "count"), 0); + Variant value = p_value; + ERR_FAIL_COND_V(!_p->typed.validate(value, "count"), 0); if (_p->array.size() == 0) { return 0; } int amount = 0; for (int i = 0; i < _p->array.size(); i++) { - if (_p->array[i] == p_value) { + if (StringLikeVariantComparator::compare(_p->array[i], value)) { amount++; } } @@ -356,9 +384,10 @@ int Array::count(const Variant &p_value) const { } bool Array::has(const Variant &p_value) const { - ERR_FAIL_COND_V(!_p->typed.validate(p_value, "use 'has'"), false); + Variant value = p_value; + ERR_FAIL_COND_V(!_p->typed.validate(value, "use 'has'"), false); - return _p->array.find(p_value, 0) != -1; + return find(value) != -1; } void Array::remove_at(int p_pos) { @@ -368,9 +397,10 @@ void Array::remove_at(int p_pos) { void Array::set(int p_idx, const Variant &p_value) { ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state."); - ERR_FAIL_COND(!_p->typed.validate(p_value, "set")); + Variant value = p_value; + ERR_FAIL_COND(!_p->typed.validate(value, "set")); - operator[](p_idx) = p_value; + operator[](p_idx) = value; } const Variant &Array::get(int p_idx) const { @@ -593,15 +623,17 @@ void Array::shuffle() { } int Array::bsearch(const Variant &p_value, bool p_before) { - ERR_FAIL_COND_V(!_p->typed.validate(p_value, "binary search"), -1); + Variant value = p_value; + ERR_FAIL_COND_V(!_p->typed.validate(value, "binary search"), -1); SearchArray<Variant, _ArrayVariantSort> avs; - return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before); + return avs.bisect(_p->array.ptrw(), _p->array.size(), value, p_before); } int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before) { - ERR_FAIL_COND_V(!_p->typed.validate(p_value, "custom binary search"), -1); + Variant value = p_value; + ERR_FAIL_COND_V(!_p->typed.validate(value, "custom binary search"), -1); - return _p->array.bsearch_custom<CallableComparator>(p_value, p_before, p_callable); + return _p->array.bsearch_custom<CallableComparator>(value, p_before, p_callable); } void Array::reverse() { @@ -611,8 +643,9 @@ void Array::reverse() { void Array::push_front(const Variant &p_value) { ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state."); - ERR_FAIL_COND(!_p->typed.validate(p_value, "push_front")); - _p->array.insert(0, p_value); + Variant value = p_value; + ERR_FAIL_COND(!_p->typed.validate(value, "push_front")); + _p->array.insert(0, value); } Variant Array::pop_back() { diff --git a/core/variant/array.h b/core/variant/array.h index ee265a9ffd..2dd3dde2d1 100644 --- a/core/variant/array.h +++ b/core/variant/array.h @@ -90,7 +90,6 @@ public: int find(const Variant &p_value, int p_from = 0) const; int rfind(const Variant &p_value, int p_from = -1) const; - int find_last(const Variant &p_value) const; int count(const Variant &p_value) const; bool has(const Variant &p_value) const; diff --git a/core/variant/container_type_validate.h b/core/variant/container_type_validate.h index 427a337aab..9976fce47f 100644 --- a/core/variant/container_type_validate.h +++ b/core/variant/container_type_validate.h @@ -74,22 +74,37 @@ struct ContainerTypeValidate { return true; } - _FORCE_INLINE_ bool validate(const Variant &p_variant, const char *p_operation = "use") { + // Coerces String and StringName into each other when needed. + _FORCE_INLINE_ bool validate(Variant &inout_variant, const char *p_operation = "use") { if (type == Variant::NIL) { return true; } - if (type != p_variant.get_type()) { - if (p_variant.get_type() == Variant::NIL && type == Variant::OBJECT) { + if (type != inout_variant.get_type()) { + if (inout_variant.get_type() == Variant::NIL && type == Variant::OBJECT) { + return true; + } + if (type == Variant::STRING && inout_variant.get_type() == Variant::STRING_NAME) { + inout_variant = String(inout_variant); + return true; + } else if (type == Variant::STRING_NAME && inout_variant.get_type() == Variant::STRING) { + inout_variant = StringName(inout_variant); return true; } - ERR_FAIL_V_MSG(false, "Attempted to " + String(p_operation) + " a variable of type '" + Variant::get_type_name(p_variant.get_type()) + "' into a " + where + " of type '" + Variant::get_type_name(type) + "'."); + ERR_FAIL_V_MSG(false, "Attempted to " + String(p_operation) + " a variable of type '" + Variant::get_type_name(inout_variant.get_type()) + "' into a " + where + " of type '" + Variant::get_type_name(type) + "'."); } if (type != Variant::OBJECT) { return true; } + + return validate_object(inout_variant, p_operation); + } + + _FORCE_INLINE_ bool validate_object(const Variant &p_variant, const char *p_operation = "use") { + ERR_FAIL_COND_V(p_variant.get_type() != Variant::OBJECT, false); + #ifdef DEBUG_ENABLED ObjectID object_id = p_variant; if (object_id == ObjectID()) { diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp index c1cb782a57..77d9fb0bc2 100644 --- a/core/variant/dictionary.cpp +++ b/core/variant/dictionary.cpp @@ -42,7 +42,7 @@ struct DictionaryPrivate { SafeRefCount refcount; Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values. - HashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map; + HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator> variant_map; }; void Dictionary::get_key_list(List<Variant> *p_keys) const { @@ -100,24 +100,12 @@ Variant &Dictionary::operator[](const Variant &p_key) { } const Variant &Dictionary::operator[](const Variant &p_key) const { - if (p_key.get_type() == Variant::STRING_NAME) { - const StringName *sn = VariantInternal::get_string_name(&p_key); - return _p->variant_map[sn->operator String()]; - } else { - return _p->variant_map[p_key]; - } + // Will not insert key, so no conversion is necessary. + return _p->variant_map[p_key]; } const Variant *Dictionary::getptr(const Variant &p_key) const { - HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E; - - if (p_key.get_type() == Variant::STRING_NAME) { - const StringName *sn = VariantInternal::get_string_name(&p_key); - E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String()); - } else { - E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key); - } - + HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(p_key)); if (!E) { return nullptr; } @@ -125,14 +113,7 @@ const Variant *Dictionary::getptr(const Variant &p_key) const { } Variant *Dictionary::getptr(const Variant &p_key) { - HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E; - - if (p_key.get_type() == Variant::STRING_NAME) { - const StringName *sn = VariantInternal::get_string_name(&p_key); - E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String()); - } else { - E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key); - } + HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::Iterator E(_p->variant_map.find(p_key)); if (!E) { return nullptr; } @@ -145,14 +126,7 @@ Variant *Dictionary::getptr(const Variant &p_key) { } Variant Dictionary::get_valid(const Variant &p_key) const { - HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E; - - if (p_key.get_type() == Variant::STRING_NAME) { - const StringName *sn = VariantInternal::get_string_name(&p_key); - E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String()); - } else { - E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key); - } + HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(p_key)); if (!E) { return Variant(); @@ -178,12 +152,7 @@ bool Dictionary::is_empty() const { } bool Dictionary::has(const Variant &p_key) const { - if (p_key.get_type() == Variant::STRING_NAME) { - const StringName *sn = VariantInternal::get_string_name(&p_key); - return _p->variant_map.has(sn->operator String()); - } else { - return _p->variant_map.has(p_key); - } + return _p->variant_map.has(p_key); } bool Dictionary::has_all(const Array &p_keys) const { @@ -206,12 +175,7 @@ Variant Dictionary::find_key(const Variant &p_value) const { bool Dictionary::erase(const Variant &p_key) { ERR_FAIL_COND_V_MSG(_p->read_only, false, "Dictionary is in read-only state."); - if (p_key.get_type() == Variant::STRING_NAME) { - const StringName *sn = VariantInternal::get_string_name(&p_key); - return _p->variant_map.erase(sn->operator String()); - } else { - return _p->variant_map.erase(p_key); - } + return _p->variant_map.erase(p_key); } bool Dictionary::operator==(const Dictionary &p_dictionary) const { @@ -238,7 +202,7 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c } recursion_count++; for (const KeyValue<Variant, Variant> &this_E : _p->variant_map) { - HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator other_E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&p_dictionary._p->variant_map)->find(this_E.key); + HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator other_E(p_dictionary._p->variant_map.find(this_E.key)); if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count)) { return false; } @@ -360,7 +324,7 @@ const Variant *Dictionary::next(const Variant *p_key) const { } return nullptr; } - HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E = _p->variant_map.find(*p_key); + HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::Iterator E = _p->variant_map.find(*p_key); if (!E) { return nullptr; diff --git a/core/variant/native_ptr.h b/core/variant/native_ptr.h index ed68e0f6c9..18670310b0 100644 --- a/core/variant/native_ptr.h +++ b/core/variant/native_ptr.h @@ -36,90 +36,90 @@ #include "core/variant/type_info.h" template <class T> -struct GDNativeConstPtr { +struct GDExtensionConstPtr { const T *data = nullptr; - GDNativeConstPtr(const T *p_assign) { data = p_assign; } + GDExtensionConstPtr(const T *p_assign) { data = p_assign; } static const char *get_name() { return "const void"; } operator const T *() const { return data; } operator Variant() const { return uint64_t(data); } }; template <class T> -struct GDNativePtr { +struct GDExtensionPtr { T *data = nullptr; - GDNativePtr(T *p_assign) { data = p_assign; } + GDExtensionPtr(T *p_assign) { data = p_assign; } static const char *get_name() { return "void"; } operator T *() const { return data; } operator Variant() const { return uint64_t(data); } }; -#define GDVIRTUAL_NATIVE_PTR(m_type) \ - template <> \ - struct GDNativeConstPtr<const m_type> { \ - const m_type *data = nullptr; \ - GDNativeConstPtr() {} \ - GDNativeConstPtr(const m_type *p_assign) { data = p_assign; } \ - static const char *get_name() { return "const " #m_type; } \ - operator const m_type *() const { return data; } \ - operator Variant() const { return uint64_t(data); } \ - }; \ - template <> \ - struct VariantCaster<GDNativeConstPtr<const m_type>> { \ - static _FORCE_INLINE_ GDNativeConstPtr<const m_type> cast(const Variant &p_variant) { \ - return GDNativeConstPtr<const m_type>((const m_type *)p_variant.operator uint64_t()); \ - } \ - }; \ - template <> \ - struct GDNativePtr<m_type> { \ - m_type *data = nullptr; \ - GDNativePtr() {} \ - GDNativePtr(m_type *p_assign) { data = p_assign; } \ - static const char *get_name() { return #m_type; } \ - operator m_type *() const { return data; } \ - operator Variant() const { return uint64_t(data); } \ - }; \ - template <> \ - struct VariantCaster<GDNativePtr<m_type>> { \ - static _FORCE_INLINE_ GDNativePtr<m_type> cast(const Variant &p_variant) { \ - return GDNativePtr<m_type>((m_type *)p_variant.operator uint64_t()); \ - } \ +#define GDVIRTUAL_NATIVE_PTR(m_type) \ + template <> \ + struct GDExtensionConstPtr<const m_type> { \ + const m_type *data = nullptr; \ + GDExtensionConstPtr() {} \ + GDExtensionConstPtr(const m_type *p_assign) { data = p_assign; } \ + static const char *get_name() { return "const " #m_type; } \ + operator const m_type *() const { return data; } \ + operator Variant() const { return uint64_t(data); } \ + }; \ + template <> \ + struct VariantCaster<GDExtensionConstPtr<const m_type>> { \ + static _FORCE_INLINE_ GDExtensionConstPtr<const m_type> cast(const Variant &p_variant) { \ + return GDExtensionConstPtr<const m_type>((const m_type *)p_variant.operator uint64_t()); \ + } \ + }; \ + template <> \ + struct GDExtensionPtr<m_type> { \ + m_type *data = nullptr; \ + GDExtensionPtr() {} \ + GDExtensionPtr(m_type *p_assign) { data = p_assign; } \ + static const char *get_name() { return #m_type; } \ + operator m_type *() const { return data; } \ + operator Variant() const { return uint64_t(data); } \ + }; \ + template <> \ + struct VariantCaster<GDExtensionPtr<m_type>> { \ + static _FORCE_INLINE_ GDExtensionPtr<m_type> cast(const Variant &p_variant) { \ + return GDExtensionPtr<m_type>((m_type *)p_variant.operator uint64_t()); \ + } \ }; template <class T> -struct GetTypeInfo<GDNativeConstPtr<T>> { +struct GetTypeInfo<GDExtensionConstPtr<T>> { static const Variant::Type VARIANT_TYPE = Variant::NIL; static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; static inline PropertyInfo get_class_info() { - return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDNativeConstPtr<T>::get_name()); + return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDExtensionConstPtr<T>::get_name()); } }; template <class T> -struct GetTypeInfo<GDNativePtr<T>> { +struct GetTypeInfo<GDExtensionPtr<T>> { static const Variant::Type VARIANT_TYPE = Variant::NIL; static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; static inline PropertyInfo get_class_info() { - return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDNativePtr<T>::get_name()); + return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDExtensionPtr<T>::get_name()); } }; template <class T> -struct PtrToArg<GDNativeConstPtr<T>> { - _FORCE_INLINE_ static GDNativeConstPtr<T> convert(const void *p_ptr) { - return GDNativeConstPtr<T>(reinterpret_cast<const T *>(p_ptr)); +struct PtrToArg<GDExtensionConstPtr<T>> { + _FORCE_INLINE_ static GDExtensionConstPtr<T> convert(const void *p_ptr) { + return GDExtensionConstPtr<T>(reinterpret_cast<const T *>(p_ptr)); } typedef const T *EncodeT; - _FORCE_INLINE_ static void encode(GDNativeConstPtr<T> p_val, void *p_ptr) { + _FORCE_INLINE_ static void encode(GDExtensionConstPtr<T> p_val, void *p_ptr) { *((const T **)p_ptr) = p_val.data; } }; template <class T> -struct PtrToArg<GDNativePtr<T>> { - _FORCE_INLINE_ static GDNativePtr<T> convert(const void *p_ptr) { - return GDNativePtr<T>(reinterpret_cast<const T *>(p_ptr)); +struct PtrToArg<GDExtensionPtr<T>> { + _FORCE_INLINE_ static GDExtensionPtr<T> convert(const void *p_ptr) { + return GDExtensionPtr<T>(reinterpret_cast<const T *>(p_ptr)); } typedef T *EncodeT; - _FORCE_INLINE_ static void encode(GDNativePtr<T> p_val, void *p_ptr) { + _FORCE_INLINE_ static void encode(GDExtensionPtr<T> p_val, void *p_ptr) { *((T **)p_ptr) = p_val.data; } }; diff --git a/core/variant/type_info.h b/core/variant/type_info.h index e355053296..8e2d150430 100644 --- a/core/variant/type_info.h +++ b/core/variant/type_info.h @@ -290,6 +290,7 @@ public: _FORCE_INLINE_ void set_flag(T p_flag) { value |= p_flag; } _FORCE_INLINE_ bool has_flag(T p_flag) const { return value & p_flag; } _FORCE_INLINE_ void clear_flag(T p_flag) { return value &= ~p_flag; } + _FORCE_INLINE_ BitField() = default; _FORCE_INLINE_ BitField(int64_t p_value) { value = p_value; } _FORCE_INLINE_ operator int64_t() const { return value; } _FORCE_INLINE_ operator Variant() const { return value; } diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index b4528e67d1..39b7cbee0d 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -940,7 +940,7 @@ bool Variant::is_zero() const { return reinterpret_cast<const Signal *>(_data._mem)->is_null(); } case STRING_NAME: { - return *reinterpret_cast<const StringName *>(_data._mem) != StringName(); + return *reinterpret_cast<const StringName *>(_data._mem) == StringName(); } case NODE_PATH: { return reinterpret_cast<const NodePath *>(_data._mem)->is_empty(); @@ -3491,6 +3491,19 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const } } +bool StringLikeVariantComparator::compare(const Variant &p_lhs, const Variant &p_rhs) { + if (p_lhs.hash_compare(p_rhs)) { + return true; + } + if (p_lhs.get_type() == Variant::STRING && p_rhs.get_type() == Variant::STRING_NAME) { + return *VariantInternal::get_string(&p_lhs) == *VariantInternal::get_string_name(&p_rhs); + } + if (p_lhs.get_type() == Variant::STRING_NAME && p_rhs.get_type() == Variant::STRING) { + return *VariantInternal::get_string_name(&p_lhs) == *VariantInternal::get_string(&p_rhs); + } + return false; +} + bool Variant::is_ref_counted() const { return type == OBJECT && _get_obj().id.is_ref_counted(); } @@ -3609,16 +3622,16 @@ String Variant::get_call_error_text(Object *p_base, const StringName &p_method, if (ce.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) { int errorarg = ce.argument; if (p_argptrs) { - err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected)) + "."; + err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected)); } else { - err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected)) + "."; + err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected)); } } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) { - err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + "."; + err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount); } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) { - err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + "."; + err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount); } else if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) { - err_text = "Method not found."; + err_text = "Method not found"; } else if (ce.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) { err_text = "Instance is null"; } else if (ce.error == Callable::CallError::CALL_ERROR_METHOD_NOT_CONST) { diff --git a/core/variant/variant.h b/core/variant/variant.h index c5be609184..f7221e206f 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -797,6 +797,10 @@ struct VariantComparator { static _FORCE_INLINE_ bool compare(const Variant &p_lhs, const Variant &p_rhs) { return p_lhs.hash_compare(p_rhs); } }; +struct StringLikeVariantComparator { + static bool compare(const Variant &p_lhs, const Variant &p_rhs); +}; + Variant::ObjData &Variant::_get_obj() { return *reinterpret_cast<ObjData *>(&_data._mem[0]); } diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 91af2bab85..ac569941bf 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -73,6 +73,30 @@ static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...) const, Variant call_with_variant_argsc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals); } +template <class From, class R, class T, class... P> +static _FORCE_INLINE_ void vc_convert_method_call(R (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { + T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base))); + call_with_variant_args_ret_dv(&converted, method, p_args, p_argcount, r_ret, r_error, p_defvals); +} + +template <class From, class R, class T, class... P> +static _FORCE_INLINE_ void vc_convert_method_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { + T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base))); + call_with_variant_args_retc_dv(&converted, method, p_args, p_argcount, r_ret, r_error, p_defvals); +} + +template <class From, class T, class... P> +static _FORCE_INLINE_ void vc_convert_method_call(void (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { + T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base))); + call_with_variant_args_dv(&converted, method, p_args, p_argcount, r_error, p_defvals); +} + +template <class From, class T, class... P> +static _FORCE_INLINE_ void vc_convert_method_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { + T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base))); + call_with_variant_argsc_dv(&converted, method, p_args, p_argcount, r_error, p_defvals); +} + template <class R, class T, class... P> static _FORCE_INLINE_ void vc_method_call_static(R (*method)(T *, P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { call_with_variant_args_retc_static_helper_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, p_defvals, r_error); @@ -102,6 +126,29 @@ static _FORCE_INLINE_ void vc_validated_call(void (T::*method)(P...) const, Vari call_with_validated_variant_argsc(base, method, p_args); } +template <class From, class R, class T, class... P> +static _FORCE_INLINE_ void vc_convert_validated_call(R (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) { + T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base))); + call_with_validated_variant_args_ret_helper<T, R, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class From, class R, class T, class... P> +static _FORCE_INLINE_ void vc_convert_validated_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) { + T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base))); + call_with_validated_variant_args_retc_helper<T, R, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); +} +template <class From, class T, class... P> +static _FORCE_INLINE_ void vc_convert_validated_call(void (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) { + T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base))); + call_with_validated_variant_args_helper<T, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class From, class T, class... P> +static _FORCE_INLINE_ void vc_convert_validated_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) { + T converted(static_cast<T>(*VariantGetInternalPtr<From>::get_ptr(base))); + call_with_validated_variant_argsc_helper<T, P...>(&converted, method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); +} + template <class R, class T, class... P> static _FORCE_INLINE_ void vc_validated_call_static(R (*method)(T *, P...), Variant *base, const Variant **p_args, Variant *r_ret) { call_with_validated_variant_args_static_retc(base, method, p_args, r_ret); @@ -142,6 +189,30 @@ static _FORCE_INLINE_ void vc_ptrcall(void (T::*method)(P...) const, void *p_bas call_with_ptr_argsc(reinterpret_cast<T *>(p_base), method, p_args); } +template <class From, class R, class T, class... P> +static _FORCE_INLINE_ void vc_convert_ptrcall(R (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) { + T converted(*reinterpret_cast<From *>(p_base)); + call_with_ptr_args_ret(&converted, method, p_args, r_ret); +} + +template <class From, class R, class T, class... P> +static _FORCE_INLINE_ void vc_convert_ptrcall(R (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) { + T converted(*reinterpret_cast<From *>(p_base)); + call_with_ptr_args_retc(&converted, method, p_args, r_ret); +} + +template <class From, class T, class... P> +static _FORCE_INLINE_ void vc_convert_ptrcall(void (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) { + T converted(*reinterpret_cast<From *>(p_base)); + call_with_ptr_args(&converted, method, p_args); +} + +template <class From, class T, class... P> +static _FORCE_INLINE_ void vc_convert_ptrcall(void (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) { + T converted(*reinterpret_cast<From *>(p_base)); + call_with_ptr_argsc(&converted, method, p_args); +} + template <class R, class T, class... P> static _FORCE_INLINE_ int vc_get_argument_count(R (T::*method)(P...)) { return sizeof...(P); @@ -337,6 +408,46 @@ static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...) con } \ }; +#define CONVERT_METHOD_CLASS(m_class, m_method_name, m_method_ptr) \ + struct Method_##m_class##_##m_method_name { \ + static void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \ + vc_convert_method_call<m_class>(m_method_ptr, base, p_args, p_argcount, r_ret, p_defvals, r_error); \ + } \ + static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \ + vc_convert_validated_call<m_class>(m_method_ptr, base, p_args, r_ret); \ + } \ + static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \ + vc_convert_ptrcall<m_class>(m_method_ptr, p_base, p_args, r_ret); \ + } \ + static int get_argument_count() { \ + return vc_get_argument_count(m_method_ptr); \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return vc_get_argument_type(m_method_ptr, p_arg); \ + } \ + static Variant::Type get_return_type() { \ + return vc_get_return_type(m_method_ptr); \ + } \ + static bool has_return_type() { \ + return vc_has_return_type(m_method_ptr); \ + } \ + static bool is_const() { \ + return vc_is_const(m_method_ptr); \ + } \ + static bool is_static() { \ + return false; \ + } \ + static bool is_vararg() { \ + return false; \ + } \ + static Variant::Type get_base_type() { \ + return GetTypeInfo<m_class>::VARIANT_TYPE; \ + } \ + static StringName get_name() { \ + return #m_method_name; \ + } \ + }; + template <class R, class... P> static _FORCE_INLINE_ void vc_static_ptrcall(R (*method)(P...), const void **p_args, void *r_ret) { call_with_ptr_args_static_method_ret<R, P...>(method, p_args, r_ret); @@ -1422,6 +1533,16 @@ int Variant::get_enum_value(Variant::Type p_type, StringName p_enum_name, String #endif #ifdef DEBUG_METHODS_ENABLED +#define bind_convert_method(m_type_from, m_type_to, m_method, m_arg_names, m_default_args) \ + CONVERT_METHOD_CLASS(m_type_from, m_method, &m_type_to::m_method); \ + register_builtin_method<Method_##m_type_from##_##m_method>(m_arg_names, m_default_args); +#else +#define bind_convert_method(m_type_from, m_type_to, m_method, m_arg_names, m_default_args) \ + CONVERT_METHOD_CLASS(m_type_from, m_method, &m_type_to ::m_method); \ + register_builtin_method<Method_##m_type_from##_##m_method>(sarray(), m_default_args); +#endif + +#ifdef DEBUG_METHODS_ENABLED #define bind_static_method(m_type, m_method, m_arg_names, m_default_args) \ STATIC_METHOD_CLASS(m_type, m_method, m_type::m_method); \ register_builtin_method<Method_##m_type##_##m_method>(m_arg_names, m_default_args); @@ -1442,6 +1563,16 @@ int Variant::get_enum_value(Variant::Type p_type, StringName p_enum_name, String #endif #ifdef DEBUG_METHODS_ENABLED +#define bind_convert_methodv(m_type_from, m_type_to, m_name, m_method, m_arg_names, m_default_args) \ + CONVERT_METHOD_CLASS(m_type_from, m_name, m_method); \ + register_builtin_method<Method_##m_type_from##_##m_name>(m_arg_names, m_default_args); +#else +#define bind_convert_methodv(m_type_from, m_type_to, m_name, m_method, m_arg_names, m_default_args) \ + CONVERT_METHOD_CLASS(m_type_from, m_name, m_method); \ + register_builtin_method<Method_##m_type_from##_##m_name>(sarray(), m_default_args); +#endif + +#ifdef DEBUG_METHODS_ENABLED #define bind_function(m_type, m_name, m_method, m_arg_names, m_default_args) \ FUNCTION_CLASS(m_type, m_name, m_method, true); \ register_builtin_method<Method_##m_type##_##m_name>(m_arg_names, m_default_args); @@ -1461,6 +1592,14 @@ int Variant::get_enum_value(Variant::Type p_type, StringName p_enum_name, String register_builtin_method<Method_##m_type##_##m_name>(sarray(), m_default_args); #endif +#define bind_string_method(m_method, m_arg_names, m_default_args) \ + bind_method(String, m_method, m_arg_names, m_default_args); \ + bind_convert_method(StringName, String, m_method, m_arg_names, m_default_args); + +#define bind_string_methodv(m_name, m_method, m_arg_names, m_default_args) \ + bind_methodv(String, m_name, m_method, m_arg_names, m_default_args); \ + bind_convert_methodv(StringName, String, m_name, m_method, m_arg_names, m_default_args); + #define bind_custom(m_type, m_name, m_method, m_has_return, m_ret_type) \ VARARG_CLASS(m_type, m_name, m_method, m_has_return, m_ret_type) \ register_builtin_method<Method_##m_type##_##m_name>(sarray(), Vector<Variant>()); @@ -1477,108 +1616,108 @@ static void _register_variant_builtin_methods() { /* String */ - bind_method(String, casecmp_to, sarray("to"), varray()); - bind_method(String, nocasecmp_to, sarray("to"), varray()); - 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_method(String, get_slicec, sarray("delimiter", "slice"), varray()); - bind_method(String, get_slice_count, sarray("delimiter"), 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)); - bind_method(String, findn, sarray("what", "from"), varray(0)); - bind_method(String, rfind, sarray("what", "from"), varray(-1)); - bind_method(String, rfindn, sarray("what", "from"), varray(-1)); - bind_method(String, match, sarray("expr"), varray()); - bind_method(String, matchn, sarray("expr"), varray()); - bind_methodv(String, begins_with, static_cast<bool (String::*)(const String &) const>(&String::begins_with), sarray("text"), varray()); - bind_method(String, ends_with, sarray("text"), varray()); - bind_method(String, is_subsequence_of, sarray("text"), varray()); - bind_method(String, is_subsequence_ofn, sarray("text"), varray()); - bind_method(String, bigrams, sarray(), varray()); - bind_method(String, similarity, sarray("text"), varray()); - - bind_method(String, format, sarray("values", "placeholder"), varray("{_}")); - bind_methodv(String, replace, static_cast<String (String::*)(const String &, const String &) const>(&String::replace), sarray("what", "forwhat"), varray()); - bind_method(String, replacen, sarray("what", "forwhat"), varray()); - bind_method(String, repeat, sarray("count"), varray()); - bind_method(String, insert, sarray("position", "what"), varray()); - bind_method(String, capitalize, sarray(), varray()); - bind_method(String, to_camel_case, sarray(), varray()); - bind_method(String, to_pascal_case, sarray(), varray()); - bind_method(String, to_snake_case, sarray(), varray()); - bind_method(String, split, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); - bind_method(String, rsplit, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); - bind_method(String, split_floats, sarray("delimiter", "allow_empty"), varray(true)); - bind_method(String, join, sarray("parts"), varray()); - - bind_method(String, to_upper, sarray(), varray()); - bind_method(String, to_lower, sarray(), varray()); - - bind_method(String, left, sarray("length"), varray()); - bind_method(String, right, sarray("length"), varray()); - - bind_method(String, strip_edges, sarray("left", "right"), varray(true, true)); - bind_method(String, strip_escapes, sarray(), varray()); - bind_method(String, lstrip, sarray("chars"), varray()); - bind_method(String, rstrip, sarray("chars"), varray()); - bind_method(String, get_extension, sarray(), varray()); - bind_method(String, get_basename, sarray(), varray()); - bind_method(String, path_join, sarray("file"), varray()); - bind_method(String, unicode_at, sarray("at"), varray()); - bind_method(String, indent, sarray("prefix"), varray()); - bind_method(String, dedent, sarray(), varray()); + bind_string_method(casecmp_to, sarray("to"), varray()); + bind_string_method(nocasecmp_to, sarray("to"), varray()); + bind_string_method(naturalnocasecmp_to, sarray("to"), varray()); + bind_string_method(length, sarray(), varray()); + bind_string_method(substr, sarray("from", "len"), varray(-1)); + bind_string_method(get_slice, sarray("delimiter", "slice"), varray()); + bind_string_method(get_slicec, sarray("delimiter", "slice"), varray()); + bind_string_method(get_slice_count, sarray("delimiter"), varray()); + bind_string_methodv(find, static_cast<int (String::*)(const String &, int) const>(&String::find), sarray("what", "from"), varray(0)); + bind_string_method(count, sarray("what", "from", "to"), varray(0, 0)); + bind_string_method(countn, sarray("what", "from", "to"), varray(0, 0)); + bind_string_method(findn, sarray("what", "from"), varray(0)); + bind_string_method(rfind, sarray("what", "from"), varray(-1)); + bind_string_method(rfindn, sarray("what", "from"), varray(-1)); + bind_string_method(match, sarray("expr"), varray()); + bind_string_method(matchn, sarray("expr"), varray()); + bind_string_methodv(begins_with, static_cast<bool (String::*)(const String &) const>(&String::begins_with), sarray("text"), varray()); + bind_string_method(ends_with, sarray("text"), varray()); + bind_string_method(is_subsequence_of, sarray("text"), varray()); + bind_string_method(is_subsequence_ofn, sarray("text"), varray()); + bind_string_method(bigrams, sarray(), varray()); + bind_string_method(similarity, sarray("text"), varray()); + + bind_string_method(format, sarray("values", "placeholder"), varray("{_}")); + bind_string_methodv(replace, static_cast<String (String::*)(const String &, const String &) const>(&String::replace), sarray("what", "forwhat"), varray()); + bind_string_method(replacen, sarray("what", "forwhat"), varray()); + bind_string_method(repeat, sarray("count"), varray()); + bind_string_method(insert, sarray("position", "what"), varray()); + bind_string_method(capitalize, sarray(), varray()); + bind_string_method(to_camel_case, sarray(), varray()); + bind_string_method(to_pascal_case, sarray(), varray()); + bind_string_method(to_snake_case, sarray(), varray()); + bind_string_method(split, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); + bind_string_method(rsplit, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); + bind_string_method(split_floats, sarray("delimiter", "allow_empty"), varray(true)); + bind_string_method(join, sarray("parts"), varray()); + + bind_string_method(to_upper, sarray(), varray()); + bind_string_method(to_lower, sarray(), varray()); + + bind_string_method(left, sarray("length"), varray()); + bind_string_method(right, sarray("length"), varray()); + + bind_string_method(strip_edges, sarray("left", "right"), varray(true, true)); + bind_string_method(strip_escapes, sarray(), varray()); + bind_string_method(lstrip, sarray("chars"), varray()); + bind_string_method(rstrip, sarray("chars"), varray()); + bind_string_method(get_extension, sarray(), varray()); + bind_string_method(get_basename, sarray(), varray()); + bind_string_method(path_join, sarray("file"), varray()); + bind_string_method(unicode_at, sarray("at"), varray()); + bind_string_method(indent, sarray("prefix"), varray()); + bind_string_method(dedent, sarray(), varray()); bind_method(String, hash, sarray(), varray()); - bind_method(String, md5_text, sarray(), varray()); - bind_method(String, sha1_text, sarray(), varray()); - bind_method(String, sha256_text, sarray(), varray()); - bind_method(String, md5_buffer, sarray(), varray()); - bind_method(String, sha1_buffer, sarray(), varray()); - bind_method(String, sha256_buffer, sarray(), varray()); - bind_method(String, is_empty, sarray(), varray()); - bind_methodv(String, contains, static_cast<bool (String::*)(const String &) const>(&String::contains), sarray("what"), varray()); - - bind_method(String, is_absolute_path, sarray(), varray()); - bind_method(String, is_relative_path, sarray(), varray()); - bind_method(String, simplify_path, sarray(), varray()); - bind_method(String, get_base_dir, sarray(), varray()); - bind_method(String, get_file, sarray(), varray()); - bind_method(String, xml_escape, sarray("escape_quotes"), varray(false)); - bind_method(String, xml_unescape, sarray(), varray()); - bind_method(String, uri_encode, sarray(), varray()); - bind_method(String, uri_decode, sarray(), varray()); - bind_method(String, c_escape, sarray(), varray()); - bind_method(String, c_unescape, sarray(), varray()); - bind_method(String, json_escape, sarray(), varray()); - - bind_method(String, validate_node_name, sarray(), varray()); - - bind_method(String, is_valid_identifier, sarray(), varray()); - bind_method(String, is_valid_int, sarray(), varray()); - bind_method(String, is_valid_float, sarray(), varray()); - bind_method(String, is_valid_hex_number, sarray("with_prefix"), varray(false)); - bind_method(String, is_valid_html_color, sarray(), varray()); - bind_method(String, is_valid_ip_address, sarray(), varray()); - bind_method(String, is_valid_filename, sarray(), varray()); - - bind_method(String, to_int, sarray(), varray()); - bind_method(String, to_float, sarray(), varray()); - bind_method(String, hex_to_int, sarray(), varray()); - bind_method(String, bin_to_int, sarray(), varray()); - - bind_method(String, lpad, sarray("min_length", "character"), varray(" ")); - bind_method(String, rpad, sarray("min_length", "character"), varray(" ")); - bind_method(String, pad_decimals, sarray("digits"), varray()); - bind_method(String, pad_zeros, sarray("digits"), varray()); - bind_method(String, trim_prefix, sarray("prefix"), varray()); - bind_method(String, trim_suffix, sarray("suffix"), varray()); - - bind_method(String, to_ascii_buffer, sarray(), varray()); - bind_method(String, to_utf8_buffer, sarray(), varray()); - bind_method(String, to_utf16_buffer, sarray(), varray()); - bind_method(String, to_utf32_buffer, sarray(), varray()); + bind_string_method(md5_text, sarray(), varray()); + bind_string_method(sha1_text, sarray(), varray()); + bind_string_method(sha256_text, sarray(), varray()); + bind_string_method(md5_buffer, sarray(), varray()); + bind_string_method(sha1_buffer, sarray(), varray()); + bind_string_method(sha256_buffer, sarray(), varray()); + bind_string_method(is_empty, sarray(), varray()); + bind_string_methodv(contains, static_cast<bool (String::*)(const String &) const>(&String::contains), sarray("what"), varray()); + + bind_string_method(is_absolute_path, sarray(), varray()); + bind_string_method(is_relative_path, sarray(), varray()); + bind_string_method(simplify_path, sarray(), varray()); + bind_string_method(get_base_dir, sarray(), varray()); + bind_string_method(get_file, sarray(), varray()); + bind_string_method(xml_escape, sarray("escape_quotes"), varray(false)); + bind_string_method(xml_unescape, sarray(), varray()); + bind_string_method(uri_encode, sarray(), varray()); + bind_string_method(uri_decode, sarray(), varray()); + bind_string_method(c_escape, sarray(), varray()); + bind_string_method(c_unescape, sarray(), varray()); + bind_string_method(json_escape, sarray(), varray()); + + bind_string_method(validate_node_name, sarray(), varray()); + + bind_string_method(is_valid_identifier, sarray(), varray()); + bind_string_method(is_valid_int, sarray(), varray()); + bind_string_method(is_valid_float, sarray(), varray()); + bind_string_method(is_valid_hex_number, sarray("with_prefix"), varray(false)); + bind_string_method(is_valid_html_color, sarray(), varray()); + bind_string_method(is_valid_ip_address, sarray(), varray()); + bind_string_method(is_valid_filename, sarray(), varray()); + + bind_string_method(to_int, sarray(), varray()); + bind_string_method(to_float, sarray(), varray()); + bind_string_method(hex_to_int, sarray(), varray()); + bind_string_method(bin_to_int, sarray(), varray()); + + bind_string_method(lpad, sarray("min_length", "character"), varray(" ")); + bind_string_method(rpad, sarray("min_length", "character"), varray(" ")); + bind_string_method(pad_decimals, sarray("digits"), varray()); + bind_string_method(pad_zeros, sarray("digits"), varray()); + bind_string_method(trim_prefix, sarray("prefix"), varray()); + bind_string_method(trim_suffix, sarray("suffix"), varray()); + + bind_string_method(to_ascii_buffer, sarray(), varray()); + bind_string_method(to_utf8_buffer, sarray(), varray()); + bind_string_method(to_utf16_buffer, sarray(), varray()); + bind_string_method(to_utf32_buffer, sarray(), varray()); bind_static_method(String, num_scientific, sarray("number"), varray()); bind_static_method(String, num, sarray("number", "decimals"), varray(-1)); @@ -1615,6 +1754,7 @@ static void _register_variant_builtin_methods() { bind_method(Vector2, cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray()); bind_method(Vector2, cubic_interpolate_in_time, sarray("b", "pre_a", "post_b", "weight", "b_t", "pre_a_t", "post_b_t"), varray()); bind_method(Vector2, bezier_interpolate, sarray("control_1", "control_2", "end", "t"), varray()); + bind_method(Vector2, bezier_derivative, sarray("control_1", "control_2", "end", "t"), 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()); @@ -1646,6 +1786,7 @@ static void _register_variant_builtin_methods() { bind_method(Vector2i, sign, sarray(), varray()); bind_method(Vector2i, abs, sarray(), varray()); bind_method(Vector2i, clamp, sarray("min", "max"), varray()); + bind_method(Vector2i, snapped, sarray("step"), varray()); /* Rect2 */ @@ -1707,6 +1848,7 @@ static void _register_variant_builtin_methods() { bind_method(Vector3, cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray()); bind_method(Vector3, cubic_interpolate_in_time, sarray("b", "pre_a", "post_b", "weight", "b_t", "pre_a_t", "post_b_t"), varray()); bind_method(Vector3, bezier_interpolate, sarray("control_1", "control_2", "end", "t"), varray()); + bind_method(Vector3, bezier_derivative, sarray("control_1", "control_2", "end", "t"), varray()); bind_method(Vector3, move_toward, sarray("to", "delta"), varray()); bind_method(Vector3, dot, sarray("with"), varray()); bind_method(Vector3, cross, sarray("with"), varray()); @@ -1734,6 +1876,7 @@ static void _register_variant_builtin_methods() { bind_method(Vector3i, sign, sarray(), varray()); bind_method(Vector3i, abs, sarray(), varray()); bind_method(Vector3i, clamp, sarray("min", "max"), varray()); + bind_method(Vector3i, snapped, sarray("step"), varray()); /* Vector4 */ @@ -1773,6 +1916,7 @@ static void _register_variant_builtin_methods() { bind_method(Vector4i, sign, sarray(), varray()); bind_method(Vector4i, abs, sarray(), varray()); bind_method(Vector4i, clamp, sarray("min", "max"), varray()); + bind_method(Vector4i, snapped, sarray("step"), varray()); /* Plane */ @@ -2053,7 +2197,6 @@ static void _register_variant_builtin_methods() { bind_method(Array, pick_random, sarray(), varray()); bind_method(Array, find, sarray("what", "from"), varray(0)); bind_method(Array, rfind, sarray("what", "from"), varray(-1)); - bind_method(Array, find_last, sarray("value"), varray()); bind_method(Array, count, sarray("value"), varray()); bind_method(Array, has, sarray("value"), varray()); bind_method(Array, pop_back, sarray(), varray()); @@ -2438,7 +2581,7 @@ static void _register_variant_builtin_methods() { _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)); - Transform3D identity_transform = Transform3D(); + Transform3D identity_transform; Transform3D flip_x_transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0); Transform3D flip_y_transform = Transform3D(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0); Transform3D flip_z_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0); @@ -2447,7 +2590,7 @@ static void _register_variant_builtin_methods() { _VariantCall::add_variant_constant(Variant::TRANSFORM3D, "FLIP_Y", flip_y_transform); _VariantCall::add_variant_constant(Variant::TRANSFORM3D, "FLIP_Z", flip_z_transform); - Basis identity_basis = Basis(); + Basis identity_basis; Basis flip_x_basis = Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1); Basis flip_y_basis = Basis(1, 0, 0, 0, -1, 0, 0, 0, 1); Basis flip_z_basis = Basis(1, 0, 0, 0, 1, 0, 0, 0, -1); diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp index ae9727fe79..624a6f5e06 100644 --- a/core/variant/variant_construct.cpp +++ b/core/variant/variant_construct.cpp @@ -68,11 +68,13 @@ void Variant::_register_variant_constructors() { add_constructor<VariantConstructor<int64_t, int64_t>>(sarray("from")); add_constructor<VariantConstructor<int64_t, double>>(sarray("from")); add_constructor<VariantConstructor<int64_t, bool>>(sarray("from")); + add_constructor<VariantConstructorFromString<int64_t>>(sarray("from")); add_constructor<VariantConstructNoArgs<double>>(sarray()); add_constructor<VariantConstructor<double, double>>(sarray("from")); add_constructor<VariantConstructor<double, int64_t>>(sarray("from")); add_constructor<VariantConstructor<double, bool>>(sarray("from")); + add_constructor<VariantConstructorFromString<double>>(sarray("from")); add_constructor<VariantConstructNoArgs<String>>(sarray()); add_constructor<VariantConstructor<String, String>>(sarray("from")); diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h index 34d228f4d2..f52cc43914 100644 --- a/core/variant/variant_construct.h +++ b/core/variant/variant_construct.h @@ -222,6 +222,64 @@ public: } }; +template <class T> +class VariantConstructorFromString { +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + if (p_args[0]->get_type() != Variant::STRING) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::STRING; + return; + } + + VariantTypeChanger<T>::change(&r_ret); + const String &src_str = *VariantGetInternalPtr<String>::get_ptr(p_args[0]); + + if (r_ret.get_type() == Variant::Type::INT) { + r_ret = src_str.to_int(); + } else if (r_ret.get_type() == Variant::Type::FLOAT) { + r_ret = src_str.to_float(); + } + } + + static inline void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantTypeChanger<T>::change(r_ret); + const String &src_str = *VariantGetInternalPtr<String>::get_ptr(p_args[0]); + T ret = Variant(); + if (r_ret->get_type() == Variant::Type::INT) { + ret = src_str.to_int(); + } else if (r_ret->get_type() == Variant::Type::FLOAT) { + ret = src_str.to_float(); + } + *r_ret = ret; + } + + static void ptr_construct(void *base, const void **p_args) { + String src_str = PtrToArg<String>::convert(p_args[0]); + T dst_var = Variant(); + Variant type_test = Variant(dst_var); + if (type_test.get_type() == Variant::Type::INT) { + dst_var = src_str.to_int(); + } else if (type_test.get_type() == Variant::Type::FLOAT) { + dst_var = src_str.to_float(); + } + PtrConstruct<T>::construct(dst_var, base); + } + + static int get_argument_count() { + return 1; + } + + static Variant::Type get_argument_type(int p_arg) { + return Variant::STRING; + } + + static Variant::Type get_base_type() { + return GetTypeInfo<T>::VARIANT_TYPE; + } +}; + class VariantConstructorCallableArgs { public: static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h index 94e7296a99..f3b9bd235c 100644 --- a/core/variant/variant_internal.h +++ b/core/variant/variant_internal.h @@ -1314,7 +1314,7 @@ struct VariantZeroAssigner<float> { template <> struct VariantZeroAssigner<String> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_string(v) = String(); } }; template <> @@ -1399,12 +1399,12 @@ struct VariantZeroAssigner<Color> { template <> struct VariantZeroAssigner<StringName> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_string_name(v) = StringName(); } }; template <> struct VariantZeroAssigner<NodePath> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_node_path(v) = NodePath(); } }; template <> @@ -1414,12 +1414,12 @@ struct VariantZeroAssigner<::RID> { template <> struct VariantZeroAssigner<Callable> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_callable(v) = Callable(); } }; template <> struct VariantZeroAssigner<Signal> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_signal(v) = Signal(); } }; template <> @@ -1434,47 +1434,47 @@ struct VariantZeroAssigner<Array> { template <> struct VariantZeroAssigner<PackedByteArray> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_byte_array(v) = PackedByteArray(); } }; template <> struct VariantZeroAssigner<PackedInt32Array> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_int32_array(v) = PackedInt32Array(); } }; template <> struct VariantZeroAssigner<PackedInt64Array> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_int64_array(v) = PackedInt64Array(); } }; template <> struct VariantZeroAssigner<PackedFloat32Array> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_float32_array(v) = PackedFloat32Array(); } }; template <> struct VariantZeroAssigner<PackedFloat64Array> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_float64_array(v) = PackedFloat64Array(); } }; template <> struct VariantZeroAssigner<PackedStringArray> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_string_array(v) = PackedStringArray(); } }; template <> struct VariantZeroAssigner<PackedVector2Array> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector2_array(v) = PackedVector2Array(); } }; template <> struct VariantZeroAssigner<PackedVector3Array> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector3_array(v) = PackedVector3Array(); } }; template <> struct VariantZeroAssigner<PackedColorArray> { - static _FORCE_INLINE_ void zero(Variant *v) {} + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_color_array(v) = PackedColorArray(); } }; template <class T> @@ -1517,7 +1517,7 @@ struct VariantTypeAdjust<Object *> { } }; -// GDNative extension helpers. +// GDExtension helpers. template <class T> struct VariantTypeConstructor { diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp index 25bc241e9b..d4e6dfb4d1 100644 --- a/core/variant/variant_op.cpp +++ b/core/variant/variant_op.cpp @@ -229,6 +229,20 @@ public: static Variant::Type get_return_type() { return GetTypeInfo<Vector4>::VARIANT_TYPE; } }; +#define register_string_op(m_op_type, m_op_code) \ + do { \ + register_op<m_op_type<String, String>>(m_op_code, Variant::STRING, Variant::STRING); \ + register_op<m_op_type<String, StringName>>(m_op_code, Variant::STRING, Variant::STRING_NAME); \ + register_op<m_op_type<StringName, String>>(m_op_code, Variant::STRING_NAME, Variant::STRING); \ + register_op<m_op_type<StringName, StringName>>(m_op_code, Variant::STRING_NAME, Variant::STRING_NAME); \ + } while (false) + +#define register_string_modulo_op(m_class, m_type) \ + do { \ + register_op<OperatorEvaluatorStringFormat<String, m_class>>(Variant::OP_MODULE, Variant::STRING, m_type); \ + register_op<OperatorEvaluatorStringFormat<StringName, m_class>>(Variant::OP_MODULE, Variant::STRING_NAME, m_type); \ + } while (false) + void Variant::_register_variant_operators() { memset(operator_return_type_table, 0, sizeof(operator_return_type_table)); memset(operator_evaluator_table, 0, sizeof(operator_evaluator_table)); @@ -239,7 +253,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAdd<double, int64_t, double>>(Variant::OP_ADD, Variant::INT, Variant::FLOAT); register_op<OperatorEvaluatorAdd<double, double, int64_t>>(Variant::OP_ADD, Variant::FLOAT, Variant::INT); register_op<OperatorEvaluatorAdd<double, double, double>>(Variant::OP_ADD, Variant::FLOAT, Variant::FLOAT); - register_op<OperatorEvaluatorAdd<String, String, String>>(Variant::OP_ADD, Variant::STRING, Variant::STRING); + register_string_op(OperatorEvaluatorStringConcat, Variant::OP_ADD); register_op<OperatorEvaluatorAdd<Vector2, Vector2, Vector2>>(Variant::OP_ADD, Variant::VECTOR2, Variant::VECTOR2); register_op<OperatorEvaluatorAdd<Vector2i, Vector2i, Vector2i>>(Variant::OP_ADD, Variant::VECTOR2I, Variant::VECTOR2I); register_op<OperatorEvaluatorAdd<Vector3, Vector3, Vector3>>(Variant::OP_ADD, Variant::VECTOR3, Variant::VECTOR3); @@ -415,46 +429,46 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorModNZ<Vector4i, Vector4i, Vector4i>>(Variant::OP_MODULE, Variant::VECTOR4I, Variant::VECTOR4I); register_op<OperatorEvaluatorModNZ<Vector4i, Vector4i, int64_t>>(Variant::OP_MODULE, Variant::VECTOR4I, Variant::INT); - register_op<OperatorEvaluatorStringModNil>(Variant::OP_MODULE, Variant::STRING, Variant::NIL); - - register_op<OperatorEvaluatorStringModT<bool>>(Variant::OP_MODULE, Variant::STRING, Variant::BOOL); - register_op<OperatorEvaluatorStringModT<int64_t>>(Variant::OP_MODULE, Variant::STRING, Variant::INT); - register_op<OperatorEvaluatorStringModT<double>>(Variant::OP_MODULE, Variant::STRING, Variant::FLOAT); - register_op<OperatorEvaluatorStringModT<String>>(Variant::OP_MODULE, Variant::STRING, Variant::STRING); - register_op<OperatorEvaluatorStringModT<Vector2>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR2); - register_op<OperatorEvaluatorStringModT<Vector2i>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR2I); - register_op<OperatorEvaluatorStringModT<Rect2>>(Variant::OP_MODULE, Variant::STRING, Variant::RECT2); - register_op<OperatorEvaluatorStringModT<Rect2i>>(Variant::OP_MODULE, Variant::STRING, Variant::RECT2I); - register_op<OperatorEvaluatorStringModT<Vector3>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR3); - register_op<OperatorEvaluatorStringModT<Vector3i>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR3I); - register_op<OperatorEvaluatorStringModT<Vector4>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR4); - register_op<OperatorEvaluatorStringModT<Vector4i>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR4I); - register_op<OperatorEvaluatorStringModT<Transform2D>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM2D); - register_op<OperatorEvaluatorStringModT<Plane>>(Variant::OP_MODULE, Variant::STRING, Variant::PLANE); - register_op<OperatorEvaluatorStringModT<Quaternion>>(Variant::OP_MODULE, Variant::STRING, Variant::QUATERNION); - register_op<OperatorEvaluatorStringModT<::AABB>>(Variant::OP_MODULE, Variant::STRING, Variant::AABB); - register_op<OperatorEvaluatorStringModT<Basis>>(Variant::OP_MODULE, Variant::STRING, Variant::BASIS); - register_op<OperatorEvaluatorStringModT<Transform3D>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM3D); - register_op<OperatorEvaluatorStringModT<Projection>>(Variant::OP_MODULE, Variant::STRING, Variant::PROJECTION); - - register_op<OperatorEvaluatorStringModT<Color>>(Variant::OP_MODULE, Variant::STRING, Variant::COLOR); - register_op<OperatorEvaluatorStringModT<StringName>>(Variant::OP_MODULE, Variant::STRING, Variant::STRING_NAME); - register_op<OperatorEvaluatorStringModT<NodePath>>(Variant::OP_MODULE, Variant::STRING, Variant::NODE_PATH); - register_op<OperatorEvaluatorStringModObject>(Variant::OP_MODULE, Variant::STRING, Variant::OBJECT); - register_op<OperatorEvaluatorStringModT<Callable>>(Variant::OP_MODULE, Variant::STRING, Variant::CALLABLE); - register_op<OperatorEvaluatorStringModT<Signal>>(Variant::OP_MODULE, Variant::STRING, Variant::SIGNAL); - register_op<OperatorEvaluatorStringModT<Dictionary>>(Variant::OP_MODULE, Variant::STRING, Variant::DICTIONARY); - register_op<OperatorEvaluatorStringModArray>(Variant::OP_MODULE, Variant::STRING, Variant::ARRAY); - - register_op<OperatorEvaluatorStringModT<PackedByteArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_BYTE_ARRAY); - register_op<OperatorEvaluatorStringModT<PackedInt32Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_INT32_ARRAY); - register_op<OperatorEvaluatorStringModT<PackedInt64Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_INT64_ARRAY); - register_op<OperatorEvaluatorStringModT<PackedFloat32Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_FLOAT32_ARRAY); - register_op<OperatorEvaluatorStringModT<PackedFloat64Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_FLOAT64_ARRAY); - register_op<OperatorEvaluatorStringModT<PackedStringArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_STRING_ARRAY); - register_op<OperatorEvaluatorStringModT<PackedVector2Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_VECTOR2_ARRAY); - register_op<OperatorEvaluatorStringModT<PackedVector3Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_VECTOR3_ARRAY); - register_op<OperatorEvaluatorStringModT<PackedColorArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_COLOR_ARRAY); + register_string_modulo_op(void, Variant::NIL); + + register_string_modulo_op(bool, Variant::BOOL); + register_string_modulo_op(int64_t, Variant::INT); + register_string_modulo_op(double, Variant::FLOAT); + register_string_modulo_op(String, Variant::STRING); + register_string_modulo_op(Vector2, Variant::VECTOR2); + register_string_modulo_op(Vector2i, Variant::VECTOR2I); + register_string_modulo_op(Rect2, Variant::RECT2); + register_string_modulo_op(Rect2i, Variant::RECT2I); + register_string_modulo_op(Vector3, Variant::VECTOR3); + register_string_modulo_op(Vector3i, Variant::VECTOR3I); + register_string_modulo_op(Vector4, Variant::VECTOR4); + register_string_modulo_op(Vector4i, Variant::VECTOR4I); + register_string_modulo_op(Transform2D, Variant::TRANSFORM2D); + register_string_modulo_op(Plane, Variant::PLANE); + register_string_modulo_op(Quaternion, Variant::QUATERNION); + register_string_modulo_op(::AABB, Variant::AABB); + register_string_modulo_op(Basis, Variant::BASIS); + register_string_modulo_op(Transform3D, Variant::TRANSFORM3D); + register_string_modulo_op(Projection, Variant::PROJECTION); + + register_string_modulo_op(Color, Variant::COLOR); + register_string_modulo_op(StringName, Variant::STRING_NAME); + register_string_modulo_op(NodePath, Variant::NODE_PATH); + register_string_modulo_op(Object, Variant::OBJECT); + register_string_modulo_op(Callable, Variant::CALLABLE); + register_string_modulo_op(Signal, Variant::SIGNAL); + register_string_modulo_op(Dictionary, Variant::DICTIONARY); + register_string_modulo_op(Array, Variant::ARRAY); + + register_string_modulo_op(PackedByteArray, Variant::PACKED_BYTE_ARRAY); + register_string_modulo_op(PackedInt32Array, Variant::PACKED_INT32_ARRAY); + register_string_modulo_op(PackedInt64Array, Variant::PACKED_INT64_ARRAY); + register_string_modulo_op(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY); + register_string_modulo_op(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY); + register_string_modulo_op(PackedStringArray, Variant::PACKED_STRING_ARRAY); + register_string_modulo_op(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY); + register_string_modulo_op(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY); + register_string_modulo_op(PackedColorArray, Variant::PACKED_COLOR_ARRAY); register_op<OperatorEvaluatorPow<int64_t, int64_t, int64_t>>(Variant::OP_POWER, Variant::INT, Variant::INT); register_op<OperatorEvaluatorPow<double, int64_t, double>>(Variant::OP_POWER, Variant::INT, Variant::FLOAT); @@ -498,7 +512,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorEqual<int64_t, double>>(Variant::OP_EQUAL, Variant::INT, Variant::FLOAT); register_op<OperatorEvaluatorEqual<double, int64_t>>(Variant::OP_EQUAL, Variant::FLOAT, Variant::INT); register_op<OperatorEvaluatorEqual<double, double>>(Variant::OP_EQUAL, Variant::FLOAT, Variant::FLOAT); - register_op<OperatorEvaluatorEqual<String, String>>(Variant::OP_EQUAL, Variant::STRING, Variant::STRING); + register_string_op(OperatorEvaluatorEqual, Variant::OP_EQUAL); register_op<OperatorEvaluatorEqual<Vector2, Vector2>>(Variant::OP_EQUAL, Variant::VECTOR2, Variant::VECTOR2); register_op<OperatorEvaluatorEqual<Vector2i, Vector2i>>(Variant::OP_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I); register_op<OperatorEvaluatorEqual<Rect2, Rect2>>(Variant::OP_EQUAL, Variant::RECT2, Variant::RECT2); @@ -516,10 +530,6 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorEqual<Projection, Projection>>(Variant::OP_EQUAL, Variant::PROJECTION, Variant::PROJECTION); register_op<OperatorEvaluatorEqual<Color, Color>>(Variant::OP_EQUAL, Variant::COLOR, Variant::COLOR); - register_op<OperatorEvaluatorEqual<StringName, String>>(Variant::OP_EQUAL, Variant::STRING_NAME, Variant::STRING); - register_op<OperatorEvaluatorEqual<String, StringName>>(Variant::OP_EQUAL, Variant::STRING, Variant::STRING_NAME); - register_op<OperatorEvaluatorEqual<StringName, StringName>>(Variant::OP_EQUAL, Variant::STRING_NAME, Variant::STRING_NAME); - register_op<OperatorEvaluatorEqual<NodePath, NodePath>>(Variant::OP_EQUAL, Variant::NODE_PATH, Variant::NODE_PATH); register_op<OperatorEvaluatorEqual<::RID, ::RID>>(Variant::OP_EQUAL, Variant::RID, Variant::RID); @@ -621,7 +631,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorNotEqual<int64_t, double>>(Variant::OP_NOT_EQUAL, Variant::INT, Variant::FLOAT); register_op<OperatorEvaluatorNotEqual<double, int64_t>>(Variant::OP_NOT_EQUAL, Variant::FLOAT, Variant::INT); register_op<OperatorEvaluatorNotEqual<double, double>>(Variant::OP_NOT_EQUAL, Variant::FLOAT, Variant::FLOAT); - register_op<OperatorEvaluatorNotEqual<String, String>>(Variant::OP_NOT_EQUAL, Variant::STRING, Variant::STRING); + register_string_op(OperatorEvaluatorNotEqual, Variant::OP_NOT_EQUAL); register_op<OperatorEvaluatorNotEqual<Vector2, Vector2>>(Variant::OP_NOT_EQUAL, Variant::VECTOR2, Variant::VECTOR2); register_op<OperatorEvaluatorNotEqual<Vector2i, Vector2i>>(Variant::OP_NOT_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I); register_op<OperatorEvaluatorNotEqual<Rect2, Rect2>>(Variant::OP_NOT_EQUAL, Variant::RECT2, Variant::RECT2); @@ -639,10 +649,6 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorNotEqual<Projection, Projection>>(Variant::OP_NOT_EQUAL, Variant::PROJECTION, Variant::PROJECTION); register_op<OperatorEvaluatorNotEqual<Color, Color>>(Variant::OP_NOT_EQUAL, Variant::COLOR, Variant::COLOR); - register_op<OperatorEvaluatorNotEqual<StringName, String>>(Variant::OP_NOT_EQUAL, Variant::STRING_NAME, Variant::STRING); - register_op<OperatorEvaluatorNotEqual<String, StringName>>(Variant::OP_NOT_EQUAL, Variant::STRING, Variant::STRING_NAME); - register_op<OperatorEvaluatorNotEqual<StringName, StringName>>(Variant::OP_NOT_EQUAL, Variant::STRING_NAME, Variant::STRING_NAME); - register_op<OperatorEvaluatorNotEqual<NodePath, NodePath>>(Variant::OP_NOT_EQUAL, Variant::NODE_PATH, Variant::NODE_PATH); register_op<OperatorEvaluatorNotEqual<::RID, ::RID>>(Variant::OP_NOT_EQUAL, Variant::RID, Variant::RID); @@ -895,10 +901,7 @@ 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<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_string_op(OperatorEvaluatorInStringFind, Variant::OP_IN); register_op<OperatorEvaluatorInDictionaryHasNil>(Variant::OP_IN, Variant::NIL, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<bool>>(Variant::OP_IN, Variant::BOOL, Variant::DICTIONARY); @@ -996,6 +999,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorInArrayFind<float, PackedFloat64Array>>(Variant::OP_IN, Variant::FLOAT, Variant::PACKED_FLOAT64_ARRAY); register_op<OperatorEvaluatorInArrayFind<String, PackedStringArray>>(Variant::OP_IN, Variant::STRING, Variant::PACKED_STRING_ARRAY); + register_op<OperatorEvaluatorInArrayFind<StringName, PackedStringArray>>(Variant::OP_IN, Variant::STRING_NAME, Variant::PACKED_STRING_ARRAY); register_op<OperatorEvaluatorInArrayFind<Vector2, PackedVector2Array>>(Variant::OP_IN, Variant::VECTOR2, Variant::PACKED_VECTOR2_ARRAY); register_op<OperatorEvaluatorInArrayFind<Vector3, PackedVector3Array>>(Variant::OP_IN, Variant::VECTOR3, Variant::PACKED_VECTOR3_ARRAY); @@ -1006,6 +1010,9 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorObjectHasPropertyStringName>(Variant::OP_IN, Variant::STRING_NAME, Variant::OBJECT); } +#undef register_string_op +#undef register_string_modulo_op + void Variant::_unregister_variant_operators() { } diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h index ec1ce67445..ea4216322c 100644 --- a/core/variant/variant_op.h +++ b/core/variant/variant_op.h @@ -875,7 +875,33 @@ public: static Variant::Type get_return_type() { return GetTypeInfo<Vector<T>>::VARIANT_TYPE; } }; -class OperatorEvaluatorStringModNil { +template <class Left, class Right> +class OperatorEvaluatorStringConcat { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const String a(*VariantGetInternalPtr<Left>::get_ptr(&p_left)); + const String b(*VariantGetInternalPtr<Right>::get_ptr(&p_right)); + *r_ret = a + b; + r_valid = true; + } + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const String a(*VariantGetInternalPtr<Left>::get_ptr(left)); + const String b(*VariantGetInternalPtr<Right>::get_ptr(right)); + *VariantGetInternalPtr<String>::get_ptr(r_ret) = a + b; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + const String a(PtrToArg<Left>::convert(left)); + const String b(PtrToArg<Right>::convert(right)); + PtrToArg<String>::encode(a + b, r_ret); + } + static Variant::Type get_return_type() { return Variant::STRING; } +}; + +template <class S, class T> +class OperatorEvaluatorStringFormat; + +template <class S> +class OperatorEvaluatorStringFormat<S, void> { public: _FORCE_INLINE_ static String do_mod(const String &s, bool *r_valid) { Array values; @@ -888,20 +914,22 @@ public: return a; } static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { - const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left); - *r_ret = do_mod(a, &r_valid); - r_valid = true; + *r_ret = do_mod(*VariantGetInternalPtr<S>::get_ptr(&p_left), &r_valid); } static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { - *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), nullptr); + bool valid = true; + String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), &valid); + ERR_FAIL_COND_MSG(!valid, result); + *VariantGetInternalPtr<String>::get_ptr(r_ret) = result; } static void ptr_evaluate(const void *left, const void *right, void *r_ret) { - PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), nullptr), r_ret); + PtrToArg<String>::encode(do_mod(PtrToArg<S>::convert(left), nullptr), r_ret); } static Variant::Type get_return_type() { return Variant::STRING; } }; -class OperatorEvaluatorStringModArray { +template <class S> +class OperatorEvaluatorStringFormat<S, Array> { public: _FORCE_INLINE_ static String do_mod(const String &s, const Array &p_values, bool *r_valid) { String a = s.sprintf(p_values, r_valid); @@ -911,20 +939,22 @@ public: return a; } static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { - const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left); - *r_ret = do_mod(a, *VariantGetInternalPtr<Array>::get_ptr(&p_right), &r_valid); - r_valid = true; + *r_ret = do_mod(*VariantGetInternalPtr<S>::get_ptr(&p_left), *VariantGetInternalPtr<Array>::get_ptr(&p_right), &r_valid); } static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { - *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), nullptr); + bool valid = true; + String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), &valid); + ERR_FAIL_COND_MSG(!valid, result); + *VariantGetInternalPtr<String>::get_ptr(r_ret) = result; } static void ptr_evaluate(const void *left, const void *right, void *r_ret) { - PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Array>::convert(right), nullptr), r_ret); + PtrToArg<String>::encode(do_mod(PtrToArg<S>::convert(left), PtrToArg<Array>::convert(right), nullptr), r_ret); } static Variant::Type get_return_type() { return Variant::STRING; } }; -class OperatorEvaluatorStringModObject { +template <class S> +class OperatorEvaluatorStringFormat<S, Object> { public: _FORCE_INLINE_ static String do_mod(const String &s, const Object *p_object, bool *r_valid) { Array values; @@ -937,21 +967,22 @@ public: return a; } static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { - const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left); - *r_ret = do_mod(a, p_right.get_validated_object(), &r_valid); - r_valid = true; + *r_ret = do_mod(*VariantGetInternalPtr<S>::get_ptr(&p_left), p_right.get_validated_object(), &r_valid); } static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { - *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), right->get_validated_object(), nullptr); + bool valid = true; + String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), right->get_validated_object(), &valid); + ERR_FAIL_COND_MSG(!valid, result); + *VariantGetInternalPtr<String>::get_ptr(r_ret) = result; } static void ptr_evaluate(const void *left, const void *right, void *r_ret) { - PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Object *>::convert(right), nullptr), r_ret); + PtrToArg<String>::encode(do_mod(PtrToArg<S>::convert(left), PtrToArg<Object *>::convert(right), nullptr), r_ret); } static Variant::Type get_return_type() { return Variant::STRING; } }; -template <class T> -class OperatorEvaluatorStringModT { +template <class S, class T> +class OperatorEvaluatorStringFormat { public: _FORCE_INLINE_ static String do_mod(const String &s, const T &p_value, bool *r_valid) { Array values; @@ -963,15 +994,16 @@ public: return a; } static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { - const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left); - *r_ret = do_mod(a, *VariantGetInternalPtr<T>::get_ptr(&p_right), &r_valid); - r_valid = true; + *r_ret = do_mod(*VariantGetInternalPtr<S>::get_ptr(&p_left), *VariantGetInternalPtr<T>::get_ptr(&p_right), &r_valid); } static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { - *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), nullptr); + bool valid = true; + String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), &valid); + ERR_FAIL_COND_MSG(!valid, result); + *VariantGetInternalPtr<String>::get_ptr(r_ret) = result; } static void ptr_evaluate(const void *left, const void *right, void *r_ret) { - PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<T>::convert(right), nullptr), r_ret); + PtrToArg<String>::encode(do_mod(PtrToArg<S>::convert(left), PtrToArg<T>::convert(right), nullptr), r_ret); } static Variant::Type get_return_type() { return Variant::STRING; } }; @@ -1280,8 +1312,11 @@ public: //// +template <class Left, class Right> +class OperatorEvaluatorInStringFind; + template <class Left> -class OperatorEvaluatorInStringFind { +class OperatorEvaluatorInStringFind<Left, String> { 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); @@ -1302,7 +1337,7 @@ public: }; template <class Left> -class OperatorEvaluatorInStringNameFind { +class OperatorEvaluatorInStringFind<Left, StringName> { 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); diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index d2e4d752a4..f122ed5f8f 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -35,39 +35,93 @@ #include "core/os/keyboard.h" #include "core/string/string_buffer.h" -char32_t VariantParser::StreamFile::get_char() { - return f->get_8(); +char32_t VariantParser::Stream::get_char() { + // is within buffer? + if (readahead_pointer < readahead_filled) { + return readahead_buffer[readahead_pointer++]; + } + + // attempt to readahead + readahead_filled = _read_buffer(readahead_buffer, readahead_enabled ? READAHEAD_SIZE : 1); + if (readahead_filled) { + readahead_pointer = 0; + } else { + // EOF + readahead_pointer = 1; + eof = true; + return 0; + } + return get_char(); +} + +bool VariantParser::Stream::is_eof() const { + if (readahead_enabled) { + return eof; + } + return _is_eof(); } bool VariantParser::StreamFile::is_utf8() const { return true; } -bool VariantParser::StreamFile::is_eof() const { +bool VariantParser::StreamFile::_is_eof() const { return f->eof_reached(); } -char32_t VariantParser::StreamString::get_char() { - if (pos > s.length()) { - return 0; - } else if (pos == s.length()) { - // You need to try to read again when you have reached the end for EOF to be reported, - // so this works the same as files (like StreamFile does) - pos++; - return 0; - } else { - return s[pos++]; +uint32_t VariantParser::StreamFile::_read_buffer(char32_t *p_buffer, uint32_t p_num_chars) { + // The buffer is assumed to include at least one character (for null terminator) + ERR_FAIL_COND_V(!p_num_chars, 0); + + uint8_t *temp = (uint8_t *)alloca(p_num_chars); + uint64_t num_read = f->get_buffer(temp, p_num_chars); + ERR_FAIL_COND_V(num_read == UINT64_MAX, 0); + + // translate to wchar + for (uint32_t n = 0; n < num_read; n++) { + p_buffer[n] = temp[n]; } + + // could be less than p_num_chars, or zero + return num_read; } bool VariantParser::StreamString::is_utf8() const { return false; } -bool VariantParser::StreamString::is_eof() const { +bool VariantParser::StreamString::_is_eof() const { return pos > s.length(); } +uint32_t VariantParser::StreamString::_read_buffer(char32_t *p_buffer, uint32_t p_num_chars) { + // The buffer is assumed to include at least one character (for null terminator) + ERR_FAIL_COND_V(!p_num_chars, 0); + + int available = MAX(s.length() - pos, 0); + if (available >= (int)p_num_chars) { + const char32_t *src = s.ptr(); + src += pos; + memcpy(p_buffer, src, p_num_chars * sizeof(char32_t)); + pos += p_num_chars; + + return p_num_chars; + } + + // going to reach EOF + if (available) { + const char32_t *src = s.ptr(); + src += pos; + memcpy(p_buffer, src, available * sizeof(char32_t)); + pos += available; + } + + // add a zero + p_buffer[available] = 0; + + return available; +} + ///////////////////////////////////////////////////////////////////////////////////////////////// const char *VariantParser::tk_name[TK_MAX] = { @@ -1283,7 +1337,7 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int Variant v; err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser); - if (err) { + if (err && err != ERR_FILE_MISSING_DEPENDENCIES) { return err; } object[key] = v; diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h index 56b484c8bc..fdea355c4b 100644 --- a/core/variant/variant_parser.h +++ b/core/variant/variant_parser.h @@ -38,35 +38,55 @@ class VariantParser { public: struct Stream { - virtual char32_t get_char() = 0; - virtual bool is_utf8() const = 0; - virtual bool is_eof() const = 0; - + private: + enum { READAHEAD_SIZE = 2048 }; + char32_t readahead_buffer[READAHEAD_SIZE]; + uint32_t readahead_pointer = 0; + uint32_t readahead_filled = 0; + bool eof = false; + + protected: + bool readahead_enabled = true; + virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) = 0; + virtual bool _is_eof() const = 0; + + public: char32_t saved = 0; + char32_t get_char(); + virtual bool is_utf8() const = 0; + bool is_eof() const; + Stream() {} virtual ~Stream() {} }; struct StreamFile : public Stream { + protected: + virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) override; + virtual bool _is_eof() const override; + + public: Ref<FileAccess> f; - virtual char32_t get_char() override; virtual bool is_utf8() const override; - virtual bool is_eof() const override; - StreamFile() {} + StreamFile(bool p_readahead_enabled = true) { readahead_enabled = p_readahead_enabled; } }; struct StreamString : public Stream { String s; + + private: int pos = 0; - virtual char32_t get_char() override; - virtual bool is_utf8() const override; - virtual bool is_eof() const override; + protected: + virtual uint32_t _read_buffer(char32_t *p_buffer, uint32_t p_num_chars) override; + virtual bool _is_eof() const override; - StreamString() {} + public: + virtual bool is_utf8() const override; + StreamString(bool p_readahead_enabled = true) { readahead_enabled = p_readahead_enabled; } }; typedef Error (*ParseResourceFunc)(void *p_self, Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str); diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 3843c32bcc..4b82981fa9 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -322,8 +322,52 @@ struct VariantUtilityFunctions { return Math::step_decimals(step); } - static inline double snapped(double value, double step) { - return Math::snapped(value, step); + static inline Variant snapped(const Variant &x, const Variant &step, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; + if (x.get_type() != step.get_type() && !((x.get_type() == Variant::INT && step.get_type() == Variant::FLOAT) || (x.get_type() == Variant::FLOAT && step.get_type() == Variant::INT))) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 1; + return Variant(); + } + + switch (step.get_type()) { + case Variant::INT: { + return snappedi(x, VariantInternalAccessor<int64_t>::get(&step)); + } break; + case Variant::FLOAT: { + return snappedf(x, VariantInternalAccessor<double>::get(&step)); + } break; + case Variant::VECTOR2: { + return VariantInternalAccessor<Vector2>::get(&x).snapped(VariantInternalAccessor<Vector2>::get(&step)); + } break; + case Variant::VECTOR2I: { + return VariantInternalAccessor<Vector2i>::get(&x).snapped(VariantInternalAccessor<Vector2i>::get(&step)); + } break; + case Variant::VECTOR3: { + return VariantInternalAccessor<Vector3>::get(&x).snapped(VariantInternalAccessor<Vector3>::get(&step)); + } break; + case Variant::VECTOR3I: { + return VariantInternalAccessor<Vector3i>::get(&x).snapped(VariantInternalAccessor<Vector3i>::get(&step)); + } break; + case Variant::VECTOR4: { + return VariantInternalAccessor<Vector4>::get(&x).snapped(VariantInternalAccessor<Vector4>::get(&step)); + } break; + case Variant::VECTOR4I: { + return VariantInternalAccessor<Vector4i>::get(&x).snapped(VariantInternalAccessor<Vector4i>::get(&step)); + } break; + default: { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); + } + } + } + + static inline double snappedf(double x, double step) { + return Math::snapped(x, step); + } + + static inline int64_t snappedi(double x, int64_t step) { + return Math::snapped(x, step); } static inline Variant lerp(const Variant &from, const Variant &to, double weight, Callable::CallError &r_error) { @@ -335,6 +379,9 @@ struct VariantUtilityFunctions { } switch (from.get_type()) { + case Variant::INT: { + return lerpf(VariantInternalAccessor<int64_t>::get(&from), to, weight); + } break; case Variant::FLOAT: { return lerpf(VariantInternalAccessor<double>::get(&from), to, weight); } break; @@ -389,6 +436,10 @@ struct VariantUtilityFunctions { return Math::bezier_interpolate(p_start, p_control_1, p_control_2, p_end, p_t); } + static inline double bezier_derivative(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) { + return Math::bezier_derivative(p_start, p_control_1, p_control_2, p_end, p_t); + } + static inline double lerp_angle(double from, double to, double weight) { return Math::lerp_angle(from, to, weight); } @@ -1132,6 +1183,40 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) { }; \ register_utility_function<Func_##m_func>(#m_func, m_args) +#define FUNCBINDVR2(m_func, m_args, m_category) \ + class Func_##m_func { \ + public: \ + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ + r_error.error = Callable::CallError::CALL_OK; \ + *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], r_error); \ + } \ + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ + Callable::CallError ce; \ + *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], ce); \ + } \ + static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ + Callable::CallError ce; \ + Variant r; \ + r = VariantUtilityFunctions::m_func(PtrToArg<Variant>::convert(p_args[0]), PtrToArg<Variant>::convert(p_args[1]), ce); \ + PtrToArg<Variant>::encode(r, ret); \ + } \ + static int get_argument_count() { \ + return 2; \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return Variant::NIL; \ + } \ + static Variant::Type get_return_type() { \ + return Variant::NIL; \ + } \ + static bool has_return_type() { \ + return true; \ + } \ + static bool is_vararg() { return false; } \ + static Variant::UtilityFunctionType get_type() { return m_category; } \ + }; \ + register_utility_function<Func_##m_func>(#m_func, m_args) + #define FUNCBINDVR3(m_func, m_args, m_category) \ class Func_##m_func { \ public: \ @@ -1415,6 +1500,10 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(signf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(signi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDVR2(snapped, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(snappedf, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(snappedi, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(pow, sarray("base", "exp"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(log, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(exp, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); @@ -1428,7 +1517,6 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(ease, sarray("x", "curve"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(snapped, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDVR3(lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(lerpf, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); @@ -1437,6 +1525,7 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(cubic_interpolate_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(cubic_interpolate_angle_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(bezier_interpolate, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(bezier_derivative, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(inverse_lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(remap, sarray("value", "istart", "istop", "ostart", "ostop"), Variant::UTILITY_FUNC_TYPE_MATH); |