mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -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_x_axis(-1),
|
||||||
_dpad_y_axis(-1),
|
_dpad_y_axis(-1),
|
||||||
_dpad_left_button(-1),
|
_dpad_left_button(-1),
|
||||||
_dpad_up_button(-1) {
|
_dpad_up_button(-1),
|
||||||
|
_ltrigger_code(-1),
|
||||||
|
_rtrigger_code(-1) {
|
||||||
|
|
||||||
char path[64];
|
char path[64];
|
||||||
sprintf(path, "/dev/input/event%d", index);
|
sprintf(path, "/dev/input/event%d", index);
|
||||||
@ -239,6 +241,7 @@ init_device() {
|
|||||||
|
|
||||||
bool all_values_zero = true;
|
bool all_values_zero = true;
|
||||||
bool emulate_dpad = true;
|
bool emulate_dpad = true;
|
||||||
|
bool have_analog_triggers = false;
|
||||||
|
|
||||||
bool has_keys = false;
|
bool has_keys = false;
|
||||||
bool has_axes = false;
|
bool has_axes = false;
|
||||||
@ -375,7 +378,12 @@ init_device() {
|
|||||||
}
|
}
|
||||||
if (button.handle == GamepadButton::dpad_left()) {
|
if (button.handle == GamepadButton::dpad_left()) {
|
||||||
emulate_dpad = false;
|
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);
|
_buttons.push_back(button);
|
||||||
if (i >= _button_indices.size()) {
|
if (i >= _button_indices.size()) {
|
||||||
_button_indices.resize(i + 1, -1);
|
_button_indices.resize(i + 1, -1);
|
||||||
@ -415,6 +423,7 @@ init_device() {
|
|||||||
axis = InputDevice::C_right_x;
|
axis = InputDevice::C_right_x;
|
||||||
} else if (_device_class == DC_gamepad) {
|
} else if (_device_class == DC_gamepad) {
|
||||||
axis = InputDevice::C_left_trigger;
|
axis = InputDevice::C_left_trigger;
|
||||||
|
have_analog_triggers = true;
|
||||||
} else {
|
} else {
|
||||||
axis = InputDevice::C_throttle;
|
axis = InputDevice::C_throttle;
|
||||||
}
|
}
|
||||||
@ -434,6 +443,7 @@ init_device() {
|
|||||||
axis = InputDevice::C_right_y;
|
axis = InputDevice::C_right_y;
|
||||||
} else if (_device_class == DC_gamepad) {
|
} else if (_device_class == DC_gamepad) {
|
||||||
axis = InputDevice::C_right_trigger;
|
axis = InputDevice::C_right_trigger;
|
||||||
|
have_analog_triggers = true;
|
||||||
} else {
|
} else {
|
||||||
axis = InputDevice::C_yaw;
|
axis = InputDevice::C_yaw;
|
||||||
}
|
}
|
||||||
@ -454,6 +464,7 @@ init_device() {
|
|||||||
case ABS_GAS:
|
case ABS_GAS:
|
||||||
if (_device_class == DC_gamepad) {
|
if (_device_class == DC_gamepad) {
|
||||||
axis = InputDevice::C_right_trigger;
|
axis = InputDevice::C_right_trigger;
|
||||||
|
have_analog_triggers = true;
|
||||||
} else {
|
} else {
|
||||||
axis = InputDevice::C_accelerator;
|
axis = InputDevice::C_accelerator;
|
||||||
}
|
}
|
||||||
@ -461,6 +472,7 @@ init_device() {
|
|||||||
case ABS_BRAKE:
|
case ABS_BRAKE:
|
||||||
if (_device_class == DC_gamepad) {
|
if (_device_class == DC_gamepad) {
|
||||||
axis = InputDevice::C_left_trigger;
|
axis = InputDevice::C_left_trigger;
|
||||||
|
have_analog_triggers = true;
|
||||||
} else {
|
} else {
|
||||||
axis = InputDevice::C_brake;
|
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 path[64];
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
sprintf(path, "/sys/class/input/event%d/device/device/../product", _index);
|
sprintf(path, "/sys/class/input/event%d/device/device/../product", _index);
|
||||||
@ -666,6 +688,11 @@ process_events() {
|
|||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
button_changed(index, events[i].value != 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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -53,6 +53,11 @@ private:
|
|||||||
int _dpad_left_button;
|
int _dpad_left_button;
|
||||||
int _dpad_up_button;
|
int _dpad_up_button;
|
||||||
|
|
||||||
|
// This is used for axis emulation.
|
||||||
|
int _ltrigger_control;
|
||||||
|
int _ltrigger_code;
|
||||||
|
int _rtrigger_code;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static ButtonHandle map_button(int code, DeviceClass device_class = DC_unknown);
|
static ButtonHandle map_button(int code, DeviceClass device_class = DC_unknown);
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linuxJoystickDevice.h"
|
#include "linuxJoystickDevice.h"
|
||||||
|
#include "evdevInputDevice.h"
|
||||||
|
|
||||||
#ifdef PHAVE_LINUX_INPUT_H
|
#ifdef PHAVE_LINUX_INPUT_H
|
||||||
|
|
||||||
@ -32,7 +33,9 @@ LinuxJoystickDevice(int index) :
|
|||||||
_dpad_x_axis(-1),
|
_dpad_x_axis(-1),
|
||||||
_dpad_y_axis(-1),
|
_dpad_y_axis(-1),
|
||||||
_dpad_left_button(-1),
|
_dpad_left_button(-1),
|
||||||
_dpad_up_button(-1)
|
_dpad_up_button(-1),
|
||||||
|
_ltrigger_button(-1),
|
||||||
|
_rtrigger_button(-1)
|
||||||
{
|
{
|
||||||
LightMutexHolder holder(_lock);
|
LightMutexHolder holder(_lock);
|
||||||
if (!open_device()) {
|
if (!open_device()) {
|
||||||
@ -107,6 +110,8 @@ open_device() {
|
|||||||
ioctl(_fd, JSIOCGNAME(sizeof(name)), name);
|
ioctl(_fd, JSIOCGNAME(sizeof(name)), name);
|
||||||
_name = name;
|
_name = name;
|
||||||
|
|
||||||
|
bool have_analog_triggers = false;
|
||||||
|
|
||||||
// Get the number of axes.
|
// Get the number of axes.
|
||||||
uint8_t num_axes = 0, num_buttons = 0;
|
uint8_t num_axes = 0, num_buttons = 0;
|
||||||
ioctl(_fd, JSIOCGAXES, &num_axes);
|
ioctl(_fd, JSIOCGAXES, &num_axes);
|
||||||
@ -120,104 +125,18 @@ open_device() {
|
|||||||
ioctl(_fd, JSIOCGBTNMAP, btnmap);
|
ioctl(_fd, JSIOCGBTNMAP, btnmap);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < num_buttons; ++i) {
|
for (uint8_t i = 0; i < num_buttons; ++i) {
|
||||||
ButtonHandle handle = ButtonHandle::none();
|
ButtonHandle handle = EvdevInputDevice::map_button(btnmap[i]);
|
||||||
switch (btnmap[i]) {
|
if (handle == ButtonHandle::none()) {
|
||||||
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:
|
|
||||||
if (device_cat.is_debug()) {
|
if (device_cat.is_debug()) {
|
||||||
device_cat.debug() << "Unmapped /dev/input/js" << _index
|
device_cat.debug() << "Unmapped /dev/input/js" << _index
|
||||||
<< " button " << (int)i << ": 0x" << hex << btnmap[i] << "\n";
|
<< " button " << (int)i << ": 0x" << hex << btnmap[i] << "\n";
|
||||||
}
|
}
|
||||||
handle = ButtonHandle::none();
|
} else if (handle == GamepadButton::action_a()) {
|
||||||
break;
|
_device_class = DC_gamepad;
|
||||||
|
} else if (handle == GamepadButton::ltrigger()) {
|
||||||
|
_ltrigger_button = i;
|
||||||
|
} else if (handle == GamepadButton::rtrigger()) {
|
||||||
|
_rtrigger_button = i;
|
||||||
}
|
}
|
||||||
_buttons[i].handle = handle;
|
_buttons[i].handle = handle;
|
||||||
}
|
}
|
||||||
@ -333,6 +252,7 @@ open_device() {
|
|||||||
// We'd like to use 0.0 to indicate the resting position.
|
// We'd like to use 0.0 to indicate the resting position.
|
||||||
_controls[i]._scale = 1.0 / 65534.0;
|
_controls[i]._scale = 1.0 / 65534.0;
|
||||||
_controls[i]._bias = 0.5;
|
_controls[i]._bias = 0.5;
|
||||||
|
have_analog_triggers = true;
|
||||||
} else if (axis == C_left_y || axis == C_right_y || axis == C_y) {
|
} else if (axis == C_left_y || axis == C_right_y || axis == C_y) {
|
||||||
_controls[i]._scale = 1.0 / -32767.0;
|
_controls[i]._scale = 1.0 / -32767.0;
|
||||||
_controls[i]._bias = 0.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.
|
// Get additional information from sysfs.
|
||||||
sprintf(path, "/sys/class/input/js%d/device/id/vendor", _index);
|
sprintf(path, "/sys/class/input/js%d/device/id/vendor", _index);
|
||||||
FILE *f = fopen(path, "r");
|
FILE *f = fopen(path, "r");
|
||||||
@ -454,6 +384,11 @@ process_events() {
|
|||||||
int index = events[i].number;
|
int index = events[i].number;
|
||||||
|
|
||||||
if (events[i].type & JS_EVENT_BUTTON) {
|
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));
|
button_changed(index, (events[i].value != 0));
|
||||||
|
|
||||||
} else if (events[i].type & JS_EVENT_AXIS) {
|
} else if (events[i].type & JS_EVENT_AXIS) {
|
||||||
|
@ -45,6 +45,11 @@ private:
|
|||||||
int _dpad_left_button;
|
int _dpad_left_button;
|
||||||
int _dpad_up_button;
|
int _dpad_up_button;
|
||||||
|
|
||||||
|
// This is used for axis emulation.
|
||||||
|
int _ltrigger_control;
|
||||||
|
int _ltrigger_button;
|
||||||
|
int _rtrigger_button;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
return _type_handle;
|
return _type_handle;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user