You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-05 12:10:55 +00:00
Add the ability to get per-platform information for joypads.
This adds the ability for games to obtain platform-specific information about joypads such as their vendor/product ID, their XInput gamepad index or the real name of the device before it gets swapped out by the gamecontrollerdb's name. This PR also includes a rebased version of #76045, this is because this PR is intended to be mainly to help people implementing Steam Input, as having the gamepad index is essential.
This commit is contained in:
@@ -113,6 +113,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("get_joy_info", "device"), &Input::get_joy_info);
|
||||||
ClassDB::bind_method(D_METHOD("should_ignore_device", "vendor_id", "product_id"), &Input::should_ignore_device);
|
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);
|
||||||
@@ -437,11 +438,12 @@ static String _hex_str(uint8_t p_byte) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid) {
|
void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid, Dictionary p_joypad_info) {
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
Joypad js;
|
Joypad js;
|
||||||
js.name = p_connected ? p_name : "";
|
js.name = p_connected ? p_name : "";
|
||||||
js.uid = p_connected ? p_guid : "";
|
js.uid = p_connected ? p_guid : "";
|
||||||
|
js.info = p_connected ? p_joypad_info : Dictionary();
|
||||||
|
|
||||||
if (p_connected) {
|
if (p_connected) {
|
||||||
String uidname = p_guid;
|
String uidname = p_guid;
|
||||||
@@ -1499,6 +1501,11 @@ String Input::get_joy_guid(int p_device) const {
|
|||||||
return joy_names[p_device].uid;
|
return joy_names[p_device].uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dictionary Input::get_joy_info(int p_device) const {
|
||||||
|
ERR_FAIL_COND_V(!joy_names.has(p_device), Dictionary());
|
||||||
|
return joy_names[p_device].info;
|
||||||
|
}
|
||||||
|
|
||||||
bool Input::should_ignore_device(int p_vendor_id, int p_product_id) const {
|
bool Input::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);
|
uint32_t full_id = (((uint32_t)p_vendor_id) << 16) | ((uint16_t)p_product_id);
|
||||||
return ignored_device_ids.has(full_id);
|
return ignored_device_ids.has(full_id);
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ private:
|
|||||||
HatMask last_hat = HatMask::CENTER;
|
HatMask last_hat = HatMask::CENTER;
|
||||||
int mapping = -1;
|
int mapping = -1;
|
||||||
int hat_current = 0;
|
int hat_current = 0;
|
||||||
|
Dictionary info;
|
||||||
};
|
};
|
||||||
|
|
||||||
VelocityTrack mouse_velocity_track;
|
VelocityTrack mouse_velocity_track;
|
||||||
@@ -276,7 +277,7 @@ public:
|
|||||||
Vector2 get_joy_vibration_strength(int p_device);
|
Vector2 get_joy_vibration_strength(int p_device);
|
||||||
float get_joy_vibration_duration(int p_device);
|
float get_joy_vibration_duration(int p_device);
|
||||||
uint64_t get_joy_vibration_timestamp(int p_device);
|
uint64_t get_joy_vibration_timestamp(int p_device);
|
||||||
void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid = "");
|
void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid = "", Dictionary p_joypad_info = Dictionary());
|
||||||
|
|
||||||
Vector3 get_gravity() const;
|
Vector3 get_gravity() const;
|
||||||
Vector3 get_accelerometer() const;
|
Vector3 get_accelerometer() const;
|
||||||
@@ -332,6 +333,7 @@ public:
|
|||||||
bool is_joy_known(int p_device);
|
bool is_joy_known(int p_device);
|
||||||
String get_joy_guid(int p_device) const;
|
String get_joy_guid(int p_device) const;
|
||||||
bool should_ignore_device(int p_vendor_id, int p_product_id) const;
|
bool should_ignore_device(int p_vendor_id, int p_product_id) const;
|
||||||
|
Dictionary get_joy_info(int p_device) const;
|
||||||
void set_fallback_mapping(String p_guid);
|
void set_fallback_mapping(String p_guid);
|
||||||
|
|
||||||
void flush_buffered_events();
|
void flush_buffered_events();
|
||||||
|
|||||||
@@ -121,6 +121,20 @@
|
|||||||
Returns a SDL2-compatible device GUID on platforms that use gamepad remapping, e.g. [code]030000004c050000c405000000010000[/code]. Returns [code]"Default Gamepad"[/code] otherwise. Godot uses the [url=https://github.com/gabomdq/SDL_GameControllerDB]SDL2 game controller database[/url] to determine gamepad names and mappings based on this GUID.
|
Returns a SDL2-compatible device GUID on platforms that use gamepad remapping, e.g. [code]030000004c050000c405000000010000[/code]. Returns [code]"Default Gamepad"[/code] otherwise. Godot uses the [url=https://github.com/gabomdq/SDL_GameControllerDB]SDL2 game controller database[/url] to determine gamepad names and mappings based on this GUID.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="get_joy_info" qualifiers="const">
|
||||||
|
<return type="Dictionary" />
|
||||||
|
<param index="0" name="device" type="int" />
|
||||||
|
<description>
|
||||||
|
Returns a dictionary with extra platform-specific information about the device, e.g. the raw gamepad name from the OS or the Steam Input index.
|
||||||
|
On Windows the dictionary contains the following fields:
|
||||||
|
[code]xinput_index[/code]: The index of the controller in the XInput system.
|
||||||
|
On Linux:
|
||||||
|
[code]raw_name[/code]: The name of the controller as it came from the OS, before getting renamed by the godot controller database.
|
||||||
|
[code]vendor_id[/code]: The USB vendor ID of the device.
|
||||||
|
[code]product_id[/code]: The USB product ID of the device.
|
||||||
|
[code]steam_input_index[/code]: The Steam Input gamepad index, if the device is not a Steam Input device this key won't be present.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="get_joy_name">
|
<method name="get_joy_name">
|
||||||
<return type="String" />
|
<return type="String" />
|
||||||
<param index="0" name="device" type="int" />
|
<param index="0" name="device" type="int" />
|
||||||
|
|||||||
@@ -56,6 +56,14 @@
|
|||||||
static const char *ignore_str = "/dev/input/js";
|
static const char *ignore_str = "/dev/input/js";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// On Linux with Steam Input Xbox 360 devices have an index appended to their device name, this index is
|
||||||
|
// the Steam Input gamepad index
|
||||||
|
#define VALVE_GAMEPAD_NAME_PREFIX "Microsoft X-Box 360 pad "
|
||||||
|
// IDs used by Steam Input virtual controllers.
|
||||||
|
// See https://partner.steamgames.com/doc/features/steam_controller/steam_input_gamepad_emulation_bestpractices
|
||||||
|
#define VALVE_GAMEPAD_VID 0x28DE
|
||||||
|
#define VALVE_GAMEPAD_PID 0x11FF
|
||||||
|
|
||||||
JoypadLinux::Joypad::~Joypad() {
|
JoypadLinux::Joypad::~Joypad() {
|
||||||
for (int i = 0; i < MAX_ABS; i++) {
|
for (int i = 0; i < MAX_ABS; i++) {
|
||||||
if (abs_info[i]) {
|
if (abs_info[i]) {
|
||||||
@@ -411,8 +419,23 @@ 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) {
|
||||||
|
Dictionary joypad_info;
|
||||||
|
joypad_info["vendor_id"] = inpid.vendor;
|
||||||
|
joypad_info["product_id"] = inpid.product;
|
||||||
|
joypad_info["raw_name"] = name;
|
||||||
|
|
||||||
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);
|
|
||||||
|
if (inpid.vendor == VALVE_GAMEPAD_VID && inpid.product == VALVE_GAMEPAD_PID) {
|
||||||
|
if (name.begins_with(VALVE_GAMEPAD_NAME_PREFIX)) {
|
||||||
|
String idx_str = name.substr(strlen(VALVE_GAMEPAD_NAME_PREFIX));
|
||||||
|
if (idx_str.is_valid_int()) {
|
||||||
|
joypad_info["steam_input_index"] = idx_str.to_int();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input->joy_connection_changed(joy_num, true, name, uid, joypad_info);
|
||||||
} else {
|
} else {
|
||||||
String uidname = uid;
|
String uidname = uid;
|
||||||
int uidlen = MIN(name.length(), 11);
|
int uidlen = MIN(name.length(), 11);
|
||||||
|
|||||||
@@ -318,7 +318,9 @@ void JoypadWindows::probe_joypads() {
|
|||||||
x_joypads[i].ff_end_timestamp = 0;
|
x_joypads[i].ff_end_timestamp = 0;
|
||||||
x_joypads[i].vibrating = false;
|
x_joypads[i].vibrating = false;
|
||||||
attached_joypads[id] = true;
|
attached_joypads[id] = true;
|
||||||
input->joy_connection_changed(id, true, "XInput Gamepad", "__XINPUT_DEVICE__");
|
Dictionary joypad_info;
|
||||||
|
joypad_info["xinput_index"] = (int)i;
|
||||||
|
input->joy_connection_changed(id, true, "XInput Gamepad", "__XINPUT_DEVICE__", joypad_info);
|
||||||
}
|
}
|
||||||
} else if (x_joypads[i].attached) {
|
} else if (x_joypads[i].attached) {
|
||||||
x_joypads[i].attached = false;
|
x_joypads[i].attached = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user