Merge pull request #9456 from german77/virtual_gamepad

input_common: Add virtual gamepad
This commit is contained in:
bunnei 2022-12-17 17:16:13 -08:00 committed by GitHub
commit 771e450bcc
7 changed files with 274 additions and 0 deletions

View file

@ -20,6 +20,8 @@ add_library(input_common STATIC
drivers/udp_client.h
drivers/virtual_amiibo.cpp
drivers/virtual_amiibo.h
drivers/virtual_gamepad.cpp
drivers/virtual_gamepad.h
helpers/stick_from_buttons.cpp
helpers/stick_from_buttons.h
helpers/touch_from_buttons.cpp

View file

@ -0,0 +1,78 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "input_common/drivers/virtual_gamepad.h"
namespace InputCommon {
constexpr std::size_t PlayerIndexCount = 10;
VirtualGamepad::VirtualGamepad(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
for (std::size_t i = 0; i < PlayerIndexCount; i++) {
PreSetController(GetIdentifier(i));
}
}
void VirtualGamepad::SetButtonState(std::size_t player_index, int button_id, bool value) {
if (player_index > PlayerIndexCount) {
return;
}
const auto identifier = GetIdentifier(player_index);
SetButton(identifier, button_id, value);
}
void VirtualGamepad::SetButtonState(std::size_t player_index, VirtualButton button_id, bool value) {
SetButtonState(player_index, static_cast<int>(button_id), value);
}
void VirtualGamepad::SetStickPosition(std::size_t player_index, int axis_id, float x_value,
float y_value) {
if (player_index > PlayerIndexCount) {
return;
}
const auto identifier = GetIdentifier(player_index);
SetAxis(identifier, axis_id * 2, x_value);
SetAxis(identifier, (axis_id * 2) + 1, y_value);
}
void VirtualGamepad::SetStickPosition(std::size_t player_index, VirtualStick axis_id, float x_value,
float y_value) {
SetStickPosition(player_index, static_cast<int>(axis_id), x_value, y_value);
}
void VirtualGamepad::ResetControllers() {
for (std::size_t i = 0; i < PlayerIndexCount; i++) {
SetStickPosition(i, VirtualStick::Left, 0.0f, 0.0f);
SetStickPosition(i, VirtualStick::Right, 0.0f, 0.0f);
SetButtonState(i, VirtualButton::ButtonA, false);
SetButtonState(i, VirtualButton::ButtonB, false);
SetButtonState(i, VirtualButton::ButtonX, false);
SetButtonState(i, VirtualButton::ButtonY, false);
SetButtonState(i, VirtualButton::StickL, false);
SetButtonState(i, VirtualButton::StickR, false);
SetButtonState(i, VirtualButton::TriggerL, false);
SetButtonState(i, VirtualButton::TriggerR, false);
SetButtonState(i, VirtualButton::TriggerZL, false);
SetButtonState(i, VirtualButton::TriggerZR, false);
SetButtonState(i, VirtualButton::ButtonPlus, false);
SetButtonState(i, VirtualButton::ButtonMinus, false);
SetButtonState(i, VirtualButton::ButtonLeft, false);
SetButtonState(i, VirtualButton::ButtonUp, false);
SetButtonState(i, VirtualButton::ButtonRight, false);
SetButtonState(i, VirtualButton::ButtonDown, false);
SetButtonState(i, VirtualButton::ButtonSL, false);
SetButtonState(i, VirtualButton::ButtonSR, false);
SetButtonState(i, VirtualButton::ButtonHome, false);
SetButtonState(i, VirtualButton::ButtonCapture, false);
}
}
PadIdentifier VirtualGamepad::GetIdentifier(std::size_t player_index) const {
return {
.guid = Common::UUID{},
.port = player_index,
.pad = 0,
};
}
} // namespace InputCommon

View file

@ -0,0 +1,73 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "input_common/input_engine.h"
namespace InputCommon {
/**
* A virtual controller that is always assigned to the game input
*/
class VirtualGamepad final : public InputEngine {
public:
enum class VirtualButton {
ButtonA,
ButtonB,
ButtonX,
ButtonY,
StickL,
StickR,
TriggerL,
TriggerR,
TriggerZL,
TriggerZR,
ButtonPlus,
ButtonMinus,
ButtonLeft,
ButtonUp,
ButtonRight,
ButtonDown,
ButtonSL,
ButtonSR,
ButtonHome,
ButtonCapture,
};
enum class VirtualStick {
Left = 0,
Right = 1,
};
explicit VirtualGamepad(std::string input_engine_);
/**
* Sets the status of all buttons bound with the key to pressed
* @param player_index the player number that will take this action
* @param button_id the id of the button
* @param value indicates if the button is pressed or not
*/
void SetButtonState(std::size_t player_index, int button_id, bool value);
void SetButtonState(std::size_t player_index, VirtualButton button_id, bool value);
/**
* Sets the status of all buttons bound with the key to released
* @param player_index the player number that will take this action
* @param axis_id the id of the axis to move
* @param x_value the position of the stick in the x axis
* @param y_value the position of the stick in the y axis
*/
void SetStickPosition(std::size_t player_index, int axis_id, float x_value, float y_value);
void SetStickPosition(std::size_t player_index, VirtualStick axis_id, float x_value,
float y_value);
/// Restores all inputs into the neutral position
void ResetControllers();
private:
/// Returns the correct identifier corresponding to the player index
PadIdentifier GetIdentifier(std::size_t player_index) const;
};
} // namespace InputCommon

View file

@ -12,6 +12,7 @@
#include "input_common/drivers/touch_screen.h"
#include "input_common/drivers/udp_client.h"
#include "input_common/drivers/virtual_amiibo.h"
#include "input_common/drivers/virtual_gamepad.h"
#include "input_common/helpers/stick_from_buttons.h"
#include "input_common/helpers/touch_from_buttons.h"
#include "input_common/input_engine.h"
@ -85,6 +86,12 @@ struct InputSubsystem::Impl {
Common::Input::RegisterOutputFactory(virtual_amiibo->GetEngineName(),
virtual_amiibo_output_factory);
virtual_gamepad = std::make_shared<VirtualGamepad>("virtual_gamepad");
virtual_gamepad->SetMappingCallback(mapping_callback);
virtual_gamepad_input_factory = std::make_shared<InputFactory>(virtual_gamepad);
Common::Input::RegisterInputFactory(virtual_gamepad->GetEngineName(),
virtual_gamepad_input_factory);
#ifdef HAVE_SDL2
sdl = std::make_shared<SDLDriver>("sdl");
sdl->SetMappingCallback(mapping_callback);
@ -132,6 +139,9 @@ struct InputSubsystem::Impl {
Common::Input::UnregisterOutputFactory(virtual_amiibo->GetEngineName());
virtual_amiibo.reset();
Common::Input::UnregisterInputFactory(virtual_gamepad->GetEngineName());
virtual_gamepad.reset();
#ifdef HAVE_SDL2
Common::Input::UnregisterInputFactory(sdl->GetEngineName());
Common::Input::UnregisterOutputFactory(sdl->GetEngineName());
@ -290,6 +300,9 @@ struct InputSubsystem::Impl {
if (engine == tas_input->GetEngineName()) {
return true;
}
if (engine == virtual_gamepad->GetEngineName()) {
return true;
}
#ifdef HAVE_SDL2
if (engine == sdl->GetEngineName()) {
return true;
@ -338,6 +351,7 @@ struct InputSubsystem::Impl {
std::shared_ptr<CemuhookUDP::UDPClient> udp_client;
std::shared_ptr<Camera> camera;
std::shared_ptr<VirtualAmiibo> virtual_amiibo;
std::shared_ptr<VirtualGamepad> virtual_gamepad;
std::shared_ptr<InputFactory> keyboard_factory;
std::shared_ptr<InputFactory> mouse_factory;
@ -347,6 +361,7 @@ struct InputSubsystem::Impl {
std::shared_ptr<InputFactory> tas_input_factory;
std::shared_ptr<InputFactory> camera_input_factory;
std::shared_ptr<InputFactory> virtual_amiibo_input_factory;
std::shared_ptr<InputFactory> virtual_gamepad_input_factory;
std::shared_ptr<OutputFactory> keyboard_output_factory;
std::shared_ptr<OutputFactory> mouse_output_factory;
@ -423,6 +438,14 @@ const VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() const {
return impl->virtual_amiibo.get();
}
VirtualGamepad* InputSubsystem::GetVirtualGamepad() {
return impl->virtual_gamepad.get();
}
const VirtualGamepad* InputSubsystem::GetVirtualGamepad() const {
return impl->virtual_gamepad.get();
}
std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const {
return impl->GetInputDevices();
}

View file

@ -34,6 +34,7 @@ class Keyboard;
class Mouse;
class TouchScreen;
class VirtualAmiibo;
class VirtualGamepad;
struct MappingData;
} // namespace InputCommon
@ -108,6 +109,12 @@ public:
/// Retrieves the underlying virtual amiibo input device.
[[nodiscard]] const VirtualAmiibo* GetVirtualAmiibo() const;
/// Retrieves the underlying virtual gamepad input device.
[[nodiscard]] VirtualGamepad* GetVirtualGamepad();
/// Retrieves the underlying virtual gamepad input device.
[[nodiscard]] const VirtualGamepad* GetVirtualGamepad() const;
/**
* Returns all available input devices that this Factory can create a new device with.
* Each returned ParamPackage should have a `display` field used for display, a `engine` field