It builds

This commit is contained in:
GPUCode
2023-05-14 11:45:00 +03:00
parent 2a4f9b5dd4
commit 6e4cc779d7
30 changed files with 706 additions and 809 deletions

View File

@ -358,18 +358,18 @@ int main(int argc, char** argv) {
// Register frontend applets // Register frontend applets
Frontend::RegisterDefaultApplets(); Frontend::RegisterDefaultApplets();
EmuWindow_SDL2::InitializeSDL2(); InputCommon::InputSubsystem input_subsystem{};
const auto create_emu_window = [](bool fullscreen, const auto create_emu_window = [&](bool fullscreen,
bool is_secondary) -> std::unique_ptr<EmuWindow_SDL2> { bool is_secondary) -> std::unique_ptr<EmuWindow_SDL2> {
switch (Settings::values.graphics_api.GetValue()) { switch (Settings::values.graphics_api.GetValue()) {
case Settings::GraphicsAPI::OpenGL: case Settings::GraphicsAPI::OpenGL:
return std::make_unique<EmuWindow_SDL2_GL>(fullscreen, is_secondary); return std::make_unique<EmuWindow_SDL2_GL>(&input_subsystem, fullscreen, is_secondary);
case Settings::GraphicsAPI::Software: case Settings::GraphicsAPI::Software:
return std::make_unique<EmuWindow_SDL2_SW>(fullscreen, is_secondary); return std::make_unique<EmuWindow_SDL2_SW>(&input_subsystem, fullscreen, is_secondary);
} }
LOG_ERROR(Frontend, "Invalid Graphics API, using OpenGL"); LOG_ERROR(Frontend, "Invalid Graphics API, using OpenGL");
return std::make_unique<EmuWindow_SDL2_GL>(fullscreen, is_secondary); return std::make_unique<EmuWindow_SDL2_GL>(&input_subsystem, fullscreen, is_secondary);
}; };
const auto emu_window{create_emu_window(fullscreen, false)}; const auto emu_window{create_emu_window(fullscreen, false)};
@ -496,7 +496,6 @@ int main(int argc, char** argv) {
} }
Network::Shutdown(); Network::Shutdown();
InputCommon::Shutdown();
system.Shutdown(); system.Shutdown();

View File

@ -97,7 +97,7 @@ void Config::ReadSetting(const std::string& group, Settings::Setting<Type, range
void Config::ReadValues() { void Config::ReadValues() {
// Controls // Controls
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { /*for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
Settings::values.current_input_profile.buttons[i] = Settings::values.current_input_profile.buttons[i] =
sdl2_config->GetString("Controls", Settings::NativeButton::mapping[i], default_param); sdl2_config->GetString("Controls", Settings::NativeButton::mapping[i], default_param);
@ -124,7 +124,7 @@ void Config::ReadValues() {
"Controls", "udp_input_address", InputCommon::CemuhookUDP::DEFAULT_ADDR); "Controls", "udp_input_address", InputCommon::CemuhookUDP::DEFAULT_ADDR);
Settings::values.current_input_profile.udp_input_port = Settings::values.current_input_profile.udp_input_port =
static_cast<u16>(sdl2_config->GetInteger("Controls", "udp_input_port", static_cast<u16>(sdl2_config->GetInteger("Controls", "udp_input_port",
InputCommon::CemuhookUDP::DEFAULT_PORT)); InputCommon::CemuhookUDP::DEFAULT_PORT));*/
// Core // Core
ReadSetting("Core", Settings::values.use_cpu_jit); ReadSetting("Core", Settings::values.use_cpu_jit);

View File

@ -2,131 +2,38 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <SDL.h>
#include <algorithm> #include <algorithm>
#include <cstdlib> #include <cstdlib>
#include <string> #include <string>
#define SDL_MAIN_HANDLED
#include <SDL.h>
#include "citra/emu_window/emu_window_sdl2.h" #include "citra/emu_window/emu_window_sdl2.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/scm_rev.h" #include "common/scm_rev.h"
#include "core/core.h" #include "core/core.h"
#include "input_common/keyboard.h" #include "input_common/drivers/keyboard.h"
#include "input_common/drivers/mouse.h"
#include "input_common/drivers/touch_screen.h"
#include "input_common/main.h" #include "input_common/main.h"
#include "input_common/motion_emu.h"
#include "network/network.h" #include "network/network.h"
void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, bool is_secondary)
TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); : EmuWindow(is_secondary), input_subsystem{input_subsystem_} {
InputCommon::GetMotionEmu()->Tilt(x, y);
}
void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
if (button == SDL_BUTTON_LEFT) {
if (state == SDL_PRESSED) {
TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
} else {
TouchReleased();
}
} else if (button == SDL_BUTTON_RIGHT) {
if (state == SDL_PRESSED) {
InputCommon::GetMotionEmu()->BeginTilt(x, y);
} else {
InputCommon::GetMotionEmu()->EndTilt();
}
}
}
std::pair<unsigned, unsigned> EmuWindow_SDL2::TouchToPixelPos(float touch_x, float touch_y) const {
int w, h;
SDL_GetWindowSize(render_window, &w, &h);
touch_x *= w;
touch_y *= h;
return {static_cast<unsigned>(std::max(std::round(touch_x), 0.0f)),
static_cast<unsigned>(std::max(std::round(touch_y), 0.0f))};
}
void EmuWindow_SDL2::OnFingerDown(float x, float y) {
// TODO(NeatNit): keep track of multitouch using the fingerID and a dictionary of some kind
// This isn't critical because the best we can do when we have that is to average them, like the
// 3DS does
const auto [px, py] = TouchToPixelPos(x, y);
TouchPressed(px, py);
}
void EmuWindow_SDL2::OnFingerMotion(float x, float y) {
const auto [px, py] = TouchToPixelPos(x, y);
TouchMoved(px, py);
}
void EmuWindow_SDL2::OnFingerUp() {
TouchReleased();
}
void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
if (state == SDL_PRESSED) {
InputCommon::GetKeyboard()->PressKey(key);
} else if (state == SDL_RELEASED) {
InputCommon::GetKeyboard()->ReleaseKey(key);
}
}
bool EmuWindow_SDL2::IsOpen() const {
return is_open;
}
void EmuWindow_SDL2::RequestClose() {
is_open = false;
}
void EmuWindow_SDL2::OnResize() {
int width, height;
SDL_GL_GetDrawableSize(render_window, &width, &height);
UpdateCurrentFramebufferLayout(width, height);
}
void EmuWindow_SDL2::Fullscreen() {
if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN) == 0) {
return;
}
LOG_ERROR(Frontend, "Fullscreening failed: {}", SDL_GetError());
// Try a different fullscreening method
LOG_INFO(Frontend, "Attempting to use borderless fullscreen...");
if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) {
return;
}
LOG_ERROR(Frontend, "Borderless fullscreening failed: {}", SDL_GetError());
// Fallback algorithm: Maximise window.
// Works on all systems (unless something is seriously wrong), so no fallback for this one.
LOG_INFO(Frontend, "Falling back on a maximised window...");
SDL_MaximizeWindow(render_window);
}
EmuWindow_SDL2::EmuWindow_SDL2(bool is_secondary) : EmuWindow(is_secondary) {}
EmuWindow_SDL2::~EmuWindow_SDL2() {
SDL_Quit();
}
void EmuWindow_SDL2::InitializeSDL2() {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) {
LOG_CRITICAL(Frontend, "Failed to initialize SDL2: {}! Exiting...", SDL_GetError()); LOG_CRITICAL(Frontend, "Failed to initialize SDL2: {}! Exiting...", SDL_GetError());
exit(1); exit(1);
} }
InputCommon::Init(); input_subsystem->Initialize();
Network::Init(); Network::Init();
SDL_SetMainReady(); SDL_SetMainReady();
} }
EmuWindow_SDL2::~EmuWindow_SDL2() {
SDL_Quit();
}
void EmuWindow_SDL2::PollEvents() { void EmuWindow_SDL2::PollEvents() {
SDL_Event event; SDL_Event event;
std::vector<SDL_Event> other_window_events; std::vector<SDL_Event> other_window_events;
@ -170,10 +77,12 @@ void EmuWindow_SDL2::PollEvents() {
} }
break; break;
case SDL_FINGERDOWN: case SDL_FINGERDOWN:
OnFingerDown(event.tfinger.x, event.tfinger.y); OnFingerDown(event.tfinger.x, event.tfinger.y,
static_cast<std::size_t>(event.tfinger.touchId));
break; break;
case SDL_FINGERMOTION: case SDL_FINGERMOTION:
OnFingerMotion(event.tfinger.x, event.tfinger.y); OnFingerMotion(event.tfinger.x, event.tfinger.y,
static_cast<std::size_t>(event.tfinger.touchId));
break; break;
case SDL_FINGERUP: case SDL_FINGERUP:
OnFingerUp(); OnFingerUp();
@ -195,6 +104,106 @@ void EmuWindow_SDL2::PollEvents() {
} }
} }
void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
const auto [touch_x, touch_y] = MouseToTouchPos(x, y);
input_subsystem->GetMouse()->Move(x, y, 0, 0);
input_subsystem->GetMouse()->MouseMove(touch_x, touch_y);
input_subsystem->GetMouse()->TouchMove(touch_x, touch_y);
}
InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) const {
switch (button) {
case SDL_BUTTON_LEFT:
return InputCommon::MouseButton::Left;
case SDL_BUTTON_RIGHT:
return InputCommon::MouseButton::Right;
case SDL_BUTTON_MIDDLE:
return InputCommon::MouseButton::Wheel;
case SDL_BUTTON_X1:
return InputCommon::MouseButton::Backward;
case SDL_BUTTON_X2:
return InputCommon::MouseButton::Forward;
default:
return InputCommon::MouseButton::Undefined;
}
}
std::pair<float, float> EmuWindow_SDL2::MouseToTouchPos(s32 touch_x, s32 touch_y) const {
int w, h;
SDL_GetWindowSize(render_window, &w, &h);
const float fx = static_cast<float>(touch_x) / w;
const float fy = static_cast<float>(touch_y) / h;
return {std::clamp<float>(fx, 0.0f, 1.0f), std::clamp<float>(fy, 0.0f, 1.0f)};
}
void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
const auto mouse_button = SDLButtonToMouseButton(button);
if (state == SDL_PRESSED) {
const auto [touch_x, touch_y] = MouseToTouchPos(x, y);
input_subsystem->GetMouse()->PressButton(x, y, mouse_button);
input_subsystem->GetMouse()->PressMouseButton(mouse_button);
input_subsystem->GetMouse()->PressTouchButton(touch_x, touch_y, mouse_button);
} else {
input_subsystem->GetMouse()->ReleaseButton(mouse_button);
}
}
void EmuWindow_SDL2::OnFingerDown(float x, float y, std::size_t id) {
input_subsystem->GetTouchScreen()->TouchPressed(x, y, id);
}
void EmuWindow_SDL2::OnFingerMotion(float x, float y, std::size_t id) {
input_subsystem->GetTouchScreen()->TouchMoved(x, y, id);
}
void EmuWindow_SDL2::OnFingerUp() {
input_subsystem->GetTouchScreen()->ReleaseAllTouch();
}
void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
if (state == SDL_PRESSED) {
input_subsystem->GetKeyboard()->PressKey(static_cast<std::size_t>(key));
} else if (state == SDL_RELEASED) {
input_subsystem->GetKeyboard()->ReleaseKey(static_cast<std::size_t>(key));
}
}
bool EmuWindow_SDL2::IsOpen() const {
return is_open;
}
void EmuWindow_SDL2::RequestClose() {
is_open = false;
}
void EmuWindow_SDL2::OnResize() {
int width, height;
SDL_GL_GetDrawableSize(render_window, &width, &height);
UpdateCurrentFramebufferLayout(width, height);
}
void EmuWindow_SDL2::Fullscreen() {
if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN) == 0) {
return;
}
LOG_ERROR(Frontend, "Fullscreening failed: {}", SDL_GetError());
// Try a different fullscreening method
LOG_INFO(Frontend, "Attempting to use borderless fullscreen...");
if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) {
return;
}
LOG_ERROR(Frontend, "Borderless fullscreening failed: {}", SDL_GetError());
// Fallback algorithm: Maximise window.
// Works on all systems (unless something is seriously wrong), so no fallback for this one.
LOG_INFO(Frontend, "Falling back on a maximised window...");
SDL_MaximizeWindow(render_window);
}
void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) { void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) {
SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second); SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second);
} }

