diff options
Diffstat (limited to 'core')
35 files changed, 280 insertions, 111 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index cbbfe3de75..93934f2320 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -852,8 +852,8 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const RBMap<S } if (!p_custom_features.is_empty()) { + // Store how many properties are saved, add one for custom features, which must always go first. file->store_32(count + 1); - //store how many properties are saved, add one for custom featuers, which must always go first String key = CoreStringNames::get_singleton()->_custom_features; file->store_pascal_string(key); @@ -870,7 +870,8 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const RBMap<S file->store_buffer(buff.ptr(), buff.size()); } else { - file->store_32(count); //store how many properties are saved + // Store how many properties are saved. + file->store_32(count); } for (const KeyValue<String, List<String>> &E : p_props) { diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index 26512d0c56..2bac1f6592 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -678,12 +678,11 @@ GDExtensionInterfaceFunctionPtr GDExtension::get_interface_function(StringName p } Error GDExtension::open_library(const String &p_path, const String &p_entry_symbol) { - library_path = p_path; - String abs_path = ProjectSettings::get_singleton()->globalize_path(p_path); #if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED) // If running on the editor on Windows, we copy the library and open the copy. // This is so the original file isn't locked and can be updated by a compiler. + bool library_copied = false; if (Engine::get_singleton()->is_editor_hint()) { if (!FileAccess::exists(abs_path)) { ERR_PRINT("GDExtension library not found: " + library_path); @@ -705,6 +704,7 @@ Error GDExtension::open_library(const String &p_path, const String &p_entry_symb return ERR_CANT_CREATE; } FileAccess::set_hidden_attribute(copy_path, true); + library_copied = true; // Save the copied path so it can be deleted later. temp_lib_path = copy_path; @@ -714,12 +714,20 @@ Error GDExtension::open_library(const String &p_path, const String &p_entry_symb } #endif - Error err = OS::get_singleton()->open_dynamic_library(abs_path, library, true); + Error err = OS::get_singleton()->open_dynamic_library(abs_path, library, true, &library_path); if (err != OK) { ERR_PRINT("GDExtension dynamic library not found: " + abs_path); return err; } +#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED) + // If we copied the file, let's change the library path to point at the original, + // because that's what we want to check to see if it's changed. + if (library_copied) { + library_path = library_path.get_base_dir() + "\\" + p_path.get_file(); + } +#endif + void *entry_funcptr = nullptr; err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, p_entry_symbol, entry_funcptr, false); @@ -904,6 +912,8 @@ Error GDExtensionResourceLoader::load_gdextension_resource(const String &p_path, return ERR_FILE_NOT_FOUND; } + bool is_static_library = library_path.ends_with(".a") || library_path.ends_with(".xcframework"); + if (!library_path.is_resource_file() && !library_path.is_absolute_path()) { library_path = p_path.get_base_dir().path_join(library_path); } @@ -915,12 +925,12 @@ Error GDExtensionResourceLoader::load_gdextension_resource(const String &p_path, #ifdef TOOLS_ENABLED p_extension->set_reloadable(config->get_value("configuration", "reloadable", false) && Engine::get_singleton()->is_extension_reloading_enabled()); - p_extension->update_last_modified_time(MAX( - FileAccess::get_modified_time(library_path), - FileAccess::get_modified_time(p_path))); + p_extension->update_last_modified_time( + FileAccess::get_modified_time(p_path), + FileAccess::get_modified_time(library_path)); #endif - err = p_extension->open_library(library_path, entry_symbol); + err = p_extension->open_library(is_static_library ? String() : library_path, entry_symbol); if (err != OK) { #if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED) // If the DLL fails to load, make sure that temporary DLL copies are cleaned up. @@ -959,13 +969,15 @@ Ref<Resource> GDExtensionResourceLoader::load(const String &p_path, const String // object if one has already been loaded (even if caching is disabled at the resource // loader level). GDExtensionManager *manager = GDExtensionManager::get_singleton(); - Ref<GDExtension> lib = manager->get_extension(p_path); - if (lib.is_null()) { - Error err = load_gdextension_resource(p_path, lib); - if (err != OK && r_error) { - // Errors already logged in load_gdextension_resource(). - *r_error = err; - } + if (manager->is_extension_loaded(p_path)) { + return manager->get_extension(p_path); + } + + Ref<GDExtension> lib; + Error err = load_gdextension_resource(p_path, lib); + if (err != OK && r_error) { + // Errors already logged in load_gdextension_resource(). + *r_error = err; } return lib; } @@ -988,10 +1000,13 @@ String GDExtensionResourceLoader::get_resource_type(const String &p_path) const #ifdef TOOLS_ENABLED bool GDExtension::has_library_changed() const { - if (FileAccess::get_modified_time(get_path()) > last_modified_time) { + // Check only that the last modified time is different (rather than checking + // that it's newer) since some OS's (namely Windows) will preserve the modified + // time by default when copying files. + if (FileAccess::get_modified_time(get_path()) != resource_last_modified_time) { return true; } - if (FileAccess::get_modified_time(library_path) > last_modified_time) { + if (FileAccess::get_modified_time(library_path) != library_last_modified_time) { return true; } return false; diff --git a/core/extension/gdextension.h b/core/extension/gdextension.h index bab3bcd198..0d20b8e50c 100644 --- a/core/extension/gdextension.h +++ b/core/extension/gdextension.h @@ -90,7 +90,8 @@ class GDExtension : public Resource { int32_t level_initialized = -1; #ifdef TOOLS_ENABLED - uint64_t last_modified_time = 0; + uint64_t resource_last_modified_time = 0; + uint64_t library_last_modified_time = 0; bool is_reloading = false; Vector<GDExtensionMethodBind *> invalid_methods; Vector<ObjectID> instance_bindings; @@ -140,8 +141,9 @@ public: void set_reloadable(bool p_reloadable) { reloadable = p_reloadable; } bool has_library_changed() const; - void update_last_modified_time(uint64_t p_last_modified_time) { - last_modified_time = MAX(last_modified_time, p_last_modified_time); + void update_last_modified_time(uint64_t p_resource_last_modified_time, uint64_t p_library_last_modified_time) { + resource_last_modified_time = p_resource_last_modified_time; + library_last_modified_time = p_library_last_modified_time; } void track_instance_binding(Object *p_object); diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp index d1b4e6a30f..e02e7aa701 100644 --- a/core/extension/gdextension_interface.cpp +++ b/core/extension/gdextension_interface.cpp @@ -159,9 +159,7 @@ public: userdata = p_info->callable_userdata; token = p_info->token; - if (p_info->object != nullptr) { - object = ((Object *)p_info->object)->get_instance_id(); - } + object = p_info->object_id; call_func = p_info->call_func; is_valid_func = p_info->is_valid_func; diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h index 240da6e073..d58f0226d8 100644 --- a/core/extension/gdextension_interface.h +++ b/core/extension/gdextension_interface.h @@ -392,7 +392,7 @@ typedef GDExtensionBool (*GDExtensionCallableCustomLessThan)(void *callable_user typedef void (*GDExtensionCallableCustomToString)(void *callable_userdata, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out); typedef struct { - /* Only `call_func` and `token` are strictly required, however, `object` should be passed if its not a static method. + /* Only `call_func` and `token` are strictly required, however, `object_id` should be passed if its not a static method. * * `token` should point to an address that uniquely identifies the GDExtension (for example, the * `GDExtensionClassLibraryPtr` passed to the entry symbol function. @@ -409,7 +409,7 @@ typedef struct { void *callable_userdata; void *token; - GDExtensionObjectPtr object; + GDObjectInstanceID object_id; GDExtensionCallableCustomCall call_func; GDExtensionCallableCustomIsValid is_valid_func; diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt index 9a43c4e35d..77655e9b6a 100644 --- a/core/input/gamecontrollerdb.txt +++ b/core/input/gamecontrollerdb.txt @@ -414,6 +414,8 @@ 03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 03000000ad1b00003ef0000000000000,MLG Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, 03000000380700006382000000000000,MLG PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000004523000015e0000000000000,Mobapad Chitu HD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000491900000904000000000000,Mobapad Chitu HD,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,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000ffff00000000000000000000,Mocute M053,a:b3,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b11,leftstick:b7,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b6,righttrigger:b4,rightx:a3,righty:a4,start:b8,x:b1,y:b0,platform:Windows, 03000000d6200000e589000000000000,Moga 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, 03000000d62000007162000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, @@ -582,6 +584,7 @@ 03000000921200004547000000000000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows, 03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, 03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +0300000003040000c197000000000000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,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, @@ -643,7 +646,6 @@ 030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows, 03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, 03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -0300000003040000c197000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, 0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows, 03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, 030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, @@ -772,6 +774,7 @@ 03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 03000000450c00002043000000000000,Xeox 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, +03000000e0ff00000201000000000000,Xiaomi Black Shark (L),back:b0,dpdown:b11,dpleft:b9,dpright:b10,dpup:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,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, 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, @@ -928,6 +931,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e0400000300000006010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Mac OS X, 030000005e0400000700000006010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Mac OS X, 030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X, +030000004523000015e0000072050000,Mobapad Chitu HD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, 03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000c62400002b89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, @@ -979,6 +983,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X, +0300000003040000c197000000000000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,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, @@ -1335,8 +1340,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000000b000007040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000000b000008040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e0400008e02000030110000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b00000b050000,Microsoft 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, 03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, +03000000790000001c18000010010000,Mobapad Chitu HD,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, 050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 05000000e80400006e0400001b010000,Mocute 053X M59,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, 050000004d4f435554452d3035305800,Mocute 054X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, @@ -1490,6 +1497,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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, 03000000321500000b10000011010000,Razer Wolverine 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, 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, +0300000003040000c197000011010000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,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, @@ -1639,6 +1647,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 060000005e040000120b000007050000,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, 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, 060000005e040000120b00000f050000,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,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000120b00000d050000,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, 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, @@ -1792,6 +1801,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 33323763323132376537376266393366,Microsoft Dual Strike,a:b24,b:b23,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android, 30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b20,lefttrigger:b9,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android, 32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4d4f42415041442050726f2d48440000,Mobapad Chitu HD,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, 4d4f435554452d303533582d4d35312d,Mocute 053X,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, 33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, diff --git a/core/input/input.cpp b/core/input/input.cpp index 2d48bdd4cf..257452b3d8 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -695,53 +695,34 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em } for (const KeyValue<StringName, InputMap::Action> &E : InputMap::get_singleton()->get_action_map()) { - if (InputMap::get_singleton()->event_is_action(p_event, E.key)) { - Action &action = action_state[E.key]; - bool is_joypad_axis = jm.is_valid(); - bool is_pressed = false; - if (!p_event->is_echo()) { - if (p_event->is_action_pressed(E.key)) { - bool is_joypad_axis_valid_zone_enter = false; - if (is_joypad_axis) { - if (!action.axis_pressed) { - is_joypad_axis_valid_zone_enter = true; - action.pressed++; - action.axis_pressed = true; - } - } else { - action.pressed++; - } - if (action.pressed == 1 && (is_joypad_axis_valid_zone_enter || !is_joypad_axis)) { - action.pressed_physics_frame = Engine::get_singleton()->get_physics_frames(); - action.pressed_process_frame = Engine::get_singleton()->get_process_frames(); - } - is_pressed = true; - } else { - bool is_released = true; - if (is_joypad_axis) { - if (action.axis_pressed) { - action.axis_pressed = false; - } else { - is_released = false; - } - } + const int event_index = InputMap::get_singleton()->event_get_index(p_event, E.key); + if (event_index == -1) { + continue; + } - if (is_released) { - if (action.pressed == 1) { - action.released_physics_frame = Engine::get_singleton()->get_physics_frames(); - action.released_process_frame = Engine::get_singleton()->get_process_frames(); - } - action.pressed = MAX(action.pressed - 1, 0); - } + Action &action = action_state[E.key]; + if (!p_event->is_echo()) { + if (p_event->is_action_pressed(E.key)) { + if (!action.pressed) { + action.pressed_physics_frame = Engine::get_singleton()->get_physics_frames(); + action.pressed_process_frame = Engine::get_singleton()->get_process_frames(); } - action.exact = InputMap::get_singleton()->event_is_action(p_event, E.key, true); - } + action.pressed |= ((uint64_t)1 << event_index); + } else { + action.pressed &= ~((uint64_t)1 << event_index); + action.pressed &= ~(1 << MAX_EVENT); // Always release the event from action_press() method. - if (is_pressed || action.pressed == 0) { - action.strength = p_event->get_action_strength(E.key); - action.raw_strength = p_event->get_action_raw_strength(E.key); + if (!action.pressed) { + action.released_physics_frame = Engine::get_singleton()->get_physics_frames(); + action.released_process_frame = Engine::get_singleton()->get_process_frames(); + } + _update_action_strength(action, MAX_EVENT, 0.0); + _update_action_raw_strength(action, MAX_EVENT, 0.0); } + action.exact = InputMap::get_singleton()->event_is_action(p_event, E.key, true); } + _update_action_strength(action, event_index, p_event->get_action_strength(E.key)); + _update_action_raw_strength(action, event_index, p_event->get_action_raw_strength(E.key)); } if (event_dispatch_function) { @@ -858,13 +839,13 @@ void Input::action_press(const StringName &p_action, float p_strength) { // Create or retrieve existing action. Action &action = action_state[p_action]; - action.pressed++; - if (action.pressed == 1) { + if (!action.pressed) { action.pressed_physics_frame = Engine::get_singleton()->get_physics_frames(); action.pressed_process_frame = Engine::get_singleton()->get_process_frames(); } - action.strength = p_strength; - action.raw_strength = p_strength; + action.pressed |= 1 << MAX_EVENT; + _update_action_strength(action, MAX_EVENT, p_strength); + _update_action_raw_strength(action, MAX_EVENT, p_strength); action.exact = true; } @@ -872,13 +853,15 @@ void Input::action_release(const StringName &p_action) { // Create or retrieve existing action. Action &action = action_state[p_action]; - action.pressed--; - if (action.pressed == 0) { - action.released_physics_frame = Engine::get_singleton()->get_physics_frames(); - action.released_process_frame = Engine::get_singleton()->get_process_frames(); + action.pressed = 0; + action.strength = 0.0; + action.raw_strength = 0.0; + action.released_physics_frame = Engine::get_singleton()->get_physics_frames(); + action.released_process_frame = Engine::get_singleton()->get_process_frames(); + for (uint64_t i = 0; i <= MAX_EVENT; i++) { + action.strengths[i] = 0.0; + action.raw_strengths[i] = 0.0; } - action.strength = 0.0f; - action.raw_strength = 0.0f; action.exact = true; } @@ -1207,6 +1190,38 @@ void Input::_axis_event(int p_device, JoyAxis p_axis, float p_value) { parse_input_event(ievent); } +void Input::_update_action_strength(Action &p_action, int p_event_index, float p_strength) { + ERR_FAIL_INDEX(p_event_index, (int)MAX_EVENT + 1); + + float old_strength = p_action.strengths[p_event_index]; + p_action.strengths[p_event_index] = p_strength; + + if (p_strength > p_action.strength) { + p_action.strength = p_strength; + } else if (Math::is_equal_approx(old_strength, p_action.strength)) { + p_action.strength = p_strength; + for (uint64_t i = 0; i <= MAX_EVENT; i++) { + p_action.strength = MAX(p_action.strength, p_action.strengths[i]); + } + } +} + +void Input::_update_action_raw_strength(Action &p_action, int p_event_index, float p_strength) { + ERR_FAIL_INDEX(p_event_index, (int)MAX_EVENT + 1); + + float old_strength = p_action.raw_strengths[p_event_index]; + p_action.raw_strengths[p_event_index] = p_strength; + + if (p_strength > p_action.raw_strength) { + p_action.raw_strength = p_strength; + } else if (Math::is_equal_approx(old_strength, p_action.raw_strength)) { + p_action.raw_strength = p_strength; + for (uint64_t i = 0; i <= MAX_EVENT; i++) { + p_action.raw_strength = MAX(p_action.raw_strength, p_action.raw_strengths[i]); + } + } +} + Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button) { JoyEvent event; diff --git a/core/input/input.h b/core/input/input.h index bedc3fa0e3..dd613c4877 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -44,6 +44,8 @@ class Input : public Object { static Input *singleton; + static constexpr uint64_t MAX_EVENT = 31; + public: enum MouseMode { MOUSE_MODE_VISIBLE, @@ -103,11 +105,22 @@ private: uint64_t pressed_process_frame = UINT64_MAX; uint64_t released_physics_frame = UINT64_MAX; uint64_t released_process_frame = UINT64_MAX; - int pressed = 0; - bool axis_pressed = false; + uint64_t pressed = 0; bool exact = true; float strength = 0.0f; float raw_strength = 0.0f; + LocalVector<float> strengths; + LocalVector<float> raw_strengths; + + Action() { + strengths.resize(MAX_EVENT + 1); + raw_strengths.resize(MAX_EVENT + 1); + + for (uint64_t i = 0; i <= MAX_EVENT; i++) { + strengths[i] = 0.0; + raw_strengths[i] = 0.0; + } + } }; HashMap<StringName, Action> action_state; @@ -227,6 +240,8 @@ private: JoyAxis _get_output_axis(String output); void _button_event(int p_device, JoyButton p_index, bool p_pressed); void _axis_event(int p_device, JoyAxis p_axis, float p_value); + void _update_action_strength(Action &p_action, int p_event_index, float p_strength); + void _update_action_raw_strength(Action &p_action, int p_event_index, float p_strength); void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated); diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index ddfde0e7cd..78b9ada884 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -127,16 +127,21 @@ List<StringName> InputMap::get_actions() const { return actions; } -List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match, bool *r_pressed, float *r_strength, float *r_raw_strength) const { +List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match, bool *r_pressed, float *r_strength, float *r_raw_strength, int *r_event_index) const { ERR_FAIL_COND_V(!p_event.is_valid(), nullptr); + int i = 0; for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) { int device = E->get()->get_device(); if (device == ALL_DEVICES || device == p_event->get_device()) { if (E->get()->action_match(p_event, p_exact_match, p_action.deadzone, r_pressed, r_strength, r_raw_strength)) { + if (r_event_index) { + *r_event_index = i; + } return E; } } + i++; } return nullptr; @@ -179,6 +184,7 @@ void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEve List<Ref<InputEvent>>::Element *E = _find_event(input_map[p_action], p_event, true); if (E) { input_map[p_action].inputs.erase(E); + if (Input::get_singleton()->is_action_pressed(p_action)) { Input::get_singleton()->action_release(p_action); } @@ -216,7 +222,13 @@ bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName return event_get_action_status(p_event, p_action, p_exact_match); } -bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *r_pressed, float *r_strength, float *r_raw_strength) const { +int InputMap::event_get_index(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match) const { + int index = -1; + event_get_action_status(p_event, p_action, p_exact_match, nullptr, nullptr, nullptr, &index); + return index; +} + +bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *r_pressed, float *r_strength, float *r_raw_strength, int *r_event_index) const { HashMap<StringName, Action>::Iterator E = input_map.find(p_action); ERR_FAIL_COND_V_MSG(!E, false, suggest_actions(p_action)); @@ -236,7 +248,7 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str return input_event_action->get_action() == p_action; } - List<Ref<InputEvent>>::Element *event = _find_event(E->value, p_event, p_exact_match, r_pressed, r_strength, r_raw_strength); + List<Ref<InputEvent>>::Element *event = _find_event(E->value, p_event, p_exact_match, r_pressed, r_strength, r_raw_strength, r_event_index); return event != nullptr; } diff --git a/core/input/input_map.h b/core/input/input_map.h index b4d5beacb3..6407ea489e 100644 --- a/core/input/input_map.h +++ b/core/input/input_map.h @@ -61,7 +61,7 @@ private: HashMap<String, List<Ref<InputEvent>>> default_builtin_cache; HashMap<String, List<Ref<InputEvent>>> default_builtin_with_overrides_cache; - List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const; + List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr, int *r_event_index = nullptr) const; TypedArray<InputEvent> _action_get_events(const StringName &p_action); TypedArray<StringName> _get_actions(); @@ -86,7 +86,8 @@ public: const List<Ref<InputEvent>> *action_get_events(const StringName &p_action); bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false) const; - bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const; + int event_get_index(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false) const; + bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr, int *r_event_index = nullptr) const; const HashMap<StringName, Action> &get_action_map() const; void load_from_project_settings(); diff --git a/core/io/image.cpp b/core/io/image.cpp index 15d0182dfc..ce08b417a8 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -3773,7 +3773,7 @@ void Image::fix_alpha_edges() { } int closest_dist = max_dist; - uint8_t closest_color[3]; + uint8_t closest_color[3] = { 0 }; int from_x = MAX(0, j - max_radius); int to_x = MIN(width - 1, j + max_radius); diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index 79e4b207d4..3d384d9345 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -1621,8 +1621,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo encode_uint32(datalen, buf); buf += 4; const uint8_t *r = data.ptr(); - memcpy(buf, &r[0], datalen * datasize); - buf += datalen * datasize; + if (r) { + memcpy(buf, &r[0], datalen * datasize); + buf += datalen * datasize; + } } r_len += 4 + datalen * datasize; diff --git a/core/io/resource.cpp b/core/io/resource.cpp index e0d42a274a..64fa597a67 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -90,6 +90,10 @@ String Resource::get_path() const { return path_cache; } +void Resource::set_path_cache(const String &p_path) { + path_cache = p_path; +} + String Resource::generate_scene_unique_id() { // Generate a unique enough hash, but still user-readable. // If it's not unique it does not matter because the saver will try again. diff --git a/core/io/resource.h b/core/io/resource.h index a9b1a88f6b..610c2150db 100644 --- a/core/io/resource.h +++ b/core/io/resource.h @@ -103,6 +103,7 @@ public: virtual void set_path(const String &p_path, bool p_take_over = false); String get_path() const; + void set_path_cache(const String &p_path); // Set raw path without involving resource cache. _FORCE_INLINE_ bool is_built_in() const { return path_cache.is_empty() || path_cache.contains("::") || path_cache.begins_with("local://"); } static String generate_scene_unique_id(); diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index ea97e5ecce..2a33f723dc 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -774,6 +774,8 @@ Error ResourceLoaderBinary::load() { res = Ref<Resource>(r); if (!path.is_empty() && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) { r->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE); //if got here because the resource with same path has different type, replace it + } else if (!path.is_resource_file()) { + r->set_path_cache(path); } r->set_scene_unique_id(id); } diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index 0089544caa..e17644058a 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -136,6 +136,7 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const = 0; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const = 0; + virtual void handle_compatibility_options(HashMap<StringName, Variant> &p_import_params) const {} virtual String get_option_group_file() const { return String(); } virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) = 0; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index f7915261af..b1ebdff91f 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -341,6 +341,8 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { if (load_task.resource.is_valid()) { if (load_task.cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) { load_task.resource->set_path(load_task.local_path); + } else if (!load_task.local_path.is_resource_file()) { + load_task.resource->set_path_cache(load_task.local_path); } if (load_task.xl_remapped) { @@ -1053,8 +1055,9 @@ void ResourceLoader::clear_thread_load_tasks() { thread_load_mutex.lock(); } - for (KeyValue<String, LoadToken *> &E : user_load_tokens) { - memdelete(E.value); + while (user_load_tokens.begin()) { + // User load tokens remove themselves from the map on destruction. + memdelete(user_load_tokens.begin()->value); } user_load_tokens.clear(); diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp index 216fc24fff..edff3e1f14 100644 --- a/core/io/resource_uid.cpp +++ b/core/io/resource_uid.cpp @@ -35,6 +35,8 @@ #include "core/io/dir_access.h" #include "core/io/file_access.h" +// These constants are off by 1, causing the 'z' and '9' characters never to be used. +// This cannot be fixed without breaking compatibility; see GH-83843. static constexpr uint32_t char_count = ('z' - 'a'); static constexpr uint32_t base = char_count + ('9' - '0'); diff --git a/core/math/geometry_2d.h b/core/math/geometry_2d.h index 0e5702e0af..b37fce9e9c 100644 --- a/core/math/geometry_2d.h +++ b/core/math/geometry_2d.h @@ -306,10 +306,12 @@ public: Vector<Delaunay2D::Triangle> tr = Delaunay2D::triangulate(p_points); Vector<int> triangles; + triangles.resize(3 * tr.size()); + int *ptr = triangles.ptrw(); for (int i = 0; i < tr.size(); i++) { - triangles.push_back(tr[i].points[0]); - triangles.push_back(tr[i].points[1]); - triangles.push_back(tr[i].points[2]); + *ptr++ = tr[i].points[0]; + *ptr++ = tr[i].points[1]; + *ptr++ = tr[i].points[2]; } return triangles; } diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index c594f4a9b4..bf1bd0de93 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -98,9 +98,24 @@ void ClassDB::get_class_list(List<StringName> *p_classes) { p_classes->push_back(E.key); } - p_classes->sort(); + p_classes->sort_custom<StringName::AlphCompare>(); } +#ifdef TOOLS_ENABLED +void ClassDB::get_extensions_class_list(List<StringName> *p_classes) { + OBJTYPE_RLOCK; + + for (const KeyValue<StringName, ClassInfo> &E : classes) { + if (E.value.api != API_EXTENSION && E.value.api != API_EDITOR_EXTENSION) { + continue; + } + p_classes->push_back(E.key); + } + + p_classes->sort_custom<StringName::AlphCompare>(); +} +#endif + void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) { OBJTYPE_RLOCK; @@ -165,8 +180,8 @@ ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) { } uint32_t ClassDB::get_api_hash(APIType p_api) { - OBJTYPE_RLOCK; #ifdef DEBUG_METHODS_ENABLED + OBJTYPE_WLOCK; if (api_hashes_cache.has(p_api)) { return api_hashes_cache[p_api]; @@ -175,7 +190,9 @@ uint32_t ClassDB::get_api_hash(APIType p_api) { uint64_t hash = hash_murmur3_one_64(HashMapHasherDefault::hash(VERSION_FULL_CONFIG)); List<StringName> class_list; - ClassDB::get_class_list(&class_list); + for (const KeyValue<StringName, ClassInfo> &E : classes) { + class_list.push_back(E.key); + } // Must be alphabetically sorted for hash to compute. class_list.sort_custom<StringName::AlphCompare>(); @@ -859,8 +876,8 @@ void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_ } void ClassDB::set_method_error_return_values(const StringName &p_class, const StringName &p_method, const Vector<Error> &p_values) { - OBJTYPE_RLOCK; #ifdef DEBUG_METHODS_ENABLED + OBJTYPE_WLOCK; ClassInfo *type = classes.getptr(p_class); ERR_FAIL_NULL(type); @@ -871,6 +888,7 @@ void ClassDB::set_method_error_return_values(const StringName &p_class, const St Vector<Error> ClassDB::get_method_error_return_values(const StringName &p_class, const StringName &p_method) { #ifdef DEBUG_METHODS_ENABLED + OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); ERR_FAIL_NULL_V(type, Vector<Error>()); @@ -1415,6 +1433,8 @@ void ClassDB::_bind_compatibility(ClassInfo *type, MethodBind *p_method) { } void ClassDB::_bind_method_custom(const StringName &p_class, MethodBind *p_method, bool p_compatibility) { + OBJTYPE_WLOCK; + ClassInfo *type = classes.getptr(p_class); if (!type) { ERR_FAIL_MSG("Couldn't bind custom method '" + p_method->get_name() + "' for instance '" + p_class + "'."); diff --git a/core/object/class_db.h b/core/object/class_db.h index 5c2c59d508..7a4ee1afa4 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -251,6 +251,9 @@ public: } static void get_class_list(List<StringName> *p_classes); +#ifdef TOOLS_ENABLED + static void get_extensions_class_list(List<StringName> *p_classes); +#endif static void get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes); static void get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes); static StringName get_parent_class_nocheck(const StringName &p_class); diff --git a/core/object/object.cpp b/core/object/object.cpp index 2e5b897bce..40df13849b 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -198,6 +198,7 @@ bool Object::_predelete() { notification(NOTIFICATION_PREDELETE, true); if (_predelete_ok) { _class_name_ptr = nullptr; // Must restore, so constructors/destructors have proper class name access at each stage. + notification(NOTIFICATION_PREDELETE_CLEANUP, true); } return _predelete_ok; } diff --git a/core/object/object.h b/core/object/object.h index a444db0f70..f3c387594b 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -801,6 +801,8 @@ public: NOTIFICATION_POSTINITIALIZE = 0, NOTIFICATION_PREDELETE = 1, NOTIFICATION_EXTENSION_RELOADED = 2, + // Internal notification to send after NOTIFICATION_PREDELETE, not bound to scripting. + NOTIFICATION_PREDELETE_CLEANUP = 3, }; /* TYPE API */ diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index 011f4203ea..2bdbfb5ad1 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -39,10 +39,11 @@ ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES]; int ScriptServer::_language_count = 0; +bool ScriptServer::languages_ready = false; +Mutex ScriptServer::languages_mutex; bool ScriptServer::scripting_enabled = true; bool ScriptServer::reload_scripts_on_save = false; -SafeFlag ScriptServer::languages_finished; // Used until GH-76581 is fixed properly. ScriptEditRequestFunction ScriptServer::edit_request_func = nullptr; void Script::_notification(int p_what) { @@ -160,12 +161,13 @@ bool ScriptServer::is_scripting_enabled() { } ScriptLanguage *ScriptServer::get_language(int p_idx) { + MutexLock lock(languages_mutex); ERR_FAIL_INDEX_V(p_idx, _language_count, nullptr); - return _languages[p_idx]; } Error ScriptServer::register_language(ScriptLanguage *p_language) { + MutexLock lock(languages_mutex); ERR_FAIL_NULL_V(p_language, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V_MSG(_language_count >= MAX_LANGUAGES, ERR_UNAVAILABLE, "Script languages limit has been reach, cannot register more."); for (int i = 0; i < _language_count; i++) { @@ -179,6 +181,8 @@ Error ScriptServer::register_language(ScriptLanguage *p_language) { } Error ScriptServer::unregister_language(const ScriptLanguage *p_language) { + MutexLock lock(languages_mutex); + for (int i = 0; i < _language_count; i++) { if (_languages[i] == p_language) { _language_count--; @@ -219,17 +223,31 @@ void ScriptServer::init_languages() { } } - for (int i = 0; i < _language_count; i++) { - _languages[i]->init(); + { + MutexLock lock(languages_mutex); + + for (int i = 0; i < _language_count; i++) { + _languages[i]->init(); + } + + languages_ready = true; } } void ScriptServer::finish_languages() { + MutexLock lock(languages_mutex); + for (int i = 0; i < _language_count; i++) { _languages[i]->finish(); } global_classes_clear(); - languages_finished.set(); + + languages_ready = false; +} + +bool ScriptServer::are_languages_initialized() { + MutexLock lock(languages_mutex); + return languages_ready; } void ScriptServer::set_reload_scripts_on_save(bool p_enable) { @@ -241,7 +259,8 @@ bool ScriptServer::is_reload_scripts_on_save_enabled() { } void ScriptServer::thread_enter() { - if (!languages_finished.is_set()) { + MutexLock lock(languages_mutex); + if (!languages_ready) { return; } for (int i = 0; i < _language_count; i++) { @@ -250,7 +269,8 @@ void ScriptServer::thread_enter() { } void ScriptServer::thread_exit() { - if (!languages_finished.is_set()) { + MutexLock lock(languages_mutex); + if (!languages_ready) { return; } for (int i = 0; i < _language_count; i++) { diff --git a/core/object/script_language.h b/core/object/script_language.h index 3e4041d173..85e64c8d62 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -52,9 +52,11 @@ class ScriptServer { static ScriptLanguage *_languages[MAX_LANGUAGES]; static int _language_count; + static bool languages_ready; + static Mutex languages_mutex; + static bool scripting_enabled; static bool reload_scripts_on_save; - static SafeFlag languages_finished; // Used until GH-76581 is fixed properly. struct GlobalScriptClass { StringName language; @@ -98,8 +100,7 @@ public: static void init_languages(); static void finish_languages(); - - static bool are_languages_finished() { return languages_finished.is_set(); } + static bool are_languages_initialized(); }; class PlaceHolderScriptInstance; diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index 5f3a70cad8..00ab1cd6c0 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -313,6 +313,9 @@ public: ERR_CONTINUE(!err.has("message")); ScriptError serr; + if (err.has("path")) { + serr.path = err["path"]; + } serr.line = err["line"]; serr.column = err["column"]; serr.message = err["message"]; diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp index a8f2ac5bfe..1d0dff526d 100644 --- a/core/object/undo_redo.cpp +++ b/core/object/undo_redo.cpp @@ -463,6 +463,10 @@ bool UndoRedo::has_redo() const { return (current_action + 1) < actions.size(); } +bool UndoRedo::is_merging() const { + return merging; +} + uint64_t UndoRedo::get_version() const { return version; } diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h index 74a6bea732..b3a3322e4b 100644 --- a/core/object/undo_redo.h +++ b/core/object/undo_redo.h @@ -131,6 +131,8 @@ public: bool has_undo() const; bool has_redo() const; + bool is_merging() const; + uint64_t get_version() const; void set_commit_notify_callback(CommitNotifyCallback p_callback, void *p_ud); diff --git a/core/object/worker_thread_pool.cpp b/core/object/worker_thread_pool.cpp index 2fcd0867e6..784acadab4 100644 --- a/core/object/worker_thread_pool.cpp +++ b/core/object/worker_thread_pool.cpp @@ -30,6 +30,7 @@ #include "worker_thread_pool.h" +#include "core/object/script_language.h" #include "core/os/os.h" #include "core/os/thread_safe.h" @@ -60,6 +61,14 @@ void WorkerThreadPool::_process_task(Task *p_task) { set_current_thread_safe_for_nodes(false); pool_thread_index = thread_ids[Thread::get_caller_id()]; ThreadData &curr_thread = threads[pool_thread_index]; + // Since the WorkerThreadPool is started before the script server, + // its pre-created threads can't have ScriptServer::thread_enter() called on them early. + // Therefore, we do it late at the first opportunity, so in case the task + // about to be run uses scripting, guarantees are held. + if (!curr_thread.ready_for_scripting && ScriptServer::are_languages_initialized()) { + ScriptServer::thread_enter(); + curr_thread.ready_for_scripting = true; + } task_mutex.lock(); p_task->pool_thread_index = pool_thread_index; if (low_priority) { diff --git a/core/object/worker_thread_pool.h b/core/object/worker_thread_pool.h index d4d9387765..f323a979f7 100644 --- a/core/object/worker_thread_pool.h +++ b/core/object/worker_thread_pool.h @@ -106,6 +106,7 @@ private: uint32_t index; Thread thread; Task *current_low_prio_task = nullptr; + bool ready_for_scripting = false; }; TightLocalVector<ThreadData> threads; diff --git a/core/os/os.cpp b/core/os/os.cpp index 991b179e1f..c7390f14ff 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -490,6 +490,12 @@ bool OS::has_feature(const String &p_feature) { } #endif +#if defined(IOS_SIMULATOR) + if (p_feature == "simulator") { + return true; + } +#endif + if (_check_internal_feature_support(p_feature)) { return true; } diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp index 5a8df07410..658297d805 100644 --- a/core/string/string_name.cpp +++ b/core/string/string_name.cpp @@ -122,7 +122,7 @@ void StringName::unref() { if (_data && _data->refcount.unref()) { MutexLock lock(mutex); - if (_data->static_count.get() > 0) { + if (CoreGlobals::leak_reporting_enabled && _data->static_count.get() > 0) { if (_data->cname) { ERR_PRINT("BUG: Unreferenced static string to 0: " + String(_data->cname)); } else { diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 9be7c04158..60e2d539f8 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -4699,11 +4699,16 @@ String String::property_name_encode() const { static const char32_t invalid_node_name_characters[] = { '.', ':', '@', '/', '\"', UNIQUE_NODE_PREFIX[0], 0 }; -String String::get_invalid_node_name_characters() { +String String::get_invalid_node_name_characters(bool p_allow_internal) { // Do not use this function for critical validation. String r; const char32_t *c = invalid_node_name_characters; while (*c) { + if (p_allow_internal && *c == '@') { + c++; + continue; + } + if (c != invalid_node_name_characters) { r += " "; } diff --git a/core/string/ustring.h b/core/string/ustring.h index f45392eee1..897b06fc6d 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -437,7 +437,7 @@ public: String property_name_encode() const; // node functions - static String get_invalid_node_name_characters(); + static String get_invalid_node_name_characters(bool p_allow_internal = false); String validate_node_name() const; String validate_identifier() const; String validate_filename() const; diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 09fb34e7c1..4c0212075b 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -1291,7 +1291,13 @@ void Variant::zero() { break; default: + Type prev_type = type; this->clear(); + if (type != prev_type) { + // clear() changes type to NIL, so it needs to be restored. + Callable::CallError ce; + Variant::construct(prev_type, *this, nullptr, 0, ce); + } break; } } |