input: allow multiple key codes per button

This commit is contained in:
Megamouse 2023-06-13 01:19:32 +02:00
parent 16f869fe5a
commit d3be8ee2b7
14 changed files with 640 additions and 498 deletions

View file

@ -113,10 +113,10 @@ bool evdev_joystick_handler::Init()
for (const auto& node : m_pos_axis_config.get_nodes())
{
if (*static_cast<cfg::_bool*>(node))
if (node && *static_cast<cfg::_bool*>(node))
{
const auto name = node->get_name();
const int code = libevdev_event_code_from_name(EV_ABS, name.c_str());
const std::string& name = node->get_name();
const int code = libevdev_event_code_from_name(EV_ABS, name.c_str());
if (code < 0)
evdev_log.error("Failed to read axis name from %s. [code = %d] [name = %s]", m_pos_axis_config.cfg_name, code, name);
else
@ -130,12 +130,14 @@ bool evdev_joystick_handler::Init()
std::string evdev_joystick_handler::get_device_name(const libevdev* dev)
{
std::string name = libevdev_get_name(dev);
const auto unique = libevdev_get_uniq(dev);
std::string name;
if (const char* raw_name = libevdev_get_name(dev))
name = raw_name;
if (name.empty())
{
if (unique)
if (const char* unique = libevdev_get_uniq(dev))
name = unique;
if (name.empty())
@ -151,8 +153,8 @@ bool evdev_joystick_handler::update_device(const std::shared_ptr<PadDevice>& dev
if (!evdev_device)
return false;
const auto& path = evdev_device->path;
libevdev*& dev = evdev_device->device;
const std::string& path = evdev_device->path;
libevdev*& dev = evdev_device->device;
const bool was_connected = dev != nullptr;
@ -206,18 +208,18 @@ void evdev_joystick_handler::close_devices()
}
};
for (auto& binding : m_bindings)
for (pad_ensemble& binding : m_bindings)
{
free_device(static_cast<EvdevDevice*>(binding.device.get()));
free_device(static_cast<EvdevDevice*>(binding.buddy_device.get()));
}
for (auto [name, device] : m_settings_added)
for (auto& [name, device] : m_settings_added)
{
free_device(static_cast<EvdevDevice*>(device.get()));
}
for (auto [name, device] : m_motion_settings_added)
for (auto& [name, device] : m_motion_settings_added)
{
free_device(static_cast<EvdevDevice*>(device.get()));
}
@ -229,14 +231,14 @@ std::unordered_map<u64, std::pair<u16, bool>> evdev_joystick_handler::GetButtonV
if (!device)
return button_values;
auto& dev = device->device;
libevdev* dev = device->device;
if (!Init())
return button_values;
for (const auto& entry : button_list)
{
const auto code = entry.first;
const u32 code = entry.first;
if (code == NO_BUTTON)
continue;
@ -251,8 +253,8 @@ std::unordered_map<u64, std::pair<u16, bool>> evdev_joystick_handler::GetButtonV
for (const auto& entry : axis_list)
{
const auto code = entry.first;
int val = 0;
const u32 code = entry.first;
int val = 0;
if (libevdev_fetch_event_value(dev, EV_ABS, code, &val) == 0)
continue;
@ -298,7 +300,7 @@ PadHandlerBase::connection evdev_joystick_handler::get_next_button_press(const s
m_blacklist.clear();
// Get our evdev device
auto device = get_evdev_device(padId);
std::shared_ptr<EvdevDevice> device = get_evdev_device(padId);
if (!device || !device->device)
{
if (fail_callback)
@ -328,16 +330,36 @@ PadHandlerBase::connection evdev_joystick_handler::get_next_button_press(const s
auto data = GetButtonValues(device);
auto find_value = [=, this](const std::string& name)
const auto find_value = [&, this](const std::string& str)
{
int key = FindKeyCodeByString(rev_axis_list, name, false);
const bool dir = key >= 0;
if (key < 0)
key = FindKeyCodeByString(axis_list, name, false);
if (key < 0)
key = FindKeyCodeByString(button_list, name);
auto it = data.find(static_cast<u64>(key));
return it != data.end() && dir == it->second.second ? it->second.first : 0;
const std::vector<std::string> names = cfg_pad::get_buttons(str);
u16 value{};
const auto set_value = [&value, &data](u32 code, bool dir)
{
if (const auto it = data.find(static_cast<u64>(code)); it != data.cend() && dir == it->second.second)
{
value = std::max(value, it->second.first);
}
};
for (const u32 code : FindKeyCodes<u32, u32>(rev_axis_list, names))
{
set_value(code, true);
}
for (const u32 code : FindKeyCodes<u32, u32>(axis_list, names))
{
set_value(code, false);
}
for (const u32 code : FindKeyCodes<u32, u32>(button_list, names))
{
set_value(code, false);
}
return value;
};
pad_preview_values preview_values{};
@ -469,7 +491,7 @@ PadHandlerBase::connection evdev_joystick_handler::get_next_button_press(const s
void evdev_joystick_handler::get_motion_sensors(const std::string& padId, const motion_callback& callback, const motion_fail_callback& fail_callback, motion_preview_values preview_values, const std::array<AnalogSensor, 4>& sensors)
{
// Add device if not yet present
auto device = add_motion_device(padId, true);
std::shared_ptr<EvdevDevice> device = add_motion_device(padId, true);
if (!device || !update_device(device) || !device->device)
{
if (fail_callback)
@ -477,7 +499,7 @@ void evdev_joystick_handler::get_motion_sensors(const std::string& padId, const
return;
}
auto& dev = device->device;
libevdev* dev = device->device;
// Try to fetch all new events from the joystick.
bool is_dirty = false;
@ -605,7 +627,7 @@ void evdev_joystick_handler::SetRumble(EvdevDevice* device, u8 large, u8 small)
void evdev_joystick_handler::SetPadData(const std::string& padId, u8 /*player_id*/, u8 large_motor, u8 small_motor, s32 /* r*/, s32 /* g*/, s32 /* b*/, bool /*player_led*/, bool /*battery_led*/, u32 /*battery_led_brightness*/)
{
// Get our evdev device
auto dev = get_evdev_device(padId);
std::shared_ptr<EvdevDevice> dev = get_evdev_device(padId);
if (!dev)
{
evdev_log.error("evdev TestVibration: Device [%s] not found! [large_motor = %d] [small_motor = %d]", padId, large_motor, small_motor);
@ -637,7 +659,7 @@ u32 evdev_joystick_handler::GetButtonInfo(const input_event& evt, const std::sha
if (button_list.find(code) == button_list.end())
{
evdev_log.error("Evdev button %s (%d) is unknown. Please add it to the button list.", libevdev_event_code_get_name(EV_KEY, code), code);
return -1;
return umax;
}
value = val > 0 ? 255 : 0;
@ -647,9 +669,10 @@ u32 evdev_joystick_handler::GetButtonInfo(const input_event& evt, const std::sha
{
if (!device || !device->device)
{
return -1;
return umax;
}
auto& dev = device->device;
libevdev* dev = device->device;
const int min = libevdev_get_abs_minimum(dev, code);
const int max = libevdev_get_abs_maximum(dev, code);
@ -667,7 +690,8 @@ u32 evdev_joystick_handler::GetButtonInfo(const input_event& evt, const std::sha
value = static_cast<u16>(std::abs(fvalue));
return code;
}
default: return -1;
default:
return umax;
}
}
@ -778,7 +802,7 @@ std::shared_ptr<evdev_joystick_handler::EvdevDevice> evdev_joystick_handler::add
{
if (const input_absinfo *info = libevdev_get_abs_info(dev, code))
{
const auto code_name = libevdev_event_code_get_name(EV_ABS, code);
const char* code_name = libevdev_event_code_get_name(EV_ABS, code);
evdev_log.notice("Axis info for %s: %s (%s) => minimum=%d, maximum=%d, fuzz=%d, flat=%d, resolution=%d",
name, code_name, axis_name, info->minimum, info->maximum, info->fuzz, info->flat, info->resolution);
}
@ -853,7 +877,7 @@ std::shared_ptr<evdev_joystick_handler::EvdevDevice> evdev_joystick_handler::add
if (const input_absinfo *info = libevdev_get_abs_info(dev, code))
{
const bool is_accel = code == ABS_X || code == ABS_Y || code == ABS_Z;
const auto code_name = libevdev_event_code_get_name(EV_ABS, code);
const char* code_name = libevdev_event_code_get_name(EV_ABS, code);
evdev_log.notice("Axis info for %s: %s (%s, %s) => minimum=%d, maximum=%d, fuzz=%d, flat=%d, resolution=%d",
name, code_name, axis_name, is_accel ? "accelerometer" : "gyro", info->minimum, info->maximum, info->fuzz, info->flat, info->resolution);
}
@ -898,7 +922,7 @@ void evdev_joystick_handler::get_mapping(const pad_ensemble& binding)
if (!m_dev || !pad)
return;
auto& dev = m_dev->device;
libevdev* dev = m_dev->device;
if (!dev)
return;
@ -940,7 +964,7 @@ void evdev_joystick_handler::get_extended_info(const pad_ensemble& binding)
if (!pad || !device || !update_device(device))
return;
auto& dev = device->device;
libevdev* dev = device->device;
if (!dev)
return;
@ -1011,39 +1035,51 @@ void evdev_joystick_handler::handle_input_event(const input_event& evt, const st
if (button_code == NO_BUTTON || value < 0)
return;
const auto cfg = m_dev->config;
const cfg_pad* cfg = m_dev->config;
if (!cfg)
return;
auto axis_orientations = m_dev->axis_orientations;
// Find out if special buttons are pressed (introduced by RPCS3).
// These buttons will have a delay of one cycle, but whatever.
const bool adjust_pressure = pad->get_pressure_intensity_enabled(cfg->pressure_intensity_toggle_mode.get());
// We can only have one match for this physical event in our button sets.
const auto find_evdev_button = [this, &button_code, &evt](const std::set<u32>& indices) -> const EvdevButton*
{
for (u32 index : indices)
{
const EvdevButton& evdev_button = ::at32(m_dev->all_buttons, index);
if (evdev_button.code == button_code && evdev_button.type == evt.type)
{
return &evdev_button;
}
}
return nullptr;
};
// Translate any corresponding keycodes to our normal DS3 buttons and triggers
for (int i = 0; i < static_cast<int>(pad->m_buttons.size()); i++)
{
auto& button = pad->m_buttons[i];
Button& button = pad->m_buttons[i];
if (button.m_keyCode != button_code)
const EvdevButton* evdev_button = find_evdev_button(button.m_key_codes);
if (!evdev_button)
continue;
// Be careful to handle mapped axis specially
if (evt.type == EV_ABS)
{
// get axis direction and skip on error or set to 0 if the stick/hat is actually pointing to the other direction.
// maybe mimic on error, needs investigation. FindAxisDirection should ideally never return -1 anyway
const int direction = FindAxisDirection(axis_orientations, i);
m_dev->cur_dir = direction;
// get axis direction for TranslateButtonPress and skip on error.
m_dev->cur_dir = evdev_button->dir;
if (direction < 0)
if (evdev_button->dir < 0)
{
evdev_log.error("FindAxisDirection = %d, Button Nr.%d, value = %d", direction, i, value);
evdev_log.error("Invalid axis direction = %d, Button Nr.%d, value = %d", evdev_button->dir, i, value);
continue;
}
if (direction != (m_is_negative ? 1 : 0))
// Set to 0 if the stick / hat is actually pointing to the other direction.
if (evdev_button->dir != (m_is_negative ? 1 : 0))
{
button.m_value = 0;
button.m_pressed = 0;
@ -1051,19 +1087,19 @@ void evdev_joystick_handler::handle_input_event(const input_event& evt, const st
}
}
// Using a temporary buffer because the values can change during translation
Button tmp = button;
tmp.m_value = static_cast<u16>(value);
bool pressed{};
u16 val = static_cast<u16>(value);
TranslateButtonPress(m_dev, button_code, tmp.m_pressed, tmp.m_value);
TranslateButtonPress(m_dev, button_code, pressed, val);
// Modify pressure if necessary if the button was pressed
if (adjust_pressure && tmp.m_pressed)
if (adjust_pressure && pressed)
{
tmp.m_value = pad->m_pressure_intensity;
val = pad->m_pressure_intensity;
}
button = tmp;
button.m_value = val;
button.m_pressed = pressed;
}
// Translate any corresponding keycodes to our two sticks. (ignoring thresholds for now)
@ -1072,19 +1108,20 @@ void evdev_joystick_handler::handle_input_event(const input_event& evt, const st
bool pressed_min = false;
bool pressed_max = false;
// m_keyCodeMin is the mapped key for left or down
if (pad->m_sticks[idx].m_keyCodeMin == button_code)
// m_key_codes_min are the mapped keys for left or down
if (const EvdevButton* evdev_button = find_evdev_button(pad->m_sticks[idx].m_key_codes_min))
{
bool is_direction_min = false;
if (!m_is_button_or_trigger && evt.type == EV_ABS)
{
const int index = pad->m_buttons.size() + (idx * 2) + 1;
const int min_direction = FindAxisDirection(axis_orientations, index);
m_dev->cur_dir = min_direction;
const int min_direction = evdev_button->dir;
// We need to set the current direction for TranslateButtonPress
m_dev->cur_dir = min_direction;
if (min_direction < 0)
evdev_log.error("keyCodeMin FindAxisDirection = %d, Axis Nr.%d, Button Nr.%d, value = %d", min_direction, idx, index, value);
evdev_log.error("min_direction = %d, Axis Nr.%d, value = %d", min_direction, idx, value);
else
is_direction_min = m_is_negative == (min_direction == 1);
}
@ -1100,19 +1137,20 @@ void evdev_joystick_handler::handle_input_event(const input_event& evt, const st
}
}
// m_keyCodeMax is the mapped key for right or up
if (pad->m_sticks[idx].m_keyCodeMax == button_code)
// m_key_codes_max are the mapped keys for right or up
if (const EvdevButton* evdev_button = find_evdev_button(pad->m_sticks[idx].m_key_codes_max))
{
bool is_direction_max = false;
if (!m_is_button_or_trigger && evt.type == EV_ABS)
{
const int index = pad->m_buttons.size() + (idx * 2);
const int max_direction = FindAxisDirection(axis_orientations, index);
m_dev->cur_dir = max_direction;
const int max_direction = evdev_button->dir;
// We need to set the current direction for TranslateButtonPress
m_dev->cur_dir = max_direction;
if (max_direction < 0)
evdev_log.error("keyCodeMax FindAxisDirection = %d, Axis Nr.%d, Button Nr.%d, value = %d", max_direction, idx, index, value);
evdev_log.error("max_direction = %d, Axis Nr.%d, value = %d", max_direction, idx, value);
else
is_direction_max = m_is_negative == (max_direction == 1);
}
@ -1153,7 +1191,7 @@ void evdev_joystick_handler::apply_pad_data(const pad_ensemble& binding)
if (!evdev_device)
return;
auto cfg = device->config;
cfg_pad* cfg = device->config;
if (!cfg)
return;
@ -1165,16 +1203,6 @@ void evdev_joystick_handler::apply_pad_data(const pad_ensemble& binding)
SetRumble(evdev_device, force_large, force_small);
}
// Search axis_orientations map for the direction by index, returns -1 if not found, 0 for positive and 1 for negative
int evdev_joystick_handler::FindAxisDirection(const std::unordered_map<int, bool>& map, int index)
{
if (const auto it = map.find(index); it != map.end())
{
return it->second;
}
return -1;
}
bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player_id)
{
if (!pad || player_id >= g_cfg_input.player.size())
@ -1195,38 +1223,46 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player
if (!cfg)
return false;
std::unordered_map<int, bool> axis_orientations;
int i = 0; // increment to know the axis location
auto evdevbutton = [&](const cfg::string& name)
// We need to register EvdevButtons due to their axis directions.
const auto register_evdevbutton = [this](u32 code, bool is_axis, bool is_reverse) -> u32
{
EvdevButton button{ 0, -1, EV_ABS };
const u32 index = ::narrow<u32>(m_dev->all_buttons.size());
int key = FindKeyCode(axis_list, name, false);
if (key >= 0)
axis_orientations.emplace(i, false);
if (key < 0)
if (is_axis)
{
key = FindKeyCode(rev_axis_list, name, false);
if (key >= 0)
axis_orientations.emplace(i, true);
}
if (key < 0)
{
key = FindKeyCode(button_list, name);
button.type = EV_KEY;
m_dev->all_buttons.push_back(EvdevButton{ code, is_reverse ? 1 : 0, EV_ABS });
}
else
{
button.dir = axis_orientations[i];
m_dev->all_buttons.push_back(EvdevButton{ code, -1, EV_KEY });
}
button.code = static_cast<u32>(key);
return index;
};
i++;
return button;
const auto find_buttons = [&](const cfg::string& name) -> std::set<u32>
{
const std::vector<std::string> names = cfg_pad::get_buttons(name);
// In evdev we store indices to an EvdevButton vector in our pad objects instead of the usual key codes.
std::set<u32> indices;
for (const u32 code : FindKeyCodes<u32, u32>(axis_list, names))
{
indices.insert(register_evdevbutton(code, true, false));
}
for (const u32 code : FindKeyCodes<u32, u32>(rev_axis_list, names))
{
indices.insert(register_evdevbutton(code, true, true));
}
for (const u32 code : FindKeyCodes<u32, u32>(button_list, names))
{
indices.insert(register_evdevbutton(code, false, false));
}
return indices;
};
const auto find_motion_button = [&](const cfg_sensor& sensor) -> evdev_sensor
@ -1235,14 +1271,15 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player
e_sensor.type = EV_ABS;
e_sensor.mirrored = sensor.mirrored.get();
e_sensor.shift = sensor.shift.get();
const int key = FindKeyCode(motion_axis_list, sensor.axis, false);
if (key >= 0) e_sensor.code = static_cast<u32>(key);
const std::set<u32> keys = FindKeyCodes<u32, u32>(motion_axis_list, sensor.axis);
if (!keys.empty()) e_sensor.code = *keys.begin(); // We should only have one key for each of our sensors
return e_sensor;
};
u32 pclass_profile = 0x0;
for (const auto product : input::get_products_by_class(cfg->device_class_type))
for (const input::product_info& product : input::get_products_by_class(cfg->device_class_type))
{
if (product.vendor_id == cfg->vendor_id && product.product_id == cfg->product_id)
{
@ -1262,45 +1299,45 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player
cfg->pressure_intensity
);
pad->m_buttons.emplace_back(special_button_offset, evdevbutton(cfg->pressure_intensity_button).code, special_button_value::pressure_intensity);
pad->m_buttons.emplace_back(special_button_offset, find_buttons(cfg->pressure_intensity_button), special_button_value::pressure_intensity);
pad->m_pressure_intensity_button_index = static_cast<s32>(pad->m_buttons.size()) - 1;
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, evdevbutton(cfg->triangle).code, CELL_PAD_CTRL_TRIANGLE);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, evdevbutton(cfg->circle).code, CELL_PAD_CTRL_CIRCLE);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, evdevbutton(cfg->cross).code, CELL_PAD_CTRL_CROSS);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, evdevbutton(cfg->square).code, CELL_PAD_CTRL_SQUARE);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2,find_buttons(cfg->triangle), CELL_PAD_CTRL_TRIANGLE);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2,find_buttons(cfg->circle), CELL_PAD_CTRL_CIRCLE);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2,find_buttons(cfg->cross), CELL_PAD_CTRL_CROSS);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2,find_buttons(cfg->square), CELL_PAD_CTRL_SQUARE);
m_dev->trigger_left = evdevbutton(cfg->l2);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev->trigger_left.code, CELL_PAD_CTRL_L2);
m_dev->trigger_left = find_buttons(cfg->l2);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev->trigger_left, CELL_PAD_CTRL_L2);
m_dev->trigger_right = evdevbutton(cfg->r2);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev->trigger_right.code, CELL_PAD_CTRL_R2);
m_dev->trigger_right = find_buttons(cfg->r2);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev->trigger_right, CELL_PAD_CTRL_R2);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, evdevbutton(cfg->l1).code, CELL_PAD_CTRL_L1);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, evdevbutton(cfg->r1).code, CELL_PAD_CTRL_R1);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, evdevbutton(cfg->start).code, CELL_PAD_CTRL_START);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, evdevbutton(cfg->select).code, CELL_PAD_CTRL_SELECT);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, evdevbutton(cfg->l3).code, CELL_PAD_CTRL_L3);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, evdevbutton(cfg->r3).code, CELL_PAD_CTRL_R3);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, evdevbutton(cfg->ps).code, CELL_PAD_CTRL_PS);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, evdevbutton(cfg->up).code, CELL_PAD_CTRL_UP);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, evdevbutton(cfg->down).code, CELL_PAD_CTRL_DOWN);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, evdevbutton(cfg->left).code, CELL_PAD_CTRL_LEFT);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, evdevbutton(cfg->right).code, CELL_PAD_CTRL_RIGHT);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_buttons(cfg->l1), CELL_PAD_CTRL_L1);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_buttons(cfg->r1), CELL_PAD_CTRL_R1);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->start), CELL_PAD_CTRL_START);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->select), CELL_PAD_CTRL_SELECT);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->l3), CELL_PAD_CTRL_L3);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->r3), CELL_PAD_CTRL_R3);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->ps), CELL_PAD_CTRL_PS);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->up), CELL_PAD_CTRL_UP);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->down), CELL_PAD_CTRL_DOWN);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->left), CELL_PAD_CTRL_LEFT);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_buttons(cfg->right), CELL_PAD_CTRL_RIGHT);
m_dev->axis_left[0] = evdevbutton(cfg->ls_right);
m_dev->axis_left[1] = evdevbutton(cfg->ls_left);
m_dev->axis_left[2] = evdevbutton(cfg->ls_up);
m_dev->axis_left[3] = evdevbutton(cfg->ls_down);
m_dev->axis_right[0] = evdevbutton(cfg->rs_right);
m_dev->axis_right[1] = evdevbutton(cfg->rs_left);
m_dev->axis_right[2] = evdevbutton(cfg->rs_up);
m_dev->axis_right[3] = evdevbutton(cfg->rs_down);
m_dev->axis_left[0] = find_buttons(cfg->ls_right);
m_dev->axis_left[1] = find_buttons(cfg->ls_left);
m_dev->axis_left[2] = find_buttons(cfg->ls_up);
m_dev->axis_left[3] = find_buttons(cfg->ls_down);
m_dev->axis_right[0] = find_buttons(cfg->rs_right);
m_dev->axis_right[1] = find_buttons(cfg->rs_left);
m_dev->axis_right[2] = find_buttons(cfg->rs_up);
m_dev->axis_right[3] = find_buttons(cfg->rs_down);
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, m_dev->axis_left[1].code, m_dev->axis_left[0].code);
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, m_dev->axis_left[3].code, m_dev->axis_left[2].code);
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, m_dev->axis_right[1].code, m_dev->axis_right[0].code);
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, m_dev->axis_right[3].code, m_dev->axis_right[2].code);
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, m_dev->axis_left[1], m_dev->axis_left[0]);
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, m_dev->axis_left[3], m_dev->axis_left[2]);
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, m_dev->axis_right[1], m_dev->axis_right[0]);
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, m_dev->axis_right[3], m_dev->axis_right[2]);
m_dev->axis_motion[0] = find_motion_button(cfg->motion_sensor_x);
m_dev->axis_motion[1] = find_motion_button(cfg->motion_sensor_y);
@ -1315,11 +1352,9 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player
pad->m_vibrateMotors.emplace_back(true, 0);
pad->m_vibrateMotors.emplace_back(false, 0);
m_dev->axis_orientations = axis_orientations;
if (auto evdev_device = add_device(player_config->device, false))
if (std::shared_ptr<EvdevDevice> evdev_device = add_device(player_config->device, false))
{
if (auto motion_device = add_motion_device(player_config->buddy_device, false))
if (std::shared_ptr<EvdevDevice> motion_device = add_motion_device(player_config->buddy_device, false))
{
m_bindings.emplace_back(pad, evdev_device, motion_device);
}
@ -1334,7 +1369,7 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player
evdev_log.warning("evdev add_device in bindPadToDevice failed for device %s", player_config->device.to_string());
}
for (auto& binding : m_bindings)
for (pad_ensemble& binding : m_bindings)
{
update_device(binding.device);
update_device(binding.buddy_device);
@ -1343,34 +1378,46 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player
return true;
}
bool evdev_joystick_handler::check_button(const EvdevButton& b, const u32 code)
bool evdev_joystick_handler::check_button_set(const std::set<u32>& indices, const u32 code)
{
return m_dev && b.code == code && b.type == m_dev->cur_type && b.dir == m_dev->cur_dir;
if (!m_dev)
return false;
for (u32 index : indices)
{
const EvdevButton& button = ::at32(m_dev->all_buttons, index);
if (button.code == code && button.type == m_dev->cur_type && button.dir == m_dev->cur_dir)
{
return true;
}
}
return false;
}
bool evdev_joystick_handler::check_buttons(const std::array<EvdevButton, 4>& b, const u32 code)
bool evdev_joystick_handler::check_button_sets(const std::array<std::set<u32>, 4>& sets, const u32 code)
{
return std::any_of(b.begin(), b.end(), [this, code](const EvdevButton& b) { return check_button(b, code); });
return std::any_of(sets.begin(), sets.end(), [this, code](const std::set<u32>& indices) { return check_button_set(indices, code); });
};
bool evdev_joystick_handler::get_is_left_trigger(const std::shared_ptr<PadDevice>& /*device*/, u64 keyCode)
{
return check_button(m_dev->trigger_left, static_cast<u32>(keyCode));
return check_button_set(m_dev->trigger_left, static_cast<u32>(keyCode));
}
bool evdev_joystick_handler::get_is_right_trigger(const std::shared_ptr<PadDevice>& /*device*/, u64 keyCode)
{
return check_button(m_dev->trigger_right, static_cast<u32>(keyCode));
return check_button_set(m_dev->trigger_right, static_cast<u32>(keyCode));
}
bool evdev_joystick_handler::get_is_left_stick(const std::shared_ptr<PadDevice>& /*device*/, u64 keyCode)
{
return check_buttons(m_dev->axis_left, static_cast<u32>(keyCode));
return check_button_sets(m_dev->axis_left, static_cast<u32>(keyCode));
}
bool evdev_joystick_handler::get_is_right_stick(const std::shared_ptr<PadDevice>& /*device*/, u64 keyCode)
{
return check_buttons(m_dev->axis_right, static_cast<u32>(keyCode));
return check_button_sets(m_dev->axis_right, static_cast<u32>(keyCode));
}
#endif

