From 0d807264a1d6cf6c6055171021f7e984bdce5b1d Mon Sep 17 00:00:00 2001 From: Ariel Manzur Date: Mon, 2 Mar 2015 16:57:18 +0100 Subject: [PATCH] supports SDLs joystick database format and remaps joystick events --- core/os/input.cpp | 386 ++++++++++++++++++++++++++++++-- core/os/input.h | 88 +++++++- platform/windows/os_windows.cpp | 108 ++------- platform/windows/os_windows.h | 6 +- 4 files changed, 483 insertions(+), 105 deletions(-) diff --git a/core/os/input.cpp b/core/os/input.cpp index 5d4b3a834dc6..e9f03cc78754 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -223,20 +223,6 @@ float InputDefault::get_joy_axis(int p_device,int p_axis) { } } -String InputDefault::get_joy_name(int p_idx) { - - _THREAD_SAFE_METHOD_ - return joy_names[p_idx]; -}; - -void InputDefault::joy_connection_changed(int p_idx, bool p_connected, String p_name) { - - _THREAD_SAFE_METHOD_ - joy_names[p_idx] = p_connected ? p_name : ""; - - emit_signal("joy_connection_changed", p_idx, p_connected); -}; - Vector3 InputDefault::get_accelerometer() { _THREAD_SAFE_METHOD_ @@ -362,8 +348,380 @@ void InputDefault::action_release(const StringName& p_action){ } } +String InputDefault::get_joy_name(int p_idx) { + + _THREAD_SAFE_METHOD_; + return joy_names[p_idx].name; +}; + +static String _hex_str(uint8_t p_byte) { + + static const char* dict = "0123456789abcdef"; + char ret[3]; + ret[2] = 0; + + ret[0] = dict[p_byte>>4]; + ret[1] = dict[p_byte & 0xf]; + + return ret; +}; + +void InputDefault::joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid) { + + _THREAD_SAFE_METHOD_; + Joystick js; + js.name = p_connected ? p_name : ""; + js.uid = p_connected ? p_guid : ""; + js.mapping = -1; + js.hat_current = 0; + if (p_connected) { + + String uidname = p_guid; + if (p_guid == "") { + int uidlen = MIN(p_name.length(), 16); + for (int i=0; i::Element* el = map_db[joy.mapping].buttons.find(p_button); + if (!el) { + return _button_event(p_last_id, p_device, p_button, p_pressed); + }; + + JoyEvent map = el->get(); + if (map.type == TYPE_BUTTON) { + + return _button_event(p_last_id, p_device, map.index, p_pressed); + }; + + if (map.type == TYPE_AXIS) { + return _axis_event(p_last_id, p_device, map.index, p_pressed ? 1.0 : 0.0); + }; + + return p_last_id; // no event? +}; + +uint32_t InputPC::joy_axis(uint32_t p_last_id, int p_device, int p_axis, float p_value) { + + _THREAD_SAFE_METHOD_; + const Joystick& joy = joy_names[p_device]; + + if (joy.mapping == -1) { + return _axis_event(p_last_id, p_device, p_axis, p_value); + }; + + Map::Element* el = map_db[joy.mapping].axis.find(p_axis); + if (!el) { + return _axis_event(p_last_id, p_device, p_axis, p_value); + }; + + JoyEvent map = el->get(); + if (map.type == TYPE_BUTTON) { + return _button_event(p_last_id, p_device, map.index, Math::abs(p_value) > 0.5 ? true : false); + }; + + if (map.type == TYPE_AXIS) { + + return _axis_event(p_last_id, p_device, map.index, p_value); + }; + + return p_last_id; +}; + +uint32_t InputPC::joy_hat(uint32_t p_last_id, int p_device, int p_val) { + + _THREAD_SAFE_METHOD_; + const Joystick& joy = joy_names[p_device]; + + JoyEvent* map; + + if (joy.mapping == -1) { + map = hat_map_default; + } else { + map = map_db[joy.mapping].hat; + }; + + int cur_val = joy_names[p_device].hat_current; + + if ( (p_val & HAT_MASK_UP) != (cur_val & HAT_MASK_UP) ) { + p_last_id = _button_event(p_last_id, p_device, map[HAT_UP].index, p_val & HAT_MASK_UP); + }; + + if ( (p_val & HAT_MASK_RIGHT) != (cur_val & HAT_MASK_RIGHT) ) { + p_last_id = _button_event(p_last_id, p_device, map[HAT_RIGHT].index, p_val & HAT_MASK_RIGHT); + }; + if ( (p_val & HAT_MASK_DOWN) != (cur_val & HAT_MASK_DOWN) ) { + p_last_id = _button_event(p_last_id, p_device, map[HAT_DOWN].index, p_val & HAT_MASK_DOWN); + }; + if ( (p_val & HAT_MASK_LEFT) != (cur_val & HAT_MASK_LEFT) ) { + p_last_id = _button_event(p_last_id, p_device, map[HAT_LEFT].index, p_val & HAT_MASK_LEFT); + }; + + joy_names[p_device].hat_current = p_val; + + return p_last_id; +}; + +uint32_t InputPC::_button_event(uint32_t p_last_id, int p_device, int p_index, bool p_pressed) { + + InputEvent ievent; + ievent.type = InputEvent::JOYSTICK_BUTTON; + ievent.device = p_device; + ievent.ID = ++p_last_id; + ievent.joy_button.button_index = p_index; + ievent.joy_button.pressed = p_pressed; + + parse_input_event(ievent); + + return p_last_id; +}; + +uint32_t InputPC::_axis_event(uint32_t p_last_id, int p_device, int p_axis, float p_value) { + + InputEvent ievent; + ievent.type = InputEvent::JOYSTICK_MOTION; + ievent.device = p_device; + ievent.ID = ++p_last_id; + ievent.joy_motion.axis = p_axis; + ievent.joy_motion.axis_value = p_value; + + parse_input_event( ievent ); + + return p_last_id; +}; + +static const char *s_ControllerMappings [] = +{ +#ifdef WINDOWS_ENABLED + "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", + "ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", + "6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", + "6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */ + "4d6963726f736f66742050432d6a6f79,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a5,righty:a4,x:b1,y:b2,", + "88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,", + "4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", + "25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,", + "4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", +#endif +#ifdef OSX_ENABLED + "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", + "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */ + "6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", + "6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", + "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */ + "4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", + "4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", + "5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", +#endif +#if X11_ENABLED + "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", + "03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,", + "030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", + "030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */ + "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "050000003620000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,", + "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", + "030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", + "050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", + "03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", +#endif +#if defined(__ANDROID__) + "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", +#endif + NULL +}; + +static int char2int(char p_input) +{ + if(p_input >= '0' && p_input <= '9') + return p_input - '0'; + if(p_input >= 'A' && p_input <= 'F') + return p_input - 'A' + 10; + if(p_input >= 'a' && p_input <= 'f') + return p_input - 'a' + 10; + return -1; +} + +InputPC::JoyEvent InputPC::_find_to_event(String p_to) { + + // string names of the SDL buttons in the same order as input_event.h godot buttons + static const char* buttons[] = {"b", "a", "x", "y", "leftshoulder", "rightshoulder", "lefttrigger", "righttrigger", "leftstick", "rightstick", "back", "start", "dpup", "dpdown", "dpleft", "dpright", NULL }; + + // same for axis + static const char* axis[] = {"leftx", "lefty", "rightx", "righty", NULL }; + + JoyEvent ret; + ret.type = -1; + + int i=0; + while (buttons[i]) { + + if (p_to == buttons[i]) { + ret.type = TYPE_BUTTON; + ret.index = i; + ret.value = 0; + return ret; + }; + ++i; + }; + + i = 0; + while (axis[i]) { + + if (p_to == axis[i]) { + ret.type = TYPE_AXIS; + ret.index = i; + ret.value = 0; + return ret; + }; + ++i; + }; + + return ret; +}; + +void InputPC::parse_mapping(String p_mapping) { + + _THREAD_SAFE_METHOD_; + JoyDeviceMapping mapping; + + Vector entry = p_mapping.split(","); + CharString uid; + uid.resize(17); + + mapping.uid = entry[0]; + + int idx = 1; + while (++idx < entry.size()) { + + if (entry[idx] == "") + continue; + + String from = entry[idx].get_slice(":", 1); + String to = entry[idx].get_slice(":", 0); + + JoyEvent to_event = _find_to_event(to); + if (to_event.type == -1) + continue; + + String etype = from.substr(0, 1); + if (etype == "a") { + + int aid = from.substr(1, from.length()-1).to_int(); + mapping.axis[aid] = to_event; + + } else if (etype == "b") { + + int bid = from.substr(1, from.length()-1).to_int(); + mapping.buttons[bid] = to_event; + + } else if (etype == "h") { + + int hat_value = from.get_slice(".", 1).to_int(); + switch (hat_value) { + case 1: + mapping.hat[HAT_UP] = to_event; + break; + case 2: + mapping.hat[HAT_RIGHT] = to_event; + break; + case 4: + mapping.hat[HAT_DOWN] = to_event; + break; + case 8: + mapping.hat[HAT_LEFT] = to_event; + break; + }; + }; + }; + map_db.push_back(mapping); + printf("added mapping with uuid %ls\n", mapping.uid.c_str()); +}; + +InputPC::InputPC() { + + hat_map_default[HAT_UP].type = TYPE_BUTTON; + hat_map_default[HAT_UP].index = JOY_DPAD_UP; + hat_map_default[HAT_UP].value = 0; + + hat_map_default[HAT_RIGHT].type = TYPE_BUTTON; + hat_map_default[HAT_RIGHT].index = JOY_DPAD_RIGHT; + hat_map_default[HAT_RIGHT].value = 0; + + hat_map_default[HAT_DOWN].type = TYPE_BUTTON; + hat_map_default[HAT_DOWN].index = JOY_DPAD_DOWN; + hat_map_default[HAT_DOWN].value = 0; + + hat_map_default[HAT_LEFT].type = TYPE_BUTTON; + hat_map_default[HAT_LEFT].index = JOY_DPAD_LEFT; + hat_map_default[HAT_LEFT].value = 0; + + int i = 0; + while (s_ControllerMappings[i]) { + + parse_mapping(s_ControllerMappings[i++]); + }; + + String env_mapping = OS::get_singleton()->get_environment("SDL_GAMECONTROLLERCONFIG"); + if (env_mapping != "") { + + Vector entries = env_mapping.split("\n"); + for (int i=0; i < entries.size(); i++) { + if (entries[i] == "") + continue; + parse_mapping(entries[i]); + }; + }; +}; + +InputPC::~InputPC() { + +}; diff --git a/core/os/input.h b/core/os/input.h index 387a43a35a4a..1e0470ebf127 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -62,7 +62,7 @@ class Input : public Object { virtual float get_joy_axis(int p_device,int p_axis)=0; virtual String get_joy_name(int p_idx)=0; - virtual void joy_connection_changed(int p_idx, bool p_connected, String p_name)=0; + virtual void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid = "")=0; virtual Point2 get_mouse_pos() const=0; @@ -87,6 +87,8 @@ VARIANT_ENUM_CAST(Input::MouseMode); class InputDefault : public Input { OBJ_TYPE( InputDefault, Input ); + +protected: _THREAD_SAFE_CLASS_ int mouse_button_mask; @@ -94,7 +96,6 @@ class InputDefault : public Input { Set joy_buttons_pressed; Map joy_axis; Map custom_action_press; - Map joy_names; Vector3 accelerometer; Vector2 mouse_pos; MainLoop *main_loop; @@ -115,6 +116,15 @@ class InputDefault : public Input { SpeedTrack mouse_speed_track; + struct Joystick { + StringName name; + StringName uid; + int mapping; + int hat_current; + }; + + Map joy_names; + public: virtual bool is_key_pressed(int p_scancode); @@ -123,8 +133,9 @@ class InputDefault : public Input { virtual bool is_action_pressed(const StringName& p_action); virtual float get_joy_axis(int p_device,int p_axis); + String get_joy_name(int p_idx); - void joy_connection_changed(int p_idx, bool p_connected, String p_name); + void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid=""); virtual Vector3 get_accelerometer(); @@ -134,7 +145,6 @@ class InputDefault : public Input { virtual void warp_mouse_pos(const Vector2& p_to); - void parse_input_event(const InputEvent& p_event); void set_accelerometer(const Vector3& p_accel); void set_joy_axis(int p_device,int p_axis,float p_value); @@ -151,4 +161,74 @@ class InputDefault : public Input { }; +class InputPC : public InputDefault { + + OBJ_TYPE( InputPC, InputDefault ); + +public: + enum HatMask { + HAT_MASK_CENTER = 0, + HAT_MASK_UP = 1, + HAT_MASK_RIGHT = 2, + HAT_MASK_DOWN = 4, + HAT_MASK_LEFT = 8, + }; + + enum HatDir { + HAT_UP, + HAT_RIGHT, + HAT_DOWN, + HAT_LEFT, + HAT_MAX, + }; + +private: + + enum JoyType { + TYPE_BUTTON, + TYPE_AXIS, + TYPE_HAT, + TYPE_MAX, + }; + + struct JoyEvent { + int type; + int index; + int value; + }; + + struct JoyDeviceMapping { + + String uid; + Map buttons; + Map axis; + JoyEvent hat[HAT_MAX]; + }; + + JoyEvent hat_map_default[HAT_MAX]; + + Vector map_db; + + JoyEvent _find_to_event(String p_to); + uint32_t _button_event(uint32_t p_last_id, int p_device, int p_index, bool p_pressed); + uint32_t _axis_event(uint32_t p_last_id, int p_device, int p_axis, float p_value); + +protected: + + +public: + + void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid=""); + + void parse_mapping(String p_mapping); + + uint32_t joy_button(uint32_t p_last_id, int p_device, int p_button, bool p_pressed); + uint32_t joy_axis(uint32_t p_last_id, int p_device, int p_axis, float p_value); + uint32_t joy_hat(uint32_t p_last_id, int p_device, int p_val); + + InputPC(); + ~InputPC(); +}; + + #endif // INPUT_H diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index e392a56aa8f8..58e7c919212a 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -688,7 +688,7 @@ LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { } -String OS_Windows::get_joystick_name(int id, JOYCAPS jcaps) +String OS_Windows::get_joystick_name(int id, JOYCAPS jcaps, HKEY p_hkey) { char buffer [256]; char OEM [256]; @@ -699,7 +699,7 @@ String OS_Windows::get_joystick_name(int id, JOYCAPS jcaps) _snprintf(buffer, sizeof(buffer), "%s\\%s\\%s", REGSTR_PATH_JOYCONFIG, jcaps.szRegKey, REGSTR_KEY_JOYCURR ); - res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey); + res = RegOpenKeyEx(p_hkey, buffer, 0, KEY_QUERY_VALUE, &hKey); if (res != ERROR_SUCCESS) { res = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, 0, KEY_QUERY_VALUE, &hKey); @@ -715,14 +715,9 @@ String OS_Windows::get_joystick_name(int id, JOYCAPS jcaps) return ""; _snprintf( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEM); - res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey); - if (res != ERROR_SUCCESS) - { - res = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, 0, KEY_QUERY_VALUE, &hKey); - if (res != ERROR_SUCCESS) - return ""; - } - + res = RegOpenKeyEx ( p_hkey, buffer, 0, KEY_QUERY_VALUE, &hKey); + if (res != ERROR_SUCCESS) + return ""; sz = sizeof(buffer); res = RegQueryValueEx(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buffer, @@ -775,7 +770,9 @@ void OS_Windows::probe_joysticks() { JOYCAPS jcaps; MMRESULT res = joyGetDevCaps(JOYSTICKID1 + i, &jcaps, sizeof(jcaps)); if (res == JOYERR_NOERROR) { - String name = get_joystick_name(JOYSTICKID1 + i, jcaps); + String name = get_joystick_name(JOYSTICKID1 + i, jcaps, HKEY_LOCAL_MACHINE); + if (name == "") + name = get_joystick_name(JOYSTICKID1 + i, jcaps, HKEY_CURRENT_USER); if ( name == "") joy.name = jcaps.szPname; else @@ -860,78 +857,44 @@ void OS_Windows::process_key_events() { key_event_pos=0; } -void OS_Windows::_post_dpad(DWORD p_dpad, int p_device, bool p_pressed) { +void OS_Windows::_post_hat(int p_device, DWORD p_dpad) { - InputEvent ievent; - ievent.device = p_device; - ievent.type = InputEvent::JOYSTICK_BUTTON; - ievent.joy_button.pressed = p_pressed; - ievent.joy_button.pressure = p_pressed ? 1.0 : 0.0; + int dpad_val = 0; if (p_dpad == 0) { - ievent.joy_button.button_index = JOY_DPAD_UP; - ievent.ID = ++last_id; - input->parse_input_event(ievent); + dpad_val = 0; } else if (p_dpad == 4500) { - ievent.joy_button.button_index = JOY_DPAD_UP; - ievent.ID = ++last_id; - input->parse_input_event(ievent); - - ievent.joy_button.button_index = JOY_DPAD_RIGHT; - ievent.ID = ++last_id; - input->parse_input_event(ievent); + dpad_val = ( InputPC::HAT_MASK_UP | InputPC::HAT_MASK_RIGHT ); } else if (p_dpad == 9000) { - ievent.joy_button.button_index = JOY_DPAD_RIGHT; - ievent.ID = ++last_id; - input->parse_input_event(ievent); + dpad_val = InputPC::HAT_MASK_RIGHT; } else if (p_dpad == 13500) { - ievent.joy_button.button_index = JOY_DPAD_RIGHT; - ievent.ID = ++last_id; - input->parse_input_event(ievent); - - ievent.joy_button.button_index = JOY_DPAD_DOWN; - ievent.ID = ++last_id; - input->parse_input_event(ievent); + dpad_val = ( InputPC::HAT_MASK_RIGHT | InputPC::HAT_MASK_DOWN ); } else if (p_dpad == 18000) { - ievent.joy_button.button_index = JOY_DPAD_DOWN; - ievent.ID = ++last_id; - input->parse_input_event(ievent); + dpad_val = InputPC::HAT_MASK_DOWN; } else if (p_dpad == 22500) { - ievent.joy_button.button_index = JOY_DPAD_DOWN; - ievent.ID = ++last_id; - input->parse_input_event(ievent); - - ievent.joy_button.button_index = JOY_DPAD_LEFT; - ievent.ID = ++last_id; - input->parse_input_event(ievent); + dpad_val = ( InputPC::HAT_MASK_DOWN | InputPC::HAT_MASK_LEFT ); } else if (p_dpad == 27000) { - ievent.joy_button.button_index = JOY_DPAD_LEFT; - ievent.ID = ++last_id; - input->parse_input_event(ievent); + dpad_val = InputPC::HAT_MASK_LEFT; } else if (p_dpad == 31500) { - ievent.joy_button.button_index = JOY_DPAD_LEFT; - ievent.ID = ++last_id; - input->parse_input_event(ievent); - - ievent.joy_button.button_index = JOY_DPAD_UP; - ievent.ID = ++last_id; - input->parse_input_event(ievent); + dpad_val = ( InputPC::HAT_MASK_LEFT | InputPC::HAT_MASK_UP ); }; + + last_id = input->joy_hat(last_id, p_device, dpad_val); }; void OS_Windows::process_joysticks() { @@ -940,8 +903,6 @@ void OS_Windows::process_joysticks() { return; }; - InputEvent ievent; - JOYINFOEX jinfo; jinfo.dwSize = sizeof(JOYINFOEX); jinfo.dwFlags = JOY_RETURNALL; @@ -957,16 +918,10 @@ void OS_Windows::process_joysticks() { continue; }; - ievent.device = i; - #define CHECK_AXIS(n, var) \ if (joysticks[i].last_axis[n] != var) {\ - ievent.type = InputEvent::JOYSTICK_MOTION;\ - ievent.ID = ++last_id;\ - ievent.joy_motion.axis = n;\ - ievent.joy_motion.axis_value = (float)((int)var - MAX_JOY_AXIS) / (float)MAX_JOY_AXIS;\ + last_id = input->joy_axis(last_id, i, n, (float)((int)var - MAX_JOY_AXIS) / (float)MAX_JOY_AXIS);\ joysticks[i].last_axis[n] = var;\ - input->parse_input_event(ievent);\ }; CHECK_AXIS(0, jinfo.dwXpos); @@ -976,30 +931,17 @@ void OS_Windows::process_joysticks() { CHECK_AXIS(4, jinfo.dwUpos); CHECK_AXIS(5, jinfo.dwVpos); - if (joysticks[i].last_pov != jinfo.dwPOV) { - - if (joysticks[i].last_pov != JOY_POVCENTERED) - _post_dpad(joysticks[i].last_pov, i, false); - - if (jinfo.dwPOV != JOY_POVCENTERED) - _post_dpad(jinfo.dwPOV, i, true); - - joysticks[i].last_pov = jinfo.dwPOV; - }; + _post_hat(i, jinfo.dwPOV); if (joysticks[i].last_buttons == jinfo.dwButtons) { continue; }; - ievent.type = InputEvent::JOYSTICK_BUTTON; for (int j=0; j<32; j++) { if ( (joysticks[i].last_buttons & (1<parse_input_event(ievent); + last_id = input->joy_button(last_id, i, j, jinfo.dwButtons & 1<init(); - input = memnew( InputDefault ); + input = memnew( InputPC ); AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton(); @@ -2002,8 +1944,6 @@ String OS_Windows::get_data_dir() const { } return Globals::get_singleton()->get_resource_path(); - - } diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 210e25d2d6b5..0fc5fa04ad4e 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -152,13 +152,13 @@ class OS_Windows : public OS { CursorShape cursor_shape; - InputDefault *input; + InputPC *input; #ifdef RTAUDIO_ENABLED AudioDriverRtAudio driver_rtaudio; #endif - void _post_dpad(DWORD p_dpad, int p_device, bool p_pressed); + void _post_hat(int p_device, DWORD p_dpad); void _drag_event(int p_x, int p_y, int idx); void _touch_event(bool p_pressed, int p_x, int p_y, int idx); @@ -187,7 +187,7 @@ class OS_Windows : public OS { void probe_joysticks(); void process_joysticks(); void process_key_events(); - String get_joystick_name( int id, JOYCAPS jcaps); + String get_joystick_name( int id, JOYCAPS jcaps, HKEY p_hkey); struct ProcessInfo {