/* This file is part of Flycast. Flycast is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Flycast is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Flycast. If not, see . */ #pragma once #include "input/gamepad_device.h" #include "input/mouse.h" #include "sdl.h" class SDLGamepad : public GamepadDevice { public: SDLGamepad(int maple_port, int joystick_idx, SDL_Joystick *sdl_joystick); void set_maple_port(int port) override; bool gamepad_axis_input(u32 code, int value) override { if (isHalfAxis(code)) value = std::min((32768 + value * axisDirection[code]) / 2, 32767); return GamepadDevice::gamepad_axis_input(code, value); } void rumble(float power, float inclination, u32 duration_ms) override; void update_rumble() override; void setSine(float power, float freq, u32 duration_ms); void setTorque(float torque); void setSpring(float saturation, float speed); void setDamper(float param, float speed); void stopHaptic(); void close(); const char *get_button_name(u32 code) override; const char *get_axis_name(u32 code) override; std::shared_ptr getDefaultMapping() override; void resetMappingToDefault(bool arcade, bool gamepad) override; static void AddSDLGamepad(std::shared_ptr gamepad) { sdl_gamepads[gamepad->sdl_joystick_instance] = gamepad; GamepadDevice::Register(gamepad); } static std::shared_ptr GetSDLGamepad(SDL_JoystickID id) { auto it = sdl_gamepads.find(id); if (it != sdl_gamepads.end()) return it->second; else return NULL; } static void closeAllGamepads() { while (!sdl_gamepads.empty()) sdl_gamepads.begin()->second->close(); } static void UpdateRumble() { for (auto &[k, gamepad] : sdl_gamepads) gamepad->update_rumble(); } static void SetTorque(int port, float torque) { applyToPort(port, &SDLGamepad::setTorque, torque); } static void SetSpring(int port, float saturation, float speed) { applyToPort(port, &SDLGamepad::setSpring, saturation, speed); } static void SetDamper(int port, float param, float speed) { applyToPort(port, &SDLGamepad::setDamper, param, speed); } static void SetSine(int port, float power, float freq, u32 duration_ms) { applyToPort(port, &SDLGamepad::setSine, power, freq, duration_ms); } static void StopHaptic(int port) { applyToPort(port, &SDLGamepad::stopHaptic); } protected: u64 vib_stop_time = 0; SDL_JoystickID sdl_joystick_instance; private: template static void applyToPort(int port, Func func, Args&&... args) { for (auto &[k, gamepad] : sdl_gamepads) if (gamepad->maple_port() == port) ((*gamepad).*func)(std::forward(args)...); } u16 getRumbleIntensity(float power) const; void doRumble(float power, u32 duration_ms); SDL_Joystick* sdl_joystick; float vib_inclination = 0; SDL_GameController *sdl_controller = nullptr; std::unordered_map axisDirection; static std::map> sdl_gamepads; SDL_Haptic *haptic = nullptr; bool hapticRumble = false; bool hasAutocenter = false; bool isWheel = false; int sineEffectId = -1; int constEffectId = -1; int springEffectId = -1; int damperEffectId = -1; }; class SDLMouse : public Mouse { public: SDLMouse(u64 mouseId); void setAbsPos(int x, int y); };