diff options
Diffstat (limited to 'src/input_common')
33 files changed, 1023 insertions, 232 deletions
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index d4fa69a77..2cf9eb97f 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt | |||
| @@ -1,4 +1,9 @@ | |||
| 1 | # SPDX-FileCopyrightText: 2018 yuzu Emulator Project | ||
| 2 | # SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 1 | add_library(input_common STATIC | 4 | add_library(input_common STATIC |
| 5 | drivers/camera.cpp | ||
| 6 | drivers/camera.h | ||
| 2 | drivers/gc_adapter.cpp | 7 | drivers/gc_adapter.cpp |
| 3 | drivers/gc_adapter.h | 8 | drivers/gc_adapter.h |
| 4 | drivers/keyboard.cpp | 9 | drivers/keyboard.cpp |
| @@ -13,6 +18,8 @@ add_library(input_common STATIC | |||
| 13 | drivers/touch_screen.h | 18 | drivers/touch_screen.h |
| 14 | drivers/udp_client.cpp | 19 | drivers/udp_client.cpp |
| 15 | drivers/udp_client.h | 20 | drivers/udp_client.h |
| 21 | drivers/virtual_amiibo.cpp | ||
| 22 | drivers/virtual_amiibo.h | ||
| 16 | helpers/stick_from_buttons.cpp | 23 | helpers/stick_from_buttons.cpp |
| 17 | helpers/stick_from_buttons.h | 24 | helpers/stick_from_buttons.h |
| 18 | helpers/touch_from_buttons.cpp | 25 | helpers/touch_from_buttons.cpp |
| @@ -44,7 +51,6 @@ else() | |||
| 44 | -Werror | 51 | -Werror |
| 45 | -Werror=conversion | 52 | -Werror=conversion |
| 46 | -Werror=ignored-qualifiers | 53 | -Werror=ignored-qualifiers |
| 47 | -Werror=shadow | ||
| 48 | $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> | 54 | $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> |
| 49 | $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable> | 55 | $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable> |
| 50 | -Werror=unused-variable | 56 | -Werror=unused-variable |
diff --git a/src/input_common/drivers/camera.cpp b/src/input_common/drivers/camera.cpp new file mode 100644 index 000000000..dceea67e0 --- /dev/null +++ b/src/input_common/drivers/camera.cpp | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <fmt/format.h> | ||
| 5 | |||
| 6 | #include "common/param_package.h" | ||
| 7 | #include "input_common/drivers/camera.h" | ||
| 8 | |||
| 9 | namespace InputCommon { | ||
| 10 | constexpr PadIdentifier identifier = { | ||
| 11 | .guid = Common::UUID{}, | ||
| 12 | .port = 0, | ||
| 13 | .pad = 0, | ||
| 14 | }; | ||
| 15 | |||
| 16 | Camera::Camera(std::string input_engine_) : InputEngine(std::move(input_engine_)) { | ||
| 17 | PreSetController(identifier); | ||
| 18 | } | ||
| 19 | |||
| 20 | void Camera::SetCameraData(std::size_t width, std::size_t height, std::vector<u32> data) { | ||
| 21 | const std::size_t desired_width = getImageWidth(); | ||
| 22 | const std::size_t desired_height = getImageHeight(); | ||
| 23 | status.data.resize(desired_width * desired_height); | ||
| 24 | |||
| 25 | // Resize image to desired format | ||
| 26 | for (std::size_t y = 0; y < desired_height; y++) { | ||
| 27 | for (std::size_t x = 0; x < desired_width; x++) { | ||
| 28 | const std::size_t pixel_index = y * desired_width + x; | ||
| 29 | const std::size_t old_x = width * x / desired_width; | ||
| 30 | const std::size_t old_y = height * y / desired_height; | ||
| 31 | const std::size_t data_pixel_index = old_y * width + old_x; | ||
| 32 | status.data[pixel_index] = static_cast<u8>(data[data_pixel_index] & 0xFF); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | SetCamera(identifier, status); | ||
| 37 | } | ||
| 38 | |||
| 39 | std::size_t Camera::getImageWidth() const { | ||
| 40 | switch (status.format) { | ||
| 41 | case Common::Input::CameraFormat::Size320x240: | ||
| 42 | return 320; | ||
| 43 | case Common::Input::CameraFormat::Size160x120: | ||
| 44 | return 160; | ||
| 45 | case Common::Input::CameraFormat::Size80x60: | ||
| 46 | return 80; | ||
| 47 | case Common::Input::CameraFormat::Size40x30: | ||
| 48 | return 40; | ||
| 49 | case Common::Input::CameraFormat::Size20x15: | ||
| 50 | return 20; | ||
| 51 | case Common::Input::CameraFormat::None: | ||
| 52 | default: | ||
| 53 | return 0; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | std::size_t Camera::getImageHeight() const { | ||
| 58 | switch (status.format) { | ||
| 59 | case Common::Input::CameraFormat::Size320x240: | ||
| 60 | return 240; | ||
| 61 | case Common::Input::CameraFormat::Size160x120: | ||
| 62 | return 120; | ||
| 63 | case Common::Input::CameraFormat::Size80x60: | ||
| 64 | return 60; | ||
| 65 | case Common::Input::CameraFormat::Size40x30: | ||
| 66 | return 30; | ||
| 67 | case Common::Input::CameraFormat::Size20x15: | ||
| 68 | return 15; | ||
| 69 | case Common::Input::CameraFormat::None: | ||
| 70 | default: | ||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | Common::Input::CameraError Camera::SetCameraFormat( | ||
| 76 | [[maybe_unused]] const PadIdentifier& identifier_, | ||
| 77 | const Common::Input::CameraFormat camera_format) { | ||
| 78 | status.format = camera_format; | ||
| 79 | return Common::Input::CameraError::None; | ||
| 80 | } | ||
| 81 | |||
| 82 | } // namespace InputCommon | ||
diff --git a/src/input_common/drivers/camera.h b/src/input_common/drivers/camera.h new file mode 100644 index 000000000..b8a7c75e5 --- /dev/null +++ b/src/input_common/drivers/camera.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "input_common/input_engine.h" | ||
| 7 | |||
| 8 | namespace InputCommon { | ||
| 9 | |||
| 10 | /** | ||
| 11 | * A button device factory representing a keyboard. It receives keyboard events and forward them | ||
| 12 | * to all button devices it created. | ||
| 13 | */ | ||
| 14 | class Camera final : public InputEngine { | ||
| 15 | public: | ||
| 16 | explicit Camera(std::string input_engine_); | ||
| 17 | |||
| 18 | void SetCameraData(std::size_t width, std::size_t height, std::vector<u32> data); | ||
| 19 | |||
| 20 | std::size_t getImageWidth() const; | ||
| 21 | std::size_t getImageHeight() const; | ||
| 22 | |||
| 23 | Common::Input::CameraError SetCameraFormat(const PadIdentifier& identifier_, | ||
| 24 | Common::Input::CameraFormat camera_format) override; | ||
| 25 | |||
| 26 | Common::Input::CameraStatus status{}; | ||
| 27 | }; | ||
| 28 | |||
| 29 | } // namespace InputCommon | ||
diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp index 155caae42..f4dd24e7d 100644 --- a/src/input_common/drivers/gc_adapter.cpp +++ b/src/input_common/drivers/gc_adapter.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2014 Dolphin Emulator Project | 1 | // SPDX-FileCopyrightText: 2014 Dolphin Emulator Project |
| 2 | // Licensed under GPLv2+ | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #include <fmt/format.h> | 4 | #include <fmt/format.h> |
| 6 | #include <libusb.h> | 5 | #include <libusb.h> |
| @@ -91,7 +90,7 @@ GCAdapter::~GCAdapter() { | |||
| 91 | 90 | ||
| 92 | void GCAdapter::AdapterInputThread(std::stop_token stop_token) { | 91 | void GCAdapter::AdapterInputThread(std::stop_token stop_token) { |
| 93 | LOG_DEBUG(Input, "Input thread started"); | 92 | LOG_DEBUG(Input, "Input thread started"); |
| 94 | Common::SetCurrentThreadName("yuzu:input:GCAdapter"); | 93 | Common::SetCurrentThreadName("GCAdapter"); |
| 95 | s32 payload_size{}; | 94 | s32 payload_size{}; |
| 96 | AdapterPayload adapter_payload{}; | 95 | AdapterPayload adapter_payload{}; |
| 97 | 96 | ||
| @@ -215,7 +214,7 @@ void GCAdapter::UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_ | |||
| 215 | } | 214 | } |
| 216 | 215 | ||
| 217 | void GCAdapter::AdapterScanThread(std::stop_token stop_token) { | 216 | void GCAdapter::AdapterScanThread(std::stop_token stop_token) { |
| 218 | Common::SetCurrentThreadName("yuzu:input:ScanGCAdapter"); | 217 | Common::SetCurrentThreadName("ScanGCAdapter"); |
| 219 | usb_adapter_handle = nullptr; | 218 | usb_adapter_handle = nullptr; |
| 220 | pads = {}; | 219 | pads = {}; |
| 221 | while (!stop_token.stop_requested() && !Setup()) { | 220 | while (!stop_token.stop_requested() && !Setup()) { |
| @@ -524,4 +523,20 @@ Common::Input::ButtonNames GCAdapter::GetUIName(const Common::ParamPackage& para | |||
| 524 | return Common::Input::ButtonNames::Invalid; | 523 | return Common::Input::ButtonNames::Invalid; |
| 525 | } | 524 | } |
| 526 | 525 | ||
| 526 | bool GCAdapter::IsStickInverted(const Common::ParamPackage& params) { | ||
| 527 | if (!params.Has("port")) { | ||
| 528 | return false; | ||
| 529 | } | ||
| 530 | |||
| 531 | const auto x_axis = static_cast<PadAxes>(params.Get("axis_x", 0)); | ||
| 532 | const auto y_axis = static_cast<PadAxes>(params.Get("axis_y", 0)); | ||
| 533 | if (x_axis != PadAxes::StickY && x_axis != PadAxes::SubstickY) { | ||
| 534 | return false; | ||
| 535 | } | ||
| 536 | if (y_axis != PadAxes::StickX && y_axis != PadAxes::SubstickX) { | ||
| 537 | return false; | ||
| 538 | } | ||
| 539 | return true; | ||
| 540 | } | ||
| 541 | |||
| 527 | } // namespace InputCommon | 542 | } // namespace InputCommon |
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h index 7ce1912a3..8682da847 100644 --- a/src/input_common/drivers/gc_adapter.h +++ b/src/input_common/drivers/gc_adapter.h | |||
| @@ -1,12 +1,10 @@ | |||
| 1 | // Copyright 2014 Dolphin Emulator Project | 1 | // SPDX-FileCopyrightText: 2014 Dolphin Emulator Project |
| 2 | // Licensed under GPLv2+ | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
| 7 | #include <array> | 6 | #include <array> |
| 8 | #include <memory> | 7 | #include <memory> |
| 9 | #include <mutex> | ||
| 10 | #include <stop_token> | 8 | #include <stop_token> |
| 11 | #include <string> | 9 | #include <string> |
| 12 | #include <thread> | 10 | #include <thread> |
| @@ -36,6 +34,8 @@ public: | |||
| 36 | AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; | 34 | AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; |
| 37 | Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override; | 35 | Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override; |
| 38 | 36 | ||
| 37 | bool IsStickInverted(const Common::ParamPackage& params) override; | ||
| 38 | |||
| 39 | private: | 39 | private: |
| 40 | enum class PadButton { | 40 | enum class PadButton { |
| 41 | Undefined = 0x0000, | 41 | Undefined = 0x0000, |
diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp index 59e3d9cc0..71e612fbf 100644 --- a/src/input_common/drivers/keyboard.cpp +++ b/src/input_common/drivers/keyboard.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #include "common/param_package.h" | 4 | #include "common/param_package.h" |
| 6 | #include "common/settings_input.h" | 5 | #include "common/settings_input.h" |
diff --git a/src/input_common/drivers/keyboard.h b/src/input_common/drivers/keyboard.h index 3856c882c..62436dba4 100644 --- a/src/input_common/drivers/keyboard.h +++ b/src/input_common/drivers/keyboard.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index 3c9a4e747..98c3157a8 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #include <stop_token> | 4 | #include <stop_token> |
| 6 | #include <thread> | 5 | #include <thread> |
| @@ -38,7 +37,7 @@ Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) | |||
| 38 | } | 37 | } |
| 39 | 38 | ||
| 40 | void Mouse::UpdateThread(std::stop_token stop_token) { | 39 | void Mouse::UpdateThread(std::stop_token stop_token) { |
| 41 | Common::SetCurrentThreadName("yuzu:input:Mouse"); | 40 | Common::SetCurrentThreadName("Mouse"); |
| 42 | constexpr int update_time = 10; | 41 | constexpr int update_time = 10; |
| 43 | while (!stop_token.stop_requested()) { | 42 | while (!stop_token.stop_requested()) { |
| 44 | if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) { | 43 | if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) { |
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index c5833b8ed..286ce1cf6 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 5cf1987ad..b72e4b397 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2018 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2018 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #include "common/logging/log.h" | 4 | #include "common/logging/log.h" |
| 6 | #include "common/math_util.h" | 5 | #include "common/math_util.h" |
| @@ -13,11 +12,11 @@ | |||
| 13 | namespace InputCommon { | 12 | namespace InputCommon { |
| 14 | 13 | ||
| 15 | namespace { | 14 | namespace { |
| 16 | std::string GetGUID(SDL_Joystick* joystick) { | 15 | Common::UUID GetGUID(SDL_Joystick* joystick) { |
| 17 | const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); | 16 | const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); |
| 18 | char guid_str[33]; | 17 | std::array<u8, 16> data{}; |
| 19 | SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); | 18 | std::memcpy(data.data(), guid.data, sizeof(data)); |
| 20 | return guid_str; | 19 | return Common::UUID{data}; |
| 21 | } | 20 | } |
| 22 | } // Anonymous namespace | 21 | } // Anonymous namespace |
| 23 | 22 | ||
| @@ -31,9 +30,9 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) { | |||
| 31 | 30 | ||
| 32 | class SDLJoystick { | 31 | class SDLJoystick { |
| 33 | public: | 32 | public: |
| 34 | SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, | 33 | SDLJoystick(Common::UUID guid_, int port_, SDL_Joystick* joystick, |
| 35 | SDL_GameController* game_controller) | 34 | SDL_GameController* game_controller) |
| 36 | : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, | 35 | : guid{guid_}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, |
| 37 | sdl_controller{game_controller, &SDL_GameControllerClose} { | 36 | sdl_controller{game_controller, &SDL_GameControllerClose} { |
| 38 | EnableMotion(); | 37 | EnableMotion(); |
| 39 | } | 38 | } |
| @@ -41,13 +40,13 @@ public: | |||
| 41 | void EnableMotion() { | 40 | void EnableMotion() { |
| 42 | if (sdl_controller) { | 41 | if (sdl_controller) { |
| 43 | SDL_GameController* controller = sdl_controller.get(); | 42 | SDL_GameController* controller = sdl_controller.get(); |
| 44 | if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) && !has_accel) { | 43 | has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL); |
| 44 | has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO); | ||
| 45 | if (has_accel) { | ||
| 45 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); | 46 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); |
| 46 | has_accel = true; | ||
| 47 | } | 47 | } |
| 48 | if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) && !has_gyro) { | 48 | if (has_gyro) { |
| 49 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE); | 49 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE); |
| 50 | has_gyro = true; | ||
| 51 | } | 50 | } |
| 52 | } | 51 | } |
| 53 | } | 52 | } |
| @@ -62,7 +61,7 @@ public: | |||
| 62 | 61 | ||
| 63 | bool UpdateMotion(SDL_ControllerSensorEvent event) { | 62 | bool UpdateMotion(SDL_ControllerSensorEvent event) { |
| 64 | constexpr float gravity_constant = 9.80665f; | 63 | constexpr float gravity_constant = 9.80665f; |
| 65 | std::lock_guard lock{mutex}; | 64 | std::scoped_lock lock{mutex}; |
| 66 | const u64 time_difference = event.timestamp - last_motion_update; | 65 | const u64 time_difference = event.timestamp - last_motion_update; |
| 67 | last_motion_update = event.timestamp; | 66 | last_motion_update = event.timestamp; |
| 68 | switch (event.sensor) { | 67 | switch (event.sensor) { |
| @@ -120,7 +119,7 @@ public: | |||
| 120 | */ | 119 | */ |
| 121 | const PadIdentifier GetPadIdentifier() const { | 120 | const PadIdentifier GetPadIdentifier() const { |
| 122 | return { | 121 | return { |
| 123 | .guid = Common::UUID{guid}, | 122 | .guid = guid, |
| 124 | .port = static_cast<std::size_t>(port), | 123 | .port = static_cast<std::size_t>(port), |
| 125 | .pad = 0, | 124 | .pad = 0, |
| 126 | }; | 125 | }; |
| @@ -129,7 +128,7 @@ public: | |||
| 129 | /** | 128 | /** |
| 130 | * The guid of the joystick | 129 | * The guid of the joystick |
| 131 | */ | 130 | */ |
| 132 | const std::string& GetGUID() const { | 131 | const Common::UUID& GetGUID() const { |
| 133 | return guid; | 132 | return guid; |
| 134 | } | 133 | } |
| 135 | 134 | ||
| @@ -175,22 +174,23 @@ public: | |||
| 175 | return false; | 174 | return false; |
| 176 | } | 175 | } |
| 177 | 176 | ||
| 178 | BatteryLevel GetBatteryLevel() { | 177 | Common::Input::BatteryLevel GetBatteryLevel() { |
| 179 | const auto level = SDL_JoystickCurrentPowerLevel(sdl_joystick.get()); | 178 | const auto level = SDL_JoystickCurrentPowerLevel(sdl_joystick.get()); |
| 180 | switch (level) { | 179 | switch (level) { |
| 181 | case SDL_JOYSTICK_POWER_EMPTY: | 180 | case SDL_JOYSTICK_POWER_EMPTY: |
| 182 | return BatteryLevel::Empty; | 181 | return Common::Input::BatteryLevel::Empty; |
| 183 | case SDL_JOYSTICK_POWER_LOW: | 182 | case SDL_JOYSTICK_POWER_LOW: |
| 184 | return BatteryLevel::Low; | 183 | return Common::Input::BatteryLevel::Low; |
| 185 | case SDL_JOYSTICK_POWER_MEDIUM: | 184 | case SDL_JOYSTICK_POWER_MEDIUM: |
| 186 | return BatteryLevel::Medium; | 185 | return Common::Input::BatteryLevel::Medium; |
| 187 | case SDL_JOYSTICK_POWER_FULL: | 186 | case SDL_JOYSTICK_POWER_FULL: |
| 188 | case SDL_JOYSTICK_POWER_MAX: | 187 | case SDL_JOYSTICK_POWER_MAX: |
| 189 | return BatteryLevel::Full; | 188 | return Common::Input::BatteryLevel::Full; |
| 190 | case SDL_JOYSTICK_POWER_UNKNOWN: | ||
| 191 | case SDL_JOYSTICK_POWER_WIRED: | 189 | case SDL_JOYSTICK_POWER_WIRED: |
| 190 | return Common::Input::BatteryLevel::Charging; | ||
| 191 | case SDL_JOYSTICK_POWER_UNKNOWN: | ||
| 192 | default: | 192 | default: |
| 193 | return BatteryLevel::Charging; | 193 | return Common::Input::BatteryLevel::None; |
| 194 | } | 194 | } |
| 195 | } | 195 | } |
| 196 | 196 | ||
| @@ -227,7 +227,7 @@ public: | |||
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | private: | 229 | private: |
| 230 | std::string guid; | 230 | Common::UUID guid; |
| 231 | int port; | 231 | int port; |
| 232 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; | 232 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; |
| 233 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | 233 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; |
| @@ -239,8 +239,8 @@ private: | |||
| 239 | BasicMotion motion; | 239 | BasicMotion motion; |
| 240 | }; | 240 | }; |
| 241 | 241 | ||
| 242 | std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string& guid, int port) { | 242 | std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const Common::UUID& guid, int port) { |
| 243 | std::lock_guard lock{joystick_map_mutex}; | 243 | std::scoped_lock lock{joystick_map_mutex}; |
| 244 | const auto it = joystick_map.find(guid); | 244 | const auto it = joystick_map.find(guid); |
| 245 | 245 | ||
| 246 | if (it != joystick_map.end()) { | 246 | if (it != joystick_map.end()) { |
| @@ -258,11 +258,15 @@ std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string& | |||
| 258 | return joystick_map[guid].emplace_back(std::move(joystick)); | 258 | return joystick_map[guid].emplace_back(std::move(joystick)); |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string& guid, int port) { | ||
| 262 | return GetSDLJoystickByGUID(Common::UUID{guid}, port); | ||
| 263 | } | ||
| 264 | |||
| 261 | std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { | 265 | std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { |
| 262 | auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); | 266 | auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); |
| 263 | const std::string guid = GetGUID(sdl_joystick); | 267 | const auto guid = GetGUID(sdl_joystick); |
| 264 | 268 | ||
| 265 | std::lock_guard lock{joystick_map_mutex}; | 269 | std::scoped_lock lock{joystick_map_mutex}; |
| 266 | const auto map_it = joystick_map.find(guid); | 270 | const auto map_it = joystick_map.find(guid); |
| 267 | 271 | ||
| 268 | if (map_it == joystick_map.end()) { | 272 | if (map_it == joystick_map.end()) { |
| @@ -294,13 +298,14 @@ void SDLDriver::InitJoystick(int joystick_index) { | |||
| 294 | return; | 298 | return; |
| 295 | } | 299 | } |
| 296 | 300 | ||
| 297 | const std::string guid = GetGUID(sdl_joystick); | 301 | const auto guid = GetGUID(sdl_joystick); |
| 298 | 302 | ||
| 299 | std::lock_guard lock{joystick_map_mutex}; | 303 | std::scoped_lock lock{joystick_map_mutex}; |
| 300 | if (joystick_map.find(guid) == joystick_map.end()) { | 304 | if (joystick_map.find(guid) == joystick_map.end()) { |
| 301 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller); | 305 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller); |
| 302 | PreSetController(joystick->GetPadIdentifier()); | 306 | PreSetController(joystick->GetPadIdentifier()); |
| 303 | SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); | 307 | SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); |
| 308 | joystick->EnableMotion(); | ||
| 304 | joystick_map[guid].emplace_back(std::move(joystick)); | 309 | joystick_map[guid].emplace_back(std::move(joystick)); |
| 305 | return; | 310 | return; |
| 306 | } | 311 | } |
| @@ -312,6 +317,7 @@ void SDLDriver::InitJoystick(int joystick_index) { | |||
| 312 | 317 | ||
| 313 | if (joystick_it != joystick_guid_list.end()) { | 318 | if (joystick_it != joystick_guid_list.end()) { |
| 314 | (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller); | 319 | (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller); |
| 320 | (*joystick_it)->EnableMotion(); | ||
| 315 | return; | 321 | return; |
| 316 | } | 322 | } |
| 317 | 323 | ||
| @@ -319,13 +325,14 @@ void SDLDriver::InitJoystick(int joystick_index) { | |||
| 319 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller); | 325 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller); |
| 320 | PreSetController(joystick->GetPadIdentifier()); | 326 | PreSetController(joystick->GetPadIdentifier()); |
| 321 | SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); | 327 | SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); |
| 328 | joystick->EnableMotion(); | ||
| 322 | joystick_guid_list.emplace_back(std::move(joystick)); | 329 | joystick_guid_list.emplace_back(std::move(joystick)); |
| 323 | } | 330 | } |
| 324 | 331 | ||
| 325 | void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) { | 332 | void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) { |
| 326 | const std::string guid = GetGUID(sdl_joystick); | 333 | const auto guid = GetGUID(sdl_joystick); |
| 327 | 334 | ||
| 328 | std::lock_guard lock{joystick_map_mutex}; | 335 | std::scoped_lock lock{joystick_map_mutex}; |
| 329 | // This call to guid is safe since the joystick is guaranteed to be in the map | 336 | // This call to guid is safe since the joystick is guaranteed to be in the map |
| 330 | const auto& joystick_guid_list = joystick_map[guid]; | 337 | const auto& joystick_guid_list = joystick_map[guid]; |
| 331 | const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(), | 338 | const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(), |
| @@ -351,6 +358,8 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { | |||
| 351 | if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { | 358 | if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { |
| 352 | const PadIdentifier identifier = joystick->GetPadIdentifier(); | 359 | const PadIdentifier identifier = joystick->GetPadIdentifier(); |
| 353 | SetButton(identifier, event.jbutton.button, true); | 360 | SetButton(identifier, event.jbutton.button, true); |
| 361 | // Battery doesn't trigger an event so just update every button press | ||
| 362 | SetBattery(identifier, joystick->GetBatteryLevel()); | ||
| 354 | } | 363 | } |
| 355 | break; | 364 | break; |
| 356 | } | 365 | } |
| @@ -389,7 +398,7 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { | |||
| 389 | } | 398 | } |
| 390 | 399 | ||
| 391 | void SDLDriver::CloseJoysticks() { | 400 | void SDLDriver::CloseJoysticks() { |
| 392 | std::lock_guard lock{joystick_map_mutex}; | 401 | std::scoped_lock lock{joystick_map_mutex}; |
| 393 | joystick_map.clear(); | 402 | joystick_map.clear(); |
| 394 | } | 403 | } |
| 395 | 404 | ||
| @@ -427,13 +436,21 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en | |||
| 427 | initialized = true; | 436 | initialized = true; |
| 428 | if (start_thread) { | 437 | if (start_thread) { |
| 429 | poll_thread = std::thread([this] { | 438 | poll_thread = std::thread([this] { |
| 430 | Common::SetCurrentThreadName("yuzu:input:SDL"); | 439 | Common::SetCurrentThreadName("SDL_MainLoop"); |
| 431 | using namespace std::chrono_literals; | 440 | using namespace std::chrono_literals; |
| 432 | while (initialized) { | 441 | while (initialized) { |
| 433 | SDL_PumpEvents(); | 442 | SDL_PumpEvents(); |
| 434 | std::this_thread::sleep_for(1ms); | 443 | std::this_thread::sleep_for(1ms); |
| 435 | } | 444 | } |
| 436 | }); | 445 | }); |
| 446 | vibration_thread = std::thread([this] { | ||
| 447 | Common::SetCurrentThreadName("SDL_Vibration"); | ||
| 448 | using namespace std::chrono_literals; | ||
| 449 | while (initialized) { | ||
| 450 | SendVibrations(); | ||
| 451 | std::this_thread::sleep_for(10ms); | ||
| 452 | } | ||
| 453 | }); | ||
| 437 | } | 454 | } |
| 438 | // Because the events for joystick connection happens before we have our event watcher added, we | 455 | // Because the events for joystick connection happens before we have our event watcher added, we |
| 439 | // can just open all the joysticks right here | 456 | // can just open all the joysticks right here |
| @@ -449,6 +466,7 @@ SDLDriver::~SDLDriver() { | |||
| 449 | initialized = false; | 466 | initialized = false; |
| 450 | if (start_thread) { | 467 | if (start_thread) { |
| 451 | poll_thread.join(); | 468 | poll_thread.join(); |
| 469 | vibration_thread.join(); | ||
| 452 | SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER); | 470 | SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER); |
| 453 | } | 471 | } |
| 454 | } | 472 | } |
| @@ -466,7 +484,7 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const { | |||
| 466 | devices.emplace_back(Common::ParamPackage{ | 484 | devices.emplace_back(Common::ParamPackage{ |
| 467 | {"engine", GetEngineName()}, | 485 | {"engine", GetEngineName()}, |
| 468 | {"display", std::move(name)}, | 486 | {"display", std::move(name)}, |
| 469 | {"guid", joystick->GetGUID()}, | 487 | {"guid", joystick->GetGUID().RawString()}, |
| 470 | {"port", std::to_string(joystick->GetPort())}, | 488 | {"port", std::to_string(joystick->GetPort())}, |
| 471 | }); | 489 | }); |
| 472 | if (joystick->IsJoyconLeft()) { | 490 | if (joystick->IsJoyconLeft()) { |
| @@ -489,8 +507,8 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const { | |||
| 489 | devices.emplace_back(Common::ParamPackage{ | 507 | devices.emplace_back(Common::ParamPackage{ |
| 490 | {"engine", GetEngineName()}, | 508 | {"engine", GetEngineName()}, |
| 491 | {"display", std::move(name)}, | 509 | {"display", std::move(name)}, |
| 492 | {"guid", joystick->GetGUID()}, | 510 | {"guid", joystick->GetGUID().RawString()}, |
| 493 | {"guid2", joystick2->GetGUID()}, | 511 | {"guid2", joystick2->GetGUID().RawString()}, |
| 494 | {"port", std::to_string(joystick->GetPort())}, | 512 | {"port", std::to_string(joystick->GetPort())}, |
| 495 | }); | 513 | }); |
| 496 | } | 514 | } |
| @@ -528,57 +546,75 @@ Common::Input::VibrationError SDLDriver::SetRumble( | |||
| 528 | .type = Common::Input::VibrationAmplificationType::Exponential, | 546 | .type = Common::Input::VibrationAmplificationType::Exponential, |
| 529 | }; | 547 | }; |
| 530 | 548 | ||
| 531 | if (!joystick->RumblePlay(new_vibration)) { | 549 | if (vibration.type == Common::Input::VibrationAmplificationType::Test) { |
| 532 | return Common::Input::VibrationError::Unknown; | 550 | if (!joystick->RumblePlay(new_vibration)) { |
| 551 | return Common::Input::VibrationError::Unknown; | ||
| 552 | } | ||
| 553 | return Common::Input::VibrationError::None; | ||
| 533 | } | 554 | } |
| 534 | 555 | ||
| 556 | vibration_queue.Push(VibrationRequest{ | ||
| 557 | .identifier = identifier, | ||
| 558 | .vibration = new_vibration, | ||
| 559 | }); | ||
| 560 | |||
| 535 | return Common::Input::VibrationError::None; | 561 | return Common::Input::VibrationError::None; |
| 536 | } | 562 | } |
| 537 | 563 | ||
| 538 | Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, | 564 | void SDLDriver::SendVibrations() { |
| 565 | while (!vibration_queue.Empty()) { | ||
| 566 | VibrationRequest request; | ||
| 567 | vibration_queue.Pop(request); | ||
| 568 | const auto joystick = GetSDLJoystickByGUID(request.identifier.guid.RawString(), | ||
| 569 | static_cast<int>(request.identifier.port)); | ||
| 570 | joystick->RumblePlay(request.vibration); | ||
| 571 | } | ||
| 572 | } | ||
| 573 | |||
| 574 | Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, const Common::UUID& guid, | ||
| 539 | s32 axis, float value) const { | 575 | s32 axis, float value) const { |
| 540 | Common::ParamPackage params{}; | 576 | Common::ParamPackage params{}; |
| 541 | params.Set("engine", GetEngineName()); | 577 | params.Set("engine", GetEngineName()); |
| 542 | params.Set("port", port); | 578 | params.Set("port", port); |
| 543 | params.Set("guid", std::move(guid)); | 579 | params.Set("guid", guid.RawString()); |
| 544 | params.Set("axis", axis); | 580 | params.Set("axis", axis); |
| 545 | params.Set("threshold", "0.5"); | 581 | params.Set("threshold", "0.5"); |
| 546 | params.Set("invert", value < 0 ? "-" : "+"); | 582 | params.Set("invert", value < 0 ? "-" : "+"); |
| 547 | return params; | 583 | return params; |
| 548 | } | 584 | } |
| 549 | 585 | ||
| 550 | Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, std::string guid, | 586 | Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, const Common::UUID& guid, |
| 551 | s32 button) const { | 587 | s32 button) const { |
| 552 | Common::ParamPackage params{}; | 588 | Common::ParamPackage params{}; |
| 553 | params.Set("engine", GetEngineName()); | 589 | params.Set("engine", GetEngineName()); |
| 554 | params.Set("port", port); | 590 | params.Set("port", port); |
| 555 | params.Set("guid", std::move(guid)); | 591 | params.Set("guid", guid.RawString()); |
| 556 | params.Set("button", button); | 592 | params.Set("button", button); |
| 557 | return params; | 593 | return params; |
| 558 | } | 594 | } |
| 559 | 595 | ||
| 560 | Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, std::string guid, s32 hat, | 596 | Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, const Common::UUID& guid, |
| 561 | u8 value) const { | 597 | s32 hat, u8 value) const { |
| 562 | Common::ParamPackage params{}; | 598 | Common::ParamPackage params{}; |
| 563 | params.Set("engine", GetEngineName()); | 599 | params.Set("engine", GetEngineName()); |
| 564 | params.Set("port", port); | 600 | params.Set("port", port); |
| 565 | params.Set("guid", std::move(guid)); | 601 | params.Set("guid", guid.RawString()); |
| 566 | params.Set("hat", hat); | 602 | params.Set("hat", hat); |
| 567 | params.Set("direction", GetHatButtonName(value)); | 603 | params.Set("direction", GetHatButtonName(value)); |
| 568 | return params; | 604 | return params; |
| 569 | } | 605 | } |
| 570 | 606 | ||
| 571 | Common::ParamPackage SDLDriver::BuildMotionParam(int port, std::string guid) const { | 607 | Common::ParamPackage SDLDriver::BuildMotionParam(int port, const Common::UUID& guid) const { |
| 572 | Common::ParamPackage params{}; | 608 | Common::ParamPackage params{}; |
| 573 | params.Set("engine", GetEngineName()); | 609 | params.Set("engine", GetEngineName()); |
| 574 | params.Set("motion", 0); | 610 | params.Set("motion", 0); |
| 575 | params.Set("port", port); | 611 | params.Set("port", port); |
| 576 | params.Set("guid", std::move(guid)); | 612 | params.Set("guid", guid.RawString()); |
| 577 | return params; | 613 | return params; |
| 578 | } | 614 | } |
| 579 | 615 | ||
| 580 | Common::ParamPackage SDLDriver::BuildParamPackageForBinding( | 616 | Common::ParamPackage SDLDriver::BuildParamPackageForBinding( |
| 581 | int port, const std::string& guid, const SDL_GameControllerButtonBind& binding) const { | 617 | int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const { |
| 582 | switch (binding.bindType) { | 618 | switch (binding.bindType) { |
| 583 | case SDL_CONTROLLER_BINDTYPE_NONE: | 619 | case SDL_CONTROLLER_BINDTYPE_NONE: |
| 584 | break; | 620 | break; |
| @@ -931,4 +967,37 @@ u8 SDLDriver::GetHatButtonId(const std::string& direction_name) const { | |||
| 931 | return direction; | 967 | return direction; |
| 932 | } | 968 | } |
| 933 | 969 | ||
| 970 | bool SDLDriver::IsStickInverted(const Common::ParamPackage& params) { | ||
| 971 | if (!params.Has("guid") || !params.Has("port")) { | ||
| 972 | return false; | ||
| 973 | } | ||
| 974 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); | ||
| 975 | if (joystick == nullptr) { | ||
| 976 | return false; | ||
| 977 | } | ||
| 978 | auto* controller = joystick->GetSDLGameController(); | ||
| 979 | if (controller == nullptr) { | ||
| 980 | return false; | ||
| 981 | } | ||
| 982 | |||
| 983 | const auto& axis_x = params.Get("axis_x", 0); | ||
| 984 | const auto& axis_y = params.Get("axis_y", 0); | ||
| 985 | const auto& binding_left_x = | ||
| 986 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); | ||
| 987 | const auto& binding_right_x = | ||
| 988 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); | ||
| 989 | const auto& binding_left_y = | ||
| 990 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); | ||
| 991 | const auto& binding_right_y = | ||
| 992 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY); | ||
| 993 | |||
| 994 | if (axis_x != binding_left_y.value.axis && axis_x != binding_right_y.value.axis) { | ||
| 995 | return false; | ||
| 996 | } | ||
| 997 | if (axis_y != binding_left_x.value.axis && axis_y != binding_right_x.value.axis) { | ||
| 998 | return false; | ||
| 999 | } | ||
| 1000 | return true; | ||
| 1001 | } | ||
| 1002 | |||
| 934 | } // namespace InputCommon | 1003 | } // namespace InputCommon |
diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index 4cde3606f..fc3a44572 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2018 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2018 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
| @@ -12,6 +11,7 @@ | |||
| 12 | #include <SDL.h> | 11 | #include <SDL.h> |
| 13 | 12 | ||
| 14 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/threadsafe_queue.h" | ||
| 15 | #include "input_common/input_engine.h" | 15 | #include "input_common/input_engine.h" |
| 16 | 16 | ||
| 17 | union SDL_Event; | 17 | union SDL_Event; |
| @@ -46,6 +46,7 @@ public: | |||
| 46 | * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so | 46 | * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so |
| 47 | * tie it to a SDLJoystick with the same guid and that port | 47 | * tie it to a SDLJoystick with the same guid and that port |
| 48 | */ | 48 | */ |
| 49 | std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const Common::UUID& guid, int port); | ||
| 49 | std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port); | 50 | std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port); |
| 50 | 51 | ||
| 51 | std::vector<Common::ParamPackage> GetInputDevices() const override; | 52 | std::vector<Common::ParamPackage> GetInputDevices() const override; |
| @@ -58,28 +59,38 @@ public: | |||
| 58 | std::string GetHatButtonName(u8 direction_value) const override; | 59 | std::string GetHatButtonName(u8 direction_value) const override; |
| 59 | u8 GetHatButtonId(const std::string& direction_name) const override; | 60 | u8 GetHatButtonId(const std::string& direction_name) const override; |
| 60 | 61 | ||
| 62 | bool IsStickInverted(const Common::ParamPackage& params) override; | ||
| 63 | |||
| 61 | Common::Input::VibrationError SetRumble( | 64 | Common::Input::VibrationError SetRumble( |
| 62 | const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; | 65 | const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; |
| 63 | 66 | ||
| 64 | private: | 67 | private: |
| 68 | struct VibrationRequest { | ||
| 69 | PadIdentifier identifier; | ||
| 70 | Common::Input::VibrationStatus vibration; | ||
| 71 | }; | ||
| 72 | |||
| 65 | void InitJoystick(int joystick_index); | 73 | void InitJoystick(int joystick_index); |
| 66 | void CloseJoystick(SDL_Joystick* sdl_joystick); | 74 | void CloseJoystick(SDL_Joystick* sdl_joystick); |
| 67 | 75 | ||
| 68 | /// Needs to be called before SDL_QuitSubSystem. | 76 | /// Needs to be called before SDL_QuitSubSystem. |
| 69 | void CloseJoysticks(); | 77 | void CloseJoysticks(); |
| 70 | 78 | ||
| 71 | Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, | 79 | /// Takes all vibrations from the queue and sends the command to the controller |
| 72 | float value = 0.1f) const; | 80 | void SendVibrations(); |
| 73 | Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, | 81 | |
| 82 | Common::ParamPackage BuildAnalogParamPackageForButton(int port, const Common::UUID& guid, | ||
| 83 | s32 axis, float value = 0.1f) const; | ||
| 84 | Common::ParamPackage BuildButtonParamPackageForButton(int port, const Common::UUID& guid, | ||
| 74 | s32 button) const; | 85 | s32 button) const; |
| 75 | 86 | ||
| 76 | Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s32 hat, | 87 | Common::ParamPackage BuildHatParamPackageForButton(int port, const Common::UUID& guid, s32 hat, |
| 77 | u8 value) const; | 88 | u8 value) const; |
| 78 | 89 | ||
| 79 | Common::ParamPackage BuildMotionParam(int port, std::string guid) const; | 90 | Common::ParamPackage BuildMotionParam(int port, const Common::UUID& guid) const; |
| 80 | 91 | ||
| 81 | Common::ParamPackage BuildParamPackageForBinding( | 92 | Common::ParamPackage BuildParamPackageForBinding( |
| 82 | int port, const std::string& guid, const SDL_GameControllerButtonBind& binding) const; | 93 | int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const; |
| 83 | 94 | ||
| 84 | Common::ParamPackage BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x, | 95 | Common::ParamPackage BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x, |
| 85 | int axis_y, float offset_x, | 96 | int axis_y, float offset_x, |
| @@ -105,13 +116,17 @@ private: | |||
| 105 | /// Returns true if the button is on the left joycon | 116 | /// Returns true if the button is on the left joycon |
| 106 | bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const; | 117 | bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const; |
| 107 | 118 | ||
| 119 | /// Queue of vibration request to controllers | ||
| 120 | Common::SPSCQueue<VibrationRequest> vibration_queue; | ||
| 121 | |||
| 108 | /// Map of GUID of a list of corresponding virtual Joysticks | 122 | /// Map of GUID of a list of corresponding virtual Joysticks |
| 109 | std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map; | 123 | std::unordered_map<Common::UUID, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map; |
| 110 | std::mutex joystick_map_mutex; | 124 | std::mutex joystick_map_mutex; |
| 111 | 125 | ||
| 112 | bool start_thread = false; | 126 | bool start_thread = false; |
| 113 | std::atomic<bool> initialized = false; | 127 | std::atomic<bool> initialized = false; |
| 114 | 128 | ||
| 115 | std::thread poll_thread; | 129 | std::thread poll_thread; |
| 130 | std::thread vibration_thread; | ||
| 116 | }; | 131 | }; |
| 117 | } // namespace InputCommon | 132 | } // namespace InputCommon |
diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 944e141bf..21c6ed405 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2+ | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #include <cstring> | 4 | #include <cstring> |
| 6 | #include <fmt/format.h> | 5 | #include <fmt/format.h> |
diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h index 4b4e6c417..38a27a230 100644 --- a/src/input_common/drivers/tas_input.h +++ b/src/input_common/drivers/tas_input.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
diff --git a/src/input_common/drivers/touch_screen.cpp b/src/input_common/drivers/touch_screen.cpp index 30c727df4..1753e0893 100644 --- a/src/input_common/drivers/touch_screen.cpp +++ b/src/input_common/drivers/touch_screen.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #include "common/param_package.h" | 4 | #include "common/param_package.h" |
| 6 | #include "input_common/drivers/touch_screen.h" | 5 | #include "input_common/drivers/touch_screen.h" |
| @@ -15,38 +14,93 @@ constexpr PadIdentifier identifier = { | |||
| 15 | 14 | ||
| 16 | TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) { | 15 | TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) { |
| 17 | PreSetController(identifier); | 16 | PreSetController(identifier); |
| 17 | ReleaseAllTouch(); | ||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | void TouchScreen::TouchMoved(float x, float y, std::size_t finger) { | 20 | void TouchScreen::TouchMoved(float x, float y, std::size_t finger_id) { |
| 21 | if (finger >= 16) { | 21 | const auto index = GetIndexFromFingerId(finger_id); |
| 22 | if (!index) { | ||
| 23 | // Touch doesn't exist handle it as a new one | ||
| 24 | TouchPressed(x, y, finger_id); | ||
| 22 | return; | 25 | return; |
| 23 | } | 26 | } |
| 24 | TouchPressed(x, y, finger); | 27 | const auto i = index.value(); |
| 28 | fingers[i].is_active = true; | ||
| 29 | SetButton(identifier, static_cast<int>(i), true); | ||
| 30 | SetAxis(identifier, static_cast<int>(i * 2), x); | ||
| 31 | SetAxis(identifier, static_cast<int>(i * 2 + 1), y); | ||
| 25 | } | 32 | } |
| 26 | 33 | ||
| 27 | void TouchScreen::TouchPressed(float x, float y, std::size_t finger) { | 34 | void TouchScreen::TouchPressed(float x, float y, std::size_t finger_id) { |
| 28 | if (finger >= 16) { | 35 | if (GetIndexFromFingerId(finger_id)) { |
| 36 | // Touch already exist. Just update the data | ||
| 37 | TouchMoved(x, y, finger_id); | ||
| 29 | return; | 38 | return; |
| 30 | } | 39 | } |
| 31 | SetButton(identifier, static_cast<int>(finger), true); | 40 | const auto index = GetNextFreeIndex(); |
| 32 | SetAxis(identifier, static_cast<int>(finger * 2), x); | 41 | if (!index) { |
| 33 | SetAxis(identifier, static_cast<int>(finger * 2 + 1), y); | 42 | // No free entries. Ignore input |
| 43 | return; | ||
| 44 | } | ||
| 45 | const auto i = index.value(); | ||
| 46 | fingers[i].is_enabled = true; | ||
| 47 | fingers[i].finger_id = finger_id; | ||
| 48 | TouchMoved(x, y, finger_id); | ||
| 34 | } | 49 | } |
| 35 | 50 | ||
| 36 | void TouchScreen::TouchReleased(std::size_t finger) { | 51 | void TouchScreen::TouchReleased(std::size_t finger_id) { |
| 37 | if (finger >= 16) { | 52 | const auto index = GetIndexFromFingerId(finger_id); |
| 53 | if (!index) { | ||
| 38 | return; | 54 | return; |
| 39 | } | 55 | } |
| 40 | SetButton(identifier, static_cast<int>(finger), false); | 56 | const auto i = index.value(); |
| 41 | SetAxis(identifier, static_cast<int>(finger * 2), 0.0f); | 57 | fingers[i].is_enabled = false; |
| 42 | SetAxis(identifier, static_cast<int>(finger * 2 + 1), 0.0f); | 58 | SetButton(identifier, static_cast<int>(i), false); |
| 59 | SetAxis(identifier, static_cast<int>(i * 2), 0.0f); | ||
| 60 | SetAxis(identifier, static_cast<int>(i * 2 + 1), 0.0f); | ||
| 61 | } | ||
| 62 | |||
| 63 | std::optional<std::size_t> TouchScreen::GetIndexFromFingerId(std::size_t finger_id) const { | ||
| 64 | for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) { | ||
| 65 | const auto& finger = fingers[index]; | ||
| 66 | if (!finger.is_enabled) { | ||
| 67 | continue; | ||
| 68 | } | ||
| 69 | if (finger.finger_id == finger_id) { | ||
| 70 | return index; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | return std::nullopt; | ||
| 74 | } | ||
| 75 | |||
| 76 | std::optional<std::size_t> TouchScreen::GetNextFreeIndex() const { | ||
| 77 | for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) { | ||
| 78 | if (!fingers[index].is_enabled) { | ||
| 79 | return index; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | return std::nullopt; | ||
| 83 | } | ||
| 84 | |||
| 85 | void TouchScreen::ClearActiveFlag() { | ||
| 86 | for (auto& finger : fingers) { | ||
| 87 | finger.is_active = false; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | void TouchScreen::ReleaseInactiveTouch() { | ||
| 92 | for (const auto& finger : fingers) { | ||
| 93 | if (!finger.is_active) { | ||
| 94 | TouchReleased(finger.finger_id); | ||
| 95 | } | ||
| 96 | } | ||
| 43 | } | 97 | } |
| 44 | 98 | ||
| 45 | void TouchScreen::ReleaseAllTouch() { | 99 | void TouchScreen::ReleaseAllTouch() { |
| 46 | for (int index = 0; index < 16; ++index) { | 100 | for (const auto& finger : fingers) { |
| 47 | SetButton(identifier, index, false); | 101 | if (finger.is_enabled) { |
| 48 | SetAxis(identifier, index * 2, 0.0f); | 102 | TouchReleased(finger.finger_id); |
| 49 | SetAxis(identifier, index * 2 + 1, 0.0f); | 103 | } |
| 50 | } | 104 | } |
| 51 | } | 105 | } |
| 52 | 106 | ||
diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h index bf395c40b..f46036ffd 100644 --- a/src/input_common/drivers/touch_screen.h +++ b/src/input_common/drivers/touch_screen.h | |||
| @@ -1,44 +1,67 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
| 6 | #include <optional> | ||
| 7 | |||
| 7 | #include "input_common/input_engine.h" | 8 | #include "input_common/input_engine.h" |
| 8 | 9 | ||
| 9 | namespace InputCommon { | 10 | namespace InputCommon { |
| 10 | 11 | ||
| 11 | /** | 12 | /** |
| 12 | * A button device factory representing a keyboard. It receives keyboard events and forward them | 13 | * A touch device factory representing a touch screen. It receives touch events and forward them |
| 13 | * to all button devices it created. | 14 | * to all touch devices it created. |
| 14 | */ | 15 | */ |
| 15 | class TouchScreen final : public InputEngine { | 16 | class TouchScreen final : public InputEngine { |
| 16 | public: | 17 | public: |
| 17 | explicit TouchScreen(std::string input_engine_); | 18 | explicit TouchScreen(std::string input_engine_); |
| 18 | 19 | ||
| 19 | /** | 20 | /** |
| 20 | * Signals that mouse has moved. | 21 | * Signals that touch has moved and marks this touch point as active |
| 21 | * @param x the x-coordinate of the cursor | 22 | * @param x new horizontal position |
| 22 | * @param y the y-coordinate of the cursor | 23 | * @param y new vertical position |
| 23 | * @param center_x the x-coordinate of the middle of the screen | 24 | * @param finger_id of the touch point to be updated |
| 24 | * @param center_y the y-coordinate of the middle of the screen | ||
| 25 | */ | 25 | */ |
| 26 | void TouchMoved(float x, float y, std::size_t finger); | 26 | void TouchMoved(float x, float y, std::size_t finger_id); |
| 27 | 27 | ||
| 28 | /** | 28 | /** |
| 29 | * Sets the status of all buttons bound with the key to pressed | 29 | * Signals and creates a new touch point with this finger id |
| 30 | * @param key_code the code of the key to press | 30 | * @param x starting horizontal position |
| 31 | * @param y starting vertical position | ||
| 32 | * @param finger_id to be assigned to the new touch point | ||
| 31 | */ | 33 | */ |
| 32 | void TouchPressed(float x, float y, std::size_t finger); | 34 | void TouchPressed(float x, float y, std::size_t finger_id); |
| 33 | 35 | ||
| 34 | /** | 36 | /** |
| 35 | * Sets the status of all buttons bound with the key to released | 37 | * Signals and resets the touch point related to the this finger id |
| 36 | * @param key_code the code of the key to release | 38 | * @param finger_id to be released |
| 37 | */ | 39 | */ |
| 38 | void TouchReleased(std::size_t finger); | 40 | void TouchReleased(std::size_t finger_id); |
| 41 | |||
| 42 | /// Resets the active flag for each touch point | ||
| 43 | void ClearActiveFlag(); | ||
| 44 | |||
| 45 | /// Releases all touch that haven't been marked as active | ||
| 46 | void ReleaseInactiveTouch(); | ||
| 39 | 47 | ||
| 40 | /// Resets all inputs to their initial value | 48 | /// Resets all inputs to their initial value |
| 41 | void ReleaseAllTouch(); | 49 | void ReleaseAllTouch(); |
| 50 | |||
| 51 | private: | ||
| 52 | static constexpr std::size_t MAX_FINGER_COUNT = 16; | ||
| 53 | |||
| 54 | struct TouchStatus { | ||
| 55 | std::size_t finger_id{}; | ||
| 56 | bool is_enabled{}; | ||
| 57 | bool is_active{}; | ||
| 58 | }; | ||
| 59 | |||
| 60 | std::optional<std::size_t> GetIndexFromFingerId(std::size_t finger_id) const; | ||
| 61 | |||
| 62 | std::optional<std::size_t> GetNextFreeIndex() const; | ||
| 63 | |||
| 64 | std::array<TouchStatus, MAX_FINGER_COUNT> fingers{}; | ||
| 42 | }; | 65 | }; |
| 43 | 66 | ||
| 44 | } // namespace InputCommon | 67 | } // namespace InputCommon |
diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp index 64162f431..808b21069 100644 --- a/src/input_common/drivers/udp_client.cpp +++ b/src/input_common/drivers/udp_client.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2018 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2018 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #include <random> | 4 | #include <random> |
| 6 | #include <boost/asio.hpp> | 5 | #include <boost/asio.hpp> |
| @@ -192,22 +191,22 @@ std::size_t UDPClient::GetClientNumber(std::string_view host, u16 port) const { | |||
| 192 | return MAX_UDP_CLIENTS; | 191 | return MAX_UDP_CLIENTS; |
| 193 | } | 192 | } |
| 194 | 193 | ||
| 195 | BatteryLevel UDPClient::GetBatteryLevel(Response::Battery battery) const { | 194 | Common::Input::BatteryLevel UDPClient::GetBatteryLevel(Response::Battery battery) const { |
| 196 | switch (battery) { | 195 | switch (battery) { |
| 197 | case Response::Battery::Dying: | 196 | case Response::Battery::Dying: |
| 198 | return BatteryLevel::Empty; | 197 | return Common::Input::BatteryLevel::Empty; |
| 199 | case Response::Battery::Low: | 198 | case Response::Battery::Low: |
| 200 | return BatteryLevel::Critical; | 199 | return Common::Input::BatteryLevel::Critical; |
| 201 | case Response::Battery::Medium: | 200 | case Response::Battery::Medium: |
| 202 | return BatteryLevel::Low; | 201 | return Common::Input::BatteryLevel::Low; |
| 203 | case Response::Battery::High: | 202 | case Response::Battery::High: |
| 204 | return BatteryLevel::Medium; | 203 | return Common::Input::BatteryLevel::Medium; |
| 205 | case Response::Battery::Full: | 204 | case Response::Battery::Full: |
| 206 | case Response::Battery::Charged: | 205 | case Response::Battery::Charged: |
| 207 | return BatteryLevel::Full; | 206 | return Common::Input::BatteryLevel::Full; |
| 208 | case Response::Battery::Charging: | 207 | case Response::Battery::Charging: |
| 209 | default: | 208 | default: |
| 210 | return BatteryLevel::Charging; | 209 | return Common::Input::BatteryLevel::Charging; |
| 211 | } | 210 | } |
| 212 | } | 211 | } |
| 213 | 212 | ||
| @@ -547,6 +546,22 @@ Common::Input::ButtonNames UDPClient::GetUIName(const Common::ParamPackage& para | |||
| 547 | return Common::Input::ButtonNames::Invalid; | 546 | return Common::Input::ButtonNames::Invalid; |
| 548 | } | 547 | } |
| 549 | 548 | ||
| 549 | bool UDPClient::IsStickInverted(const Common::ParamPackage& params) { | ||
| 550 | if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) { | ||
| 551 | return false; | ||
| 552 | } | ||
| 553 | |||
| 554 | const auto x_axis = static_cast<PadAxes>(params.Get("axis_x", 0)); | ||
| 555 | const auto y_axis = static_cast<PadAxes>(params.Get("axis_y", 0)); | ||
| 556 | if (x_axis != PadAxes::LeftStickY && x_axis != PadAxes::RightStickY) { | ||
| 557 | return false; | ||
| 558 | } | ||
| 559 | if (y_axis != PadAxes::LeftStickX && y_axis != PadAxes::RightStickX) { | ||
| 560 | return false; | ||
| 561 | } | ||
| 562 | return true; | ||
| 563 | } | ||
| 564 | |||
| 550 | void TestCommunication(const std::string& host, u16 port, | 565 | void TestCommunication(const std::string& host, u16 port, |
| 551 | const std::function<void()>& success_callback, | 566 | const std::function<void()>& success_callback, |
| 552 | const std::function<void()>& failure_callback) { | 567 | const std::function<void()>& failure_callback) { |
diff --git a/src/input_common/drivers/udp_client.h b/src/input_common/drivers/udp_client.h index 76e32bd04..cea9f579a 100644 --- a/src/input_common/drivers/udp_client.h +++ b/src/input_common/drivers/udp_client.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2018 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2018 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
| @@ -64,6 +63,8 @@ public: | |||
| 64 | MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override; | 63 | MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override; |
| 65 | Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override; | 64 | Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override; |
| 66 | 65 | ||
| 66 | bool IsStickInverted(const Common::ParamPackage& params) override; | ||
| 67 | |||
| 67 | private: | 68 | private: |
| 68 | enum class PadButton { | 69 | enum class PadButton { |
| 69 | Undefined = 0x0000, | 70 | Undefined = 0x0000, |
| @@ -141,7 +142,7 @@ private: | |||
| 141 | std::size_t GetClientNumber(std::string_view host, u16 port) const; | 142 | std::size_t GetClientNumber(std::string_view host, u16 port) const; |
| 142 | 143 | ||
| 143 | // Translates UDP battery level to input engine battery level | 144 | // Translates UDP battery level to input engine battery level |
| 144 | BatteryLevel GetBatteryLevel(Response::Battery battery) const; | 145 | Common::Input::BatteryLevel GetBatteryLevel(Response::Battery battery) const; |
| 145 | 146 | ||
| 146 | void OnVersion(Response::Version); | 147 | void OnVersion(Response::Version); |
| 147 | void OnPortInfo(Response::PortInfo); | 148 | void OnPortInfo(Response::PortInfo); |
diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp new file mode 100644 index 000000000..0cd5129da --- /dev/null +++ b/src/input_common/drivers/virtual_amiibo.cpp | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include <cstring> | ||
| 5 | #include <fmt/format.h> | ||
| 6 | |||
| 7 | #include "common/fs/file.h" | ||
| 8 | #include "common/fs/fs.h" | ||
| 9 | #include "common/fs/path_util.h" | ||
| 10 | #include "common/logging/log.h" | ||
| 11 | #include "common/settings.h" | ||
| 12 | #include "input_common/drivers/virtual_amiibo.h" | ||
| 13 | |||
| 14 | namespace InputCommon { | ||
| 15 | constexpr PadIdentifier identifier = { | ||
| 16 | .guid = Common::UUID{}, | ||
| 17 | .port = 0, | ||
| 18 | .pad = 0, | ||
| 19 | }; | ||
| 20 | |||
| 21 | VirtualAmiibo::VirtualAmiibo(std::string input_engine_) : InputEngine(std::move(input_engine_)) {} | ||
| 22 | |||
| 23 | VirtualAmiibo::~VirtualAmiibo() = default; | ||
| 24 | |||
| 25 | Common::Input::PollingError VirtualAmiibo::SetPollingMode( | ||
| 26 | [[maybe_unused]] const PadIdentifier& identifier_, | ||
| 27 | const Common::Input::PollingMode polling_mode_) { | ||
| 28 | polling_mode = polling_mode_; | ||
| 29 | |||
| 30 | if (polling_mode == Common::Input::PollingMode::NFC) { | ||
| 31 | if (state == State::Initialized) { | ||
| 32 | state = State::WaitingForAmiibo; | ||
| 33 | } | ||
| 34 | } else { | ||
| 35 | if (state == State::AmiiboIsOpen) { | ||
| 36 | CloseAmiibo(); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | return Common::Input::PollingError::None; | ||
| 41 | } | ||
| 42 | |||
| 43 | Common::Input::NfcState VirtualAmiibo::SupportsNfc( | ||
| 44 | [[maybe_unused]] const PadIdentifier& identifier_) const { | ||
| 45 | return Common::Input::NfcState::Success; | ||
| 46 | } | ||
| 47 | |||
| 48 | Common::Input::NfcState VirtualAmiibo::WriteNfcData( | ||
| 49 | [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) { | ||
| 50 | const Common::FS::IOFile amiibo_file{file_path, Common::FS::FileAccessMode::ReadWrite, | ||
| 51 | Common::FS::FileType::BinaryFile}; | ||
| 52 | |||
| 53 | if (!amiibo_file.IsOpen()) { | ||
| 54 | LOG_ERROR(Core, "Amiibo is already on use"); | ||
| 55 | return Common::Input::NfcState::WriteFailed; | ||
| 56 | } | ||
| 57 | |||
| 58 | if (!amiibo_file.Write(data)) { | ||
| 59 | LOG_ERROR(Service_NFP, "Error writting to file"); | ||
| 60 | return Common::Input::NfcState::WriteFailed; | ||
| 61 | } | ||
| 62 | |||
| 63 | return Common::Input::NfcState::Success; | ||
| 64 | } | ||
| 65 | |||
| 66 | VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const { | ||
| 67 | return state; | ||
| 68 | } | ||
| 69 | |||
| 70 | VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) { | ||
| 71 | const Common::FS::IOFile amiibo_file{filename, Common::FS::FileAccessMode::Read, | ||
| 72 | Common::FS::FileType::BinaryFile}; | ||
| 73 | |||
| 74 | if (state != State::WaitingForAmiibo) { | ||
| 75 | return Info::WrongDeviceState; | ||
| 76 | } | ||
| 77 | |||
| 78 | if (!amiibo_file.IsOpen()) { | ||
| 79 | return Info::UnableToLoad; | ||
| 80 | } | ||
| 81 | |||
| 82 | amiibo_data.resize(amiibo_size); | ||
| 83 | |||
| 84 | if (amiibo_file.Read(amiibo_data) < amiibo_size_without_password) { | ||
| 85 | return Info::NotAnAmiibo; | ||
| 86 | } | ||
| 87 | |||
| 88 | file_path = filename; | ||
| 89 | state = State::AmiiboIsOpen; | ||
| 90 | SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, amiibo_data}); | ||
| 91 | return Info::Success; | ||
| 92 | } | ||
| 93 | |||
| 94 | VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() { | ||
| 95 | state = polling_mode == Common::Input::PollingMode::NFC ? State::WaitingForAmiibo | ||
| 96 | : State::Initialized; | ||
| 97 | SetNfc(identifier, {Common::Input::NfcState::AmiiboRemoved, {}}); | ||
| 98 | return Info::Success; | ||
| 99 | } | ||
| 100 | |||
| 101 | } // namespace InputCommon | ||
diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h new file mode 100644 index 000000000..9eac07544 --- /dev/null +++ b/src/input_common/drivers/virtual_amiibo.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <string> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "input_common/input_engine.h" | ||
| 12 | |||
| 13 | namespace Common::FS { | ||
| 14 | class IOFile; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace InputCommon { | ||
| 18 | |||
| 19 | class VirtualAmiibo final : public InputEngine { | ||
| 20 | public: | ||
| 21 | enum class State { | ||
| 22 | Initialized, | ||
| 23 | WaitingForAmiibo, | ||
| 24 | AmiiboIsOpen, | ||
| 25 | }; | ||
| 26 | |||
| 27 | enum class Info { | ||
| 28 | Success, | ||
| 29 | UnableToLoad, | ||
| 30 | NotAnAmiibo, | ||
| 31 | WrongDeviceState, | ||
| 32 | Unknown, | ||
| 33 | }; | ||
| 34 | |||
| 35 | explicit VirtualAmiibo(std::string input_engine_); | ||
| 36 | ~VirtualAmiibo() override; | ||
| 37 | |||
| 38 | // Sets polling mode to a controller | ||
| 39 | Common::Input::PollingError SetPollingMode( | ||
| 40 | const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) override; | ||
| 41 | |||
| 42 | Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override; | ||
| 43 | |||
| 44 | Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_, | ||
| 45 | const std::vector<u8>& data) override; | ||
| 46 | |||
| 47 | State GetCurrentState() const; | ||
| 48 | |||
| 49 | Info LoadAmiibo(const std::string& amiibo_file); | ||
| 50 | Info CloseAmiibo(); | ||
| 51 | |||
| 52 | private: | ||
| 53 | static constexpr std::size_t amiibo_size = 0x21C; | ||
| 54 | static constexpr std::size_t amiibo_size_without_password = amiibo_size - 0x8; | ||
| 55 | |||
| 56 | std::string file_path{}; | ||
| 57 | State state{State::Initialized}; | ||
| 58 | std::vector<u8> amiibo_data; | ||
| 59 | Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Pasive}; | ||
| 60 | }; | ||
| 61 | } // namespace InputCommon | ||
diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp index 31e6f62ab..536d413a5 100644 --- a/src/input_common/helpers/stick_from_buttons.cpp +++ b/src/input_common/helpers/stick_from_buttons.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2017 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #include <chrono> | 4 | #include <chrono> |
| 6 | #include <cmath> | 5 | #include <cmath> |
diff --git a/src/input_common/helpers/stick_from_buttons.h b/src/input_common/helpers/stick_from_buttons.h index 437ace4f7..e8d865743 100644 --- a/src/input_common/helpers/stick_from_buttons.h +++ b/src/input_common/helpers/stick_from_buttons.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2017 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp index f1b57d03a..da4a3dca5 100644 --- a/src/input_common/helpers/touch_from_buttons.cpp +++ b/src/input_common/helpers/touch_from_buttons.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2020 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2020 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #include <algorithm> | 4 | #include <algorithm> |
| 6 | #include "common/settings.h" | 5 | #include "common/settings.h" |
diff --git a/src/input_common/helpers/touch_from_buttons.h b/src/input_common/helpers/touch_from_buttons.h index 628f18215..c6cb3ab3c 100644 --- a/src/input_common/helpers/touch_from_buttons.h +++ b/src/input_common/helpers/touch_from_buttons.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2020 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2020 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
diff --git a/src/input_common/helpers/udp_protocol.cpp b/src/input_common/helpers/udp_protocol.cpp index cdeab7e11..994380d21 100644 --- a/src/input_common/helpers/udp_protocol.cpp +++ b/src/input_common/helpers/udp_protocol.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2018 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2018 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #include <cstddef> | 4 | #include <cstddef> |
| 6 | #include <cstring> | 5 | #include <cstring> |
diff --git a/src/input_common/helpers/udp_protocol.h b/src/input_common/helpers/udp_protocol.h index 2d5d54ddb..d9643ffe0 100644 --- a/src/input_common/helpers/udp_protocol.h +++ b/src/input_common/helpers/udp_protocol.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2018 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2018 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
| @@ -8,9 +7,17 @@ | |||
| 8 | #include <optional> | 7 | #include <optional> |
| 9 | #include <type_traits> | 8 | #include <type_traits> |
| 10 | 9 | ||
| 10 | #ifdef _MSC_VER | ||
| 11 | #pragma warning(push) | ||
| 12 | #pragma warning(disable : 4701) // Potentially uninitialized local variable 'result' used | ||
| 13 | #endif | ||
| 14 | |||
| 11 | #include <boost/crc.hpp> | 15 | #include <boost/crc.hpp> |
| 12 | 16 | ||
| 13 | #include "common/bit_field.h" | 17 | #ifdef _MSC_VER |
| 18 | #pragma warning(pop) | ||
| 19 | #endif | ||
| 20 | |||
| 14 | #include "common/swap.h" | 21 | #include "common/swap.h" |
| 15 | 22 | ||
| 16 | namespace InputCommon::CemuhookUDP { | 23 | namespace InputCommon::CemuhookUDP { |
| @@ -77,7 +84,7 @@ enum RegisterFlags : u8 { | |||
| 77 | struct Version {}; | 84 | struct Version {}; |
| 78 | /** | 85 | /** |
| 79 | * Requests the server to send information about what controllers are plugged into the ports | 86 | * Requests the server to send information about what controllers are plugged into the ports |
| 80 | * In citra's case, we only have one controller, so for simplicity's sake, we can just send a | 87 | * In yuzu's case, we only have one controller, so for simplicity's sake, we can just send a |
| 81 | * request explicitly for the first controller port and leave it at that. In the future it would be | 88 | * request explicitly for the first controller port and leave it at that. In the future it would be |
| 82 | * nice to make this configurable | 89 | * nice to make this configurable |
| 83 | */ | 90 | */ |
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp index 65ae1b848..61cfd0911 100644 --- a/src/input_common/input_engine.cpp +++ b/src/input_common/input_engine.cpp | |||
| @@ -1,45 +1,43 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #include "common/logging/log.h" | 4 | #include "common/logging/log.h" |
| 6 | #include "common/param_package.h" | ||
| 7 | #include "input_common/input_engine.h" | 5 | #include "input_common/input_engine.h" |
| 8 | 6 | ||
| 9 | namespace InputCommon { | 7 | namespace InputCommon { |
| 10 | 8 | ||
| 11 | void InputEngine::PreSetController(const PadIdentifier& identifier) { | 9 | void InputEngine::PreSetController(const PadIdentifier& identifier) { |
| 12 | std::lock_guard lock{mutex}; | 10 | std::scoped_lock lock{mutex}; |
| 13 | controller_list.try_emplace(identifier); | 11 | controller_list.try_emplace(identifier); |
| 14 | } | 12 | } |
| 15 | 13 | ||
| 16 | void InputEngine::PreSetButton(const PadIdentifier& identifier, int button) { | 14 | void InputEngine::PreSetButton(const PadIdentifier& identifier, int button) { |
| 17 | std::lock_guard lock{mutex}; | 15 | std::scoped_lock lock{mutex}; |
| 18 | ControllerData& controller = controller_list.at(identifier); | 16 | ControllerData& controller = controller_list.at(identifier); |
| 19 | controller.buttons.try_emplace(button, false); | 17 | controller.buttons.try_emplace(button, false); |
| 20 | } | 18 | } |
| 21 | 19 | ||
| 22 | void InputEngine::PreSetHatButton(const PadIdentifier& identifier, int button) { | 20 | void InputEngine::PreSetHatButton(const PadIdentifier& identifier, int button) { |
| 23 | std::lock_guard lock{mutex}; | 21 | std::scoped_lock lock{mutex}; |
| 24 | ControllerData& controller = controller_list.at(identifier); | 22 | ControllerData& controller = controller_list.at(identifier); |
| 25 | controller.hat_buttons.try_emplace(button, u8{0}); | 23 | controller.hat_buttons.try_emplace(button, u8{0}); |
| 26 | } | 24 | } |
| 27 | 25 | ||
| 28 | void InputEngine::PreSetAxis(const PadIdentifier& identifier, int axis) { | 26 | void InputEngine::PreSetAxis(const PadIdentifier& identifier, int axis) { |
| 29 | std::lock_guard lock{mutex}; | 27 | std::scoped_lock lock{mutex}; |
| 30 | ControllerData& controller = controller_list.at(identifier); | 28 | ControllerData& controller = controller_list.at(identifier); |
| 31 | controller.axes.try_emplace(axis, 0.0f); | 29 | controller.axes.try_emplace(axis, 0.0f); |
| 32 | } | 30 | } |
| 33 | 31 | ||
| 34 | void InputEngine::PreSetMotion(const PadIdentifier& identifier, int motion) { | 32 | void InputEngine::PreSetMotion(const PadIdentifier& identifier, int motion) { |
| 35 | std::lock_guard lock{mutex}; | 33 | std::scoped_lock lock{mutex}; |
| 36 | ControllerData& controller = controller_list.at(identifier); | 34 | ControllerData& controller = controller_list.at(identifier); |
| 37 | controller.motions.try_emplace(motion); | 35 | controller.motions.try_emplace(motion); |
| 38 | } | 36 | } |
| 39 | 37 | ||
| 40 | void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool value) { | 38 | void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool value) { |
| 41 | { | 39 | { |
| 42 | std::lock_guard lock{mutex}; | 40 | std::scoped_lock lock{mutex}; |
| 43 | ControllerData& controller = controller_list.at(identifier); | 41 | ControllerData& controller = controller_list.at(identifier); |
| 44 | if (!configuring) { | 42 | if (!configuring) { |
| 45 | controller.buttons.insert_or_assign(button, value); | 43 | controller.buttons.insert_or_assign(button, value); |
| @@ -50,7 +48,7 @@ void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool va | |||
| 50 | 48 | ||
| 51 | void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 value) { | 49 | void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 value) { |
| 52 | { | 50 | { |
| 53 | std::lock_guard lock{mutex}; | 51 | std::scoped_lock lock{mutex}; |
| 54 | ControllerData& controller = controller_list.at(identifier); | 52 | ControllerData& controller = controller_list.at(identifier); |
| 55 | if (!configuring) { | 53 | if (!configuring) { |
| 56 | controller.hat_buttons.insert_or_assign(button, value); | 54 | controller.hat_buttons.insert_or_assign(button, value); |
| @@ -61,7 +59,7 @@ void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 v | |||
| 61 | 59 | ||
| 62 | void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) { | 60 | void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) { |
| 63 | { | 61 | { |
| 64 | std::lock_guard lock{mutex}; | 62 | std::scoped_lock lock{mutex}; |
| 65 | ControllerData& controller = controller_list.at(identifier); | 63 | ControllerData& controller = controller_list.at(identifier); |
| 66 | if (!configuring) { | 64 | if (!configuring) { |
| 67 | controller.axes.insert_or_assign(axis, value); | 65 | controller.axes.insert_or_assign(axis, value); |
| @@ -70,9 +68,9 @@ void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) | |||
| 70 | TriggerOnAxisChange(identifier, axis, value); | 68 | TriggerOnAxisChange(identifier, axis, value); |
| 71 | } | 69 | } |
| 72 | 70 | ||
| 73 | void InputEngine::SetBattery(const PadIdentifier& identifier, BatteryLevel value) { | 71 | void InputEngine::SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value) { |
| 74 | { | 72 | { |
| 75 | std::lock_guard lock{mutex}; | 73 | std::scoped_lock lock{mutex}; |
| 76 | ControllerData& controller = controller_list.at(identifier); | 74 | ControllerData& controller = controller_list.at(identifier); |
| 77 | if (!configuring) { | 75 | if (!configuring) { |
| 78 | controller.battery = value; | 76 | controller.battery = value; |
| @@ -83,7 +81,7 @@ void InputEngine::SetBattery(const PadIdentifier& identifier, BatteryLevel value | |||
| 83 | 81 | ||
| 84 | void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value) { | 82 | void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value) { |
| 85 | { | 83 | { |
| 86 | std::lock_guard lock{mutex}; | 84 | std::scoped_lock lock{mutex}; |
| 87 | ControllerData& controller = controller_list.at(identifier); | 85 | ControllerData& controller = controller_list.at(identifier); |
| 88 | if (!configuring) { | 86 | if (!configuring) { |
| 89 | controller.motions.insert_or_assign(motion, value); | 87 | controller.motions.insert_or_assign(motion, value); |
| @@ -92,8 +90,31 @@ void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const B | |||
| 92 | TriggerOnMotionChange(identifier, motion, value); | 90 | TriggerOnMotionChange(identifier, motion, value); |
| 93 | } | 91 | } |
| 94 | 92 | ||
| 93 | void InputEngine::SetCamera(const PadIdentifier& identifier, | ||
| 94 | const Common::Input::CameraStatus& value) { | ||
| 95 | { | ||
| 96 | std::scoped_lock lock{mutex}; | ||
| 97 | ControllerData& controller = controller_list.at(identifier); | ||
| 98 | if (!configuring) { | ||
| 99 | controller.camera = value; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | TriggerOnCameraChange(identifier, value); | ||
| 103 | } | ||
| 104 | |||
| 105 | void InputEngine::SetNfc(const PadIdentifier& identifier, const Common::Input::NfcStatus& value) { | ||
| 106 | { | ||
| 107 | std::scoped_lock lock{mutex}; | ||
| 108 | ControllerData& controller = controller_list.at(identifier); | ||
| 109 | if (!configuring) { | ||
| 110 | controller.nfc = value; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | TriggerOnNfcChange(identifier, value); | ||
| 114 | } | ||
| 115 | |||
| 95 | bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { | 116 | bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { |
| 96 | std::lock_guard lock{mutex}; | 117 | std::scoped_lock lock{mutex}; |
| 97 | const auto controller_iter = controller_list.find(identifier); | 118 | const auto controller_iter = controller_list.find(identifier); |
| 98 | if (controller_iter == controller_list.cend()) { | 119 | if (controller_iter == controller_list.cend()) { |
| 99 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | 120 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), |
| @@ -110,7 +131,7 @@ bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { | |||
| 110 | } | 131 | } |
| 111 | 132 | ||
| 112 | bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const { | 133 | bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const { |
| 113 | std::lock_guard lock{mutex}; | 134 | std::scoped_lock lock{mutex}; |
| 114 | const auto controller_iter = controller_list.find(identifier); | 135 | const auto controller_iter = controller_list.find(identifier); |
| 115 | if (controller_iter == controller_list.cend()) { | 136 | if (controller_iter == controller_list.cend()) { |
| 116 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | 137 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), |
| @@ -127,7 +148,7 @@ bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 d | |||
| 127 | } | 148 | } |
| 128 | 149 | ||
| 129 | f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const { | 150 | f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const { |
| 130 | std::lock_guard lock{mutex}; | 151 | std::scoped_lock lock{mutex}; |
| 131 | const auto controller_iter = controller_list.find(identifier); | 152 | const auto controller_iter = controller_list.find(identifier); |
| 132 | if (controller_iter == controller_list.cend()) { | 153 | if (controller_iter == controller_list.cend()) { |
| 133 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | 154 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), |
| @@ -143,20 +164,20 @@ f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const { | |||
| 143 | return axis_iter->second; | 164 | return axis_iter->second; |
| 144 | } | 165 | } |
| 145 | 166 | ||
| 146 | BatteryLevel InputEngine::GetBattery(const PadIdentifier& identifier) const { | 167 | Common::Input::BatteryLevel InputEngine::GetBattery(const PadIdentifier& identifier) const { |
| 147 | std::lock_guard lock{mutex}; | 168 | std::scoped_lock lock{mutex}; |
| 148 | const auto controller_iter = controller_list.find(identifier); | 169 | const auto controller_iter = controller_list.find(identifier); |
| 149 | if (controller_iter == controller_list.cend()) { | 170 | if (controller_iter == controller_list.cend()) { |
| 150 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | 171 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), |
| 151 | identifier.pad, identifier.port); | 172 | identifier.pad, identifier.port); |
| 152 | return BatteryLevel::Charging; | 173 | return Common::Input::BatteryLevel::Charging; |
| 153 | } | 174 | } |
| 154 | const ControllerData& controller = controller_iter->second; | 175 | const ControllerData& controller = controller_iter->second; |
| 155 | return controller.battery; | 176 | return controller.battery; |
| 156 | } | 177 | } |
| 157 | 178 | ||
| 158 | BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) const { | 179 | BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) const { |
| 159 | std::lock_guard lock{mutex}; | 180 | std::scoped_lock lock{mutex}; |
| 160 | const auto controller_iter = controller_list.find(identifier); | 181 | const auto controller_iter = controller_list.find(identifier); |
| 161 | if (controller_iter == controller_list.cend()) { | 182 | if (controller_iter == controller_list.cend()) { |
| 162 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | 183 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), |
| @@ -167,6 +188,30 @@ BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) | |||
| 167 | return controller.motions.at(motion); | 188 | return controller.motions.at(motion); |
| 168 | } | 189 | } |
| 169 | 190 | ||
| 191 | Common::Input::CameraStatus InputEngine::GetCamera(const PadIdentifier& identifier) const { | ||
| 192 | std::scoped_lock lock{mutex}; | ||
| 193 | const auto controller_iter = controller_list.find(identifier); | ||
| 194 | if (controller_iter == controller_list.cend()) { | ||
| 195 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | ||
| 196 | identifier.pad, identifier.port); | ||
| 197 | return {}; | ||
| 198 | } | ||
| 199 | const ControllerData& controller = controller_iter->second; | ||
| 200 | return controller.camera; | ||
| 201 | } | ||
| 202 | |||
| 203 | Common::Input::NfcStatus InputEngine::GetNfc(const PadIdentifier& identifier) const { | ||
| 204 | std::scoped_lock lock{mutex}; | ||
| 205 | const auto controller_iter = controller_list.find(identifier); | ||
| 206 | if (controller_iter == controller_list.cend()) { | ||
| 207 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | ||
| 208 | identifier.pad, identifier.port); | ||
| 209 | return {}; | ||
| 210 | } | ||
| 211 | const ControllerData& controller = controller_iter->second; | ||
| 212 | return controller.nfc; | ||
| 213 | } | ||
| 214 | |||
| 170 | void InputEngine::ResetButtonState() { | 215 | void InputEngine::ResetButtonState() { |
| 171 | for (const auto& controller : controller_list) { | 216 | for (const auto& controller : controller_list) { |
| 172 | for (const auto& button : controller.second.buttons) { | 217 | for (const auto& button : controller.second.buttons) { |
| @@ -187,7 +232,7 @@ void InputEngine::ResetAnalogState() { | |||
| 187 | } | 232 | } |
| 188 | 233 | ||
| 189 | void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value) { | 234 | void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value) { |
| 190 | std::lock_guard lock{mutex_callback}; | 235 | std::scoped_lock lock{mutex_callback}; |
| 191 | for (const auto& poller_pair : callback_list) { | 236 | for (const auto& poller_pair : callback_list) { |
| 192 | const InputIdentifier& poller = poller_pair.second; | 237 | const InputIdentifier& poller = poller_pair.second; |
| 193 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Button, button)) { | 238 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Button, button)) { |
| @@ -215,7 +260,7 @@ void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int but | |||
| 215 | } | 260 | } |
| 216 | 261 | ||
| 217 | void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value) { | 262 | void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value) { |
| 218 | std::lock_guard lock{mutex_callback}; | 263 | std::scoped_lock lock{mutex_callback}; |
| 219 | for (const auto& poller_pair : callback_list) { | 264 | for (const auto& poller_pair : callback_list) { |
| 220 | const InputIdentifier& poller = poller_pair.second; | 265 | const InputIdentifier& poller = poller_pair.second; |
| 221 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::HatButton, button)) { | 266 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::HatButton, button)) { |
| @@ -244,7 +289,7 @@ void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int | |||
| 244 | } | 289 | } |
| 245 | 290 | ||
| 246 | void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value) { | 291 | void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value) { |
| 247 | std::lock_guard lock{mutex_callback}; | 292 | std::scoped_lock lock{mutex_callback}; |
| 248 | for (const auto& poller_pair : callback_list) { | 293 | for (const auto& poller_pair : callback_list) { |
| 249 | const InputIdentifier& poller = poller_pair.second; | 294 | const InputIdentifier& poller = poller_pair.second; |
| 250 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Analog, axis)) { | 295 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Analog, axis)) { |
| @@ -270,8 +315,8 @@ void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, | |||
| 270 | } | 315 | } |
| 271 | 316 | ||
| 272 | void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier, | 317 | void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier, |
| 273 | [[maybe_unused]] BatteryLevel value) { | 318 | [[maybe_unused]] Common::Input::BatteryLevel value) { |
| 274 | std::lock_guard lock{mutex_callback}; | 319 | std::scoped_lock lock{mutex_callback}; |
| 275 | for (const auto& poller_pair : callback_list) { | 320 | for (const auto& poller_pair : callback_list) { |
| 276 | const InputIdentifier& poller = poller_pair.second; | 321 | const InputIdentifier& poller = poller_pair.second; |
| 277 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Battery, 0)) { | 322 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Battery, 0)) { |
| @@ -285,7 +330,7 @@ void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier, | |||
| 285 | 330 | ||
| 286 | void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int motion, | 331 | void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int motion, |
| 287 | const BasicMotion& value) { | 332 | const BasicMotion& value) { |
| 288 | std::lock_guard lock{mutex_callback}; | 333 | std::scoped_lock lock{mutex_callback}; |
| 289 | for (const auto& poller_pair : callback_list) { | 334 | for (const auto& poller_pair : callback_list) { |
| 290 | const InputIdentifier& poller = poller_pair.second; | 335 | const InputIdentifier& poller = poller_pair.second; |
| 291 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Motion, motion)) { | 336 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Motion, motion)) { |
| @@ -319,6 +364,34 @@ void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int mot | |||
| 319 | }); | 364 | }); |
| 320 | } | 365 | } |
| 321 | 366 | ||
| 367 | void InputEngine::TriggerOnCameraChange(const PadIdentifier& identifier, | ||
| 368 | [[maybe_unused]] const Common::Input::CameraStatus& value) { | ||
| 369 | std::scoped_lock lock{mutex_callback}; | ||
| 370 | for (const auto& poller_pair : callback_list) { | ||
| 371 | const InputIdentifier& poller = poller_pair.second; | ||
| 372 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Camera, 0)) { | ||
| 373 | continue; | ||
| 374 | } | ||
| 375 | if (poller.callback.on_change) { | ||
| 376 | poller.callback.on_change(); | ||
| 377 | } | ||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 381 | void InputEngine::TriggerOnNfcChange(const PadIdentifier& identifier, | ||
| 382 | [[maybe_unused]] const Common::Input::NfcStatus& value) { | ||
| 383 | std::scoped_lock lock{mutex_callback}; | ||
| 384 | for (const auto& poller_pair : callback_list) { | ||
| 385 | const InputIdentifier& poller = poller_pair.second; | ||
| 386 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Nfc, 0)) { | ||
| 387 | continue; | ||
| 388 | } | ||
| 389 | if (poller.callback.on_change) { | ||
| 390 | poller.callback.on_change(); | ||
| 391 | } | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 322 | bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier, | 395 | bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier, |
| 323 | const PadIdentifier& identifier, EngineInputType type, | 396 | const PadIdentifier& identifier, EngineInputType type, |
| 324 | int index) const { | 397 | int index) const { |
| @@ -347,18 +420,18 @@ const std::string& InputEngine::GetEngineName() const { | |||
| 347 | } | 420 | } |
| 348 | 421 | ||
| 349 | int InputEngine::SetCallback(InputIdentifier input_identifier) { | 422 | int InputEngine::SetCallback(InputIdentifier input_identifier) { |
| 350 | std::lock_guard lock{mutex_callback}; | 423 | std::scoped_lock lock{mutex_callback}; |
| 351 | callback_list.insert_or_assign(last_callback_key, std::move(input_identifier)); | 424 | callback_list.insert_or_assign(last_callback_key, std::move(input_identifier)); |
| 352 | return last_callback_key++; | 425 | return last_callback_key++; |
| 353 | } | 426 | } |
| 354 | 427 | ||
| 355 | void InputEngine::SetMappingCallback(MappingCallback callback) { | 428 | void InputEngine::SetMappingCallback(MappingCallback callback) { |
| 356 | std::lock_guard lock{mutex_callback}; | 429 | std::scoped_lock lock{mutex_callback}; |
| 357 | mapping_callback = std::move(callback); | 430 | mapping_callback = std::move(callback); |
| 358 | } | 431 | } |
| 359 | 432 | ||
| 360 | void InputEngine::DeleteCallback(int key) { | 433 | void InputEngine::DeleteCallback(int key) { |
| 361 | std::lock_guard lock{mutex_callback}; | 434 | std::scoped_lock lock{mutex_callback}; |
| 362 | const auto& iterator = callback_list.find(key); | 435 | const auto& iterator = callback_list.find(key); |
| 363 | if (iterator == callback_list.end()) { | 436 | if (iterator == callback_list.end()) { |
| 364 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); | 437 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); |
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h index c6c027aef..cfbdb26bd 100644 --- a/src/input_common/input_engine.h +++ b/src/input_common/input_engine.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
| @@ -34,24 +33,16 @@ struct BasicMotion { | |||
| 34 | u64 delta_timestamp{}; | 33 | u64 delta_timestamp{}; |
| 35 | }; | 34 | }; |
| 36 | 35 | ||
| 37 | // Stages of a battery charge | ||
| 38 | enum class BatteryLevel { | ||
| 39 | Empty, | ||
| 40 | Critical, | ||
| 41 | Low, | ||
| 42 | Medium, | ||
| 43 | Full, | ||
| 44 | Charging, | ||
| 45 | }; | ||
| 46 | |||
| 47 | // Types of input that are stored in the engine | 36 | // Types of input that are stored in the engine |
| 48 | enum class EngineInputType { | 37 | enum class EngineInputType { |
| 49 | None, | 38 | None, |
| 39 | Analog, | ||
| 40 | Battery, | ||
| 50 | Button, | 41 | Button, |
| 42 | Camera, | ||
| 51 | HatButton, | 43 | HatButton, |
| 52 | Analog, | ||
| 53 | Motion, | 44 | Motion, |
| 54 | Battery, | 45 | Nfc, |
| 55 | }; | 46 | }; |
| 56 | 47 | ||
| 57 | namespace std { | 48 | namespace std { |
| @@ -126,10 +117,29 @@ public: | |||
| 126 | // Sets polling mode to a controller | 117 | // Sets polling mode to a controller |
| 127 | virtual Common::Input::PollingError SetPollingMode( | 118 | virtual Common::Input::PollingError SetPollingMode( |
| 128 | [[maybe_unused]] const PadIdentifier& identifier, | 119 | [[maybe_unused]] const PadIdentifier& identifier, |
| 129 | [[maybe_unused]] const Common::Input::PollingMode vibration) { | 120 | [[maybe_unused]] const Common::Input::PollingMode polling_mode) { |
| 130 | return Common::Input::PollingError::NotSupported; | 121 | return Common::Input::PollingError::NotSupported; |
| 131 | } | 122 | } |
| 132 | 123 | ||
| 124 | // Sets camera format to a controller | ||
| 125 | virtual Common::Input::CameraError SetCameraFormat( | ||
| 126 | [[maybe_unused]] const PadIdentifier& identifier, | ||
| 127 | [[maybe_unused]] Common::Input::CameraFormat camera_format) { | ||
| 128 | return Common::Input::CameraError::NotSupported; | ||
| 129 | } | ||
| 130 | |||
| 131 | // Request nfc data from a controller | ||
| 132 | virtual Common::Input::NfcState SupportsNfc( | ||
| 133 | [[maybe_unused]] const PadIdentifier& identifier) const { | ||
| 134 | return Common::Input::NfcState::NotSupported; | ||
| 135 | } | ||
| 136 | |||
| 137 | // Writes data to an nfc tag | ||
| 138 | virtual Common::Input::NfcState WriteNfcData([[maybe_unused]] const PadIdentifier& identifier, | ||
| 139 | [[maybe_unused]] const std::vector<u8>& data) { | ||
| 140 | return Common::Input::NfcState::NotSupported; | ||
| 141 | } | ||
| 142 | |||
| 133 | // Returns the engine name | 143 | // Returns the engine name |
| 134 | [[nodiscard]] const std::string& GetEngineName() const; | 144 | [[nodiscard]] const std::string& GetEngineName() const; |
| 135 | 145 | ||
| @@ -167,6 +177,11 @@ public: | |||
| 167 | return 0; | 177 | return 0; |
| 168 | } | 178 | } |
| 169 | 179 | ||
| 180 | /// Returns true if axis of a stick aren't mapped in the correct direction | ||
| 181 | virtual bool IsStickInverted([[maybe_unused]] const Common::ParamPackage& params) { | ||
| 182 | return false; | ||
| 183 | } | ||
| 184 | |||
| 170 | void PreSetController(const PadIdentifier& identifier); | 185 | void PreSetController(const PadIdentifier& identifier); |
| 171 | void PreSetButton(const PadIdentifier& identifier, int button); | 186 | void PreSetButton(const PadIdentifier& identifier, int button); |
| 172 | void PreSetHatButton(const PadIdentifier& identifier, int button); | 187 | void PreSetHatButton(const PadIdentifier& identifier, int button); |
| @@ -178,8 +193,10 @@ public: | |||
| 178 | bool GetButton(const PadIdentifier& identifier, int button) const; | 193 | bool GetButton(const PadIdentifier& identifier, int button) const; |
| 179 | bool GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const; | 194 | bool GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const; |
| 180 | f32 GetAxis(const PadIdentifier& identifier, int axis) const; | 195 | f32 GetAxis(const PadIdentifier& identifier, int axis) const; |
| 181 | BatteryLevel GetBattery(const PadIdentifier& identifier) const; | 196 | Common::Input::BatteryLevel GetBattery(const PadIdentifier& identifier) const; |
| 182 | BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const; | 197 | BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const; |
| 198 | Common::Input::CameraStatus GetCamera(const PadIdentifier& identifier) const; | ||
| 199 | Common::Input::NfcStatus GetNfc(const PadIdentifier& identifier) const; | ||
| 183 | 200 | ||
| 184 | int SetCallback(InputIdentifier input_identifier); | 201 | int SetCallback(InputIdentifier input_identifier); |
| 185 | void SetMappingCallback(MappingCallback callback); | 202 | void SetMappingCallback(MappingCallback callback); |
| @@ -189,8 +206,10 @@ protected: | |||
| 189 | void SetButton(const PadIdentifier& identifier, int button, bool value); | 206 | void SetButton(const PadIdentifier& identifier, int button, bool value); |
| 190 | void SetHatButton(const PadIdentifier& identifier, int button, u8 value); | 207 | void SetHatButton(const PadIdentifier& identifier, int button, u8 value); |
| 191 | void SetAxis(const PadIdentifier& identifier, int axis, f32 value); | 208 | void SetAxis(const PadIdentifier& identifier, int axis, f32 value); |
| 192 | void SetBattery(const PadIdentifier& identifier, BatteryLevel value); | 209 | void SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value); |
| 193 | void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value); | 210 | void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value); |
| 211 | void SetCamera(const PadIdentifier& identifier, const Common::Input::CameraStatus& value); | ||
| 212 | void SetNfc(const PadIdentifier& identifier, const Common::Input::NfcStatus& value); | ||
| 194 | 213 | ||
| 195 | virtual std::string GetHatButtonName([[maybe_unused]] u8 direction_value) const { | 214 | virtual std::string GetHatButtonName([[maybe_unused]] u8 direction_value) const { |
| 196 | return "Unknown"; | 215 | return "Unknown"; |
| @@ -202,15 +221,20 @@ private: | |||
| 202 | std::unordered_map<int, u8> hat_buttons; | 221 | std::unordered_map<int, u8> hat_buttons; |
| 203 | std::unordered_map<int, float> axes; | 222 | std::unordered_map<int, float> axes; |
| 204 | std::unordered_map<int, BasicMotion> motions; | 223 | std::unordered_map<int, BasicMotion> motions; |
| 205 | BatteryLevel battery{}; | 224 | Common::Input::BatteryLevel battery{}; |
| 225 | Common::Input::CameraStatus camera{}; | ||
| 226 | Common::Input::NfcStatus nfc{}; | ||
| 206 | }; | 227 | }; |
| 207 | 228 | ||
| 208 | void TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value); | 229 | void TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value); |
| 209 | void TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value); | 230 | void TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value); |
| 210 | void TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value); | 231 | void TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value); |
| 211 | void TriggerOnBatteryChange(const PadIdentifier& identifier, BatteryLevel value); | 232 | void TriggerOnBatteryChange(const PadIdentifier& identifier, Common::Input::BatteryLevel value); |
| 212 | void TriggerOnMotionChange(const PadIdentifier& identifier, int motion, | 233 | void TriggerOnMotionChange(const PadIdentifier& identifier, int motion, |
| 213 | const BasicMotion& value); | 234 | const BasicMotion& value); |
| 235 | void TriggerOnCameraChange(const PadIdentifier& identifier, | ||
| 236 | const Common::Input::CameraStatus& value); | ||
| 237 | void TriggerOnNfcChange(const PadIdentifier& identifier, const Common::Input::NfcStatus& value); | ||
| 214 | 238 | ||
| 215 | bool IsInputIdentifierEqual(const InputIdentifier& input_identifier, | 239 | bool IsInputIdentifierEqual(const InputIdentifier& input_identifier, |
| 216 | const PadIdentifier& identifier, EngineInputType type, | 240 | const PadIdentifier& identifier, EngineInputType type, |
diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp index fb78093b8..0fa4b1ddb 100644 --- a/src/input_common/input_mapping.cpp +++ b/src/input_common/input_mapping.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #include "common/settings.h" | 4 | #include "common/settings.h" |
| 6 | #include "input_common/input_engine.h" | 5 | #include "input_common/input_engine.h" |
diff --git a/src/input_common/input_mapping.h b/src/input_common/input_mapping.h index e0dfbc7ad..79bd083e0 100644 --- a/src/input_common/input_mapping.h +++ b/src/input_common/input_mapping.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 7f3c08597..75705b67e 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #include "common/common_types.h" | 4 | #include "common/common_types.h" |
| 6 | #include "common/input.h" | 5 | #include "common/input.h" |
| @@ -470,7 +469,7 @@ public: | |||
| 470 | } | 469 | } |
| 471 | 470 | ||
| 472 | Common::Input::BatteryStatus GetStatus() const { | 471 | Common::Input::BatteryStatus GetStatus() const { |
| 473 | return static_cast<Common::Input::BatteryLevel>(input_engine->GetBattery(identifier)); | 472 | return input_engine->GetBattery(identifier); |
| 474 | } | 473 | } |
| 475 | 474 | ||
| 476 | void ForceUpdate() override { | 475 | void ForceUpdate() override { |
| @@ -665,6 +664,88 @@ private: | |||
| 665 | InputEngine* input_engine; | 664 | InputEngine* input_engine; |
| 666 | }; | 665 | }; |
| 667 | 666 | ||
| 667 | class InputFromCamera final : public Common::Input::InputDevice { | ||
| 668 | public: | ||
| 669 | explicit InputFromCamera(PadIdentifier identifier_, InputEngine* input_engine_) | ||
| 670 | : identifier(identifier_), input_engine(input_engine_) { | ||
| 671 | UpdateCallback engine_callback{[this]() { OnChange(); }}; | ||
| 672 | const InputIdentifier input_identifier{ | ||
| 673 | .identifier = identifier, | ||
| 674 | .type = EngineInputType::Camera, | ||
| 675 | .index = 0, | ||
| 676 | .callback = engine_callback, | ||
| 677 | }; | ||
| 678 | callback_key = input_engine->SetCallback(input_identifier); | ||
| 679 | } | ||
| 680 | |||
| 681 | ~InputFromCamera() override { | ||
| 682 | input_engine->DeleteCallback(callback_key); | ||
| 683 | } | ||
| 684 | |||
| 685 | Common::Input::CameraStatus GetStatus() const { | ||
| 686 | return input_engine->GetCamera(identifier); | ||
| 687 | } | ||
| 688 | |||
| 689 | void ForceUpdate() override { | ||
| 690 | OnChange(); | ||
| 691 | } | ||
| 692 | |||
| 693 | void OnChange() { | ||
| 694 | const Common::Input::CallbackStatus status{ | ||
| 695 | .type = Common::Input::InputType::IrSensor, | ||
| 696 | .camera_status = GetStatus(), | ||
| 697 | }; | ||
| 698 | |||
| 699 | TriggerOnChange(status); | ||
| 700 | } | ||
| 701 | |||
| 702 | private: | ||
| 703 | const PadIdentifier identifier; | ||
| 704 | int callback_key; | ||
| 705 | InputEngine* input_engine; | ||
| 706 | }; | ||
| 707 | |||
| 708 | class InputFromNfc final : public Common::Input::InputDevice { | ||
| 709 | public: | ||
| 710 | explicit InputFromNfc(PadIdentifier identifier_, InputEngine* input_engine_) | ||
| 711 | : identifier(identifier_), input_engine(input_engine_) { | ||
| 712 | UpdateCallback engine_callback{[this]() { OnChange(); }}; | ||
| 713 | const InputIdentifier input_identifier{ | ||
| 714 | .identifier = identifier, | ||
| 715 | .type = EngineInputType::Nfc, | ||
| 716 | .index = 0, | ||
| 717 | .callback = engine_callback, | ||
| 718 | }; | ||
| 719 | callback_key = input_engine->SetCallback(input_identifier); | ||
| 720 | } | ||
| 721 | |||
| 722 | ~InputFromNfc() override { | ||
| 723 | input_engine->DeleteCallback(callback_key); | ||
| 724 | } | ||
| 725 | |||
| 726 | Common::Input::NfcStatus GetStatus() const { | ||
| 727 | return input_engine->GetNfc(identifier); | ||
| 728 | } | ||
| 729 | |||
| 730 | void ForceUpdate() override { | ||
| 731 | OnChange(); | ||
| 732 | } | ||
| 733 | |||
| 734 | void OnChange() { | ||
| 735 | const Common::Input::CallbackStatus status{ | ||
| 736 | .type = Common::Input::InputType::Nfc, | ||
| 737 | .nfc_status = GetStatus(), | ||
| 738 | }; | ||
| 739 | |||
| 740 | TriggerOnChange(status); | ||
| 741 | } | ||
| 742 | |||
| 743 | private: | ||
| 744 | const PadIdentifier identifier; | ||
| 745 | int callback_key; | ||
| 746 | InputEngine* input_engine; | ||
| 747 | }; | ||
| 748 | |||
| 668 | class OutputFromIdentifier final : public Common::Input::OutputDevice { | 749 | class OutputFromIdentifier final : public Common::Input::OutputDevice { |
| 669 | public: | 750 | public: |
| 670 | explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_) | 751 | explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_) |
| @@ -683,6 +764,18 @@ public: | |||
| 683 | return input_engine->SetPollingMode(identifier, polling_mode); | 764 | return input_engine->SetPollingMode(identifier, polling_mode); |
| 684 | } | 765 | } |
| 685 | 766 | ||
| 767 | Common::Input::CameraError SetCameraFormat(Common::Input::CameraFormat camera_format) override { | ||
| 768 | return input_engine->SetCameraFormat(identifier, camera_format); | ||
| 769 | } | ||
| 770 | |||
| 771 | Common::Input::NfcState SupportsNfc() const override { | ||
| 772 | return input_engine->SupportsNfc(identifier); | ||
| 773 | } | ||
| 774 | |||
| 775 | Common::Input::NfcState WriteNfcData(const std::vector<u8>& data) override { | ||
| 776 | return input_engine->WriteNfcData(identifier, data); | ||
| 777 | } | ||
| 778 | |||
| 686 | private: | 779 | private: |
| 687 | const PadIdentifier identifier; | 780 | const PadIdentifier identifier; |
| 688 | InputEngine* input_engine; | 781 | InputEngine* input_engine; |
| @@ -733,7 +826,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateHatButtonDevice( | |||
| 733 | std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice( | 826 | std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice( |
| 734 | const Common::ParamPackage& params) { | 827 | const Common::ParamPackage& params) { |
| 735 | const auto deadzone = std::clamp(params.Get("deadzone", 0.15f), 0.0f, 1.0f); | 828 | const auto deadzone = std::clamp(params.Get("deadzone", 0.15f), 0.0f, 1.0f); |
| 736 | const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f); | 829 | const auto range = std::clamp(params.Get("range", 0.95f), 0.25f, 1.50f); |
| 737 | const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f); | 830 | const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f); |
| 738 | const PadIdentifier identifier = { | 831 | const PadIdentifier identifier = { |
| 739 | .guid = Common::UUID{params.Get("guid", "")}, | 832 | .guid = Common::UUID{params.Get("guid", "")}, |
| @@ -780,6 +873,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateAnalogDevice( | |||
| 780 | .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f), | 873 | .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f), |
| 781 | .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f), | 874 | .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f), |
| 782 | .inverted = params.Get("invert", "+") == "-", | 875 | .inverted = params.Get("invert", "+") == "-", |
| 876 | .toggle = static_cast<bool>(params.Get("toggle", false)), | ||
| 783 | }; | 877 | }; |
| 784 | input_engine->PreSetController(identifier); | 878 | input_engine->PreSetController(identifier); |
| 785 | input_engine->PreSetAxis(identifier, axis); | 879 | input_engine->PreSetAxis(identifier, axis); |
| @@ -921,6 +1015,30 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateMotionDevice( | |||
| 921 | properties_y, properties_z, input_engine.get()); | 1015 | properties_y, properties_z, input_engine.get()); |
| 922 | } | 1016 | } |
| 923 | 1017 | ||
| 1018 | std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateCameraDevice( | ||
| 1019 | const Common::ParamPackage& params) { | ||
| 1020 | const PadIdentifier identifier = { | ||
| 1021 | .guid = Common::UUID{params.Get("guid", "")}, | ||
| 1022 | .port = static_cast<std::size_t>(params.Get("port", 0)), | ||
| 1023 | .pad = static_cast<std::size_t>(params.Get("pad", 0)), | ||
| 1024 | }; | ||
| 1025 | |||
| 1026 | input_engine->PreSetController(identifier); | ||
| 1027 | return std::make_unique<InputFromCamera>(identifier, input_engine.get()); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateNfcDevice( | ||
| 1031 | const Common::ParamPackage& params) { | ||
| 1032 | const PadIdentifier identifier = { | ||
| 1033 | .guid = Common::UUID{params.Get("guid", "")}, | ||
| 1034 | .port = static_cast<std::size_t>(params.Get("port", 0)), | ||
| 1035 | .pad = static_cast<std::size_t>(params.Get("pad", 0)), | ||
| 1036 | }; | ||
| 1037 | |||
| 1038 | input_engine->PreSetController(identifier); | ||
| 1039 | return std::make_unique<InputFromNfc>(identifier, input_engine.get()); | ||
| 1040 | } | ||
| 1041 | |||
| 924 | InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_) | 1042 | InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_) |
| 925 | : input_engine(std::move(input_engine_)) {} | 1043 | : input_engine(std::move(input_engine_)) {} |
| 926 | 1044 | ||
| @@ -929,6 +1047,12 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::Create( | |||
| 929 | if (params.Has("battery")) { | 1047 | if (params.Has("battery")) { |
| 930 | return CreateBatteryDevice(params); | 1048 | return CreateBatteryDevice(params); |
| 931 | } | 1049 | } |
| 1050 | if (params.Has("camera")) { | ||
| 1051 | return CreateCameraDevice(params); | ||
| 1052 | } | ||
| 1053 | if (params.Has("nfc")) { | ||
| 1054 | return CreateNfcDevice(params); | ||
| 1055 | } | ||
| 932 | if (params.Has("button") && params.Has("axis")) { | 1056 | if (params.Has("button") && params.Has("axis")) { |
| 933 | return CreateTriggerDevice(params); | 1057 | return CreateTriggerDevice(params); |
| 934 | } | 1058 | } |
diff --git a/src/input_common/input_poller.h b/src/input_common/input_poller.h index 8a0977d58..d7db13ce4 100644 --- a/src/input_common/input_poller.h +++ b/src/input_common/input_poller.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
| @@ -212,6 +211,27 @@ private: | |||
| 212 | */ | 211 | */ |
| 213 | std::unique_ptr<Common::Input::InputDevice> CreateMotionDevice(Common::ParamPackage params); | 212 | std::unique_ptr<Common::Input::InputDevice> CreateMotionDevice(Common::ParamPackage params); |
| 214 | 213 | ||
| 214 | /** | ||
| 215 | * Creates a camera device from the parameters given. | ||
| 216 | * @param params contains parameters for creating the device: | ||
| 217 | * - "guid": text string for identifying controllers | ||
| 218 | * - "port": port of the connected device | ||
| 219 | * - "pad": slot of the connected controller | ||
| 220 | * @returns a unique input device with the parameters specified | ||
| 221 | */ | ||
| 222 | std::unique_ptr<Common::Input::InputDevice> CreateCameraDevice( | ||
| 223 | const Common::ParamPackage& params); | ||
| 224 | |||
| 225 | /** | ||
| 226 | * Creates a nfc device from the parameters given. | ||
| 227 | * @param params contains parameters for creating the device: | ||
| 228 | * - "guid": text string for identifying controllers | ||
| 229 | * - "port": port of the connected device | ||
| 230 | * - "pad": slot of the connected controller | ||
| 231 | * @returns a unique input device with the parameters specified | ||
| 232 | */ | ||
| 233 | std::unique_ptr<Common::Input::InputDevice> CreateNfcDevice(const Common::ParamPackage& params); | ||
| 234 | |||
| 215 | std::shared_ptr<InputEngine> input_engine; | 235 | std::shared_ptr<InputEngine> input_engine; |
| 216 | }; | 236 | }; |
| 217 | } // namespace InputCommon | 237 | } // namespace InputCommon |
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index a4d7ed645..b2064ef95 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp | |||
| @@ -1,17 +1,17 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2017 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #include <memory> | 4 | #include <memory> |
| 6 | #include <thread> | ||
| 7 | #include "common/input.h" | 5 | #include "common/input.h" |
| 8 | #include "common/param_package.h" | 6 | #include "common/param_package.h" |
| 7 | #include "input_common/drivers/camera.h" | ||
| 9 | #include "input_common/drivers/gc_adapter.h" | 8 | #include "input_common/drivers/gc_adapter.h" |
| 10 | #include "input_common/drivers/keyboard.h" | 9 | #include "input_common/drivers/keyboard.h" |
| 11 | #include "input_common/drivers/mouse.h" | 10 | #include "input_common/drivers/mouse.h" |
| 12 | #include "input_common/drivers/tas_input.h" | 11 | #include "input_common/drivers/tas_input.h" |
| 13 | #include "input_common/drivers/touch_screen.h" | 12 | #include "input_common/drivers/touch_screen.h" |
| 14 | #include "input_common/drivers/udp_client.h" | 13 | #include "input_common/drivers/udp_client.h" |
| 14 | #include "input_common/drivers/virtual_amiibo.h" | ||
| 15 | #include "input_common/helpers/stick_from_buttons.h" | 15 | #include "input_common/helpers/stick_from_buttons.h" |
| 16 | #include "input_common/helpers/touch_from_buttons.h" | 16 | #include "input_common/helpers/touch_from_buttons.h" |
| 17 | #include "input_common/input_engine.h" | 17 | #include "input_common/input_engine.h" |
| @@ -79,6 +79,24 @@ struct InputSubsystem::Impl { | |||
| 79 | Common::Input::RegisterFactory<Common::Input::OutputDevice>(tas_input->GetEngineName(), | 79 | Common::Input::RegisterFactory<Common::Input::OutputDevice>(tas_input->GetEngineName(), |
| 80 | tas_output_factory); | 80 | tas_output_factory); |
| 81 | 81 | ||
| 82 | camera = std::make_shared<Camera>("camera"); | ||
| 83 | camera->SetMappingCallback(mapping_callback); | ||
| 84 | camera_input_factory = std::make_shared<InputFactory>(camera); | ||
| 85 | camera_output_factory = std::make_shared<OutputFactory>(camera); | ||
| 86 | Common::Input::RegisterFactory<Common::Input::InputDevice>(camera->GetEngineName(), | ||
| 87 | camera_input_factory); | ||
| 88 | Common::Input::RegisterFactory<Common::Input::OutputDevice>(camera->GetEngineName(), | ||
| 89 | camera_output_factory); | ||
| 90 | |||
| 91 | virtual_amiibo = std::make_shared<VirtualAmiibo>("virtual_amiibo"); | ||
| 92 | virtual_amiibo->SetMappingCallback(mapping_callback); | ||
| 93 | virtual_amiibo_input_factory = std::make_shared<InputFactory>(virtual_amiibo); | ||
| 94 | virtual_amiibo_output_factory = std::make_shared<OutputFactory>(virtual_amiibo); | ||
| 95 | Common::Input::RegisterFactory<Common::Input::InputDevice>(virtual_amiibo->GetEngineName(), | ||
| 96 | virtual_amiibo_input_factory); | ||
| 97 | Common::Input::RegisterFactory<Common::Input::OutputDevice>(virtual_amiibo->GetEngineName(), | ||
| 98 | virtual_amiibo_output_factory); | ||
| 99 | |||
| 82 | #ifdef HAVE_SDL2 | 100 | #ifdef HAVE_SDL2 |
| 83 | sdl = std::make_shared<SDLDriver>("sdl"); | 101 | sdl = std::make_shared<SDLDriver>("sdl"); |
| 84 | sdl->SetMappingCallback(mapping_callback); | 102 | sdl->SetMappingCallback(mapping_callback); |
| @@ -242,6 +260,28 @@ struct InputSubsystem::Impl { | |||
| 242 | return Common::Input::ButtonNames::Invalid; | 260 | return Common::Input::ButtonNames::Invalid; |
| 243 | } | 261 | } |
| 244 | 262 | ||
| 263 | bool IsStickInverted(const Common::ParamPackage& params) { | ||
| 264 | const std::string engine = params.Get("engine", ""); | ||
| 265 | if (engine == mouse->GetEngineName()) { | ||
| 266 | return mouse->IsStickInverted(params); | ||
| 267 | } | ||
| 268 | if (engine == gcadapter->GetEngineName()) { | ||
| 269 | return gcadapter->IsStickInverted(params); | ||
| 270 | } | ||
| 271 | if (engine == udp_client->GetEngineName()) { | ||
| 272 | return udp_client->IsStickInverted(params); | ||
| 273 | } | ||
| 274 | if (engine == tas_input->GetEngineName()) { | ||
| 275 | return tas_input->IsStickInverted(params); | ||
| 276 | } | ||
| 277 | #ifdef HAVE_SDL2 | ||
| 278 | if (engine == sdl->GetEngineName()) { | ||
| 279 | return sdl->IsStickInverted(params); | ||
| 280 | } | ||
| 281 | #endif | ||
| 282 | return false; | ||
| 283 | } | ||
| 284 | |||
| 245 | bool IsController(const Common::ParamPackage& params) { | 285 | bool IsController(const Common::ParamPackage& params) { |
| 246 | const std::string engine = params.Get("engine", ""); | 286 | const std::string engine = params.Get("engine", ""); |
| 247 | if (engine == mouse->GetEngineName()) { | 287 | if (engine == mouse->GetEngineName()) { |
| @@ -296,6 +336,8 @@ struct InputSubsystem::Impl { | |||
| 296 | std::shared_ptr<TouchScreen> touch_screen; | 336 | std::shared_ptr<TouchScreen> touch_screen; |
| 297 | std::shared_ptr<TasInput::Tas> tas_input; | 337 | std::shared_ptr<TasInput::Tas> tas_input; |
| 298 | std::shared_ptr<CemuhookUDP::UDPClient> udp_client; | 338 | std::shared_ptr<CemuhookUDP::UDPClient> udp_client; |
| 339 | std::shared_ptr<Camera> camera; | ||
| 340 | std::shared_ptr<VirtualAmiibo> virtual_amiibo; | ||
| 299 | 341 | ||
| 300 | std::shared_ptr<InputFactory> keyboard_factory; | 342 | std::shared_ptr<InputFactory> keyboard_factory; |
| 301 | std::shared_ptr<InputFactory> mouse_factory; | 343 | std::shared_ptr<InputFactory> mouse_factory; |
| @@ -303,12 +345,16 @@ struct InputSubsystem::Impl { | |||
| 303 | std::shared_ptr<InputFactory> touch_screen_factory; | 345 | std::shared_ptr<InputFactory> touch_screen_factory; |
| 304 | std::shared_ptr<InputFactory> udp_client_input_factory; | 346 | std::shared_ptr<InputFactory> udp_client_input_factory; |
| 305 | std::shared_ptr<InputFactory> tas_input_factory; | 347 | std::shared_ptr<InputFactory> tas_input_factory; |
| 348 | std::shared_ptr<InputFactory> camera_input_factory; | ||
| 349 | std::shared_ptr<InputFactory> virtual_amiibo_input_factory; | ||
| 306 | 350 | ||
| 307 | std::shared_ptr<OutputFactory> keyboard_output_factory; | 351 | std::shared_ptr<OutputFactory> keyboard_output_factory; |
| 308 | std::shared_ptr<OutputFactory> mouse_output_factory; | 352 | std::shared_ptr<OutputFactory> mouse_output_factory; |
| 309 | std::shared_ptr<OutputFactory> gcadapter_output_factory; | 353 | std::shared_ptr<OutputFactory> gcadapter_output_factory; |
| 310 | std::shared_ptr<OutputFactory> udp_client_output_factory; | 354 | std::shared_ptr<OutputFactory> udp_client_output_factory; |
| 311 | std::shared_ptr<OutputFactory> tas_output_factory; | 355 | std::shared_ptr<OutputFactory> tas_output_factory; |
| 356 | std::shared_ptr<OutputFactory> camera_output_factory; | ||
| 357 | std::shared_ptr<OutputFactory> virtual_amiibo_output_factory; | ||
| 312 | 358 | ||
| 313 | #ifdef HAVE_SDL2 | 359 | #ifdef HAVE_SDL2 |
| 314 | std::shared_ptr<SDLDriver> sdl; | 360 | std::shared_ptr<SDLDriver> sdl; |
| @@ -361,6 +407,22 @@ const TasInput::Tas* InputSubsystem::GetTas() const { | |||
| 361 | return impl->tas_input.get(); | 407 | return impl->tas_input.get(); |
| 362 | } | 408 | } |
| 363 | 409 | ||
| 410 | Camera* InputSubsystem::GetCamera() { | ||
| 411 | return impl->camera.get(); | ||
| 412 | } | ||
| 413 | |||
| 414 | const Camera* InputSubsystem::GetCamera() const { | ||
| 415 | return impl->camera.get(); | ||
| 416 | } | ||
| 417 | |||
| 418 | VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() { | ||
| 419 | return impl->virtual_amiibo.get(); | ||
| 420 | } | ||
| 421 | |||
| 422 | const VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() const { | ||
| 423 | return impl->virtual_amiibo.get(); | ||
| 424 | } | ||
| 425 | |||
| 364 | std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const { | 426 | std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const { |
| 365 | return impl->GetInputDevices(); | 427 | return impl->GetInputDevices(); |
| 366 | } | 428 | } |
| @@ -385,6 +447,13 @@ bool InputSubsystem::IsController(const Common::ParamPackage& params) const { | |||
| 385 | return impl->IsController(params); | 447 | return impl->IsController(params); |
| 386 | } | 448 | } |
| 387 | 449 | ||
| 450 | bool InputSubsystem::IsStickInverted(const Common::ParamPackage& params) const { | ||
| 451 | if (params.Has("axis_x") && params.Has("axis_y")) { | ||
| 452 | return impl->IsStickInverted(params); | ||
| 453 | } | ||
| 454 | return false; | ||
| 455 | } | ||
| 456 | |||
| 388 | void InputSubsystem::ReloadInputDevices() { | 457 | void InputSubsystem::ReloadInputDevices() { |
| 389 | impl->udp_client.get()->ReloadSockets(); | 458 | impl->udp_client.get()->ReloadSockets(); |
| 390 | } | 459 | } |
diff --git a/src/input_common/main.h b/src/input_common/main.h index baf107e0f..ced252383 100644 --- a/src/input_common/main.h +++ b/src/input_common/main.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | 1 | // SPDX-FileCopyrightText: 2017 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | // Refer to the license.txt file included. | ||
| 4 | 3 | ||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
| @@ -30,9 +29,11 @@ enum Values : int; | |||
| 30 | } | 29 | } |
| 31 | 30 | ||
| 32 | namespace InputCommon { | 31 | namespace InputCommon { |
| 32 | class Camera; | ||
| 33 | class Keyboard; | 33 | class Keyboard; |
| 34 | class Mouse; | 34 | class Mouse; |
| 35 | class TouchScreen; | 35 | class TouchScreen; |
| 36 | class VirtualAmiibo; | ||
| 36 | struct MappingData; | 37 | struct MappingData; |
| 37 | } // namespace InputCommon | 38 | } // namespace InputCommon |
| 38 | 39 | ||
| @@ -92,9 +93,21 @@ public: | |||
| 92 | /// Retrieves the underlying tas input device. | 93 | /// Retrieves the underlying tas input device. |
| 93 | [[nodiscard]] TasInput::Tas* GetTas(); | 94 | [[nodiscard]] TasInput::Tas* GetTas(); |
| 94 | 95 | ||
| 95 | /// Retrieves the underlying tas input device. | 96 | /// Retrieves the underlying tas input device. |
| 96 | [[nodiscard]] const TasInput::Tas* GetTas() const; | 97 | [[nodiscard]] const TasInput::Tas* GetTas() const; |
| 97 | 98 | ||
| 99 | /// Retrieves the underlying camera input device. | ||
| 100 | [[nodiscard]] Camera* GetCamera(); | ||
| 101 | |||
| 102 | /// Retrieves the underlying camera input device. | ||
| 103 | [[nodiscard]] const Camera* GetCamera() const; | ||
| 104 | |||
| 105 | /// Retrieves the underlying virtual amiibo input device. | ||
| 106 | [[nodiscard]] VirtualAmiibo* GetVirtualAmiibo(); | ||
| 107 | |||
| 108 | /// Retrieves the underlying virtual amiibo input device. | ||
| 109 | [[nodiscard]] const VirtualAmiibo* GetVirtualAmiibo() const; | ||
| 110 | |||
| 98 | /** | 111 | /** |
| 99 | * Returns all available input devices that this Factory can create a new device with. | 112 | * Returns all available input devices that this Factory can create a new device with. |
| 100 | * Each returned ParamPackage should have a `display` field used for display, a `engine` field | 113 | * Each returned ParamPackage should have a `display` field used for display, a `engine` field |
| @@ -119,6 +132,9 @@ public: | |||
| 119 | /// Returns true if device is a controller. | 132 | /// Returns true if device is a controller. |
| 120 | [[nodiscard]] bool IsController(const Common::ParamPackage& params) const; | 133 | [[nodiscard]] bool IsController(const Common::ParamPackage& params) const; |
| 121 | 134 | ||
| 135 | /// Returns true if axis of a stick aren't mapped in the correct direction | ||
| 136 | [[nodiscard]] bool IsStickInverted(const Common::ParamPackage& device) const; | ||
| 137 | |||
| 122 | /// Reloads the input devices. | 138 | /// Reloads the input devices. |
| 123 | void ReloadInputDevices(); | 139 | void ReloadInputDevices(); |
| 124 | 140 | ||