Compare commits
1 Commits
sdl_who
...
system-con
Author | SHA1 | Date | |
---|---|---|---|
896670345e |
@ -159,6 +159,8 @@ add_library(core STATIC
|
|||||||
hid/irs_types.h
|
hid/irs_types.h
|
||||||
hid/motion_input.cpp
|
hid/motion_input.cpp
|
||||||
hid/motion_input.h
|
hid/motion_input.h
|
||||||
|
hid/system_controller.cpp
|
||||||
|
hid/system_controller.h
|
||||||
hle/api_version.h
|
hle/api_version.h
|
||||||
hle/ipc.h
|
hle/ipc.h
|
||||||
hle/kernel/board/nintendo/nx/k_memory_layout.cpp
|
hle/kernel/board/nintendo/nx/k_memory_layout.cpp
|
||||||
|
@ -46,26 +46,26 @@ void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callbac
|
|||||||
// Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
|
// Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
|
||||||
if (parameters.allow_pro_controller) {
|
if (parameters.allow_pro_controller) {
|
||||||
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
|
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
|
||||||
controller->Connect(true);
|
controller->Connect();
|
||||||
} else if (parameters.allow_dual_joycons) {
|
} else if (parameters.allow_dual_joycons) {
|
||||||
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual);
|
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual);
|
||||||
controller->Connect(true);
|
controller->Connect();
|
||||||
} else if (parameters.allow_left_joycon && parameters.allow_right_joycon) {
|
} else if (parameters.allow_left_joycon && parameters.allow_right_joycon) {
|
||||||
// Assign left joycons to even player indices and right joycons to odd player indices.
|
// Assign left joycons to even player indices and right joycons to odd player indices.
|
||||||
// We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and
|
// We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and
|
||||||
// a right Joycon for Player 2 in 2 Player Assist mode.
|
// a right Joycon for Player 2 in 2 Player Assist mode.
|
||||||
if (index % 2 == 0) {
|
if (index % 2 == 0) {
|
||||||
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconLeft);
|
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconLeft);
|
||||||
controller->Connect(true);
|
controller->Connect();
|
||||||
} else {
|
} else {
|
||||||
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconRight);
|
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconRight);
|
||||||
controller->Connect(true);
|
controller->Connect();
|
||||||
}
|
}
|
||||||
} else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
|
} else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
|
||||||
!Settings::values.use_docked_mode.GetValue()) {
|
!Settings::values.use_docked_mode.GetValue()) {
|
||||||
// We should *never* reach here under any normal circumstances.
|
// We should *never* reach here under any normal circumstances.
|
||||||
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
|
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
|
||||||
controller->Connect(true);
|
controller->Connect();
|
||||||
} else {
|
} else {
|
||||||
ASSERT_MSG(false, "Unable to add a new controller based on the given parameters!");
|
ASSERT_MSG(false, "Unable to add a new controller based on the given parameters!");
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,6 @@ void EmulatedController::ReloadFromSettings() {
|
|||||||
motion_params[index] = Common::ParamPackage(player.motions[index]);
|
motion_params[index] = Common::ParamPackage(player.motions[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.color_values = {};
|
|
||||||
controller.colors_state.fullkey = {
|
controller.colors_state.fullkey = {
|
||||||
.body = GetNpadColor(player.body_color_left),
|
.body = GetNpadColor(player.body_color_left),
|
||||||
.button = GetNpadColor(player.button_color_left),
|
.button = GetNpadColor(player.button_color_left),
|
||||||
@ -537,181 +536,18 @@ void EmulatedController::UnloadInput() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::EnableConfiguration() {
|
void EmulatedController::DisableInput() {
|
||||||
is_configuring = true;
|
npad_input_enabled = false;
|
||||||
tmp_is_connected = is_connected;
|
|
||||||
tmp_npad_type = npad_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::DisableConfiguration() {
|
void EmulatedController::EnableInput() {
|
||||||
is_configuring = false;
|
npad_input_enabled = true;
|
||||||
|
|
||||||
// Get Joycon colors before turning on the controller
|
// Get Joycon colors before turning on the controller
|
||||||
for (const auto& color_device : color_devices) {
|
for (const auto& color_device : color_devices) {
|
||||||
color_device->ForceUpdate();
|
color_device->ForceUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply temporary npad type to the real controller
|
|
||||||
if (tmp_npad_type != npad_type) {
|
|
||||||
if (is_connected) {
|
|
||||||
Disconnect();
|
|
||||||
}
|
|
||||||
SetNpadStyleIndex(tmp_npad_type);
|
|
||||||
original_npad_type = tmp_npad_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply temporary connected status to the real controller
|
|
||||||
if (tmp_is_connected != is_connected) {
|
|
||||||
if (tmp_is_connected) {
|
|
||||||
Connect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmulatedController::EnableSystemButtons() {
|
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
system_buttons_enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmulatedController::DisableSystemButtons() {
|
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
system_buttons_enabled = false;
|
|
||||||
controller.home_button_state.raw = 0;
|
|
||||||
controller.capture_button_state.raw = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmulatedController::ResetSystemButtons() {
|
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
controller.home_button_state.home.Assign(false);
|
|
||||||
controller.capture_button_state.capture.Assign(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmulatedController::IsConfiguring() const {
|
|
||||||
return is_configuring;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmulatedController::SaveCurrentConfig() {
|
|
||||||
const auto player_index = NpadIdTypeToIndex(npad_id_type);
|
|
||||||
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) {
|
|
||||||
player.buttons[index] = button_params[index].Serialize();
|
|
||||||
}
|
|
||||||
for (std::size_t index = 0; index < player.analogs.size(); ++index) {
|
|
||||||
player.analogs[index] = stick_params[index].Serialize();
|
|
||||||
}
|
|
||||||
for (std::size_t index = 0; index < player.motions.size(); ++index) {
|
|
||||||
player.motions[index] = motion_params[index].Serialize();
|
|
||||||
}
|
|
||||||
if (npad_id_type == NpadIdType::Player1) {
|
|
||||||
Settings::values.ringcon_analogs = ring_params[0].Serialize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmulatedController::RestoreConfig() {
|
|
||||||
if (!is_configuring) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ReloadFromSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices() const {
|
|
||||||
std::vector<Common::ParamPackage> devices;
|
|
||||||
for (const auto& param : button_params) {
|
|
||||||
if (!param.Has("engine")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const auto devices_it = std::find_if(
|
|
||||||
devices.begin(), devices.end(), [¶m](const Common::ParamPackage& param_) {
|
|
||||||
return param.Get("engine", "") == param_.Get("engine", "") &&
|
|
||||||
param.Get("guid", "") == param_.Get("guid", "") &&
|
|
||||||
param.Get("port", 0) == param_.Get("port", 0) &&
|
|
||||||
param.Get("pad", 0) == param_.Get("pad", 0);
|
|
||||||
});
|
|
||||||
if (devices_it != devices.end()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& device = devices.emplace_back();
|
|
||||||
device.Set("engine", param.Get("engine", ""));
|
|
||||||
device.Set("guid", param.Get("guid", ""));
|
|
||||||
device.Set("port", param.Get("port", 0));
|
|
||||||
device.Set("pad", param.Get("pad", 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& param : stick_params) {
|
|
||||||
if (!param.Has("engine")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (param.Get("engine", "") == "analog_from_button") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const auto devices_it = std::find_if(
|
|
||||||
devices.begin(), devices.end(), [¶m](const Common::ParamPackage& param_) {
|
|
||||||
return param.Get("engine", "") == param_.Get("engine", "") &&
|
|
||||||
param.Get("guid", "") == param_.Get("guid", "") &&
|
|
||||||
param.Get("port", 0) == param_.Get("port", 0) &&
|
|
||||||
param.Get("pad", 0) == param_.Get("pad", 0);
|
|
||||||
});
|
|
||||||
if (devices_it != devices.end()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& device = devices.emplace_back();
|
|
||||||
device.Set("engine", param.Get("engine", ""));
|
|
||||||
device.Set("guid", param.Get("guid", ""));
|
|
||||||
device.Set("port", param.Get("port", 0));
|
|
||||||
device.Set("pad", param.Get("pad", 0));
|
|
||||||
}
|
|
||||||
return devices;
|
|
||||||
}
|
|
||||||
|
|
||||||
Common::ParamPackage EmulatedController::GetButtonParam(std::size_t index) const {
|
|
||||||
if (index >= button_params.size()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return button_params[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
Common::ParamPackage EmulatedController::GetStickParam(std::size_t index) const {
|
|
||||||
if (index >= stick_params.size()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return stick_params[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
Common::ParamPackage EmulatedController::GetMotionParam(std::size_t index) const {
|
|
||||||
if (index >= motion_params.size()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return motion_params[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmulatedController::SetButtonParam(std::size_t index, Common::ParamPackage param) {
|
|
||||||
if (index >= button_params.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
button_params[index] = std::move(param);
|
|
||||||
ReloadInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmulatedController::SetStickParam(std::size_t index, Common::ParamPackage param) {
|
|
||||||
if (index >= stick_params.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stick_params[index] = std::move(param);
|
|
||||||
ReloadInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage param) {
|
|
||||||
if (index >= motion_params.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
motion_params[index] = std::move(param);
|
|
||||||
ReloadInput();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::StartMotionCalibration() {
|
void EmulatedController::StartMotionCalibration() {
|
||||||
@ -766,16 +602,6 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_configuring) {
|
|
||||||
controller.npad_button_state.raw = NpadButton::None;
|
|
||||||
controller.debug_pad_button_state.raw = 0;
|
|
||||||
controller.home_button_state.raw = 0;
|
|
||||||
controller.capture_button_state.raw = 0;
|
|
||||||
lock.unlock();
|
|
||||||
TriggerOnChange(ControllerTriggerType::Button, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GC controllers have triggers not buttons
|
// GC controllers have triggers not buttons
|
||||||
if (npad_type == NpadStyleIndex::GameCube) {
|
if (npad_type == NpadStyleIndex::GameCube) {
|
||||||
if (index == Settings::NativeButton::ZR) {
|
if (index == Settings::NativeButton::ZR) {
|
||||||
@ -857,18 +683,6 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback
|
|||||||
controller.npad_button_state.left_sr.Assign(current_status.value);
|
controller.npad_button_state.left_sr.Assign(current_status.value);
|
||||||
controller.npad_button_state.right_sr.Assign(current_status.value);
|
controller.npad_button_state.right_sr.Assign(current_status.value);
|
||||||
break;
|
break;
|
||||||
case Settings::NativeButton::Home:
|
|
||||||
if (!system_buttons_enabled) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
controller.home_button_state.home.Assign(current_status.value);
|
|
||||||
break;
|
|
||||||
case Settings::NativeButton::Screenshot:
|
|
||||||
if (!system_buttons_enabled) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
controller.capture_button_state.capture.Assign(current_status.value);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
@ -881,7 +695,7 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback
|
|||||||
Connect();
|
Connect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TriggerOnChange(ControllerTriggerType::Button, true);
|
TriggerOnChange(ControllerTriggerType::Button);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, std::size_t index,
|
void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, std::size_t index,
|
||||||
@ -890,7 +704,7 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto trigger_guard =
|
auto trigger_guard =
|
||||||
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); });
|
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick); });
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
const auto stick_value = TransformToStick(callback);
|
const auto stick_value = TransformToStick(callback);
|
||||||
|
|
||||||
@ -911,12 +725,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
|
|||||||
controller.stick_values[index] = stick_value;
|
controller.stick_values[index] = stick_value;
|
||||||
controller.stick_values[index].uuid = uuid;
|
controller.stick_values[index].uuid = uuid;
|
||||||
|
|
||||||
if (is_configuring) {
|
|
||||||
controller.analog_stick_state.left = {};
|
|
||||||
controller.analog_stick_state.right = {};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AnalogStickState stick{
|
const AnalogStickState stick{
|
||||||
.x = static_cast<s32>(controller.stick_values[index].x.value * HID_JOYSTICK_MAX),
|
.x = static_cast<s32>(controller.stick_values[index].x.value * HID_JOYSTICK_MAX),
|
||||||
.y = static_cast<s32>(controller.stick_values[index].y.value * HID_JOYSTICK_MAX),
|
.y = static_cast<s32>(controller.stick_values[index].y.value * HID_JOYSTICK_MAX),
|
||||||
@ -946,7 +754,7 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto trigger_guard =
|
auto trigger_guard =
|
||||||
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); });
|
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger); });
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
const auto trigger_value = TransformToTrigger(callback);
|
const auto trigger_value = TransformToTrigger(callback);
|
||||||
|
|
||||||
@ -960,12 +768,6 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
|
|||||||
controller.trigger_values[index] = trigger_value;
|
controller.trigger_values[index] = trigger_value;
|
||||||
controller.trigger_values[index].uuid = uuid;
|
controller.trigger_values[index].uuid = uuid;
|
||||||
|
|
||||||
if (is_configuring) {
|
|
||||||
controller.gc_trigger_state.left = 0;
|
|
||||||
controller.gc_trigger_state.right = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only GC controllers have analog triggers
|
// Only GC controllers have analog triggers
|
||||||
if (npad_type != NpadStyleIndex::GameCube) {
|
if (npad_type != NpadStyleIndex::GameCube) {
|
||||||
trigger_guard.Cancel();
|
trigger_guard.Cancel();
|
||||||
@ -992,7 +794,7 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
|
|||||||
if (index >= controller.motion_values.size()) {
|
if (index >= controller.motion_values.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Motion, !is_configuring); });
|
SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Motion); });
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
auto& raw_status = controller.motion_values[index].raw_status;
|
auto& raw_status = controller.motion_values[index].raw_status;
|
||||||
auto& emulated = controller.motion_values[index].emulated;
|
auto& emulated = controller.motion_values[index].emulated;
|
||||||
@ -1023,48 +825,44 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
|
|||||||
|
|
||||||
void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback,
|
void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback,
|
||||||
std::size_t index) {
|
std::size_t index) {
|
||||||
if (index >= controller.color_values.size()) {
|
if (index > RightIndex) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto trigger_guard =
|
auto trigger_guard =
|
||||||
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Color, !is_configuring); });
|
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Color); });
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
controller.color_values[index] = TransformToColor(callback);
|
const auto color_values = TransformToColor(callback);
|
||||||
|
|
||||||
if (is_configuring) {
|
if (color_values.body == 0) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (controller.color_values[index].body == 0) {
|
|
||||||
trigger_guard.Cancel();
|
trigger_guard.Cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.colors_state.fullkey = {
|
controller.colors_state.fullkey = {
|
||||||
.body = GetNpadColor(controller.color_values[index].body),
|
.body = GetNpadColor(color_values.body),
|
||||||
.button = GetNpadColor(controller.color_values[index].buttons),
|
.button = GetNpadColor(color_values.buttons),
|
||||||
};
|
};
|
||||||
if (npad_type == NpadStyleIndex::ProController) {
|
if (npad_type == NpadStyleIndex::ProController) {
|
||||||
controller.colors_state.left = {
|
controller.colors_state.left = {
|
||||||
.body = GetNpadColor(controller.color_values[index].left_grip),
|
.body = GetNpadColor(color_values.left_grip),
|
||||||
.button = GetNpadColor(controller.color_values[index].buttons),
|
.button = GetNpadColor(color_values.buttons),
|
||||||
};
|
};
|
||||||
controller.colors_state.right = {
|
controller.colors_state.right = {
|
||||||
.body = GetNpadColor(controller.color_values[index].right_grip),
|
.body = GetNpadColor(color_values.right_grip),
|
||||||
.button = GetNpadColor(controller.color_values[index].buttons),
|
.button = GetNpadColor(color_values.buttons),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case LeftIndex:
|
case LeftIndex:
|
||||||
controller.colors_state.left = {
|
controller.colors_state.left = {
|
||||||
.body = GetNpadColor(controller.color_values[index].body),
|
.body = GetNpadColor(color_values.body),
|
||||||
.button = GetNpadColor(controller.color_values[index].buttons),
|
.button = GetNpadColor(color_values.buttons),
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case RightIndex:
|
case RightIndex:
|
||||||
controller.colors_state.right = {
|
controller.colors_state.right = {
|
||||||
.body = GetNpadColor(controller.color_values[index].body),
|
.body = GetNpadColor(color_values.body),
|
||||||
.button = GetNpadColor(controller.color_values[index].buttons),
|
.button = GetNpadColor(color_values.buttons),
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1073,21 +871,17 @@ void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback
|
|||||||
|
|
||||||
void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback,
|
void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback,
|
||||||
std::size_t index) {
|
std::size_t index) {
|
||||||
if (index >= controller.battery_values.size()) {
|
if (index > DualIndex) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Battery, !is_configuring); });
|
SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Battery); });
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
controller.battery_values[index] = TransformToBattery(callback);
|
const auto battery_values = TransformToBattery(callback);
|
||||||
|
|
||||||
if (is_configuring) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_charging = false;
|
bool is_charging = false;
|
||||||
bool is_powered = false;
|
bool is_powered = false;
|
||||||
NpadBatteryLevel battery_level = 0;
|
NpadBatteryLevel battery_level = 0;
|
||||||
switch (controller.battery_values[index]) {
|
switch (battery_values) {
|
||||||
case Common::Input::BatteryLevel::Charging:
|
case Common::Input::BatteryLevel::Charging:
|
||||||
is_charging = true;
|
is_charging = true;
|
||||||
is_powered = true;
|
is_powered = true;
|
||||||
@ -1139,46 +933,33 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) {
|
void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) {
|
||||||
SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::IrSensor, !is_configuring); });
|
SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::IrSensor); });
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
controller.camera_values = TransformToCamera(callback);
|
const auto camera_values = TransformToCamera(callback);
|
||||||
|
|
||||||
if (is_configuring) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller.camera_state.sample++;
|
controller.camera_state.sample++;
|
||||||
controller.camera_state.format =
|
controller.camera_state.format =
|
||||||
static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format);
|
static_cast<Core::IrSensor::ImageTransferProcessorFormat>(camera_values.format);
|
||||||
controller.camera_state.data = controller.camera_values.data;
|
controller.camera_state.data = camera_values.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) {
|
void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) {
|
||||||
SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::RingController, !is_configuring); });
|
SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::RingController); });
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
const auto force_value = TransformToStick(callback);
|
const auto force_value = TransformToStick(callback);
|
||||||
|
|
||||||
controller.ring_analog_value = force_value.x;
|
|
||||||
|
|
||||||
if (is_configuring) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller.ring_analog_state.force = force_value.x.value;
|
controller.ring_analog_state.force = force_value.x.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
|
void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
|
||||||
SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Nfc, !is_configuring); });
|
SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Nfc); });
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
controller.nfc_values = TransformToNfc(callback);
|
const auto nfc_values = TransformToNfc(callback);
|
||||||
|
|
||||||
if (is_configuring) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller.nfc_state = {
|
controller.nfc_state = {
|
||||||
controller.nfc_values.state,
|
nfc_values.state,
|
||||||
controller.nfc_values.data,
|
nfc_values.data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1409,10 +1190,9 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles)
|
|||||||
npad_type);
|
npad_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const {
|
bool EmulatedController::IsControllerFullkey() const {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
|
switch (npad_type) {
|
||||||
switch (type) {
|
|
||||||
case NpadStyleIndex::ProController:
|
case NpadStyleIndex::ProController:
|
||||||
case NpadStyleIndex::GameCube:
|
case NpadStyleIndex::GameCube:
|
||||||
case NpadStyleIndex::NES:
|
case NpadStyleIndex::NES:
|
||||||
@ -1425,10 +1205,9 @@ bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmulatedController::IsControllerSupported(bool use_temporary_value) const {
|
bool EmulatedController::IsControllerSupported() const {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
|
switch (npad_type) {
|
||||||
switch (type) {
|
|
||||||
case NpadStyleIndex::ProController:
|
case NpadStyleIndex::ProController:
|
||||||
return supported_style_tag.fullkey.As<bool>();
|
return supported_style_tag.fullkey.As<bool>();
|
||||||
case NpadStyleIndex::Handheld:
|
case NpadStyleIndex::Handheld:
|
||||||
@ -1456,20 +1235,15 @@ bool EmulatedController::IsControllerSupported(bool use_temporary_value) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::Connect(bool use_temporary_value) {
|
void EmulatedController::Connect() {
|
||||||
if (!IsControllerSupported(use_temporary_value)) {
|
if (!IsControllerSupported()) {
|
||||||
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
|
LOG_ERROR(Service_HID, "Controller type {} is not supported", npad_type);
|
||||||
LOG_ERROR(Service_HID, "Controller type {} is not supported", type);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto trigger_guard =
|
auto trigger_guard =
|
||||||
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); });
|
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected); });
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
if (is_configuring) {
|
|
||||||
tmp_is_connected = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_connected) {
|
if (is_connected) {
|
||||||
trigger_guard.Cancel();
|
trigger_guard.Cancel();
|
||||||
@ -1480,12 +1254,8 @@ void EmulatedController::Connect(bool use_temporary_value) {
|
|||||||
|
|
||||||
void EmulatedController::Disconnect() {
|
void EmulatedController::Disconnect() {
|
||||||
auto trigger_guard =
|
auto trigger_guard =
|
||||||
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); });
|
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected); });
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
if (is_configuring) {
|
|
||||||
tmp_is_connected = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_connected) {
|
if (!is_connected) {
|
||||||
trigger_guard.Cancel();
|
trigger_guard.Cancel();
|
||||||
@ -1494,11 +1264,8 @@ void EmulatedController::Disconnect() {
|
|||||||
is_connected = false;
|
is_connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmulatedController::IsConnected(bool get_temporary_value) const {
|
bool EmulatedController::IsConnected() const {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
if (get_temporary_value && is_configuring) {
|
|
||||||
return tmp_is_connected;
|
|
||||||
}
|
|
||||||
return is_connected;
|
return is_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1508,27 +1275,14 @@ NpadIdType EmulatedController::GetNpadIdType() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const {
|
NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const {
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
if (get_temporary_value && is_configuring) {
|
|
||||||
return tmp_npad_type;
|
|
||||||
}
|
|
||||||
return npad_type;
|
return npad_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
|
void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
|
||||||
auto trigger_guard =
|
auto trigger_guard =
|
||||||
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type, !is_configuring); });
|
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type); });
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
if (is_configuring) {
|
|
||||||
if (tmp_npad_type == npad_type_) {
|
|
||||||
trigger_guard.Cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tmp_npad_type = npad_type_;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npad_type == npad_type_) {
|
if (npad_type == npad_type_) {
|
||||||
trigger_guard.Cancel();
|
trigger_guard.Cancel();
|
||||||
return;
|
return;
|
||||||
@ -1568,87 +1322,23 @@ ButtonValues EmulatedController::GetButtonsValues() const {
|
|||||||
return controller.button_values;
|
return controller.button_values;
|
||||||
}
|
}
|
||||||
|
|
||||||
SticksValues EmulatedController::GetSticksValues() const {
|
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
return controller.stick_values;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerValues EmulatedController::GetTriggersValues() const {
|
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
return controller.trigger_values;
|
|
||||||
}
|
|
||||||
|
|
||||||
ControllerMotionValues EmulatedController::GetMotionValues() const {
|
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
return controller.motion_values;
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorValues EmulatedController::GetColorsValues() const {
|
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
return controller.color_values;
|
|
||||||
}
|
|
||||||
|
|
||||||
BatteryValues EmulatedController::GetBatteryValues() const {
|
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
return controller.battery_values;
|
|
||||||
}
|
|
||||||
|
|
||||||
CameraValues EmulatedController::GetCameraValues() const {
|
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
return controller.camera_values;
|
|
||||||
}
|
|
||||||
|
|
||||||
RingAnalogValue EmulatedController::GetRingSensorValues() const {
|
|
||||||
return controller.ring_analog_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
HomeButtonState EmulatedController::GetHomeButtons() const {
|
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
if (is_configuring) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return controller.home_button_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
CaptureButtonState EmulatedController::GetCaptureButtons() const {
|
|
||||||
std::scoped_lock lock{mutex};
|
|
||||||
if (is_configuring) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return controller.capture_button_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
NpadButtonState EmulatedController::GetNpadButtons() const {
|
NpadButtonState EmulatedController::GetNpadButtons() const {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
if (is_configuring) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return {controller.npad_button_state.raw & GetTurboButtonMask()};
|
return {controller.npad_button_state.raw & GetTurboButtonMask()};
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugPadButton EmulatedController::GetDebugPadButtons() const {
|
DebugPadButton EmulatedController::GetDebugPadButtons() const {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
if (is_configuring) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return controller.debug_pad_button_state;
|
return controller.debug_pad_button_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnalogSticks EmulatedController::GetSticks() const {
|
AnalogSticks EmulatedController::GetSticks() const {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
if (is_configuring) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return controller.analog_stick_state;
|
return controller.analog_stick_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
NpadGcTriggerState EmulatedController::GetTriggers() const {
|
NpadGcTriggerState EmulatedController::GetTriggers() const {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
if (is_configuring) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return controller.gc_trigger_state;
|
return controller.gc_trigger_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1673,6 +1363,7 @@ const CameraState& EmulatedController::GetCamera() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RingSensorForce EmulatedController::GetRingSensorForce() const {
|
RingSensorForce EmulatedController::GetRingSensorForce() const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
return controller.ring_analog_state;
|
return controller.ring_analog_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1690,13 +1381,10 @@ NpadColor EmulatedController::GetNpadColor(u32 color) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) {
|
void EmulatedController::TriggerOnChange(ControllerTriggerType type) {
|
||||||
std::scoped_lock lock{callback_mutex};
|
std::scoped_lock lock{callback_mutex};
|
||||||
for (const auto& poller_pair : callback_list) {
|
for (const auto& poller_pair : callback_list) {
|
||||||
const ControllerUpdateCallback& poller = poller_pair.second;
|
const ControllerUpdateCallback& poller = poller_pair.second;
|
||||||
if (!is_npad_service_update && poller.is_npad_service) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (poller.on_change) {
|
if (poller.on_change) {
|
||||||
poller.on_change(type);
|
poller.on_change(type);
|
||||||
}
|
}
|
||||||
|
@ -126,16 +126,8 @@ struct ControllerStatus {
|
|||||||
SticksValues stick_values{};
|
SticksValues stick_values{};
|
||||||
ControllerMotionValues motion_values{};
|
ControllerMotionValues motion_values{};
|
||||||
TriggerValues trigger_values{};
|
TriggerValues trigger_values{};
|
||||||
ColorValues color_values{};
|
|
||||||
BatteryValues battery_values{};
|
|
||||||
VibrationValues vibration_values{};
|
|
||||||
CameraValues camera_values{};
|
|
||||||
RingAnalogValue ring_analog_value{};
|
|
||||||
NfcValues nfc_values{};
|
|
||||||
|
|
||||||
// Data for HID services
|
// Data for HID services
|
||||||
HomeButtonState home_button_state{};
|
|
||||||
CaptureButtonState capture_button_state{};
|
|
||||||
NpadButtonState npad_button_state{};
|
NpadButtonState npad_button_state{};
|
||||||
DebugPadButton debug_pad_button_state{};
|
DebugPadButton debug_pad_button_state{};
|
||||||
AnalogSticks analog_stick_state{};
|
AnalogSticks analog_stick_state{};
|
||||||
@ -167,7 +159,6 @@ enum class ControllerTriggerType {
|
|||||||
|
|
||||||
struct ControllerUpdateCallback {
|
struct ControllerUpdateCallback {
|
||||||
std::function<void(ControllerTriggerType)> on_change;
|
std::function<void(ControllerTriggerType)> on_change;
|
||||||
bool is_npad_service;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmulatedController {
|
class EmulatedController {
|
||||||
@ -210,43 +201,29 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the connected status to true
|
* Sets the connected status to true
|
||||||
* @param use_temporary_value If true tmp_npad_type will be used
|
|
||||||
*/
|
*/
|
||||||
void Connect(bool use_temporary_value = false);
|
void Connect();
|
||||||
|
|
||||||
/// Sets the connected status to false
|
/// Sets the connected status to false
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the emulated connected
|
* Is the emulated connected
|
||||||
* @param get_temporary_value If true tmp_is_connected will be returned
|
|
||||||
* @return true if the controller has the connected status
|
* @return true if the controller has the connected status
|
||||||
*/
|
*/
|
||||||
bool IsConnected(bool get_temporary_value = false) const;
|
bool IsConnected() const;
|
||||||
|
|
||||||
/// Removes all callbacks created from input devices
|
/// Removes all callbacks created from input devices
|
||||||
void UnloadInput();
|
void UnloadInput();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the emulated controller into configuring mode
|
* Sets the emulated controller into idle mode
|
||||||
* This prevents the modification of the HID state of the emulated controller by input commands
|
* This prevents the modification of the HID state of the emulated controller by input commands
|
||||||
*/
|
*/
|
||||||
void EnableConfiguration();
|
void DisableInput();
|
||||||
|
|
||||||
/// Returns the emulated controller into normal mode, allowing the modification of the HID state
|
/// Returns the emulated controller into normal mode, allowing the modification of the HID state
|
||||||
void DisableConfiguration();
|
void EnableInput();
|
||||||
|
|
||||||
/// Enables Home and Screenshot buttons
|
|
||||||
void EnableSystemButtons();
|
|
||||||
|
|
||||||
/// Disables Home and Screenshot buttons
|
|
||||||
void DisableSystemButtons();
|
|
||||||
|
|
||||||
/// Sets Home and Screenshot buttons to false
|
|
||||||
void ResetSystemButtons();
|
|
||||||
|
|
||||||
/// Returns true if the emulated controller is in configuring mode
|
|
||||||
bool IsConfiguring() const;
|
|
||||||
|
|
||||||
/// Reload all input devices
|
/// Reload all input devices
|
||||||
void ReloadInput();
|
void ReloadInput();
|
||||||
@ -254,75 +231,9 @@ public:
|
|||||||
/// Overrides current mapped devices with the stored configuration and reloads all input devices
|
/// Overrides current mapped devices with the stored configuration and reloads all input devices
|
||||||
void ReloadFromSettings();
|
void ReloadFromSettings();
|
||||||
|
|
||||||
/// Saves the current mapped configuration
|
|
||||||
void SaveCurrentConfig();
|
|
||||||
|
|
||||||
/// Reverts any mapped changes made that weren't saved
|
|
||||||
void RestoreConfig();
|
|
||||||
|
|
||||||
/// Returns a vector of mapped devices from the mapped button and stick parameters
|
|
||||||
std::vector<Common::ParamPackage> GetMappedDevices() const;
|
|
||||||
|
|
||||||
// Returns the current mapped button device
|
|
||||||
Common::ParamPackage GetButtonParam(std::size_t index) const;
|
|
||||||
|
|
||||||
// Returns the current mapped stick device
|
|
||||||
Common::ParamPackage GetStickParam(std::size_t index) const;
|
|
||||||
|
|
||||||
// Returns the current mapped motion device
|
|
||||||
Common::ParamPackage GetMotionParam(std::size_t index) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the current mapped button device
|
|
||||||
* @param param ParamPackage with controller data to be mapped
|
|
||||||
*/
|
|
||||||
void SetButtonParam(std::size_t index, Common::ParamPackage param);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the current mapped stick device
|
|
||||||
* @param param ParamPackage with controller data to be mapped
|
|
||||||
*/
|
|
||||||
void SetStickParam(std::size_t index, Common::ParamPackage param);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the current mapped motion device
|
|
||||||
* @param param ParamPackage with controller data to be mapped
|
|
||||||
*/
|
|
||||||
void SetMotionParam(std::size_t index, Common::ParamPackage param);
|
|
||||||
|
|
||||||
/// Auto calibrates the current motion devices
|
|
||||||
void StartMotionCalibration();
|
|
||||||
|
|
||||||
/// Returns the latest button status from the controller with parameters
|
/// Returns the latest button status from the controller with parameters
|
||||||
ButtonValues GetButtonsValues() const;
|
ButtonValues GetButtonsValues() const;
|
||||||
|
|
||||||
/// Returns the latest analog stick status from the controller with parameters
|
|
||||||
SticksValues GetSticksValues() const;
|
|
||||||
|
|
||||||
/// Returns the latest trigger status from the controller with parameters
|
|
||||||
TriggerValues GetTriggersValues() const;
|
|
||||||
|
|
||||||
/// Returns the latest motion status from the controller with parameters
|
|
||||||
ControllerMotionValues GetMotionValues() const;
|
|
||||||
|
|
||||||
/// Returns the latest color status from the controller with parameters
|
|
||||||
ColorValues GetColorsValues() const;
|
|
||||||
|
|
||||||
/// Returns the latest battery status from the controller with parameters
|
|
||||||
BatteryValues GetBatteryValues() const;
|
|
||||||
|
|
||||||
/// Returns the latest camera status from the controller with parameters
|
|
||||||
CameraValues GetCameraValues() const;
|
|
||||||
|
|
||||||
/// Returns the latest status of analog input from the ring sensor with parameters
|
|
||||||
RingAnalogValue GetRingSensorValues() const;
|
|
||||||
|
|
||||||
/// Returns the latest status of button input for the hid::HomeButton service
|
|
||||||
HomeButtonState GetHomeButtons() const;
|
|
||||||
|
|
||||||
/// Returns the latest status of button input for the hid::CaptureButton service
|
|
||||||
CaptureButtonState GetCaptureButtons() const;
|
|
||||||
|
|
||||||
/// Returns the latest status of button input for the hid::Npad service
|
/// Returns the latest status of button input for the hid::Npad service
|
||||||
NpadButtonState GetNpadButtons() const;
|
NpadButtonState GetNpadButtons() const;
|
||||||
|
|
||||||
@ -432,17 +343,15 @@ private:
|
|||||||
void LoadVirtualGamepadParams();
|
void LoadVirtualGamepadParams();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param use_temporary_value If true tmp_npad_type will be used
|
|
||||||
* @return true if the controller style is fullkey
|
* @return true if the controller style is fullkey
|
||||||
*/
|
*/
|
||||||
bool IsControllerFullkey(bool use_temporary_value = false) const;
|
bool IsControllerFullkey() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the current controller type against the supported_style_tag
|
* Checks the current controller type against the supported_style_tag
|
||||||
* @param use_temporary_value If true tmp_npad_type will be used
|
|
||||||
* @return true if the controller is supported
|
* @return true if the controller is supported
|
||||||
*/
|
*/
|
||||||
bool IsControllerSupported(bool use_temporary_value = false) const;
|
bool IsControllerSupported() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the button status of the controller
|
* Updates the button status of the controller
|
||||||
@ -517,9 +426,8 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Triggers a callback that something has changed on the controller status
|
* Triggers a callback that something has changed on the controller status
|
||||||
* @param type Input type of the event to trigger
|
* @param type Input type of the event to trigger
|
||||||
* @param is_service_update indicates if this event should only be sent to HID services
|
|
||||||
*/
|
*/
|
||||||
void TriggerOnChange(ControllerTriggerType type, bool is_service_update);
|
void TriggerOnChange(ControllerTriggerType type);
|
||||||
|
|
||||||
NpadButton GetTurboButtonMask() const;
|
NpadButton GetTurboButtonMask() const;
|
||||||
|
|
||||||
@ -528,15 +436,10 @@ private:
|
|||||||
NpadStyleIndex original_npad_type{NpadStyleIndex::None};
|
NpadStyleIndex original_npad_type{NpadStyleIndex::None};
|
||||||
NpadStyleTag supported_style_tag{NpadStyleSet::All};
|
NpadStyleTag supported_style_tag{NpadStyleSet::All};
|
||||||
bool is_connected{false};
|
bool is_connected{false};
|
||||||
bool is_configuring{false};
|
bool npad_input_enabled{true};
|
||||||
bool system_buttons_enabled{true};
|
|
||||||
f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard};
|
f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard};
|
||||||
u32 turbo_button_state{0};
|
u32 turbo_button_state{0};
|
||||||
|
|
||||||
// Temporary values to avoid doing changes while the controller is in configuring mode
|
|
||||||
NpadStyleIndex tmp_npad_type{NpadStyleIndex::None};
|
|
||||||
bool tmp_is_connected{false};
|
|
||||||
|
|
||||||
ButtonParams button_params;
|
ButtonParams button_params;
|
||||||
StickParams stick_params;
|
StickParams stick_params;
|
||||||
ControllerMotionParams motion_params;
|
ControllerMotionParams motion_params;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "core/hid/emulated_controller.h"
|
#include "core/hid/emulated_controller.h"
|
||||||
#include "core/hid/emulated_devices.h"
|
#include "core/hid/emulated_devices.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
|
#include "core/hid/system_controller.h"
|
||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
|
|
||||||
@ -20,6 +21,16 @@ HIDCore::HIDCore()
|
|||||||
player_8{std::make_unique<EmulatedController>(NpadIdType::Player8)},
|
player_8{std::make_unique<EmulatedController>(NpadIdType::Player8)},
|
||||||
other{std::make_unique<EmulatedController>(NpadIdType::Other)},
|
other{std::make_unique<EmulatedController>(NpadIdType::Other)},
|
||||||
handheld{std::make_unique<EmulatedController>(NpadIdType::Handheld)},
|
handheld{std::make_unique<EmulatedController>(NpadIdType::Handheld)},
|
||||||
|
system_player_1{std::make_unique<SystemController>(NpadIdType::Player1)},
|
||||||
|
system_player_2{std::make_unique<SystemController>(NpadIdType::Player2)},
|
||||||
|
system_player_3{std::make_unique<SystemController>(NpadIdType::Player3)},
|
||||||
|
system_player_4{std::make_unique<SystemController>(NpadIdType::Player4)},
|
||||||
|
system_player_5{std::make_unique<SystemController>(NpadIdType::Player5)},
|
||||||
|
system_player_6{std::make_unique<SystemController>(NpadIdType::Player6)},
|
||||||
|
system_player_7{std::make_unique<SystemController>(NpadIdType::Player7)},
|
||||||
|
system_player_8{std::make_unique<SystemController>(NpadIdType::Player8)},
|
||||||
|
system_other{std::make_unique<SystemController>(NpadIdType::Other)},
|
||||||
|
system_handheld{std::make_unique<SystemController>(NpadIdType::Handheld)},
|
||||||
console{std::make_unique<EmulatedConsole>()}, devices{std::make_unique<EmulatedDevices>()} {}
|
console{std::make_unique<EmulatedConsole>()}, devices{std::make_unique<EmulatedDevices>()} {}
|
||||||
|
|
||||||
HIDCore::~HIDCore() = default;
|
HIDCore::~HIDCore() = default;
|
||||||
@ -81,6 +92,65 @@ const EmulatedController* HIDCore::GetEmulatedController(NpadIdType npad_id_type
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SystemController* HIDCore::GetSystemController(NpadIdType npad_id_type) {
|
||||||
|
switch (npad_id_type) {
|
||||||
|
case NpadIdType::Player1:
|
||||||
|
return system_player_1.get();
|
||||||
|
case NpadIdType::Player2:
|
||||||
|
return system_player_2.get();
|
||||||
|
case NpadIdType::Player3:
|
||||||
|
return system_player_3.get();
|
||||||
|
case NpadIdType::Player4:
|
||||||
|
return system_player_4.get();
|
||||||
|
case NpadIdType::Player5:
|
||||||
|
return system_player_5.get();
|
||||||
|
case NpadIdType::Player6:
|
||||||
|
return system_player_6.get();
|
||||||
|
case NpadIdType::Player7:
|
||||||
|
return system_player_7.get();
|
||||||
|
case NpadIdType::Player8:
|
||||||
|
return system_player_8.get();
|
||||||
|
case NpadIdType::Other:
|
||||||
|
return system_other.get();
|
||||||
|
case NpadIdType::Handheld:
|
||||||
|
return system_handheld.get();
|
||||||
|
case NpadIdType::Invalid:
|
||||||
|
default:
|
||||||
|
ASSERT_MSG(false, "Invalid NpadIdType={}", npad_id_type);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SystemController* HIDCore::GetSystemController(NpadIdType npad_id_type) const {
|
||||||
|
switch (npad_id_type) {
|
||||||
|
case NpadIdType::Player1:
|
||||||
|
return system_player_1.get();
|
||||||
|
case NpadIdType::Player2:
|
||||||
|
return system_player_2.get();
|
||||||
|
case NpadIdType::Player3:
|
||||||
|
return system_player_3.get();
|
||||||
|
case NpadIdType::Player4:
|
||||||
|
return system_player_4.get();
|
||||||
|
case NpadIdType::Player5:
|
||||||
|
return system_player_5.get();
|
||||||
|
case NpadIdType::Player6:
|
||||||
|
return system_player_6.get();
|
||||||
|
case NpadIdType::Player7:
|
||||||
|
return system_player_7.get();
|
||||||
|
case NpadIdType::Player8:
|
||||||
|
return system_player_8.get();
|
||||||
|
case NpadIdType::Other:
|
||||||
|
return system_other.get();
|
||||||
|
case NpadIdType::Handheld:
|
||||||
|
return system_handheld.get();
|
||||||
|
case NpadIdType::Invalid:
|
||||||
|
default:
|
||||||
|
ASSERT_MSG(false, "Invalid NpadIdType={}", npad_id_type);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EmulatedConsole* HIDCore::GetEmulatedConsole() {
|
EmulatedConsole* HIDCore::GetEmulatedConsole() {
|
||||||
return console.get();
|
return console.get();
|
||||||
}
|
}
|
||||||
@ -107,16 +177,16 @@ const EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t inde
|
|||||||
|
|
||||||
void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) {
|
void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) {
|
||||||
supported_style_tag.raw = style_tag.raw;
|
supported_style_tag.raw = style_tag.raw;
|
||||||
player_1->SetSupportedNpadStyleTag(supported_style_tag);
|
system_player_1->SetSupportedNpadStyleTag(supported_style_tag);
|
||||||
player_2->SetSupportedNpadStyleTag(supported_style_tag);
|
system_player_2->SetSupportedNpadStyleTag(supported_style_tag);
|
||||||
player_3->SetSupportedNpadStyleTag(supported_style_tag);
|
system_player_3->SetSupportedNpadStyleTag(supported_style_tag);
|
||||||
player_4->SetSupportedNpadStyleTag(supported_style_tag);
|
system_player_4->SetSupportedNpadStyleTag(supported_style_tag);
|
||||||
player_5->SetSupportedNpadStyleTag(supported_style_tag);
|
system_player_5->SetSupportedNpadStyleTag(supported_style_tag);
|
||||||
player_6->SetSupportedNpadStyleTag(supported_style_tag);
|
system_player_6->SetSupportedNpadStyleTag(supported_style_tag);
|
||||||
player_7->SetSupportedNpadStyleTag(supported_style_tag);
|
system_player_7->SetSupportedNpadStyleTag(supported_style_tag);
|
||||||
player_8->SetSupportedNpadStyleTag(supported_style_tag);
|
system_player_8->SetSupportedNpadStyleTag(supported_style_tag);
|
||||||
other->SetSupportedNpadStyleTag(supported_style_tag);
|
system_other->SetSupportedNpadStyleTag(supported_style_tag);
|
||||||
handheld->SetSupportedNpadStyleTag(supported_style_tag);
|
system_handheld->SetSupportedNpadStyleTag(supported_style_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
NpadStyleTag HIDCore::GetSupportedStyleTag() const {
|
NpadStyleTag HIDCore::GetSupportedStyleTag() const {
|
||||||
@ -155,57 +225,57 @@ NpadIdType HIDCore::GetFirstDisconnectedNpadId() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HIDCore::EnableAllControllerConfiguration() {
|
void HIDCore::EnableAllControllerConfiguration() {
|
||||||
player_1->EnableConfiguration();
|
system_player_1->EnableConfiguration();
|
||||||
player_2->EnableConfiguration();
|
system_player_2->EnableConfiguration();
|
||||||
player_3->EnableConfiguration();
|
system_player_3->EnableConfiguration();
|
||||||
player_4->EnableConfiguration();
|
system_player_4->EnableConfiguration();
|
||||||
player_5->EnableConfiguration();
|
system_player_5->EnableConfiguration();
|
||||||
player_6->EnableConfiguration();
|
system_player_6->EnableConfiguration();
|
||||||
player_7->EnableConfiguration();
|
system_player_7->EnableConfiguration();
|
||||||
player_8->EnableConfiguration();
|
system_player_8->EnableConfiguration();
|
||||||
other->EnableConfiguration();
|
system_other->EnableConfiguration();
|
||||||
handheld->EnableConfiguration();
|
system_handheld->EnableConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDCore::DisableAllControllerConfiguration() {
|
void HIDCore::DisableAllControllerConfiguration() {
|
||||||
player_1->DisableConfiguration();
|
system_player_1->DisableConfiguration();
|
||||||
player_2->DisableConfiguration();
|
system_player_2->DisableConfiguration();
|
||||||
player_3->DisableConfiguration();
|
system_player_3->DisableConfiguration();
|
||||||
player_4->DisableConfiguration();
|
system_player_4->DisableConfiguration();
|
||||||
player_5->DisableConfiguration();
|
system_player_5->DisableConfiguration();
|
||||||
player_6->DisableConfiguration();
|
system_player_6->DisableConfiguration();
|
||||||
player_7->DisableConfiguration();
|
system_player_7->DisableConfiguration();
|
||||||
player_8->DisableConfiguration();
|
system_player_8->DisableConfiguration();
|
||||||
other->DisableConfiguration();
|
system_other->DisableConfiguration();
|
||||||
handheld->DisableConfiguration();
|
system_handheld->DisableConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDCore::ReloadInputDevices() {
|
void HIDCore::ReloadInputDevices() {
|
||||||
player_1->ReloadFromSettings();
|
system_player_1->ReloadFromSettings();
|
||||||
player_2->ReloadFromSettings();
|
system_player_2->ReloadFromSettings();
|
||||||
player_3->ReloadFromSettings();
|
system_player_3->ReloadFromSettings();
|
||||||
player_4->ReloadFromSettings();
|
system_player_4->ReloadFromSettings();
|
||||||
player_5->ReloadFromSettings();
|
system_player_5->ReloadFromSettings();
|
||||||
player_6->ReloadFromSettings();
|
system_player_6->ReloadFromSettings();
|
||||||
player_7->ReloadFromSettings();
|
system_player_7->ReloadFromSettings();
|
||||||
player_8->ReloadFromSettings();
|
system_player_8->ReloadFromSettings();
|
||||||
other->ReloadFromSettings();
|
system_other->ReloadFromSettings();
|
||||||
handheld->ReloadFromSettings();
|
system_handheld->ReloadFromSettings();
|
||||||
console->ReloadFromSettings();
|
console->ReloadFromSettings();
|
||||||
devices->ReloadFromSettings();
|
devices->ReloadFromSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDCore::UnloadInputDevices() {
|
void HIDCore::UnloadInputDevices() {
|
||||||
player_1->UnloadInput();
|
system_player_1->UnloadInput();
|
||||||
player_2->UnloadInput();
|
system_player_2->UnloadInput();
|
||||||
player_3->UnloadInput();
|
system_player_3->UnloadInput();
|
||||||
player_4->UnloadInput();
|
system_player_4->UnloadInput();
|
||||||
player_5->UnloadInput();
|
system_player_5->UnloadInput();
|
||||||
player_6->UnloadInput();
|
system_player_6->UnloadInput();
|
||||||
player_7->UnloadInput();
|
system_player_7->UnloadInput();
|
||||||
player_8->UnloadInput();
|
system_player_8->UnloadInput();
|
||||||
other->UnloadInput();
|
system_other->UnloadInput();
|
||||||
handheld->UnloadInput();
|
system_handheld->UnloadInput();
|
||||||
console->UnloadInput();
|
console->UnloadInput();
|
||||||
devices->UnloadInput();
|
devices->UnloadInput();
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ namespace Core::HID {
|
|||||||
class EmulatedConsole;
|
class EmulatedConsole;
|
||||||
class EmulatedController;
|
class EmulatedController;
|
||||||
class EmulatedDevices;
|
class EmulatedDevices;
|
||||||
|
class SystemController;
|
||||||
} // namespace Core::HID
|
} // namespace Core::HID
|
||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
@ -30,6 +31,12 @@ public:
|
|||||||
EmulatedController* GetEmulatedControllerByIndex(std::size_t index);
|
EmulatedController* GetEmulatedControllerByIndex(std::size_t index);
|
||||||
const EmulatedController* GetEmulatedControllerByIndex(std::size_t index) const;
|
const EmulatedController* GetEmulatedControllerByIndex(std::size_t index) const;
|
||||||
|
|
||||||
|
SystemController* GetSystemController(NpadIdType npad_id_type);
|
||||||
|
const SystemController* GetSystemController(NpadIdType npad_id_type) const;
|
||||||
|
|
||||||
|
SystemController* GetSystemControllerByIndex(std::size_t index);
|
||||||
|
const SystemController* GetSystemControllerByIndex(std::size_t index) const;
|
||||||
|
|
||||||
EmulatedConsole* GetEmulatedConsole();
|
EmulatedConsole* GetEmulatedConsole();
|
||||||
const EmulatedConsole* GetEmulatedConsole() const;
|
const EmulatedConsole* GetEmulatedConsole() const;
|
||||||
|
|
||||||
@ -76,6 +83,16 @@ private:
|
|||||||
std::unique_ptr<EmulatedController> handheld;
|
std::unique_ptr<EmulatedController> handheld;
|
||||||
std::unique_ptr<EmulatedConsole> console;
|
std::unique_ptr<EmulatedConsole> console;
|
||||||
std::unique_ptr<EmulatedDevices> devices;
|
std::unique_ptr<EmulatedDevices> devices;
|
||||||
|
std::unique_ptr<SystemController> system_player_1;
|
||||||
|
std::unique_ptr<SystemController> system_player_2;
|
||||||
|
std::unique_ptr<SystemController> system_player_3;
|
||||||
|
std::unique_ptr<SystemController> system_player_4;
|
||||||
|
std::unique_ptr<SystemController> system_player_5;
|
||||||
|
std::unique_ptr<SystemController> system_player_6;
|
||||||
|
std::unique_ptr<SystemController> system_player_7;
|
||||||
|
std::unique_ptr<SystemController> system_player_8;
|
||||||
|
std::unique_ptr<SystemController> system_other;
|
||||||
|
std::unique_ptr<SystemController> system_handheld;
|
||||||
NpadStyleTag supported_style_tag{NpadStyleSet::All};
|
NpadStyleTag supported_style_tag{NpadStyleSet::All};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
860
src/core/hid/system_controller.cpp
Normal file
860
src/core/hid/system_controller.cpp
Normal file
@ -0,0 +1,860 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <common/scope_exit.h>
|
||||||
|
|
||||||
|
#include "common/polyfill_ranges.h"
|
||||||
|
#include "common/thread.h"
|
||||||
|
#include "core/hid/system_controller.h"
|
||||||
|
#include "core/hid/input_converter.h"
|
||||||
|
|
||||||
|
namespace Core::HID {
|
||||||
|
constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
|
||||||
|
constexpr s32 HID_TRIGGER_MAX = 0x7fff;
|
||||||
|
|
||||||
|
SystemController::SystemController(NpadIdType npad_id_type_) : npad_id_type(npad_id_type_) {}
|
||||||
|
|
||||||
|
SystemController::~SystemController() = default;
|
||||||
|
|
||||||
|
NpadStyleIndex SystemController::MapSettingsTypeToNPad(Settings::ControllerType type) {
|
||||||
|
switch (type) {
|
||||||
|
case Settings::ControllerType::ProController:
|
||||||
|
return NpadStyleIndex::ProController;
|
||||||
|
case Settings::ControllerType::DualJoyconDetached:
|
||||||
|
return NpadStyleIndex::JoyconDual;
|
||||||
|
case Settings::ControllerType::LeftJoycon:
|
||||||
|
return NpadStyleIndex::JoyconLeft;
|
||||||
|
case Settings::ControllerType::RightJoycon:
|
||||||
|
return NpadStyleIndex::JoyconRight;
|
||||||
|
case Settings::ControllerType::Handheld:
|
||||||
|
return NpadStyleIndex::Handheld;
|
||||||
|
case Settings::ControllerType::GameCube:
|
||||||
|
return NpadStyleIndex::GameCube;
|
||||||
|
case Settings::ControllerType::Pokeball:
|
||||||
|
return NpadStyleIndex::Pokeball;
|
||||||
|
case Settings::ControllerType::NES:
|
||||||
|
return NpadStyleIndex::NES;
|
||||||
|
case Settings::ControllerType::SNES:
|
||||||
|
return NpadStyleIndex::SNES;
|
||||||
|
case Settings::ControllerType::N64:
|
||||||
|
return NpadStyleIndex::N64;
|
||||||
|
case Settings::ControllerType::SegaGenesis:
|
||||||
|
return NpadStyleIndex::SegaGenesis;
|
||||||
|
default:
|
||||||
|
return NpadStyleIndex::ProController;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::ControllerType SystemController::MapNPadToSettingsType(NpadStyleIndex type) {
|
||||||
|
switch (type) {
|
||||||
|
case NpadStyleIndex::ProController:
|
||||||
|
return Settings::ControllerType::ProController;
|
||||||
|
case NpadStyleIndex::JoyconDual:
|
||||||
|
return Settings::ControllerType::DualJoyconDetached;
|
||||||
|
case NpadStyleIndex::JoyconLeft:
|
||||||
|
return Settings::ControllerType::LeftJoycon;
|
||||||
|
case NpadStyleIndex::JoyconRight:
|
||||||
|
return Settings::ControllerType::RightJoycon;
|
||||||
|
case NpadStyleIndex::Handheld:
|
||||||
|
return Settings::ControllerType::Handheld;
|
||||||
|
case NpadStyleIndex::GameCube:
|
||||||
|
return Settings::ControllerType::GameCube;
|
||||||
|
case NpadStyleIndex::Pokeball:
|
||||||
|
return Settings::ControllerType::Pokeball;
|
||||||
|
case NpadStyleIndex::NES:
|
||||||
|
return Settings::ControllerType::NES;
|
||||||
|
case NpadStyleIndex::SNES:
|
||||||
|
return Settings::ControllerType::SNES;
|
||||||
|
case NpadStyleIndex::N64:
|
||||||
|
return Settings::ControllerType::N64;
|
||||||
|
case NpadStyleIndex::SegaGenesis:
|
||||||
|
return Settings::ControllerType::SegaGenesis;
|
||||||
|
default:
|
||||||
|
return Settings::ControllerType::ProController;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::ReloadFromSettings() {
|
||||||
|
const auto player_index = NpadIdTypeToIndex(npad_id_type);
|
||||||
|
const auto& player = Settings::values.players.GetValue()[player_index];
|
||||||
|
|
||||||
|
for (std::size_t index = 0; index < player.buttons.size(); ++index) {
|
||||||
|
button_params[index] = Common::ParamPackage(player.buttons[index]);
|
||||||
|
}
|
||||||
|
for (std::size_t index = 0; index < player.analogs.size(); ++index) {
|
||||||
|
stick_params[index] = Common::ParamPackage(player.analogs[index]);
|
||||||
|
}
|
||||||
|
for (std::size_t index = 0; index < player.motions.size(); ++index) {
|
||||||
|
motion_params[index] = Common::ParamPackage(player.motions[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ring_params[0] = Common::ParamPackage(Settings::values.ringcon_analogs);
|
||||||
|
|
||||||
|
// Other or debug controller should always be a pro controller
|
||||||
|
if (npad_id_type != NpadIdType::Other) {
|
||||||
|
SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type));
|
||||||
|
original_npad_type = npad_type;
|
||||||
|
} else {
|
||||||
|
SetNpadStyleIndex(NpadStyleIndex::ProController);
|
||||||
|
original_npad_type = npad_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Disconnect();
|
||||||
|
if (player.connected) {
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReloadInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::LoadDevices() {
|
||||||
|
// TODO(german77): Use more buttons to detect the correct device
|
||||||
|
const auto left_joycon = button_params[Settings::NativeButton::DRight];
|
||||||
|
const auto right_joycon = button_params[Settings::NativeButton::A];
|
||||||
|
|
||||||
|
// Triggers for GC controllers
|
||||||
|
trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL];
|
||||||
|
trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR];
|
||||||
|
|
||||||
|
std::ranges::transform(button_params, button_devices.begin(), Common::Input::CreateInputDevice);
|
||||||
|
std::ranges::transform(stick_params, stick_devices.begin(), Common::Input::CreateInputDevice);
|
||||||
|
std::ranges::transform(motion_params, motion_devices.begin(), Common::Input::CreateInputDevice);
|
||||||
|
std::ranges::transform(trigger_params, trigger_devices.begin(),
|
||||||
|
Common::Input::CreateInputDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::ReloadInput() {
|
||||||
|
// If you load any device here add the equivalent to the UnloadInput() function
|
||||||
|
LoadDevices();
|
||||||
|
for (std::size_t index = 0; index < button_devices.size(); ++index) {
|
||||||
|
if (!button_devices[index]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto uuid = Common::UUID{button_params[index].Get("guid", "")};
|
||||||
|
button_devices[index]->SetCallback({
|
||||||
|
.on_change =
|
||||||
|
[this, index, uuid](const Common::Input::CallbackStatus& callback) {
|
||||||
|
SetButton(callback, index, uuid);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
button_devices[index]->ForceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t index = 0; index < stick_devices.size(); ++index) {
|
||||||
|
if (!stick_devices[index]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto uuid = Common::UUID{stick_params[index].Get("guid", "")};
|
||||||
|
stick_devices[index]->SetCallback({
|
||||||
|
.on_change =
|
||||||
|
[this, index, uuid](const Common::Input::CallbackStatus& callback) {
|
||||||
|
SetStick(callback, index, uuid);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
stick_devices[index]->ForceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t index = 0; index < trigger_devices.size(); ++index) {
|
||||||
|
if (!trigger_devices[index]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto uuid = Common::UUID{trigger_params[index].Get("guid", "")};
|
||||||
|
trigger_devices[index]->SetCallback({
|
||||||
|
.on_change =
|
||||||
|
[this, index, uuid](const Common::Input::CallbackStatus& callback) {
|
||||||
|
SetTrigger(callback, index, uuid);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
trigger_devices[index]->ForceUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::UnloadInput() {
|
||||||
|
for (auto& button : button_devices) {
|
||||||
|
button.reset();
|
||||||
|
}
|
||||||
|
for (auto& stick : stick_devices) {
|
||||||
|
stick.reset();
|
||||||
|
}
|
||||||
|
for (auto& motion : motion_devices) {
|
||||||
|
motion.reset();
|
||||||
|
}
|
||||||
|
for (auto& trigger : trigger_devices) {
|
||||||
|
trigger.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::EnableConfiguration() {
|
||||||
|
is_configuring = true;
|
||||||
|
tmp_is_connected = is_connected;
|
||||||
|
tmp_npad_type = npad_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::DisableConfiguration() {
|
||||||
|
is_configuring = false;
|
||||||
|
|
||||||
|
// Apply temporary npad type to the real controller
|
||||||
|
if (tmp_npad_type != npad_type) {
|
||||||
|
if (is_connected) {
|
||||||
|
Disconnect();
|
||||||
|
}
|
||||||
|
SetNpadStyleIndex(tmp_npad_type);
|
||||||
|
original_npad_type = tmp_npad_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply temporary connected status to the real controller
|
||||||
|
if (tmp_is_connected != is_connected) {
|
||||||
|
if (tmp_is_connected) {
|
||||||
|
Connect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::EnableSystemButtons() {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
system_buttons_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::DisableSystemButtons() {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
system_buttons_enabled = false;
|
||||||
|
controller.home_button_state.raw = 0;
|
||||||
|
controller.capture_button_state.raw = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::ResetSystemButtons() {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
controller.home_button_state.home.Assign(false);
|
||||||
|
controller.capture_button_state.capture.Assign(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SystemController::IsConfiguring() const {
|
||||||
|
return is_configuring;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::SaveCurrentConfig() {
|
||||||
|
const auto player_index = NpadIdTypeToIndex(npad_id_type);
|
||||||
|
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) {
|
||||||
|
player.buttons[index] = button_params[index].Serialize();
|
||||||
|
}
|
||||||
|
for (std::size_t index = 0; index < player.analogs.size(); ++index) {
|
||||||
|
player.analogs[index] = stick_params[index].Serialize();
|
||||||
|
}
|
||||||
|
for (std::size_t index = 0; index < player.motions.size(); ++index) {
|
||||||
|
player.motions[index] = motion_params[index].Serialize();
|
||||||
|
}
|
||||||
|
if (npad_id_type == NpadIdType::Player1) {
|
||||||
|
Settings::values.ringcon_analogs = ring_params[0].Serialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::RestoreConfig() {
|
||||||
|
if (!is_configuring) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ReloadFromSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Common::ParamPackage> SystemController::GetMappedDevices() const {
|
||||||
|
std::vector<Common::ParamPackage> devices;
|
||||||
|
for (const auto& param : button_params) {
|
||||||
|
if (!param.Has("engine")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto devices_it = std::find_if(
|
||||||
|
devices.begin(), devices.end(), [¶m](const Common::ParamPackage& param_) {
|
||||||
|
return param.Get("engine", "") == param_.Get("engine", "") &&
|
||||||
|
param.Get("guid", "") == param_.Get("guid", "") &&
|
||||||
|
param.Get("port", 0) == param_.Get("port", 0) &&
|
||||||
|
param.Get("pad", 0) == param_.Get("pad", 0);
|
||||||
|
});
|
||||||
|
if (devices_it != devices.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& device = devices.emplace_back();
|
||||||
|
device.Set("engine", param.Get("engine", ""));
|
||||||
|
device.Set("guid", param.Get("guid", ""));
|
||||||
|
device.Set("port", param.Get("port", 0));
|
||||||
|
device.Set("pad", param.Get("pad", 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& param : stick_params) {
|
||||||
|
if (!param.Has("engine")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (param.Get("engine", "") == "analog_from_button") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto devices_it = std::find_if(
|
||||||
|
devices.begin(), devices.end(), [¶m](const Common::ParamPackage& param_) {
|
||||||
|
return param.Get("engine", "") == param_.Get("engine", "") &&
|
||||||
|
param.Get("guid", "") == param_.Get("guid", "") &&
|
||||||
|
param.Get("port", 0) == param_.Get("port", 0) &&
|
||||||
|
param.Get("pad", 0) == param_.Get("pad", 0);
|
||||||
|
});
|
||||||
|
if (devices_it != devices.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& device = devices.emplace_back();
|
||||||
|
device.Set("engine", param.Get("engine", ""));
|
||||||
|
device.Set("guid", param.Get("guid", ""));
|
||||||
|
device.Set("port", param.Get("port", 0));
|
||||||
|
device.Set("pad", param.Get("pad", 0));
|
||||||
|
}
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::ParamPackage SystemController::GetButtonParam(std::size_t index) const {
|
||||||
|
if (index >= button_params.size()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return button_params[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::ParamPackage SystemController::GetStickParam(std::size_t index) const {
|
||||||
|
if (index >= stick_params.size()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return stick_params[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::ParamPackage SystemController::GetMotionParam(std::size_t index) const {
|
||||||
|
if (index >= motion_params.size()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return motion_params[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::SetButtonParam(std::size_t index, Common::ParamPackage param) {
|
||||||
|
if (index >= button_params.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
button_params[index] = std::move(param);
|
||||||
|
ReloadInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::SetStickParam(std::size_t index, Common::ParamPackage param) {
|
||||||
|
if (index >= stick_params.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stick_params[index] = std::move(param);
|
||||||
|
ReloadInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::SetMotionParam(std::size_t index, Common::ParamPackage param) {
|
||||||
|
if (index >= motion_params.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
motion_params[index] = std::move(param);
|
||||||
|
ReloadInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::SetButton(const Common::Input::CallbackStatus& callback, std::size_t index,
|
||||||
|
Common::UUID uuid) {
|
||||||
|
if (index >= controller.button_values.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::unique_lock lock{mutex};
|
||||||
|
bool value_changed = false;
|
||||||
|
const auto new_status = TransformToButton(callback);
|
||||||
|
auto& current_status = controller.button_values[index];
|
||||||
|
|
||||||
|
// Only read button values that have the same uuid or are pressed once
|
||||||
|
if (current_status.uuid != uuid) {
|
||||||
|
if (!new_status.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current_status.toggle = new_status.toggle;
|
||||||
|
current_status.turbo = new_status.turbo;
|
||||||
|
current_status.uuid = uuid;
|
||||||
|
|
||||||
|
// Update button status with current
|
||||||
|
if (!current_status.toggle) {
|
||||||
|
current_status.locked = false;
|
||||||
|
if (current_status.value != new_status.value) {
|
||||||
|
current_status.value = new_status.value;
|
||||||
|
value_changed = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Toggle button and lock status
|
||||||
|
if (new_status.value && !current_status.locked) {
|
||||||
|
current_status.locked = true;
|
||||||
|
current_status.value = !current_status.value;
|
||||||
|
value_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlock button ready for next press
|
||||||
|
if (!new_status.value && current_status.locked) {
|
||||||
|
current_status.locked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value_changed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_configuring) {
|
||||||
|
controller.npad_button_state.raw = NpadButton::None;
|
||||||
|
controller.home_button_state.raw = 0;
|
||||||
|
controller.capture_button_state.raw = 0;
|
||||||
|
lock.unlock();
|
||||||
|
TriggerOnChange(ControllerTriggerType::Button, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GC controllers have triggers not buttons
|
||||||
|
if (npad_type == NpadStyleIndex::GameCube) {
|
||||||
|
if (index == Settings::NativeButton::ZR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (index == Settings::NativeButton::ZL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case Settings::NativeButton::A:
|
||||||
|
controller.npad_button_state.a.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::B:
|
||||||
|
controller.npad_button_state.b.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::X:
|
||||||
|
controller.npad_button_state.x.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::Y:
|
||||||
|
controller.npad_button_state.y.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::LStick:
|
||||||
|
controller.npad_button_state.stick_l.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::RStick:
|
||||||
|
controller.npad_button_state.stick_r.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::L:
|
||||||
|
controller.npad_button_state.l.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::R:
|
||||||
|
controller.npad_button_state.r.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::ZL:
|
||||||
|
controller.npad_button_state.zl.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::ZR:
|
||||||
|
controller.npad_button_state.zr.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::Plus:
|
||||||
|
controller.npad_button_state.plus.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::Minus:
|
||||||
|
controller.npad_button_state.minus.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::DLeft:
|
||||||
|
controller.npad_button_state.left.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::DUp:
|
||||||
|
controller.npad_button_state.up.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::DRight:
|
||||||
|
controller.npad_button_state.right.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::DDown:
|
||||||
|
controller.npad_button_state.down.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::SL:
|
||||||
|
controller.npad_button_state.left_sl.Assign(current_status.value);
|
||||||
|
controller.npad_button_state.right_sl.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::SR:
|
||||||
|
controller.npad_button_state.left_sr.Assign(current_status.value);
|
||||||
|
controller.npad_button_state.right_sr.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::Home:
|
||||||
|
if (!system_buttons_enabled) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
controller.home_button_state.home.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeButton::Screenshot:
|
||||||
|
if (!system_buttons_enabled) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
controller.capture_button_state.capture.Assign(current_status.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
if (!is_connected) {
|
||||||
|
if (npad_id_type == NpadIdType::Player1 && npad_type != NpadStyleIndex::Handheld) {
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
if (npad_id_type == NpadIdType::Handheld && npad_type == NpadStyleIndex::Handheld) {
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TriggerOnChange(ControllerTriggerType::Button, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::SetStick(const Common::Input::CallbackStatus& callback, std::size_t index,
|
||||||
|
Common::UUID uuid) {
|
||||||
|
if (index >= controller.stick_values.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto trigger_guard =
|
||||||
|
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); });
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
const auto stick_value = TransformToStick(callback);
|
||||||
|
|
||||||
|
// Only read stick values that have the same uuid or are over the threshold to avoid flapping
|
||||||
|
if (controller.stick_values[index].uuid != uuid) {
|
||||||
|
if (!stick_value.down && !stick_value.up && !stick_value.left &&
|
||||||
|
!stick_value.right) {
|
||||||
|
trigger_guard.Cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.stick_values[index] = stick_value;
|
||||||
|
controller.stick_values[index].uuid = uuid;
|
||||||
|
|
||||||
|
if (is_configuring) {
|
||||||
|
controller.analog_stick_state.left = {};
|
||||||
|
controller.analog_stick_state.right = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AnalogStickState stick{
|
||||||
|
.x = static_cast<s32>(controller.stick_values[index].x.value * HID_JOYSTICK_MAX),
|
||||||
|
.y = static_cast<s32>(controller.stick_values[index].y.value * HID_JOYSTICK_MAX),
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case Settings::NativeAnalog::LStick:
|
||||||
|
controller.analog_stick_state.left = stick;
|
||||||
|
controller.npad_button_state.stick_l_left.Assign(controller.stick_values[index].left);
|
||||||
|
controller.npad_button_state.stick_l_up.Assign(controller.stick_values[index].up);
|
||||||
|
controller.npad_button_state.stick_l_right.Assign(controller.stick_values[index].right);
|
||||||
|
controller.npad_button_state.stick_l_down.Assign(controller.stick_values[index].down);
|
||||||
|
break;
|
||||||
|
case Settings::NativeAnalog::RStick:
|
||||||
|
controller.analog_stick_state.right = stick;
|
||||||
|
controller.npad_button_state.stick_r_left.Assign(controller.stick_values[index].left);
|
||||||
|
controller.npad_button_state.stick_r_up.Assign(controller.stick_values[index].up);
|
||||||
|
controller.npad_button_state.stick_r_right.Assign(controller.stick_values[index].right);
|
||||||
|
controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::SetTrigger(const Common::Input::CallbackStatus& callback,
|
||||||
|
std::size_t index, Common::UUID uuid) {
|
||||||
|
if (index >= controller.trigger_values.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto trigger_guard =
|
||||||
|
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); });
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
const auto trigger_value = TransformToTrigger(callback);
|
||||||
|
|
||||||
|
// Only read trigger values that have the same uuid or are pressed once
|
||||||
|
if (controller.trigger_values[index].uuid != uuid) {
|
||||||
|
if (!trigger_value.pressed.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.trigger_values[index] = trigger_value;
|
||||||
|
controller.trigger_values[index].uuid = uuid;
|
||||||
|
|
||||||
|
if (is_configuring) {
|
||||||
|
controller.gc_trigger_state.left = 0;
|
||||||
|
controller.gc_trigger_state.right = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only GC controllers have analog triggers
|
||||||
|
if (npad_type != NpadStyleIndex::GameCube) {
|
||||||
|
trigger_guard.Cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& trigger = controller.trigger_values[index];
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case Settings::NativeTrigger::LTrigger:
|
||||||
|
controller.gc_trigger_state.left = static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX);
|
||||||
|
controller.npad_button_state.zl.Assign(trigger.pressed.value);
|
||||||
|
break;
|
||||||
|
case Settings::NativeTrigger::RTrigger:
|
||||||
|
controller.gc_trigger_state.right =
|
||||||
|
static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX);
|
||||||
|
controller.npad_button_state.zr.Assign(trigger.pressed.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) {
|
||||||
|
supported_style_tag = supported_styles;
|
||||||
|
if (!is_connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to reconnect with the original type
|
||||||
|
if (npad_type != original_npad_type) {
|
||||||
|
Disconnect();
|
||||||
|
const auto current_npad_type = npad_type;
|
||||||
|
SetNpadStyleIndex(original_npad_type);
|
||||||
|
if (IsControllerSupported()) {
|
||||||
|
Connect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SetNpadStyleIndex(current_npad_type);
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsControllerSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Disconnect();
|
||||||
|
|
||||||
|
// Fallback Fullkey controllers to Pro controllers
|
||||||
|
if (IsControllerFullkey() && supported_style_tag.fullkey) {
|
||||||
|
LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type);
|
||||||
|
SetNpadStyleIndex(NpadStyleIndex::ProController);
|
||||||
|
Connect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback Dual joycon controllers to Pro controllers
|
||||||
|
if (npad_type == NpadStyleIndex::JoyconDual && supported_style_tag.fullkey) {
|
||||||
|
LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type);
|
||||||
|
SetNpadStyleIndex(NpadStyleIndex::ProController);
|
||||||
|
Connect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback Pro controllers to Dual joycon
|
||||||
|
if (npad_type == NpadStyleIndex::ProController && supported_style_tag.joycon_dual) {
|
||||||
|
LOG_WARNING(Service_HID, "Reconnecting controller type {} as Dual Joycons", npad_type);
|
||||||
|
SetNpadStyleIndex(NpadStyleIndex::JoyconDual);
|
||||||
|
Connect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_ERROR(Service_HID, "Controller type {} is not supported. Disconnecting controller",
|
||||||
|
npad_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SystemController::IsControllerFullkey(bool use_temporary_value) const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
|
||||||
|
switch (type) {
|
||||||
|
case NpadStyleIndex::ProController:
|
||||||
|
case NpadStyleIndex::GameCube:
|
||||||
|
case NpadStyleIndex::NES:
|
||||||
|
case NpadStyleIndex::SNES:
|
||||||
|
case NpadStyleIndex::N64:
|
||||||
|
case NpadStyleIndex::SegaGenesis:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SystemController::IsControllerSupported(bool use_temporary_value) const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
|
||||||
|
switch (type) {
|
||||||
|
case NpadStyleIndex::ProController:
|
||||||
|
return supported_style_tag.fullkey.As<bool>();
|
||||||
|
case NpadStyleIndex::Handheld:
|
||||||
|
return supported_style_tag.handheld.As<bool>();
|
||||||
|
case NpadStyleIndex::JoyconDual:
|
||||||
|
return supported_style_tag.joycon_dual.As<bool>();
|
||||||
|
case NpadStyleIndex::JoyconLeft:
|
||||||
|
return supported_style_tag.joycon_left.As<bool>();
|
||||||
|
case NpadStyleIndex::JoyconRight:
|
||||||
|
return supported_style_tag.joycon_right.As<bool>();
|
||||||
|
case NpadStyleIndex::GameCube:
|
||||||
|
return supported_style_tag.gamecube.As<bool>();
|
||||||
|
case NpadStyleIndex::Pokeball:
|
||||||
|
return supported_style_tag.palma.As<bool>();
|
||||||
|
case NpadStyleIndex::NES:
|
||||||
|
return supported_style_tag.lark.As<bool>();
|
||||||
|
case NpadStyleIndex::SNES:
|
||||||
|
return supported_style_tag.lucia.As<bool>();
|
||||||
|
case NpadStyleIndex::N64:
|
||||||
|
return supported_style_tag.lagoon.As<bool>();
|
||||||
|
case NpadStyleIndex::SegaGenesis:
|
||||||
|
return supported_style_tag.lager.As<bool>();
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::Connect(bool use_temporary_value) {
|
||||||
|
if (!IsControllerSupported(use_temporary_value)) {
|
||||||
|
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
|
||||||
|
LOG_ERROR(Service_HID, "Controller type {} is not supported", type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto trigger_guard =
|
||||||
|
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); });
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
if (is_configuring) {
|
||||||
|
tmp_is_connected = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_connected) {
|
||||||
|
trigger_guard.Cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
is_connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::Disconnect() {
|
||||||
|
auto trigger_guard =
|
||||||
|
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); });
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
if (is_configuring) {
|
||||||
|
tmp_is_connected = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_connected) {
|
||||||
|
trigger_guard.Cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
is_connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SystemController::IsConnected(bool get_temporary_value) const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
if (get_temporary_value && is_configuring) {
|
||||||
|
return tmp_is_connected;
|
||||||
|
}
|
||||||
|
return is_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
NpadIdType SystemController::GetNpadIdType() const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
return npad_id_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
NpadStyleIndex SystemController::GetNpadStyleIndex(bool get_temporary_value) const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
if (get_temporary_value && is_configuring) {
|
||||||
|
return tmp_npad_type;
|
||||||
|
}
|
||||||
|
return npad_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
|
||||||
|
auto trigger_guard =
|
||||||
|
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type, !is_configuring); });
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
|
if (is_configuring) {
|
||||||
|
if (tmp_npad_type == npad_type_) {
|
||||||
|
trigger_guard.Cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tmp_npad_type = npad_type_;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npad_type == npad_type_) {
|
||||||
|
trigger_guard.Cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (is_connected) {
|
||||||
|
LOG_WARNING(Service_HID, "Controller {} type changed while it's connected",
|
||||||
|
NpadIdTypeToIndex(npad_id_type));
|
||||||
|
}
|
||||||
|
npad_type = npad_type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonValues SystemController::GetButtonsValues() const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
return controller.button_values;
|
||||||
|
}
|
||||||
|
|
||||||
|
SticksValues SystemController::GetSticksValues() const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
return controller.stick_values;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerValues SystemController::GetTriggersValues() const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
return controller.trigger_values;
|
||||||
|
}
|
||||||
|
|
||||||
|
HomeButtonState SystemController::GetHomeButtons() const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
return controller.home_button_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
CaptureButtonState SystemController::GetCaptureButtons() const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
return controller.capture_button_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
NpadButtonState SystemController::GetNpadButtons() const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
return controller.npad_button_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalogSticks SystemController::GetSticks() const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
return controller.analog_stick_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
NpadGcTriggerState SystemController::GetTriggers() const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
return controller.gc_trigger_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) {
|
||||||
|
std::scoped_lock lock{callback_mutex};
|
||||||
|
for (const auto& poller_pair : callback_list) {
|
||||||
|
const ControllerUpdateCallback& poller = poller_pair.second;
|
||||||
|
if (!is_npad_service_update && poller.is_npad_service) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (poller.on_change) {
|
||||||
|
poller.on_change(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SystemController::SetCallback(ControllerUpdateCallback update_callback) {
|
||||||
|
std::scoped_lock lock{callback_mutex};
|
||||||
|
callback_list.insert_or_assign(last_callback_key, std::move(update_callback));
|
||||||
|
return last_callback_key++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemController::DeleteCallback(int key) {
|
||||||
|
std::scoped_lock lock{callback_mutex};
|
||||||
|
const auto& iterator = callback_list.find(key);
|
||||||
|
if (iterator == callback_list.end()) {
|
||||||
|
LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback_list.erase(iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core::HID
|
330
src/core/hid/system_controller.h
Normal file
330
src/core/hid/system_controller.h
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "common/input.h"
|
||||||
|
#include "common/param_package.h"
|
||||||
|
#include "common/settings.h"
|
||||||
|
#include "common/vector_math.h"
|
||||||
|
#include "core/hid/hid_types.h"
|
||||||
|
#include "core/hid/irs_types.h"
|
||||||
|
#include "core/hid/motion_input.h"
|
||||||
|
|
||||||
|
namespace Core::HID {
|
||||||
|
const std::size_t max_emulated_controllers = 2;
|
||||||
|
const std::size_t output_devices_size = 4;
|
||||||
|
struct ControllerMotionInfo {
|
||||||
|
Common::Input::MotionStatus raw_status{};
|
||||||
|
MotionInput emulated{};
|
||||||
|
};
|
||||||
|
|
||||||
|
using ButtonDevices =
|
||||||
|
std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeButton::NumButtons>;
|
||||||
|
using StickDevices =
|
||||||
|
std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeAnalog::NumAnalogs>;
|
||||||
|
using ControllerMotionDevices =
|
||||||
|
std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeMotion::NumMotions>;
|
||||||
|
using TriggerDevices =
|
||||||
|
std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
|
||||||
|
|
||||||
|
using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
|
||||||
|
using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
|
||||||
|
using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>;
|
||||||
|
using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>;
|
||||||
|
using RingAnalogParams = std::array<Common::ParamPackage, max_emulated_controllers>;
|
||||||
|
|
||||||
|
using ButtonValues = std::array<Common::Input::ButtonStatus, Settings::NativeButton::NumButtons>;
|
||||||
|
using SticksValues = std::array<Common::Input::StickStatus, Settings::NativeAnalog::NumAnalogs>;
|
||||||
|
using TriggerValues =
|
||||||
|
std::array<Common::Input::TriggerStatus, Settings::NativeTrigger::NumTriggers>;
|
||||||
|
|
||||||
|
struct AnalogSticks {
|
||||||
|
AnalogStickState left{};
|
||||||
|
AnalogStickState right{};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum EmulatedDeviceIndex : u8 {
|
||||||
|
LeftIndex,
|
||||||
|
RightIndex,
|
||||||
|
DualIndex,
|
||||||
|
AllDevices,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ControllerStatus {
|
||||||
|
// Data from input_common
|
||||||
|
ButtonValues button_values{};
|
||||||
|
SticksValues stick_values{};
|
||||||
|
TriggerValues trigger_values{};
|
||||||
|
|
||||||
|
// Data for HID services
|
||||||
|
HomeButtonState home_button_state{};
|
||||||
|
CaptureButtonState capture_button_state{};
|
||||||
|
NpadButtonState npad_button_state{};
|
||||||
|
AnalogSticks analog_stick_state{};
|
||||||
|
NpadGcTriggerState gc_trigger_state{};
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ControllerTriggerType {
|
||||||
|
Button,
|
||||||
|
Stick,
|
||||||
|
Trigger,
|
||||||
|
Connected,
|
||||||
|
Disconnected,
|
||||||
|
Type,
|
||||||
|
All,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ControllerUpdateCallback {
|
||||||
|
std::function<void(ControllerTriggerType)> on_change;
|
||||||
|
bool is_npad_service;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SystemController {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Contains all input data (buttons, joysticks, vibration, and motion) within this controller.
|
||||||
|
* @param npad_id_type npad id type for this specific controller
|
||||||
|
*/
|
||||||
|
explicit SystemController(NpadIdType npad_id_type_);
|
||||||
|
~SystemController();
|
||||||
|
|
||||||
|
YUZU_NON_COPYABLE(SystemController);
|
||||||
|
YUZU_NON_MOVEABLE(SystemController);
|
||||||
|
|
||||||
|
/// Converts the controller type from settings to npad type
|
||||||
|
static NpadStyleIndex MapSettingsTypeToNPad(Settings::ControllerType type);
|
||||||
|
|
||||||
|
/// Converts npad type to the equivalent of controller type from settings
|
||||||
|
static Settings::ControllerType MapNPadToSettingsType(NpadStyleIndex type);
|
||||||
|
|
||||||
|
/// Gets the NpadIdType for this controller
|
||||||
|
NpadIdType GetNpadIdType() const;
|
||||||
|
|
||||||
|
/// Sets the NpadStyleIndex for this controller
|
||||||
|
void SetNpadStyleIndex(NpadStyleIndex npad_type_);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the NpadStyleIndex for this controller
|
||||||
|
* @param get_temporary_value If true tmp_npad_type will be returned
|
||||||
|
* @return NpadStyleIndex set on the controller
|
||||||
|
*/
|
||||||
|
NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the supported controller types. Disconnects the controller if current type is not
|
||||||
|
* supported
|
||||||
|
* @param supported_styles bitflag with supported types
|
||||||
|
*/
|
||||||
|
void SetSupportedNpadStyleTag(NpadStyleTag supported_styles);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the connected status to true
|
||||||
|
* @param use_temporary_value If true tmp_npad_type will be used
|
||||||
|
*/
|
||||||
|
void Connect(bool use_temporary_value = false);
|
||||||
|
|
||||||
|
/// Sets the connected status to false
|
||||||
|
void Disconnect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the emulated connected
|
||||||
|
* @param get_temporary_value If true tmp_is_connected will be returned
|
||||||
|
* @return true if the controller has the connected status
|
||||||
|
*/
|
||||||
|
bool IsConnected(bool get_temporary_value = false) const;
|
||||||
|
|
||||||
|
/// Removes all callbacks created from input devices
|
||||||
|
void UnloadInput();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the emulated controller into configuring mode
|
||||||
|
* This prevents the modification of the HID state of the emulated controller by input commands
|
||||||
|
*/
|
||||||
|
void EnableConfiguration();
|
||||||
|
|
||||||
|
/// Returns the emulated controller into normal mode, allowing the modification of the HID state
|
||||||
|
void DisableConfiguration();
|
||||||
|
|
||||||
|
/// Enables Home and Screenshot buttons
|
||||||
|
void EnableSystemButtons();
|
||||||
|
|
||||||
|
/// Disables Home and Screenshot buttons
|
||||||
|
void DisableSystemButtons();
|
||||||
|
|
||||||
|
/// Sets Home and Screenshot buttons to false
|
||||||
|
void ResetSystemButtons();
|
||||||
|
|
||||||
|
/// Returns true if the emulated controller is in configuring mode
|
||||||
|
bool IsConfiguring() const;
|
||||||
|
|
||||||
|
/// Reload all input devices
|
||||||
|
void ReloadInput();
|
||||||
|
|
||||||
|
/// Overrides current mapped devices with the stored configuration and reloads all input devices
|
||||||
|
void ReloadFromSettings();
|
||||||
|
|
||||||
|
/// Saves the current mapped configuration
|
||||||
|
void SaveCurrentConfig();
|
||||||
|
|
||||||
|
/// Reverts any mapped changes made that weren't saved
|
||||||
|
void RestoreConfig();
|
||||||
|
|
||||||
|
/// Returns a vector of mapped devices from the mapped button and stick parameters
|
||||||
|
std::vector<Common::ParamPackage> GetMappedDevices() const;
|
||||||
|
|
||||||
|
// Returns the current mapped button device
|
||||||
|
Common::ParamPackage GetButtonParam(std::size_t index) const;
|
||||||
|
|
||||||
|
// Returns the current mapped stick device
|
||||||
|
Common::ParamPackage GetStickParam(std::size_t index) const;
|
||||||
|
|
||||||
|
// Returns the current mapped motion device
|
||||||
|
Common::ParamPackage GetMotionParam(std::size_t index) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the current mapped button device
|
||||||
|
* @param param ParamPackage with controller data to be mapped
|
||||||
|
*/
|
||||||
|
void SetButtonParam(std::size_t index, Common::ParamPackage param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the current mapped stick device
|
||||||
|
* @param param ParamPackage with controller data to be mapped
|
||||||
|
*/
|
||||||
|
void SetStickParam(std::size_t index, Common::ParamPackage param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the current mapped motion device
|
||||||
|
* @param param ParamPackage with controller data to be mapped
|
||||||
|
*/
|
||||||
|
void SetMotionParam(std::size_t index, Common::ParamPackage param);
|
||||||
|
|
||||||
|
/// Returns the latest button status from the controller with parameters
|
||||||
|
ButtonValues GetButtonsValues() const;
|
||||||
|
|
||||||
|
/// Returns the latest analog stick status from the controller with parameters
|
||||||
|
SticksValues GetSticksValues() const;
|
||||||
|
|
||||||
|
/// Returns the latest trigger status from the controller with parameters
|
||||||
|
TriggerValues GetTriggersValues() const;
|
||||||
|
|
||||||
|
/// Returns the latest status of button input for the hid::HomeButton service
|
||||||
|
HomeButtonState GetHomeButtons() const;
|
||||||
|
|
||||||
|
/// Returns the latest status of button input for the hid::CaptureButton service
|
||||||
|
CaptureButtonState GetCaptureButtons() const;
|
||||||
|
|
||||||
|
/// Returns the latest status of button input for the hid::Npad service
|
||||||
|
NpadButtonState GetNpadButtons() const;
|
||||||
|
|
||||||
|
/// Returns the latest status of stick input from the mouse
|
||||||
|
AnalogSticks GetSticks() const;
|
||||||
|
|
||||||
|
/// Returns the latest status of trigger input from the mouse
|
||||||
|
NpadGcTriggerState GetTriggers() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a callback to the list of events
|
||||||
|
* @param update_callback A ConsoleUpdateCallback that will be triggered
|
||||||
|
* @return an unique key corresponding to the callback index in the list
|
||||||
|
*/
|
||||||
|
int SetCallback(ControllerUpdateCallback update_callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a callback from the list stopping any future events to this object
|
||||||
|
* @param key Key corresponding to the callback index in the list
|
||||||
|
*/
|
||||||
|
void DeleteCallback(int key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// creates input devices from params
|
||||||
|
void LoadDevices();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param use_temporary_value If true tmp_npad_type will be used
|
||||||
|
* @return true if the controller style is fullkey
|
||||||
|
*/
|
||||||
|
bool IsControllerFullkey(bool use_temporary_value = false) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the current controller type against the supported_style_tag
|
||||||
|
* @param use_temporary_value If true tmp_npad_type will be used
|
||||||
|
* @return true if the controller is supported
|
||||||
|
*/
|
||||||
|
bool IsControllerSupported(bool use_temporary_value = false) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the button status of the controller
|
||||||
|
* @param callback A CallbackStatus containing the button status
|
||||||
|
* @param index Button ID of the to be updated
|
||||||
|
*/
|
||||||
|
void SetButton(const Common::Input::CallbackStatus& callback, std::size_t index,
|
||||||
|
Common::UUID uuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the analog stick status of the controller
|
||||||
|
* @param callback A CallbackStatus containing the analog stick status
|
||||||
|
* @param index stick ID of the to be updated
|
||||||
|
*/
|
||||||
|
void SetStick(const Common::Input::CallbackStatus& callback, std::size_t index,
|
||||||
|
Common::UUID uuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the trigger status of the controller
|
||||||
|
* @param callback A CallbackStatus containing the trigger status
|
||||||
|
* @param index trigger ID of the to be updated
|
||||||
|
*/
|
||||||
|
void SetTrigger(const Common::Input::CallbackStatus& callback, std::size_t index,
|
||||||
|
Common::UUID uuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a callback that something has changed on the controller status
|
||||||
|
* @param type Input type of the event to trigger
|
||||||
|
* @param is_service_update indicates if this event should only be sent to HID services
|
||||||
|
*/
|
||||||
|
void TriggerOnChange(ControllerTriggerType type, bool is_service_update);
|
||||||
|
|
||||||
|
const NpadIdType npad_id_type;
|
||||||
|
NpadStyleIndex npad_type{NpadStyleIndex::None};
|
||||||
|
NpadStyleIndex original_npad_type{NpadStyleIndex::None};
|
||||||
|
NpadStyleTag supported_style_tag{NpadStyleSet::All};
|
||||||
|
bool is_connected{false};
|
||||||
|
bool is_configuring{false};
|
||||||
|
bool system_buttons_enabled{true};
|
||||||
|
f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard};
|
||||||
|
|
||||||
|
// Temporary values to avoid doing changes while the controller is in configuring mode
|
||||||
|
NpadStyleIndex tmp_npad_type{NpadStyleIndex::None};
|
||||||
|
bool tmp_is_connected{false};
|
||||||
|
|
||||||
|
ButtonParams button_params;
|
||||||
|
StickParams stick_params;
|
||||||
|
TriggerParams trigger_params;
|
||||||
|
ControllerMotionParams motion_params;
|
||||||
|
RingAnalogParams ring_params;
|
||||||
|
|
||||||
|
ButtonDevices button_devices;
|
||||||
|
StickDevices stick_devices;
|
||||||
|
ControllerMotionDevices motion_devices;
|
||||||
|
TriggerDevices trigger_devices;
|
||||||
|
|
||||||
|
mutable std::mutex mutex;
|
||||||
|
mutable std::mutex callback_mutex;
|
||||||
|
std::unordered_map<int, ControllerUpdateCallback> callback_list;
|
||||||
|
int last_callback_key = 0;
|
||||||
|
|
||||||
|
// Stores the current status of all controller input
|
||||||
|
ControllerStatus controller;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::HID
|
@ -24,7 +24,6 @@ ClusteringProcessor::ClusteringProcessor(Core::HID::HIDCore& hid_core_,
|
|||||||
|
|
||||||
Core::HID::ControllerUpdateCallback engine_callback{
|
Core::HID::ControllerUpdateCallback engine_callback{
|
||||||
.on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); },
|
.on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); },
|
||||||
.is_npad_service = true,
|
|
||||||
};
|
};
|
||||||
callback_key = npad_device->SetCallback(engine_callback);
|
callback_key = npad_device->SetCallback(engine_callback);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "core/hid/emulated_controller.h"
|
#include "core/hid/system_controller.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
|
|
||||||
#include "ui_configure_hotkeys.h"
|
#include "ui_configure_hotkeys.h"
|
||||||
@ -42,7 +42,7 @@ ConfigureHotkeys::ConfigureHotkeys(Core::HID::HIDCore& hid_core, QWidget* parent
|
|||||||
&ConfigureHotkeys::RestoreDefaults);
|
&ConfigureHotkeys::RestoreDefaults);
|
||||||
connect(ui->button_clear_all, &QPushButton::clicked, this, &ConfigureHotkeys::ClearAll);
|
connect(ui->button_clear_all, &QPushButton::clicked, this, &ConfigureHotkeys::ClearAll);
|
||||||
|
|
||||||
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
controller = hid_core.GetSystemController(Core::HID::NpadIdType::Player1);
|
||||||
|
|
||||||
connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
|
connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ class ParamPackage;
|
|||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
class HIDCore;
|
class HIDCore;
|
||||||
class EmulatedController;
|
class SystemController;
|
||||||
enum class NpadButton : u64;
|
enum class NpadButton : u64;
|
||||||
} // namespace Core::HID
|
} // namespace Core::HID
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ private:
|
|||||||
|
|
||||||
void SetPollingResult(Core::HID::NpadButton button, bool cancel);
|
void SetPollingResult(Core::HID::NpadButton button, bool cancel);
|
||||||
QString GetButtonCombinationName(Core::HID::NpadButton button, bool home, bool capture) const;
|
QString GetButtonCombinationName(Core::HID::NpadButton button, bool home, bool capture) const;
|
||||||
Core::HID::EmulatedController* controller;
|
Core::HID::SystemController* controller;
|
||||||
std::unique_ptr<QTimer> timeout_timer;
|
std::unique_ptr<QTimer> timeout_timer;
|
||||||
std::unique_ptr<QTimer> poll_timer;
|
std::unique_ptr<QTimer> poll_timer;
|
||||||
std::optional<std::function<void(Core::HID::NpadButton, bool)>> input_setter;
|
std::optional<std::function<void(Core::HID::NpadButton, bool)>> input_setter;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/param_package.h"
|
#include "common/param_package.h"
|
||||||
#include "core/hid/emulated_controller.h"
|
#include "core/hid/system_controller.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
#include "core/hid/hid_types.h"
|
#include "core/hid/hid_types.h"
|
||||||
#include "input_common/drivers/keyboard.h"
|
#include "input_common/drivers/keyboard.h"
|
||||||
@ -297,24 +297,24 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
timeout_timer(std::make_unique<QTimer>()),
|
timeout_timer(std::make_unique<QTimer>()),
|
||||||
poll_timer(std::make_unique<QTimer>()), bottom_row{bottom_row_}, hid_core{hid_core_} {
|
poll_timer(std::make_unique<QTimer>()), bottom_row{bottom_row_}, hid_core{hid_core_} {
|
||||||
if (player_index == 0) {
|
if (player_index == 0) {
|
||||||
auto* emulated_controller_p1 =
|
auto* system_controller_p1 =
|
||||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
hid_core.GetSystemController(Core::HID::NpadIdType::Player1);
|
||||||
auto* emulated_controller_handheld =
|
auto* system_controller_handheld =
|
||||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
hid_core.GetSystemController(Core::HID::NpadIdType::Handheld);
|
||||||
emulated_controller_p1->SaveCurrentConfig();
|
system_controller_p1->SaveCurrentConfig();
|
||||||
emulated_controller_p1->EnableConfiguration();
|
system_controller_p1->EnableConfiguration();
|
||||||
emulated_controller_handheld->SaveCurrentConfig();
|
system_controller_handheld->SaveCurrentConfig();
|
||||||
emulated_controller_handheld->EnableConfiguration();
|
system_controller_handheld->EnableConfiguration();
|
||||||
if (emulated_controller_handheld->IsConnected(true)) {
|
if (system_controller_handheld->IsConnected(true)) {
|
||||||
emulated_controller_p1->Disconnect();
|
system_controller_p1->Disconnect();
|
||||||
emulated_controller = emulated_controller_handheld;
|
system_controller = system_controller_handheld;
|
||||||
} else {
|
} else {
|
||||||
emulated_controller = emulated_controller_p1;
|
system_controller = system_controller_p1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
emulated_controller = hid_core.GetEmulatedControllerByIndex(player_index);
|
system_controller = hid_core.GetSystemControllerByIndex(player_index);
|
||||||
emulated_controller->SaveCurrentConfig();
|
system_controller->SaveCurrentConfig();
|
||||||
emulated_controller->EnableConfiguration();
|
system_controller->EnableConfiguration();
|
||||||
}
|
}
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
@ -357,7 +357,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup};
|
analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup};
|
||||||
analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange};
|
analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange};
|
||||||
|
|
||||||
ui->controllerFrame->SetController(emulated_controller);
|
ui->controllerFrame->SetController(system_controller->GetNpadIdType());
|
||||||
|
|
||||||
for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
|
for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
|
||||||
auto* const button = button_map[button_id];
|
auto* const button = button_map[button_id];
|
||||||
@ -370,7 +370,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
HandleClick(
|
HandleClick(
|
||||||
button, button_id,
|
button, button_id,
|
||||||
[=, this](const Common::ParamPackage& params) {
|
[=, this](const Common::ParamPackage& params) {
|
||||||
emulated_controller->SetButtonParam(button_id, params);
|
system_controller->SetButtonParam(button_id, params);
|
||||||
},
|
},
|
||||||
InputCommon::Polling::InputType::Button);
|
InputCommon::Polling::InputType::Button);
|
||||||
});
|
});
|
||||||
@ -379,9 +379,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
connect(button, &QPushButton::customContextMenuRequested,
|
connect(button, &QPushButton::customContextMenuRequested,
|
||||||
[=, this](const QPoint& menu_location) {
|
[=, this](const QPoint& menu_location) {
|
||||||
QMenu context_menu;
|
QMenu context_menu;
|
||||||
Common::ParamPackage param = emulated_controller->GetButtonParam(button_id);
|
Common::ParamPackage param = system_controller->GetButtonParam(button_id);
|
||||||
context_menu.addAction(tr("Clear"), [&] {
|
context_menu.addAction(tr("Clear"), [&] {
|
||||||
emulated_controller->SetButtonParam(button_id, {});
|
system_controller->SetButtonParam(button_id, {});
|
||||||
button_map[button_id]->setText(tr("[not set]"));
|
button_map[button_id]->setText(tr("[not set]"));
|
||||||
});
|
});
|
||||||
if (param.Has("code") || param.Has("button") || param.Has("hat")) {
|
if (param.Has("code") || param.Has("button") || param.Has("hat")) {
|
||||||
@ -389,19 +389,19 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
const bool invert_value = !param.Get("inverted", false);
|
const bool invert_value = !param.Get("inverted", false);
|
||||||
param.Set("inverted", invert_value);
|
param.Set("inverted", invert_value);
|
||||||
button_map[button_id]->setText(ButtonToText(param));
|
button_map[button_id]->setText(ButtonToText(param));
|
||||||
emulated_controller->SetButtonParam(button_id, param);
|
system_controller->SetButtonParam(button_id, param);
|
||||||
});
|
});
|
||||||
context_menu.addAction(tr("Toggle button"), [&] {
|
context_menu.addAction(tr("Toggle button"), [&] {
|
||||||
const bool toggle_value = !param.Get("toggle", false);
|
const bool toggle_value = !param.Get("toggle", false);
|
||||||
param.Set("toggle", toggle_value);
|
param.Set("toggle", toggle_value);
|
||||||
button_map[button_id]->setText(ButtonToText(param));
|
button_map[button_id]->setText(ButtonToText(param));
|
||||||
emulated_controller->SetButtonParam(button_id, param);
|
system_controller->SetButtonParam(button_id, param);
|
||||||
});
|
});
|
||||||
context_menu.addAction(tr("Turbo button"), [&] {
|
context_menu.addAction(tr("Turbo button"), [&] {
|
||||||
const bool turbo_value = !param.Get("turbo", false);
|
const bool turbo_value = !param.Get("turbo", false);
|
||||||
param.Set("turbo", turbo_value);
|
param.Set("turbo", turbo_value);
|
||||||
button_map[button_id]->setText(ButtonToText(param));
|
button_map[button_id]->setText(ButtonToText(param));
|
||||||
emulated_controller->SetButtonParam(button_id, param);
|
system_controller->SetButtonParam(button_id, param);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (param.Has("axis")) {
|
if (param.Has("axis")) {
|
||||||
@ -409,13 +409,13 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
const bool toggle_value = !(param.Get("invert", "+") == "-");
|
const bool toggle_value = !(param.Get("invert", "+") == "-");
|
||||||
param.Set("invert", toggle_value ? "-" : "+");
|
param.Set("invert", toggle_value ? "-" : "+");
|
||||||
button_map[button_id]->setText(ButtonToText(param));
|
button_map[button_id]->setText(ButtonToText(param));
|
||||||
emulated_controller->SetButtonParam(button_id, param);
|
system_controller->SetButtonParam(button_id, param);
|
||||||
});
|
});
|
||||||
context_menu.addAction(tr("Invert button"), [&] {
|
context_menu.addAction(tr("Invert button"), [&] {
|
||||||
const bool invert_value = !param.Get("inverted", false);
|
const bool invert_value = !param.Get("inverted", false);
|
||||||
param.Set("inverted", invert_value);
|
param.Set("inverted", invert_value);
|
||||||
button_map[button_id]->setText(ButtonToText(param));
|
button_map[button_id]->setText(ButtonToText(param));
|
||||||
emulated_controller->SetButtonParam(button_id, param);
|
system_controller->SetButtonParam(button_id, param);
|
||||||
});
|
});
|
||||||
context_menu.addAction(tr("Set threshold"), [&] {
|
context_menu.addAction(tr("Set threshold"), [&] {
|
||||||
const int button_threshold =
|
const int button_threshold =
|
||||||
@ -431,13 +431,13 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
if (button_id == Settings::NativeButton::ZR) {
|
if (button_id == Settings::NativeButton::ZR) {
|
||||||
ui->sliderZRThreshold->setValue(new_threshold);
|
ui->sliderZRThreshold->setValue(new_threshold);
|
||||||
}
|
}
|
||||||
emulated_controller->SetButtonParam(button_id, param);
|
system_controller->SetButtonParam(button_id, param);
|
||||||
});
|
});
|
||||||
context_menu.addAction(tr("Toggle axis"), [&] {
|
context_menu.addAction(tr("Toggle axis"), [&] {
|
||||||
const bool toggle_value = !param.Get("toggle", false);
|
const bool toggle_value = !param.Get("toggle", false);
|
||||||
param.Set("toggle", toggle_value);
|
param.Set("toggle", toggle_value);
|
||||||
button_map[button_id]->setText(ButtonToText(param));
|
button_map[button_id]->setText(ButtonToText(param));
|
||||||
emulated_controller->SetButtonParam(button_id, param);
|
system_controller->SetButtonParam(button_id, param);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
|
context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
|
||||||
@ -454,7 +454,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
HandleClick(
|
HandleClick(
|
||||||
button, motion_id,
|
button, motion_id,
|
||||||
[=, this](const Common::ParamPackage& params) {
|
[=, this](const Common::ParamPackage& params) {
|
||||||
emulated_controller->SetMotionParam(motion_id, params);
|
system_controller->SetMotionParam(motion_id, params);
|
||||||
},
|
},
|
||||||
InputCommon::Polling::InputType::Motion);
|
InputCommon::Polling::InputType::Motion);
|
||||||
});
|
});
|
||||||
@ -464,9 +464,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
connect(button, &QPushButton::customContextMenuRequested,
|
connect(button, &QPushButton::customContextMenuRequested,
|
||||||
[=, this](const QPoint& menu_location) {
|
[=, this](const QPoint& menu_location) {
|
||||||
QMenu context_menu;
|
QMenu context_menu;
|
||||||
Common::ParamPackage param = emulated_controller->GetMotionParam(motion_id);
|
Common::ParamPackage param = system_controller->GetMotionParam(motion_id);
|
||||||
context_menu.addAction(tr("Clear"), [&] {
|
context_menu.addAction(tr("Clear"), [&] {
|
||||||
emulated_controller->SetMotionParam(motion_id, {});
|
system_controller->SetMotionParam(motion_id, {});
|
||||||
motion_map[motion_id]->setText(tr("[not set]"));
|
motion_map[motion_id]->setText(tr("[not set]"));
|
||||||
});
|
});
|
||||||
if (param.Has("motion")) {
|
if (param.Has("motion")) {
|
||||||
@ -477,7 +477,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
this, tr("Set threshold"), tr("Choose a value between 0% and 100%"),
|
this, tr("Set threshold"), tr("Choose a value between 0% and 100%"),
|
||||||
gyro_threshold, 0, 100);
|
gyro_threshold, 0, 100);
|
||||||
param.Set("threshold", new_threshold / 1000.0f);
|
param.Set("threshold", new_threshold / 1000.0f);
|
||||||
emulated_controller->SetMotionParam(motion_id, param);
|
system_controller->SetMotionParam(motion_id, param);
|
||||||
});
|
});
|
||||||
context_menu.addAction(tr("Calibrate sensor"), [&] {
|
context_menu.addAction(tr("Calibrate sensor"), [&] {
|
||||||
emulated_controller->StartMotionCalibration();
|
emulated_controller->StartMotionCalibration();
|
||||||
@ -489,21 +489,21 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
|
|
||||||
connect(ui->sliderZLThreshold, &QSlider::valueChanged, [=, this] {
|
connect(ui->sliderZLThreshold, &QSlider::valueChanged, [=, this] {
|
||||||
Common::ParamPackage param =
|
Common::ParamPackage param =
|
||||||
emulated_controller->GetButtonParam(Settings::NativeButton::ZL);
|
system_controller->GetButtonParam(Settings::NativeButton::ZL);
|
||||||
if (param.Has("threshold")) {
|
if (param.Has("threshold")) {
|
||||||
const auto slider_value = ui->sliderZLThreshold->value();
|
const auto slider_value = ui->sliderZLThreshold->value();
|
||||||
param.Set("threshold", slider_value / 100.0f);
|
param.Set("threshold", slider_value / 100.0f);
|
||||||
emulated_controller->SetButtonParam(Settings::NativeButton::ZL, param);
|
system_controller->SetButtonParam(Settings::NativeButton::ZL, param);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(ui->sliderZRThreshold, &QSlider::valueChanged, [=, this] {
|
connect(ui->sliderZRThreshold, &QSlider::valueChanged, [=, this] {
|
||||||
Common::ParamPackage param =
|
Common::ParamPackage param =
|
||||||
emulated_controller->GetButtonParam(Settings::NativeButton::ZR);
|
system_controller->GetButtonParam(Settings::NativeButton::ZR);
|
||||||
if (param.Has("threshold")) {
|
if (param.Has("threshold")) {
|
||||||
const auto slider_value = ui->sliderZRThreshold->value();
|
const auto slider_value = ui->sliderZRThreshold->value();
|
||||||
param.Set("threshold", slider_value / 100.0f);
|
param.Set("threshold", slider_value / 100.0f);
|
||||||
emulated_controller->SetButtonParam(Settings::NativeButton::ZR, param);
|
system_controller->SetButtonParam(Settings::NativeButton::ZR, param);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -531,7 +531,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
HandleClick(
|
HandleClick(
|
||||||
analog_map_buttons[analog_id][sub_button_id], analog_id,
|
analog_map_buttons[analog_id][sub_button_id], analog_id,
|
||||||
[=, this](const Common::ParamPackage& params) {
|
[=, this](const Common::ParamPackage& params) {
|
||||||
Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
|
Common::ParamPackage param = system_controller->GetStickParam(analog_id);
|
||||||
SetAnalogParam(params, param, analog_sub_buttons[sub_button_id]);
|
SetAnalogParam(params, param, analog_sub_buttons[sub_button_id]);
|
||||||
// Correct axis direction for inverted sticks
|
// Correct axis direction for inverted sticks
|
||||||
if (input_subsystem->IsStickInverted(param)) {
|
if (input_subsystem->IsStickInverted(param)) {
|
||||||
@ -552,7 +552,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
},
|
},
|
||||||
InputCommon::Polling::InputType::Stick);
|
InputCommon::Polling::InputType::Stick);
|
||||||
});
|
});
|
||||||
@ -562,10 +562,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
connect(analog_button, &QPushButton::customContextMenuRequested,
|
connect(analog_button, &QPushButton::customContextMenuRequested,
|
||||||
[=, this](const QPoint& menu_location) {
|
[=, this](const QPoint& menu_location) {
|
||||||
QMenu context_menu;
|
QMenu context_menu;
|
||||||
Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
|
Common::ParamPackage param = system_controller->GetStickParam(analog_id);
|
||||||
context_menu.addAction(tr("Clear"), [&] {
|
context_menu.addAction(tr("Clear"), [&] {
|
||||||
if (param.Get("engine", "") != "analog_from_button") {
|
if (param.Get("engine", "") != "analog_from_button") {
|
||||||
emulated_controller->SetStickParam(analog_id, {});
|
system_controller->SetStickParam(analog_id, {});
|
||||||
for (auto button : analog_map_buttons[analog_id]) {
|
for (auto button : analog_map_buttons[analog_id]) {
|
||||||
button->setText(tr("[not set]"));
|
button->setText(tr("[not set]"));
|
||||||
}
|
}
|
||||||
@ -585,12 +585,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
param.Erase("right");
|
param.Erase("right");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));
|
analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));
|
||||||
});
|
});
|
||||||
context_menu.addAction(tr("Center axis"), [&] {
|
context_menu.addAction(tr("Center axis"), [&] {
|
||||||
const auto stick_value =
|
const auto stick_value =
|
||||||
emulated_controller->GetSticksValues()[analog_id];
|
system_controller->GetSticksValues()[analog_id];
|
||||||
const float offset_x = stick_value.x.properties.offset;
|
const float offset_x = stick_value.x.properties.offset;
|
||||||
const float offset_y = stick_value.y.properties.offset;
|
const float offset_y = stick_value.y.properties.offset;
|
||||||
float raw_value_x = stick_value.x.raw_value;
|
float raw_value_x = stick_value.x.raw_value;
|
||||||
@ -612,20 +612,20 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
}
|
}
|
||||||
param.Set("offset_x", -raw_value_x + offset_x);
|
param.Set("offset_x", -raw_value_x + offset_x);
|
||||||
param.Set("offset_y", -raw_value_y + offset_y);
|
param.Set("offset_y", -raw_value_y + offset_y);
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
});
|
});
|
||||||
context_menu.addAction(tr("Invert axis"), [&] {
|
context_menu.addAction(tr("Invert axis"), [&] {
|
||||||
if (sub_button_id == 2 || sub_button_id == 3) {
|
if (sub_button_id == 2 || sub_button_id == 3) {
|
||||||
const bool invert_value = param.Get("invert_x", "+") == "-";
|
const bool invert_value = param.Get("invert_x", "+") == "-";
|
||||||
const std::string invert_str = invert_value ? "+" : "-";
|
const std::string invert_str = invert_value ? "+" : "-";
|
||||||
param.Set("invert_x", invert_str);
|
param.Set("invert_x", invert_str);
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
}
|
}
|
||||||
if (sub_button_id == 0 || sub_button_id == 1) {
|
if (sub_button_id == 0 || sub_button_id == 1) {
|
||||||
const bool invert_value = param.Get("invert_y", "+") == "-";
|
const bool invert_value = param.Get("invert_y", "+") == "-";
|
||||||
const std::string invert_str = invert_value ? "+" : "-";
|
const std::string invert_str = invert_value ? "+" : "-";
|
||||||
param.Set("invert_y", invert_str);
|
param.Set("invert_y", invert_str);
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
}
|
}
|
||||||
for (int analog_sub_button_id = 0;
|
for (int analog_sub_button_id = 0;
|
||||||
analog_sub_button_id < ANALOG_SUB_BUTTONS_NUM;
|
analog_sub_button_id < ANALOG_SUB_BUTTONS_NUM;
|
||||||
@ -644,9 +644,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
HandleClick(
|
HandleClick(
|
||||||
analog_map_modifier_button[analog_id], analog_id,
|
analog_map_modifier_button[analog_id], analog_id,
|
||||||
[=, this](const Common::ParamPackage& params) {
|
[=, this](const Common::ParamPackage& params) {
|
||||||
Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
|
Common::ParamPackage param = system_controller->GetStickParam(analog_id);
|
||||||
param.Set("modifier", params.Serialize());
|
param.Set("modifier", params.Serialize());
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
},
|
},
|
||||||
InputCommon::Polling::InputType::Button);
|
InputCommon::Polling::InputType::Button);
|
||||||
});
|
});
|
||||||
@ -657,11 +657,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
analog_map_modifier_button[analog_id], &QPushButton::customContextMenuRequested,
|
analog_map_modifier_button[analog_id], &QPushButton::customContextMenuRequested,
|
||||||
[=, this](const QPoint& menu_location) {
|
[=, this](const QPoint& menu_location) {
|
||||||
QMenu context_menu;
|
QMenu context_menu;
|
||||||
Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
|
Common::ParamPackage param = system_controller->GetStickParam(analog_id);
|
||||||
context_menu.addAction(tr("Clear"), [&] {
|
context_menu.addAction(tr("Clear"), [&] {
|
||||||
param.Set("modifier", "");
|
param.Set("modifier", "");
|
||||||
analog_map_modifier_button[analog_id]->setText(tr("[not set]"));
|
analog_map_modifier_button[analog_id]->setText(tr("[not set]"));
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
});
|
});
|
||||||
context_menu.addAction(tr("Toggle button"), [&] {
|
context_menu.addAction(tr("Toggle button"), [&] {
|
||||||
Common::ParamPackage modifier_param =
|
Common::ParamPackage modifier_param =
|
||||||
@ -670,7 +670,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
modifier_param.Set("toggle", toggle_value);
|
modifier_param.Set("toggle", toggle_value);
|
||||||
param.Set("modifier", modifier_param.Serialize());
|
param.Set("modifier", modifier_param.Serialize());
|
||||||
analog_map_modifier_button[analog_id]->setText(ButtonToText(modifier_param));
|
analog_map_modifier_button[analog_id]->setText(ButtonToText(modifier_param));
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
});
|
});
|
||||||
context_menu.addAction(tr("Invert button"), [&] {
|
context_menu.addAction(tr("Invert button"), [&] {
|
||||||
Common::ParamPackage modifier_param =
|
Common::ParamPackage modifier_param =
|
||||||
@ -679,7 +679,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
modifier_param.Set("inverted", invert_value);
|
modifier_param.Set("inverted", invert_value);
|
||||||
param.Set("modifier", modifier_param.Serialize());
|
param.Set("modifier", modifier_param.Serialize());
|
||||||
analog_map_modifier_button[analog_id]->setText(ButtonToText(modifier_param));
|
analog_map_modifier_button[analog_id]->setText(ButtonToText(modifier_param));
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
});
|
});
|
||||||
context_menu.exec(
|
context_menu.exec(
|
||||||
analog_map_modifier_button[analog_id]->mapToGlobal(menu_location));
|
analog_map_modifier_button[analog_id]->mapToGlobal(menu_location));
|
||||||
@ -687,27 +687,27 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
|
|
||||||
connect(analog_map_range_spinbox[analog_id], qOverload<int>(&QSpinBox::valueChanged),
|
connect(analog_map_range_spinbox[analog_id], qOverload<int>(&QSpinBox::valueChanged),
|
||||||
[=, this] {
|
[=, this] {
|
||||||
Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
|
Common::ParamPackage param = system_controller->GetStickParam(analog_id);
|
||||||
const auto spinbox_value = analog_map_range_spinbox[analog_id]->value();
|
const auto spinbox_value = analog_map_range_spinbox[analog_id]->value();
|
||||||
param.Set("range", spinbox_value / 100.0f);
|
param.Set("range", spinbox_value / 100.0f);
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] {
|
connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] {
|
||||||
Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
|
Common::ParamPackage param = system_controller->GetStickParam(analog_id);
|
||||||
const auto slider_value = analog_map_deadzone_slider[analog_id]->value();
|
const auto slider_value = analog_map_deadzone_slider[analog_id]->value();
|
||||||
analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value));
|
analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value));
|
||||||
param.Set("deadzone", slider_value / 100.0f);
|
param.Set("deadzone", slider_value / 100.0f);
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] {
|
connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] {
|
||||||
Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
|
Common::ParamPackage param = system_controller->GetStickParam(analog_id);
|
||||||
const auto slider_value = analog_map_modifier_slider[analog_id]->value();
|
const auto slider_value = analog_map_modifier_slider[analog_id]->value();
|
||||||
analog_map_modifier_label[analog_id]->setText(
|
analog_map_modifier_label[analog_id]->setText(
|
||||||
tr("Modifier Range: %1%").arg(slider_value));
|
tr("Modifier Range: %1%").arg(slider_value));
|
||||||
param.Set("modifier_scale", slider_value / 100.0f);
|
param.Set("modifier_scale", slider_value / 100.0f);
|
||||||
emulated_controller->SetStickParam(analog_id, param);
|
system_controller->SetStickParam(analog_id, param);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,28 +749,28 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
|
GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
|
||||||
|
|
||||||
if (player_index == 0) {
|
if (player_index == 0) {
|
||||||
auto* emulated_controller_p1 =
|
auto* system_controller_p1 =
|
||||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
hid_core.GetSystemController(Core::HID::NpadIdType::Player1);
|
||||||
auto* emulated_controller_handheld =
|
auto* system_controller_handheld =
|
||||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
hid_core.GetSystemController(Core::HID::NpadIdType::Handheld);
|
||||||
bool is_connected = emulated_controller->IsConnected(true);
|
bool is_connected = system_controller->IsConnected(true);
|
||||||
|
|
||||||
emulated_controller_p1->SetNpadStyleIndex(type);
|
system_controller_p1->SetNpadStyleIndex(type);
|
||||||
emulated_controller_handheld->SetNpadStyleIndex(type);
|
system_controller_handheld->SetNpadStyleIndex(type);
|
||||||
if (is_connected) {
|
if (is_connected) {
|
||||||
if (type == Core::HID::NpadStyleIndex::Handheld) {
|
if (type == Core::HID::NpadStyleIndex::Handheld) {
|
||||||
emulated_controller_p1->Disconnect();
|
system_controller_p1->Disconnect();
|
||||||
emulated_controller_handheld->Connect(true);
|
system_controller_handheld->Connect(true);
|
||||||
emulated_controller = emulated_controller_handheld;
|
system_controller = system_controller_handheld;
|
||||||
} else {
|
} else {
|
||||||
emulated_controller_handheld->Disconnect();
|
system_controller_handheld->Disconnect();
|
||||||
emulated_controller_p1->Connect(true);
|
system_controller_p1->Connect(true);
|
||||||
emulated_controller = emulated_controller_p1;
|
system_controller = system_controller_p1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui->controllerFrame->SetController(emulated_controller);
|
ui->controllerFrame->SetController(system_controller->GetNpadIdType());
|
||||||
}
|
}
|
||||||
emulated_controller->SetNpadStyleIndex(type);
|
system_controller->SetNpadStyleIndex(type);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
|
connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
|
||||||
@ -806,34 +806,33 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||||||
|
|
||||||
ConfigureInputPlayer::~ConfigureInputPlayer() {
|
ConfigureInputPlayer::~ConfigureInputPlayer() {
|
||||||
if (player_index == 0) {
|
if (player_index == 0) {
|
||||||
auto* emulated_controller_p1 =
|
auto* system_controller_p1 =
|
||||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
hid_core.GetSystemController(Core::HID::NpadIdType::Player1);
|
||||||
auto* emulated_controller_handheld =
|
auto* system_controller_handheld =
|
||||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
hid_core.GetSystemController(Core::HID::NpadIdType::Handheld);
|
||||||
emulated_controller_p1->DisableConfiguration();
|
system_controller_p1->DisableConfiguration();
|
||||||
emulated_controller_handheld->DisableConfiguration();
|
system_controller_handheld->DisableConfiguration();
|
||||||
} else {
|
} else {
|
||||||
emulated_controller->DisableConfiguration();
|
system_controller->DisableConfiguration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInputPlayer::ApplyConfiguration() {
|
void ConfigureInputPlayer::ApplyConfiguration() {
|
||||||
if (player_index == 0) {
|
if (player_index == 0) {
|
||||||
auto* emulated_controller_p1 =
|
auto* system_controller_p1 = hid_core.GetSystemController(Core::HID::NpadIdType::Player1);
|
||||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
auto* system_controller_handheld =
|
||||||
auto* emulated_controller_handheld =
|
hid_core.GetSystemController(Core::HID::NpadIdType::Handheld);
|
||||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
system_controller_p1->DisableConfiguration();
|
||||||
emulated_controller_p1->DisableConfiguration();
|
system_controller_p1->SaveCurrentConfig();
|
||||||
emulated_controller_p1->SaveCurrentConfig();
|
system_controller_p1->EnableConfiguration();
|
||||||
emulated_controller_p1->EnableConfiguration();
|
system_controller_handheld->DisableConfiguration();
|
||||||
emulated_controller_handheld->DisableConfiguration();
|
system_controller_handheld->SaveCurrentConfig();
|
||||||
emulated_controller_handheld->SaveCurrentConfig();
|
system_controller_handheld->EnableConfiguration();
|
||||||
emulated_controller_handheld->EnableConfiguration();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emulated_controller->DisableConfiguration();
|
system_controller->DisableConfiguration();
|
||||||
emulated_controller->SaveCurrentConfig();
|
system_controller->SaveCurrentConfig();
|
||||||
emulated_controller->EnableConfiguration();
|
system_controller->EnableConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInputPlayer::showEvent(QShowEvent* event) {
|
void ConfigureInputPlayer::showEvent(QShowEvent* event) {
|
||||||
@ -858,7 +857,7 @@ void ConfigureInputPlayer::RetranslateUI() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInputPlayer::LoadConfiguration() {
|
void ConfigureInputPlayer::LoadConfiguration() {
|
||||||
emulated_controller->ReloadFromSettings();
|
system_controller->ReloadFromSettings();
|
||||||
|
|
||||||
UpdateUI();
|
UpdateUI();
|
||||||
UpdateInputDeviceCombobox();
|
UpdateInputDeviceCombobox();
|
||||||
@ -868,17 +867,17 @@ void ConfigureInputPlayer::LoadConfiguration() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const int comboBoxIndex =
|
const int comboBoxIndex =
|
||||||
GetIndexFromControllerType(emulated_controller->GetNpadStyleIndex(true));
|
GetIndexFromControllerType(system_controller->GetNpadStyleIndex(true));
|
||||||
ui->comboControllerType->setCurrentIndex(comboBoxIndex);
|
ui->comboControllerType->setCurrentIndex(comboBoxIndex);
|
||||||
ui->groupConnectedController->setChecked(emulated_controller->IsConnected(true));
|
ui->groupConnectedController->setChecked(system_controller->IsConnected(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInputPlayer::ConnectPlayer(bool connected) {
|
void ConfigureInputPlayer::ConnectPlayer(bool connected) {
|
||||||
ui->groupConnectedController->setChecked(connected);
|
ui->groupConnectedController->setChecked(connected);
|
||||||
if (connected) {
|
if (connected) {
|
||||||
emulated_controller->Connect(true);
|
system_controller->Connect(true);
|
||||||
} else {
|
} else {
|
||||||
emulated_controller->Disconnect();
|
system_controller->Disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -889,7 +888,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto devices = emulated_controller->GetMappedDevices();
|
const auto devices = system_controller->GetMappedDevices();
|
||||||
UpdateInputDevices();
|
UpdateInputDevices();
|
||||||
|
|
||||||
if (devices.empty()) {
|
if (devices.empty()) {
|
||||||
@ -968,7 +967,7 @@ void ConfigureInputPlayer::ClearAll() {
|
|||||||
if (button == nullptr) {
|
if (button == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
emulated_controller->SetButtonParam(button_id, {});
|
system_controller->SetButtonParam(button_id, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
|
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
|
||||||
@ -977,7 +976,7 @@ void ConfigureInputPlayer::ClearAll() {
|
|||||||
if (analog_button == nullptr) {
|
if (analog_button == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
emulated_controller->SetStickParam(analog_id, {});
|
system_controller->SetStickParam(analog_id, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -986,7 +985,7 @@ void ConfigureInputPlayer::ClearAll() {
|
|||||||
if (motion_button == nullptr) {
|
if (motion_button == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
emulated_controller->SetMotionParam(motion_id, {});
|
system_controller->SetMotionParam(motion_id, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateUI();
|
UpdateUI();
|
||||||
@ -995,31 +994,31 @@ void ConfigureInputPlayer::ClearAll() {
|
|||||||
|
|
||||||
void ConfigureInputPlayer::UpdateUI() {
|
void ConfigureInputPlayer::UpdateUI() {
|
||||||
for (int button = 0; button < Settings::NativeButton::NumButtons; ++button) {
|
for (int button = 0; button < Settings::NativeButton::NumButtons; ++button) {
|
||||||
const Common::ParamPackage param = emulated_controller->GetButtonParam(button);
|
const Common::ParamPackage param = system_controller->GetButtonParam(button);
|
||||||
button_map[button]->setText(ButtonToText(param));
|
button_map[button]->setText(ButtonToText(param));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Common::ParamPackage ZL_param =
|
const Common::ParamPackage ZL_param =
|
||||||
emulated_controller->GetButtonParam(Settings::NativeButton::ZL);
|
system_controller->GetButtonParam(Settings::NativeButton::ZL);
|
||||||
if (ZL_param.Has("threshold")) {
|
if (ZL_param.Has("threshold")) {
|
||||||
const int button_threshold = static_cast<int>(ZL_param.Get("threshold", 0.5f) * 100.0f);
|
const int button_threshold = static_cast<int>(ZL_param.Get("threshold", 0.5f) * 100.0f);
|
||||||
ui->sliderZLThreshold->setValue(button_threshold);
|
ui->sliderZLThreshold->setValue(button_threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Common::ParamPackage ZR_param =
|
const Common::ParamPackage ZR_param =
|
||||||
emulated_controller->GetButtonParam(Settings::NativeButton::ZR);
|
system_controller->GetButtonParam(Settings::NativeButton::ZR);
|
||||||
if (ZR_param.Has("threshold")) {
|
if (ZR_param.Has("threshold")) {
|
||||||
const int button_threshold = static_cast<int>(ZR_param.Get("threshold", 0.5f) * 100.0f);
|
const int button_threshold = static_cast<int>(ZR_param.Get("threshold", 0.5f) * 100.0f);
|
||||||
ui->sliderZRThreshold->setValue(button_threshold);
|
ui->sliderZRThreshold->setValue(button_threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
|
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
|
||||||
const Common::ParamPackage param = emulated_controller->GetMotionParam(motion_id);
|
const Common::ParamPackage param = system_controller->GetMotionParam(motion_id);
|
||||||
motion_map[motion_id]->setText(ButtonToText(param));
|
motion_map[motion_id]->setText(ButtonToText(param));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
|
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
|
||||||
const Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
|
const Common::ParamPackage param = system_controller->GetStickParam(analog_id);
|
||||||
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
|
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
|
||||||
auto* const analog_button = analog_map_buttons[analog_id][sub_button_id];
|
auto* const analog_button = analog_map_buttons[analog_id][sub_button_id];
|
||||||
|
|
||||||
@ -1347,7 +1346,7 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
|
|||||||
if (button == nullptr) {
|
if (button == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
emulated_controller->SetButtonParam(button_id, {});
|
system_controller->SetButtonParam(button_id, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
|
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
|
||||||
@ -1356,7 +1355,7 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
|
|||||||
if (analog_button == nullptr) {
|
if (analog_button == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
emulated_controller->SetStickParam(analog_id, {});
|
system_controller->SetStickParam(analog_id, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1365,13 +1364,13 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
|
|||||||
if (motion_button == nullptr) {
|
if (motion_button == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
emulated_controller->SetMotionParam(motion_id, {});
|
system_controller->SetMotionParam(motion_id, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset keyboard or mouse bindings
|
// Reset keyboard or mouse bindings
|
||||||
if (ui->comboDevices->currentIndex() == 1 || ui->comboDevices->currentIndex() == 2) {
|
if (ui->comboDevices->currentIndex() == 1 || ui->comboDevices->currentIndex() == 2) {
|
||||||
for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
|
for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
|
||||||
emulated_controller->SetButtonParam(
|
system_controller->SetButtonParam(
|
||||||
button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
|
button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
|
||||||
Config::default_buttons[button_id])});
|
Config::default_buttons[button_id])});
|
||||||
}
|
}
|
||||||
@ -1385,11 +1384,11 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
|
|||||||
|
|
||||||
analog_param.Set("modifier", InputCommon::GenerateKeyboardParam(
|
analog_param.Set("modifier", InputCommon::GenerateKeyboardParam(
|
||||||
Config::default_stick_mod[analog_id]));
|
Config::default_stick_mod[analog_id]));
|
||||||
emulated_controller->SetStickParam(analog_id, analog_param);
|
system_controller->SetStickParam(analog_id, analog_param);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
|
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
|
||||||
emulated_controller->SetMotionParam(
|
system_controller->SetMotionParam(
|
||||||
motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
|
motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
|
||||||
Config::default_motions[motion_id])});
|
Config::default_motions[motion_id])});
|
||||||
}
|
}
|
||||||
@ -1409,15 +1408,15 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
|
|||||||
|
|
||||||
for (const auto& button_mapping : button_mappings) {
|
for (const auto& button_mapping : button_mappings) {
|
||||||
const std::size_t index = button_mapping.first;
|
const std::size_t index = button_mapping.first;
|
||||||
emulated_controller->SetButtonParam(index, button_mapping.second);
|
system_controller->SetButtonParam(index, button_mapping.second);
|
||||||
}
|
}
|
||||||
for (const auto& analog_mapping : analog_mappings) {
|
for (const auto& analog_mapping : analog_mappings) {
|
||||||
const std::size_t index = analog_mapping.first;
|
const std::size_t index = analog_mapping.first;
|
||||||
emulated_controller->SetStickParam(index, analog_mapping.second);
|
system_controller->SetStickParam(index, analog_mapping.second);
|
||||||
}
|
}
|
||||||
for (const auto& motion_mapping : motion_mappings) {
|
for (const auto& motion_mapping : motion_mappings) {
|
||||||
const std::size_t index = motion_mapping.first;
|
const std::size_t index = motion_mapping.first;
|
||||||
emulated_controller->SetMotionParam(index, motion_mapping.second);
|
system_controller->SetMotionParam(index, motion_mapping.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateUI();
|
UpdateUI();
|
||||||
@ -1609,7 +1608,7 @@ void ConfigureInputPlayer::SaveProfile() {
|
|||||||
ApplyConfiguration();
|
ApplyConfiguration();
|
||||||
|
|
||||||
// When we're in handheld mode, only the handheld emulated controller bindings are updated
|
// When we're in handheld mode, only the handheld emulated controller bindings are updated
|
||||||
const bool is_handheld = player_index == 0 && emulated_controller->GetNpadIdType() ==
|
const bool is_handheld = player_index == 0 && system_controller->GetNpadIdType() ==
|
||||||
Core::HID::NpadIdType::Handheld;
|
Core::HID::NpadIdType::Handheld;
|
||||||
const auto profile_player_index = is_handheld ? HANDHELD_INDEX : player_index;
|
const auto profile_player_index = is_handheld ? HANDHELD_INDEX : player_index;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ class ConfigureInputPlayer;
|
|||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
class HIDCore;
|
class HIDCore;
|
||||||
class EmulatedController;
|
class SystemController;
|
||||||
enum class NpadStyleIndex : u8;
|
enum class NpadStyleIndex : u8;
|
||||||
} // namespace Core::HID
|
} // namespace Core::HID
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ private:
|
|||||||
/// This will be the the setting function when an input is awaiting configuration.
|
/// This will be the the setting function when an input is awaiting configuration.
|
||||||
std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
|
std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
|
||||||
|
|
||||||
Core::HID::EmulatedController* emulated_controller;
|
Core::HID::SystemController* system_controller;
|
||||||
|
|
||||||
static constexpr int ANALOG_SUB_BUTTONS_NUM = 4;
|
static constexpr int ANALOG_SUB_BUTTONS_NUM = 4;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user