Port citra-emu/citra#5509
This commit is contained in:
		| @@ -1014,11 +1014,44 @@ public: | |||||||
|         } |         } | ||||||
|         return {}; |         return {}; | ||||||
|     } |     } | ||||||
|     [[nodiscard]] std::optional<Common::ParamPackage> FromEvent(const SDL_Event& event) const { |     [[nodiscard]] std::optional<Common::ParamPackage> FromEvent(SDL_Event& event) { | ||||||
|         switch (event.type) { |         switch (event.type) { | ||||||
|         case SDL_JOYAXISMOTION: |         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; |                 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]]; |             [[fallthrough]]; | ||||||
|         case SDL_JOYBUTTONUP: |         case SDL_JOYBUTTONUP: | ||||||
| @@ -1027,6 +1060,16 @@ public: | |||||||
|         } |         } | ||||||
|         return std::nullopt; |         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 { | class SDLMotionPoller final : public SDLPoller { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user