View file

@ -341,9 +341,9 @@ class evdev_joystick_handler final : public PadHandlerBase
struct EvdevButton
{
u32 code = 0;
int dir = 0;
int type = 0;
u32 code = 0; // key code of our button or axis
int dir = 0; // dir is -1 in case of a button, 0 in case of a regular axis and 1 in case of a reverse axis
int type = 0; // EV_KEY or EV_ABS
};
struct evdev_sensor : public EvdevButton
@ -356,14 +356,14 @@ class evdev_joystick_handler final : public PadHandlerBase
{
libevdev* device{ nullptr };
std::string path;
std::unordered_map<int, bool> axis_orientations; // value is true if key was found in rev_axis_list
std::array<s32, 4> stick_val{};
std::array<u16, 4> val_min{};
std::array<u16, 4> val_max{};
EvdevButton trigger_left{};
EvdevButton trigger_right{};
std::array<EvdevButton, 4> axis_left{};
std::array<EvdevButton, 4> axis_right{};
std::vector<EvdevButton> all_buttons;
std::set<u32> trigger_left{};
std::set<u32> trigger_right{};
std::array<std::set<u32>, 4> axis_left{};
std::array<std::set<u32>, 4> axis_right{};
std::array<evdev_sensor, 4> axis_motion{};
int cur_dir = 0;
int cur_type = 0;
@ -397,20 +397,17 @@ private:
std::unordered_map<u64, std::pair<u16, bool>> GetButtonValues(const std::shared_ptr<EvdevDevice>& device);
void SetRumble(EvdevDevice* device, u8 large, u8 small);
// Search axis_orientations map for the direction by index, returns -1 if not found, 0 for positive and 1 for negative
int FindAxisDirection(const std::unordered_map<int, bool>& map, int index);
positive_axis m_pos_axis_config;
std::vector<u32> m_positive_axis;
std::vector<std::string> m_blacklist;
std::unordered_map<std::string, std::shared_ptr<evdev_joystick_handler::EvdevDevice>> m_settings_added;
std::unordered_map<std::string, std::shared_ptr<evdev_joystick_handler::EvdevDevice>> m_motion_settings_added;
std::shared_ptr<EvdevDevice> m_dev;
bool m_is_button_or_trigger;
bool m_is_negative;
bool m_is_button_or_trigger{};
bool m_is_negative{};
bool check_button(const EvdevButton& b, const u32 code);
bool check_buttons(const std::array<EvdevButton, 4>& b, const u32 code);
bool check_button_set(const std::set<u32>& indices, const u32 code);
bool check_button_sets(const std::array<std::set<u32>, 4>& sets, const u32 code);
void handle_input_event(const input_event& evt, const std::shared_ptr<Pad>& pad);

View file

@ -6,8 +6,6 @@
#include <QApplication>
LOG_CHANNEL(input_log, "Input");
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
constexpr auto qstr = QString::fromStdString;
@ -85,7 +83,7 @@ void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)
{
Button& pressure_intensity_button = pad.m_buttons[pad.m_pressure_intensity_button_index];
if (pressure_intensity_button.m_keyCode == code)
if (pressure_intensity_button.m_key_codes.contains(code))
{
pressure_intensity_button.m_pressed = pressed;
pressure_intensity_button.m_value = value;
@ -97,9 +95,31 @@ void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)
// Handle buttons
for (Button& button : pad.m_buttons)
{
if (button.m_keyCode != code)
if (!button.m_key_codes.contains(code))
continue;
// Make sure we keep this button pressed until all related keys are released.
if (pressed)
{
button.m_pressed_keys.insert(code);
if (button.m_pressed_keys.size() > 1)
{
// This button was already pressed by another key. Ignore this key press.
continue;
}
}
else
{
button.m_pressed_keys.erase(code);
if (!button.m_pressed_keys.empty())
{
// This button is still pressed by another key. Ignore this key release.
continue;
}
}
button.m_actual_value = pressed ? value : 0;
bool update_button = true;
@ -133,8 +153,8 @@ void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)
// Handle sticks
for (usz i = 0; i < pad.m_sticks.size(); i++)
{
const bool is_max = pad.m_sticks[i].m_keyCodeMax == code;
const bool is_min = pad.m_sticks[i].m_keyCodeMin == code;
const bool is_max = pad.m_sticks[i].m_key_codes_max.contains(code);
const bool is_min = pad.m_sticks[i].m_key_codes_min.contains(code);
if (!is_max && !is_min)
{
@ -697,9 +717,17 @@ std::string keyboard_pad_handler::GetKeyName(const u32& keyCode)
return sstr(QKeySequence(keyCode).toString(QKeySequence::NativeText));
}
u32 keyboard_pad_handler::GetKeyCode(const std::string& keyName)
std::set<u32> keyboard_pad_handler::GetKeyCodes(const cfg::string& cfg_string)
{
return GetKeyCode(qstr(keyName));
std::set<u32> key_codes;
for (const std::string& key_name : cfg_pad::get_buttons(cfg_string))
{
if (u32 code = GetKeyCode(QString::fromStdString(key_name)); code != Qt::NoButton)
{
key_codes.insert(code);
}
}
return key_codes;
}
u32 keyboard_pad_handler::GetKeyCode(const QString& keyName)
@ -731,7 +759,7 @@ u32 keyboard_pad_handler::GetKeyCode(const QString& keyName)
#endif
const QKeySequence seq(keyName);
u32 key_code = 0;
u32 key_code = Qt::NoButton;
if (seq.count() == 1)
key_code = seq[0];
@ -812,18 +840,25 @@ bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player_i
m_r_stick_multiplier = cfg->rstickmultiplier;
m_pressure_intensity_toggle_mode = cfg->pressure_intensity_toggle_mode.get();
const auto find_key = [this](const cfg::string& name)
const auto find_keys = [this](const cfg::string& name)
{
int key = FindKeyCode(mouse_list, name, false);
if (key < 0)
key = GetKeyCode(name);
if (key < 0)
key = 0;
else if (!m_mouse_move_used && (key == mouse::move_left || key == mouse::move_right || key == mouse::move_up || key == mouse::move_down))
m_mouse_move_used = true;
else if (!m_mouse_wheel_used && (key == mouse::wheel_left || key == mouse::wheel_right || key == mouse::wheel_up || key == mouse::wheel_down))
m_mouse_wheel_used = true;
return key;
std::set<u32> keys = FindKeyCodes<u32, u32>(mouse_list, name, false);
if (keys.empty())
{
keys = GetKeyCodes(name);
}
if (!keys.empty())
{
if (!m_mouse_move_used && (keys.contains(mouse::move_left) || keys.contains(mouse::move_right) || keys.contains(mouse::move_up) || keys.contains(mouse::move_down)))
{
m_mouse_move_used = true;
}
else if (!m_mouse_wheel_used && (keys.contains(mouse::wheel_left) || keys.contains(mouse::wheel_right) || keys.contains(mouse::wheel_up) || keys.contains(mouse::wheel_down)))
{
m_mouse_wheel_used = true;
}
}
return keys;
};
u32 pclass_profile = 0x0;
@ -849,31 +884,31 @@ bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player_i
cfg->pressure_intensity
);
pad->m_buttons.emplace_back(special_button_offset, find_key(cfg->pressure_intensity_button), special_button_value::pressure_intensity);
pad->m_buttons.emplace_back(special_button_offset, find_keys(cfg->pressure_intensity_button), special_button_value::pressure_intensity);
pad->m_pressure_intensity_button_index = static_cast<s32>(pad->m_buttons.size()) - 1;
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(cfg->left), CELL_PAD_CTRL_LEFT);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(cfg->down), CELL_PAD_CTRL_DOWN);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(cfg->right), CELL_PAD_CTRL_RIGHT);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(cfg->up), CELL_PAD_CTRL_UP);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(cfg->start), CELL_PAD_CTRL_START);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(cfg->r3), CELL_PAD_CTRL_R3);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(cfg->l3), CELL_PAD_CTRL_L3);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(cfg->select), CELL_PAD_CTRL_SELECT);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(cfg->ps), CELL_PAD_CTRL_PS);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(cfg->square), CELL_PAD_CTRL_SQUARE);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(cfg->cross), CELL_PAD_CTRL_CROSS);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(cfg->circle), CELL_PAD_CTRL_CIRCLE);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(cfg->triangle), CELL_PAD_CTRL_TRIANGLE);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(cfg->r1), CELL_PAD_CTRL_R1);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(cfg->l1), CELL_PAD_CTRL_L1);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(cfg->r2), CELL_PAD_CTRL_R2);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(cfg->l2), CELL_PAD_CTRL_L2);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_keys(cfg->left), CELL_PAD_CTRL_LEFT);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_keys(cfg->down), CELL_PAD_CTRL_DOWN);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_keys(cfg->right), CELL_PAD_CTRL_RIGHT);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_keys(cfg->up), CELL_PAD_CTRL_UP);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_keys(cfg->start), CELL_PAD_CTRL_START);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_keys(cfg->r3), CELL_PAD_CTRL_R3);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_keys(cfg->l3), CELL_PAD_CTRL_L3);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_keys(cfg->select), CELL_PAD_CTRL_SELECT);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_keys(cfg->ps), CELL_PAD_CTRL_PS);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->square), CELL_PAD_CTRL_SQUARE);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->cross), CELL_PAD_CTRL_CROSS);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->circle), CELL_PAD_CTRL_CIRCLE);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->triangle), CELL_PAD_CTRL_TRIANGLE);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->r1), CELL_PAD_CTRL_R1);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->l1), CELL_PAD_CTRL_L1);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->r2), CELL_PAD_CTRL_R2);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_keys(cfg->l2), CELL_PAD_CTRL_L2);
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, find_key(cfg->ls_left), find_key(cfg->ls_right));
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, find_key(cfg->ls_up), find_key(cfg->ls_down));
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, find_key(cfg->rs_left), find_key(cfg->rs_right));
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, find_key(cfg->rs_up), find_key(cfg->rs_down));
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, find_keys(cfg->ls_left), find_keys(cfg->ls_right));
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, find_keys(cfg->ls_up), find_keys(cfg->ls_down));
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, find_keys(cfg->rs_left), find_keys(cfg->rs_right));
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, find_keys(cfg->rs_up), find_keys(cfg->rs_down));
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_X, 0, 0, 0, DEFAULT_MOTION_X);
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Y, 0, 0, 0, DEFAULT_MOTION_Y);
@ -891,8 +926,8 @@ bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player_i
void keyboard_pad_handler::process()
{
static const double stick_interval = 10.0;
static const double button_interval = 10.0;
constexpr double stick_interval = 10.0;
constexpr double button_interval = 10.0;
const auto now = steady_clock::now();
@ -914,7 +949,7 @@ void keyboard_pad_handler::process()
if (m_mouse_move_used && m_mouse_movement_mode == mouse_movement_mode::relative)
{
static const double mouse_interval = 30.0;
constexpr double mouse_interval = 30.0;
const double elapsed_left = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_left).count() / 1000.0;
const double elapsed_right = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_right).count() / 1000.0;
@ -987,7 +1022,7 @@ void keyboard_pad_handler::process()
if (update_buttons)
{
for (auto& button : pad.m_buttons)
for (Button& button : pad.m_buttons)
{
if (button.m_analog)
{

View file

@ -93,7 +93,7 @@ public:
static QStringList GetKeyNames(const QKeyEvent* keyEvent);
static std::string GetKeyName(const QKeyEvent* keyEvent);
static std::string GetKeyName(const u32& keyCode);
static u32 GetKeyCode(const std::string& keyName);
static std::set<u32> GetKeyCodes(const cfg::string& cfg_string);
static u32 GetKeyCode(const QString& keyName);
static int native_scan_code_from_string(const std::string& key);

View file

@ -2,8 +2,6 @@
#include "mm_joystick_handler.h"
#include "Emu/Io/pad_config.h"
LOG_CHANNEL(input_log, "Input");
mm_joystick_handler::mm_joystick_handler() : PadHandlerBase(pad_handler::mm)
{
init_configs();
@ -113,62 +111,70 @@ std::vector<pad_list_entry> mm_joystick_handler::list_devices()
return devices;
}
u64 mm_joystick_handler::find_key(const std::string& name) const
template <typename T>
std::set<T> mm_joystick_handler::find_keys(const cfg::string& cfg_string) const
{
long key = FindKeyCodeByString(axis_list, name, false);
if (key < 0)
key = FindKeyCodeByString(pov_list, name, false);
if (key < 0)
key = FindKeyCodeByString(button_list, name);
return static_cast<u64>(key);
return find_keys<T>(cfg_pad::get_buttons(cfg_string));
}
std::array<u32, PadHandlerBase::button::button_count> mm_joystick_handler::get_mapped_key_codes(const std::shared_ptr<PadDevice>& device, const cfg_pad* cfg)
template <typename T>
std::set<T> mm_joystick_handler::find_keys(const std::vector<std::string>& names) const
{
std::array<u32, button::button_count> mapping{};
std::set<T> keys;
for (const T& k : FindKeyCodes<u64, T>(axis_list, names)) keys.insert(k);
for (const T& k : FindKeyCodes<u64, T>(pov_list, names)) keys.insert(k);
for (const T& k : FindKeyCodes<u64, T>(button_list, names)) keys.insert(k);
return keys;
}
std::array<std::set<u32>, PadHandlerBase::button::button_count> mm_joystick_handler::get_mapped_key_codes(const std::shared_ptr<PadDevice>& device, const cfg_pad* cfg)
{
std::array<std::set<u32>, button::button_count> mapping{};
MMJOYDevice* joy_device = static_cast<MMJOYDevice*>(device.get());
if (!joy_device || !cfg)
return mapping;
joy_device->trigger_code_left = find_key(cfg->l2);
joy_device->trigger_code_right = find_key(cfg->r2);
joy_device->axis_code_left[0] = find_key(cfg->ls_left);
joy_device->axis_code_left[1] = find_key(cfg->ls_right);
joy_device->axis_code_left[2] = find_key(cfg->ls_down);
joy_device->axis_code_left[3] = find_key(cfg->ls_up);
joy_device->axis_code_right[0] = find_key(cfg->rs_left);
joy_device->axis_code_right[1] = find_key(cfg->rs_right);
joy_device->axis_code_right[2] = find_key(cfg->rs_down);
joy_device->axis_code_right[3] = find_key(cfg->rs_up);
joy_device->trigger_code_left = find_keys<u64>(cfg->l2);
joy_device->trigger_code_right = find_keys<u64>(cfg->r2);
joy_device->axis_code_left[0] = find_keys<u64>(cfg->ls_left);
joy_device->axis_code_left[1] = find_keys<u64>(cfg->ls_right);
joy_device->axis_code_left[2] = find_keys<u64>(cfg->ls_down);
joy_device->axis_code_left[3] = find_keys<u64>(cfg->ls_up);
joy_device->axis_code_right[0] = find_keys<u64>(cfg->rs_left);
joy_device->axis_code_right[1] = find_keys<u64>(cfg->rs_right);
joy_device->axis_code_right[2] = find_keys<u64>(cfg->rs_down);
joy_device->axis_code_right[3] = find_keys<u64>(cfg->rs_up);
mapping[button::up] = static_cast<u32>(find_key(cfg->up));
mapping[button::down] = static_cast<u32>(find_key(cfg->down));
mapping[button::left] = static_cast<u32>(find_key(cfg->left));
mapping[button::right] = static_cast<u32>(find_key(cfg->right));
mapping[button::cross] = static_cast<u32>(find_key(cfg->cross));
mapping[button::square] = static_cast<u32>(find_key(cfg->square));
mapping[button::circle] = static_cast<u32>(find_key(cfg->circle));
mapping[button::triangle] = static_cast<u32>(find_key(cfg->triangle));
mapping[button::l1] = static_cast<u32>(find_key(cfg->l1));
mapping[button::l2] = static_cast<u32>(joy_device->trigger_code_left);
mapping[button::l3] = static_cast<u32>(find_key(cfg->l3));
mapping[button::r1] = static_cast<u32>(find_key(cfg->r1));
mapping[button::r2] = static_cast<u32>(joy_device->trigger_code_right);
mapping[button::r3] = static_cast<u32>(find_key(cfg->r3));
mapping[button::start] = static_cast<u32>(find_key(cfg->start));
mapping[button::select] = static_cast<u32>(find_key(cfg->select));
mapping[button::ps] = static_cast<u32>(find_key(cfg->ps));
mapping[button::ls_left] = static_cast<u32>(joy_device->axis_code_left[0]);
mapping[button::ls_right] = static_cast<u32>(joy_device->axis_code_left[1]);
mapping[button::ls_down] = static_cast<u32>(joy_device->axis_code_left[2]);
mapping[button::ls_up] = static_cast<u32>(joy_device->axis_code_left[3]);
mapping[button::rs_left] = static_cast<u32>(joy_device->axis_code_right[0]);
mapping[button::rs_right] = static_cast<u32>(joy_device->axis_code_right[1]);
mapping[button::rs_down] = static_cast<u32>(joy_device->axis_code_right[2]);
mapping[button::rs_up] = static_cast<u32>(joy_device->axis_code_right[3]);
mapping[button::up] = find_keys<u32>(cfg->up);
mapping[button::down] = find_keys<u32>(cfg->down);
mapping[button::left] = find_keys<u32>(cfg->left);
mapping[button::right] = find_keys<u32>(cfg->right);
mapping[button::cross] = find_keys<u32>(cfg->cross);
mapping[button::square] = find_keys<u32>(cfg->square);
mapping[button::circle] = find_keys<u32>(cfg->circle);
mapping[button::triangle] = find_keys<u32>(cfg->triangle);
mapping[button::l1] = find_keys<u32>(cfg->l1);
mapping[button::l2] = narrow_set(joy_device->trigger_code_left);
mapping[button::l3] = find_keys<u32>(cfg->l3);
mapping[button::r1] = find_keys<u32>(cfg->r1);
mapping[button::r2] = narrow_set(joy_device->trigger_code_right);
mapping[button::r3] = find_keys<u32>(cfg->r3);
mapping[button::start] = find_keys<u32>(cfg->start);
mapping[button::select] = find_keys<u32>(cfg->select);
mapping[button::ps] = find_keys<u32>(cfg->ps);
mapping[button::ls_left] = narrow_set(joy_device->axis_code_left[0]);
mapping[button::ls_right] = narrow_set(joy_device->axis_code_left[1]);
mapping[button::ls_down] = narrow_set(joy_device->axis_code_left[2]);
mapping[button::ls_up] = narrow_set(joy_device->axis_code_left[3]);
mapping[button::rs_left] = narrow_set(joy_device->axis_code_right[0]);
mapping[button::rs_right] = narrow_set(joy_device->axis_code_right[1]);
mapping[button::rs_down] = narrow_set(joy_device->axis_code_right[2]);
mapping[button::rs_up] = narrow_set(joy_device->axis_code_right[3]);
mapping[button::pressure_intensity_button] = static_cast<u32>(find_key(cfg->pressure_intensity_button));
mapping[button::pressure_intensity_button] = find_keys<u32>(cfg->pressure_intensity_button);
return mapping;
}
@ -230,9 +236,8 @@ PadHandlerBase::connection mm_joystick_handler::get_next_button_press(const std:
std::string name;
} pressed_button{};
for (const auto& button : axis_list)
for (const auto& [keycode, name] : axis_list)
{
u64 keycode = button.first;
u16 value = data[keycode];
if (!get_blacklist && std::find(m_blacklist.cbegin(), m_blacklist.cend(), keycode) != m_blacklist.cend())
@ -242,20 +247,19 @@ PadHandlerBase::connection mm_joystick_handler::get_next_button_press(const std:
{
if (get_blacklist)
{
m_blacklist.emplace_back(keycode);
input_log.error("MMJOY Calibration: Added axis [ %d = %s ] to blacklist. Value = %d", keycode, button.second, value);
m_blacklist.push_back(keycode);
input_log.error("MMJOY Calibration: Added axis [ %d = %s ] to blacklist. Value = %d", keycode, name, value);
}
else if (value > pressed_button.value)
{
pressed_button = { .value = value, .name = button.second };
pressed_button = { .value = value, .name = name };
}
}
}
for (const auto& button : pov_list)
for (const auto& [keycode, name] : pov_list)
{
u64 keycode = button.first;
u16 value = data[keycode];
const u16 value = data[keycode];
if (!get_blacklist && std::find(m_blacklist.cbegin(), m_blacklist.cend(), keycode) != m_blacklist.cend())
continue;
@ -264,20 +268,18 @@ PadHandlerBase::connection mm_joystick_handler::get_next_button_press(const std:
{
if (get_blacklist)
{
m_blacklist.emplace_back(keycode);
input_log.error("MMJOY Calibration: Added pov [ %d = %s ] to blacklist. Value = %d", keycode, button.second, value);
m_blacklist.push_back(keycode);
input_log.error("MMJOY Calibration: Added pov [ %d = %s ] to blacklist. Value = %d", keycode, name, value);
}
else if (value > pressed_button.value)
{
pressed_button = { .value = value, .name = button.second };
pressed_button = { .value = value, .name = name };
}
}
}
for (const auto& button : button_list)
for (const auto& [keycode, name] : button_list)
{
const u64 keycode = button.first;
if (keycode == NO_BUTTON)
continue;
@ -290,12 +292,12 @@ PadHandlerBase::connection mm_joystick_handler::get_next_button_press(const std:
{
if (get_blacklist)
{
m_blacklist.emplace_back(keycode);
input_log.error("MMJOY Calibration: Added button [ %d = %s ] to blacklist. Value = %d", keycode, button.second, value);
m_blacklist.push_back(keycode);
input_log.error("MMJOY Calibration: Added button [ %d = %s ] to blacklist. Value = %d", keycode, name, value);
}
else if (value > pressed_button.value)
{
pressed_button = { .value = value, .name = button.second };
pressed_button = { .value = value, .name = name };
}
}
}
@ -312,12 +314,24 @@ PadHandlerBase::connection mm_joystick_handler::get_next_button_press(const std:
pad_preview_values preview_values{};
if (buttons.size() == 10)
{
preview_values[0] = data[find_key(buttons[0])];
preview_values[1] = data[find_key(buttons[1])];
preview_values[2] = data[find_key(buttons[3])] - data[find_key(buttons[2])];
preview_values[3] = data[find_key(buttons[5])] - data[find_key(buttons[4])];
preview_values[4] = data[find_key(buttons[7])] - data[find_key(buttons[6])];
preview_values[5] = data[find_key(buttons[9])] - data[find_key(buttons[8])];
const auto get_key_value = [this, &data](const std::string& str) -> u16
{
u16 value{};
for (u32 key_code : find_keys<u32>(cfg_pad::get_buttons(str)))
{
if (const auto it = data.find(key_code); it != data.cend())
{
value = std::max(value, it->second);
}
}
return value;
};
preview_values[0] = get_key_value(buttons[0]);
preview_values[1] = get_key_value(buttons[1]);
preview_values[2] = get_key_value(buttons[3]) - get_key_value(buttons[2]);
preview_values[3] = get_key_value(buttons[5]) - get_key_value(buttons[4]);
preview_values[4] = get_key_value(buttons[7]) - get_key_value(buttons[6]);
preview_values[5] = get_key_value(buttons[9]) - get_key_value(buttons[8]);
}
if (pressed_button.value > 0)
@ -492,25 +506,25 @@ std::shared_ptr<PadDevice> mm_joystick_handler::get_device(const std::string& de
bool mm_joystick_handler::get_is_left_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode)
{
const MMJOYDevice* dev = static_cast<MMJOYDevice*>(device.get());
return dev && dev->trigger_code_left == keyCode;
return dev && dev->trigger_code_left.contains(keyCode);
}
bool mm_joystick_handler::get_is_right_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode)
{
const MMJOYDevice* dev = static_cast<MMJOYDevice*>(device.get());
return dev && dev->trigger_code_right == keyCode;
return dev && dev->trigger_code_right.contains(keyCode);
}
bool mm_joystick_handler::get_is_left_stick(const std::shared_ptr<PadDevice>& device, u64 keyCode)
{
const MMJOYDevice* dev = static_cast<MMJOYDevice*>(device.get());
return dev && std::find(dev->axis_code_left.cbegin(), dev->axis_code_left.cend(), keyCode) != dev->axis_code_left.cend();
return dev && std::any_of(dev->axis_code_left.cbegin(), dev->axis_code_left.cend(), [&keyCode](const std::set<u64>& s){ return s.contains(keyCode); });
}
bool mm_joystick_handler::get_is_right_stick(const std::shared_ptr<PadDevice>& device, u64 keyCode)
{
const MMJOYDevice* dev = static_cast<MMJOYDevice*>(device.get());
return dev && std::find(dev->axis_code_right.cbegin(), dev->axis_code_right.cend(), keyCode) != dev->axis_code_right.cend();
return dev && std::any_of(dev->axis_code_right.cbegin(), dev->axis_code_right.cend(), [&keyCode](const std::set<u64>& s){ return s.contains(keyCode); });
}
PadHandlerBase::connection mm_joystick_handler::update_connection(const std::shared_ptr<PadDevice>& device)

View file

@ -126,9 +126,13 @@ private:
std::vector<u64> m_blacklist;
std::unordered_map<int, MMJOYDevice> m_devices;
u64 find_key(const std::string& name) const;
template <typename T>
std::set<T> find_keys(const std::vector<std::string>& names) const;
std::array<u32, PadHandlerBase::button::button_count> get_mapped_key_codes(const std::shared_ptr<PadDevice>& device, const cfg_pad* cfg) override;
template <typename T>
std::set<T> find_keys(const cfg::string& cfg_string) const;
std::array<std::set<u32>, PadHandlerBase::button::button_count> get_mapped_key_codes(const std::shared_ptr<PadDevice>& device, const cfg_pad* cfg) override;
std::shared_ptr<PadDevice> get_device(const std::string& device) override;
bool get_is_left_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;
bool get_is_right_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;

View file

@ -24,7 +24,6 @@
#include "Utilities/Thread.h"
#include "util/atomic.hpp"
LOG_CHANNEL(input_log, "Input");
LOG_CHANNEL(sys_log, "SYS");
extern bool is_input_allowed();