diff options
author | bunnei <bunneidev@gmail.com> | 2020-11-18 05:02:27 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-18 05:02:27 +0100 |
commit | abda36636245c416a75774165d2a5b49610952fc (patch) | |
tree | 0bf3bab90e2155a3a16ffa21eabbc2a4c8f9d39d /src/input_common | |
parent | Merge pull request #4933 from lioncash/nodisc-gpu (diff) | |
parent | sdl_impl: Pump SDL Events at 1000 Hz (diff) | |
download | yuzu-abda36636245c416a75774165d2a5b49610952fc.tar yuzu-abda36636245c416a75774165d2a5b49610952fc.tar.gz yuzu-abda36636245c416a75774165d2a5b49610952fc.tar.bz2 yuzu-abda36636245c416a75774165d2a5b49610952fc.tar.lz yuzu-abda36636245c416a75774165d2a5b49610952fc.tar.xz yuzu-abda36636245c416a75774165d2a5b49610952fc.tar.zst yuzu-abda36636245c416a75774165d2a5b49610952fc.zip |
Diffstat (limited to 'src/input_common')
-rw-r--r-- | src/input_common/gcadapter/gc_adapter.cpp | 6 | ||||
-rw-r--r-- | src/input_common/gcadapter/gc_adapter.h | 4 | ||||
-rw-r--r-- | src/input_common/gcadapter/gc_poller.cpp | 50 | ||||
-rw-r--r-- | src/input_common/gcadapter/gc_poller.h | 11 | ||||
-rw-r--r-- | src/input_common/main.cpp | 15 | ||||
-rw-r--r-- | src/input_common/sdl/sdl_impl.cpp | 138 | ||||
-rw-r--r-- | src/input_common/sdl/sdl_impl.h | 2 | ||||
-rw-r--r-- | src/input_common/settings.cpp | 21 | ||||
-rw-r--r-- | src/input_common/settings.h | 35 | ||||
-rw-r--r-- | src/input_common/udp/client.cpp | 2 |
10 files changed, 177 insertions, 107 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 d32fd8b81..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"); @@ -78,7 +82,7 @@ struct InputSubsystem::Impl { [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { std::vector<Common::ParamPackage> devices = { Common::ParamPackage{{"display", "Any"}, {"class", "any"}}, - Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}}, + Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "keyboard"}}, }; #ifdef HAVE_SDL2 auto sdl_devices = sdl->GetInputDevices(); @@ -96,10 +100,6 @@ struct InputSubsystem::Impl { if (!params.Has("class") || params.Get("class", "") == "any") { return {}; } - if (params.Get("class", "") == "key") { - // TODO consider returning the SDL key codes for the default keybindings - return {}; - } if (params.Get("class", "") == "gcpad") { return gcadapter->GetAnalogMappingForDevice(params); } @@ -116,10 +116,6 @@ struct InputSubsystem::Impl { if (!params.Has("class") || params.Get("class", "") == "any") { return {}; } - if (params.Get("class", "") == "key") { - // TODO consider returning the SDL key codes for the default keybindings - return {}; - } if (params.Get("class", "") == "gcpad") { return gcadapter->GetButtonMappingForDevice(params); } @@ -150,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 10883e2d9..8c48bb861 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp @@ -80,30 +80,13 @@ public: return static_cast<float>(state.axes.at(axis)) / (32767.0f * range); } - bool RumblePlay(f32 amp_low, f32 amp_high, u32 time) { - const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF); - const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF); - // Lower drastically the number of state changes - if (raw_amp_low >> 11 == last_state_rumble_low >> 11 && - raw_amp_high >> 11 == last_state_rumble_high >> 11) { - if (raw_amp_low + raw_amp_high != 0 || - last_state_rumble_low + last_state_rumble_high == 0) { - return false; - } - } - // Don't change state if last vibration was < 20ms - const auto now = std::chrono::system_clock::now(); - if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_vibration) < - std::chrono::milliseconds(20)) { - return raw_amp_low + raw_amp_high == 0; + bool RumblePlay(u16 amp_low, u16 amp_high) { + if (sdl_controller) { + return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0; + } else if (sdl_joystick) { + return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0; } - last_vibration = now; - last_state_rumble_low = raw_amp_low; - last_state_rumble_high = raw_amp_high; - if (sdl_joystick) { - SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time); - } return false; } @@ -172,9 +155,6 @@ private: } state; std::string guid; int port; - u16 last_state_rumble_high = 0; - u16 last_state_rumble_low = 0; - std::chrono::time_point<std::chrono::system_clock> last_vibration; std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; mutable std::mutex mutex; @@ -327,12 +307,6 @@ public: return joystick->GetButton(button); } - bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override { - const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f)); - const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f)); - return joystick->RumblePlay(new_amp_low, new_amp_high, 250); - } - private: std::shared_ptr<SDLJoystick> joystick; int button; @@ -416,6 +390,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_) @@ -558,7 +558,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 @@ -584,6 +584,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: @@ -650,11 +670,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 @@ -676,7 +698,7 @@ SDLState::SDLState() { using namespace std::chrono_literals; while (initialized) { SDL_PumpEvents(); - std::this_thread::sleep_for(5ms); + std::this_thread::sleep_for(1ms); } }); } @@ -691,6 +713,7 @@ SDLState::~SDLState() { using namespace Input; UnregisterFactory<ButtonDevice>("sdl"); UnregisterFactory<AnalogDevice>("sdl"); + UnregisterFactory<VibrationDevice>("sdl"); UnregisterFactory<MotionDevice>("sdl"); CloseJoysticks(); @@ -1045,7 +1068,6 @@ public: void Start(const std::string& device_id) override { SDLPoller::Start(device_id); - // Load the game controller // Reset stored axes analog_x_axis = -1; analog_y_axis = -1; @@ -1058,40 +1080,21 @@ public: if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) { continue; } - // Simplify controller config by testing if game controller support is enabled. if (event.type == SDL_JOYAXISMOTION) { const auto axis = event.jaxis.axis; - if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); - auto* const controller = joystick->GetSDLGameController()) { - const auto axis_left_x = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) - .value.axis; - const auto axis_left_y = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) - .value.axis; - const auto axis_right_x = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX) - .value.axis; - const auto axis_right_y = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY) - .value.axis; - - if (axis == axis_left_x || axis == axis_left_y) { - analog_x_axis = axis_left_x; - analog_y_axis = axis_left_y; - break; - } else if (axis == axis_right_x || axis == axis_right_y) { - analog_x_axis = axis_right_x; - analog_y_axis = axis_right_y; - break; - } + // In order to return a complete analog param, we need inputs for both axes. + // First we take the x-axis (horizontal) input, then the y-axis (vertical) input. + if (analog_x_axis == -1) { + analog_x_axis = axis; + } else if (analog_y_axis == -1 && analog_x_axis != axis) { + analog_y_axis = axis; + } + } else { + // If the press wasn't accepted as a joy axis, check for a button press + auto button_press = button_poller.FromEvent(event); + if (button_press) { + return *button_press; } - } - - // If the press wasn't accepted as a joy axis, check for a button press - auto button_press = button_poller.FromEvent(event); - if (button_press) { - return *button_press; } } @@ -1104,6 +1107,7 @@ public: return params; } } + return {}; } 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 f52d28540..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,11 @@ struct PlayerInput { ControllerType controller_type; ButtonsRaw buttons; AnalogsRaw analogs; - MotionRaw motions; + VibrationsRaw vibrations; + MotionsRaw motions; + + bool vibration_enabled; + int vibration_strength; u32 body_color_left; u32 body_color_right; diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index 7039d6fc3..3677e79ca 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp @@ -344,7 +344,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, }; Socket socket{host, port, pad_index, client_id, std::move(callback)}; std::thread worker_thread{SocketLoop, &socket}; - const bool result = success_event.WaitFor(std::chrono::seconds(8)); + const bool result = success_event.WaitFor(std::chrono::seconds(5)); socket.Stop(); worker_thread.join(); if (result) { |