hid: Motion controls
This commit is contained in:
@@ -235,6 +235,11 @@ void Controller_NPad::OnLoadInputDevices() {
|
||||
std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
|
||||
players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
|
||||
sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>);
|
||||
std::transform(players[i].motion_devices.begin(), players[i].motion_devices.end(),
|
||||
motion_devices[i].begin(), [](const Settings::MotionRaw& raw) {
|
||||
return raw.enabled ? Input::CreateDevice<Input::MotionDevice>(raw.config)
|
||||
: nullptr;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,6 +343,41 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
cur_entry.timestamp2 = cur_entry.timestamp;
|
||||
}
|
||||
|
||||
const std::array<SixAxisGeneric*, 6> controller_sixaxes{
|
||||
&npad.sixaxis_full, &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
|
||||
&npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right,
|
||||
};
|
||||
|
||||
for (auto* sixaxis_sensor : controller_sixaxes) {
|
||||
sixaxis_sensor->common.entry_count = 16;
|
||||
sixaxis_sensor->common.total_entry_count = 17;
|
||||
|
||||
const auto& last_entry =
|
||||
sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
|
||||
|
||||
sixaxis_sensor->common.timestamp = core_timing.GetTicks();
|
||||
sixaxis_sensor->common.last_entry_index =
|
||||
(sixaxis_sensor->common.last_entry_index + 1) % 17;
|
||||
|
||||
auto& cur_entry = sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
|
||||
|
||||
cur_entry.timestamp = last_entry.timestamp + 1;
|
||||
cur_entry.timestamp2 = cur_entry.timestamp;
|
||||
}
|
||||
|
||||
// Try to read sixaxis sensor states
|
||||
Common::Vec3f accel1, gyro1, accel2, gyro2;
|
||||
if (sixaxis_sensors_enabled) {
|
||||
const auto& device1 = motion_devices[i][0];
|
||||
if (device1) {
|
||||
std::tie(accel1, gyro1) = device1->GetStatus();
|
||||
}
|
||||
const auto& device2 = motion_devices[i][1];
|
||||
if (device2) {
|
||||
std::tie(accel2, gyro2) = device2->GetStatus();
|
||||
}
|
||||
}
|
||||
|
||||
const auto& controller_type = connected_controllers[i].type;
|
||||
|
||||
if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
|
||||
@@ -359,6 +399,19 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
|
||||
auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
|
||||
|
||||
auto& full_sixaxis_entry =
|
||||
npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index];
|
||||
auto& handheld_sixaxis_entry =
|
||||
npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
|
||||
auto& dual_left_sixaxis_entry =
|
||||
npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index];
|
||||
auto& dual_right_sixaxis_entry =
|
||||
npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index];
|
||||
auto& left_sixaxis_entry =
|
||||
npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index];
|
||||
auto& right_sixaxis_entry =
|
||||
npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index];
|
||||
|
||||
libnx_entry.connection_status.raw = 0;
|
||||
|
||||
switch (controller_type) {
|
||||
@@ -375,6 +428,11 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
handheld_entry.pad.l_stick = pad_state.l_stick;
|
||||
handheld_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
if (sixaxis_sensors_enabled && motion_devices[i][0]) {
|
||||
handheld_sixaxis_entry.accel = accel1;
|
||||
handheld_sixaxis_entry.gyro = gyro1;
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyDual:
|
||||
dual_entry.connection_status.raw = 0;
|
||||
@@ -390,6 +448,20 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
dual_entry.pad.l_stick = pad_state.l_stick;
|
||||
dual_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
if (sixaxis_sensors_enabled) {
|
||||
if (motion_devices[i][0] && motion_devices[i][1]) {
|
||||
// set both
|
||||
dual_left_sixaxis_entry.accel = accel1;
|
||||
dual_left_sixaxis_entry.gyro = gyro1;
|
||||
dual_right_sixaxis_entry.accel = accel2;
|
||||
dual_right_sixaxis_entry.gyro = gyro2;
|
||||
} else if (motion_devices[i][0]) {
|
||||
// set right
|
||||
dual_right_sixaxis_entry.accel = accel1;
|
||||
dual_right_sixaxis_entry.gyro = gyro1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyLeft:
|
||||
left_entry.connection_status.raw = 0;
|
||||
@@ -398,6 +470,11 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
left_entry.pad.l_stick = pad_state.l_stick;
|
||||
left_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
if (sixaxis_sensors_enabled && motion_devices[i][0]) {
|
||||
left_sixaxis_entry.accel = accel1;
|
||||
left_sixaxis_entry.gyro = gyro1;
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyRight:
|
||||
right_entry.connection_status.raw = 0;
|
||||
@@ -406,6 +483,11 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
right_entry.pad.l_stick = pad_state.l_stick;
|
||||
right_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
if (sixaxis_sensors_enabled && motion_devices[i][0]) {
|
||||
right_sixaxis_entry.accel = accel1;
|
||||
right_sixaxis_entry.gyro = gyro1;
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::Pokeball:
|
||||
pokeball_entry.connection_status.raw = 0;
|
||||
@@ -425,6 +507,11 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
main_controller.pad.l_stick = pad_state.l_stick;
|
||||
main_controller.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
if (sixaxis_sensors_enabled && motion_devices[i][0]) {
|
||||
full_sixaxis_entry.accel = accel1;
|
||||
full_sixaxis_entry.gyro = gyro1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -244,6 +244,24 @@ private:
|
||||
};
|
||||
static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size");
|
||||
|
||||
struct SixAxisStates {
|
||||
s64_le timestamp;
|
||||
INSERT_PADDING_WORDS(2);
|
||||
s64_le timestamp2;
|
||||
Common::Vec3f accel{};
|
||||
Common::Vec3f gyro{};
|
||||
INSERT_PADDING_WORDS(3);
|
||||
std::array<Common::Vec3f, 3> orientation{};
|
||||
s64_le always_one{1};
|
||||
};
|
||||
static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size");
|
||||
|
||||
struct SixAxisGeneric {
|
||||
CommonHeader common{};
|
||||
std::array<SixAxisStates, 17> sixaxis{};
|
||||
};
|
||||
static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size");
|
||||
|
||||
enum class ColorReadError : u32_le {
|
||||
ReadOk = 0,
|
||||
ColorDoesntExist = 1,
|
||||
@@ -292,9 +310,12 @@ private:
|
||||
NPadGeneric pokeball_states;
|
||||
NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be
|
||||
// relying on this for the time being
|
||||
INSERT_PADDING_BYTES(
|
||||
0x708 *
|
||||
6); // TODO(ogniK): SixAxis states, require more information before implementation
|
||||
SixAxisGeneric sixaxis_full;
|
||||
SixAxisGeneric sixaxis_handheld;
|
||||
SixAxisGeneric sixaxis_dual_left;
|
||||
SixAxisGeneric sixaxis_dual_right;
|
||||
SixAxisGeneric sixaxis_left;
|
||||
SixAxisGeneric sixaxis_right;
|
||||
NPadDevice device_type;
|
||||
NPadProperties properties;
|
||||
INSERT_PADDING_WORDS(1);
|
||||
@@ -326,6 +347,8 @@ private:
|
||||
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>,
|
||||
10>
|
||||
sticks;
|
||||
std::array<std::array<std::unique_ptr<Input::MotionDevice>, 2>, 10> motion_devices;
|
||||
bool sixaxis_sensors_enabled{true};
|
||||
std::vector<u32> supported_npad_id_types{};
|
||||
NpadHoldType hold_type{NpadHoldType::Vertical};
|
||||
// Each controller should have their own styleset changed event
|
||||
|
||||
@@ -324,11 +324,17 @@ enum class ControllerType {
|
||||
LeftJoycon,
|
||||
};
|
||||
|
||||
struct MotionRaw {
|
||||
bool enabled;
|
||||
std::string config;
|
||||
};
|
||||
|
||||
struct PlayerInput {
|
||||
bool connected;
|
||||
ControllerType type;
|
||||
ButtonsRaw buttons;
|
||||
AnalogsRaw analogs;
|
||||
std::array<MotionRaw, 2> motion_devices;
|
||||
|
||||
u32 body_color_right;
|
||||
u32 button_color_right;
|
||||
|
||||
@@ -231,6 +231,13 @@ const std::array<UISettings::Shortcut, 16> Config::default_hotkeys{{
|
||||
}};
|
||||
// clang-format on
|
||||
|
||||
const std::array<Settings::MotionRaw, 2> Config::default_motion_devices{{
|
||||
{false, std::string("engine:cemuhookudp,address:127.0.0.1,port:26760,pad_index:0,cx:0.0,cy:0.0,"
|
||||
"cz:0.0,sensitivity:1.0")},
|
||||
{false, std::string("engine:cemuhookudp,address:127.0.0.1,port:26760,pad_index:0,cx:0.0,cy:0.0,"
|
||||
"cz:0.0,sensitivity:1.0")},
|
||||
}};
|
||||
|
||||
void Config::ReadPlayerValues() {
|
||||
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
|
||||
auto& player = Settings::values.players[p];
|
||||
@@ -294,6 +301,26 @@ void Config::ReadPlayerValues() {
|
||||
player_analogs = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < player.motion_devices.size(); ++i) {
|
||||
const Settings::MotionRaw& default_param = default_motion_devices[i];
|
||||
auto& player_motion_device = player.motion_devices[i];
|
||||
|
||||
player_motion_device.config =
|
||||
qt_config
|
||||
->value(QStringLiteral("player_%1_motion_device%2").arg(p).arg(i),
|
||||
QString::fromStdString(default_param.config))
|
||||
.toString()
|
||||
.toStdString();
|
||||
player_motion_device.enabled =
|
||||
qt_config
|
||||
->value(QStringLiteral("player_%1_motion_device%2/enabled").arg(p).arg(i),
|
||||
default_param.enabled)
|
||||
.toBool();
|
||||
if (player_motion_device.config.empty()) {
|
||||
player_motion_device.config = default_param.config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::stable_partition(
|
||||
@@ -850,6 +877,16 @@ void Config::SavePlayerValues() {
|
||||
QString::fromStdString(player.analogs[i]),
|
||||
QString::fromStdString(default_param));
|
||||
}
|
||||
|
||||
for (int i = 0; i < player.motion_devices.size(); ++i) {
|
||||
const Settings::MotionRaw& default_param = default_motion_devices[i];
|
||||
const Settings::MotionRaw& player_motion_device = player.motion_devices[i];
|
||||
WriteSetting(QStringLiteral("player_%1_motion_device%2").arg(p).arg(i),
|
||||
QString::fromStdString(player_motion_device.config),
|
||||
QString::fromStdString(default_param.config));
|
||||
WriteSetting(QStringLiteral("player_%1_motion_device%2/enabled").arg(p).arg(i),
|
||||
player_motion_device.enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ public:
|
||||
static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys;
|
||||
static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods;
|
||||
static const std::array<UISettings::Shortcut, 16> default_hotkeys;
|
||||
static const std::array<Settings::MotionRaw, 2> default_motion_devices;
|
||||
|
||||
private:
|
||||
void ReadValues();
|
||||
|
||||
Reference in New Issue
Block a user