From 40832387ce49ecbcaa6302ead0cb89688b983785 Mon Sep 17 00:00:00 2001 From: MJacred Date: Sun, 15 Dec 2024 13:39:29 +0100 Subject: [PATCH] Fix Input::remove_joy_mapping Erasing a joypad mapping can invalidate other attached joypads and the fallback mapping guid --- core/input/input.cpp | 30 +++++++++++++++++++++++++++++- core/input/input.h | 2 +- doc/classes/Input.xml | 2 +- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/core/input/input.cpp b/core/input/input.cpp index c50e8b0163cc..af28774c669e 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -1712,16 +1712,44 @@ void Input::add_joy_mapping(const String &p_mapping, bool p_update_existing) { } void Input::remove_joy_mapping(const String &p_guid) { + int fallback_mapping_offset = 0; // Fix the fallback, if we invalidate its index. + for (int i = map_db.size() - 1; i >= 0; i--) { if (p_guid == map_db[i].uid) { map_db.remove_at(i); + + if (i == fallback_mapping) { + fallback_mapping = -1; + WARN_PRINT_ONCE(vformat("Removed fallback joypad input mapping \"%s\". This could lead to joypads not working as intended.", p_guid)); + } else if (i < fallback_mapping) { + fallback_mapping_offset--; + } } } + + if (fallback_mapping_offset < 0) { + fallback_mapping += fallback_mapping_offset; + } + for (KeyValue &E : joy_names) { Joypad &joy = E.value; + int mapping; + if (joy.uid == p_guid) { - _set_joypad_mapping(joy, -1); + mapping = -1; + } else if (joy.mapping == (fallback_mapping - fallback_mapping_offset)) { + // Fix the mapping for the joypad that uses an outdated fallback index. + mapping = fallback_mapping; + } else { + // Re-validate the joypad's correct mapping. Fix it if necessary. + mapping = fallback_mapping; + for (int i = 0; i < map_db.size(); i++) { + if (joy.uid == map_db[i].uid) { + mapping = i; + } + } } + _set_joypad_mapping(joy, mapping); } } diff --git a/core/input/input.h b/core/input/input.h index 81722d013e6d..6893c4b997b4 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -184,7 +184,7 @@ class Input : public Object { HashSet ignored_device_ids; - int fallback_mapping = -1; + int fallback_mapping = -1; // Index of the guid in map_db. CursorShape default_shape = CURSOR_ARROW; diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 3a8bbb246a49..7e2534f0f77f 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -311,7 +311,7 @@ - Removes all mappings from the internal database that match the given GUID. + Removes all mappings from the internal database that match the given GUID. All currently connected joypads that use this GUID will become unmapped.