diff options
| author | bunnei <bunneidev@gmail.com> | 2020-12-30 22:24:30 -0800 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-12-30 22:24:30 -0800 | 
| commit | fb41c82aaa6f633fcf09108bc9e104c54313f191 (patch) | |
| tree | 5d1d536f4760d1a70dc2a2e371135078a3fd18f0 | |
| parent | 25d607f5f63929369fb74f386a920b69bb24f442 (diff) | |
| parent | aa4c7687eeaf79552b3563cd61172b0d6a7a99e1 (diff) | |
Merge pull request #5265 from german77/port5509
Port citra-emu/citra#5509 "Look at direction of analog axis travel instead of instantaneous sample"
| -rw-r--r-- | src/input_common/sdl/sdl_impl.cpp | 47 | 
1 files changed, 45 insertions, 2 deletions
| diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 0b531f698..d32eb732a 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp @@ -1030,11 +1030,44 @@ public:          }          return {};      } -    [[nodiscard]] std::optional<Common::ParamPackage> FromEvent(const SDL_Event& event) const { +    [[nodiscard]] std::optional<Common::ParamPackage> FromEvent(SDL_Event& event) {          switch (event.type) {          case SDL_JOYAXISMOTION: -            if (std::abs(event.jaxis.value / 32767.0) < 0.5) { +            if (!axis_memory.count(event.jaxis.which) || +                !axis_memory[event.jaxis.which].count(event.jaxis.axis)) { +                axis_memory[event.jaxis.which][event.jaxis.axis] = event.jaxis.value; +                axis_event_count[event.jaxis.which][event.jaxis.axis] = 1;                  break; +            } else { +                axis_event_count[event.jaxis.which][event.jaxis.axis]++; +                // The joystick and axis exist in our map if we take this branch, so no checks +                // needed +                if (std::abs( +                        (event.jaxis.value - axis_memory[event.jaxis.which][event.jaxis.axis]) / +                        32767.0) < 0.5) { +                    break; +                } else { +                    if (axis_event_count[event.jaxis.which][event.jaxis.axis] == 2 && +                        IsAxisAtPole(event.jaxis.value) && +                        IsAxisAtPole(axis_memory[event.jaxis.which][event.jaxis.axis])) { +                        // If we have exactly two events and both are near a pole, this is +                        // likely a digital input masquerading as an analog axis; Instead of +                        // trying to look at the direction the axis travelled, assume the first +                        // event was press and the second was release; This should handle most +                        // digital axes while deferring to the direction of travel for analog +                        // axes +                        event.jaxis.value = static_cast<Sint16>( +                            std::copysign(32767, axis_memory[event.jaxis.which][event.jaxis.axis])); +                    } else { +                        // There are more than two events, so this is likely a true analog axis, +                        // check the direction it travelled +                        event.jaxis.value = static_cast<Sint16>(std::copysign( +                            32767, +                            event.jaxis.value - axis_memory[event.jaxis.which][event.jaxis.axis])); +                    } +                    axis_memory.clear(); +                    axis_event_count.clear(); +                }              }              [[fallthrough]];          case SDL_JOYBUTTONUP: @@ -1043,6 +1076,16 @@ public:          }          return std::nullopt;      } + +private: +    // Determine whether an axis value is close to an extreme or center +    // Some controllers have a digital D-Pad as a pair of analog sticks, with 3 possible values per +    // axis, which is why the center must be considered a pole +    bool IsAxisAtPole(int16_t value) const { +        return std::abs(value) >= 32767 || std::abs(value) < 327; +    } +    std::unordered_map<SDL_JoystickID, std::unordered_map<uint8_t, int16_t>> axis_memory; +    std::unordered_map<SDL_JoystickID, std::unordered_map<uint8_t, uint32_t>> axis_event_count;  };  class SDLMotionPoller final : public SDLPoller { | 
