|
@@ -85,16 +85,17 @@ public:
|
|
|
using std::chrono::milliseconds;
|
|
using std::chrono::milliseconds;
|
|
|
using std::chrono::steady_clock;
|
|
using std::chrono::steady_clock;
|
|
|
|
|
|
|
|
- // Prevent vibrations less than 10ms apart from each other.
|
|
|
|
|
- if (duration_cast<milliseconds>(steady_clock::now() - last_vibration) < milliseconds(10)) {
|
|
|
|
|
|
|
+ // Block non-zero vibrations less than 10ms apart from each other.
|
|
|
|
|
+ if ((amp_low != 0 || amp_high != 0) &&
|
|
|
|
|
+ duration_cast<milliseconds>(steady_clock::now() - last_vibration) < milliseconds(10)) {
|
|
|
return false;
|
|
return false;
|
|
|
- };
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
last_vibration = steady_clock::now();
|
|
last_vibration = steady_clock::now();
|
|
|
|
|
|
|
|
- if (sdl_controller != nullptr) {
|
|
|
|
|
|
|
+ if (sdl_controller) {
|
|
|
return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0;
|
|
return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0;
|
|
|
- } else if (sdl_joystick != nullptr) {
|
|
|
|
|
|
|
+ } else if (sdl_joystick) {
|
|
|
return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0;
|
|
return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -321,14 +322,6 @@ public:
|
|
|
return joystick->GetButton(button);
|
|
return joystick->GetButton(button);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override {
|
|
|
|
|
- const u16 processed_amp_low =
|
|
|
|
|
- static_cast<u16>(pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f)) * 0xFFFF);
|
|
|
|
|
- const u16 processed_amp_high =
|
|
|
|
|
- static_cast<u16>(pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f)) * 0xFFFF);
|
|
|
|
|
- return joystick->RumblePlay(processed_amp_low, processed_amp_high);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
private:
|
|
private:
|
|
|
std::shared_ptr<SDLJoystick> joystick;
|
|
std::shared_ptr<SDLJoystick> joystick;
|
|
|
int button;
|
|
int button;
|
|
@@ -412,6 +405,32 @@ private:
|
|
|
const float range;
|
|
const float range;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+class SDLVibration final : public Input::VibrationDevice {
|
|
|
|
|
+public:
|
|
|
|
|
+ explicit SDLVibration(std::shared_ptr<SDLJoystick> joystick_)
|
|
|
|
|
+ : joystick(std::move(joystick_)) {}
|
|
|
|
|
+
|
|
|
|
|
+ u8 GetStatus() const override {
|
|
|
|
|
+ joystick->RumblePlay(1, 1);
|
|
|
|
|
+ return joystick->RumblePlay(0, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override {
|
|
|
|
|
+ const auto process_amplitude = [](f32 amplitude) {
|
|
|
|
|
+ return static_cast<u16>(std::pow(amplitude, 0.5f) *
|
|
|
|
|
+ (3.0f - 2.0f * std::pow(amplitude, 0.15f)) * 0xFFFF);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const auto processed_amp_low = process_amplitude(amp_low);
|
|
|
|
|
+ const auto processed_amp_high = process_amplitude(amp_high);
|
|
|
|
|
+
|
|
|
|
|
+ return joystick->RumblePlay(processed_amp_low, processed_amp_high);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+private:
|
|
|
|
|
+ std::shared_ptr<SDLJoystick> joystick;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
class SDLDirectionMotion final : public Input::MotionDevice {
|
|
class SDLDirectionMotion final : public Input::MotionDevice {
|
|
|
public:
|
|
public:
|
|
|
explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
|
|
explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
|
|
@@ -554,7 +573,7 @@ class SDLAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
|
|
|
public:
|
|
public:
|
|
|
explicit SDLAnalogFactory(SDLState& state_) : state(state_) {}
|
|
explicit SDLAnalogFactory(SDLState& state_) : state(state_) {}
|
|
|
/**
|
|
/**
|
|
|
- * Creates analog device from joystick axes
|
|
|
|
|
|
|
+ * Creates an analog device from joystick axes
|
|
|
* @param params contains parameters for creating the device:
|
|
* @param params contains parameters for creating the device:
|
|
|
* - "guid": the guid of the joystick to bind
|
|
* - "guid": the guid of the joystick to bind
|
|
|
* - "port": the nth joystick of the same type
|
|
* - "port": the nth joystick of the same type
|
|
@@ -580,6 +599,26 @@ private:
|
|
|
SDLState& state;
|
|
SDLState& state;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+/// An vibration device factory that creates vibration devices from SDL joystick
|
|
|
|
|
+class SDLVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
|
|
|
|
|
+public:
|
|
|
|
|
+ explicit SDLVibrationFactory(SDLState& state_) : state(state_) {}
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Creates a vibration device from a joystick
|
|
|
|
|
+ * @param params contains parameters for creating the device:
|
|
|
|
|
+ * - "guid": the guid of the joystick to bind
|
|
|
|
|
+ * - "port": the nth joystick of the same type
|
|
|
|
|
+ */
|
|
|
|
|
+ std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override {
|
|
|
|
|
+ const std::string guid = params.Get("guid", "0");
|
|
|
|
|
+ const int port = params.Get("port", 0);
|
|
|
|
|
+ return std::make_unique<SDLVibration>(state.GetSDLJoystickByGUID(guid, port));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+private:
|
|
|
|
|
+ SDLState& state;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
/// A motion device factory that creates motion devices from SDL joystick
|
|
/// A motion device factory that creates motion devices from SDL joystick
|
|
|
class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> {
|
|
class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> {
|
|
|
public:
|
|
public:
|
|
@@ -646,11 +685,13 @@ private:
|
|
|
|
|
|
|
|
SDLState::SDLState() {
|
|
SDLState::SDLState() {
|
|
|
using namespace Input;
|
|
using namespace Input;
|
|
|
- analog_factory = std::make_shared<SDLAnalogFactory>(*this);
|
|
|
|
|
button_factory = std::make_shared<SDLButtonFactory>(*this);
|
|
button_factory = std::make_shared<SDLButtonFactory>(*this);
|
|
|
|
|
+ analog_factory = std::make_shared<SDLAnalogFactory>(*this);
|
|
|
|
|
+ vibration_factory = std::make_shared<SDLVibrationFactory>(*this);
|
|
|
motion_factory = std::make_shared<SDLMotionFactory>(*this);
|
|
motion_factory = std::make_shared<SDLMotionFactory>(*this);
|
|
|
- RegisterFactory<AnalogDevice>("sdl", analog_factory);
|
|
|
|
|
RegisterFactory<ButtonDevice>("sdl", button_factory);
|
|
RegisterFactory<ButtonDevice>("sdl", button_factory);
|
|
|
|
|
+ RegisterFactory<AnalogDevice>("sdl", analog_factory);
|
|
|
|
|
+ RegisterFactory<VibrationDevice>("sdl", vibration_factory);
|
|
|
RegisterFactory<MotionDevice>("sdl", motion_factory);
|
|
RegisterFactory<MotionDevice>("sdl", motion_factory);
|
|
|
|
|
|
|
|
// If the frontend is going to manage the event loop, then we don't start one here
|
|
// If the frontend is going to manage the event loop, then we don't start one here
|
|
@@ -687,6 +728,7 @@ SDLState::~SDLState() {
|
|
|
using namespace Input;
|
|
using namespace Input;
|
|
|
UnregisterFactory<ButtonDevice>("sdl");
|
|
UnregisterFactory<ButtonDevice>("sdl");
|
|
|
UnregisterFactory<AnalogDevice>("sdl");
|
|
UnregisterFactory<AnalogDevice>("sdl");
|
|
|
|
|
+ UnregisterFactory<VibrationDevice>("sdl");
|
|
|
UnregisterFactory<MotionDevice>("sdl");
|
|
UnregisterFactory<MotionDevice>("sdl");
|
|
|
|
|
|
|
|
CloseJoysticks();
|
|
CloseJoysticks();
|