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
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> {
switch (Settings::values.graphics_api.GetValue()) {
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:
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");
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)};
@ -496,7 +496,6 @@ int main(int argc, char** argv) {
}
Network::Shutdown();
InputCommon::Shutdown();
system.Shutdown();

View File

@ -97,7 +97,7 @@ void Config::ReadSetting(const std::string& group, Settings::Setting<Type, range
void Config::ReadValues() {
// 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]);
Settings::values.current_input_profile.buttons[i] =
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);
Settings::values.current_input_profile.udp_input_port =
static_cast<u16>(sdl2_config->GetInteger("Controls", "udp_input_port",
InputCommon::CemuhookUDP::DEFAULT_PORT));
InputCommon::CemuhookUDP::DEFAULT_PORT));*/
// Core
ReadSetting("Core", Settings::values.use_cpu_jit);

View File

@ -2,131 +2,38 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <SDL.h>
#include <algorithm>
#include <cstdlib>
#include <string>
#define SDL_MAIN_HANDLED
#include <SDL.h>
#include "citra/emu_window/emu_window_sdl2.h"
#include "common/logging/log.h"
#include "common/scm_rev.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/motion_emu.h"
#include "network/network.h"
void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
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() {
EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, bool is_secondary)
: EmuWindow(is_secondary), input_subsystem{input_subsystem_} {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) {
LOG_CRITICAL(Frontend, "Failed to initialize SDL2: {}! Exiting...", SDL_GetError());
exit(1);
}
InputCommon::Init();
input_subsystem->Initialize();
Network::Init();
SDL_SetMainReady();
}
EmuWindow_SDL2::~EmuWindow_SDL2() {
SDL_Quit();
}
void EmuWindow_SDL2::PollEvents() {
SDL_Event event;
std::vector<SDL_Event> other_window_events;
@ -170,10 +77,12 @@ void EmuWindow_SDL2::PollEvents() {
}
break;
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;
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;
case SDL_FINGERUP:
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) {
SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second);
}

View File

