mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
device: a couple of fixes with Windows device input
This commit is contained in:
parent
c61b480a41
commit
2bde2baed2
@ -277,7 +277,6 @@ on_input_device_arrival(HANDLE handle) {
|
|||||||
if (info.dwType == RIM_TYPEHID && strstr(path, "&IG_") != nullptr) {
|
if (info.dwType == RIM_TYPEHID && strstr(path, "&IG_") != nullptr) {
|
||||||
// This is a device we should handle via the XInput API. Check which of
|
// This is a device we should handle via the XInput API. Check which of
|
||||||
// the four players was the lucky one.
|
// the four players was the lucky one.
|
||||||
WinRawInputDevice idev(this, path);
|
|
||||||
if (_xinput_device0.check_arrival(info, inst, name, manufacturer)) {
|
if (_xinput_device0.check_arrival(info, inst, name, manufacturer)) {
|
||||||
add_device(&_xinput_device0);
|
add_device(&_xinput_device0);
|
||||||
}
|
}
|
||||||
|
@ -604,13 +604,16 @@ on_removal() {
|
|||||||
_is_connected = false;
|
_is_connected = false;
|
||||||
_handle = nullptr;
|
_handle = nullptr;
|
||||||
if (_preparsed != nullptr) {
|
if (_preparsed != nullptr) {
|
||||||
delete _preparsed;
|
free(_preparsed);
|
||||||
_preparsed = nullptr;
|
_preparsed = nullptr;
|
||||||
}
|
}
|
||||||
_indices.clear();
|
_indices.clear();
|
||||||
_report_buttons.clear();
|
_report_buttons.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by InputDeviceManager when raw input is received for this device.
|
||||||
|
*/
|
||||||
void WinRawInputDevice::
|
void WinRawInputDevice::
|
||||||
on_input(PRAWINPUT input) {
|
on_input(PRAWINPUT input) {
|
||||||
nassertv(input != nullptr);
|
nassertv(input != nullptr);
|
||||||
@ -621,59 +624,68 @@ on_input(PRAWINPUT input) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PHIDP_DATA data = (PHIDP_DATA)alloca(sizeof(HIDP_DATA) * _max_data_count);
|
|
||||||
nassertv(data != nullptr);
|
|
||||||
ULONG count;
|
|
||||||
|
|
||||||
LightMutexHolder holder(_lock);
|
LightMutexHolder holder(_lock);
|
||||||
|
|
||||||
for (DWORD i = 0; i < input->data.hid.dwCount; ++i) {
|
for (DWORD i = 0; i < input->data.hid.dwCount; ++i) {
|
||||||
// The first byte is the report identifier. We need it to figure out
|
process_report((PCHAR)ptr, input->data.hid.dwSizeHid);
|
||||||
// which buttons are off, since each report only contains the buttons that
|
ptr += input->data.hid.dwSizeHid;
|
||||||
// are "on".
|
}
|
||||||
UCHAR report_id = ptr[0];
|
}
|
||||||
BitArray unset_buttons = _report_buttons[report_id];
|
|
||||||
|
|
||||||
count = _max_data_count;
|
/**
|
||||||
NTSTATUS status = _HidP_GetData(HidP_Input, data, &count, (PHIDP_PREPARSED_DATA)_preparsed, (PCHAR)ptr, input->data.hid.dwSizeHid);
|
* Processes a single HID report. Assumes the lock is held.
|
||||||
if (status == HIDP_STATUS_SUCCESS) {
|
*/
|
||||||
for (ULONG di = 0; di < count; ++di) {
|
void WinRawInputDevice::
|
||||||
if (data[di].DataIndex != _hat_data_index) {
|
process_report(PCHAR ptr, size_t size) {
|
||||||
const Index &idx = _indices[data[di].DataIndex];
|
// The first byte is the report identifier. We need it to figure out which
|
||||||
if (idx._axis >= 0) {
|
// buttons are off, since each report only contains the "on" buttons.
|
||||||
if (idx._signed) {
|
UCHAR report_id = ptr[0];
|
||||||
axis_changed(idx._axis, (SHORT)data[di].RawValue);
|
BitArray unset_buttons;
|
||||||
} else {
|
|
||||||
axis_changed(idx._axis, data[di].RawValue);
|
if (report_id < _report_buttons.size()) {
|
||||||
}
|
unset_buttons = _report_buttons[report_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
PHIDP_DATA data = (PHIDP_DATA)alloca(sizeof(HIDP_DATA) * _max_data_count);
|
||||||
|
nassertv(data != nullptr);
|
||||||
|
|
||||||
|
ULONG count = _max_data_count;
|
||||||
|
NTSTATUS status = _HidP_GetData(HidP_Input, data, &count, (PHIDP_PREPARSED_DATA)_preparsed, ptr, size);
|
||||||
|
if (status == HIDP_STATUS_SUCCESS) {
|
||||||
|
for (ULONG di = 0; di < count; ++di) {
|
||||||
|
if (data[di].DataIndex != _hat_data_index) {
|
||||||
|
const Index &idx = _indices[data[di].DataIndex];
|
||||||
|
if (idx._axis >= 0) {
|
||||||
|
if (idx._signed) {
|
||||||
|
axis_changed(idx._axis, (SHORT)data[di].RawValue);
|
||||||
|
} else {
|
||||||
|
axis_changed(idx._axis, data[di].RawValue);
|
||||||
}
|
}
|
||||||
if (idx._button >= 0) {
|
|
||||||
unset_buttons.clear_bit(idx._button);
|
|
||||||
button_changed(idx._button, (data[di].On != FALSE));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int value = (int)data[di].RawValue - _hat_data_minimum;
|
|
||||||
button_changed(_hat_left_button + 0, value >= 5 && value <= 7); // left
|
|
||||||
button_changed(_hat_left_button + 1, value >= 1 && value <= 3); // right
|
|
||||||
button_changed(_hat_left_button + 2, value >= 3 && value <= 5); // down
|
|
||||||
button_changed(_hat_left_button + 3, value == 7 || value == 0 || value == 1); // up
|
|
||||||
}
|
}
|
||||||
|
if (idx._button >= 0) {
|
||||||
|
unset_buttons.clear_bit(idx._button);
|
||||||
|
button_changed(idx._button, (data[di].On != FALSE));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int value = (int)data[di].RawValue - _hat_data_minimum;
|
||||||
|
button_changed(_hat_left_button + 0, value >= 5 && value <= 7); // left
|
||||||
|
button_changed(_hat_left_button + 1, value >= 1 && value <= 3); // right
|
||||||
|
button_changed(_hat_left_button + 2, value >= 3 && value <= 5); // down
|
||||||
|
button_changed(_hat_left_button + 3, value == 7 || value == 0 || value == 1); // up
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now unset the buttons in this report that aren't pressed.
|
|
||||||
int button_index = unset_buttons.get_lowest_on_bit();
|
|
||||||
while (button_index >= 0) {
|
|
||||||
button_changed(button_index, false);
|
|
||||||
unset_buttons.clear_bit(button_index);
|
|
||||||
button_index = unset_buttons.get_lowest_on_bit();
|
|
||||||
}
|
|
||||||
} else if (device_cat.is_spam()) {
|
|
||||||
device_cat.spam()
|
|
||||||
<< "Failed to get data from raw device " << _path
|
|
||||||
<< " (error 0x" << std::hex << (status & 0xffffffffu) << std::dec << ")\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr += input->data.hid.dwSizeHid;
|
// Now unset the buttons in this report that aren't pressed.
|
||||||
|
int button_index = unset_buttons.get_lowest_on_bit();
|
||||||
|
while (button_index >= 0) {
|
||||||
|
button_changed(button_index, false);
|
||||||
|
unset_buttons.clear_bit(button_index);
|
||||||
|
button_index = unset_buttons.get_lowest_on_bit();
|
||||||
|
}
|
||||||
|
} else if (device_cat.is_spam()) {
|
||||||
|
device_cat.spam()
|
||||||
|
<< "Failed to get data from raw device " << _path
|
||||||
|
<< " (error 0x" << std::hex << (status & 0xffffffffu) << std::dec << ")\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ public:
|
|||||||
bool on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name);
|
bool on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name);
|
||||||
void on_removal();
|
void on_removal();
|
||||||
void on_input(PRAWINPUT input);
|
void on_input(PRAWINPUT input);
|
||||||
|
void process_report(PCHAR ptr, size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void do_poll();
|
virtual void do_poll();
|
||||||
|
@ -161,6 +161,10 @@ check_arrival(const RID_DEVICE_INFO &info, DEVINST inst,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (get_state(_index, &state) != ERROR_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Extra check for VID/PID if we have it, just to be sure.
|
// Extra check for VID/PID if we have it, just to be sure.
|
||||||
if ((caps.VendorID != 0 && caps.VendorID != info.hid.dwVendorId) ||
|
if ((caps.VendorID != 0 && caps.VendorID != info.hid.dwVendorId) ||
|
||||||
(caps.ProductID != 0 && caps.ProductID != info.hid.dwProductId)) {
|
(caps.ProductID != 0 && caps.ProductID != info.hid.dwProductId)) {
|
||||||
@ -205,6 +209,10 @@ check_arrival(const RID_DEVICE_INFO &info, DEVINST inst,
|
|||||||
*/
|
*/
|
||||||
void XInputDevice::
|
void XInputDevice::
|
||||||
detect(InputDeviceManager *mgr) {
|
detect(InputDeviceManager *mgr) {
|
||||||
|
if (!_initialized) {
|
||||||
|
nassertv_always(init_xinput());
|
||||||
|
}
|
||||||
|
|
||||||
bool connected = false;
|
bool connected = false;
|
||||||
|
|
||||||
XINPUT_CAPABILITIES_EX caps = {0};
|
XINPUT_CAPABILITIES_EX caps = {0};
|
||||||
@ -225,6 +233,10 @@ detect(InputDeviceManager *mgr) {
|
|||||||
_is_connected = connected;
|
_is_connected = connected;
|
||||||
|
|
||||||
if (connected) {
|
if (connected) {
|
||||||
|
_name = "XInput Device #";
|
||||||
|
_name += format_string(_index + 1);
|
||||||
|
_vendor_id = caps.VendorID;
|
||||||
|
_product_id = caps.ProductID;
|
||||||
init_device(caps, state);
|
init_device(caps, state);
|
||||||
mgr->add_device(this);
|
mgr->add_device(this);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user