View File

@ -10,14 +10,16 @@
struct SDL_Window; struct SDL_Window;
namespace InputCommon {
class InputSubsystem;
enum class MouseButton;
} // namespace InputCommon
class EmuWindow_SDL2 : public Frontend::EmuWindow { class EmuWindow_SDL2 : public Frontend::EmuWindow {
public: public:
explicit EmuWindow_SDL2(bool is_secondary); explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem, bool is_secondary);
~EmuWindow_SDL2(); ~EmuWindow_SDL2();
/// Initializes SDL2
static void InitializeSDL2();
/// Presents the most recent frame from the video backend /// Presents the most recent frame from the video backend
virtual void Present() {} virtual void Present() {}
@ -37,17 +39,20 @@ protected:
/// Called by PollEvents when the mouse moves. /// Called by PollEvents when the mouse moves.
void OnMouseMotion(s32 x, s32 y); void OnMouseMotion(s32 x, s32 y);
/// Converts a SDL mouse button into MouseInput mouse button
InputCommon::MouseButton SDLButtonToMouseButton(u32 button) const;
/// Translates pixel position to float position
std::pair<float, float> MouseToTouchPos(s32 touch_x, s32 touch_y) const;
/// Called by PollEvents when a mouse button is pressed or released /// Called by PollEvents when a mouse button is pressed or released
void OnMouseButton(u32 button, u8 state, s32 x, s32 y); void OnMouseButton(u32 button, u8 state, s32 x, s32 y);
/// Translates pixel position (0..1) to pixel positions
std::pair<unsigned, unsigned> TouchToPixelPos(float touch_x, float touch_y) const;
/// Called by PollEvents when a finger starts touching the touchscreen /// Called by PollEvents when a finger starts touching the touchscreen
void OnFingerDown(float x, float y); void OnFingerDown(float x, float y, std::size_t id);
/// Called by PollEvents when a finger moves while touching the touchscreen /// Called by PollEvents when a finger moves while touching the touchscreen
void OnFingerMotion(float x, float y); void OnFingerMotion(float x, float y, std::size_t id);
/// Called by PollEvents when a finger stops touching the touchscreen /// Called by PollEvents when a finger stops touching the touchscreen
void OnFingerUp(); void OnFingerUp();
@ -78,4 +83,7 @@ protected:
/// Keeps track of how often to update the title bar during gameplay /// Keeps track of how often to update the title bar during gameplay
u32 last_time = 0; u32 last_time = 0;
/// Input subsystem to use with this window.
InputCommon::InputSubsystem* input_subsystem;
}; };

View File

