From 8e75fae49ef60bcbb3a2c31980a2461ad452ff3a Mon Sep 17 00:00:00 2001 From: MJacred Date: Tue, 14 Jan 2025 12:09:16 +0100 Subject: [PATCH] Ue an array removed_idx --- core/input/input.cpp | 63 ++++++++++++++++++++++++++++--------------- doc/classes/Input.xml | 1 + 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/core/input/input.cpp b/core/input/input.cpp index 8ef82db859..4413c426cf 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -1709,15 +1709,23 @@ void Input::add_joy_mapping(const String &p_mapping, bool p_update_existing) { } void Input::remove_joy_mapping(const String &p_guid) { - int count = 0; // The amount of removals performed. - int index_removed = -1; // The smallest index where an entry was removed. + // One GUID can exist multiple times in `map_db`, and + // `add_joy_mapping` can choose not to update the existing mapping, + // so the indices can be all over the place. Therefore we need to remember them. + Vector removed_idx; + int min_removed_idx = -1; + int max_removed_idx = -1; int fallback_mapping_offset = 0; for (int i = map_db.size() - 1; i >= 0; i--) { if (p_guid == map_db[i].uid) { map_db.remove_at(i); - index_removed = i; - count++; + + if (max_removed_idx == -1) { + max_removed_idx = i; + } + min_removed_idx = i; + removed_idx.push_back(i); if (i < fallback_mapping) { fallback_mapping_offset++; @@ -1728,33 +1736,44 @@ void Input::remove_joy_mapping(const String &p_guid) { } } - if (index_removed == -1) { - return; // Not found. + if (min_removed_idx == -1) { + return; // Nothing removed. } if (fallback_mapping > 0) { - // Fixing the shifted index. + // Fix the shifted index. fallback_mapping -= fallback_mapping_offset; } + int removed_idx_size = removed_idx.size(); + + // Update joypad mapping references: some + // * should use the fallback_mapping (if set; if not, they get unmapped), or + // * need their mapping reference fixed, because the deletion(s) offset them. for (KeyValue &E : joy_names) { Joypad &joy = E.value; + if (joy.mapping < min_removed_idx) { + continue; // Not affected. + } - if (joy.uid == p_guid) { - _set_joypad_mapping(joy, fallback_mapping); - } else if (joy.mapping > index_removed) { - if (count == 1) { - // The map_db update offset this joypad's mapping reference, update it: - _set_joypad_mapping(joy, joy.mapping - 1); - } else { - // Re-validate the joypad's correct mapping. Fix it if necessary. - int 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); + if (joy.mapping > max_removed_idx) { + _set_joypad_mapping(joy, joy.mapping - removed_idx_size); + continue; // Simple offset fix. + } + + // removed_idx is in reverse order (ie. high to low), because the first loop is in reverse order. + for (int i = 0; i < removed_idx.size(); i++) { + if (removed_idx[i] == joy.mapping) { + // Set to fallback_mapping, if defined, else unmap the joypad. + // Currently, the fallback_mapping is only set internally, and only for Android. + _set_joypad_mapping(joy, fallback_mapping); + break; + } + if (removed_idx[i] < joy.mapping) { + // Complex offset fix: + // This mapping was shifted by `(removed_idx_size - i)` deletions. + _set_joypad_mapping(joy, joy.mapping - (removed_idx_size - i)); + break; } } } diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 7e2534f0f7..2e12015e5f 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -312,6 +312,7 @@ Removes all mappings from the internal database that match the given GUID. All currently connected joypads that use this GUID will become unmapped. + On Android, Godot will map to an internal fallback mapping.