diff options
| author | 2020-12-30 22:24:30 -0800 | |
|---|---|---|
| committer | 2020-12-30 22:24:30 -0800 | |
| commit | fb41c82aaa6f633fcf09108bc9e104c54313f191 (patch) | |
| tree | 5d1d536f4760d1a70dc2a2e371135078a3fd18f0 /src/input_common/sdl/sdl_impl.cpp | |
| parent | Merge pull request #5208 from bunnei/service-threads (diff) | |
| parent | Port citra-emu/citra#5509 (diff) | |
| download | yuzu-fb41c82aaa6f633fcf09108bc9e104c54313f191.tar.gz yuzu-fb41c82aaa6f633fcf09108bc9e104c54313f191.tar.xz yuzu-fb41c82aaa6f633fcf09108bc9e104c54313f191.zip | |
Merge pull request #5265 from german77/port5509
Port citra-emu/citra#5509 "Look at direction of analog axis travel instead of instantaneous sample"
Diffstat (limited to 'src/input_common/sdl/sdl_impl.cpp')
| -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: | |||
| 1030 | } | 1030 | } |
| 1031 | return {}; | 1031 | return {}; |
| 1032 | } | 1032 | } |
| 1033 | [[nodiscard]] std::optional<Common::ParamPackage> FromEvent(const SDL_Event& event) const { | 1033 | [[nodiscard]] std::optional<Common::ParamPackage> FromEvent(SDL_Event& event) { |
| 1034 | switch (event.type) { | 1034 | switch (event.type) { |
| 1035 | case SDL_JOYAXISMOTION: | 1035 | case SDL_JOYAXISMOTION: |
| 1036 | if (std::abs(event.jaxis.value / 32767.0) < 0.5) { | 1036 | if (!axis_memory.count(event.jaxis.which) || |
| 1037 | !axis_memory[event.jaxis.which].count(event.jaxis.axis)) { | ||
| 1038 | axis_memory[event.jaxis.which][event.jaxis.axis] = event.jaxis.value; | ||
| 1039 | axis_event_count[event.jaxis.which][event.jaxis.axis] = 1; | ||
| 1037 | break; | 1040 | break; |
| 1041 | } else { | ||
| 1042 | axis_event_count[event.jaxis.which][event.jaxis.axis]++; | ||
| 1043 | // The joystick and axis exist in our map if we take this branch, so no checks | ||
| 1044 | // needed | ||
| 1045 | if (std::abs( | ||
| 1046 | (event.jaxis.value - axis_memory[event.jaxis.which][event.jaxis.axis]) / | ||
| 1047 | 32767.0) < 0.5) { | ||
| 1048 | break; | ||
| 1049 | } else { | ||
| 1050 | if (axis_event_count[event.jaxis.which][event.jaxis.axis] == 2 && | ||
| 1051 | IsAxisAtPole(event.jaxis.value) && | ||
| 1052 | IsAxisAtPole(axis_memory[event.jaxis.which][event.jaxis.axis])) { | ||
| 1053 | // If we have exactly two events and both are near a pole, this is | ||
| 1054 | // likely a digital input masquerading as an analog axis; Instead of | ||
| 1055 | // trying to look at the direction the axis travelled, assume the first | ||
| 1056 | // event was press and the second was release; This should handle most | ||
| 1057 | // digital axes while deferring to the direction of travel for analog | ||
| 1058 | // axes | ||
| 1059 | event.jaxis.value = static_cast<Sint16>( | ||
| 1060 | std::copysign(32767, axis_memory[event.jaxis.which][event.jaxis.axis])); | ||
| 1061 | } else { | ||
| 1062 | // There are more than two events, so this is likely a true analog axis, | ||
| 1063 | // check the direction it travelled | ||
| 1064 | event.jaxis.value = static_cast<Sint16>(std::copysign( | ||
| 1065 | 32767, | ||
| 1066 | event.jaxis.value - axis_memory[event.jaxis.which][event.jaxis.axis])); | ||
| 1067 | } | ||
| 1068 | axis_memory.clear(); | ||
| 1069 | axis_event_count.clear(); | ||
| 1070 | } | ||
| 1038 | } | 1071 | } |
| 1039 | [[fallthrough]]; | 1072 | [[fallthrough]]; |
| 1040 | case SDL_JOYBUTTONUP: | 1073 | case SDL_JOYBUTTONUP: |
| @@ -1043,6 +1076,16 @@ public: | |||
| 1043 | } | 1076 | } |
| 1044 | return std::nullopt; | 1077 | return std::nullopt; |
| 1045 | } | 1078 | } |
| 1079 | |||
| 1080 | private: | ||
| 1081 | // Determine whether an axis value is close to an extreme or center | ||
| 1082 | // Some controllers have a digital D-Pad as a pair of analog sticks, with 3 possible values per | ||
| 1083 | // axis, which is why the center must be considered a pole | ||
| 1084 | bool IsAxisAtPole(int16_t value) const { | ||
| 1085 | return std::abs(value) >= 32767 || std::abs(value) < 327; | ||
| 1086 | } | ||
| 1087 | std::unordered_map<SDL_JoystickID, std::unordered_map<uint8_t, int16_t>> axis_memory; | ||
| 1088 | std::unordered_map<SDL_JoystickID, std::unordered_map<uint8_t, uint32_t>> axis_event_count; | ||
| 1046 | }; | 1089 | }; |
| 1047 | 1090 | ||
| 1048 | class SDLMotionPoller final : public SDLPoller { | 1091 | class SDLMotionPoller final : public SDLPoller { |