|
@@ -2,6 +2,7 @@
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
#include <algorithm>
|
|
|
|
|
+#include <common/scope_exit.h>
|
|
|
|
|
|
|
|
#include "common/polyfill_ranges.h"
|
|
#include "common/polyfill_ranges.h"
|
|
|
#include "common/thread.h"
|
|
#include "common/thread.h"
|
|
@@ -94,6 +95,7 @@ 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),
|
|
@@ -107,6 +109,8 @@ void EmulatedController::ReloadFromSettings() {
|
|
|
.button = GetNpadColor(player.button_color_right),
|
|
.button = GetNpadColor(player.button_color_right),
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ ring_params[0] = Common::ParamPackage(Settings::values.ringcon_analogs);
|
|
|
|
|
+
|
|
|
// Other or debug controller should always be a pro controller
|
|
// Other or debug controller should always be a pro controller
|
|
|
if (npad_id_type != NpadIdType::Other) {
|
|
if (npad_id_type != NpadIdType::Other) {
|
|
|
SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type));
|
|
SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type));
|
|
@@ -133,18 +137,28 @@ void EmulatedController::LoadDevices() {
|
|
|
trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL];
|
|
trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL];
|
|
|
trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR];
|
|
trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR];
|
|
|
|
|
|
|
|
|
|
+ color_params[LeftIndex] = left_joycon;
|
|
|
|
|
+ color_params[RightIndex] = right_joycon;
|
|
|
|
|
+ color_params[LeftIndex].Set("color", true);
|
|
|
|
|
+ color_params[RightIndex].Set("color", true);
|
|
|
|
|
+
|
|
|
battery_params[LeftIndex] = left_joycon;
|
|
battery_params[LeftIndex] = left_joycon;
|
|
|
battery_params[RightIndex] = right_joycon;
|
|
battery_params[RightIndex] = right_joycon;
|
|
|
battery_params[LeftIndex].Set("battery", true);
|
|
battery_params[LeftIndex].Set("battery", true);
|
|
|
battery_params[RightIndex].Set("battery", true);
|
|
battery_params[RightIndex].Set("battery", true);
|
|
|
|
|
|
|
|
- camera_params = Common::ParamPackage{"engine:camera,camera:1"};
|
|
|
|
|
- nfc_params = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"};
|
|
|
|
|
|
|
+ camera_params[0] = right_joycon;
|
|
|
|
|
+ camera_params[0].Set("camera", true);
|
|
|
|
|
+ camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"};
|
|
|
|
|
+ ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"};
|
|
|
|
|
+ nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"};
|
|
|
|
|
+ nfc_params[1] = right_joycon;
|
|
|
|
|
+ nfc_params[1].Set("nfc", true);
|
|
|
|
|
|
|
|
output_params[LeftIndex] = left_joycon;
|
|
output_params[LeftIndex] = left_joycon;
|
|
|
output_params[RightIndex] = right_joycon;
|
|
output_params[RightIndex] = right_joycon;
|
|
|
- output_params[2] = camera_params;
|
|
|
|
|
- output_params[3] = nfc_params;
|
|
|
|
|
|
|
+ output_params[2] = camera_params[1];
|
|
|
|
|
+ output_params[3] = nfc_params[0];
|
|
|
output_params[LeftIndex].Set("output", true);
|
|
output_params[LeftIndex].Set("output", true);
|
|
|
output_params[RightIndex].Set("output", true);
|
|
output_params[RightIndex].Set("output", true);
|
|
|
output_params[2].Set("output", true);
|
|
output_params[2].Set("output", true);
|
|
@@ -160,8 +174,11 @@ void EmulatedController::LoadDevices() {
|
|
|
Common::Input::CreateInputDevice);
|
|
Common::Input::CreateInputDevice);
|
|
|
std::ranges::transform(battery_params, battery_devices.begin(),
|
|
std::ranges::transform(battery_params, battery_devices.begin(),
|
|
|
Common::Input::CreateInputDevice);
|
|
Common::Input::CreateInputDevice);
|
|
|
- camera_devices = Common::Input::CreateInputDevice(camera_params);
|
|
|
|
|
- nfc_devices = Common::Input::CreateInputDevice(nfc_params);
|
|
|
|
|
|
|
+ std::ranges::transform(color_params, color_devices.begin(), Common::Input::CreateInputDevice);
|
|
|
|
|
+ std::ranges::transform(camera_params, camera_devices.begin(), Common::Input::CreateInputDevice);
|
|
|
|
|
+ std::ranges::transform(ring_params, ring_analog_devices.begin(),
|
|
|
|
|
+ Common::Input::CreateInputDevice);
|
|
|
|
|
+ std::ranges::transform(nfc_params, nfc_devices.begin(), Common::Input::CreateInputDevice);
|
|
|
std::ranges::transform(output_params, output_devices.begin(),
|
|
std::ranges::transform(output_params, output_devices.begin(),
|
|
|
Common::Input::CreateOutputDevice);
|
|
Common::Input::CreateOutputDevice);
|
|
|
|
|
|
|
@@ -323,6 +340,19 @@ void EmulatedController::ReloadInput() {
|
|
|
battery_devices[index]->ForceUpdate();
|
|
battery_devices[index]->ForceUpdate();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ for (std::size_t index = 0; index < color_devices.size(); ++index) {
|
|
|
|
|
+ if (!color_devices[index]) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ color_devices[index]->SetCallback({
|
|
|
|
|
+ .on_change =
|
|
|
|
|
+ [this, index](const Common::Input::CallbackStatus& callback) {
|
|
|
|
|
+ SetColors(callback, index);
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+ color_devices[index]->ForceUpdate();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
for (std::size_t index = 0; index < motion_devices.size(); ++index) {
|
|
for (std::size_t index = 0; index < motion_devices.size(); ++index) {
|
|
|
if (!motion_devices[index]) {
|
|
if (!motion_devices[index]) {
|
|
|
continue;
|
|
continue;
|
|
@@ -336,22 +366,37 @@ void EmulatedController::ReloadInput() {
|
|
|
motion_devices[index]->ForceUpdate();
|
|
motion_devices[index]->ForceUpdate();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (camera_devices) {
|
|
|
|
|
- camera_devices->SetCallback({
|
|
|
|
|
|
|
+ for (std::size_t index = 0; index < camera_devices.size(); ++index) {
|
|
|
|
|
+ if (!camera_devices[index]) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ camera_devices[index]->SetCallback({
|
|
|
.on_change =
|
|
.on_change =
|
|
|
[this](const Common::Input::CallbackStatus& callback) { SetCamera(callback); },
|
|
[this](const Common::Input::CallbackStatus& callback) { SetCamera(callback); },
|
|
|
});
|
|
});
|
|
|
- camera_devices->ForceUpdate();
|
|
|
|
|
|
|
+ camera_devices[index]->ForceUpdate();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (nfc_devices) {
|
|
|
|
|
- if (npad_id_type == NpadIdType::Handheld || npad_id_type == NpadIdType::Player1) {
|
|
|
|
|
- nfc_devices->SetCallback({
|
|
|
|
|
- .on_change =
|
|
|
|
|
- [this](const Common::Input::CallbackStatus& callback) { SetNfc(callback); },
|
|
|
|
|
- });
|
|
|
|
|
- nfc_devices->ForceUpdate();
|
|
|
|
|
|
|
+ for (std::size_t index = 0; index < ring_analog_devices.size(); ++index) {
|
|
|
|
|
+ if (!ring_analog_devices[index]) {
|
|
|
|
|
+ continue;
|
|
|
}
|
|
}
|
|
|
|
|
+ ring_analog_devices[index]->SetCallback({
|
|
|
|
|
+ .on_change =
|
|
|
|
|
+ [this](const Common::Input::CallbackStatus& callback) { SetRingAnalog(callback); },
|
|
|
|
|
+ });
|
|
|
|
|
+ ring_analog_devices[index]->ForceUpdate();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (std::size_t index = 0; index < nfc_devices.size(); ++index) {
|
|
|
|
|
+ if (!nfc_devices[index]) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ nfc_devices[index]->SetCallback({
|
|
|
|
|
+ .on_change =
|
|
|
|
|
+ [this](const Common::Input::CallbackStatus& callback) { SetNfc(callback); },
|
|
|
|
|
+ });
|
|
|
|
|
+ nfc_devices[index]->ForceUpdate();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Register TAS devices. No need to force update
|
|
// Register TAS devices. No need to force update
|
|
@@ -421,6 +466,9 @@ void EmulatedController::UnloadInput() {
|
|
|
for (auto& battery : battery_devices) {
|
|
for (auto& battery : battery_devices) {
|
|
|
battery.reset();
|
|
battery.reset();
|
|
|
}
|
|
}
|
|
|
|
|
+ for (auto& color : color_devices) {
|
|
|
|
|
+ color.reset();
|
|
|
|
|
+ }
|
|
|
for (auto& output : output_devices) {
|
|
for (auto& output : output_devices) {
|
|
|
output.reset();
|
|
output.reset();
|
|
|
}
|
|
}
|
|
@@ -436,8 +484,15 @@ void EmulatedController::UnloadInput() {
|
|
|
for (auto& stick : virtual_stick_devices) {
|
|
for (auto& stick : virtual_stick_devices) {
|
|
|
stick.reset();
|
|
stick.reset();
|
|
|
}
|
|
}
|
|
|
- camera_devices.reset();
|
|
|
|
|
- nfc_devices.reset();
|
|
|
|
|
|
|
+ for (auto& camera : camera_devices) {
|
|
|
|
|
+ camera.reset();
|
|
|
|
|
+ }
|
|
|
|
|
+ for (auto& ring : ring_analog_devices) {
|
|
|
|
|
+ ring.reset();
|
|
|
|
|
+ }
|
|
|
|
|
+ for (auto& nfc : nfc_devices) {
|
|
|
|
|
+ nfc.reset();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EmulatedController::EnableConfiguration() {
|
|
void EmulatedController::EnableConfiguration() {
|
|
@@ -449,6 +504,11 @@ void EmulatedController::EnableConfiguration() {
|
|
|
void EmulatedController::DisableConfiguration() {
|
|
void EmulatedController::DisableConfiguration() {
|
|
|
is_configuring = false;
|
|
is_configuring = false;
|
|
|
|
|
|
|
|
|
|
+ // Get Joycon colors before turning on the controller
|
|
|
|
|
+ for (const auto& color_device : color_devices) {
|
|
|
|
|
+ color_device->ForceUpdate();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// Apply temporary npad type to the real controller
|
|
// Apply temporary npad type to the real controller
|
|
|
if (tmp_npad_type != npad_type) {
|
|
if (tmp_npad_type != npad_type) {
|
|
|
if (is_connected) {
|
|
if (is_connected) {
|
|
@@ -502,6 +562,9 @@ void EmulatedController::SaveCurrentConfig() {
|
|
|
for (std::size_t index = 0; index < player.motions.size(); ++index) {
|
|
for (std::size_t index = 0; index < player.motions.size(); ++index) {
|
|
|
player.motions[index] = motion_params[index].Serialize();
|
|
player.motions[index] = motion_params[index].Serialize();
|
|
|
}
|
|
}
|
|
|
|
|
+ if (npad_id_type == NpadIdType::Player1) {
|
|
|
|
|
+ Settings::values.ringcon_analogs = ring_params[0].Serialize();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EmulatedController::RestoreConfig() {
|
|
void EmulatedController::RestoreConfig() {
|
|
@@ -773,17 +836,21 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
|
|
|
if (index >= controller.stick_values.size()) {
|
|
if (index >= controller.stick_values.size()) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- std::unique_lock lock{mutex};
|
|
|
|
|
|
|
+ auto trigger_guard =
|
|
|
|
|
+ SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); });
|
|
|
|
|
+ std::scoped_lock lock{mutex};
|
|
|
const auto stick_value = TransformToStick(callback);
|
|
const auto stick_value = TransformToStick(callback);
|
|
|
|
|
|
|
|
// Only read stick values that have the same uuid or are over the threshold to avoid flapping
|
|
// 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 (controller.stick_values[index].uuid != uuid) {
|
|
|
const bool is_tas = uuid == TAS_UUID;
|
|
const bool is_tas = uuid == TAS_UUID;
|
|
|
if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) {
|
|
if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) {
|
|
|
|
|
+ trigger_guard.Cancel();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left &&
|
|
if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left &&
|
|
|
!stick_value.right) {
|
|
!stick_value.right) {
|
|
|
|
|
+ trigger_guard.Cancel();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -794,8 +861,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
|
|
|
if (is_configuring) {
|
|
if (is_configuring) {
|
|
|
controller.analog_stick_state.left = {};
|
|
controller.analog_stick_state.left = {};
|
|
|
controller.analog_stick_state.right = {};
|
|
controller.analog_stick_state.right = {};
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Stick, false);
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -827,9 +892,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
|
|
|
controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down);
|
|
controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Stick, true);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback,
|
|
void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback,
|
|
@@ -837,7 +899,9 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
|
|
|
if (index >= controller.trigger_values.size()) {
|
|
if (index >= controller.trigger_values.size()) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- std::unique_lock lock{mutex};
|
|
|
|
|
|
|
+ auto trigger_guard =
|
|
|
|
|
+ SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); });
|
|
|
|
|
+ std::scoped_lock lock{mutex};
|
|
|
const auto trigger_value = TransformToTrigger(callback);
|
|
const auto trigger_value = TransformToTrigger(callback);
|
|
|
|
|
|
|
|
// Only read trigger values that have the same uuid or are pressed once
|
|
// Only read trigger values that have the same uuid or are pressed once
|
|
@@ -853,13 +917,12 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
|
|
|
if (is_configuring) {
|
|
if (is_configuring) {
|
|
|
controller.gc_trigger_state.left = 0;
|
|
controller.gc_trigger_state.left = 0;
|
|
|
controller.gc_trigger_state.right = 0;
|
|
controller.gc_trigger_state.right = 0;
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Trigger, false);
|
|
|
|
|
return;
|
|
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();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -876,9 +939,6 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
|
|
|
controller.npad_button_state.zr.Assign(trigger.pressed.value);
|
|
controller.npad_button_state.zr.Assign(trigger.pressed.value);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Trigger, true);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback,
|
|
void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback,
|
|
@@ -886,7 +946,8 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
|
|
|
if (index >= controller.motion_values.size()) {
|
|
if (index >= controller.motion_values.size()) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- std::unique_lock lock{mutex};
|
|
|
|
|
|
|
+ SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Motion, !is_configuring); });
|
|
|
|
|
+ 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;
|
|
|
|
|
|
|
@@ -907,8 +968,6 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
|
|
|
force_update_motion = raw_status.force_update;
|
|
force_update_motion = raw_status.force_update;
|
|
|
|
|
|
|
|
if (is_configuring) {
|
|
if (is_configuring) {
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Motion, false);
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -918,9 +977,56 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
|
|
|
motion.rotation = emulated.GetRotations();
|
|
motion.rotation = emulated.GetRotations();
|
|
|
motion.orientation = emulated.GetOrientation();
|
|
motion.orientation = emulated.GetOrientation();
|
|
|
motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
|
|
motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Motion, true);
|
|
|
|
|
|
|
+void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback,
|
|
|
|
|
+ std::size_t index) {
|
|
|
|
|
+ if (index >= controller.color_values.size()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ auto trigger_guard =
|
|
|
|
|
+ SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Color, !is_configuring); });
|
|
|
|
|
+ std::scoped_lock lock{mutex};
|
|
|
|
|
+ controller.color_values[index] = TransformToColor(callback);
|
|
|
|
|
+
|
|
|
|
|
+ if (is_configuring) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (controller.color_values[index].body == 0) {
|
|
|
|
|
+ trigger_guard.Cancel();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ controller.colors_state.fullkey = {
|
|
|
|
|
+ .body = GetNpadColor(controller.color_values[index].body),
|
|
|
|
|
+ .button = GetNpadColor(controller.color_values[index].buttons),
|
|
|
|
|
+ };
|
|
|
|
|
+ if (npad_type == NpadStyleIndex::ProController) {
|
|
|
|
|
+ controller.colors_state.left = {
|
|
|
|
|
+ .body = GetNpadColor(controller.color_values[index].left_grip),
|
|
|
|
|
+ .button = GetNpadColor(controller.color_values[index].buttons),
|
|
|
|
|
+ };
|
|
|
|
|
+ controller.colors_state.right = {
|
|
|
|
|
+ .body = GetNpadColor(controller.color_values[index].right_grip),
|
|
|
|
|
+ .button = GetNpadColor(controller.color_values[index].buttons),
|
|
|
|
|
+ };
|
|
|
|
|
+ } else {
|
|
|
|
|
+ switch (index) {
|
|
|
|
|
+ case LeftIndex:
|
|
|
|
|
+ controller.colors_state.left = {
|
|
|
|
|
+ .body = GetNpadColor(controller.color_values[index].body),
|
|
|
|
|
+ .button = GetNpadColor(controller.color_values[index].buttons),
|
|
|
|
|
+ };
|
|
|
|
|
+ break;
|
|
|
|
|
+ case RightIndex:
|
|
|
|
|
+ controller.colors_state.right = {
|
|
|
|
|
+ .body = GetNpadColor(controller.color_values[index].body),
|
|
|
|
|
+ .button = GetNpadColor(controller.color_values[index].buttons),
|
|
|
|
|
+ };
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback,
|
|
void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback,
|
|
@@ -928,12 +1034,11 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
|
|
|
if (index >= controller.battery_values.size()) {
|
|
if (index >= controller.battery_values.size()) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- std::unique_lock lock{mutex};
|
|
|
|
|
|
|
+ SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Battery, !is_configuring); });
|
|
|
|
|
+ std::scoped_lock lock{mutex};
|
|
|
controller.battery_values[index] = TransformToBattery(callback);
|
|
controller.battery_values[index] = TransformToBattery(callback);
|
|
|
|
|
|
|
|
if (is_configuring) {
|
|
if (is_configuring) {
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Battery, false);
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -989,18 +1094,14 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
|
|
|
};
|
|
};
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Battery, true);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) {
|
|
void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) {
|
|
|
- std::unique_lock lock{mutex};
|
|
|
|
|
|
|
+ SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::IrSensor, !is_configuring); });
|
|
|
|
|
+ std::scoped_lock lock{mutex};
|
|
|
controller.camera_values = TransformToCamera(callback);
|
|
controller.camera_values = TransformToCamera(callback);
|
|
|
|
|
|
|
|
if (is_configuring) {
|
|
if (is_configuring) {
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::IrSensor, false);
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1008,18 +1109,28 @@ void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback
|
|
|
controller.camera_state.format =
|
|
controller.camera_state.format =
|
|
|
static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format);
|
|
static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format);
|
|
|
controller.camera_state.data = controller.camera_values.data;
|
|
controller.camera_state.data = controller.camera_values.data;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::IrSensor, true);
|
|
|
|
|
|
|
+void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) {
|
|
|
|
|
+ SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::RingController, !is_configuring); });
|
|
|
|
|
+ std::scoped_lock lock{mutex};
|
|
|
|
|
+ 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;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
|
|
void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
|
|
|
- std::unique_lock lock{mutex};
|
|
|
|
|
|
|
+ SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Nfc, !is_configuring); });
|
|
|
|
|
+ std::scoped_lock lock{mutex};
|
|
|
controller.nfc_values = TransformToNfc(callback);
|
|
controller.nfc_values = TransformToNfc(callback);
|
|
|
|
|
|
|
|
if (is_configuring) {
|
|
if (is_configuring) {
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Nfc, false);
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1027,9 +1138,6 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
|
|
|
controller.nfc_values.state,
|
|
controller.nfc_values.state,
|
|
|
controller.nfc_values.data,
|
|
controller.nfc_values.data,
|
|
|
};
|
|
};
|
|
|
-
|
|
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Nfc, true);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
|
|
bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
|
|
@@ -1061,7 +1169,7 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
|
|
|
.type = type,
|
|
.type = type,
|
|
|
};
|
|
};
|
|
|
return output_devices[device_index]->SetVibration(status) ==
|
|
return output_devices[device_index]->SetVibration(status) ==
|
|
|
- Common::Input::VibrationError::None;
|
|
|
|
|
|
|
+ Common::Input::DriverResult::Success;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
|
|
bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
|
|
@@ -1083,16 +1191,32 @@ bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
|
|
|
return output_devices[device_index]->IsVibrationEnabled();
|
|
return output_devices[device_index]->IsVibrationEnabled();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) {
|
|
|
|
|
- LOG_INFO(Service_HID, "Set polling mode {}", polling_mode);
|
|
|
|
|
- auto& output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
|
|
|
|
|
|
|
+Common::Input::DriverResult EmulatedController::SetPollingMode(
|
|
|
|
|
+ EmulatedDeviceIndex device_index, Common::Input::PollingMode polling_mode) {
|
|
|
|
|
+ LOG_INFO(Service_HID, "Set polling mode {}, device_index={}", polling_mode, device_index);
|
|
|
|
|
+
|
|
|
|
|
+ auto& left_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Left)];
|
|
|
|
|
+ auto& right_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
|
|
|
auto& nfc_output_device = output_devices[3];
|
|
auto& nfc_output_device = output_devices[3];
|
|
|
|
|
|
|
|
- const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode);
|
|
|
|
|
- const auto mapped_nfc_result = output_device->SetPollingMode(polling_mode);
|
|
|
|
|
|
|
+ if (device_index == EmulatedDeviceIndex::LeftIndex) {
|
|
|
|
|
+ return left_output_device->SetPollingMode(polling_mode);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (device_index == EmulatedDeviceIndex::RightIndex) {
|
|
|
|
|
+ const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode);
|
|
|
|
|
+ const auto mapped_nfc_result = right_output_device->SetPollingMode(polling_mode);
|
|
|
|
|
+
|
|
|
|
|
+ if (virtual_nfc_result == Common::Input::DriverResult::Success) {
|
|
|
|
|
+ return virtual_nfc_result;
|
|
|
|
|
+ }
|
|
|
|
|
+ return mapped_nfc_result;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return virtual_nfc_result == Common::Input::PollingError::None ||
|
|
|
|
|
- mapped_nfc_result == Common::Input::PollingError::None;
|
|
|
|
|
|
|
+ left_output_device->SetPollingMode(polling_mode);
|
|
|
|
|
+ right_output_device->SetPollingMode(polling_mode);
|
|
|
|
|
+ nfc_output_device->SetPollingMode(polling_mode);
|
|
|
|
|
+ return Common::Input::DriverResult::Success;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool EmulatedController::SetCameraFormat(
|
|
bool EmulatedController::SetCameraFormat(
|
|
@@ -1103,13 +1227,22 @@ bool EmulatedController::SetCameraFormat(
|
|
|
auto& camera_output_device = output_devices[2];
|
|
auto& camera_output_device = output_devices[2];
|
|
|
|
|
|
|
|
if (right_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>(
|
|
if (right_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>(
|
|
|
- camera_format)) == Common::Input::CameraError::None) {
|
|
|
|
|
|
|
+ camera_format)) == Common::Input::DriverResult::Success) {
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Fallback to Qt camera if native device doesn't have support
|
|
// Fallback to Qt camera if native device doesn't have support
|
|
|
return camera_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>(
|
|
return camera_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>(
|
|
|
- camera_format)) == Common::Input::CameraError::None;
|
|
|
|
|
|
|
+ camera_format)) == Common::Input::DriverResult::Success;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+Common::ParamPackage EmulatedController::GetRingParam() const {
|
|
|
|
|
+ return ring_params[0];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void EmulatedController::SetRingParam(Common::ParamPackage param) {
|
|
|
|
|
+ ring_params[0] = std::move(param);
|
|
|
|
|
+ ReloadInput();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool EmulatedController::HasNfc() const {
|
|
bool EmulatedController::HasNfc() const {
|
|
@@ -1263,39 +1396,35 @@ void EmulatedController::Connect(bool use_temporary_value) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- std::unique_lock lock{mutex};
|
|
|
|
|
|
|
+ auto trigger_guard =
|
|
|
|
|
+ SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); });
|
|
|
|
|
+ std::scoped_lock lock{mutex};
|
|
|
if (is_configuring) {
|
|
if (is_configuring) {
|
|
|
tmp_is_connected = true;
|
|
tmp_is_connected = true;
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Connected, false);
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (is_connected) {
|
|
if (is_connected) {
|
|
|
|
|
+ trigger_guard.Cancel();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
is_connected = true;
|
|
is_connected = true;
|
|
|
-
|
|
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Connected, true);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EmulatedController::Disconnect() {
|
|
void EmulatedController::Disconnect() {
|
|
|
- std::unique_lock lock{mutex};
|
|
|
|
|
|
|
+ auto trigger_guard =
|
|
|
|
|
+ SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); });
|
|
|
|
|
+ std::scoped_lock lock{mutex};
|
|
|
if (is_configuring) {
|
|
if (is_configuring) {
|
|
|
tmp_is_connected = false;
|
|
tmp_is_connected = false;
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Disconnected, false);
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!is_connected) {
|
|
if (!is_connected) {
|
|
|
|
|
+ trigger_guard.Cancel();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
is_connected = false;
|
|
is_connected = false;
|
|
|
-
|
|
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Disconnected, true);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool EmulatedController::IsConnected(bool get_temporary_value) const {
|
|
bool EmulatedController::IsConnected(bool get_temporary_value) const {
|
|
@@ -1320,19 +1449,21 @@ NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) c
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
|
|
void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
|
|
|
- std::unique_lock lock{mutex};
|
|
|
|
|
|
|
+ auto trigger_guard =
|
|
|
|
|
+ SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type, !is_configuring); });
|
|
|
|
|
+ std::scoped_lock lock{mutex};
|
|
|
|
|
|
|
|
if (is_configuring) {
|
|
if (is_configuring) {
|
|
|
if (tmp_npad_type == npad_type_) {
|
|
if (tmp_npad_type == npad_type_) {
|
|
|
|
|
+ trigger_guard.Cancel();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
tmp_npad_type = npad_type_;
|
|
tmp_npad_type = npad_type_;
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Type, false);
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (npad_type == npad_type_) {
|
|
if (npad_type == npad_type_) {
|
|
|
|
|
+ trigger_guard.Cancel();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
if (is_connected) {
|
|
if (is_connected) {
|
|
@@ -1340,9 +1471,6 @@ void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
|
|
|
NpadIdTypeToIndex(npad_id_type));
|
|
NpadIdTypeToIndex(npad_id_type));
|
|
|
}
|
|
}
|
|
|
npad_type = npad_type_;
|
|
npad_type = npad_type_;
|
|
|
-
|
|
|
|
|
- lock.unlock();
|
|
|
|
|
- TriggerOnChange(ControllerTriggerType::Type, true);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
LedPattern EmulatedController::GetLedPattern() const {
|
|
LedPattern EmulatedController::GetLedPattern() const {
|
|
@@ -1403,6 +1531,10 @@ CameraValues EmulatedController::GetCameraValues() const {
|
|
|
return controller.camera_values;
|
|
return controller.camera_values;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+RingAnalogValue EmulatedController::GetRingSensorValues() const {
|
|
|
|
|
+ return controller.ring_analog_value;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
HomeButtonState EmulatedController::GetHomeButtons() const {
|
|
HomeButtonState EmulatedController::GetHomeButtons() const {
|
|
|
std::scoped_lock lock{mutex};
|
|
std::scoped_lock lock{mutex};
|
|
|
if (is_configuring) {
|
|
if (is_configuring) {
|
|
@@ -1436,7 +1568,7 @@ DebugPadButton EmulatedController::GetDebugPadButtons() const {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
AnalogSticks EmulatedController::GetSticks() const {
|
|
AnalogSticks EmulatedController::GetSticks() const {
|
|
|
- std::unique_lock lock{mutex};
|
|
|
|
|
|
|
+ std::scoped_lock lock{mutex};
|
|
|
|
|
|
|
|
if (is_configuring) {
|
|
if (is_configuring) {
|
|
|
return {};
|
|
return {};
|
|
@@ -1486,6 +1618,10 @@ const CameraState& EmulatedController::GetCamera() const {
|
|
|
return controller.camera_state;
|
|
return controller.camera_state;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+RingSensorForce EmulatedController::GetRingSensorForce() const {
|
|
|
|
|
+ return controller.ring_analog_state;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
const NfcState& EmulatedController::GetNfc() const {
|
|
const NfcState& EmulatedController::GetNfc() const {
|
|
|
std::scoped_lock lock{mutex};
|
|
std::scoped_lock lock{mutex};
|
|
|
return controller.nfc_state;
|
|
return controller.nfc_state;
|