ps move: allow to configure mouse move handler buttons

This commit is contained in:
Megamouse 2025-01-09 21:10:28 +01:00
parent 7e03828f35
commit a0df1e09a6
14 changed files with 273 additions and 65 deletions

View File

@ -40,9 +40,18 @@ void fmt_class_string<gem_btn>::format(std::string& out, u64 arg)
case gem_btn::square: return "Square";
case gem_btn::move: return "Move";
case gem_btn::t: return "T";
case gem_btn::count: return "Count";
case gem_btn::x_axis: return "X-Axis";
case gem_btn::y_axis: return "Y-Axis";
case gem_btn::combo: return "Combo";
case gem_btn::combo_start: return "Combo Start";
case gem_btn::combo_select: return "Combo Select";
case gem_btn::combo_triangle: return "Combo Triangle";
case gem_btn::combo_circle: return "Combo Circle";
case gem_btn::combo_cross: return "Combo Cross";
case gem_btn::combo_square: return "Combo Square";
case gem_btn::combo_move: return "Combo Move";
case gem_btn::combo_t: return "Combo T";
case gem_btn::count: return "Count";
}
return unknown;
@ -177,6 +186,7 @@ using gun_thread = named_thread<gun_handler>;
cfg_gems g_cfg_gem_real;
cfg_fake_gems g_cfg_gem_fake;
cfg_mouse_gems g_cfg_gem_mouse;
struct gem_config_data
{
@ -494,8 +504,14 @@ public:
cellGem.notice("Could not load fake gem config. Using defaults.");
}
if (!g_cfg_gem_mouse.load())
{
cellGem.notice("Could not load mouse gem config. Using defaults.");
}
cellGem.notice("Real gem config=\n", g_cfg_gem_real.to_string());
cellGem.notice("Fake gem config=\n", g_cfg_gem_fake.to_string());
cellGem.notice("Mouse gem config=\n", g_cfg_gem_mouse.to_string());
}
};
@ -1574,7 +1590,7 @@ static void ds3_input_to_pad(const u32 gem_num, be_t<u16>& digital_buttons, be_t
return;
}
const auto handle_input = [&](gem_btn btn, u16 value, bool pressed)
const auto handle_input = [&](gem_btn btn, pad_button /*pad_btn*/, u16 value, bool pressed, bool& /*abort*/)
{
if (!pressed)
return;
@ -1606,9 +1622,7 @@ static void ds3_input_to_pad(const u32 gem_num, be_t<u16>& digital_buttons, be_t
digital_buttons |= CELL_GEM_CTRL_T;
analog_t = std::max<u16>(analog_t, value);
break;
case gem_btn::x_axis:
case gem_btn::y_axis:
case gem_btn::count:
default:
break;
}
};
@ -1632,7 +1646,7 @@ static inline void ds3_get_stick_values(u32 gem_num, const std::shared_ptr<Pad>&
y_pos = 0;
const auto& cfg = ::at32(g_cfg_gem_fake.players, gem_num);
cfg->handle_input(pad, true, [&](gem_btn btn, u16 value, bool pressed)
cfg->handle_input(pad, true, [&](gem_btn btn, pad_button /*pad_btn*/, u16 value, bool pressed, bool& /*abort*/)
{
if (!pressed)
return;
@ -1828,41 +1842,97 @@ static bool mouse_input_to_pad(u32 mouse_no, be_t<u16>& digital_buttons, be_t<u1
return false;
}
std::set<MouseButtonCodes> pressed_buttons;
const Mouse& mouse_data = ::at32(handler.GetMice(), mouse_no);
const auto is_pressed = [&mouse_data, &pressed_buttons](MouseButtonCodes button) -> bool
auto& cfg = ::at32(g_cfg_gem_mouse.players, mouse_no);
bool combo_active = false;
std::set<pad_button> combos;
static const std::unordered_map<gem_btn, u16> btn_map =
{
// Only allow each button to be used for one action unless it's the combo button.
return (mouse_data.buttons & button) && (button == (CELL_MOUSE_BUTTON_3 + 0u/*fix warning*/) || pressed_buttons.insert(button).second);
{ gem_btn::start, CELL_GEM_CTRL_START },
{ gem_btn::select, CELL_GEM_CTRL_SELECT },
{ gem_btn::triangle, CELL_GEM_CTRL_TRIANGLE },
{ gem_btn::circle, CELL_GEM_CTRL_CIRCLE },
{ gem_btn::cross, CELL_GEM_CTRL_CROSS },
{ gem_btn::square, CELL_GEM_CTRL_SQUARE },
{ gem_btn::move, CELL_GEM_CTRL_MOVE },
{ gem_btn::t, CELL_GEM_CTRL_T },
{ gem_btn::combo_start, CELL_GEM_CTRL_START },
{ gem_btn::combo_select, CELL_GEM_CTRL_SELECT },
{ gem_btn::combo_triangle, CELL_GEM_CTRL_TRIANGLE },
{ gem_btn::combo_circle, CELL_GEM_CTRL_CIRCLE },
{ gem_btn::combo_cross, CELL_GEM_CTRL_CROSS },
{ gem_btn::combo_square, CELL_GEM_CTRL_SQUARE },
{ gem_btn::combo_move, CELL_GEM_CTRL_MOVE },
{ gem_btn::combo_t, CELL_GEM_CTRL_T },
};
digital_buttons = 0;
// Check combo button first
cfg->handle_input(mouse_data, [&combo_active](gem_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& abort)
{
if (pressed && btn == gem_btn::combo)
{
combo_active = true;
abort = true;
}
});
if ((is_pressed(CELL_MOUSE_BUTTON_3) && is_pressed(CELL_MOUSE_BUTTON_1)) || is_pressed(CELL_MOUSE_BUTTON_6))
digital_buttons |= CELL_GEM_CTRL_SELECT;
// Check combos
if (combo_active)
{
cfg->handle_input(mouse_data, [&digital_buttons, &combos](gem_btn btn, pad_button pad_btn, u16 /*value*/, bool pressed, bool& /*abort*/)
{
if (!pressed)
return;
if ((is_pressed(CELL_MOUSE_BUTTON_3) && is_pressed(CELL_MOUSE_BUTTON_2)) || is_pressed(CELL_MOUSE_BUTTON_7))
digital_buttons |= CELL_GEM_CTRL_START;
switch (btn)
{
case gem_btn::combo_start:
case gem_btn::combo_select:
case gem_btn::combo_triangle:
case gem_btn::combo_circle:
case gem_btn::combo_cross:
case gem_btn::combo_square:
case gem_btn::combo_move:
case gem_btn::combo_t:
digital_buttons |= ::at32(btn_map, btn);
combos.insert(pad_btn);
break;
default:
break;
}
});
}
if ((is_pressed(CELL_MOUSE_BUTTON_3) && is_pressed(CELL_MOUSE_BUTTON_4)) || is_pressed(CELL_MOUSE_BUTTON_8))
digital_buttons |= CELL_GEM_CTRL_TRIANGLE;
// Check normal buttons
cfg->handle_input(mouse_data, [&digital_buttons, &combos](gem_btn btn, pad_button pad_btn, u16 /*value*/, bool pressed, bool& /*abort*/)
{
if (!pressed)
return;
if (is_pressed(CELL_MOUSE_BUTTON_3) && is_pressed(CELL_MOUSE_BUTTON_5))
digital_buttons |= CELL_GEM_CTRL_SQUARE;
switch (btn)
{
case gem_btn::start:
case gem_btn::select:
case gem_btn::square:
case gem_btn::cross:
case gem_btn::circle:
case gem_btn::triangle:
case gem_btn::move:
case gem_btn::t:
// Ignore this gem_btn if the same pad_button was already used in a combo
if (!combos.contains(pad_btn))
{
digital_buttons |= ::at32(btn_map, btn);
}
break;
default:
break;
}
});
if (is_pressed(CELL_MOUSE_BUTTON_1))
digital_buttons |= CELL_GEM_CTRL_T;
if (is_pressed(CELL_MOUSE_BUTTON_2))
digital_buttons |= CELL_GEM_CTRL_MOVE;
if (is_pressed(CELL_MOUSE_BUTTON_4))
digital_buttons |= CELL_GEM_CTRL_CIRCLE;
if (is_pressed(CELL_MOUSE_BUTTON_5))
digital_buttons |= CELL_GEM_CTRL_CROSS;
analog_t = (mouse_data.buttons & CELL_MOUSE_BUTTON_1) ? 0xFFFF : 0;
analog_t = (digital_buttons & CELL_GEM_CTRL_T) ? 0xFFFF : 0;
return true;
}

View File

@ -161,7 +161,7 @@ void usb_device_buzz::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint*/
}
const auto& cfg = g_cfg_buzz.players[i];
cfg->handle_input(pad, true, [&buf, &index](buzz_btn btn, u16 /*value*/, bool pressed)
cfg->handle_input(pad, true, [&buf, &index](buzz_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& /*abort*/)
{
if (!pressed)
return;

View File

@ -147,7 +147,7 @@ void usb_device_ghltar::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint
}
const auto& cfg = ::at32(g_cfg_ghltar.players, m_controller_index);
cfg->handle_input(pad, true, [&buf](ghltar_btn btn, u16 value, bool pressed)
cfg->handle_input(pad, true, [&buf](ghltar_btn btn, pad_button /*pad_btn*/, u16 value, bool pressed, bool& /*abort*/)
{
if (!pressed)
return;

View File

@ -227,7 +227,7 @@ 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)
const auto input_callback = [&gc](guncon3_btn btn, pad_button /*pad_button*/, u16 value, bool pressed, bool& /*abort*/)
{
if (!pressed)
return;

View File

@ -280,7 +280,7 @@ void usb_device_topshotelite::interrupt_transfer(u32 buf_size, u8* buf, u32 /*en
}
bool up = false, right = false, down = false, left = false;
const auto input_callback = [&ts, &up, &down, &left, &right](topshotelite_btn btn, u16 value, bool pressed)
const auto input_callback = [&ts, &up, &down, &left, &right](topshotelite_btn btn, pad_button /*pad_button*/, u16 value, bool pressed, bool& /*abort*/)
{
if (!pressed)
return;

View File

@ -308,7 +308,7 @@ void usb_device_topshotfearmaster::interrupt_transfer(u32 buf_size, u8* buf, u32
}
bool up = false, right = false, down = false, left = false;
const auto input_callback = [&ts, &up, &down, &left, &right](topshotfearmaster_btn btn, u16 value, bool pressed)
const auto input_callback = [&ts, &up, &down, &left, &right](topshotfearmaster_btn btn, pad_button /*pad_button*/, u16 value, bool pressed, bool& /*abort*/)
{
if (!pressed)
return;

View File

@ -159,7 +159,7 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo
return;
const auto& cfg = ::at32(g_cfg_turntable.players, m_controller_index);
cfg->handle_input(pad, true, [&buf](turntable_btn btn, u16 value, bool pressed)
cfg->handle_input(pad, true, [&buf](turntable_btn btn, pad_button /*pad_btn*/, u16 value, bool pressed, bool& /*abort*/)
{
if (!pressed)
return;

View File

@ -88,7 +88,7 @@ public:
button_map.clear();
}
void handle_input(std::shared_ptr<Pad> pad, bool press_only, const std::function<void(T, u16, bool)>& func) const
void handle_input(std::shared_ptr<Pad> pad, bool press_only, const std::function<void(T, pad_button, u16, bool, bool&)>& func) const
{
if (!pad)
return;
@ -97,19 +97,25 @@ public:
{
if (button.m_pressed || !press_only)
{
handle_input(func, button.m_offset, button.m_outKeyCode, button.m_value, button.m_pressed, true);
if (handle_input(func, button.m_offset, button.m_outKeyCode, button.m_value, button.m_pressed, true))
{
return;
}
}
}
for (const AnalogStick& stick : pad->m_sticks)
{
handle_input(func, stick.m_offset, get_axis_keycode(stick.m_offset, stick.m_value), stick.m_value, true, true);
if (handle_input(func, stick.m_offset, get_axis_keycode(stick.m_offset, stick.m_value), stick.m_value, true, true))
{
return;
}
}
}
void handle_input(const Mouse& mouse, const std::function<void(T, u16, bool)>& func) const
void handle_input(const Mouse& mouse, const std::function<void(T, pad_button, u16, bool, bool&)>& func) const
{
for (int i = 0; i < 7; i++)
for (int i = 0; i < 8; i++)
{
const MouseButtonCodes cell_code = get_mouse_button_code(i);
if ((mouse.buttons & cell_code))
@ -117,7 +123,11 @@ public:
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);
if (handle_input(func, offset, keycode, 255, true, true))
{
return;
}
}
}
}
@ -163,10 +173,12 @@ protected:
return empty_set;
}
void handle_input(const std::function<void(T, u16, bool)>& func, u32 offset, u32 keycode, u16 value, bool pressed, bool check_axis) const
bool handle_input(const std::function<void(T, pad_button, u16, bool, bool&)>& func, u32 offset, u32 keycode, u16 value, bool pressed, bool check_axis) const
{
m_mutex.lock();
bool abort = false;
const auto& btns = find_button(offset, keycode);
if (btns.empty())
{
@ -180,24 +192,26 @@ protected:
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y:
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X:
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y:
handle_input(func, offset, static_cast<u32>(axis_direction::both), value, pressed, false);
abort = handle_input(func, offset, static_cast<u32>(axis_direction::both), value, pressed, false);
break;
default:
break;
}
}
return;
return abort;
}
for (const auto& btn : btns)
{
if (btn && func)
{
func(btn->btn_id(), value, pressed);
func(btn->btn_id(), btn->get(), value, pressed, abort);
if (abort) break;
}
}
m_mutex.unlock();
return abort;
}
};

View File

@ -4,7 +4,7 @@
#include <array>
enum class gem_btn
enum class gem_btn : u32
{
start,
select,
@ -17,6 +17,18 @@ enum class gem_btn
x_axis,
y_axis,
combo_begin,
combo = combo_begin,
combo_start,
combo_select,
combo_triangle,
combo_circle,
combo_cross,
combo_square,
combo_move,
combo_t,
combo_end = combo_t,
count
};
@ -41,6 +53,34 @@ struct cfg_fake_gems final : public emulated_pads_config<cfg_fake_gem, 4>
cfg_fake_gems() : emulated_pads_config<cfg_fake_gem, 4>("gem") {};
};
struct cfg_mouse_gem final : public emulated_pad_config<gem_btn>
{
cfg_mouse_gem(node* owner, const std::string& name) : emulated_pad_config(owner, name) {}
cfg_pad_btn<gem_btn> start{ this, "Start", gem_btn::start, pad_button::mouse_button_6 };
cfg_pad_btn<gem_btn> select{ this, "Select", gem_btn::select, pad_button::mouse_button_7 };
cfg_pad_btn<gem_btn> triangle{ this, "Triangle", gem_btn::triangle, pad_button::mouse_button_8 };
cfg_pad_btn<gem_btn> circle{ this, "Circle", gem_btn::circle, pad_button::mouse_button_4 };
cfg_pad_btn<gem_btn> cross{ this, "Cross", gem_btn::cross, pad_button::mouse_button_5 };
cfg_pad_btn<gem_btn> square{ this, "Square", gem_btn::square, pad_button::mouse_button_3 };
cfg_pad_btn<gem_btn> move{ this, "Move", gem_btn::move, pad_button::mouse_button_2 };
cfg_pad_btn<gem_btn> t{ this, "T", gem_btn::t, pad_button::mouse_button_1 };
cfg_pad_btn<gem_btn> combo{ this, "Combo", gem_btn::combo, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_start{ this, "Combo Start", gem_btn::combo_start, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_select{ this, "Combo Select", gem_btn::combo_select, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_triangle{ this, "Combo Triangle", gem_btn::combo_triangle, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_circle{ this, "Combo Circle", gem_btn::combo_circle, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_cross{ this, "Combo Cross", gem_btn::combo_cross, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_square{ this, "Combo Square", gem_btn::combo_square, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_move{ this, "Combo Move", gem_btn::combo_move, pad_button::pad_button_max_enum };
cfg_pad_btn<gem_btn> combo_t{ this, "Combo T", gem_btn::combo_t, pad_button::pad_button_max_enum };
};
struct cfg_mouse_gems final : public emulated_pads_config<cfg_mouse_gem, 4>
{
cfg_mouse_gems() : emulated_pads_config<cfg_mouse_gem, 4>("gem_mouse") {};
};
struct cfg_gem final : public emulated_pad_config<gem_btn>
{
cfg_gem(node* owner, const std::string& name) : emulated_pad_config(owner, name) {}
@ -62,3 +102,4 @@ struct cfg_gems final : public emulated_pads_config<cfg_gem, 4>
extern cfg_gems g_cfg_gem_real;
extern cfg_fake_gems g_cfg_gem_fake;
extern cfg_mouse_gems g_cfg_gem_mouse;

View File

@ -203,7 +203,7 @@ void usb_device_usio::translate_input_taiko()
if (const auto& pad = ::at32(handler->GetPads(), pad_number); (pad->m_port_status & CELL_PAD_STATUS_CONNECTED) && is_input_allowed())
{
const auto& cfg = ::at32(g_cfg_usio.players, pad_number);
cfg->handle_input(pad, false, [&](usio_btn btn, u16 /*value*/, bool pressed)
cfg->handle_input(pad, false, [&](usio_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& /*abort*/)
{
switch (btn)
{
@ -288,7 +288,7 @@ void usb_device_usio::translate_input_tekken()
if (const auto& pad = ::at32(handler->GetPads(), pad_number); (pad->m_port_status & CELL_PAD_STATUS_CONNECTED) && is_input_allowed())
{
const auto& cfg = ::at32(g_cfg_usio.players, pad_number);
cfg->handle_input(pad, false, [&](usio_btn btn, u16 /*value*/, bool pressed)
cfg->handle_input(pad, false, [&](usio_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& /*abort*/)
{
switch (btn)
{

View File

@ -92,6 +92,10 @@ emulated_pad_settings_dialog::emulated_pad_settings_dialog(pad_type type, QWidge
setWindowTitle(tr("Configure Emulated PS Move (Fake)"));
add_tabs<gem_btn>(tabs);
break;
case emulated_pad_settings_dialog::pad_type::mousegem:
setWindowTitle(tr("Configure Emulated PS Move (Mouse)"));
add_tabs<gem_btn>(tabs);
break;
case emulated_pad_settings_dialog::pad_type::guncon3:
setWindowTitle(tr("Configure Emulated GunCon 3"));
add_tabs<guncon3_btn>(tabs);
@ -116,8 +120,12 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
{
ensure(!!tabs);
constexpr u32 max_items_per_column = 6;
int count = static_cast<int>(T::count);
std::set<int> ignored_values;
const auto remove_value = [&ignored_values](int value)
{
ignored_values.insert(static_cast<int>(value));
};
usz players = 0;
switch (m_type)
@ -137,13 +145,29 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
case pad_type::gem:
players = g_cfg_gem_real.players.size();
// Ignore x and y axis
static_assert(static_cast<int>(gem_btn::y_axis) == static_cast<int>(gem_btn::count) - 1);
static_assert(static_cast<int>(gem_btn::x_axis) == static_cast<int>(gem_btn::count) - 2);
count -= 2;
// Ignore combo, x and y axis
remove_value(static_cast<int>(gem_btn::x_axis));
remove_value(static_cast<int>(gem_btn::y_axis));
for (int i = static_cast<int>(gem_btn::combo_begin); i <= static_cast<int>(gem_btn::combo_end); i++)
{
remove_value(i);
}
break;
case pad_type::ds3gem:
players = g_cfg_gem_fake.players.size();
// Ignore combo
for (int i = static_cast<int>(gem_btn::combo_begin); i <= static_cast<int>(gem_btn::combo_end); i++)
{
remove_value(i);
}
break;
case pad_type::mousegem:
players = g_cfg_gem_mouse.players.size();
// Ignore x and y axis
remove_value(static_cast<int>(gem_btn::x_axis));
remove_value(static_cast<int>(gem_btn::y_axis));
break;
case pad_type::guncon3:
players = g_cfg_guncon3.players.size();
@ -156,6 +180,8 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
break;
}
constexpr u32 max_items_per_column = 6;
const int count = static_cast<int>(T::count) - static_cast<int>(ignored_values.size());
int rows = count;
for (u32 cols = 1; utils::aligned_div(static_cast<u32>(count), cols) > max_items_per_column;)
@ -170,8 +196,10 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
QWidget* widget = new QWidget(this);
QGridLayout* grid_layout = new QGridLayout(this);
for (int i = 0, row = 0, col = 0; i < count; i++, row++)
for (int i = 0, row = 0, col = 0; i < static_cast<int>(T::count); i++)
{
if (ignored_values.contains(i)) continue;
const T id = static_cast<T>(i);
const QString name = QString::fromStdString(fmt::format("%s", id));
@ -179,16 +207,35 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
QGroupBox* gb = new QGroupBox(name, this);
QComboBox* combo = new QComboBox;
for (int p = 0; p < static_cast<int>(pad_button::pad_button_max_enum); p++)
if constexpr (std::is_same_v<T, gem_btn>)
{
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);
const gem_btn btn = static_cast<gem_btn>(i);
if (btn >= gem_btn::combo_begin && btn <= gem_btn::combo_end)
{
gb->setToolTip(tr("Press the \"Combo\" button in combination with any of the other combo buttons to trigger their related PS Move button.\n"
"This can be useful if your device does not have enough regular buttons."));
}
}
if constexpr (std::is_same_v<T, guncon3_btn> || std::is_same_v<T, topshotelite_btn> || std::is_same_v<T, topshotfearmaster_btn>)
// Add empty value
combo->addItem("");
const int index = combo->findText("");
combo->setItemData(index, static_cast<int>(pad_button::pad_button_max_enum), button_role::button);
combo->setItemData(index, i, button_role::emulated_button);
if (m_type != pad_type::mousegem)
{
for (int p = 0; p < static_cast<int>(pad_button::pad_button_max_enum); 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);
}
}
if (std::is_same_v<T, guncon3_btn> || std::is_same_v<T, topshotelite_btn> || std::is_same_v<T, topshotfearmaster_btn> || m_type == pad_type::mousegem)
{
for (int p = static_cast<int>(pad_button::mouse_button_1); p <= static_cast<int>(pad_button::mouse_button_8); p++)
{
@ -221,6 +268,9 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
case pad_type::ds3gem:
saved_btn_id = ::at32(g_cfg_gem_fake.players, player)->get_pad_button(static_cast<gem_btn>(id));
break;
case pad_type::mousegem:
saved_btn_id = ::at32(g_cfg_gem_mouse.players, player)->get_pad_button(static_cast<gem_btn>(id));
break;
case pad_type::guncon3:
saved_btn_id = ::at32(g_cfg_guncon3.players, player)->get_pad_button(static_cast<guncon3_btn>(id));
break;
@ -265,6 +315,9 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
case pad_type::ds3gem:
::at32(g_cfg_gem_fake.players, player)->set_button(static_cast<gem_btn>(id), btn_id);
break;
case pad_type::mousegem:
::at32(g_cfg_gem_mouse.players, player)->set_button(static_cast<gem_btn>(id), btn_id);
break;
case pad_type::guncon3:
::at32(g_cfg_guncon3.players, player)->set_button(static_cast<guncon3_btn>(id), btn_id);
break;
@ -287,6 +340,8 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
h_layout->addWidget(combo);
gb->setLayout(h_layout);
grid_layout->addWidget(gb, row, col);
row++;
}
widget->setLayout(grid_layout);
@ -334,6 +389,12 @@ void emulated_pad_settings_dialog::load_config()
cfg_log.notice("Could not load fake gem config. Using defaults.");
}
break;
case emulated_pad_settings_dialog::pad_type::mousegem:
if (!g_cfg_gem_mouse.load())
{
cfg_log.notice("Could not load mouse gem config. Using defaults.");
}
break;
case emulated_pad_settings_dialog::pad_type::guncon3:
if (!g_cfg_guncon3.load())
{
@ -377,6 +438,9 @@ void emulated_pad_settings_dialog::save_config()
case emulated_pad_settings_dialog::pad_type::ds3gem:
g_cfg_gem_fake.save();
break;
case emulated_pad_settings_dialog::pad_type::mousegem:
g_cfg_gem_mouse.save();
break;
case emulated_pad_settings_dialog::pad_type::guncon3:
g_cfg_guncon3.save();
break;
@ -411,6 +475,9 @@ void emulated_pad_settings_dialog::reset_config()
case emulated_pad_settings_dialog::pad_type::ds3gem:
g_cfg_gem_fake.from_default();
break;
case emulated_pad_settings_dialog::pad_type::mousegem:
g_cfg_gem_mouse.from_default();
break;
case emulated_pad_settings_dialog::pad_type::guncon3:
g_cfg_guncon3.from_default();
break;
@ -454,6 +521,9 @@ void emulated_pad_settings_dialog::reset_config()
case pad_type::ds3gem:
def_btn_id = ::at32(g_cfg_gem_fake.players, player)->default_pad_button(static_cast<gem_btn>(data.toInt()));
break;
case pad_type::mousegem:
def_btn_id = ::at32(g_cfg_gem_mouse.players, player)->default_pad_button(static_cast<gem_btn>(data.toInt()));
break;
case pad_type::guncon3:
def_btn_id = ::at32(g_cfg_guncon3.players, player)->default_pad_button(static_cast<guncon3_btn>(data.toInt()));
break;

View File

@ -21,6 +21,7 @@ public:
usio,
gem,
ds3gem,
mousegem,
guncon3,
topshotelite,
topshotfearmaster,

View File

@ -2911,6 +2911,12 @@ void main_window::CreateConnects()
dlg->show();
});
connect(ui->confPSMoveMouseAct, &QAction::triggered, this, [this]
{
emulated_pad_settings_dialog* dlg = new emulated_pad_settings_dialog(emulated_pad_settings_dialog::pad_type::mousegem, this);
dlg->show();
});
connect(ui->confPSMoveDS3Act, &QAction::triggered, this, [this]
{
emulated_pad_settings_dialog* dlg = new emulated_pad_settings_dialog(emulated_pad_settings_dialog::pad_type::ds3gem, this);

View File

@ -244,6 +244,7 @@
<addaction name="confUSIOAct"/>
<addaction name="confPSMoveAct"/>
<addaction name="confPSMoveDS3Act"/>
<addaction name="confPSMoveMouseAct"/>
<addaction name="confGunCon3Act"/>
<addaction name="confTopShotEliteAct"/>
<addaction name="confTopShotFearmasterAct"/>
@ -1333,6 +1334,11 @@
<string>PS Move (Fake)</string>
</property>
</action>
<action name="confPSMoveMouseAct">
<property name="text">
<string>PS Move (Mouse)</string>
</property>
</action>
<action name="confGunCon3Act">
<property name="text">
<string>GunCon 3</string>