mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
289 lines
8.2 KiB
C++
289 lines
8.2 KiB
C++
#include "stdafx.h"
|
|
#include "pad_motion_settings_dialog.h"
|
|
|
|
#include <QComboBox>
|
|
#include <thread>
|
|
|
|
LOG_CHANNEL(cfg_log, "CFG");
|
|
|
|
pad_motion_settings_dialog::pad_motion_settings_dialog(QDialog* parent, std::shared_ptr<PadHandlerBase> handler, cfg_player* cfg)
|
|
: QDialog(parent)
|
|
, ui(new Ui::pad_motion_settings_dialog)
|
|
, m_handler(handler)
|
|
, m_cfg(cfg)
|
|
{
|
|
ui->setupUi(this);
|
|
setModal(true);
|
|
|
|
ensure(m_handler);
|
|
ensure(m_cfg);
|
|
|
|
cfg_pad& pad = m_cfg->config;
|
|
|
|
m_preview_sliders = {{ ui->slider_x, ui->slider_y, ui->slider_z, ui->slider_g }};
|
|
m_preview_labels = {{ ui->label_x, ui->label_y, ui->label_z, ui->label_g }};
|
|
m_axis_names = {{ ui->combo_x, ui->combo_y, ui->combo_z, ui->combo_g }};
|
|
m_mirrors = {{ ui->mirror_x, ui->mirror_y, ui->mirror_z, ui->mirror_g }};
|
|
m_shifts = {{ ui->shift_x, ui->shift_y, ui->shift_z, ui->shift_g }};
|
|
m_config_entries = {{ &pad.motion_sensor_x, &pad.motion_sensor_y, &pad.motion_sensor_z, &pad.motion_sensor_g }};
|
|
|
|
for (usz i = 0; i < m_preview_sliders.size(); i++)
|
|
{
|
|
m_preview_sliders[i]->setRange(0, 1023);
|
|
m_preview_labels[i]->setText("0");
|
|
}
|
|
|
|
#if HAVE_LIBEVDEV
|
|
const bool has_device_list = m_handler->m_type == pad_handler::evdev;
|
|
#else
|
|
const bool has_device_list = false;
|
|
#endif
|
|
|
|
if (has_device_list)
|
|
{
|
|
// Combobox: Motion Devices
|
|
m_device_name = m_cfg->buddy_device.to_string();
|
|
|
|
ui->cb_choose_device->addItem(tr("Disabled"), QVariant::fromValue(pad_device_info{}));
|
|
|
|
const std::vector<pad_list_entry> device_list = m_handler->list_devices();
|
|
for (const pad_list_entry& device : device_list)
|
|
{
|
|
if (device.is_buddy_only)
|
|
{
|
|
const QString device_name = QString::fromStdString(device.name);
|
|
const QVariant user_data = QVariant::fromValue(pad_device_info{ device.name, true });
|
|
|
|
ui->cb_choose_device->addItem(device_name, user_data);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < ui->cb_choose_device->count(); i++)
|
|
{
|
|
const QVariant user_data = ui->cb_choose_device->itemData(i);
|
|
ensure(user_data.canConvert<pad_device_info>());
|
|
|
|
if (const pad_device_info info = user_data.value<pad_device_info>(); info.name == m_device_name)
|
|
{
|
|
ui->cb_choose_device->setCurrentIndex(i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
connect(ui->cb_choose_device, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &pad_motion_settings_dialog::change_device);
|
|
|
|
// Combobox: Configure Axis
|
|
m_motion_axis_list = m_handler->get_motion_axis_list();
|
|
|
|
for (const auto& [code, axis] : m_motion_axis_list)
|
|
{
|
|
const QString q_axis = QString::fromStdString(axis);
|
|
|
|
for (usz i = 0; i < m_axis_names.size(); i++)
|
|
{
|
|
m_axis_names[i]->addItem(q_axis, code);
|
|
|
|
if (m_config_entries[i]->axis.to_string() == axis)
|
|
{
|
|
m_axis_names[i]->setCurrentIndex(m_axis_names[i]->findData(code));
|
|
}
|
|
}
|
|
}
|
|
|
|
for (usz i = 0; i < m_axis_names.size(); i++)
|
|
{
|
|
const cfg_sensor* config = m_config_entries[i];
|
|
|
|
m_mirrors[i]->setChecked(config->mirrored.get());
|
|
|
|
m_shifts[i]->setRange(config->shift.min, config->shift.max);
|
|
m_shifts[i]->setValue(config->shift.get());
|
|
|
|
connect(m_mirrors[i], &QCheckBox::stateChanged, this, [this, i](int state)
|
|
{
|
|
std::lock_guard lock(m_config_mutex);
|
|
m_config_entries[i]->mirrored.set(state != Qt::Unchecked);
|
|
});
|
|
|
|
connect(m_shifts[i], QOverload<int>::of(&QSpinBox::valueChanged), this, [this, i](int value)
|
|
{
|
|
std::lock_guard lock(m_config_mutex);
|
|
m_config_entries[i]->shift.set(value);
|
|
});
|
|
|
|
connect(m_axis_names[i], QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this, i](int index)
|
|
{
|
|
std::lock_guard lock(m_config_mutex);
|
|
if (!m_config_entries[i]->axis.from_string(m_axis_names[i]->itemText(index).toStdString()))
|
|
{
|
|
cfg_log.error("Failed to convert motion axis string: %s", m_axis_names[i]->itemData(index).toString());
|
|
}
|
|
});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_device_name = m_cfg->device.to_string();
|
|
ui->gb_device->setVisible(false);
|
|
ui->cancelButton->setVisible(false);
|
|
for (usz i = 0; i < m_axis_names.size(); i++)
|
|
{
|
|
m_axis_names[i]->setVisible(false);
|
|
m_mirrors[i]->setVisible(false);
|
|
m_shifts[i]->setVisible(false);
|
|
}
|
|
}
|
|
|
|
// Use timer to display button input
|
|
connect(&m_timer_input, &QTimer::timeout, this, [this]()
|
|
{
|
|
motion_callback_data data;
|
|
{
|
|
std::lock_guard lock(m_input_mutex);
|
|
data = m_motion_callback_data;
|
|
m_motion_callback_data.has_new_data = false;
|
|
}
|
|
|
|
if (data.has_new_data)
|
|
{
|
|
// Starting with 1 because the first entry is the Disabled entry.
|
|
for (int i = 1; i < ui->cb_choose_device->count(); i++)
|
|
{
|
|
const QVariant user_data = ui->cb_choose_device->itemData(i);
|
|
ensure(user_data.canConvert<pad_device_info>());
|
|
|
|
if (const pad_device_info info = user_data.value<pad_device_info>(); info.name == data.pad_name)
|
|
{
|
|
switch_buddy_pad_info(i, info, data.success);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (usz i = 0; i < data.preview_values.size(); i++)
|
|
{
|
|
m_preview_sliders[i]->setValue(data.preview_values[i]);
|
|
m_preview_labels[i]->setText(QString::number(data.preview_values[i]));
|
|
}
|
|
}
|
|
});
|
|
m_timer_input.start(1);
|
|
|
|
// Use thread to get button input
|
|
m_input_thread = std::make_unique<named_thread<std::function<void()>>>("UI Pad Motion Thread", [this]()
|
|
{
|
|
while (thread_ctrl::state() != thread_state::aborting)
|
|
{
|
|
thread_ctrl::wait_for(1000);
|
|
|
|
if (m_input_thread_state != input_thread_state::active)
|
|
{
|
|
if (m_input_thread_state == input_thread_state::pausing)
|
|
{
|
|
m_input_thread_state = input_thread_state::paused;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
std::array<AnalogSensor, 4> sensors{};
|
|
{
|
|
std::lock_guard lock(m_config_mutex);
|
|
for (usz i = 0; i < sensors.size(); i++)
|
|
{
|
|
AnalogSensor& sensor = sensors[i];
|
|
const cfg_sensor* config = m_config_entries[i];
|
|
const std::string cfgname = config->axis.to_string();
|
|
for (const auto& [code, name] : m_motion_axis_list)
|
|
{
|
|
if (cfgname == name)
|
|
{
|
|
sensor.m_keyCode = code;
|
|
sensor.m_mirrored = config->mirrored.get();
|
|
sensor.m_shift = config->shift.get();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_handler->get_motion_sensors(m_device_name,
|
|
[this](std::string pad_name, motion_preview_values preview_values)
|
|
{
|
|
std::lock_guard lock(m_input_mutex);
|
|
m_motion_callback_data.pad_name = std::move(pad_name);
|
|
m_motion_callback_data.preview_values = std::move(preview_values);
|
|
m_motion_callback_data.has_new_data = true;
|
|
m_motion_callback_data.success = true;
|
|
},
|
|
[this](std::string pad_name, motion_preview_values preview_values)
|
|
{
|
|
std::lock_guard lock(m_input_mutex);
|
|
m_motion_callback_data.pad_name = std::move(pad_name);
|
|
m_motion_callback_data.preview_values = std::move(preview_values);
|
|
m_motion_callback_data.has_new_data = true;
|
|
m_motion_callback_data.success = false;
|
|
},
|
|
m_motion_callback_data.preview_values, sensors);
|
|
}
|
|
});
|
|
start_input_thread();
|
|
}
|
|
|
|
pad_motion_settings_dialog::~pad_motion_settings_dialog()
|
|
{
|
|
if (m_input_thread)
|
|
{
|
|
m_input_thread_state = input_thread_state::pausing;
|
|
auto& thread = *m_input_thread;
|
|
thread = thread_state::aborting;
|
|
thread();
|
|
}
|
|
}
|
|
|
|
void pad_motion_settings_dialog::change_device(int index)
|
|
{
|
|
if (index < 0)
|
|
return;
|
|
|
|
const QVariant user_data = ui->cb_choose_device->itemData(index);
|
|
ensure(user_data.canConvert<pad_device_info>());
|
|
|
|
const pad_device_info info = user_data.value<pad_device_info>();
|
|
|
|
if (!m_cfg->buddy_device.from_string(info.name))
|
|
{
|
|
cfg_log.error("Failed to convert motion device string: %s", info.name);
|
|
}
|
|
|
|
m_device_name = m_cfg->buddy_device.to_string();
|
|
}
|
|
|
|
void pad_motion_settings_dialog::switch_buddy_pad_info(int index, pad_device_info info, bool is_connected)
|
|
{
|
|
if (index >= 0 && info.is_connected != is_connected)
|
|
{
|
|
info.is_connected = is_connected;
|
|
|
|
ui->cb_choose_device->setItemData(index, QVariant::fromValue(info));
|
|
ui->cb_choose_device->setItemText(index, is_connected ? QString::fromStdString(info.name) : (QString::fromStdString(info.name) + Disconnected_suffix));
|
|
}
|
|
}
|
|
|
|
void pad_motion_settings_dialog::start_input_thread()
|
|
{
|
|
m_input_thread_state = input_thread_state::active;
|
|
}
|
|
|
|
void pad_motion_settings_dialog::pause_input_thread()
|
|
{
|
|
if (m_input_thread)
|
|
{
|
|
m_input_thread_state = input_thread_state::pausing;
|
|
|
|
while (m_input_thread_state != input_thread_state::paused)
|
|
{
|
|
std::this_thread::sleep_for(1ms);
|
|
}
|
|
}
|
|
}
|