@ -42,8 +42,8 @@ private:
SDL_GLContext context; SDL_GLContext context;
}; };
EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(bool fullscreen, bool is_secondary) EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, bool fullscreen, bool is_secondary)
: EmuWindow_SDL2{is_secondary} { : EmuWindow_SDL2{input_subsystem, is_secondary} {
// Initialize the window // Initialize the window
if (Settings::values.use_gles) { if (Settings::values.use_gles) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);

View File

@ -11,7 +11,7 @@ struct SDL_Window;
class EmuWindow_SDL2_GL : public EmuWindow_SDL2 { class EmuWindow_SDL2_GL : public EmuWindow_SDL2 {
public: public:
explicit EmuWindow_SDL2_GL(bool fullscreen, bool is_secondary); explicit EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, bool fullscreen, bool is_secondary);
~EmuWindow_SDL2_GL(); ~EmuWindow_SDL2_GL();
void Present() override; void Present() override;

View File

@ -19,8 +19,8 @@
class DummyContext : public Frontend::GraphicsContext {}; class DummyContext : public Frontend::GraphicsContext {};
EmuWindow_SDL2_SW::EmuWindow_SDL2_SW(bool fullscreen, bool is_secondary) EmuWindow_SDL2_SW::EmuWindow_SDL2_SW(InputCommon::InputSubsystem* input_subsystem, bool fullscreen, bool is_secondary)
: EmuWindow_SDL2{is_secondary} { : EmuWindow_SDL2{input_subsystem, is_secondary} {
std::string window_title = fmt::format("Citra {} | {}-{}", Common::g_build_fullname, std::string window_title = fmt::format("Citra {} | {}-{}", Common::g_build_fullname,
Common::g_scm_branch, Common::g_scm_desc); Common::g_scm_branch, Common::g_scm_desc);
render_window = render_window =

View File

@ -12,7 +12,7 @@ struct SDL_Surface;
class EmuWindow_SDL2_SW : public EmuWindow_SDL2 { class EmuWindow_SDL2_SW : public EmuWindow_SDL2 {
public: public:
explicit EmuWindow_SDL2_SW(bool fullscreen, bool is_secondary); explicit EmuWindow_SDL2_SW(InputCommon::InputSubsystem* input_subsystem, bool fullscreen, bool is_secondary);
~EmuWindow_SDL2_SW(); ~EmuWindow_SDL2_SW();
void Present() override; void Present() override;

View File

@ -37,7 +37,7 @@ CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent,
using namespace InputCommon::CemuhookUDP; using namespace InputCommon::CemuhookUDP;
job = std::make_unique<CalibrationConfigurationJob>( job = std::make_unique<CalibrationConfigurationJob>(
host, port, host, port, pad_index,
[this](CalibrationConfigurationJob::Status status) { [this](CalibrationConfigurationJob::Status status) {
QMetaObject::invokeMethod(this, [status, this] { QMetaObject::invokeMethod(this, [status, this] {
QString text; QString text;
@ -203,6 +203,7 @@ void ConfigureMotionTouch::OnCemuhookUDPTest() {
udp_test_in_progress = true; udp_test_in_progress = true;
InputCommon::CemuhookUDP::TestCommunication( InputCommon::CemuhookUDP::TestCommunication(
ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()),
static_cast<u8>(ui->udp_pad_index->currentIndex()),
[this] { [this] {
LOG_INFO(Frontend, "UDP input test success"); LOG_INFO(Frontend, "UDP input test success");
QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true));

View File

@ -101,6 +101,7 @@ add_library(citra_common STATIC
scope_exit.h scope_exit.h
settings.cpp settings.cpp
settings.h settings.h
settings_input.h
slot_vector.h slot_vector.h
serialization/atomic.h serialization/atomic.h
serialization/boost_discrete_interval.hpp serialization/boost_discrete_interval.hpp

View File

@ -39,6 +39,28 @@ enum class PollingError {
Unknown, Unknown,
}; };
// Different results that can happen from a device request
enum class DriverResult {
Success,
WrongReply,
Timeout,
UnsupportedControllerType,
HandleInUse,
ErrorReadingData,
ErrorWritingData,
NoDeviceDetected,
InvalidHandle,
NotSupported,
Disabled,
Unknown,
};
// Hint for amplification curve to be used
enum class VibrationAmplificationType {
Linear,
Exponential,
};
// Analog properties for calibration // Analog properties for calibration
struct AnalogProperties { struct AnalogProperties {
// Anything below this value will be detected as zero // Anything below this value will be detected as zero
@ -119,6 +141,15 @@ struct TouchStatus {
int id{}; int id{};
}; };
// HD rumble data
struct VibrationStatus {
f32 low_amplitude{};
f32 low_frequency{};
f32 high_amplitude{};
f32 high_frequency{};
VibrationAmplificationType type;
};
// List of buttons to be passed to Qt that can be translated // List of buttons to be passed to Qt that can be translated
enum class ButtonNames { enum class ButtonNames {
Undefined, Undefined,

View File

@ -101,24 +101,6 @@ void Apply() {
Core::DSP().SetSink(values.output_type.GetValue(), values.output_device.GetValue()); Core::DSP().SetSink(values.output_type.GetValue(), values.output_device.GetValue());
Core::DSP().EnableStretching(values.enable_audio_stretching.GetValue()); Core::DSP().EnableStretching(values.enable_audio_stretching.GetValue());
auto hid = Service::HID::GetModule(system);
if (hid) {
hid->ReloadInputDevices();
}
auto apt = Service::APT::GetModule(system);
if (apt) {
apt->GetAppletManager()->ReloadInputDevices();
}
auto sm = system.ServiceManager();
auto ir_user = sm.GetService<Service::IR::IR_USER>("ir:USER");
if (ir_user)
ir_user->ReloadInputDevices();
auto ir_rst = sm.GetService<Service::IR::IR_RST>("ir:rst");
if (ir_rst)
ir_rst->ReloadInputDevices();
auto cam = Service::CAM::GetModule(system); auto cam = Service::CAM::GetModule(system);
if (cam) { if (cam) {
cam->ReloadCameraDevices(); cam->ReloadCameraDevices();

View File

@ -13,6 +13,7 @@
#include "audio_core/input_details.h" #include "audio_core/input_details.h"
#include "audio_core/sink_details.h" #include "audio_core/sink_details.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/settings_input.h"
#include "core/hle/service/cam/cam_params.h" #include "core/hle/service/cam/cam_params.h"
namespace Settings { namespace Settings {
@ -53,8 +54,8 @@ enum class StereoRenderOption : u32 {
CardboardVR = 5 CardboardVR = 5
}; };
// Which eye to render when 3d is off. 800px wide mode could be added here in the future, when // Which eye to render when 3d is off. 800px wide mode
// implemented // could be added here in the future, when implemented.
enum class MonoRenderOption : u32 { enum class MonoRenderOption : u32 {
LeftEye = 0, LeftEye = 0,
RightEye = 1, RightEye = 1,
@ -75,109 +76,6 @@ enum class TextureFilter : u32 {
xBRZ = 5, xBRZ = 5,
}; };
namespace NativeButton {
enum Values {
A,
B,
X,
Y,
DUp,
DDown,
DLeft,
DRight,
L,
R,
Start,
Select,
Debug,
Gpio14,
ZL,
ZR,
Home,
NumButtons,
};
constexpr int BUTTON_HID_BEGIN = A;
constexpr int BUTTON_IR_BEGIN = ZL;
constexpr int BUTTON_NS_BEGIN = Home;
constexpr int BUTTON_HID_END = BUTTON_IR_BEGIN;
constexpr int BUTTON_IR_END = BUTTON_NS_BEGIN;
constexpr int BUTTON_NS_END = NumButtons;
constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN;
constexpr int NUM_BUTTONS_IR = BUTTON_IR_END - BUTTON_IR_BEGIN;
constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN;
constexpr std::array<const char*, NumButtons> mapping = {{
"button_a",
"button_b",
"button_x",
"button_y",
"button_up",
"button_down",
"button_left",
"button_right",
"button_l",
"button_r",
"button_start",
"button_select",
"button_debug",
"button_gpio14",
"button_zl",
"button_zr",
"button_home",
}};
} // namespace NativeButton
namespace NativeAnalog {
enum Values {
CirclePad,
CStick,
NumAnalogs,
};
constexpr std::array<const char*, NumAnalogs> mapping = {{
"circle_pad",
"c_stick",
}};
} // namespace NativeAnalog
namespace NativeMotion {
enum Values : int {
MotionLeft,
MotionRight,
NumMotions,
};
constexpr int MOTION_HID_BEGIN = MotionLeft;
constexpr int MOTION_HID_END = NumMotions;
constexpr int NUM_MOTIONS_HID = NumMotions;
constexpr std::array<const char*, NumMotions> mapping = {{
"motionleft",
"motionright",
}};
} // namespace NativeMotion
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>;
struct PlayerInput {
ButtonsRaw buttons;
AnalogsRaw analogs;
MotionsRaw motions;
std::string profile_name;
};
/** The Setting class is a simple resource manager. It defines a label and default value alongside /** The Setting class is a simple resource manager. It defines a label and default value alongside
* the actual value of the setting for simpler and less-error prone use with frontend * the actual value of the setting for simpler and less-error prone use with frontend
* configurations. Specifying a default value and label is required. A minimum and maximum range can * configurations. Specifying a default value and label is required. A minimum and maximum range can
@ -440,11 +338,6 @@ private:
Type custom{}; ///< The custom setting value Type custom{}; ///< The custom setting value
}; };
struct TouchFromButtonMap {
std::string name;
std::vector<std::string> buttons;
};
/// A special region value indicating that citra will automatically select a region /// A special region value indicating that citra will automatically select a region
/// value to fit the region lockout info of the game /// value to fit the region lockout info of the game
static constexpr s32 REGION_VALUE_AUTO_SELECT = -1; static constexpr s32 REGION_VALUE_AUTO_SELECT = -1;
@ -461,6 +354,9 @@ struct Values {
Setting<u16> udp_input_port{26760, "udp_input_port"}; Setting<u16> udp_input_port{26760, "udp_input_port"};
Setting<u8> udp_pad_index{0, "udp_pad_index"}; Setting<u8> udp_pad_index{0, "udp_pad_index"};
Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};
Setting<bool> keyboard_enabled{false, "keyboard_enabled"};
// Core // Core
Setting<bool> use_cpu_jit{true, "use_cpu_jit"}; Setting<bool> use_cpu_jit{true, "use_cpu_jit"};
SwitchableSetting<s32, true> cpu_clock_percentage{100, 5, 400, "cpu_clock_percentage"}; SwitchableSetting<s32, true> cpu_clock_percentage{100, 5, 400, "cpu_clock_percentage"};

119
src/common/settings_input.h Normal file
View File

@ -0,0 +1,119 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <string>
#include "common/common_types.h"
namespace Settings {
namespace NativeButton {
enum Values : int {
A,
B,
X,
Y,
DUp,
DDown,
DLeft,
DRight,
L,
R,
Start,
Select,
Debug,
Gpio14,
ZL,
ZR,
Home,
NumButtons,
};
constexpr int BUTTON_HID_BEGIN = A;
constexpr int BUTTON_IR_BEGIN = ZL;
constexpr int BUTTON_NS_BEGIN = Home;
constexpr int BUTTON_HID_END = BUTTON_IR_BEGIN;
constexpr int BUTTON_IR_END = BUTTON_NS_BEGIN;
constexpr int BUTTON_NS_END = NumButtons;
constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN;
constexpr int NUM_BUTTONS_IR = BUTTON_IR_END - BUTTON_IR_BEGIN;
constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN;
constexpr std::array<const char*, NumButtons> mapping = {{
"button_a",
"button_b",
"button_x",
"button_y",
"button_up",
"button_down",
"button_left",
"button_right",
"button_l",
"button_r",
"button_start",
"button_select",
"button_debug",
"button_gpio14",
"button_zl",
"button_zr",
"button_home",
}};
} // namespace NativeButton
namespace NativeAnalog {
enum Values : int {
CirclePad,
CStick,
NumAnalogs,
};
constexpr std::array<const char*, NumAnalogs> mapping = {{
"circle_pad",
"c_stick",
}};
} // namespace NativeAnalog
namespace NativeMotion {
enum Values : int {
MotionLeft,
MotionRight,
NumMotions,
};
constexpr int MOTION_HID_BEGIN = MotionLeft;
constexpr int MOTION_HID_END = NumMotions;
constexpr int NUM_MOTIONS_HID = NumMotions;
constexpr std::array<const char*, NumMotions> mapping = {{
"motionleft",
"motionright",
}};
} // namespace NativeMotion
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>;
struct PlayerInput {
ButtonsRaw buttons;
AnalogsRaw analogs;
MotionsRaw motions;
std::string profile_name;
};
struct TouchFromButtonMap {
std::string name;
std::vector<std::string> buttons;
};
} // namespace Settings

View File

@ -113,10 +113,6 @@ add_library(citra_core STATIC
gdbstub/gdbstub.h gdbstub/gdbstub.h
gdbstub/hio.cpp gdbstub/hio.cpp
gdbstub/hio.h gdbstub/hio.h
frontend/mic.cpp
frontend/mic.h
frontend/scope_acquire_context.cpp
frontend/scope_acquire_context.h
gdbstub/gdbstub.cpp gdbstub/gdbstub.cpp
gdbstub/gdbstub.h gdbstub/gdbstub.h
hid/emulated_console.cpp hid/emulated_console.cpp

View File

@ -19,38 +19,6 @@ EmuWindow::EmuWindow(bool is_secondary_) : is_secondary{is_secondary_} {}
EmuWindow::~EmuWindow() = default; EmuWindow::~EmuWindow() = default;
/**
* Check if the given x/y coordinates are within the touchpad specified by the framebuffer layout
* @param layout FramebufferLayout object describing the framebuffer size and screen positions
* @param framebuffer_x Framebuffer x-coordinate to check
* @param framebuffer_y Framebuffer y-coordinate to check
* @return True if the coordinates are within the touchpad, otherwise false
*/
static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigned framebuffer_x,
unsigned framebuffer_y) {
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) {
return (framebuffer_y >= layout.bottom_screen.top &&
framebuffer_y < layout.bottom_screen.bottom &&
((framebuffer_x >= layout.bottom_screen.left / 2 &&
framebuffer_x < layout.bottom_screen.right / 2) ||
(framebuffer_x >= (layout.bottom_screen.left / 2) + (layout.width / 2) &&
framebuffer_x < (layout.bottom_screen.right / 2) + (layout.width / 2))));
} else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) {
return (framebuffer_y >= layout.bottom_screen.top &&
framebuffer_y < layout.bottom_screen.bottom &&
((framebuffer_x >= layout.bottom_screen.left &&
framebuffer_x < layout.bottom_screen.right) ||
(framebuffer_x >= layout.cardboard.bottom_screen_right_eye + (layout.width / 2) &&
framebuffer_x < layout.cardboard.bottom_screen_right_eye +
layout.bottom_screen.GetWidth() + (layout.width / 2))));
} else {
return (framebuffer_y >= layout.bottom_screen.top &&
framebuffer_y < layout.bottom_screen.bottom &&
framebuffer_x >= layout.bottom_screen.left &&
framebuffer_x < layout.bottom_screen.right);
}
}
std::pair<f32, f32> EmuWindow::MapToTouchScreen(u32 framebuffer_x, u32 framebuffer_y) const { std::pair<f32, f32> EmuWindow::MapToTouchScreen(u32 framebuffer_x, u32 framebuffer_y) const {
std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y); std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y);
const float x = static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left) / const float x = static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left) /

View File

@ -134,7 +134,7 @@ void EmulatedController::ReloadInput() {
} }
motion_devices[index]->SetCallback({ motion_devices[index]->SetCallback({
.on_change = .on_change =
[this, index](const Common::Input::CallbackStatus& callback) { [/*this, index*/](const Common::Input::CallbackStatus& callback) {
// SetMotion(callback, index); // SetMotion(callback, index);
}, },
}); });

View File

@ -4,7 +4,8 @@
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h" #include "core/core.h"
#include "core/frontend/input.h" #include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "core/hle/applets/applet.h" #include "core/hle/applets/applet.h"
#include "core/hle/service/am/am.h" #include "core/hle/service/am/am.h"
#include "core/hle/service/apt/applet_manager.h" #include "core/hle/service/apt/applet_manager.h"
@ -1230,33 +1231,25 @@ void AppletManager::CaptureFrameBuffers() {
} }
} }
void AppletManager::LoadInputDevices() {
home_button = Input::CreateDevice<Input::ButtonDevice>(
Settings::values.current_input_profile.buttons[Settings::NativeButton::Home]);
}
void AppletManager::HomeButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late) { void AppletManager::HomeButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late) {
if (is_device_reload_pending.exchange(false)) { //const auto& controller = hid_core.GetEmulatedController();
LoadInputDevices(); //const bool state = home_button->GetStatus();
}
const bool state = home_button->GetStatus();
// NOTE: We technically do support loading and jumping to home menu even if it isn't // NOTE: We technically do support loading and jumping to home menu even if it isn't
// initially registered. However since the home menu suspend is not bug-free, we don't // initially registered. However since the home menu suspend is not bug-free, we don't
// want normal users who didn't launch the home menu accidentally pressing the home // want normal users who didn't launch the home menu accidentally pressing the home
// button binding and freezing their game, so for now, gate it to only environments // button binding and freezing their game, so for now, gate it to only environments
// where the home menu was already loaded by the user (last condition). // where the home menu was already loaded by the user (last condition).
if (state && !last_home_button_state && GetAppletSlot(AppletSlot::HomeMenu)->registered) { if (/*state &&*/ !last_home_button_state && GetAppletSlot(AppletSlot::HomeMenu)->registered) {
SendNotification(Notification::HomeButtonSingle); SendNotification(Notification::HomeButtonSingle);
} }
last_home_button_state = state; //last_home_button_state = state;
// Reschedule recurrent event // Reschedule recurrent event
Core::System::GetInstance().CoreTiming().ScheduleEvent( system.CoreTiming().ScheduleEvent(
usToCycles(home_button_update_interval_us) - cycles_late, home_button_update_event); usToCycles(home_button_update_interval_us) - cycles_late, home_button_update_event);
} }
AppletManager::AppletManager(Core::System& system) : system(system) { AppletManager::AppletManager(Core::System& system) : system(system), hid_core(system.HIDCore()) {
lock = system.Kernel().CreateMutex(false, "APT_U:Lock"); lock = system.Kernel().CreateMutex(false, "APT_U:Lock");
for (std::size_t slot = 0; slot < applet_slots.size(); ++slot) { for (std::size_t slot = 0; slot < applet_slots.size(); ++slot) {
auto& slot_data = applet_slots[slot]; auto& slot_data = applet_slots[slot];
@ -1283,8 +1276,4 @@ AppletManager::~AppletManager() {
HLE::Applets::Shutdown(); HLE::Applets::Shutdown();
} }
void AppletManager::ReloadInputDevices() {
is_device_reload_pending.store(true);
}
} // namespace Service::APT } // namespace Service::APT

View File

@ -23,6 +23,10 @@ namespace Core {
class System; class System;
} }
namespace Core::HID {
class HIDCore;
};
namespace Service::APT { namespace Service::APT {
/// Signals used by APT functions /// Signals used by APT functions
@ -228,8 +232,6 @@ public:
explicit AppletManager(Core::System& system); explicit AppletManager(Core::System& system);
~AppletManager(); ~AppletManager();
void ReloadInputDevices();
/** /**
* Clears any existing parameter and places a new one. This function is currently only used by * Clears any existing parameter and places a new one. This function is currently only used by
* HLE Applets and should be likely removed in the future * HLE Applets and should be likely removed in the future
@ -428,11 +430,10 @@ private:
AppletSlot application_close_target = AppletSlot::Error; AppletSlot application_close_target = AppletSlot::Error;
Core::TimingEventType* home_button_update_event; Core::TimingEventType* home_button_update_event;
std::atomic<bool> is_device_reload_pending{true};
std::unique_ptr<Input::ButtonDevice> home_button;
bool last_home_button_state = false; bool last_home_button_state = false;
Core::System& system; Core::System& system;
Core::HID::HIDCore& hid_core;
AppletSlotData* GetAppletSlot(AppletSlot slot) { AppletSlotData* GetAppletSlot(AppletSlot slot) {
return &applet_slots[static_cast<std::size_t>(slot)]; return &applet_slots[static_cast<std::size_t>(slot)];
@ -454,7 +455,6 @@ private:
void CaptureFrameBuffers(); void CaptureFrameBuffers();
void LoadInputDevices();
void HomeButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late); void HomeButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late);
template <class Archive> template <class Archive>
@ -479,10 +479,6 @@ private:
} }
ar& applet_slots; ar& applet_slots;
ar& library_applet_closing_command; ar& library_applet_closing_command;
if (Archive::is_loading::value) {
LoadInputDevices();
}
} }
friend class boost::serialization::access; friend class boost::serialization::access;
}; };

View File

@ -54,7 +54,8 @@ if (ENABLE_LIBUSB)
drivers/gc_adapter.cpp drivers/gc_adapter.cpp
drivers/gc_adapter.h drivers/gc_adapter.h
) )
target_link_libraries(input_common PRIVATE libusb::usb) target_include_directories(input_common PRIVATE ${LIBUSB_INCLUDE_DIR})
target_link_libraries(input_common PRIVATE ${LIBUSB_LIBRARIES})
target_compile_definitions(input_common PRIVATE HAVE_LIBUSB) target_compile_definitions(input_common PRIVATE HAVE_LIBUSB)
endif() endif()

View File

@ -15,7 +15,7 @@ namespace InputCommon {
class LibUSBContext { class LibUSBContext {
public: public:
explicit LibUSBContext() { explicit LibUSBContext() {
init_result = libusb_init(&ctx); init_result = libusb_init_context(&ctx, nullptr, 0);
} }
~LibUSBContext() { ~LibUSBContext() {
@ -324,7 +324,7 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) {
return true; return true;
} }
Common::Input::VibrationError GCAdapter::SetVibration( Common::Input::DriverResult GCAdapter::SetVibration(
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) {
const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f; const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f;
const auto processed_amplitude = const auto processed_amplitude =
@ -333,9 +333,9 @@ Common::Input::VibrationError GCAdapter::SetVibration(
pads[identifier.port].rumble_amplitude = processed_amplitude; pads[identifier.port].rumble_amplitude = processed_amplitude;
if (!rumble_enabled) { if (!rumble_enabled) {
return Common::Input::VibrationError::Disabled; return Common::Input::DriverResult::Disabled;
} }
return Common::Input::VibrationError::None; return Common::Input::DriverResult::Success;
} }
bool GCAdapter::IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) { bool GCAdapter::IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) {
@ -421,14 +421,14 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p
{Settings::NativeButton::B, PadButton::ButtonB}, {Settings::NativeButton::B, PadButton::ButtonB},
{Settings::NativeButton::X, PadButton::ButtonX}, {Settings::NativeButton::X, PadButton::ButtonX},
{Settings::NativeButton::Y, PadButton::ButtonY}, {Settings::NativeButton::Y, PadButton::ButtonY},
{Settings::NativeButton::Plus, PadButton::ButtonStart}, {Settings::NativeButton::Start, PadButton::ButtonStart},
{Settings::NativeButton::Select, PadButton::ButtonSelect},
{Settings::NativeButton::DLeft, PadButton::ButtonLeft}, {Settings::NativeButton::DLeft, PadButton::ButtonLeft},
{Settings::NativeButton::DUp, PadButton::ButtonUp}, {Settings::NativeButton::DUp, PadButton::ButtonUp},
{Settings::NativeButton::DRight, PadButton::ButtonRight}, {Settings::NativeButton::DRight, PadButton::ButtonRight},
{Settings::NativeButton::DDown, PadButton::ButtonDown}, {Settings::NativeButton::DDown, PadButton::ButtonDown},
{Settings::NativeButton::SL, PadButton::TriggerL}, {Settings::NativeButton::L, PadButton::TriggerL},
{Settings::NativeButton::SR, PadButton::TriggerR}, {Settings::NativeButton::R, PadButton::TriggerR},
{Settings::NativeButton::R, PadButton::TriggerZ},
}; };
if (!params.Has("port")) { if (!params.Has("port")) {
return {}; return {};
@ -474,13 +474,13 @@ AnalogMapping GCAdapter::GetAnalogMappingForDevice(const Common::ParamPackage& p
left_analog_params.Set("port", params.Get("port", 0)); left_analog_params.Set("port", params.Get("port", 0));
left_analog_params.Set("axis_x", static_cast<int>(PadAxes::StickX)); left_analog_params.Set("axis_x", static_cast<int>(PadAxes::StickX));
left_analog_params.Set("axis_y", static_cast<int>(PadAxes::StickY)); left_analog_params.Set("axis_y", static_cast<int>(PadAxes::StickY));
mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params)); mapping.insert_or_assign(Settings::NativeAnalog::CirclePad, std::move(left_analog_params));
Common::ParamPackage right_analog_params; Common::ParamPackage right_analog_params;
right_analog_params.Set("engine", GetEngineName()); right_analog_params.Set("engine", GetEngineName());
right_analog_params.Set("port", params.Get("port", 0)); right_analog_params.Set("port", params.Get("port", 0));
right_analog_params.Set("axis_x", static_cast<int>(PadAxes::SubstickX)); right_analog_params.Set("axis_x", static_cast<int>(PadAxes::SubstickX));
right_analog_params.Set("axis_y", static_cast<int>(PadAxes::SubstickY)); right_analog_params.Set("axis_y", static_cast<int>(PadAxes::SubstickY));
mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params)); mapping.insert_or_assign(Settings::NativeAnalog::CStick, std::move(right_analog_params));
return mapping; return mapping;
} }

View File

@ -25,7 +25,7 @@ public:
explicit GCAdapter(std::string input_engine_); explicit GCAdapter(std::string input_engine_);
~GCAdapter() override; ~GCAdapter() override;
Common::Input::VibrationError SetVibration( Common::Input::DriverResult SetVibration(
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
bool IsVibrationEnabled(const PadIdentifier& identifier) override; bool IsVibrationEnabled(const PadIdentifier& identifier) override;
@ -53,6 +53,7 @@ private:
ButtonX = 0x0400, ButtonX = 0x0400,
ButtonY = 0x0800, ButtonY = 0x0800,
ButtonStart = 0x1000, ButtonStart = 0x1000,
ButtonSelect = 0x2000,
}; };
enum class PadAxes : u8 { enum class PadAxes : u8 {

View File

@ -54,6 +54,21 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
} }
} }
void Mouse::Move(int x, int y, int, int) {
if (button_pressed) {
const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin;
const float sensitivity = /*Settings::values.mouse_panning_sensitivity.GetValue()*/50 * 0.0012f;
SetAxis(identifier, mouse_axis_x, static_cast<float>(mouse_move.x) * sensitivity);
SetAxis(identifier, mouse_axis_y, static_cast<float>(-mouse_move.y) * sensitivity);
last_motion_change = {
static_cast<float>(-mouse_move.y) / 50.0f,
static_cast<float>(-mouse_move.x) / 50.0f,
last_motion_change.z,
};
}
}
void Mouse::MouseMove(f32 touch_x, f32 touch_y) { void Mouse::MouseMove(f32 touch_x, f32 touch_y) {
SetAxis(real_mouse_identifier, mouse_axis_x, touch_x); SetAxis(real_mouse_identifier, mouse_axis_x, touch_x);
SetAxis(real_mouse_identifier, mouse_axis_y, touch_y); SetAxis(real_mouse_identifier, mouse_axis_y, touch_y);

View File

@ -101,6 +101,7 @@ private:
Common::Vec2<int> mouse_origin; Common::Vec2<int> mouse_origin;
Common::Vec2<int> last_mouse_position; Common::Vec2<int> last_mouse_position;
Common::Vec2<float> last_mouse_change; Common::Vec2<float> last_mouse_change;
Common::Vec3<float> last_motion_change;
Common::Vec2<int> wheel_position; Common::Vec2<int> wheel_position;
bool button_pressed; bool button_pressed;
std::jthread update_thread; std::jthread update_thread;

View File

@ -25,9 +25,10 @@ class Socket {
public: public:
using clock = std::chrono::system_clock; using clock = std::chrono::system_clock;
explicit Socket(const std::string& host, u16 port, SocketCallback callback_) explicit Socket(const std::string& host, u16 port, u8 pad_index, SocketCallback callback_)
: callback(std::move(callback_)), timer(io_service), : callback(std::move(callback_)), timer(io_service),
socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()) { socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()),
pad_index(pad_index) {
boost::system::error_code ec{}; boost::system::error_code ec{};
auto ipv4 = boost::asio::ip::make_address_v4(host, ec); auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
if (ec.value() != boost::system::errc::success) { if (ec.value() != boost::system::errc::success) {
@ -95,17 +96,13 @@ private:
void HandleSend(const boost::system::error_code&) { void HandleSend(const boost::system::error_code&) {
boost::system::error_code _ignored{}; boost::system::error_code _ignored{};
// Send a request for getting port info for the pad // Send a request for getting port info for the pad
const Request::PortInfo port_info{4, {0, 1, 2, 3}}; const Request::PortInfo port_info{1, {pad_index, 0, 0, 0}};
const auto port_message = Request::Create(port_info, client_id); const auto port_message = Request::Create(port_info, client_id);
std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE); std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE);
socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored); socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored);
// Send a request for getting pad data for the pad // Send a request for getting pad data for the pad
const Request::PadData pad_data{ const Request::PadData pad_data{Request::RegisterFlags::PadID, pad_index, EMPTY_MAC_ADDRESS};
Request::RegisterFlags::AllPads,
0,
EMPTY_MAC_ADDRESS,
};
const auto pad_message = Request::Create(pad_data, client_id); const auto pad_message = Request::Create(pad_data, client_id);
std::memcpy(send_buffer2.data(), &pad_message, PAD_DATA_SIZE); std::memcpy(send_buffer2.data(), &pad_message, PAD_DATA_SIZE);
socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint, {}, _ignored); socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint, {}, _ignored);
@ -118,6 +115,7 @@ private:
udp::socket socket; udp::socket socket;
const u32 client_id; const u32 client_id;
const u8 pad_index;
static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>); static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>);
static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>); static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>);
@ -161,7 +159,7 @@ void UDPClient::ReloadSockets() {
LOG_ERROR(Input, "Duplicated UDP servers found"); LOG_ERROR(Input, "Duplicated UDP servers found");
return; return;
} }
StartCommunication(0, host, udp_input_port); StartCommunication(0, host, udp_input_port, pad_index);
} }
std::size_t UDPClient::GetClientNumber(std::string_view host, u16 port) const { std::size_t UDPClient::GetClientNumber(std::string_view host, u16 port) const {
@ -239,7 +237,7 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
static_cast<int>(id == 0 ? PadButton::Touch1 : PadButton::Touch2); static_cast<int>(id == 0 ? PadButton::Touch1 : PadButton::Touch2);
// TODO: Use custom calibration per device // TODO: Use custom calibration per device
/* const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue()); const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue());
const u16 min_x = static_cast<u16>(touch_param.Get("min_x", 100)); const u16 min_x = static_cast<u16>(touch_param.Get("min_x", 100));
const u16 min_y = static_cast<u16>(touch_param.Get("min_y", 50)); const u16 min_y = static_cast<u16>(touch_param.Get("min_y", 50));
const u16 max_x = static_cast<u16>(touch_param.Get("max_x", 1800)); const u16 max_x = static_cast<u16>(touch_param.Get("max_x", 1800));
@ -260,7 +258,7 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
} }
SetAxis(identifier, touch_axis_x_id, 0); SetAxis(identifier, touch_axis_x_id, 0);
SetAxis(identifier, touch_axis_y_id, 0); SetAxis(identifier, touch_axis_y_id, 0);
SetButton(identifier, touch_button_id, false);*/ SetButton(identifier, touch_button_id, false);
} }
SetAxis(identifier, static_cast<int>(PadAxes::LeftStickX), SetAxis(identifier, static_cast<int>(PadAxes::LeftStickX),
@ -288,7 +286,7 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
SetButton(identifier, static_cast<int>(PadButton::TouchHardPress), data.touch_hard_press != 0); SetButton(identifier, static_cast<int>(PadButton::TouchHardPress), data.touch_hard_press != 0);
} }
void UDPClient::StartCommunication(std::size_t client, const std::string& host, u16 port) { void UDPClient::StartCommunication(std::size_t client, const std::string& host, u16 port, u8 pad_index) {
SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
[this](Response::PortInfo info) { OnPortInfo(info); }, [this](Response::PortInfo info) { OnPortInfo(info); },
[this, client](Response::PadData data) { OnPadData(data, client); }}; [this, client](Response::PadData data) { OnPadData(data, client); }};
@ -297,7 +295,7 @@ void UDPClient::StartCommunication(std::size_t client, const std::string& host,
clients[client].host = host; clients[client].host = host;
clients[client].port = port; clients[client].port = port;
clients[client].active = 0; clients[client].active = 0;
clients[client].socket = std::make_unique<Socket>(host, port, callback); clients[client].socket = std::make_unique<Socket>(host, port, pad_index, callback);
clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()}; clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()};
for (std::size_t index = 0; index < PADS_PER_CLIENT; ++index) { for (std::size_t index = 0; index < PADS_PER_CLIENT; ++index) {
const PadIdentifier identifier = GetPadIdentifier(client * PADS_PER_CLIENT + index); const PadIdentifier identifier = GetPadIdentifier(client * PADS_PER_CLIENT + index);
@ -502,7 +500,7 @@ bool UDPClient::IsStickInverted(const Common::ParamPackage& params) {
return true; return true;
} }
void TestCommunication(const std::string& host, u16 port, void TestCommunication(const std::string& host, u16 port, u8 pad_index,
const std::function<void()>& success_callback, const std::function<void()>& success_callback,
const std::function<void()>& failure_callback) { const std::function<void()>& failure_callback) {
std::thread([=] { std::thread([=] {
@ -512,7 +510,7 @@ void TestCommunication(const std::string& host, u16 port,
.port_info = [](Response::PortInfo) {}, .port_info = [](Response::PortInfo) {},
.pad_data = [&](Response::PadData) { success_event.Set(); }, .pad_data = [&](Response::PadData) { success_event.Set(); },
}; };
Socket socket{host, port, std::move(callback)}; Socket socket{host, port, pad_index, std::move(callback)};
std::thread worker_thread{SocketLoop, &socket}; std::thread worker_thread{SocketLoop, &socket};
const bool result = const bool result =
success_event.WaitUntil(std::chrono::steady_clock::now() + std::chrono::seconds(10)); success_event.WaitUntil(std::chrono::steady_clock::now() + std::chrono::seconds(10));
@ -527,7 +525,7 @@ void TestCommunication(const std::string& host, u16 port,
} }
CalibrationConfigurationJob::CalibrationConfigurationJob( CalibrationConfigurationJob::CalibrationConfigurationJob(
const std::string& host, u16 port, std::function<void(Status)> status_callback, const std::string& host, u16 port, u8 pad_index, std::function<void(Status)> status_callback,
std::function<void(u16, u16, u16, u16)> data_callback) { std::function<void(u16, u16, u16, u16)> data_callback) {
std::thread([=, this] { std::thread([=, this] {
@ -571,7 +569,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
complete_event.Set(); complete_event.Set();
} }
}}; }};
Socket socket{host, port, std::move(callback)}; Socket socket{host, port, pad_index, std::move(callback)};
std::thread worker_thread{SocketLoop, &socket}; std::thread worker_thread{SocketLoop, &socket};
complete_event.Wait(); complete_event.Wait();
socket.Stop(); socket.Stop();

View File

@ -144,7 +144,7 @@ private:
void OnVersion(Response::Version); void OnVersion(Response::Version);
void OnPortInfo(Response::PortInfo); void OnPortInfo(Response::PortInfo);
void OnPadData(Response::PadData, std::size_t client); void OnPadData(Response::PadData, std::size_t client);
void StartCommunication(std::size_t client, const std::string& host, u16 port); void StartCommunication(std::size_t client, const std::string& host, u16 port, u8 pad_index);
PadIdentifier GetPadIdentifier(std::size_t pad_index) const; PadIdentifier GetPadIdentifier(std::size_t pad_index) const;
Common::UUID GetHostUUID(const std::string& host) const; Common::UUID GetHostUUID(const std::string& host) const;
@ -172,7 +172,7 @@ public:
* @param status_callback Callback for job status updates * @param status_callback Callback for job status updates
* @param data_callback Called when calibration data is ready * @param data_callback Called when calibration data is ready
*/ */
explicit CalibrationConfigurationJob(const std::string& host, u16 port, explicit CalibrationConfigurationJob(const std::string& host, u16 port, u8 pad_index,
std::function<void(Status)> status_callback, std::function<void(Status)> status_callback,
std::function<void(u16, u16, u16, u16)> data_callback); std::function<void(u16, u16, u16, u16)> data_callback);
~CalibrationConfigurationJob(); ~CalibrationConfigurationJob();
@ -182,7 +182,7 @@ private:
Common::Event complete_event; Common::Event complete_event;
}; };
void TestCommunication(const std::string& host, u16 port, void TestCommunication(const std::string& host, u16 port, u8 pad_index,
const std::function<void()>& success_callback, const std::function<void()>& success_callback,
const std::function<void()>& failure_callback); const std::function<void()>& failure_callback);

View File

@ -11,6 +11,14 @@ namespace InputCommon {
class Stick final : public Common::Input::InputDevice { class Stick final : public Common::Input::InputDevice {
public: public:
// Some games such as EARTH DEFENSE FORCE: WORLD BROTHERS
// do not play nicely with the theoretical maximum range.
// Using a value one lower from the maximum emulates real stick behavior.
static constexpr float MAX_RANGE = 32766.0f / 32767.0f;
static constexpr float TAU = Common::PI * 2.0f;
// Use wider angle to ease the transition.
static constexpr float APERTURE = TAU * 0.15f;
using Button = std::unique_ptr<Common::Input::InputDevice>; using Button = std::unique_ptr<Common::Input::InputDevice>;
Stick(Button up_, Button down_, Button left_, Button right_, Button modifier_, Stick(Button up_, Button down_, Button left_, Button right_, Button modifier_,

View File

@ -84,7 +84,7 @@ enum RegisterFlags : u8 {
struct Version {}; struct Version {};
/** /**
* Requests the server to send information about what controllers are plugged into the ports * Requests the server to send information about what controllers are plugged into the ports
* In yuzu's case, we only have one controller, so for simplicity's sake, we can just send a * In citra's case, we only have one controller, so for simplicity's sake, we can just send a
* request explicitly for the first controller port and leave it at that. In the future it would be * request explicitly for the first controller port and leave it at that. In the future it would be
* nice to make this configurable * nice to make this configurable
*/ */

View File

@ -100,6 +100,18 @@ public:
// Disable configuring mode for mapping // Disable configuring mode for mapping
void EndConfiguration(); void EndConfiguration();
// Sets rumble to a controller
virtual Common::Input::DriverResult SetVibration(
[[maybe_unused]] const PadIdentifier& identifier,
[[maybe_unused]] const Common::Input::VibrationStatus& vibration) {
return Common::Input::DriverResult::NotSupported;
}
// Returns true if device supports vibrations
virtual bool IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) {
return false;
}
// Sets polling mode to a controller // Sets polling mode to a controller
virtual Common::Input::PollingError SetPollingMode( virtual Common::Input::PollingError SetPollingMode(
[[maybe_unused]] const PadIdentifier& identifier, [[maybe_unused]] const PadIdentifier& identifier,

View File

@ -4,14 +4,6 @@
#include <memory> #include <memory>
#include "common/input.h" #include "common/input.h"
#include "common/param_package.h" #include "common/param_package.h"
<<<<<<< HEAD
#include "input_common/analog_from_button.h"
#ifdef ENABLE_GCADAPTER
#include "input_common/gcadapter/gc_adapter.h"
#include "input_common/gcadapter/gc_poller.h"
#endif
#include "input_common/keyboard.h"
== == == =
#include "input_common/drivers/keyboard.h" #include "input_common/drivers/keyboard.h"
#include "input_common/drivers/mouse.h" #include "input_common/drivers/mouse.h"
#include "input_common/drivers/touch_screen.h" #include "input_common/drivers/touch_screen.h"
@ -22,8 +14,7 @@
#include "input_common/input_engine.h" #include "input_common/input_engine.h"
#include "input_common/input_mapping.h" #include "input_common/input_mapping.h"
#include "input_common/input_poller.h" #include "input_common/input_poller.h"
>>>>>>> 6e5fec9fe (add input common changes) #include "input_common/main.h"
#include "input_common/main.h"
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
#include "input_common/drivers/gc_adapter.h" #include "input_common/drivers/gc_adapter.h"
@ -32,52 +23,20 @@
#include "input_common/drivers/sdl_driver.h" #include "input_common/drivers/sdl_driver.h"
#endif #endif
namespace InputCommon { namespace InputCommon {
<<<<<<< HEAD struct InputSubsystem::Impl {
#ifdef ENABLE_GCADAPTER std::shared_ptr < GCButtonFactory> gcbuttons;
std::shared_ptr<GCAnalogFactory> gcanalog;
std::shared_ptr<GCAdapter::Adapter> gcadapter;
#endif
static std::shared_ptr<Keyboard> keyboard;
static std::shared_ptr<MotionEmu> motion_emu;
static std::unique_ptr<CemuhookUDP::State> udp;
static std::unique_ptr<SDL::State> sdl;
void Init() {
#ifdef ENABLE_GCADAPTER
gcadapter = std::make_shared<GCAdapter::Adapter>();
gcbuttons = std::make_shared<GCButtonFactory>(gcadapter);
Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons);
gcanalog = std::make_shared<GCAnalogFactory>(gcadapter);
Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog);
#endif
keyboard = std::make_shared<Keyboard>();
Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
Input::RegisterFactory<Input::AnalogDevice>("analog_from_button",
std::make_shared<AnalogFromButton>());
motion_emu = std::make_shared<MotionEmu>();
Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu);
Input::RegisterFactory<Input::TouchDevice>("touch_from_button",
std::make_shared<TouchFromButtonFactory>());
== == == = struct InputSubsystem::Impl {
template <typename Engine> template <typename Engine>
void RegisterEngine(std::string name, std::shared_ptr<Engine>& engine) { void RegisterEngine(std::string name, std::shared_ptr<Engine>& engine) {
MappingCallback mapping_callback{ MappingCallback mapping_callback{[this](const MappingData& data) { RegisterInput(data); }};
[this](const MappingData& data) { RegisterInput(data); }};
engine = std::make_shared<Engine>(name); engine = std::make_shared<Engine>(name);
engine->SetMappingCallback(mapping_callback); engine->SetMappingCallback(mapping_callback);
>>>>>>> 6e5fec9fe (add input common changes)
std::shared_ptr<InputFactory> input_factory = std::shared_ptr<InputFactory> input_factory = std::make_shared<InputFactory>(engine);
std::make_shared<InputFactory>(engine); std::shared_ptr<OutputFactory> output_factory = std::make_shared<OutputFactory>(engine);
std::shared_ptr<OutputFactory> output_factory = Common::Input::RegisterInputFactory(engine->GetEngineName(), std::move(input_factory));
std::make_shared<OutputFactory>(engine); Common::Input::RegisterOutputFactory(engine->GetEngineName(), std::move(output_factory));
Common::Input::RegisterInputFactory(engine->GetEngineName(),
std::move(input_factory));
Common::Input::RegisterOutputFactory(engine->GetEngineName(),
std::move(output_factory));
} }
void Initialize() { void Initialize() {
@ -305,138 +264,115 @@
#ifdef HAVE_SDL2 #ifdef HAVE_SDL2
std::shared_ptr<SDLDriver> sdl; std::shared_ptr<SDLDriver> sdl;
#endif #endif
}; };
InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {} InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {}
InputSubsystem::~InputSubsystem() = default; InputSubsystem::~InputSubsystem() = default;
void InputSubsystem::Initialize() { void InputSubsystem::Initialize() {
impl->Initialize(); impl->Initialize();
} }
<<<<<<< HEAD void InputSubsystem::Shutdown() {
void Shutdown() {
#ifdef ENABLE_GCADAPTER
Input::UnregisterFactory<Input::ButtonDevice>("gcpad");
Input::UnregisterFactory<Input::AnalogDevice>("gcpad");
gcbuttons.reset();
gcanalog.reset();
#endif
Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
keyboard.reset();
Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button");
Input::UnregisterFactory<Input::MotionDevice>("motion_emu");
motion_emu.reset();
Input::UnregisterFactory<Input::TouchDevice>("emu_window");
Input::UnregisterFactory<Input::TouchDevice>("touch_from_button");
sdl.reset();
udp.reset();
== == == = void InputSubsystem::Shutdown() {
impl->Shutdown(); impl->Shutdown();
>>>>>>> 6e5fec9fe (add input common changes) }
}
Keyboard* InputSubsystem::GetKeyboard() { Keyboard* InputSubsystem::GetKeyboard() {
return impl->keyboard.get(); return impl->keyboard.get();
} }
const Keyboard* InputSubsystem::GetKeyboard() const { const Keyboard* InputSubsystem::GetKeyboard() const {
return impl->keyboard.get(); return impl->keyboard.get();
} }
Mouse* InputSubsystem::GetMouse() { Mouse* InputSubsystem::GetMouse() {
return impl->mouse.get(); return impl->mouse.get();
} }
const Mouse* InputSubsystem::GetMouse() const { const Mouse* InputSubsystem::GetMouse() const {
return impl->mouse.get(); return impl->mouse.get();
} }
TouchScreen* InputSubsystem::GetTouchScreen() { TouchScreen* InputSubsystem::GetTouchScreen() {
return impl->touch_screen.get(); return impl->touch_screen.get();
} }
const TouchScreen* InputSubsystem::GetTouchScreen() const { const TouchScreen* InputSubsystem::GetTouchScreen() const {
return impl->touch_screen.get(); return impl->touch_screen.get();
} }
VirtualGamepad* InputSubsystem::GetVirtualGamepad() { VirtualGamepad* InputSubsystem::GetVirtualGamepad() {
return impl->virtual_gamepad.get(); return impl->virtual_gamepad.get();
} }
const VirtualGamepad* InputSubsystem::GetVirtualGamepad() const { const VirtualGamepad* InputSubsystem::GetVirtualGamepad() const {
return impl->virtual_gamepad.get(); return impl->virtual_gamepad.get();
} }
std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const { std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const {
return impl->GetInputDevices(); return impl->GetInputDevices();
} }
AnalogMapping InputSubsystem::GetAnalogMappingForDevice( AnalogMapping InputSubsystem::GetAnalogMappingForDevice(const Common::ParamPackage& device) const {
const Common::ParamPackage& device) const {
return impl->GetAnalogMappingForDevice(device); return impl->GetAnalogMappingForDevice(device);
} }
ButtonMapping InputSubsystem::GetButtonMappingForDevice( ButtonMapping InputSubsystem::GetButtonMappingForDevice(const Common::ParamPackage& device) const {
const Common::ParamPackage& device) const {
return impl->GetButtonMappingForDevice(device); return impl->GetButtonMappingForDevice(device);
} }
MotionMapping InputSubsystem::GetMotionMappingForDevice( MotionMapping InputSubsystem::GetMotionMappingForDevice(const Common::ParamPackage& device) const {
const Common::ParamPackage& device) const {
return impl->GetMotionMappingForDevice(device); return impl->GetMotionMappingForDevice(device);
} }
Common::Input::ButtonNames InputSubsystem::GetButtonName( Common::Input::ButtonNames InputSubsystem::GetButtonName(const Common::ParamPackage& params) const {
const Common::ParamPackage& params) const {
return impl->GetButtonName(params); return impl->GetButtonName(params);
} }
bool InputSubsystem::IsController(const Common::ParamPackage& params) const { bool InputSubsystem::IsController(const Common::ParamPackage& params) const {
return impl->IsController(params); return impl->IsController(params);
} }
bool InputSubsystem::IsStickInverted(const Common::ParamPackage& params) const { bool InputSubsystem::IsStickInverted(const Common::ParamPackage& params) const {
if (params.Has("axis_x") && params.Has("axis_y")) { if (params.Has("axis_x") && params.Has("axis_y")) {
return impl->IsStickInverted(params); return impl->IsStickInverted(params);
} }
return false; return false;
} }
void InputSubsystem::ReloadInputDevices() { void InputSubsystem::ReloadInputDevices() {
impl->udp_client.get()->ReloadSockets(); impl->udp_client.get()->ReloadSockets();
} }
void InputSubsystem::BeginMapping(Polling::InputType type) { void InputSubsystem::BeginMapping(Polling::InputType type) {
impl->BeginConfiguration(); impl->BeginConfiguration();
impl->mapping_factory->BeginMapping(type); impl->mapping_factory->BeginMapping(type);
} }
Common::ParamPackage InputSubsystem::GetNextInput() const { Common::ParamPackage InputSubsystem::GetNextInput() const {
return impl->mapping_factory->GetNextInput(); return impl->mapping_factory->GetNextInput();
} }
void InputSubsystem::StopMapping() const { void InputSubsystem::StopMapping() const {
impl->EndConfiguration(); impl->EndConfiguration();
impl->mapping_factory->StopMapping(); impl->mapping_factory->StopMapping();
} }
void InputSubsystem::PumpEvents() const { void InputSubsystem::PumpEvents() const {
impl->PumpEvents(); impl->PumpEvents();
} }
std::string GenerateKeyboardParam(int key_code) { std::string GenerateKeyboardParam(int key_code) {
Common::ParamPackage param; Common::ParamPackage param;
param.Set("engine", "keyboard"); param.Set("engine", "keyboard");
param.Set("code", key_code); param.Set("code", key_code);
param.Set("toggle", false); param.Set("toggle", false);
return param.Serialize(); return param.Serialize();
} }
std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
int key_right, int key_modifier, int key_modifier, float modifier_scale) {
float modifier_scale) {
Common::ParamPackage circle_pad_param{ Common::ParamPackage circle_pad_param{
{"engine", "analog_from_button"}, {"engine", "analog_from_button"},
{"up", GenerateKeyboardParam(key_up)}, {"up", GenerateKeyboardParam(key_up)},
@ -447,75 +383,5 @@
{"modifier_scale", std::to_string(modifier_scale)}, {"modifier_scale", std::to_string(modifier_scale)},
}; };
return circle_pad_param.Serialize(); return circle_pad_param.Serialize();
} }
<<<<<<< HEAD } // namespace InputCommon
Common::ParamPackage GetControllerButtonBinds(const Common::ParamPackage& params,
int button) {
const auto native_button{static_cast<Settings::NativeButton::Values>(button)};
const auto engine{params.Get("engine", "")};
if (engine == "sdl") {
return dynamic_cast<SDL::SDLState*>(sdl.get())
->GetSDLControllerButtonBindByGUID(params.Get("guid", "0"),
params.Get("port", 0), native_button);
}
#ifdef ENABLE_GCADAPTER
if (engine == "gcpad") {
return gcbuttons->GetGcTo3DSMappedButton(params.Get("port", 0), native_button);
}
#endif
return {};
}
Common::ParamPackage GetControllerAnalogBinds(const Common::ParamPackage& params,
int analog) {
const auto native_analog{static_cast<Settings::NativeAnalog::Values>(analog)};
const auto engine{params.Get("engine", "")};
if (engine == "sdl") {
return dynamic_cast<SDL::SDLState*>(sdl.get())
->GetSDLControllerAnalogBindByGUID(params.Get("guid", "0"),
params.Get("port", 0), native_analog);
}
#ifdef ENABLE_GCADAPTER
if (engine == "gcpad") {
return gcanalog->GetGcTo3DSMappedAnalog(params.Get("port", 0), native_analog);
}
#endif
return {};
}
void ReloadInputDevices() {
if (!udp) {
return;
}
udp->ReloadUDPClient();
}
namespace Polling {
std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type) {
std::vector<std::unique_ptr<DevicePoller>> pollers;
#ifdef HAVE_SDL2
pollers = sdl->GetPollers(type);
#endif
#ifdef ENABLE_GCADAPTER
switch (type) {
case DeviceType::Analog:
pollers.push_back(std::make_unique<GCAnalogFactory>(*gcanalog));
break;
case DeviceType::Button:
pollers.push_back(std::make_unique<GCButtonFactory>(*gcbuttons));
break;
default:
break;
}
#endif
return pollers;
}
} // namespace Polling
== == == =
>>>>>>> 6e5fec9fe (add input common changes)
} // namespace InputCommon