mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-14 10:21:21 +00:00
input/qt: allow to map mouse buttons in the guncon config
This commit is contained in:
parent
5a08ae4f41
commit
32a938abd2
@ -220,6 +220,32 @@ void usb_device_guncon3::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint,
|
||||
return;
|
||||
}
|
||||
|
||||
const auto input_callback = [&gc](guncon3_btn btn, u16 value, bool pressed)
|
||||
{
|
||||
if (!pressed)
|
||||
return;
|
||||
|
||||
switch (btn)
|
||||
{
|
||||
case guncon3_btn::trigger: gc.btn_trigger |= 1; break;
|
||||
case guncon3_btn::a1: gc.btn_a1 |= 1; break;
|
||||
case guncon3_btn::a2: gc.btn_a2 |= 1; break;
|
||||
case guncon3_btn::a3: gc.btn_a3 |= 1; break;
|
||||
case guncon3_btn::b1: gc.btn_b1 |= 1; break;
|
||||
case guncon3_btn::b2: gc.btn_b2 |= 1; break;
|
||||
case guncon3_btn::b3: gc.btn_b3 |= 1; break;
|
||||
case guncon3_btn::c1: gc.btn_c1 |= 1; break;
|
||||
case guncon3_btn::c2: gc.btn_c2 |= 1; break;
|
||||
case guncon3_btn::as_x: gc.stick_ax = static_cast<uint8_t>(value); break;
|
||||
case guncon3_btn::as_y: gc.stick_ay = static_cast<uint8_t>(value); break;
|
||||
case guncon3_btn::bs_x: gc.stick_bx = static_cast<uint8_t>(value); break;
|
||||
case guncon3_btn::bs_y: gc.stick_by = static_cast<uint8_t>(value); break;
|
||||
case guncon3_btn::count: break;
|
||||
}
|
||||
};
|
||||
|
||||
const auto& cfg = ::at32(g_cfg_guncon3.players, m_controller_index);
|
||||
|
||||
{
|
||||
std::lock_guard lock(pad::g_pad_mutex);
|
||||
const auto gamepad_handler = pad::get_current_handler();
|
||||
@ -227,30 +253,7 @@ void usb_device_guncon3::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint,
|
||||
const auto& pad = ::at32(pads, m_controller_index);
|
||||
if (pad->m_port_status & CELL_PAD_STATUS_CONNECTED)
|
||||
{
|
||||
const auto& cfg = ::at32(g_cfg_guncon3.players, m_controller_index);
|
||||
cfg->handle_input(pad, true, [&](guncon3_btn btn, u16 value, bool pressed)
|
||||
{
|
||||
if (!pressed)
|
||||
return;
|
||||
|
||||
switch (btn)
|
||||
{
|
||||
case guncon3_btn::trigger: gc.btn_trigger |= 1; break;
|
||||
case guncon3_btn::a1: gc.btn_a1 |= 1; break;
|
||||
case guncon3_btn::a2: gc.btn_a2 |= 1; break;
|
||||
case guncon3_btn::a3: gc.btn_a3 |= 1; break;
|
||||
case guncon3_btn::b1: gc.btn_b1 |= 1; break;
|
||||
case guncon3_btn::b2: gc.btn_b2 |= 1; break;
|
||||
case guncon3_btn::b3: gc.btn_b3 |= 1; break;
|
||||
case guncon3_btn::c1: gc.btn_c1 |= 1; break;
|
||||
case guncon3_btn::c2: gc.btn_c2 |= 1; break;
|
||||
case guncon3_btn::as_x: gc.stick_ax = static_cast<uint8_t>(value); break;
|
||||
case guncon3_btn::as_y: gc.stick_ay = static_cast<uint8_t>(value); break;
|
||||
case guncon3_btn::bs_x: gc.stick_bx = static_cast<uint8_t>(value); break;
|
||||
case guncon3_btn::bs_y: gc.stick_by = static_cast<uint8_t>(value); break;
|
||||
case guncon3_btn::count: break;
|
||||
}
|
||||
});
|
||||
cfg->handle_input(pad, true, input_callback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,7 +280,7 @@ void usb_device_guncon3::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint,
|
||||
gc.gun_x = (mouse_data.x_pos * USHRT_MAX / mouse_data.x_max) - SHRT_MAX;
|
||||
gc.gun_y = (mouse_data.y_pos * -USHRT_MAX / mouse_data.y_max) + SHRT_MAX;
|
||||
|
||||
gc.btn_trigger |= !!(mouse_data.buttons & CELL_MOUSE_BUTTON_1);
|
||||
cfg->handle_input(mouse_data, true, input_callback);
|
||||
}
|
||||
|
||||
guncon3_encode(&gc, buf, m_key.data());
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "Utilities/Config.h"
|
||||
#include "Utilities/mutex.h"
|
||||
#include "pad_types.h"
|
||||
#include "MouseHandler.h"
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
@ -106,6 +107,21 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void handle_input(const Mouse& mouse, bool press_only, const std::function<void(T, u16, bool)>& func) const
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
const MouseButtonCodes cell_code = get_mouse_button_code(i);
|
||||
if ((mouse.buttons & cell_code))
|
||||
{
|
||||
const pad_button button = static_cast<pad_button>(static_cast<int>(pad_button::mouse_button_1) + i);
|
||||
const u32 offset = pad_button_offset(button);
|
||||
const u32 keycode = pad_button_keycode(button);
|
||||
handle_input(func, offset, keycode, 255, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable shared_mutex m_mutex;
|
||||
std::vector<cfg_pad_btn<T>*> buttons;
|
||||
|
@ -38,6 +38,14 @@ void fmt_class_string<pad_button>::format(std::string& out, u64 arg)
|
||||
case pad_button::rs_x: return "Right Stick X-Axis";
|
||||
case pad_button::rs_y: return "Right Stick Y-Axis";
|
||||
case pad_button::pad_button_max_enum: return unknown;
|
||||
case pad_button::mouse_button_1: return "Mouse Button 1";
|
||||
case pad_button::mouse_button_2: return "Mouse Button 2";
|
||||
case pad_button::mouse_button_3: return "Mouse Button 3";
|
||||
case pad_button::mouse_button_4: return "Mouse Button 4";
|
||||
case pad_button::mouse_button_5: return "Mouse Button 5";
|
||||
case pad_button::mouse_button_6: return "Mouse Button 6";
|
||||
case pad_button::mouse_button_7: return "Mouse Button 7";
|
||||
case pad_button::mouse_button_8: return "Mouse Button 8";
|
||||
}
|
||||
|
||||
return unknown;
|
||||
@ -77,7 +85,16 @@ u32 pad_button_offset(pad_button button)
|
||||
case pad_button::rs_right: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X;
|
||||
case pad_button::rs_x: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X;
|
||||
case pad_button::rs_y: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y;
|
||||
case pad_button::pad_button_max_enum: return 0;
|
||||
case pad_button::pad_button_max_enum:
|
||||
case pad_button::mouse_button_1:
|
||||
case pad_button::mouse_button_2:
|
||||
case pad_button::mouse_button_3:
|
||||
case pad_button::mouse_button_4:
|
||||
case pad_button::mouse_button_5:
|
||||
case pad_button::mouse_button_6:
|
||||
case pad_button::mouse_button_7:
|
||||
case pad_button::mouse_button_8:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -116,6 +133,14 @@ u32 pad_button_keycode(pad_button button)
|
||||
case pad_button::rs_x: return static_cast<u32>(axis_direction::both);
|
||||
case pad_button::rs_y: return static_cast<u32>(axis_direction::both);
|
||||
case pad_button::pad_button_max_enum: return 0;
|
||||
case pad_button::mouse_button_1: return 1;
|
||||
case pad_button::mouse_button_2: return 2;
|
||||
case pad_button::mouse_button_3: return 3;
|
||||
case pad_button::mouse_button_4: return 4;
|
||||
case pad_button::mouse_button_5: return 5;
|
||||
case pad_button::mouse_button_6: return 6;
|
||||
case pad_button::mouse_button_7: return 7;
|
||||
case pad_button::mouse_button_8: return 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -41,7 +41,17 @@ enum class pad_button : u8
|
||||
rs_x,
|
||||
rs_y,
|
||||
|
||||
pad_button_max_enum
|
||||
pad_button_max_enum,
|
||||
|
||||
// Special buttons for mouse input
|
||||
mouse_button_1,
|
||||
mouse_button_2,
|
||||
mouse_button_3,
|
||||
mouse_button_4,
|
||||
mouse_button_5,
|
||||
mouse_button_6,
|
||||
mouse_button_7,
|
||||
mouse_button_8,
|
||||
};
|
||||
|
||||
u32 pad_button_offset(pad_button button);
|
||||
|
@ -2,6 +2,38 @@
|
||||
#include "raw_mouse_config.h"
|
||||
#include "Emu/Io/MouseHandler.h"
|
||||
|
||||
std::string mouse_button_id(int code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CELL_MOUSE_BUTTON_1: return "Button 1";
|
||||
case CELL_MOUSE_BUTTON_2: return "Button 2";
|
||||
case CELL_MOUSE_BUTTON_3: return "Button 3";
|
||||
case CELL_MOUSE_BUTTON_4: return "Button 4";
|
||||
case CELL_MOUSE_BUTTON_5: return "Button 5";
|
||||
case CELL_MOUSE_BUTTON_6: return "Button 6";
|
||||
case CELL_MOUSE_BUTTON_7: return "Button 7";
|
||||
case CELL_MOUSE_BUTTON_8: return "Button 8";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
cfg::string& raw_mouse_config::get_button_by_index(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return mouse_button_1;
|
||||
case 1: return mouse_button_2;
|
||||
case 2: return mouse_button_3;
|
||||
case 3: return mouse_button_4;
|
||||
case 4: return mouse_button_5;
|
||||
case 5: return mouse_button_6;
|
||||
case 6: return mouse_button_7;
|
||||
case 7: return mouse_button_8;
|
||||
default: fmt::throw_exception("Invalid index %d", index);
|
||||
}
|
||||
}
|
||||
|
||||
cfg::string& raw_mouse_config::get_button(int code)
|
||||
{
|
||||
switch (code)
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
LOG_CHANNEL(cfg_log, "CFG");
|
||||
|
||||
std::string mouse_button_id(int code);
|
||||
|
||||
struct raw_mouse_config : cfg::node
|
||||
{
|
||||
public:
|
||||
@ -25,6 +27,7 @@ public:
|
||||
cfg::string mouse_button_7{this, "Button 7", "No Button"};
|
||||
cfg::string mouse_button_8{this, "Button 8", "No Button"};
|
||||
|
||||
cfg::string& get_button_by_index(int index);
|
||||
cfg::string& get_button(int code);
|
||||
};
|
||||
|
||||
|
@ -116,12 +116,6 @@ void raw_mouse::update_values(const RAWMOUSE& state)
|
||||
// Update window handle and size
|
||||
update_window_handle();
|
||||
|
||||
// Check if the window handle is active
|
||||
if (!m_window_handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto get_button_pressed = [this](u8 button, int button_flags)
|
||||
{
|
||||
const auto& [down, up] = ::at32(m_buttons, button);
|
||||
@ -130,10 +124,12 @@ void raw_mouse::update_values(const RAWMOUSE& state)
|
||||
if ((button_flags & down))
|
||||
{
|
||||
m_handler->Button(m_index, button, true);
|
||||
m_handler->mouse_press_callback(m_device_name, button, true);
|
||||
}
|
||||
else if ((button_flags & up))
|
||||
{
|
||||
m_handler->Button(m_index, button, false);
|
||||
m_handler->mouse_press_callback(m_device_name, button, false);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -69,6 +69,19 @@ public:
|
||||
|
||||
const std::map<void*, raw_mouse>& get_mice() const { return m_raw_mice; };
|
||||
|
||||
void set_mouse_press_callback(std::function<void(const std::string&, s32, bool)> cb)
|
||||
{
|
||||
m_mouse_press_callback = std::move(cb);
|
||||
}
|
||||
|
||||
void mouse_press_callback(const std::string& device_name, s32 cell_code, bool pressed)
|
||||
{
|
||||
if (m_mouse_press_callback)
|
||||
{
|
||||
m_mouse_press_callback(device_name, cell_code, pressed);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void handle_native_event(const MSG& msg);
|
||||
#endif
|
||||
@ -78,4 +91,5 @@ private:
|
||||
|
||||
bool m_ignore_config = false;
|
||||
std::map<void*, raw_mouse> m_raw_mice;
|
||||
std::function<void(const std::string&, s32, bool)> m_mouse_press_callback;
|
||||
};
|
||||
|
@ -162,16 +162,18 @@ void basic_mouse_settings_dialog::reset_config()
|
||||
|
||||
void basic_mouse_settings_dialog::on_button_click(int id)
|
||||
{
|
||||
if (id <= 0)
|
||||
if (id < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto but : m_buttons->buttons())
|
||||
{
|
||||
but->setEnabled(false);
|
||||
but->setFocusPolicy(Qt::ClickFocus);
|
||||
}
|
||||
|
||||
m_button_box->setEnabled(false);
|
||||
for (auto but : m_button_box->buttons())
|
||||
{
|
||||
but->setFocusPolicy(Qt::ClickFocus);
|
||||
@ -185,19 +187,12 @@ void basic_mouse_settings_dialog::on_button_click(int id)
|
||||
button->grabMouse();
|
||||
}
|
||||
|
||||
// Disable all buttons
|
||||
m_button_box->setEnabled(false);
|
||||
for (auto button : m_buttons->buttons())
|
||||
{
|
||||
button->setEnabled(false);
|
||||
}
|
||||
|
||||
m_remap_timer.start(1000);
|
||||
}
|
||||
|
||||
void basic_mouse_settings_dialog::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (m_button_id <= 0)
|
||||
if (m_button_id < 0)
|
||||
{
|
||||
// We are not remapping a button, so pass the event to the base class.
|
||||
QDialog::mouseReleaseEvent(event);
|
||||
@ -222,7 +217,7 @@ bool basic_mouse_settings_dialog::eventFilter(QObject* object, QEvent* event)
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
// On right click clear binding if we are not remapping pad button
|
||||
if (m_button_id <= 0)
|
||||
if (m_button_id < 0)
|
||||
{
|
||||
QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
|
||||
if (const auto button = qobject_cast<QPushButton*>(object); button && mouse_event->button() == Qt::RightButton)
|
||||
@ -254,7 +249,7 @@ void basic_mouse_settings_dialog::reactivate_buttons()
|
||||
m_remap_timer.stop();
|
||||
m_seconds = MAX_SECONDS;
|
||||
|
||||
if (m_button_id <= 0)
|
||||
if (m_button_id < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -265,19 +260,19 @@ void basic_mouse_settings_dialog::reactivate_buttons()
|
||||
button->releaseMouse();
|
||||
}
|
||||
|
||||
m_button_id = 0;
|
||||
m_button_id = -1;
|
||||
|
||||
// Enable all buttons
|
||||
m_button_box->setEnabled(true);
|
||||
|
||||
for (auto but : m_button_box->buttons())
|
||||
{
|
||||
but->setFocusPolicy(Qt::StrongFocus);
|
||||
}
|
||||
|
||||
for (auto but : m_buttons->buttons())
|
||||
{
|
||||
but->setEnabled(true);
|
||||
but->setFocusPolicy(Qt::StrongFocus);
|
||||
}
|
||||
|
||||
for (auto but : m_button_box->buttons())
|
||||
{
|
||||
but->setFocusPolicy(Qt::StrongFocus);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ private:
|
||||
QDialogButtonBox* m_button_box = nullptr;
|
||||
QButtonGroup* m_buttons = nullptr;
|
||||
std::unordered_map<int, QPushButton*> m_push_buttons;
|
||||
u32 m_button_id = 0;
|
||||
int m_button_id = -1;
|
||||
|
||||
// Backup for standard button palette
|
||||
QPalette m_palette;
|
||||
|
@ -158,6 +158,18 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
|
||||
combo->setItemData(index, i, button_role::emulated_button);
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<T, guncon3_btn>)
|
||||
{
|
||||
for (int p = static_cast<int>(pad_button::mouse_button_1); p <= static_cast<int>(pad_button::mouse_button_8); p++)
|
||||
{
|
||||
const QString translated = localized_emu::translated_pad_button(static_cast<pad_button>(p));
|
||||
combo->addItem(translated);
|
||||
const int index = combo->findText(translated);
|
||||
combo->setItemData(index, p, button_role::button);
|
||||
combo->setItemData(index, i, button_role::emulated_button);
|
||||
}
|
||||
}
|
||||
|
||||
pad_button saved_btn_id = pad_button::pad_button_max_enum;
|
||||
switch (m_type)
|
||||
{
|
||||
|
@ -1113,7 +1113,7 @@ void gui_application::OnAppStateChanged(Qt::ApplicationState state)
|
||||
bool gui_application::native_event_filter::nativeEventFilter([[maybe_unused]] const QByteArray& eventType, [[maybe_unused]] void* message, [[maybe_unused]] qintptr* result)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!Emu.IsRunning())
|
||||
if (!Emu.IsRunning() && !g_raw_mouse_handler)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -36,6 +36,14 @@ QString localized_emu::translated_pad_button(pad_button btn)
|
||||
case pad_button::rs_x: return tr("Right Stick X-Axis");
|
||||
case pad_button::rs_y: return tr("Right Stick Y-Axis");
|
||||
case pad_button::pad_button_max_enum: return "";
|
||||
case pad_button::mouse_button_1: return tr("Mouse Button 1");
|
||||
case pad_button::mouse_button_2: return tr("Mouse Button 2");
|
||||
case pad_button::mouse_button_3: return tr("Mouse Button 3");
|
||||
case pad_button::mouse_button_4: return tr("Mouse Button 4");
|
||||
case pad_button::mouse_button_5: return tr("Mouse Button 5");
|
||||
case pad_button::mouse_button_6: return tr("Mouse Button 6");
|
||||
case pad_button::mouse_button_7: return tr("Mouse Button 7");
|
||||
case pad_button::mouse_button_8: return tr("Mouse Button 8");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
@ -6,17 +6,11 @@
|
||||
#include "Input/raw_mouse_handler.h"
|
||||
#include "util/asm.hpp"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGroupBox>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
enum button_role
|
||||
{
|
||||
button_name = Qt::UserRole,
|
||||
button_code
|
||||
};
|
||||
constexpr u32 button_count = 8;
|
||||
|
||||
raw_mouse_settings_dialog::raw_mouse_settings_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
@ -29,30 +23,30 @@ raw_mouse_settings_dialog::raw_mouse_settings_dialog(QWidget* parent)
|
||||
|
||||
QVBoxLayout* v_layout = new QVBoxLayout(this);
|
||||
|
||||
QTabWidget* tabs = new QTabWidget();
|
||||
tabs->setUsesScrollButtons(false);
|
||||
m_tab_widget = new QTabWidget();
|
||||
m_tab_widget->setUsesScrollButtons(false);
|
||||
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox(this);
|
||||
buttons->setStandardButtons(QDialogButtonBox::Apply | QDialogButtonBox::Cancel | QDialogButtonBox::Save | QDialogButtonBox::RestoreDefaults);
|
||||
m_button_box = new QDialogButtonBox(this);
|
||||
m_button_box->setStandardButtons(QDialogButtonBox::Apply | QDialogButtonBox::Cancel | QDialogButtonBox::Save | QDialogButtonBox::RestoreDefaults);
|
||||
|
||||
connect(buttons, &QDialogButtonBox::clicked, this, [this, buttons](QAbstractButton* button)
|
||||
connect(m_button_box, &QDialogButtonBox::clicked, this, [this](QAbstractButton* button)
|
||||
{
|
||||
if (button == buttons->button(QDialogButtonBox::Apply))
|
||||
if (button == m_button_box->button(QDialogButtonBox::Apply))
|
||||
{
|
||||
g_cfg_raw_mouse.save();
|
||||
}
|
||||
else if (button == buttons->button(QDialogButtonBox::Save))
|
||||
else if (button == m_button_box->button(QDialogButtonBox::Save))
|
||||
{
|
||||
g_cfg_raw_mouse.save();
|
||||
accept();
|
||||
}
|
||||
else if (button == buttons->button(QDialogButtonBox::RestoreDefaults))
|
||||
else if (button == m_button_box->button(QDialogButtonBox::RestoreDefaults))
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Confirm Reset"), tr("Reset settings of all players?")) != QMessageBox::Yes)
|
||||
return;
|
||||
reset_config();
|
||||
}
|
||||
else if (button == buttons->button(QDialogButtonBox::Cancel))
|
||||
else if (button == m_button_box->button(QDialogButtonBox::Cancel))
|
||||
{
|
||||
// Restore config
|
||||
if (!g_cfg_raw_mouse.load())
|
||||
@ -70,12 +64,58 @@ raw_mouse_settings_dialog::raw_mouse_settings_dialog(QWidget* parent)
|
||||
|
||||
g_raw_mouse_handler = std::make_unique<raw_mouse_handler>(true);
|
||||
g_raw_mouse_handler->Init(::size32(g_cfg_raw_mouse.players));
|
||||
g_raw_mouse_handler->set_mouse_press_callback([this](const std::string& device_name, s32 cell_code, bool pressed)
|
||||
{
|
||||
mouse_press(device_name, cell_code, pressed);
|
||||
});
|
||||
|
||||
add_tabs(tabs);
|
||||
m_buttons = new QButtonGroup(this);
|
||||
connect(m_buttons, &QButtonGroup::idClicked, this, &raw_mouse_settings_dialog::on_button_click);
|
||||
|
||||
v_layout->addWidget(tabs);
|
||||
v_layout->addWidget(buttons);
|
||||
connect(&m_remap_timer, &QTimer::timeout, this, [this]()
|
||||
{
|
||||
auto button = m_buttons->button(m_button_id);
|
||||
|
||||
if (--m_seconds <= 0)
|
||||
{
|
||||
if (button)
|
||||
{
|
||||
if (const int button_id = m_buttons->id(button); button_id >= 0)
|
||||
{
|
||||
auto& config = ::at32(g_cfg_raw_mouse.players, m_tab_widget->currentIndex());
|
||||
const std::string name = config->get_button_by_index(button_id).to_string();
|
||||
button->setText(name.empty() ? QStringLiteral("-") : QString::fromStdString(name));
|
||||
}
|
||||
}
|
||||
reactivate_buttons();
|
||||
return;
|
||||
}
|
||||
if (button)
|
||||
{
|
||||
button->setText(tr("[ Waiting %1 ]").arg(m_seconds));
|
||||
}
|
||||
});
|
||||
|
||||
connect(&m_mouse_release_timer, &QTimer::timeout, this, [this]()
|
||||
{
|
||||
m_mouse_release_timer.stop();
|
||||
m_disable_mouse_release_event = false;
|
||||
});
|
||||
|
||||
add_tabs(m_tab_widget);
|
||||
|
||||
v_layout->addWidget(m_tab_widget);
|
||||
v_layout->addWidget(m_button_box);
|
||||
setLayout(v_layout);
|
||||
|
||||
m_palette = m_push_buttons[0][CELL_MOUSE_BUTTON_1]->palette(); // save normal palette
|
||||
|
||||
connect(m_tab_widget, &QTabWidget::currentChanged, this, [this](int index)
|
||||
{
|
||||
handle_device_change(get_current_device_name(index));
|
||||
});
|
||||
|
||||
handle_device_change(get_current_device_name(0));
|
||||
}
|
||||
|
||||
raw_mouse_settings_dialog::~raw_mouse_settings_dialog()
|
||||
@ -87,7 +127,6 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs)
|
||||
{
|
||||
ensure(!!tabs);
|
||||
|
||||
constexpr u32 button_count = 8;
|
||||
constexpr u32 max_items_per_column = 6;
|
||||
int rows = button_count;
|
||||
|
||||
@ -98,11 +137,17 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs)
|
||||
|
||||
const usz players = g_cfg_raw_mouse.players.size();
|
||||
|
||||
m_combos.resize(players);
|
||||
m_push_buttons.resize(players);
|
||||
|
||||
ensure(g_raw_mouse_handler);
|
||||
const auto& mice = g_raw_mouse_handler->get_mice();
|
||||
|
||||
const auto insert_button = [this](int id, QPushButton* button)
|
||||
{
|
||||
m_buttons->addButton(button, id);
|
||||
button->installEventFilter(this);
|
||||
};
|
||||
|
||||
for (usz player = 0; player < players; player++)
|
||||
{
|
||||
QWidget* widget = new QWidget(this);
|
||||
@ -131,8 +176,12 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs)
|
||||
if (!data.isValid() || !data.canConvert<QString>())
|
||||
return;
|
||||
|
||||
const std::string device_name = data.toString().toStdString();
|
||||
|
||||
auto& config = ::at32(g_cfg_raw_mouse.players, player)->device;
|
||||
config.from_string(data.toString().toStdString());
|
||||
config.from_string(device_name);
|
||||
|
||||
handle_device_change(device_name);
|
||||
});
|
||||
|
||||
h_layout->addWidget(combo);
|
||||
@ -148,33 +197,13 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs)
|
||||
|
||||
QHBoxLayout* h_layout = new QHBoxLayout(this);
|
||||
QGroupBox* gb = new QGroupBox(translated_cell_button, this);
|
||||
QComboBox* combo = new QComboBox;
|
||||
QPushButton* pb = new QPushButton;
|
||||
|
||||
for (const auto& [name, btn] : raw_mouse_button_map)
|
||||
{
|
||||
const QString id = QString::fromStdString(name);
|
||||
const QString translated_id = id; // We could localize the id, but I am too lazy at the moment
|
||||
combo->addItem(translated_id);
|
||||
const int index = combo->findText(translated_id);
|
||||
combo->setItemData(index, id, button_role::button_name);
|
||||
combo->setItemData(index, cell_code, button_role::button_code);
|
||||
}
|
||||
insert_button(static_cast<int>(player * button_count + i), pb);
|
||||
|
||||
const std::string saved_btn = config->get_button(cell_code);
|
||||
|
||||
combo->setCurrentIndex(combo->findData(QString::fromStdString(saved_btn), button_role::button_name));
|
||||
|
||||
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this, player, cell_code, combo](int index)
|
||||
{
|
||||
if (index < 0 || !combo)
|
||||
return;
|
||||
|
||||
const QVariant data = combo->itemData(index, button_role::button_name);
|
||||
if (!data.isValid() || !data.canConvert<QString>())
|
||||
return;
|
||||
|
||||
::at32(g_cfg_raw_mouse.players, player)->get_button(cell_code).from_string(data.toString().toStdString());
|
||||
});
|
||||
pb->setText(saved_btn.empty() ? QStringLiteral("-") : QString::fromStdString(saved_btn));
|
||||
|
||||
if (row >= rows + first_row)
|
||||
{
|
||||
@ -182,8 +211,8 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs)
|
||||
col++;
|
||||
}
|
||||
|
||||
::at32(m_combos, player).push_back(combo);
|
||||
h_layout->addWidget(combo);
|
||||
m_push_buttons[player][cell_code] = pb;
|
||||
h_layout->addWidget(pb);
|
||||
gb->setLayout(h_layout);
|
||||
grid_layout->addWidget(gb, row, col);
|
||||
}
|
||||
@ -213,23 +242,17 @@ void raw_mouse_settings_dialog::reset_config()
|
||||
{
|
||||
g_cfg_raw_mouse.from_default();
|
||||
|
||||
for (usz player = 0; player < m_combos.size(); player++)
|
||||
for (usz player = 0; player < m_push_buttons.size(); player++)
|
||||
{
|
||||
auto& config = ::at32(g_cfg_raw_mouse.players, player);
|
||||
|
||||
for (QComboBox* combo : m_combos.at(player))
|
||||
for (auto& [cell_code, pb] : m_push_buttons[player])
|
||||
{
|
||||
if (!combo)
|
||||
if (!pb)
|
||||
continue;
|
||||
|
||||
const QVariant data = combo->itemData(0, button_role::button_code);
|
||||
if (!data.isValid() || !data.canConvert<int>())
|
||||
continue;
|
||||
|
||||
const int cell_code = data.toInt();
|
||||
const QString def_btn_id = QString::fromStdString(config->get_button(cell_code).def);
|
||||
|
||||
combo->setCurrentIndex(combo->findData(def_btn_id, button_role::button_name));
|
||||
const QString text = QString::fromStdString(config->get_button(cell_code).def);
|
||||
pb->setText(text.isEmpty() ? QStringLiteral("-") : text);
|
||||
}
|
||||
|
||||
if (QComboBox* combo = ::at32(m_device_combos, player))
|
||||
@ -243,3 +266,199 @@ void raw_mouse_settings_dialog::reset_config()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void raw_mouse_settings_dialog::mouse_press(const std::string& device_name, s32 cell_code, bool pressed)
|
||||
{
|
||||
if (m_button_id < 0 || pressed) // Let's only react to mouse releases
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const int player = m_tab_widget->currentIndex();
|
||||
const std::string current_device_name = get_current_device_name(player);
|
||||
|
||||
if (device_name != current_device_name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& config = ::at32(g_cfg_raw_mouse.players, m_tab_widget->currentIndex());
|
||||
config->get_button_by_index(m_button_id % button_count).from_string(mouse_button_id(cell_code));
|
||||
|
||||
if (auto button = m_buttons->button(m_button_id))
|
||||
{
|
||||
button->setText(localized_emu::translated_mouse_button(cell_code));
|
||||
}
|
||||
|
||||
reactivate_buttons();
|
||||
}
|
||||
|
||||
void raw_mouse_settings_dialog::handle_device_change(const std::string& device_name)
|
||||
{
|
||||
if (is_device_active(device_name))
|
||||
{
|
||||
reactivate_buttons();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto but : m_buttons->buttons())
|
||||
{
|
||||
but->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool raw_mouse_settings_dialog::is_device_active(const std::string& device_name)
|
||||
{
|
||||
if (!g_raw_mouse_handler || device_name.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& mice = g_raw_mouse_handler->get_mice();
|
||||
|
||||
return std::any_of(mice.cbegin(), mice.cend(), [&device_name](const auto& entry){ return entry.second.device_name() == device_name; });
|
||||
}
|
||||
|
||||
std::string raw_mouse_settings_dialog::get_current_device_name(int player)
|
||||
{
|
||||
if (player < 0)
|
||||
return {};
|
||||
|
||||
const QVariant data = ::at32(m_device_combos, player)->currentData();
|
||||
|
||||
if (!data.canConvert<QString>())
|
||||
return {};
|
||||
|
||||
return data.toString().toStdString();
|
||||
}
|
||||
|
||||
bool raw_mouse_settings_dialog::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
// On right click clear binding if we are not remapping pad button
|
||||
if (m_button_id < 0 && !m_disable_mouse_release_event)
|
||||
{
|
||||
QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
|
||||
if (const auto button = qobject_cast<QPushButton*>(object); button && mouse_event->button() == Qt::RightButton)
|
||||
{
|
||||
if (const int button_id = m_buttons->id(button); button_id >= 0)
|
||||
{
|
||||
button->setText(QStringLiteral("-"));
|
||||
auto& config = ::at32(g_cfg_raw_mouse.players, m_tab_widget->currentIndex());
|
||||
config->get_button_by_index(button_id).from_string("");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disabled buttons should not absorb mouseclicks
|
||||
event->ignore();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QDialog::eventFilter(object, event);
|
||||
}
|
||||
|
||||
void raw_mouse_settings_dialog::on_button_click(int id)
|
||||
{
|
||||
if (id < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto sb : m_accel_spin_boxes)
|
||||
{
|
||||
sb->setEnabled(false);
|
||||
sb->setFocusPolicy(Qt::ClickFocus);
|
||||
}
|
||||
|
||||
for (auto cb : m_device_combos)
|
||||
{
|
||||
cb->setEnabled(false);
|
||||
cb->setFocusPolicy(Qt::ClickFocus);
|
||||
}
|
||||
|
||||
for (auto but : m_buttons->buttons())
|
||||
{
|
||||
but->setEnabled(false);
|
||||
but->setFocusPolicy(Qt::ClickFocus);
|
||||
}
|
||||
|
||||
m_button_box->setEnabled(false);
|
||||
for (auto but : m_button_box->buttons())
|
||||
{
|
||||
but->setFocusPolicy(Qt::ClickFocus);
|
||||
}
|
||||
|
||||
m_button_id = id;
|
||||
if (auto button = m_buttons->button(m_button_id))
|
||||
{
|
||||
button->setText(tr("[ Waiting %1 ]").arg(MAX_SECONDS));
|
||||
button->setPalette(QPalette(Qt::blue));
|
||||
button->grabMouse();
|
||||
}
|
||||
|
||||
m_tab_widget->setEnabled(false);
|
||||
|
||||
m_remap_timer.start(1000);
|
||||
|
||||
// We need to disable the mouse release event filter or we will clear the button if the raw mouse does a right click
|
||||
m_mouse_release_timer.stop();
|
||||
m_disable_mouse_release_event = true;
|
||||
}
|
||||
|
||||
void raw_mouse_settings_dialog::reactivate_buttons()
|
||||
{
|
||||
m_remap_timer.stop();
|
||||
m_seconds = MAX_SECONDS;
|
||||
|
||||
if (m_button_id >= 0)
|
||||
{
|
||||
if (auto button = m_buttons->button(m_button_id))
|
||||
{
|
||||
button->setPalette(m_palette);
|
||||
button->releaseMouse();
|
||||
}
|
||||
|
||||
m_button_id = -1;
|
||||
}
|
||||
|
||||
// Enable all buttons
|
||||
m_button_box->setEnabled(true);
|
||||
|
||||
for (auto but : m_button_box->buttons())
|
||||
{
|
||||
but->setFocusPolicy(Qt::StrongFocus);
|
||||
}
|
||||
|
||||
for (auto sb : m_accel_spin_boxes)
|
||||
{
|
||||
sb->setEnabled(true);
|
||||
sb->setFocusPolicy(Qt::StrongFocus);
|
||||
}
|
||||
|
||||
for (auto cb : m_device_combos)
|
||||
{
|
||||
cb->setEnabled(true);
|
||||
cb->setFocusPolicy(Qt::StrongFocus);
|
||||
}
|
||||
|
||||
for (auto but : m_buttons->buttons())
|
||||
{
|
||||
but->setEnabled(true);
|
||||
but->setFocusPolicy(Qt::StrongFocus);
|
||||
}
|
||||
|
||||
m_tab_widget->setEnabled(true);
|
||||
|
||||
m_mouse_release_timer.start(100ms);
|
||||
}
|
||||
|
@ -1,11 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/types.hpp"
|
||||
|
||||
#include <QButtonGroup>
|
||||
#include <QComboBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDialog>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QMouseEvent>
|
||||
#include <QPalette>
|
||||
#include <QPushButton>
|
||||
#include <QTabWidget>
|
||||
#include <QTimer>
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
class raw_mouse_settings_dialog : public QDialog
|
||||
{
|
||||
@ -20,7 +29,33 @@ private:
|
||||
|
||||
void reset_config();
|
||||
|
||||
void on_button_click(int id);
|
||||
void mouse_press(const std::string& device_name, s32 cell_code, bool pressed);
|
||||
void handle_device_change(const std::string& device_name);
|
||||
bool is_device_active(const std::string& device_name);
|
||||
std::string get_current_device_name(int player);
|
||||
void reactivate_buttons();
|
||||
|
||||
QTabWidget* m_tab_widget = nullptr;
|
||||
std::vector<QComboBox*> m_device_combos;
|
||||
std::vector<QDoubleSpinBox*> m_accel_spin_boxes;
|
||||
std::vector<std::vector<QComboBox*>> m_combos;
|
||||
|
||||
// Buttons
|
||||
QDialogButtonBox* m_button_box = nullptr;
|
||||
QButtonGroup* m_buttons = nullptr;
|
||||
std::vector<std::unordered_map<int, QPushButton*>> m_push_buttons;
|
||||
int m_button_id = -1;
|
||||
|
||||
// Backup for standard button palette
|
||||
QPalette m_palette;
|
||||
|
||||
// Remap Timer
|
||||
static constexpr int MAX_SECONDS = 5;
|
||||
int m_seconds = MAX_SECONDS;
|
||||
QTimer m_remap_timer;
|
||||
QTimer m_mouse_release_timer;
|
||||
bool m_disable_mouse_release_event = false;
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user