core/hid: Add output devices
This commit is contained in:
parent
e14ae06391
commit
06a5ef5874
20 changed files with 313 additions and 145 deletions
|
@ -38,6 +38,27 @@ enum class BatteryLevel {
|
||||||
Charging,
|
Charging,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class PollingMode {
|
||||||
|
Active,
|
||||||
|
Pasive,
|
||||||
|
Camera,
|
||||||
|
NCF,
|
||||||
|
IR,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class VibrationError {
|
||||||
|
None,
|
||||||
|
NotSupported,
|
||||||
|
Disabled,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PollingError {
|
||||||
|
None,
|
||||||
|
NotSupported,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
struct AnalogProperties {
|
struct AnalogProperties {
|
||||||
float deadzone{};
|
float deadzone{};
|
||||||
float range{1.0f};
|
float range{1.0f};
|
||||||
|
@ -149,6 +170,24 @@ private:
|
||||||
InputCallback callback;
|
InputCallback callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// An abstract class template for an output device (rumble, LED pattern, polling mode).
|
||||||
|
class OutputDevice {
|
||||||
|
public:
|
||||||
|
virtual ~OutputDevice() = default;
|
||||||
|
|
||||||
|
virtual void SetLED([[maybe_unused]] LedStatus led_status) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual VibrationError SetVibration([[maybe_unused]] VibrationStatus vibration_status) {
|
||||||
|
return VibrationError::NotSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual PollingError SetPollingMode([[maybe_unused]] PollingMode polling_mode) {
|
||||||
|
return PollingError::NotSupported;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// An abstract class template for a factory that can create input devices.
|
/// An abstract class template for a factory that can create input devices.
|
||||||
template <typename InputDeviceType>
|
template <typename InputDeviceType>
|
||||||
class Factory {
|
class Factory {
|
||||||
|
|
|
@ -66,12 +66,32 @@ void EmulatedController::ReloadFromSettings() {
|
||||||
for (std::size_t index = 0; index < player.motions.size(); ++index) {
|
for (std::size_t index = 0; index < player.motions.size(); ++index) {
|
||||||
motion_params[index] = Common::ParamPackage(player.motions[index]);
|
motion_params[index] = Common::ParamPackage(player.motions[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
controller.colors_state.left = {
|
||||||
|
.body = player.body_color_left,
|
||||||
|
.button = player.button_color_left,
|
||||||
|
};
|
||||||
|
|
||||||
|
controller.colors_state.right = {
|
||||||
|
.body = player.body_color_right,
|
||||||
|
.button = player.button_color_right,
|
||||||
|
};
|
||||||
|
|
||||||
|
controller.colors_state.fullkey = controller.colors_state.left;
|
||||||
|
|
||||||
|
SetNpadType(MapSettingsTypeToNPad(player.controller_type));
|
||||||
|
|
||||||
|
if (player.connected) {
|
||||||
|
Connect();
|
||||||
|
} else {
|
||||||
|
Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
ReloadInput();
|
ReloadInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::ReloadInput() {
|
void EmulatedController::ReloadInput() {
|
||||||
const auto player_index = NpadIdTypeToIndex(npad_id_type);
|
const auto player_index = NpadIdTypeToIndex(npad_id_type);
|
||||||
const auto& player = Settings::values.players.GetValue()[player_index];
|
|
||||||
const auto left_side = button_params[Settings::NativeButton::ZL];
|
const auto left_side = button_params[Settings::NativeButton::ZL];
|
||||||
const auto right_side = button_params[Settings::NativeButton::ZR];
|
const auto right_side = button_params[Settings::NativeButton::ZR];
|
||||||
|
|
||||||
|
@ -90,21 +110,13 @@ void EmulatedController::ReloadInput() {
|
||||||
trigger_devices[1] =
|
trigger_devices[1] =
|
||||||
Input::CreateDevice<Input::InputDevice>(button_params[Settings::NativeButton::ZR]);
|
Input::CreateDevice<Input::InputDevice>(button_params[Settings::NativeButton::ZR]);
|
||||||
|
|
||||||
controller.colors_state.left = {
|
|
||||||
.body = player.body_color_left,
|
|
||||||
.button = player.button_color_left,
|
|
||||||
};
|
|
||||||
|
|
||||||
controller.colors_state.right = {
|
|
||||||
.body = player.body_color_right,
|
|
||||||
.button = player.button_color_right,
|
|
||||||
};
|
|
||||||
|
|
||||||
controller.colors_state.fullkey = controller.colors_state.left;
|
|
||||||
|
|
||||||
battery_devices[0] = Input::CreateDevice<Input::InputDevice>(left_side);
|
battery_devices[0] = Input::CreateDevice<Input::InputDevice>(left_side);
|
||||||
battery_devices[1] = Input::CreateDevice<Input::InputDevice>(right_side);
|
battery_devices[1] = Input::CreateDevice<Input::InputDevice>(right_side);
|
||||||
|
|
||||||
|
button_params[Settings::NativeButton::ZL].Set("output",true);
|
||||||
|
output_devices[0] =
|
||||||
|
Input::CreateDevice<Input::OutputDevice>(button_params[Settings::NativeButton::ZL]);
|
||||||
|
|
||||||
for (std::size_t index = 0; index < button_devices.size(); ++index) {
|
for (std::size_t index = 0; index < button_devices.size(); ++index) {
|
||||||
if (!button_devices[index]) {
|
if (!button_devices[index]) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -149,14 +161,6 @@ void EmulatedController::ReloadInput() {
|
||||||
[this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }};
|
[this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }};
|
||||||
motion_devices[index]->SetCallback(motion_callback);
|
motion_devices[index]->SetCallback(motion_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetNpadType(MapSettingsTypeToNPad(player.controller_type));
|
|
||||||
|
|
||||||
if (player.connected) {
|
|
||||||
Connect();
|
|
||||||
} else {
|
|
||||||
Disconnect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::UnloadInput() {
|
void EmulatedController::UnloadInput() {
|
||||||
|
@ -197,7 +201,8 @@ void EmulatedController::SaveCurrentConfig() {
|
||||||
|
|
||||||
const auto player_index = NpadIdTypeToIndex(npad_id_type);
|
const auto player_index = NpadIdTypeToIndex(npad_id_type);
|
||||||
auto& player = Settings::values.players.GetValue()[player_index];
|
auto& player = Settings::values.players.GetValue()[player_index];
|
||||||
|
player.connected = is_connected;
|
||||||
|
player.controller_type = MapNPadToSettingsType(npad_type);
|
||||||
for (std::size_t index = 0; index < player.buttons.size(); ++index) {
|
for (std::size_t index = 0; index < player.buttons.size(); ++index) {
|
||||||
player.buttons[index] = button_params[index].Serialize();
|
player.buttons[index] = button_params[index].Serialize();
|
||||||
}
|
}
|
||||||
|
@ -601,13 +606,50 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t
|
||||||
TriggerOnChange(ControllerTriggerType::Battery);
|
TriggerOnChange(ControllerTriggerType::Battery);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmulatedController::SetVibration([[maybe_unused]] std::size_t device_index,
|
bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
|
||||||
[[maybe_unused]] VibrationValue vibration) {
|
if (!output_devices[device_index]) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Input::VibrationStatus status = {
|
||||||
|
.low_amplitude = vibration.high_amplitude,
|
||||||
|
.low_frequency = vibration.high_amplitude,
|
||||||
|
.high_amplitude = vibration.high_amplitude,
|
||||||
|
.high_frequency = vibration.high_amplitude,
|
||||||
|
};
|
||||||
|
return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EmulatedController::TestVibration(std::size_t device_index) {
|
bool EmulatedController::TestVibration(std::size_t device_index) {
|
||||||
return 1;
|
if (!output_devices[device_index]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a slight vibration to test for rumble support
|
||||||
|
constexpr Input::VibrationStatus status = {
|
||||||
|
.low_amplitude = 0.001f,
|
||||||
|
.low_frequency = 160.0f,
|
||||||
|
.high_amplitude = 0.001f,
|
||||||
|
.high_frequency = 320.0f,
|
||||||
|
};
|
||||||
|
return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatedController::SetLedPattern() {
|
||||||
|
for (auto& device : output_devices) {
|
||||||
|
if (!device) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LedPattern pattern = GetLedPattern();
|
||||||
|
const Input::LedStatus status = {
|
||||||
|
.led_1 = pattern.position1 != 0,
|
||||||
|
.led_2 = pattern.position2 != 0,
|
||||||
|
.led_3 = pattern.position3 != 0,
|
||||||
|
.led_4 = pattern.position4 != 0,
|
||||||
|
};
|
||||||
|
device->SetLED(status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::Connect() {
|
void EmulatedController::Connect() {
|
||||||
|
@ -655,6 +697,29 @@ void EmulatedController::SetNpadType(NpadType npad_type_) {
|
||||||
TriggerOnChange(ControllerTriggerType::Type);
|
TriggerOnChange(ControllerTriggerType::Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LedPattern EmulatedController::GetLedPattern() const {
|
||||||
|
switch (npad_id_type) {
|
||||||
|
case NpadIdType::Player1:
|
||||||
|
return LedPattern{1, 0, 0, 0};
|
||||||
|
case NpadIdType::Player2:
|
||||||
|
return LedPattern{1, 1, 0, 0};
|
||||||
|
case NpadIdType::Player3:
|
||||||
|
return LedPattern{1, 1, 1, 0};
|
||||||
|
case NpadIdType::Player4:
|
||||||
|
return LedPattern{1, 1, 1, 1};
|
||||||
|
case NpadIdType::Player5:
|
||||||
|
return LedPattern{1, 0, 0, 1};
|
||||||
|
case NpadIdType::Player6:
|
||||||
|
return LedPattern{1, 0, 1, 0};
|
||||||
|
case NpadIdType::Player7:
|
||||||
|
return LedPattern{1, 0, 1, 1};
|
||||||
|
case NpadIdType::Player8:
|
||||||
|
return LedPattern{0, 1, 1, 0};
|
||||||
|
default:
|
||||||
|
return LedPattern{0, 0, 0, 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ButtonValues EmulatedController::GetButtonsValues() const {
|
ButtonValues EmulatedController::GetButtonsValues() const {
|
||||||
return controller.button_values;
|
return controller.button_values;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,12 +33,14 @@ using ControllerMotionDevices =
|
||||||
using TriggerDevices =
|
using TriggerDevices =
|
||||||
std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
|
std::array<std::unique_ptr<Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
|
||||||
using BatteryDevices = std::array<std::unique_ptr<Input::InputDevice>, 2>;
|
using BatteryDevices = std::array<std::unique_ptr<Input::InputDevice>, 2>;
|
||||||
|
using OutputDevices = std::array<std::unique_ptr<Input::OutputDevice>, 2>;
|
||||||
|
|
||||||
using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
|
using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
|
||||||
using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
|
using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
|
||||||
using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>;
|
using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>;
|
||||||
using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>;
|
using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>;
|
||||||
using BatteryParams = std::array<Common::ParamPackage, 2>;
|
using BatteryParams = std::array<Common::ParamPackage, 2>;
|
||||||
|
using OutputParams = std::array<Common::ParamPackage, 2>;
|
||||||
|
|
||||||
using ButtonValues = std::array<Input::ButtonStatus, Settings::NativeButton::NumButtons>;
|
using ButtonValues = std::array<Input::ButtonStatus, Settings::NativeButton::NumButtons>;
|
||||||
using SticksValues = std::array<Input::StickStatus, Settings::NativeAnalog::NumAnalogs>;
|
using SticksValues = std::array<Input::StickStatus, Settings::NativeAnalog::NumAnalogs>;
|
||||||
|
@ -94,6 +96,7 @@ struct ControllerStatus {
|
||||||
ControllerColors colors_state{};
|
ControllerColors colors_state{};
|
||||||
BatteryLevelState battery_state{};
|
BatteryLevelState battery_state{};
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ControllerTriggerType {
|
enum class ControllerTriggerType {
|
||||||
Button,
|
Button,
|
||||||
Stick,
|
Stick,
|
||||||
|
@ -137,6 +140,9 @@ public:
|
||||||
/// Gets the NpadType for this controller.
|
/// Gets the NpadType for this controller.
|
||||||
NpadType GetNpadType() const;
|
NpadType GetNpadType() const;
|
||||||
|
|
||||||
|
/// Gets the NpadType for this controller.
|
||||||
|
LedPattern GetLedPattern() const;
|
||||||
|
|
||||||
void Connect();
|
void Connect();
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
|
|
||||||
|
@ -179,7 +185,9 @@ public:
|
||||||
BatteryLevelState GetBattery() const;
|
BatteryLevelState GetBattery() const;
|
||||||
|
|
||||||
bool SetVibration(std::size_t device_index, VibrationValue vibration);
|
bool SetVibration(std::size_t device_index, VibrationValue vibration);
|
||||||
int TestVibration(std::size_t device_index);
|
bool TestVibration(std::size_t device_index);
|
||||||
|
|
||||||
|
void SetLedPattern();
|
||||||
|
|
||||||
int SetCallback(ControllerUpdateCallback update_callback);
|
int SetCallback(ControllerUpdateCallback update_callback);
|
||||||
void DeleteCallback(int key);
|
void DeleteCallback(int key);
|
||||||
|
@ -215,13 +223,14 @@ private:
|
||||||
ControllerMotionParams motion_params;
|
ControllerMotionParams motion_params;
|
||||||
TriggerParams trigger_params;
|
TriggerParams trigger_params;
|
||||||
BatteryParams battery_params;
|
BatteryParams battery_params;
|
||||||
|
OutputParams output_params;
|
||||||
|
|
||||||
ButtonDevices button_devices;
|
ButtonDevices button_devices;
|
||||||
StickDevices stick_devices;
|
StickDevices stick_devices;
|
||||||
ControllerMotionDevices motion_devices;
|
ControllerMotionDevices motion_devices;
|
||||||
TriggerDevices trigger_devices;
|
TriggerDevices trigger_devices;
|
||||||
BatteryDevices battery_devices;
|
BatteryDevices battery_devices;
|
||||||
// VibrationDevices vibration_devices;
|
OutputDevices output_devices;
|
||||||
|
|
||||||
mutable std::mutex mutex;
|
mutable std::mutex mutex;
|
||||||
std::unordered_map<int, ControllerUpdateCallback> callback_list;
|
std::unordered_map<int, ControllerUpdateCallback> callback_list;
|
||||||
|
|
|
@ -112,6 +112,8 @@ struct NpadStyleTag {
|
||||||
BitField<7, 1, u32> lark;
|
BitField<7, 1, u32> lark;
|
||||||
BitField<8, 1, u32> handheld_lark;
|
BitField<8, 1, u32> handheld_lark;
|
||||||
BitField<9, 1, u32> lucia;
|
BitField<9, 1, u32> lucia;
|
||||||
|
BitField<10, 1, u32> lagoon;
|
||||||
|
BitField<11, 1, u32> lager;
|
||||||
BitField<29, 1, u32> system_ext;
|
BitField<29, 1, u32> system_ext;
|
||||||
BitField<30, 1, u32> system;
|
BitField<30, 1, u32> system;
|
||||||
};
|
};
|
||||||
|
@ -175,6 +177,22 @@ struct NpadPowerInfo {
|
||||||
};
|
};
|
||||||
static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
|
static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
|
||||||
|
|
||||||
|
struct LedPattern {
|
||||||
|
explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
|
||||||
|
position1.Assign(light1);
|
||||||
|
position2.Assign(light2);
|
||||||
|
position3.Assign(light3);
|
||||||
|
position4.Assign(light4);
|
||||||
|
}
|
||||||
|
union {
|
||||||
|
u64 raw{};
|
||||||
|
BitField<0, 1, u64> position1;
|
||||||
|
BitField<1, 1, u64> position2;
|
||||||
|
BitField<2, 1, u64> position3;
|
||||||
|
BitField<3, 1, u64> position4;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// This is nn::hid::NpadButton
|
// This is nn::hid::NpadButton
|
||||||
enum class NpadButton : u64 {
|
enum class NpadButton : u64 {
|
||||||
None = 0,
|
None = 0,
|
||||||
|
|
|
@ -796,7 +796,7 @@ void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index,
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.vibration[device_index].device_mounted =
|
controller.vibration[device_index].device_mounted =
|
||||||
controller.device->TestVibration(device_index) == 1;
|
controller.device->TestVibration(device_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
|
void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
|
||||||
|
@ -954,31 +954,12 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
|
Core::HID::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
|
||||||
if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
|
if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
|
||||||
// These are controllers without led patterns
|
// These are controllers without led patterns
|
||||||
return LedPattern{0, 0, 0, 0};
|
return Core::HID::LedPattern{0, 0, 0, 0};
|
||||||
}
|
|
||||||
switch (npad_id) {
|
|
||||||
case 0:
|
|
||||||
return LedPattern{1, 0, 0, 0};
|
|
||||||
case 1:
|
|
||||||
return LedPattern{1, 1, 0, 0};
|
|
||||||
case 2:
|
|
||||||
return LedPattern{1, 1, 1, 0};
|
|
||||||
case 3:
|
|
||||||
return LedPattern{1, 1, 1, 1};
|
|
||||||
case 4:
|
|
||||||
return LedPattern{1, 0, 0, 1};
|
|
||||||
case 5:
|
|
||||||
return LedPattern{1, 0, 1, 0};
|
|
||||||
case 6:
|
|
||||||
return LedPattern{1, 0, 1, 1};
|
|
||||||
case 7:
|
|
||||||
return LedPattern{0, 1, 1, 0};
|
|
||||||
default:
|
|
||||||
return LedPattern{0, 0, 0, 0};
|
|
||||||
}
|
}
|
||||||
|
return controller_data[npad_id].device->GetLedPattern();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const {
|
bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const {
|
||||||
|
|
|
@ -115,22 +115,6 @@ public:
|
||||||
.freq_high = 320.0f,
|
.freq_high = 320.0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LedPattern {
|
|
||||||
explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
|
|
||||||
position1.Assign(light1);
|
|
||||||
position2.Assign(light2);
|
|
||||||
position3.Assign(light3);
|
|
||||||
position4.Assign(light4);
|
|
||||||
}
|
|
||||||
union {
|
|
||||||
u64 raw{};
|
|
||||||
BitField<0, 1, u64> position1;
|
|
||||||
BitField<1, 1, u64> position2;
|
|
||||||
BitField<2, 1, u64> position3;
|
|
||||||
BitField<3, 1, u64> position4;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
|
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
|
||||||
Core::HID::NpadStyleTag GetSupportedStyleSet() const;
|
Core::HID::NpadStyleTag GetSupportedStyleSet() const;
|
||||||
|
|
||||||
|
@ -186,7 +170,7 @@ public:
|
||||||
void SetSixAxisFusionParameters(f32 parameter1, f32 parameter2);
|
void SetSixAxisFusionParameters(f32 parameter1, f32 parameter2);
|
||||||
std::pair<f32, f32> GetSixAxisFusionParameters();
|
std::pair<f32, f32> GetSixAxisFusionParameters();
|
||||||
void ResetSixAxisFusionParameters();
|
void ResetSixAxisFusionParameters();
|
||||||
LedPattern GetLedPattern(u32 npad_id);
|
Core::HID::LedPattern GetLedPattern(u32 npad_id);
|
||||||
bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
|
bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
|
||||||
void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
|
void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
|
||||||
void SetAnalogStickUseCenterClamp(bool use_center_clamp);
|
void SetAnalogStickUseCenterClamp(bool use_center_clamp);
|
||||||
|
|
|
@ -322,13 +322,17 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GCAdapter::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) {
|
Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier, const 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 =
|
||||||
static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8);
|
static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8);
|
||||||
|
|
||||||
pads[identifier.port].rumble_amplitude = processed_amplitude;
|
pads[identifier.port].rumble_amplitude = processed_amplitude;
|
||||||
return rumble_enabled;
|
|
||||||
|
if (!rumble_enabled) {
|
||||||
|
return Input::VibrationError::Disabled;
|
||||||
|
}
|
||||||
|
return Input::VibrationError::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCAdapter::UpdateVibrations() {
|
void GCAdapter::UpdateVibrations() {
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
explicit GCAdapter(const std::string input_engine_);
|
explicit GCAdapter(const std::string input_engine_);
|
||||||
~GCAdapter();
|
~GCAdapter();
|
||||||
|
|
||||||
bool SetRumble(const PadIdentifier& identifier,
|
Input::VibrationError SetRumble(const PadIdentifier& identifier,
|
||||||
const Input::VibrationStatus vibration) override;
|
const Input::VibrationStatus vibration) override;
|
||||||
|
|
||||||
/// Used for automapping features
|
/// Used for automapping features
|
||||||
|
|
|
@ -506,7 +506,8 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
|
||||||
}
|
}
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
bool SDLDriver::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) {
|
Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier,
|
||||||
|
const Input::VibrationStatus vibration) {
|
||||||
const auto joystick =
|
const auto joystick =
|
||||||
GetSDLJoystickByGUID(identifier.guid.Format(), static_cast<int>(identifier.port));
|
GetSDLJoystickByGUID(identifier.guid.Format(), static_cast<int>(identifier.port));
|
||||||
const auto process_amplitude = [](f32 amplitude) {
|
const auto process_amplitude = [](f32 amplitude) {
|
||||||
|
@ -519,7 +520,10 @@ bool SDLDriver::SetRumble(const PadIdentifier& identifier, const Input::Vibratio
|
||||||
.high_frequency = vibration.high_frequency,
|
.high_frequency = vibration.high_frequency,
|
||||||
};
|
};
|
||||||
|
|
||||||
return joystick->RumblePlay(new_vibration);
|
if (!joystick->RumblePlay(new_vibration)) {
|
||||||
|
return Input::VibrationError::Unknown;
|
||||||
|
}
|
||||||
|
return Input::VibrationError::None;
|
||||||
}
|
}
|
||||||
Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,
|
Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,
|
||||||
s32 axis, float value) const {
|
s32 axis, float value) const {
|
||||||
|
|
|
@ -58,7 +58,7 @@ public:
|
||||||
std::string GetHatButtonName(u8 direction_value) const override;
|
std::string GetHatButtonName(u8 direction_value) const override;
|
||||||
u8 GetHatButtonId(const std::string direction_name) const override;
|
u8 GetHatButtonId(const std::string direction_name) const override;
|
||||||
|
|
||||||
bool SetRumble(const PadIdentifier& identifier,
|
Input::VibrationError SetRumble(const PadIdentifier& identifier,
|
||||||
const Input::VibrationStatus vibration) override;
|
const Input::VibrationStatus vibration) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -251,7 +251,8 @@ private:
|
||||||
std::chrono::time_point<std::chrono::steady_clock> last_update;
|
std::chrono::time_point<std::chrono::steady_clock> last_update;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<Input::InputDevice> StickFromButton::Create(const Common::ParamPackage& params) {
|
std::unique_ptr<Input::InputDevice> StickFromButton::Create(
|
||||||
|
const Common::ParamPackage& params) {
|
||||||
const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
|
const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
|
||||||
auto up = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("up", null_engine));
|
auto up = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("up", null_engine));
|
||||||
auto down = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("down", null_engine));
|
auto down = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("down", null_engine));
|
||||||
|
|
|
@ -25,7 +25,8 @@ public:
|
||||||
* - "modifier": a serialized ParamPackage for creating a button device as the modifier
|
* - "modifier": a serialized ParamPackage for creating a button device as the modifier
|
||||||
* - "modifier_scale": a float for the multiplier the modifier gives to the position
|
* - "modifier_scale": a float for the multiplier the modifier gives to the position
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
|
std::unique_ptr<Input::InputDevice> Create(
|
||||||
|
const Common::ParamPackage& params) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace InputCommon
|
} // namespace InputCommon
|
||||||
|
|
|
@ -57,7 +57,9 @@ private:
|
||||||
const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
|
const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<Input::InputDevice> TouchFromButton::Create(const Common::ParamPackage& params) {
|
|
||||||
|
std::unique_ptr<Input::InputDevice> TouchFromButton::Create(
|
||||||
|
const Common::ParamPackage& params) {
|
||||||
const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
|
const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
|
||||||
auto button =
|
auto button =
|
||||||
Input::CreateDeviceFromString<Input::InputDevice>(params.Get("button", null_engine));
|
Input::CreateDeviceFromString<Input::InputDevice>(params.Get("button", null_engine));
|
||||||
|
|
|
@ -114,18 +114,24 @@ public:
|
||||||
// Disable configuring mode for mapping
|
// Disable configuring mode for mapping
|
||||||
void EndConfiguration();
|
void EndConfiguration();
|
||||||
|
|
||||||
// Sets rumble to a controller
|
|
||||||
virtual bool SetRumble([[maybe_unused]] const PadIdentifier& identifier,
|
|
||||||
[[maybe_unused]] const Input::VibrationStatus vibration) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets a led pattern for a controller
|
// Sets a led pattern for a controller
|
||||||
virtual void SetLeds([[maybe_unused]] const PadIdentifier& identifier,
|
virtual void SetLeds([[maybe_unused]] const PadIdentifier& identifier,
|
||||||
[[maybe_unused]] const Input::LedStatus led_status) {
|
[[maybe_unused]] const Input::LedStatus led_status) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets rumble to a controller
|
||||||
|
virtual Input::VibrationError SetRumble([[maybe_unused]] const PadIdentifier& identifier,
|
||||||
|
[[maybe_unused]] const Input::VibrationStatus vibration) {
|
||||||
|
return Input::VibrationError::NotSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets polling mode to a controller
|
||||||
|
virtual Input::PollingError SetPollingMode([[maybe_unused]] const PadIdentifier& identifier,
|
||||||
|
[[maybe_unused]] const Input::PollingMode vibration) {
|
||||||
|
return Input::PollingError::NotSupported;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the engine name
|
// Returns the engine name
|
||||||
[[nodiscard]] const std::string& GetEngineName() const;
|
[[nodiscard]] const std::string& GetEngineName() const;
|
||||||
|
|
||||||
|
|
|
@ -592,6 +592,28 @@ private:
|
||||||
InputEngine* input_engine;
|
InputEngine* input_engine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OutputFromIdentifier final : public Input::OutputDevice {
|
||||||
|
public:
|
||||||
|
explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_)
|
||||||
|
: identifier(identifier_), input_engine(input_engine_) {}
|
||||||
|
|
||||||
|
virtual void SetLED( Input::LedStatus led_status) {
|
||||||
|
input_engine->SetLeds(identifier, led_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Input::VibrationError SetVibration(Input::VibrationStatus vibration_status) {
|
||||||
|
return input_engine->SetRumble(identifier, vibration_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Input::PollingError SetPollingMode(Input::PollingMode polling_mode) {
|
||||||
|
return input_engine->SetPollingMode(identifier, polling_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const PadIdentifier identifier;
|
||||||
|
InputEngine* input_engine;
|
||||||
|
};
|
||||||
|
|
||||||
std::unique_ptr<Input::InputDevice> InputFactory::CreateButtonDevice(
|
std::unique_ptr<Input::InputDevice> InputFactory::CreateButtonDevice(
|
||||||
const Common::ParamPackage& params) {
|
const Common::ParamPackage& params) {
|
||||||
const PadIdentifier identifier = {
|
const PadIdentifier identifier = {
|
||||||
|
@ -825,7 +847,8 @@ std::unique_ptr<Input::InputDevice> InputFactory::CreateMotionDevice(Common::Par
|
||||||
InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_)
|
InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_)
|
||||||
: input_engine(std::move(input_engine_)) {}
|
: input_engine(std::move(input_engine_)) {}
|
||||||
|
|
||||||
std::unique_ptr<Input::InputDevice> InputFactory::Create(const Common::ParamPackage& params) {
|
std::unique_ptr<Input::InputDevice> InputFactory::Create(
|
||||||
|
const Common::ParamPackage& params) {
|
||||||
if (params.Has("button") && params.Has("axis")) {
|
if (params.Has("button") && params.Has("axis")) {
|
||||||
return CreateTriggerDevice(params);
|
return CreateTriggerDevice(params);
|
||||||
}
|
}
|
||||||
|
@ -857,4 +880,19 @@ std::unique_ptr<Input::InputDevice> InputFactory::Create(const Common::ParamPack
|
||||||
return std::make_unique<DummyInput>();
|
return std::make_unique<DummyInput>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OutputFactory::OutputFactory(std::shared_ptr<InputEngine> input_engine_)
|
||||||
|
: input_engine(std::move(input_engine_)) {}
|
||||||
|
|
||||||
|
std::unique_ptr<Input::OutputDevice> OutputFactory::Create(
|
||||||
|
const Common::ParamPackage& params) {
|
||||||
|
const PadIdentifier identifier = {
|
||||||
|
.guid = Common::UUID{params.Get("guid", "")},
|
||||||
|
.port = static_cast<std::size_t>(params.Get("port", 0)),
|
||||||
|
.pad = static_cast<std::size_t>(params.Get("pad", 0)),
|
||||||
|
};
|
||||||
|
|
||||||
|
input_engine->PreSetController(identifier);
|
||||||
|
return std::make_unique<OutputFromIdentifier>(identifier, input_engine.get());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace InputCommon
|
} // namespace InputCommon
|
||||||
|
|
|
@ -16,12 +16,32 @@ class InputEngine;
|
||||||
/**
|
/**
|
||||||
* An Input factory. It receives input events and forward them to all input devices it created.
|
* An Input factory. It receives input events and forward them to all input devices it created.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class OutputFactory final : public Input::Factory<Input::OutputDevice> {
|
||||||
|
public:
|
||||||
|
explicit OutputFactory(std::shared_ptr<InputEngine> input_engine_);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an output device from the parameters given.
|
||||||
|
* @param params contains parameters for creating the device:
|
||||||
|
* @param - "guid": text string for identifing controllers
|
||||||
|
* @param - "port": port of the connected device
|
||||||
|
* @param - "pad": slot of the connected controller
|
||||||
|
* @return an unique ouput device with the parameters specified
|
||||||
|
*/
|
||||||
|
std::unique_ptr<Input::OutputDevice> Create(
|
||||||
|
const Common::ParamPackage& params) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<InputEngine> input_engine;
|
||||||
|
};
|
||||||
|
|
||||||
class InputFactory final : public Input::Factory<Input::InputDevice> {
|
class InputFactory final : public Input::Factory<Input::InputDevice> {
|
||||||
public:
|
public:
|
||||||
explicit InputFactory(std::shared_ptr<InputEngine> input_engine_);
|
explicit InputFactory(std::shared_ptr<InputEngine> input_engine_);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a input device from the parameters given. Identifies the type of input to be returned
|
* Creates an input device from the parameters given. Identifies the type of input to be returned
|
||||||
* if it contains the following parameters:
|
* if it contains the following parameters:
|
||||||
* - button: Contains "button" or "code"
|
* - button: Contains "button" or "code"
|
||||||
* - hat_button: Contains "hat"
|
* - hat_button: Contains "hat"
|
||||||
|
@ -32,6 +52,7 @@ public:
|
||||||
* - motion: Contains "motion"
|
* - motion: Contains "motion"
|
||||||
* - touch: Contains "button", "axis_x" and "axis_y"
|
* - touch: Contains "button", "axis_x" and "axis_y"
|
||||||
* - battery: Contains "battery"
|
* - battery: Contains "battery"
|
||||||
|
* - output: Contains "output"
|
||||||
* @param params contains parameters for creating the device:
|
* @param params contains parameters for creating the device:
|
||||||
* @param - "code": the code of the keyboard key to bind with the input
|
* @param - "code": the code of the keyboard key to bind with the input
|
||||||
* @param - "button": same as "code" but for controller buttons
|
* @param - "button": same as "code" but for controller buttons
|
||||||
|
@ -41,10 +62,11 @@ public:
|
||||||
* @param - "axis_x": same as axis but specifing horizontal direction
|
* @param - "axis_x": same as axis but specifing horizontal direction
|
||||||
* @param - "axis_y": same as axis but specifing vertical direction
|
* @param - "axis_y": same as axis but specifing vertical direction
|
||||||
* @param - "axis_z": same as axis but specifing forward direction
|
* @param - "axis_z": same as axis but specifing forward direction
|
||||||
* @param - "battery": Only used as a placeholder to set the input type
|
* @param - "battery": Only used as a placeholder to set the input type
|
||||||
* @return an unique input device with the parameters specified
|
* @return an unique input device with the parameters specified
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
|
std::unique_ptr<Input::InputDevice> Create(
|
||||||
|
const Common::ParamPackage& params) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -46,8 +46,10 @@ struct InputSubsystem::Impl {
|
||||||
|
|
||||||
gcadapter = std::make_shared<GCAdapter>("gcpad");
|
gcadapter = std::make_shared<GCAdapter>("gcpad");
|
||||||
gcadapter->SetMappingCallback(mapping_callback);
|
gcadapter->SetMappingCallback(mapping_callback);
|
||||||
gcadapter_factory = std::make_shared<InputFactory>(gcadapter);
|
gcadapter_input_factory = std::make_shared<InputFactory>(gcadapter);
|
||||||
Input::RegisterFactory<Input::InputDevice>(gcadapter->GetEngineName(), gcadapter_factory);
|
gcadapter_output_factory = std::make_shared<OutputFactory>(gcadapter);
|
||||||
|
Input::RegisterFactory<Input::InputDevice>(gcadapter->GetEngineName(), gcadapter_input_factory);
|
||||||
|
Input::RegisterFactory<Input::OutputDevice>(gcadapter->GetEngineName(), gcadapter_output_factory);
|
||||||
|
|
||||||
udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
|
udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
|
||||||
udp_client->SetMappingCallback(mapping_callback);
|
udp_client->SetMappingCallback(mapping_callback);
|
||||||
|
@ -62,8 +64,10 @@ struct InputSubsystem::Impl {
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
sdl = std::make_shared<SDLDriver>("sdl");
|
sdl = std::make_shared<SDLDriver>("sdl");
|
||||||
sdl->SetMappingCallback(mapping_callback);
|
sdl->SetMappingCallback(mapping_callback);
|
||||||
sdl_factory = std::make_shared<InputFactory>(sdl);
|
sdl_input_factory = std::make_shared<InputFactory>(sdl);
|
||||||
Input::RegisterFactory<Input::InputDevice>(sdl->GetEngineName(), sdl_factory);
|
sdl_output_factory = std::make_shared<OutputFactory>(sdl);
|
||||||
|
Input::RegisterFactory<Input::InputDevice>(sdl->GetEngineName(), sdl_input_factory);
|
||||||
|
Input::RegisterFactory<Input::OutputDevice>(sdl->GetEngineName(), sdl_output_factory);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Input::RegisterFactory<Input::InputDevice>("touch_from_button",
|
Input::RegisterFactory<Input::InputDevice>("touch_from_button",
|
||||||
|
@ -247,21 +251,27 @@ struct InputSubsystem::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MappingFactory> mapping_factory;
|
std::shared_ptr<MappingFactory> mapping_factory;
|
||||||
|
|
||||||
std::shared_ptr<Keyboard> keyboard;
|
std::shared_ptr<Keyboard> keyboard;
|
||||||
std::shared_ptr<InputFactory> keyboard_factory;
|
|
||||||
std::shared_ptr<Mouse> mouse;
|
std::shared_ptr<Mouse> mouse;
|
||||||
std::shared_ptr<InputFactory> mouse_factory;
|
|
||||||
std::shared_ptr<GCAdapter> gcadapter;
|
std::shared_ptr<GCAdapter> gcadapter;
|
||||||
std::shared_ptr<InputFactory> gcadapter_factory;
|
|
||||||
std::shared_ptr<TouchScreen> touch_screen;
|
std::shared_ptr<TouchScreen> touch_screen;
|
||||||
std::shared_ptr<InputFactory> touch_screen_factory;
|
|
||||||
std::shared_ptr<CemuhookUDP::UDPClient> udp_client;
|
|
||||||
std::shared_ptr<InputFactory> udp_client_factory;
|
|
||||||
std::shared_ptr<TasInput::Tas> tas_input;
|
std::shared_ptr<TasInput::Tas> tas_input;
|
||||||
|
std::shared_ptr<CemuhookUDP::UDPClient> udp_client;
|
||||||
|
|
||||||
|
std::shared_ptr<InputFactory> keyboard_factory;
|
||||||
|
std::shared_ptr<InputFactory> mouse_factory;
|
||||||
|
std::shared_ptr<InputFactory> gcadapter_input_factory;
|
||||||
|
std::shared_ptr<InputFactory> touch_screen_factory;
|
||||||
|
std::shared_ptr<InputFactory> udp_client_factory;
|
||||||
std::shared_ptr<InputFactory> tas_input_factory;
|
std::shared_ptr<InputFactory> tas_input_factory;
|
||||||
|
|
||||||
|
std::shared_ptr<OutputFactory> gcadapter_output_factory;
|
||||||
|
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
std::shared_ptr<SDLDriver> sdl;
|
std::shared_ptr<SDLDriver> sdl;
|
||||||
std::shared_ptr<InputFactory> sdl_factory;
|
std::shared_ptr<InputFactory> sdl_input_factory;
|
||||||
|
std::shared_ptr<OutputFactory> sdl_output_factory;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -465,6 +465,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
UpdateControllerEnabledButtons();
|
UpdateControllerEnabledButtons();
|
||||||
UpdateControllerButtonNames();
|
UpdateControllerButtonNames();
|
||||||
UpdateMotionButtons();
|
UpdateMotionButtons();
|
||||||
|
emulated_controller->SetNpadType(
|
||||||
|
GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()));
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
|
connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
|
||||||
|
@ -540,6 +542,11 @@ void ConfigureInputPlayer::LoadConfiguration() {
|
||||||
|
|
||||||
void ConfigureInputPlayer::ConnectPlayer(bool connected) {
|
void ConfigureInputPlayer::ConnectPlayer(bool connected) {
|
||||||
ui->groupConnectedController->setChecked(connected);
|
ui->groupConnectedController->setChecked(connected);
|
||||||
|
if (connected) {
|
||||||
|
emulated_controller->Connect();
|
||||||
|
} else {
|
||||||
|
emulated_controller->Disconnect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
|
void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
|
||||||
|
|
|
@ -24,34 +24,6 @@ PlayerControlPreview::~PlayerControlPreview() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PlayerControlPreview::LedPattern PlayerControlPreview::GetColorPattern(std::size_t index,
|
|
||||||
bool player_on) {
|
|
||||||
if (!player_on) {
|
|
||||||
return {0, 0, 0, 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
return {1, 0, 0, 0};
|
|
||||||
case 1:
|
|
||||||
return {1, 1, 0, 0};
|
|
||||||
case 2:
|
|
||||||
return {1, 1, 1, 0};
|
|
||||||
case 3:
|
|
||||||
return {1, 1, 1, 1};
|
|
||||||
case 4:
|
|
||||||
return {1, 0, 0, 1};
|
|
||||||
case 5:
|
|
||||||
return {1, 0, 1, 0};
|
|
||||||
case 6:
|
|
||||||
return {1, 0, 1, 1};
|
|
||||||
case 7:
|
|
||||||
return {0, 1, 1, 0};
|
|
||||||
default:
|
|
||||||
return {0, 0, 0, 0};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerControlPreview::SetController(Core::HID::EmulatedController* controller_) {
|
void PlayerControlPreview::SetController(Core::HID::EmulatedController* controller_) {
|
||||||
if (is_controller_set) {
|
if (is_controller_set) {
|
||||||
controller->DeleteCallback(callback_key);
|
controller->DeleteCallback(callback_key);
|
||||||
|
@ -160,8 +132,13 @@ void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType typ
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Core::HID::ControllerTriggerType::Connected:
|
case Core::HID::ControllerTriggerType::Connected:
|
||||||
|
is_connected = true;
|
||||||
|
led_pattern = controller->GetLedPattern();
|
||||||
|
needs_redraw = true;
|
||||||
|
break;
|
||||||
case Core::HID::ControllerTriggerType::Disconnected:
|
case Core::HID::ControllerTriggerType::Disconnected:
|
||||||
is_connected = controller->IsConnected();
|
is_connected = false;
|
||||||
|
led_pattern.raw = 0;
|
||||||
needs_redraw = true;
|
needs_redraw = true;
|
||||||
break;
|
break;
|
||||||
case Core::HID::ControllerTriggerType::Type:
|
case Core::HID::ControllerTriggerType::Type:
|
||||||
|
@ -1853,10 +1830,14 @@ void PlayerControlPreview::DrawLeftBody(QPainter& p, const QPointF center) {
|
||||||
const float led_size = 5.0f;
|
const float led_size = 5.0f;
|
||||||
const QPointF led_position = sideview_center + QPointF(0, -36);
|
const QPointF led_position = sideview_center + QPointF(0, -36);
|
||||||
int led_count = 0;
|
int led_count = 0;
|
||||||
for (const auto& color : led_color) {
|
p.setBrush(led_pattern.position1 ? colors.led_on : colors.led_off);
|
||||||
p.setBrush(color);
|
DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
|
||||||
DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
|
p.setBrush(led_pattern.position2 ? colors.led_on : colors.led_off);
|
||||||
}
|
DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
|
||||||
|
p.setBrush(led_pattern.position3 ? colors.led_on : colors.led_off);
|
||||||
|
DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
|
||||||
|
p.setBrush(led_pattern.position4 ? colors.led_on : colors.led_off);
|
||||||
|
DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) {
|
void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) {
|
||||||
|
@ -1949,10 +1930,14 @@ void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) {
|
||||||
const float led_size = 5.0f;
|
const float led_size = 5.0f;
|
||||||
const QPointF led_position = sideview_center + QPointF(0, -36);
|
const QPointF led_position = sideview_center + QPointF(0, -36);
|
||||||
int led_count = 0;
|
int led_count = 0;
|
||||||
for (const auto& color : led_color) {
|
p.setBrush(led_pattern.position1 ? colors.led_on : colors.led_off);
|
||||||
p.setBrush(color);
|
DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
|
||||||
DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
|
p.setBrush(led_pattern.position2 ? colors.led_on : colors.led_off);
|
||||||
}
|
DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
|
||||||
|
p.setBrush(led_pattern.position3 ? colors.led_on : colors.led_off);
|
||||||
|
DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
|
||||||
|
p.setBrush(led_pattern.position4 ? colors.led_on : colors.led_off);
|
||||||
|
DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center,
|
void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center,
|
||||||
|
|
|
@ -59,13 +59,6 @@ private:
|
||||||
SR,
|
SR,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LedPattern {
|
|
||||||
bool position1;
|
|
||||||
bool position2;
|
|
||||||
bool position3;
|
|
||||||
bool position4;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ColorMapping {
|
struct ColorMapping {
|
||||||
QColor outline{};
|
QColor outline{};
|
||||||
QColor primary{};
|
QColor primary{};
|
||||||
|
@ -88,7 +81,6 @@ private:
|
||||||
QColor deadzone{};
|
QColor deadzone{};
|
||||||
};
|
};
|
||||||
|
|
||||||
static LedPattern GetColorPattern(std::size_t index, bool player_on);
|
|
||||||
void UpdateColors();
|
void UpdateColors();
|
||||||
void ResetInputs();
|
void ResetInputs();
|
||||||
|
|
||||||
|
@ -194,7 +186,7 @@ private:
|
||||||
int callback_key;
|
int callback_key;
|
||||||
QColor button_color{};
|
QColor button_color{};
|
||||||
ColorMapping colors{};
|
ColorMapping colors{};
|
||||||
std::array<QColor, 4> led_color{};
|
Core::HID::LedPattern led_pattern{0, 0, 0, 0};
|
||||||
std::size_t player_index{};
|
std::size_t player_index{};
|
||||||
Core::HID::EmulatedController* controller;
|
Core::HID::EmulatedController* controller;
|
||||||
std::size_t button_mapping_index{Settings::NativeButton::NumButtons};
|
std::size_t button_mapping_index{Settings::NativeButton::NumButtons};
|
||||||
|
|
Loading…
Reference in a new issue