@@ -1709,15 +1709,23 @@ void Input::add_joy_mapping(const String &p_mapping, bool p_update_existing) {
17091709}
17101710
17111711void Input::remove_joy_mapping (const String &p_guid) {
1712- int count = 0 ; // The amount of removals performed.
1713- int index_removed = -1 ; // The smallest index where an entry was removed.
1712+ // One GUID can exist multiple times in `map_db`, and
1713+ // `add_joy_mapping` can choose not to update the existing mapping,
1714+ // so the indices can be all over the place. Therefore we need to remember them.
1715+ Vector<int > removed_idx;
1716+ int min_removed_idx = -1 ;
1717+ int max_removed_idx = -1 ;
17141718 int fallback_mapping_offset = 0 ;
17151719
17161720 for (int i = map_db.size () - 1 ; i >= 0 ; i--) {
17171721 if (p_guid == map_db[i].uid ) {
17181722 map_db.remove_at (i);
1719- index_removed = i;
1720- count++;
1723+
1724+ if (max_removed_idx == -1 ) {
1725+ max_removed_idx = i;
1726+ }
1727+ min_removed_idx = i;
1728+ removed_idx.push_back (i);
17211729
17221730 if (i < fallback_mapping) {
17231731 fallback_mapping_offset++;
@@ -1728,33 +1736,44 @@ void Input::remove_joy_mapping(const String &p_guid) {
17281736 }
17291737 }
17301738
1731- if (index_removed == -1 ) {
1732- return ; // Not found .
1739+ if (min_removed_idx == -1 ) {
1740+ return ; // Nothing removed .
17331741 }
17341742
17351743 if (fallback_mapping > 0 ) {
1736- // Fixing the shifted index.
1744+ // Fix the shifted index.
17371745 fallback_mapping -= fallback_mapping_offset;
17381746 }
17391747
1748+ int removed_idx_size = removed_idx.size ();
1749+
1750+ // Update joypad mapping references: some
1751+ // * should use the fallback_mapping (if set; if not, they get unmapped), or
1752+ // * need their mapping reference fixed, because the deletion(s) offset them.
17401753 for (KeyValue<int , Joypad> &E : joy_names) {
17411754 Joypad &joy = E.value ;
1755+ if (joy.mapping < min_removed_idx) {
1756+ continue ; // Not affected.
1757+ }
17421758
1743- if (joy.uid == p_guid) {
1744- _set_joypad_mapping (joy, fallback_mapping);
1745- } else if (joy.mapping > index_removed) {
1746- if (count == 1 ) {
1747- // The map_db update offset this joypad's mapping reference, update it:
1748- _set_joypad_mapping (joy, joy.mapping - 1 );
1749- } else {
1750- // Re-validate the joypad's correct mapping. Fix it if necessary.
1751- int mapping = fallback_mapping;
1752- for (int i = 0 ; i < map_db.size (); i++) {
1753- if (joy.uid == map_db[i].uid ) {
1754- mapping = i;
1755- }
1756- }
1757- _set_joypad_mapping (joy, mapping);
1759+ if (joy.mapping > max_removed_idx) {
1760+ _set_joypad_mapping (joy, joy.mapping - removed_idx_size);
1761+ continue ; // Simple offset fix.
1762+ }
1763+
1764+ // removed_idx is in reverse order (ie. high to low), because the first loop is in reverse order.
1765+ for (int i = 0 ; i < removed_idx.size (); i++) {
1766+ if (removed_idx[i] == joy.mapping ) {
1767+ // Set to fallback_mapping, if defined, else unmap the joypad.
1768+ // Currently, the fallback_mapping is only set internally, and only for Android.
1769+ _set_joypad_mapping (joy, fallback_mapping);
1770+ break ;
1771+ }
1772+ if (removed_idx[i] < joy.mapping ) {
1773+ // Complex offset fix:
1774+ // This mapping was shifted by `(removed_idx_size - i)` deletions.
1775+ _set_joypad_mapping (joy, joy.mapping - (removed_idx_size - i));
1776+ break ;
17581777 }
17591778 }
17601779 }
0 commit comments