mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 18:31:55 -04:00
input: add analog trigger emulation on Linux
This commit is contained in:
parent
4f739e88cf
commit
9fbdefe120
@ -90,7 +90,9 @@ EvdevInputDevice(int index) :
|
||||
_dpad_x_axis(-1),
|
||||
_dpad_y_axis(-1),
|
||||
_dpad_left_button(-1),
|
||||
_dpad_up_button(-1) {
|
||||
_dpad_up_button(-1),
|
||||
_ltrigger_code(-1),
|
||||
_rtrigger_code(-1) {
|
||||
|
||||
char path[64];
|
||||
sprintf(path, "/dev/input/event%d", index);
|
||||
@ -239,6 +241,7 @@ init_device() {
|
||||
|
||||
bool all_values_zero = true;
|
||||
bool emulate_dpad = true;
|
||||
bool have_analog_triggers = false;
|
||||
|
||||
bool has_keys = false;
|
||||
bool has_axes = false;
|
||||
@ -375,7 +378,12 @@ init_device() {
|
||||
}
|
||||
if (button.handle == GamepadButton::dpad_left()) {
|
||||
emulate_dpad = false;
|
||||
} else if (button.handle == GamepadButton::ltrigger()) {
|
||||
_ltrigger_code = i;
|
||||
} else if (button.handle == GamepadButton::rtrigger()) {
|
||||
_rtrigger_code = i;
|
||||
}
|
||||
|
||||
_buttons.push_back(button);
|
||||
if (i >= _button_indices.size()) {
|
||||
_button_indices.resize(i + 1, -1);
|
||||
@ -415,6 +423,7 @@ init_device() {
|
||||
axis = InputDevice::C_right_x;
|
||||
} else if (_device_class == DC_gamepad) {
|
||||
axis = InputDevice::C_left_trigger;
|
||||
have_analog_triggers = true;
|
||||
} else {
|
||||
axis = InputDevice::C_throttle;
|
||||
}
|
||||
@ -434,6 +443,7 @@ init_device() {
|
||||
axis = InputDevice::C_right_y;
|
||||
} else if (_device_class == DC_gamepad) {
|
||||
axis = InputDevice::C_right_trigger;
|
||||
have_analog_triggers = true;
|
||||
} else {
|
||||
axis = InputDevice::C_yaw;
|
||||
}
|
||||
@ -454,6 +464,7 @@ init_device() {
|
||||
case ABS_GAS:
|
||||
if (_device_class == DC_gamepad) {
|
||||
axis = InputDevice::C_right_trigger;
|
||||
have_analog_triggers = true;
|
||||
} else {
|
||||
axis = InputDevice::C_accelerator;
|
||||
}
|
||||
@ -461,6 +472,7 @@ init_device() {
|
||||
case ABS_BRAKE:
|
||||
if (_device_class == DC_gamepad) {
|
||||
axis = InputDevice::C_left_trigger;
|
||||
have_analog_triggers = true;
|
||||
} else {
|
||||
axis = InputDevice::C_brake;
|
||||
}
|
||||
@ -541,6 +553,16 @@ init_device() {
|
||||
}
|
||||
}
|
||||
|
||||
if (_ltrigger_code >= 0 && _rtrigger_code >= 0 && !have_analog_triggers) {
|
||||
// Emulate analog triggers.
|
||||
_ltrigger_control = (int)_controls.size();
|
||||
add_control(C_left_trigger, 0, 1, false);
|
||||
add_control(C_right_trigger, 0, 1, false);
|
||||
} else {
|
||||
_ltrigger_code = -1;
|
||||
_rtrigger_code = -1;
|
||||
}
|
||||
|
||||
char path[64];
|
||||
char buffer[256];
|
||||
sprintf(path, "/sys/class/input/event%d/device/device/../product", _index);
|
||||
@ -666,6 +688,11 @@ process_events() {
|
||||
if (index >= 0) {
|
||||
button_changed(index, events[i].value != 0);
|
||||
}
|
||||
if (code == _ltrigger_code) {
|
||||
control_changed(_ltrigger_control, events[i].value);
|
||||
} else if (code == _rtrigger_code) {
|
||||
control_changed(_ltrigger_control + 1, events[i].value);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -53,6 +53,11 @@ private:
|
||||
int _dpad_left_button;
|
||||
int _dpad_up_button;
|
||||
|
||||
// This is used for axis emulation.
|
||||
int _ltrigger_control;
|
||||
int _ltrigger_code;
|
||||
int _rtrigger_code;
|
||||
|
||||
public:
|
||||
static ButtonHandle map_button(int code, DeviceClass device_class = DC_unknown);
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "linuxJoystickDevice.h"
|
||||
#include "evdevInputDevice.h"
|
||||
|
||||
#ifdef PHAVE_LINUX_INPUT_H
|
||||
|
||||
@ -32,7 +33,9 @@ LinuxJoystickDevice(int index) :
|
||||
_dpad_x_axis(-1),
|
||||
_dpad_y_axis(-1),
|
||||
_dpad_left_button(-1),
|
||||
_dpad_up_button(-1)
|
||||
_dpad_up_button(-1),
|
||||
_ltrigger_button(-1),
|
||||
_rtrigger_button(-1)
|
||||
{
|
||||
LightMutexHolder holder(_lock);
|
||||
if (!open_device()) {
|
||||
@ -107,6 +110,8 @@ open_device() {
|
||||
ioctl(_fd, JSIOCGNAME(sizeof(name)), name);
|
||||
_name = name;
|
||||
|
||||
bool have_analog_triggers = false;
|
||||
|
||||
// Get the number of axes.
|
||||
uint8_t num_axes = 0, num_buttons = 0;
|
||||
ioctl(_fd, JSIOCGAXES, &num_axes);
|
||||
@ -120,104 +125,18 @@ open_device() {
|
||||
ioctl(_fd, JSIOCGBTNMAP, btnmap);
|
||||
|
||||
for (uint8_t i = 0; i < num_buttons; ++i) {
|
||||
ButtonHandle handle = ButtonHandle::none();
|
||||
switch (btnmap[i]) {
|
||||
case BTN_A:
|
||||
handle = GamepadButton::action_a();
|
||||
_device_class = DC_gamepad;
|
||||
break;
|
||||
|
||||
case BTN_B:
|
||||
handle = GamepadButton::action_b();
|
||||
break;
|
||||
|
||||
case BTN_C:
|
||||
handle = GamepadButton::action_c();
|
||||
break;
|
||||
|
||||
case BTN_X:
|
||||
handle = GamepadButton::action_x();
|
||||
break;
|
||||
|
||||
case BTN_Y:
|
||||
handle = GamepadButton::action_y();
|
||||
break;
|
||||
|
||||
case BTN_Z:
|
||||
handle = GamepadButton::action_z();
|
||||
break;
|
||||
|
||||
case BTN_TL:
|
||||
handle = GamepadButton::lshoulder();
|
||||
break;
|
||||
|
||||
case BTN_TR:
|
||||
handle = GamepadButton::rshoulder();
|
||||
break;
|
||||
|
||||
case BTN_TL2:
|
||||
handle = GamepadButton::ltrigger();
|
||||
break;
|
||||
|
||||
case BTN_TR2:
|
||||
handle = GamepadButton::rtrigger();
|
||||
break;
|
||||
|
||||
case BTN_1:
|
||||
handle = GamepadButton::action_1();
|
||||
break;
|
||||
|
||||
case BTN_2:
|
||||
handle = GamepadButton::action_2();
|
||||
break;
|
||||
|
||||
case BTN_SELECT:
|
||||
case KEY_PREVIOUS:
|
||||
handle = GamepadButton::back();
|
||||
break;
|
||||
|
||||
case BTN_START:
|
||||
case KEY_NEXT:
|
||||
handle = GamepadButton::start();
|
||||
break;
|
||||
|
||||
case BTN_MODE:
|
||||
handle = GamepadButton::guide();
|
||||
break;
|
||||
|
||||
case BTN_THUMBL:
|
||||
handle = GamepadButton::lstick();
|
||||
break;
|
||||
|
||||
case BTN_THUMBR:
|
||||
handle = GamepadButton::rstick();
|
||||
break;
|
||||
|
||||
case BTN_TRIGGER_HAPPY1:
|
||||
handle = GamepadButton::dpad_left();
|
||||
_dpad_left_button = i;
|
||||
break;
|
||||
|
||||
case BTN_TRIGGER_HAPPY2:
|
||||
handle = GamepadButton::dpad_right();
|
||||
break;
|
||||
|
||||
case BTN_TRIGGER_HAPPY3:
|
||||
handle = GamepadButton::dpad_up();
|
||||
_dpad_up_button = i;
|
||||
break;
|
||||
|
||||
case BTN_TRIGGER_HAPPY4:
|
||||
handle = GamepadButton::dpad_down();
|
||||
break;
|
||||
|
||||
default:
|
||||
ButtonHandle handle = EvdevInputDevice::map_button(btnmap[i]);
|
||||
if (handle == ButtonHandle::none()) {
|
||||
if (device_cat.is_debug()) {
|
||||
device_cat.debug() << "Unmapped /dev/input/js" << _index
|
||||
<< " button " << (int)i << ": 0x" << hex << btnmap[i] << "\n";
|
||||
}
|
||||
handle = ButtonHandle::none();
|
||||
break;
|
||||
} else if (handle == GamepadButton::action_a()) {
|
||||
_device_class = DC_gamepad;
|
||||
} else if (handle == GamepadButton::ltrigger()) {
|
||||
_ltrigger_button = i;
|
||||
} else if (handle == GamepadButton::rtrigger()) {
|
||||
_rtrigger_button = i;
|
||||
}
|
||||
_buttons[i].handle = handle;
|
||||
}
|
||||
@ -333,6 +252,7 @@ open_device() {
|
||||
// We'd like to use 0.0 to indicate the resting position.
|
||||
_controls[i]._scale = 1.0 / 65534.0;
|
||||
_controls[i]._bias = 0.5;
|
||||
have_analog_triggers = true;
|
||||
} else if (axis == C_left_y || axis == C_right_y || axis == C_y) {
|
||||
_controls[i]._scale = 1.0 / -32767.0;
|
||||
_controls[i]._bias = 0.0;
|
||||
@ -343,6 +263,16 @@ open_device() {
|
||||
}
|
||||
}
|
||||
|
||||
if (_ltrigger_button >= 0 && _rtrigger_button >= 0 && !have_analog_triggers) {
|
||||
// Emulate analog triggers.
|
||||
_ltrigger_control = (int)_controls.size();
|
||||
add_control(C_left_trigger, 0, 1, false);
|
||||
add_control(C_right_trigger, 0, 1, false);
|
||||
} else {
|
||||
_ltrigger_button = -1;
|
||||
_rtrigger_button = -1;
|
||||
}
|
||||
|
||||
// Get additional information from sysfs.
|
||||
sprintf(path, "/sys/class/input/js%d/device/id/vendor", _index);
|
||||
FILE *f = fopen(path, "r");
|
||||
@ -454,6 +384,11 @@ process_events() {
|
||||
int index = events[i].number;
|
||||
|
||||
if (events[i].type & JS_EVENT_BUTTON) {
|
||||
if (index == _ltrigger_button) {
|
||||
control_changed(_ltrigger_control, events[i].value);
|
||||
} else if (index == _rtrigger_button) {
|
||||
control_changed(_ltrigger_control + 1, events[i].value);
|
||||
}
|
||||
button_changed(index, (events[i].value != 0));
|
||||
|
||||
} else if (events[i].type & JS_EVENT_AXIS) {
|
||||
|
@ -45,6 +45,11 @@ private:
|
||||
int _dpad_left_button;
|
||||
int _dpad_up_button;
|
||||
|
||||
// This is used for axis emulation.
|
||||
int _ltrigger_control;
|
||||
int _ltrigger_button;
|
||||
int _rtrigger_button;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
Loading…
x
Reference in New Issue
Block a user