summaryrefslogtreecommitdiffstats
path: root/src/input_common
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common')
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp6
-rw-r--r--src/input_common/gcadapter/gc_adapter.h4
-rw-r--r--src/input_common/gcadapter/gc_poller.cpp50
-rw-r--r--src/input_common/gcadapter/gc_poller.h11
-rw-r--r--src/input_common/main.cpp5
-rw-r--r--src/input_common/sdl/sdl_impl.cpp74
-rw-r--r--src/input_common/sdl/sdl_impl.h2
-rw-r--r--src/input_common/settings.cpp21
-rw-r--r--src/input_common/settings.h32
9 files changed, 159 insertions, 46 deletions
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp
index b912188b6..d80195c82 100644
--- a/src/input_common/gcadapter/gc_adapter.cpp
+++ b/src/input_common/gcadapter/gc_adapter.cpp
@@ -230,10 +230,8 @@ void Adapter::SendVibrations() {
vibration_changed = false;
}
-bool Adapter::RumblePlay(std::size_t port, f32 amplitude) {
- amplitude = std::clamp(amplitude, 0.0f, 1.0f);
- const auto raw_amp = static_cast<u8>(amplitude * 0x8);
- pads[port].rumble_amplitude = raw_amp;
+bool Adapter::RumblePlay(std::size_t port, u8 amplitude) {
+ pads[port].rumble_amplitude = amplitude;
return rumble_enabled;
}
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h
index d28dcfad3..f1256c9da 100644
--- a/src/input_common/gcadapter/gc_adapter.h
+++ b/src/input_common/gcadapter/gc_adapter.h
@@ -77,8 +77,8 @@ public:
Adapter();
~Adapter();
- /// Request a vibration for a controlelr
- bool RumblePlay(std::size_t port, f32 amplitude);
+ /// Request a vibration for a controller
+ bool RumblePlay(std::size_t port, u8 amplitude);
/// Used for polling
void BeginConfiguration();
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp
index 6bd6f57fc..fe57c13a5 100644
--- a/src/input_common/gcadapter/gc_poller.cpp
+++ b/src/input_common/gcadapter/gc_poller.cpp
@@ -15,7 +15,7 @@ namespace InputCommon {
class GCButton final : public Input::ButtonDevice {
public:
- explicit GCButton(u32 port_, s32 button_, GCAdapter::Adapter* adapter)
+ explicit GCButton(u32 port_, s32 button_, const GCAdapter::Adapter* adapter)
: port(port_), button(button_), gcadapter(adapter) {}
~GCButton() override;
@@ -27,18 +27,10 @@ public:
return false;
}
- bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override {
- const float amplitude = amp_high + amp_low > 2.0f ? 1.0f : (amp_high + amp_low) * 0.5f;
- const auto new_amp =
- static_cast<f32>(pow(amplitude, 0.5f) * (3.0f - 2.0f * pow(amplitude, 0.15f)));
-
- return gcadapter->RumblePlay(port, new_amp);
- }
-
private:
const u32 port;
const s32 button;
- GCAdapter::Adapter* gcadapter;
+ const GCAdapter::Adapter* gcadapter;
};
class GCAxisButton final : public Input::ButtonDevice {
@@ -299,4 +291,42 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
return params;
}
+class GCVibration final : public Input::VibrationDevice {
+public:
+ explicit GCVibration(u32 port_, GCAdapter::Adapter* adapter)
+ : port(port_), gcadapter(adapter) {}
+
+ u8 GetStatus() const override {
+ return gcadapter->RumblePlay(port, 0);
+ }
+
+ bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override {
+ const auto mean_amplitude = (amp_low + amp_high) * 0.5f;
+ const auto processed_amplitude = static_cast<u8>(
+ pow(mean_amplitude, 0.5f) * (3.0f - 2.0f * pow(mean_amplitude, 0.15f)) * 0x8);
+
+ return gcadapter->RumblePlay(port, processed_amplitude);
+ }
+
+private:
+ const u32 port;
+ GCAdapter::Adapter* gcadapter;
+};
+
+/// An vibration device factory that creates vibration devices from GC Adapter
+GCVibrationFactory::GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
+ : adapter(std::move(adapter_)) {}
+
+/**
+ * Creates a vibration device from a joystick
+ * @param params contains parameters for creating the device:
+ * - "port": the nth gcpad on the adapter
+ */
+std::unique_ptr<Input::VibrationDevice> GCVibrationFactory::Create(
+ const Common::ParamPackage& params) {
+ const auto port = static_cast<u32>(params.Get("port", 0));
+
+ return std::make_unique<GCVibration>(port, adapter.get());
+}
+
} // namespace InputCommon
diff --git a/src/input_common/gcadapter/gc_poller.h b/src/input_common/gcadapter/gc_poller.h
index 0527f328f..d1271e3ea 100644
--- a/src/input_common/gcadapter/gc_poller.h
+++ b/src/input_common/gcadapter/gc_poller.h
@@ -64,4 +64,15 @@ private:
bool polling = false;
};
+/// A vibration device factory creates vibration devices from GC Adapter
+class GCVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
+public:
+ explicit GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_);
+
+ std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override;
+
+private:
+ std::shared_ptr<GCAdapter::Adapter> adapter;
+};
+
} // namespace InputCommon
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index b438482cc..e59ad4ff5 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -28,6 +28,8 @@ struct InputSubsystem::Impl {
Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons);
gcanalog = std::make_shared<GCAnalogFactory>(gcadapter);
Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog);
+ gcvibration = std::make_shared<GCVibrationFactory>(gcadapter);
+ Input::RegisterFactory<Input::VibrationDevice>("gcpad", gcvibration);
keyboard = std::make_shared<Keyboard>();
Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
@@ -64,9 +66,11 @@ struct InputSubsystem::Impl {
#endif
Input::UnregisterFactory<Input::ButtonDevice>("gcpad");
Input::UnregisterFactory<Input::AnalogDevice>("gcpad");
+ Input::UnregisterFactory<Input::VibrationDevice>("gcpad");
gcbuttons.reset();
gcanalog.reset();
+ gcvibration.reset();
Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp");
@@ -142,6 +146,7 @@ struct InputSubsystem::Impl {
#endif
std::shared_ptr<GCButtonFactory> gcbuttons;
std::shared_ptr<GCAnalogFactory> gcanalog;
+ std::shared_ptr<GCVibrationFactory> gcvibration;
std::shared_ptr<UDPMotionFactory> udpmotion;
std::shared_ptr<UDPTouchFactory> udptouch;
std::shared_ptr<CemuhookUDP::Client> udp;
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index 18fb2ac5e..a2a83cdc9 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -85,16 +85,17 @@ public:
using std::chrono::milliseconds;
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;
- };
+ }
last_vibration = steady_clock::now();
- if (sdl_controller != nullptr) {
+ if (sdl_controller) {
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;
}
@@ -321,14 +322,6 @@ public:
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:
std::shared_ptr<SDLJoystick> joystick;
int button;
@@ -412,6 +405,32 @@ private:
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 {
public:
explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
@@ -554,7 +573,7 @@ class SDLAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
public:
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:
* - "guid": the guid of the joystick to bind
* - "port": the nth joystick of the same type
@@ -580,6 +599,26 @@ private:
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
class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> {
public:
@@ -646,11 +685,13 @@ private:
SDLState::SDLState() {
using namespace Input;
- analog_factory = std::make_shared<SDLAnalogFactory>(*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);
- RegisterFactory<AnalogDevice>("sdl", analog_factory);
RegisterFactory<ButtonDevice>("sdl", button_factory);
+ RegisterFactory<AnalogDevice>("sdl", analog_factory);
+ RegisterFactory<VibrationDevice>("sdl", vibration_factory);
RegisterFactory<MotionDevice>("sdl", motion_factory);
// 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;
UnregisterFactory<ButtonDevice>("sdl");
UnregisterFactory<AnalogDevice>("sdl");
+ UnregisterFactory<VibrationDevice>("sdl");
UnregisterFactory<MotionDevice>("sdl");
CloseJoysticks();
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h
index b9bb4dc56..08044b00d 100644
--- a/src/input_common/sdl/sdl_impl.h
+++ b/src/input_common/sdl/sdl_impl.h
@@ -22,6 +22,7 @@ namespace InputCommon::SDL {
class SDLAnalogFactory;
class SDLButtonFactory;
class SDLMotionFactory;
+class SDLVibrationFactory;
class SDLJoystick;
class SDLState : public State {
@@ -72,6 +73,7 @@ private:
std::shared_ptr<SDLButtonFactory> button_factory;
std::shared_ptr<SDLAnalogFactory> analog_factory;
+ std::shared_ptr<SDLVibrationFactory> vibration_factory;
std::shared_ptr<SDLMotionFactory> motion_factory;
bool start_thread = false;
diff --git a/src/input_common/settings.cpp b/src/input_common/settings.cpp
index b66c05856..557e7a9a0 100644
--- a/src/input_common/settings.cpp
+++ b/src/input_common/settings.cpp
@@ -14,13 +14,6 @@ const std::array<const char*, NumButtons> mapping = {{
}};
}
-namespace NativeMotion {
-const std::array<const char*, NumMotions> mapping = {{
- "motionleft",
- "motionright",
-}};
-}
-
namespace NativeAnalog {
const std::array<const char*, NumAnalogs> mapping = {{
"lstick",
@@ -28,6 +21,20 @@ const std::array<const char*, NumAnalogs> mapping = {{
}};
}
+namespace NativeVibration {
+const std::array<const char*, NumVibrations> mapping = {{
+ "left_vibration_device",
+ "right_vibration_device",
+}};
+}
+
+namespace NativeMotion {
+const std::array<const char*, NumMotions> mapping = {{
+ "motionleft",
+ "motionright",
+}};
+}
+
namespace NativeMouseButton {
const std::array<const char*, NumMouseButtons> mapping = {{
"left",
diff --git a/src/input_common/settings.h b/src/input_common/settings.h
index 2763ed991..75486554b 100644
--- a/src/input_common/settings.h
+++ b/src/input_common/settings.h
@@ -66,17 +66,32 @@ constexpr int NUM_STICKS_HID = NumAnalogs;
extern const std::array<const char*, NumAnalogs> mapping;
} // namespace NativeAnalog
+namespace NativeVibration {
+enum Values : int {
+ LeftVibrationDevice,
+ RightVibrationDevice,
+
+ NumVibrations,
+};
+
+constexpr int VIBRATION_HID_BEGIN = LeftVibrationDevice;
+constexpr int VIBRATION_HID_END = NumVibrations;
+constexpr int NUM_VIBRATIONS_HID = NumVibrations;
+
+extern const std::array<const char*, NumVibrations> mapping;
+}; // namespace NativeVibration
+
namespace NativeMotion {
enum Values : int {
- MOTIONLEFT,
- MOTIONRIGHT,
+ MotionLeft,
+ MotionRight,
NumMotions,
};
-constexpr int MOTION_HID_BEGIN = MOTIONLEFT;
+constexpr int MOTION_HID_BEGIN = MotionLeft;
constexpr int MOTION_HID_END = NumMotions;
-constexpr int NUM_MOTION_HID = NumMotions;
+constexpr int NUM_MOTIONS_HID = NumMotions;
extern const std::array<const char*, NumMotions> mapping;
} // namespace NativeMotion
@@ -305,9 +320,11 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
} // namespace NativeKeyboard
-using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
-using MotionRaw = std::array<std::string, NativeMotion::NumMotions>;
+using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
+using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>;
+using VibrationsRaw = std::array<std::string, NativeVibration::NumVibrations>;
+
using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
@@ -330,7 +347,8 @@ struct PlayerInput {
ControllerType controller_type;
ButtonsRaw buttons;
AnalogsRaw analogs;
- MotionRaw motions;
+ VibrationsRaw vibrations;
+ MotionsRaw motions;
bool vibration_enabled;
int vibration_strength;