[3.x] Prevent double input events on gamepad when running through steam input #79706
Co-authored-by: Eoin O'Neill <eoinoneill1991@gmail.com>
This commit is contained in:
parent
ac5d7dc821
commit
140440ee82
6 changed files with 51 additions and 4 deletions
|
@ -72,6 +72,7 @@ void Input::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_joy_axis", "device", "axis"), &Input::get_joy_axis);
|
ClassDB::bind_method(D_METHOD("get_joy_axis", "device", "axis"), &Input::get_joy_axis);
|
||||||
ClassDB::bind_method(D_METHOD("get_joy_name", "device"), &Input::get_joy_name);
|
ClassDB::bind_method(D_METHOD("get_joy_name", "device"), &Input::get_joy_name);
|
||||||
ClassDB::bind_method(D_METHOD("get_joy_guid", "device"), &Input::get_joy_guid);
|
ClassDB::bind_method(D_METHOD("get_joy_guid", "device"), &Input::get_joy_guid);
|
||||||
|
ClassDB::bind_method(D_METHOD("should_ignore_device", "vendor_id", "product_id"), &Input::should_ignore_device);
|
||||||
ClassDB::bind_method(D_METHOD("get_connected_joypads"), &Input::get_connected_joypads);
|
ClassDB::bind_method(D_METHOD("get_connected_joypads"), &Input::get_connected_joypads);
|
||||||
ClassDB::bind_method(D_METHOD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength);
|
ClassDB::bind_method(D_METHOD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength);
|
||||||
ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration);
|
ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration);
|
||||||
|
|
|
@ -100,6 +100,7 @@ public:
|
||||||
virtual void remove_joy_mapping(String p_guid) = 0;
|
virtual void remove_joy_mapping(String p_guid) = 0;
|
||||||
virtual bool is_joy_known(int p_device) = 0;
|
virtual bool is_joy_known(int p_device) = 0;
|
||||||
virtual String get_joy_guid(int p_device) const = 0;
|
virtual String get_joy_guid(int p_device) const = 0;
|
||||||
|
virtual bool should_ignore_device(int p_vendor_id, int p_product_id) const = 0;
|
||||||
virtual Vector2 get_joy_vibration_strength(int p_device) = 0;
|
virtual Vector2 get_joy_vibration_strength(int p_device) = 0;
|
||||||
virtual float get_joy_vibration_duration(int p_device) = 0;
|
virtual float get_joy_vibration_duration(int p_device) = 0;
|
||||||
virtual uint64_t get_joy_vibration_timestamp(int p_device) = 0;
|
virtual uint64_t get_joy_vibration_timestamp(int p_device) = 0;
|
||||||
|
|
|
@ -360,6 +360,15 @@
|
||||||
[b]Note:[/b] This value can be immediately overwritten by the hardware sensor value on Android and iOS.
|
[b]Note:[/b] This value can be immediately overwritten by the hardware sensor value on Android and iOS.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="should_ignore_device" qualifiers="const">
|
||||||
|
<return type="bool" />
|
||||||
|
<argument index="0" name="vendor_id" type="int" />
|
||||||
|
<argument index="1" name="product_id" type="int" />
|
||||||
|
<description>
|
||||||
|
Queries whether an input device should be ignored or not. Devices can be ignored by setting the environment variable [code]SDL_GAMECONTROLLER_IGNORE_DEVICES[/code]. Read the [url=https://wiki.libsdl.org/SDL2]SDL documentation[/url] for more information.
|
||||||
|
[b]Note:[/b] Some 3rd party tools can contribute to the list of ignored devices. For example, [i]SteamInput[/i] creates virtual devices from physical devices for remapping purposes. To avoid handling the same input device twice, the original device is added to the ignore list.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="start_joy_vibration">
|
<method name="start_joy_vibration">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<argument index="0" name="device" type="int" />
|
<argument index="0" name="device" type="int" />
|
||||||
|
|
|
@ -858,6 +858,27 @@ InputDefault::InputDefault() {
|
||||||
parse_mapping(entries[i]);
|
parse_mapping(entries[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String env_ignore_devices = OS::get_singleton()->get_environment("SDL_GAMECONTROLLER_IGNORE_DEVICES");
|
||||||
|
if (!env_ignore_devices.empty()) {
|
||||||
|
Vector<String> entries = env_ignore_devices.split(",");
|
||||||
|
for (int i = 0; i < entries.size(); i++) {
|
||||||
|
Vector<String> vid_pid = entries[i].split("/");
|
||||||
|
|
||||||
|
if (vid_pid.size() < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_verbose(vformat("Device Ignored -- Vendor: %s Product: %s", vid_pid[0], vid_pid[1]));
|
||||||
|
const uint16_t vid_unswapped = vid_pid[0].hex_to_int();
|
||||||
|
const uint16_t pid_unswapped = vid_pid[1].hex_to_int();
|
||||||
|
const uint16_t vid = BSWAP16(vid_unswapped);
|
||||||
|
const uint16_t pid = BSWAP16(pid_unswapped);
|
||||||
|
|
||||||
|
uint32_t full_id = (((uint32_t)vid) << 16) | ((uint16_t)pid);
|
||||||
|
ignored_device_ids.insert(full_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputDefault::joy_button(int p_device, int p_button, bool p_pressed) {
|
void InputDefault::joy_button(int p_device, int p_button, bool p_pressed) {
|
||||||
|
@ -1350,6 +1371,11 @@ String InputDefault::get_joy_guid(int p_device) const {
|
||||||
return OS::get_singleton()->get_joy_guid(p_device);
|
return OS::get_singleton()->get_joy_guid(p_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InputDefault::should_ignore_device(int p_vendor_id, int p_product_id) const {
|
||||||
|
uint32_t full_id = (((uint32_t)p_vendor_id) << 16) | ((uint16_t)p_product_id);
|
||||||
|
return ignored_device_ids.has(full_id);
|
||||||
|
}
|
||||||
|
|
||||||
//platforms that use the remapping system can override and call to these ones
|
//platforms that use the remapping system can override and call to these ones
|
||||||
bool InputDefault::is_joy_mapped(int p_device) {
|
bool InputDefault::is_joy_mapped(int p_device) {
|
||||||
if (joy_names.has(p_device)) {
|
if (joy_names.has(p_device)) {
|
||||||
|
|
|
@ -193,6 +193,8 @@ private:
|
||||||
|
|
||||||
Vector<JoyDeviceMapping> map_db;
|
Vector<JoyDeviceMapping> map_db;
|
||||||
|
|
||||||
|
Set<uint32_t> ignored_device_ids;
|
||||||
|
|
||||||
JoyEvent _get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button);
|
JoyEvent _get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button);
|
||||||
JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, float p_value);
|
JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, float p_value);
|
||||||
void _get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, JoyEvent r_events[HAT_MAX]);
|
void _get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, JoyEvent r_events[HAT_MAX]);
|
||||||
|
@ -295,6 +297,8 @@ public:
|
||||||
virtual bool is_joy_known(int p_device);
|
virtual bool is_joy_known(int p_device);
|
||||||
virtual String get_joy_guid(int p_device) const;
|
virtual String get_joy_guid(int p_device) const;
|
||||||
|
|
||||||
|
bool should_ignore_device(int p_vendor_id, int p_product_id) const;
|
||||||
|
|
||||||
virtual String get_joy_button_string(int p_button);
|
virtual String get_joy_button_string(int p_button);
|
||||||
virtual String get_joy_axis_string(int p_axis);
|
virtual String get_joy_axis_string(int p_axis);
|
||||||
virtual int get_joy_axis_index_from_string(String p_axis);
|
virtual int get_joy_axis_index_from_string(String p_axis);
|
||||||
|
|
|
@ -387,6 +387,16 @@ void JoypadLinux::open_joypad(const char *p_path) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t vendor = BSWAP16(inpid.vendor);
|
||||||
|
uint16_t product = BSWAP16(inpid.product);
|
||||||
|
uint16_t version = BSWAP16(inpid.version);
|
||||||
|
|
||||||
|
if (input->should_ignore_device(vendor, product)) {
|
||||||
|
// This can be true in cases where Steam is passing information into the game to ignore
|
||||||
|
// original gamepads when using virtual rebindings (See SteamInput).
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MutexLock lock(joypads_mutex[joy_num]);
|
MutexLock lock(joypads_mutex[joy_num]);
|
||||||
Joypad &joypad = joypads[joy_num];
|
Joypad &joypad = joypads[joy_num];
|
||||||
joypad.reset();
|
joypad.reset();
|
||||||
|
@ -395,10 +405,6 @@ void JoypadLinux::open_joypad(const char *p_path) {
|
||||||
setup_joypad_properties(joypad);
|
setup_joypad_properties(joypad);
|
||||||
sprintf(uid, "%04x%04x", BSWAP16(inpid.bustype), 0);
|
sprintf(uid, "%04x%04x", BSWAP16(inpid.bustype), 0);
|
||||||
if (inpid.vendor && inpid.product && inpid.version) {
|
if (inpid.vendor && inpid.product && inpid.version) {
|
||||||
uint16_t vendor = BSWAP16(inpid.vendor);
|
|
||||||
uint16_t product = BSWAP16(inpid.product);
|
|
||||||
uint16_t version = BSWAP16(inpid.version);
|
|
||||||
|
|
||||||
sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor, 0, product, 0, version, 0);
|
sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor, 0, product, 0, version, 0);
|
||||||
input->joy_connection_changed(joy_num, true, name, uid);
|
input->joy_connection_changed(joy_num, true, name, uid);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue