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,
|
std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
|
||||||
players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
|
players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
|
||||||
sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>);
|
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;
|
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;
|
const auto& controller_type = connected_controllers[i].type;
|
||||||
|
|
||||||
if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
|
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];
|
npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
|
||||||
auto& libnx_entry = npad.libnx.npad[npad.libnx.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;
|
libnx_entry.connection_status.raw = 0;
|
||||||
|
|
||||||
switch (controller_type) {
|
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.pad_states.raw = pad_state.pad_states.raw;
|
||||||
handheld_entry.pad.l_stick = pad_state.l_stick;
|
handheld_entry.pad.l_stick = pad_state.l_stick;
|
||||||
handheld_entry.pad.r_stick = pad_state.r_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;
|
break;
|
||||||
case NPadControllerType::JoyDual:
|
case NPadControllerType::JoyDual:
|
||||||
dual_entry.connection_status.raw = 0;
|
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.pad_states.raw = pad_state.pad_states.raw;
|
||||||
dual_entry.pad.l_stick = pad_state.l_stick;
|
dual_entry.pad.l_stick = pad_state.l_stick;
|
||||||
dual_entry.pad.r_stick = pad_state.r_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;
|
break;
|
||||||
case NPadControllerType::JoyLeft:
|
case NPadControllerType::JoyLeft:
|
||||||
left_entry.connection_status.raw = 0;
|
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.pad_states.raw = pad_state.pad_states.raw;
|
||||||
left_entry.pad.l_stick = pad_state.l_stick;
|
left_entry.pad.l_stick = pad_state.l_stick;
|
||||||
left_entry.pad.r_stick = pad_state.r_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;
|
break;
|
||||||
case NPadControllerType::JoyRight:
|
case NPadControllerType::JoyRight:
|
||||||
right_entry.connection_status.raw = 0;
|
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.pad_states.raw = pad_state.pad_states.raw;
|
||||||
right_entry.pad.l_stick = pad_state.l_stick;
|
right_entry.pad.l_stick = pad_state.l_stick;
|
||||||
right_entry.pad.r_stick = pad_state.r_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;
|
break;
|
||||||
case NPadControllerType::Pokeball:
|
case NPadControllerType::Pokeball:
|
||||||
pokeball_entry.connection_status.raw = 0;
|
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.pad_states.raw = pad_state.pad_states.raw;
|
||||||
main_controller.pad.l_stick = pad_state.l_stick;
|
main_controller.pad.l_stick = pad_state.l_stick;
|
||||||
main_controller.pad.r_stick = pad_state.r_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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -244,6 +244,24 @@ private:
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size");
|
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 {
|
enum class ColorReadError : u32_le {
|
||||||
ReadOk = 0,
|
ReadOk = 0,
|
||||||
ColorDoesntExist = 1,
|
ColorDoesntExist = 1,
|
||||||
@@ -292,9 +310,12 @@ private:
|
|||||||
NPadGeneric pokeball_states;
|
NPadGeneric pokeball_states;
|
||||||
NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be
|
NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be
|
||||||
// relying on this for the time being
|
// relying on this for the time being
|
||||||
INSERT_PADDING_BYTES(
|
SixAxisGeneric sixaxis_full;
|
||||||
0x708 *
|
SixAxisGeneric sixaxis_handheld;
|
||||||
6); // TODO(ogniK): SixAxis states, require more information before implementation
|
SixAxisGeneric sixaxis_dual_left;
|
||||||
|
SixAxisGeneric sixaxis_dual_right;
|
||||||
|
SixAxisGeneric sixaxis_left;
|
||||||
|
SixAxisGeneric sixaxis_right;
|
||||||
NPadDevice device_type;
|
NPadDevice device_type;
|
||||||
NPadProperties properties;
|
NPadProperties properties;
|
||||||
INSERT_PADDING_WORDS(1);
|
INSERT_PADDING_WORDS(1);
|
||||||
@@ -326,6 +347,8 @@ private:
|
|||||||
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>,
|
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>,
|
||||||
10>
|
10>
|
||||||
sticks;
|
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{};
|
std::vector<u32> supported_npad_id_types{};
|
||||||
NpadHoldType hold_type{NpadHoldType::Vertical};
|
NpadHoldType hold_type{NpadHoldType::Vertical};
|
||||||
// Each controller should have their own styleset changed event
|
// Each controller should have their own styleset changed event
|
||||||
|
|||||||
@@ -324,11 +324,17 @@ enum class ControllerType {
|
|||||||
LeftJoycon,
|
LeftJoycon,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MotionRaw {
|
||||||
|
bool enabled;
|
||||||
|
std::string config;
|
||||||
|
};
|
||||||
|
|
||||||
struct PlayerInput {
|
struct PlayerInput {
|
||||||
bool connected;
|
bool connected;
|
||||||
ControllerType type;
|
ControllerType type;
|
||||||
ButtonsRaw buttons;
|
ButtonsRaw buttons;
|
||||||
AnalogsRaw analogs;
|
AnalogsRaw analogs;
|
||||||
|
std::array<MotionRaw, 2> motion_devices;
|
||||||
|
|
||||||
u32 body_color_right;
|
u32 body_color_right;
|
||||||
u32 button_color_right;
|
u32 button_color_right;
|
||||||
|
|||||||
@@ -231,6 +231,13 @@ const std::array<UISettings::Shortcut, 16> Config::default_hotkeys{{
|
|||||||
}};
|
}};
|
||||||
// clang-format on
|
// 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() {
|
void Config::ReadPlayerValues() {
|
||||||
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
|
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
|
||||||
auto& player = Settings::values.players[p];
|
auto& player = Settings::values.players[p];
|
||||||
@@ -294,6 +301,26 @@ void Config::ReadPlayerValues() {
|
|||||||
player_analogs = default_param;
|
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(
|
std::stable_partition(
|
||||||
@@ -850,6 +877,16 @@ void Config::SavePlayerValues() {
|
|||||||
QString::fromStdString(player.analogs[i]),
|
QString::fromStdString(player.analogs[i]),
|
||||||
QString::fromStdString(default_param));
|
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::NumKeyboardKeys> default_keyboard_keys;
|
||||||
static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods;
|
static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods;
|
||||||
static const std::array<UISettings::Shortcut, 16> default_hotkeys;
|
static const std::array<UISettings::Shortcut, 16> default_hotkeys;
|
||||||
|
static const std::array<Settings::MotionRaw, 2> default_motion_devices;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReadValues();
|
void ReadValues();
|
||||||
|
|||||||
Reference in New Issue
Block a user