@ -10,14 +10,16 @@
struct SDL_Window;
namespace InputCommon {
class InputSubsystem;
enum class MouseButton;
} // namespace InputCommon
class EmuWindow_SDL2 : public Frontend::EmuWindow {
public:
explicit EmuWindow_SDL2(bool is_secondary);
explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem, bool is_secondary);
~EmuWindow_SDL2();
/// Initializes SDL2
static void InitializeSDL2();
/// Presents the most recent frame from the video backend
virtual void Present() {}
@ -37,17 +39,20 @@ protected:
/// Called by PollEvents when the mouse moves.
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
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
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
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
void OnFingerUp();
@ -78,4 +83,7 @@ protected:
/// Keeps track of how often to update the title bar during gameplay
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;
};
EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(bool fullscreen, bool is_secondary)
: EmuWindow_SDL2{is_secondary} {
EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, bool fullscreen, bool is_secondary)
: EmuWindow_SDL2{input_subsystem, is_secondary} {
// Initialize the window
if (Settings::values.use_gles) {
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 {
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();
void Present() override;

View File

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

View File

@ -12,7 +12,7 @@ struct SDL_Surface;
class EmuWindow_SDL2_SW : public EmuWindow_SDL2 {
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();
void Present() override;

View File

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

View File

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

View File

@ -39,6 +39,28 @@ enum class PollingError {
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
struct AnalogProperties {
// Anything below this value will be detected as zero
@ -119,6 +141,15 @@ struct TouchStatus {
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
enum class ButtonNames {
Undefined,

View File

@ -101,24 +101,6 @@ void Apply() {
Core::DSP().SetSink(values.output_type.GetValue(), values.output_device.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);
if (cam) {
cam->ReloadCameraDevices();

View File

@ -13,6 +13,7 @@
#include "audio_core/input_details.h"
#include "audio_core/sink_details.h"
#include "common/common_types.h"
#include "common/settings_input.h"
#include "core/hle/service/cam/cam_params.h"
namespace Settings {
@ -53,8 +54,8 @@ enum class StereoRenderOption : u32 {
CardboardVR = 5
};
// Which eye to render when 3d is off. 800px wide mode could be added here in the future, when
// implemented
// Which eye to render when 3d is off. 800px wide mode
// could be added here in the future, when implemented.
enum class MonoRenderOption : u32 {
LeftEye = 0,
RightEye = 1,
@ -75,109 +76,6 @@ enum class TextureFilter : u32 {
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 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
@ -440,11 +338,6 @@ private:
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
/// value to fit the region lockout info of the game
static constexpr s32 REGION_VALUE_AUTO_SELECT = -1;
@ -461,6 +354,9 @@ struct Values {
Setting<u16> udp_input_port{26760, "udp_input_port"};
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
Setting<bool> use_cpu_jit{true, "use_cpu_jit"};
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/hio.cpp
gdbstub/hio.h
frontend/mic.cpp
frontend/mic.h
frontend/scope_acquire_context.cpp
frontend/scope_acquire_context.h
gdbstub/gdbstub.cpp
gdbstub/gdbstub.h
hid/emulated_console.cpp

View File

@ -19,38 +19,6 @@ EmuWindow::EmuWindow(bool is_secondary_) : is_secondary{is_secondary_} {}
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::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y);
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({
.on_change =
[this, index](const Common::Input::CallbackStatus& callback) {
[/*this, index*/](const Common::Input::CallbackStatus& callback) {
// SetMotion(callback, index);
},
});

View File

@ -4,7 +4,8 @@
#include "common/settings.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/service/am/am.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) {
if (is_device_reload_pending.exchange(false)) {
LoadInputDevices();
}
const bool state = home_button->GetStatus();
//const auto& controller = hid_core.GetEmulatedController();
//const bool state = home_button->GetStatus();
// 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
// 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
// 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);
}
last_home_button_state = state;
//last_home_button_state = state;
// Reschedule recurrent event
Core::System::GetInstance().CoreTiming().ScheduleEvent(
system.CoreTiming().ScheduleEvent(
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");
for (std::size_t slot = 0; slot < applet_slots.size(); ++slot) {
auto& slot_data = applet_slots[slot];
@ -1283,8 +1276,4 @@ AppletManager::~AppletManager() {
HLE::Applets::Shutdown();
}
void AppletManager::ReloadInputDevices() {
is_device_reload_pending.store(true);
}
} // namespace Service::APT

View File

@ -23,6 +23,10 @@ namespace Core {
class System;
}
namespace Core::HID {
class HIDCore;
};
namespace Service::APT {
/// Signals used by APT functions
@ -228,8 +232,6 @@ public:
explicit AppletManager(Core::System& system);
~AppletManager();
void ReloadInputDevices();
/**
* 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
@ -428,11 +430,10 @@ private:
AppletSlot application_close_target = AppletSlot::Error;
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;
Core::System& system;
Core::HID::HIDCore& hid_core;
AppletSlotData* GetAppletSlot(AppletSlot slot) {
return &applet_slots[static_cast<std::size_t>(slot)];
@ -454,7 +455,6 @@ private:
void CaptureFrameBuffers();
void LoadInputDevices();
void HomeButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late);
template <class Archive>
@ -479,10 +479,6 @@ private:
}
ar& applet_slots;
ar& library_applet_closing_command;
if (Archive::is_loading::value) {
LoadInputDevices();
}
}
friend class boost::serialization::access;
};

View File

@ -54,7 +54,8 @@ if (ENABLE_LIBUSB)
drivers/gc_adapter.cpp
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)
endif()

View File

@ -15,7 +15,7 @@ namespace InputCommon {
class LibUSBContext {
public:
explicit LibUSBContext() {
init_result = libusb_init(&ctx);
init_result = libusb_init_context(&ctx, nullptr, 0);
}
~LibUSBContext() {
@ -324,7 +324,7 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) {
return true;
}
Common::Input::VibrationError GCAdapter::SetVibration(
Common::Input::DriverResult GCAdapter::SetVibration(
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) {
const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f;
const auto processed_amplitude =
@ -333,9 +333,9 @@ Common::Input::VibrationError GCAdapter::SetVibration(
pads[identifier.port].rumble_amplitude = processed_amplitude;
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) {
@ -421,14 +421,14 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p
{Settings::NativeButton::B, PadButton::ButtonB},
{Settings::NativeButton::X, PadButton::ButtonX},
{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::DUp, PadButton::ButtonUp},
{Settings::NativeButton::DRight, PadButton::ButtonRight},
{Settings::NativeButton::DDown, PadButton::ButtonDown},
{Settings::NativeButton::SL, PadButton::TriggerL},
{Settings::NativeButton::SR, PadButton::TriggerR},
{Settings::NativeButton::R, PadButton::TriggerZ},
{Settings::NativeButton::L, PadButton::TriggerL},
{Settings::NativeButton::R, PadButton::TriggerR},
};
if (!params.Has("port")) {
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("axis_x", static_cast<int>(PadAxes::StickX));
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;
right_analog_params.Set("engine", GetEngineName());
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_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;
}

View File

@ -25,7 +25,7 @@ public:
explicit GCAdapter(std::string input_engine_);
~GCAdapter() override;
Common::Input::VibrationError SetVibration(
Common::Input::DriverResult SetVibration(
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
bool IsVibrationEnabled(const PadIdentifier& identifier) override;
@ -53,6 +53,7 @@ private:
ButtonX = 0x0400,
ButtonY = 0x0800,
ButtonStart = 0x1000,
ButtonSelect = 0x2000,
};
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) {
SetAxis(real_mouse_identifier, mouse_axis_x, touch_x);
SetAxis(real_mouse_identifier, mouse_axis_y, touch_y);

View File

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

View File

@ -25,9 +25,10 @@ class Socket {
public:
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),
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{};
auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
if (ec.value() != boost::system::errc::success) {
@ -95,17 +96,13 @@ private:
void HandleSend(const boost::system::error_code&) {
boost::system::error_code _ignored{};
// 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);
std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE);
socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored);
// Send a request for getting pad data for the pad
const Request::PadData pad_data{
Request::RegisterFlags::AllPads,
0,
EMPTY_MAC_ADDRESS,
};
const Request::PadData pad_data{Request::RegisterFlags::PadID, pad_index, EMPTY_MAC_ADDRESS};
const auto pad_message = Request::Create(pad_data, client_id);
std::memcpy(send_buffer2.data(), &pad_message, PAD_DATA_SIZE);
socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint, {}, _ignored);
@ -118,6 +115,7 @@ private:
udp::socket socket;
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 PAD_DATA_SIZE = sizeof(Message<Request::PadData>);
@ -161,7 +159,7 @@ void UDPClient::ReloadSockets() {
LOG_ERROR(Input, "Duplicated UDP servers found");
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 {
@ -239,7 +237,7 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
static_cast<int>(id == 0 ? PadButton::Touch1 : PadButton::Touch2);
// 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_y = static_cast<u16>(touch_param.Get("min_y", 50));
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_y_id, 0);
SetButton(identifier, touch_button_id, false);*/
SetButton(identifier, touch_button_id, false);
}
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);
}
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); },
[this](Response::PortInfo info) { OnPortInfo(info); },
[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].port = port;
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()};
for (std::size_t index = 0; index < 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;
}
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()>& failure_callback) {
std::thread([=] {
@ -512,7 +510,7 @@ void TestCommunication(const std::string& host, u16 port,
.port_info = [](Response::PortInfo) {},
.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};
const bool result =
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(
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::thread([=, this] {
@ -571,7 +569,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
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};
complete_event.Wait();
socket.Stop();

View File

@ -144,7 +144,7 @@ private:
void OnVersion(Response::Version);
void OnPortInfo(Response::PortInfo);
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;
Common::UUID GetHostUUID(const std::string& host) const;
@ -172,7 +172,7 @@ public:
* @param status_callback Callback for job status updates
* @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(u16, u16, u16, u16)> data_callback);
~CalibrationConfigurationJob();
@ -182,7 +182,7 @@ private:
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()>& failure_callback);

View File

@ -11,6 +11,14 @@ namespace InputCommon {
class Stick final : public Common::Input::InputDevice {
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>;
Stick(Button up_, Button down_, Button left_, Button right_, Button modifier_,

View File

@ -84,7 +84,7 @@ enum RegisterFlags : u8 {
struct Version {};
/**
* 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
* nice to make this configurable
*/

View File

@ -100,6 +100,18 @@ public:
// Disable configuring mode for mapping
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
virtual Common::Input::PollingError SetPollingMode(
[[maybe_unused]] const PadIdentifier& identifier,

View File

@ -4,14 +4,6 @@
#include <memory>
#include "common/input.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/mouse.h"
#include "input_common/drivers/touch_screen.h"
@ -22,7 +14,6 @@
#include "input_common/input_engine.h"
#include "input_common/input_mapping.h"
#include "input_common/input_poller.h"
>>>>>>> 6e5fec9fe (add input common changes)
#include "input_common/main.h"
#ifdef HAVE_LIBUSB
@ -34,50 +25,18 @@
namespace InputCommon {
<<<<<<< HEAD
#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 {
struct InputSubsystem::Impl {
template <typename Engine>
void RegisterEngine(std::string name, std::shared_ptr<Engine>& engine) {
MappingCallback mapping_callback{
[this](const MappingData& data) { RegisterInput(data); }};
MappingCallback mapping_callback{[this](const MappingData& data) { RegisterInput(data); }};
engine = std::make_shared<Engine>(name);
engine->SetMappingCallback(mapping_callback);
>>>>>>> 6e5fec9fe (add input common changes)
std::shared_ptr<InputFactory> input_factory =
std::make_shared<InputFactory>(engine);
std::shared_ptr<OutputFactory> output_factory =
std::make_shared<OutputFactory>(engine);
Common::Input::RegisterInputFactory(engine->GetEngineName(),
std::move(input_factory));
Common::Input::RegisterOutputFactory(engine->GetEngineName(),
std::move(output_factory));
std::shared_ptr<InputFactory> input_factory = std::make_shared<InputFactory>(engine);
std::shared_ptr<OutputFactory> output_factory = std::make_shared<OutputFactory>(engine);
Common::Input::RegisterInputFactory(engine->GetEngineName(), std::move(input_factory));
Common::Input::RegisterOutputFactory(engine->GetEngineName(), std::move(output_factory));
}
void Initialize() {
@ -315,26 +274,8 @@
impl->Initialize();
}
<<<<<<< HEAD
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() {
void InputSubsystem::Shutdown() {
impl->Shutdown();
>>>>>>> 6e5fec9fe (add input common changes)
}
Keyboard* InputSubsystem::GetKeyboard() {
@ -373,23 +314,19 @@
return impl->GetInputDevices();
}
AnalogMapping InputSubsystem::GetAnalogMappingForDevice(
const Common::ParamPackage& device) const {
AnalogMapping InputSubsystem::GetAnalogMappingForDevice(const Common::ParamPackage& device) const {
return impl->GetAnalogMappingForDevice(device);
}
ButtonMapping InputSubsystem::GetButtonMappingForDevice(
const Common::ParamPackage& device) const {
ButtonMapping InputSubsystem::GetButtonMappingForDevice(const Common::ParamPackage& device) const {
return impl->GetButtonMappingForDevice(device);
}
MotionMapping InputSubsystem::GetMotionMappingForDevice(
const Common::ParamPackage& device) const {
MotionMapping InputSubsystem::GetMotionMappingForDevice(const Common::ParamPackage& device) const {
return impl->GetMotionMappingForDevice(device);
}
Common::Input::ButtonNames InputSubsystem::GetButtonName(
const Common::ParamPackage& params) const {
Common::Input::ButtonNames InputSubsystem::GetButtonName(const Common::ParamPackage& params) const {
return impl->GetButtonName(params);
}
@ -434,9 +371,8 @@
return param.Serialize();
}
std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left,
int key_right, int key_modifier,
float modifier_scale) {
std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
int key_modifier, float modifier_scale) {
Common::ParamPackage circle_pad_param{
{"engine", "analog_from_button"},
{"up", GenerateKeyboardParam(key_up)},
@ -448,74 +384,4 @@
};
return circle_pad_param.Serialize();
}
<<<<<<< HEAD
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