diff options
390 files changed, 8618 insertions, 3905 deletions
diff --git a/AUTHORS.md b/AUTHORS.md index 0d6a1e6688..f58afc2b17 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -69,7 +69,6 @@ name is available. Dmitry Koteroff (Krakean) Dominik Jasiński (dreamsComeTrue) DualMatrix - Duroxxigar Ellen Poe (ellenhp) Emmanuel Barroga (codecustard) Emmanuel Leblond (touilleMan) @@ -110,6 +109,7 @@ name is available. Ilaria Cislaghi (QbieShay) Indah Sylvia (ISylvox) J08nY + Jake Young (Duroxxigar) Jakub Grzesik (kubecz3k) James Buck (jbuck3) Jean-Michel Bernard (jmb462) @@ -22,9 +22,7 @@ generous deed immortalized in the next stable release of Godot Engine. ## Silver sponsors - ABE ASIFA-Hollywood <https://www.asifa-hollywood.org> - jong ## Bronze sponsors diff --git a/core/core_constants.cpp b/core/core_constants.cpp index b2d5a8fdf1..c04d6ea56e 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -598,7 +598,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT_INTL); - BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NOEDITOR); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NO_EDITOR); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_NORMAL); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_EDITOR); diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 4607bd2f3f..87e65e592a 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -475,7 +475,7 @@ void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char * } // send_error will lock internally. - rd->script_debugger->send_error(p_func, p_file, p_line, p_err, p_descr, p_editor_notify, p_type, si); + rd->script_debugger->send_error(String::utf8(p_func), String::utf8(p_file), p_line, String::utf8(p_err), String::utf8(p_descr), p_editor_notify, p_type, si); } void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p_error) { diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt index f136d83496..0da8f8dfdb 100644 --- a/core/input/gamecontrollerdb.txt +++ b/core/input/gamecontrollerdb.txt @@ -1,11 +1,15 @@ -# Game Controller DB for SDL in 2.0.9 format +# Game Controller DB for SDL in 2.0.16 format # Source: https://github.com/gabomdq/SDL_GameControllerDB # Windows 03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows, -03000000c82d00002038000000000000,8bitdo,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000d0160000600a000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000040d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000050d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000060d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000070d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, 03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows, -03000000c82d000011ab000000000000,8BitDo F30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, @@ -14,12 +18,16 @@ 03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d0000e002000000000000,8BitDo N30,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b6,platform:Windows, 03000000c82d00000451000000000000,8BitDo N30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,start:b11,platform:Windows, 03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00002038000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00002867000000000000,8BitDo S30 Modkit,a:b0,b:b1,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, @@ -36,6 +44,7 @@ 03000000c82d00000351000000000000,8BitDo SN30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00000121000000000000,8BitDo SN30 Pro for Android,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, @@ -43,12 +52,19 @@ 03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, -03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, -030000008f0e00001200000000000000,Acme GA-02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, -03000000c01100000355000011010000,ACRUX USB GAME PAD,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,platform:Windows, -03000000fa190000f0ff000000000000,Acteck AGJ-3200,a:b2,b:b1,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:b3,y:b0,platform:Windows, +03000000d81d00000e00000000000000,AC02,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows, +030000008f0e00001200000000000000,Acme GA02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000c01100000355000000000000,Acrux,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,platform:Windows, +03000000fa190000f0ff000000000000,Acteck AGJ 3200,a:b2,b:b1,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:b3,y:b0,platform:Windows, +030000006d0400000bc2000000000000,Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows, +03000000d1180000402c000000000000,ADT1,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a5,x:b3,y:b4,platform:Windows, 030000006f0e00001413000000000000,Afterglow,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,platform:Windows, +030000006f0e00001301000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00003901000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001302000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ab1200000103000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001304000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000000f9000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000341a00003608000000000000,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,platform:Windows, 030000006f0e00000263000000000000,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,platform:Windows, 030000006f0e00001101000000000000,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,platform:Windows, @@ -56,68 +72,147 @@ 030000006f0e00001402000000000000,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,platform:Windows, 030000006f0e00001901000000000000,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,platform:Windows, 030000006f0e00001a01000000000000,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,platform:Windows, -03000000d62000001d57000000000000,Airflo 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,platform:Windows, +03000000120c00000288000000000000,Nyko Air Flo Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000d62000001d57000000000000,Nyko Airflo 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,platform:Windows, 03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, 03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows, +03000000830500000160000000000000,Arcade,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b4,platform:Windows, +03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, 03000000ef0500000300000000000000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, +03000000fd0500000230000000000000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, 03000000d6200000e557000000000000,Batarang,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,platform:Windows, +03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, 030000006f0e00003201000000000000,Battlefield 4 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,platform:Windows, +03000000ad1b000001f9000000000000,BB 070,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000d62000002a79000000000000,BDA PS4 Fightpad,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,platform:Windows, +030000000d0500000208000000000000,Belkin Nostromo N40,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, 03000000bc2000006012000000000000,Betop 2126F,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000bc2000000055000000000000,Betop BFM Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000bc2000006312000000000000,Betop Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows, -03000000bc2000006321000000000000,BETOP CONTROLLER,a:b2,b:b1,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:b3,y:b0,platform:Windows, +03000000bc2000006321000000000000,Betop Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000bc2000006412000000000000,Betop Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000c01100000555000000000000,Betop Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000c01100000655000000000000,Betop Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000790000000700000000000000,Betop Gamepad,a:b2,b:b1,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:a4,start:b9,x:b3,y:b0,platform:Windows, 03000000808300000300000000000000,Betop Gamepad,a:b2,b:b1,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:a4,start:b9,x:b3,y:b0,platform:Windows, +030000006f0e00006401000000000000,BF One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000300f00000202000000000000,Bigben,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a5,righty:a2,start:b7,x:b2,y:b3,platform:Windows, +030000006b1400000209000000000000,Bigben,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,platform:Windows, 030000006b1400000055000000000000,Bigben PS3 Controller,a:b0,b:b1,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:b2,y:b3,platform:Windows, 030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,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:b3,y:b2,platform:Windows, -03000000120c0000210e000000000000,Brook Mars,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,platform:Windows, +03000000380700008232000000000000,Brawlpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000210e000000000000,Brook Mars 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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000200e000000000000,Brook Mars PS4 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,platform:Windows, 0300000066f700000500000000000000,BrutalLegendTest,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:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, +03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, +030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000457500000401000000000000,Cobra,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:a5,start:b9,x:b0,y:b3,platform:Windows, -030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000a102000000000000,Controller (Xbox 360 Wireless Receiver for Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000ff02000000000000,Controller (Xbox One For Windows) - Wired,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000ea02000000000000,Controller (Xbox One For Windows) - Wireless,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000b0400003365000000000000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000a102000000000000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000ff02000000000000,Wired Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000ea02000000000000,Wireless Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000004c050000c505000000000000,CronusMax Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000d8140000cefa000000000000,Cthulhu,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:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000d814000007cd000000000000,Cthulhu,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:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700006352000000000000,Mad Catz CTRLR,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:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows, +030000003807000002cb000000000000,Cyborg,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000f806000000a3000000000000,DA Leader,a:b7,b:b6,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b8,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:b3,rightx:a2,righty:a3,start:b12,x:b4,y:b5,platform:Windows, +030000001a1c00000001000000000000,Datel,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,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:b2,y:b3,platform:Windows, 030000007d0400000840000000000000,Destroyer Tiltpad,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows, +03000000c0160000e105000000000000,Dual,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000007c1800000006000000000000,Dual Compat,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:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows, +030000004f04000012b3000000000000,Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, 03000000bd12000002e0000000000000,Dual USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows, +03000000ff1100003133000000000000,DualForce,a:b2,b:b3,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:a4,start:b9,x:b0,y:b1,platform:Windows, 030000008f0e00000910000000000000,DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows, -030000006f0e00003001000000000000,EA SPORTS 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,platform:Windows, +03000000317300000100000000000000,DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +030000006f0e00003001000000000000,EA Sports 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,platform:Windows, +03000000fc0400000250000000000000,Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +030000006e0500000a20000000000000,Elecom DUX60 MMO Gamepad,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows, 03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,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:b1,platform:Windows, 03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,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:b1,platform:Windows, +030000006e0500000520000000000000,Elecom P301U,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000320000000000000,Elecom U3613M (DInput),a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000e20000000000000,Elecom U3912T,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000f20000000000000,Elecom U4013S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500001320000000000000,Elecom U4113,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,platform:Windows, +030000006e0500001020000000000000,Elecom U4113S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000720000000000000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, 03000000120c0000f61c000000000000,Elite,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,platform:Windows, +03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows, +03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,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:b3,y:b2,platform:Windows, 03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000006f0e00008401000000000000,Faceoff Deluxe+ Audio Wired Controller for Nintendo Switch,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,platform:Windows, +03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000008000000210000000000000,8BitDo F30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001028000000000000,8BitDo F30 Arcade Joystick,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +030000003512000011ab000000000000,8BitDo F30 Arcade Joystick,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:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000790000003018000000000000,F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000242f00003900000000000000,F300 Elite,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006d0400001ec2000000000000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00008401000000000000,Faceoff Deluxe Audio Wired Controller for Nintendo Switch,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,platform:Windows, 030000006f0e00008001000000000000,Faceoff Wired Pro Controller for Nintendo Switch,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,platform:Windows, -03000000852100000201000000000000,FF-GP1,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,platform:Windows, +03000000021000000090000000000000,FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +0300000011040000c600000000000000,FC801,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +030000004f04000008d0000000000000,Ferrari 150,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000852100000201000000000000,FF GP1,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,platform:Windows, 030000000d0f00008500000000000000,Fighting Commander 2016 PS3,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,platform:Windows, 030000000d0f00008400000000000000,Fighting Commander 5,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:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, 030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700002847000000000000,FightPad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +03000000380700008031000000000000,FightStick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000380700008731000000000000,FightStick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700001847000000000000,FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +030000003807000038b7000000000000,FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, 78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows, +03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows, +03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows, +03000000b40400001024000000000000,Flydigi Apex,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000151900004000000000000000,Flydigi Vader 2,a:b11,b:b10,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,leftstick:b1,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b0,righttrigger:b4,rightx:a3,righty:a4,start:b2,x:b9,y:b8,platform:Windows, +03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows, +030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows, +03000000ac0500002d02000000000000,G2U,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000790000002201000000000000,Game Controller for PC,a:b2,b:b1,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:b3,y:b0,platform:Windows, 0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, +03000000430b00000500000000000000,GameCube,a:b0,b:b2,dpdown:b10,dpleft:b8,dpright:b9,dpup:b11,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a3,rightx:a5,righty:a2,start:b7,x:b1,y:b3,platform:Windows, +03000000341a000005f7000000000000,GameCube,a:b2,b:b3,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b1,y:b0,platform:Windows, +03000000790000004718000000000000,GameCube,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, 03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows, -03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,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,platform:Windows, +03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +030000008f0e00000d31000000000000,Gamepad 3 Turbo,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,platform:Windows, 03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 03000000ac0500003d03000000000000,GameSir,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000ac0500004d04000000000000,GameSir,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00001110000000000000,GameStick Bluetooth Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +0300000047530000616d000000000000,GameStop,a:b0,b:b1,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:b2,y:b3,platform:Windows, 03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,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:b2,y:b3,platform:Windows, 03000000c01100000140000000000000,GameStop PS4 Fun 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,platform:Windows, -030000009b2800003200000000000000,GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, -030000009b2800006000000000000000,GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, +03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows, +030000008f0e00001411000000000000,Gamo2 Divaller PS4 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,platform:Windows, +03000000120c0000a857000000000000,Gator Claw,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000c9110000f055000000000000,GC100XF,a:b0,b:b1,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:b2,y:b3,platform:Windows, 030000008305000009a0000000000000,Genius,a:b0,b:b1,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:b2,y:b3,platform:Windows, 030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,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:b2,y:b3,platform:Windows, 03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,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:b2,y:b3,platform:Windows, @@ -127,50 +222,96 @@ 03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000f0250000c383000000000000,Gioteck VX2 Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000f0250000c483000000000000,Gioteck VX2 Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows, +030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000007d0400000540000000000000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000007d0400000340000000000000,Gravis G44011 Xterminator,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a2,start:b9,x:b3,y:b4,platform:Windows, +030000008f0e00000610000000000000,GreenAsia,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a5,righty:a2,start:b11,x:b3,y:b0,platform:Windows, +03000000ac0500006b05000000000000,GT2a,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000341a00000302000000000000,Hama Scorpad,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,platform:Windows, +03000000fd0500003902000000000000,Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows, +03000000fd0500002a26000000000000,Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, +03000000fd0500002f26000000000000,Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows, 030000000d0f00004900000000000000,Hatsune Miku Sho 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,platform:Windows, -030000001008000001e1000000000000,Havit HV-G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows, -03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, -03000000632500002605000000000000,HJD-X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +030000001008000001e1000000000000,Havit HV G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows, +030000000d0f00000c00000000000000,HEXT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00000d00000000000000,Hori Fighting Stick EX2,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00003701000000000000,Hori Fighting Stick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Windows, +030000000d0f00002100000000000000,Hori Fighting Stick V3,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00001000000000000000,Hori Fighting Stick,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000f0d00000010000000000000,Hori Fighting Stick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000d81400000862000000000000,HitBox Edition Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +03000000632500002605000000000000,HJD X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +030000000d0f00000a00000000000000,Hori DOA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00008600000000000000,Hori Fighting Commander,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f0000ba00000000000000,Hori Fighting Commander,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005100000000000000,Hori Fighting Pad,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00003200000000000000,Hori Fighting Stick 3W,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000c000000000000000,Hori Fighting Stick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000a000000000000000,Hori Grip TAC4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b13,x:b0,y:b3,platform:Windows, +030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,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,platform:Windows, 030000000d0f00005400000000000000,Hori Pad 3,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,platform:Windows, 030000000d0f00000900000000000000,Hori Pad 3 Turbo,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,platform:Windows, 030000000d0f00004d00000000000000,Hori Pad A,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,platform:Windows, +030000000d0f00003801000000000000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Windows, 030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00001600000000007803,HORI Real Arcade Pro EX-SE (Xbox 360),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows, 030000000d0f00009c00000000000000,Hori TAC Pro,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,platform:Windows, +030000000d0f0000c900000000000000,Hori Taiko 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,platform:Windows, +030000000d0f00002301000000000000,Hori Wired PS4 Controller Light,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 030000000d0f0000c100000000000000,Horipad,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,platform:Windows, -030000000d0f00006e00000000000000,HORIPAD 4 (PS3),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,platform:Windows, -030000000d0f00006600000000000000,HORIPAD 4 (PS4),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,platform:Windows, +030000000d0f00006400000000000000,Horipad 3TP,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00001300000000000000,Horipad 3W,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006e00000000000000,Horipad 4 PS3,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,platform:Windows, +030000000d0f00006600000000000000,Horipad 4 PS4,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,platform:Windows, 030000000d0f00005500000000000000,Horipad 4 FPS,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,platform:Windows, -030000000d0f0000ee00000000000000,HORIPAD mini4,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:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, +030000000d0f00004200000000000000,Horipad A,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000005b1c00002400000000000000,Horipad Mini,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, +030000000d0f0000ee00000000000000,Horipad Mini 4,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000001f5000000000000,Horipad EXT2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00002600000000000000,Hori Real Arcade Pro 3P,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004b00000000000000,Hori Real Arcade Pro 3W,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00003d00000000000000,Hori Real Arcade Pro N3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b4,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b6,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000ae00000000000000,Hori Real Arcade Pro N4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f0000d800000000000000,Hori Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,platform:Windows, +030000000d0f0000aa00000000000000,Hori Real Arcade Pro S,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000af00000000000000,Hori Real Arcade Pro VHS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00001b00000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000002f5000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b07,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b08,righttrigger:b11,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Windows, +03000000250900000017000000000000,Joypad to USB Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, +030000000d0f00008c00000000000000,Hori Real Arcade Pro P4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00006f00000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows, 03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows, +030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows, +03000000696400006964000000000000,iDroidCon Bluetooth 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,platform:Windows, 03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -030000006f0e00002401000000000000,INJUSTICE FightStick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000ac0500002c02000000000000,IPEGA,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000491900000304000000000000,Ipega PG-9087 - Bluetooth Gamepad,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows, -030000006e0500000a20000000000000,JC-DUX60 ELECOM MMO Gamepad,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows, -030000006e0500000520000000000000,JC-P301U,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, -030000006e0500000320000000000000,JC-U3613M (DInput),a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, -030000006e0500000720000000000000,JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +030000006f0e00002401000000000000,Injustice FightStick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows, +03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000491900000204000000000000,Ipega PG9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000491900000304000000000000,Ipega PG9087 - Bluetooth Gamepad,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows, 030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows, -030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows, 030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, -030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, -03000000bd12000003c0000010010000,Joypad Alpha Shock,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,platform:Windows, -03000000bd12000003c0000000000000,JY-P70UR,a:b1,b:b0,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b4,x:b3,y:b2,platform:Windows, +03000000bd12000003c0000000000000,Joypad Alpha Shock,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,platform:Windows, +03000000ff1100004033000000000000,JPD FFB,a:b2,b:b1,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:a2,start:b15,x:b3,y:b0,platform:Windows, 03000000242f00002d00000000000000,JYS Wireless Adapter,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000242f00008a00000000000000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +03000000c4100000c082000000000000,KADE,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:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000828200000180000000000000,Keio,a:b4,b:b5,back:b8,leftshoulder:b2,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b1,platform:Windows, 03000000790000000200000000000000,King PS3 Controller,a:b2,b:b1,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:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000bd12000001e0000000000000,Leadership,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +030000008f0e00001300000000000000,Logic3,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000006f0e00000103000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00000104000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000006d040000d1ca000000000000,Logitech ChillStream,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,platform:Windows, 030000006d040000d2ca000000000000,Logitech Cordless Precision,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,platform:Windows, 030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows, @@ -178,21 +319,24 @@ 030000006d04000018c2000000000000,Logitech F510 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,platform:Windows, 030000006d04000019c2000000000000,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,platform:Windows, 030000006d0400001ac2000000000000,Logitech Precision Gamepad,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000009c2000000000000,Logitech WingMan,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, 030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows, -03000000380700006652000000000000,Mad Catz C.T.R.L.R,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),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,platform:Windows, -03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),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,platform:Windows, -03000000380700008433000000000000,Mad Catz FightStick TE S+ (PS3),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,platform:Windows, -03000000380700008483000000000000,Mad Catz FightStick TE S+ (PS4),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,platform:Windows, -03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700006252000000000000,Mad Catz Micro C.T.R.L.R,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000380700005645000000000000,Lynx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700006652000000000000,Mad Catz CTRLR,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000380700005032000000000000,Mad Catz FightPad Pro PS3,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,platform:Windows, +03000000380700005082000000000000,Mad Catz FightPad PRO PS4,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,platform:Windows, +03000000380700008433000000000000,Mad Catz FightStick TE S PS3,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,platform:Windows, +03000000380700008483000000000000,Mad Catz FightStick TE S PS4,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,platform:Windows, +03000000380700008134000000000000,Mad Catz FightStick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008184000000000000,Mad Catz FightStick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700006252000000000000,Mad Catz Micro CTRLR,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008532000000000000,Mad Catz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700003888000000000000,Mad Catz Arcade Fightstick TE S Plus PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700001888000000000000,Mad Catz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000380700008081000000000000,Mad Catz SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000002a0600001024000000000000,Matricom,a:b0,b:b1,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:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, 030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, 03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, @@ -205,36 +349,69 @@ 0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, 03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (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,platform:Windows, 03000000790000002418000000000000,Mega Drive,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows, +0300000079000000ae18000000000000,Mega Drive,a:b0,b:b1,back:b7,dpdown:b14,dpleft:b15,dpright:b13,dpup:b2,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000c0160000990a000000000000,Mega Drive,a:b0,b:b1,leftx:a0,lefty:a1,righttrigger:b2,start:b3,platform:Windows, +030000005e0400000300000000000000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +030000005e0400000700000000000000,Microsoft SideWinder,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +030000005e0400002700000000000000,Microsoft SideWinder,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,x:b2,y:b3,platform:Windows, +030000005e0400000e00000000000000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows, +03000000280d00000202000000000000,Miller Lite Cantroller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b5,x:b2,y:b3,platform:Windows, +030000005b1c00002500000000000000,Mini,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, +03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000ad1b00003ef0000000000000,MLG FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, 03000000380700006382000000000000,MLG GamePad 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,platform:Windows, -03000000c62400002a89000000000000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c62400002b89000000000000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c62400001a89000000000000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c62400001b89000000000000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000d6200000e589000000000000,Moga 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000d62000007162000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000d6200000ad0d000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c62400002a89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c62400002b89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c62400001a89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c62400001b89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000efbe0000edfe000000000000,Monect Virtual Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, 03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -030000006b140000010c000000000000,NACON GC-400ES,a:b0,b:b1,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:b2,y:b3,platform:Windows, -03000000921200004b46000000000000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows, -03000000790000004518000000000000,NEXILUX GAMECUBE Controller Adapter,platform:Windows,a:b1,b:b0,x:b2,y:b3,start:b9,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4, +03000000f70600000100000000000000,N64 Controller,a:b1,b:b2,back:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b0,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b8,x:b4,y:b5,platform:Windows, +030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,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:b2,y:b3,platform:Windows, +030000006b1400001106000000000000,Nacon Revolution 3 PS4 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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006b140000100d000000000000,Nacon Revolution Infinity PS4 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,platform:Windows, +030000006b140000080d000000000000,Nacon Revolution Unlimited Pro 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,platform:Windows, +03000000bd12000001c0000000000000,Nebular,a:b2,b:b1,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:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000eb0300000000000000000000,NeGcon USB Adapter,a:a2,b:b13,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,lefttrigger:a4,leftx:a1,righttrigger:b11,start:b3,x:a3,y:b12,platform:Windows, +0300000038070000efbe000000000000,NEO SE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +03000000571d00002100000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +03000000921200004b46000000000000,NES 2 port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows, +03000000790000004518000000000000,NEXILUX GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, 030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows, +03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows, 03000000152000000182000000000000,NGDS,a:b2,b:b1,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:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, -03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, 030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,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:b2,y:b3,platform:Windows, 030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows, +03000000d620000013a7000000000000,NSW wired 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,platform:Windows, 03000000550900001472000000000000,NVIDIA Controller v01.04,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows, -030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows, +03000000550900001072000000000000,NVIDIA Shield,a:b9,b:b8,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b3,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b2,righttrigger:a4,rightx:a2,righty:a5,start:b0,x:b7,y:b6,platform:Windows, +030000005509000000b4000000000000,NVIDIA Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000004b120000014d000000000000,Nyko Airflo,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows, 03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows, +030000000d0f00000401000000000000,Onyx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000008916000001fd000000000000,Onza CE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a3,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000d62000006d57000000000000,OPP 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,platform:Windows, 030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, 03000000362800000100000000000000,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,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows, 03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00008501000000000000,PDP Fightpad Pro,a:b2,b:b3,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:b1,y:b0,platform:Windows, 030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 030000004c050000da0c000000000000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000d9040000160f000000000000,Playstation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000d62000006dca000000000000,PowerA Pro Ex,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,platform:Windows, +030000006d04000084ca000000000000,Precision,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 03000000d62000009557000000000000,Pro Elite 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,platform:Windows, +03000000c62400001a53000000000000,Pro Ex Mini,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000d62000009f31000000000000,Pro Ex mini 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,platform:Windows, 03000000d6200000c757000000000000,Pro Ex mini 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,platform:Windows, +03000000120c0000110e000000000000,Pro5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, 03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, 03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, 03000000100800000100000000000000,PS1 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, @@ -244,122 +421,281 @@ 03000000666600006706000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows, 030000006b1400000303000000000000,PS2 Controller,a:b0,b:b1,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:b2,y:b3,platform:Windows, 030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000250900000088000000000000,PS2 Controllera:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900006888000000000000,PS2 Controllera:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b6,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,platform:Windows, +03000000430b00000300000000000000,EMS Production PS2 Adapter,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:b12,dpdown:b14,dpleft:b15,dpright:b13,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Windows, 03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,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,platform:Windows, 030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows, 03000000632500007505000000000000,PS3 Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000888800000803000000000000,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,platform:Windows, 030000008f0e00001431000000000000,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,platform:Windows, +03000000120a00000100000000000000,PS3 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +030000008f0e00000300000000000000,PS3 Controller,a:b2,b:b1,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:a5,start:b9,x:b3,y:b0,platform:Windows, +030000004f1f00000800000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000ba2200002010000000000000,PS3 Controller,a:b0,b:b1,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:a5,righty:a2,start:b9,x:b3,y:b2,platform:Windows, +03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000888800000804000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,leftshoulder:b10,leftstick:b1,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, +03000000120c00001307000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000250900000118000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900000218000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000120c0000f90e000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, 030000003807000056a8000000000000,PS3 RF pad,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,platform:Windows, -03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000100000008200000000000000,PS360 v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000004c050000a00b000000000000,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,platform:Windows, 030000004c050000c405000000000000,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,platform:Windows, 030000004c050000cc09000000000000,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,platform:Windows, +03000000120c00000807000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000160e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +030000001a1e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000f51c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000f10e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000130e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000150e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000f70e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000180e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000111e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000121e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000181e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000120c0000191e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, 030000004c050000e60c000000000000,PS5 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000ff000000cb01000000000000,PSP,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, -03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows, -03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, -03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, -03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows, -03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,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,platform:Windows, -03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,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,platform:Windows, +03000000830500005020000000000000,PSX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Windows, +03000000300f00000111000000000000,Qanba 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000300f00000211000000000000,Qanba 2P,a:b1,b:b0,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:b2,y:b3,platform:Windows, +03000000300f00000011000000000000,Qanba Arcade Stick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows, +03000000300f00001611000000000000,Qanba Arcade Stick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +03000000222c00000020000000000000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, +03000000341a00000104000000000000,Qanba Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows, +03000000300f00001211000000000000,Qanba Joystick,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:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000222c00000223000000000000,Qanba Obsidian Arcade Stick PS3,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,platform:Windows, +03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,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,platform:Windows, +030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows, +03000000086700006626000000000000,RadioShack,a:b2,b:b1,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:a5,start:b9,x:b3,y:b0,platform:Windows, +030000009b2800002300000000000000,Raphnet Technologies 3DO USB Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows, +030000009b2800006900000000000000,Raphnet Technologies 3DO USB Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows, +030000009b2800000800000000000000,Raphnet Technologies Dreamcast USB Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows, +030000009b2800003200000000000000,Raphnet Technologies GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, +030000009b2800006000000000000000,Raphnet Technologies GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, +030000009b2800001800000000000000,Raphnet Technologies Jaguar USB Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows, +030000009b2800000200000000000000,Raphnet Technologies NES USB Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows, +030000009b2800004300000000000000,Raphnet Technologies Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +030000009b2800000500000000000000,Raphnet Technologies Saturn Adapter 2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +030000009b2800000300000000000000,Raphnet Technologies SNES USB Adapter,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +030000009b2800005600000000000000,Raphnet Technologies SNES USB Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800005700000000000000,Raphnet Technologies SNES USB Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800001e00000000000000,Raphnet Technologies Vectrex USB Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows, +030000009b2800002b00000000000000,Raphnet Technologies Wii Classic USB Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800002c00000000000000,Raphnet Technologies Wii Classic USB Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, 03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000321500000204000000000000,Razer Panthera (PS3),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,platform:Windows, -03000000321500000104000000000000,Razer Panthera (PS4),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,platform:Windows, +03000000321500000204000000000000,Razer Panthera PS3,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,platform:Windows, +03000000321500000104000000000000,Razer Panthera PS4,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,platform:Windows, +03000000321500000010000000000000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, 03000000321500000507000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000321500000707000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000321500000710000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000321500000a10000000000000,Razer Raiju TE,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,platform:Windows, +03000000321500000410000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, 03000000321500000011000000000000,Razer Raion Fightpad for PS4,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,platform:Windows, 03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f00001100000000000000,REAL ARCADE PRO.3,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00006a00000000000000,Real Arcade Pro.4,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,platform:Windows, -030000000d0f00006b00000000000000,Real Arcade Pro.4,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,platform:Windows, -030000000d0f00008a00000000000000,Real Arcade Pro.4,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,platform:Windows, -030000000d0f00008b00000000000000,Real Arcade Pro.4,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,platform:Windows, -030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005b00000000000000,Real Arcade Pro.V4,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:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005c00000000000000,Real Arcade Pro.V4,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,platform:Windows, -03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000bd12000013d0000000000000,Retrolink USB SEGA Saturn Classic,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows, +030000000d0f00001100000000000000,Hori Real Arcade Pro 3,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006a00000000000000,Hori Real Arcade Pro 4,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,platform:Windows, +030000000d0f00006b00000000000000,Hori Real Arcade Pro 4,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,platform:Windows, +030000000d0f00008a00000000000000,Hori Real Arcade Pro 4,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,platform:Windows, +030000000d0f00008b00000000000000,Hori Real Arcade Pro 4,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,platform:Windows, +030000000d0f00007000000000000000,Hori Real Arcade Pro 4 VLX,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002200000000000000,Hori Real Arcade Pro V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005b00000000000000,Hori Real Arcade Pro V4,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005c00000000000000,Hori Real Arcade Pro V4,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,platform:Windows, +03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +03000000c82d00000290000000000000,Retrobit 64,a:b3,b:b9,back:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b0,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,start:b11,x:b4,y:b8,platform:Windows, +03000000c82d00003038000000000000,Retrobit 64,a:b3,b:b9,back:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b0,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,start:b11,x:b4,y:b8,platform:Windows, +03000000bd12000013d0000000000000,Retrolink USB Sega Saturn Classic,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows, +03000000bd12000015d0000000000000,Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, 0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, 0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +03000000830500000960000000000000,Revenger,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b5,platform:Windows, 030000006b140000010d000000000000,Revolution Pro 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,platform:Windows, -030000006b140000020d000000000000,Revolution Pro Controller 2(1/2),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,platform:Windows, +030000006b140000020d000000000000,Revolution Pro Controller 2,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,platform:Windows, 030000006b140000130d000000000000,Revolution Pro Controller 3,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,platform:Windows, +030000006f0e00004601000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001f01000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000006f0e00001e01000000000000,Rock Candy 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,platform:Windows, 030000006f0e00002801000000000000,Rock Candy 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,platform:Windows, 030000006f0e00002f01000000000000,Rock Candy 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,platform:Windows, -030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000c6240000fefa000000000000,Rock Candy Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Windows, +030000004f04000001d0000000000000,Rumble Force,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000009d0000000000000,Run N Drive,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,platform:Windows, +030000004f04000003d0000000000000,Run N Drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000a30600001af5000000000000,Saitek Cyborg,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,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:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, 03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows, 03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows, +03000000a30600000d5f000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows, +03000000a30600000dff000000000000,Saitek P2600,a:b1,b:b2,back:b9,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:a5,righty:a2,start:b8,x:b0,y:b3,platform:Windows, 03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000a306000018f5000000000000,Saitek P3200,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000a30600000901000000000000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b5,rightx:a3,righty:a2,x:b0,y:b1,platform:Windows, 03000000a30600000b04000000000000,Saitek P990,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:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,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:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows, +03000000a30600000b04000000000000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,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:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows, 03000000a30600002106000000000000,Saitek PS1000,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:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000a306000020f6000000000000,Saitek PS2700,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:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000300f00001101000000000000,Saitek Rumble Pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000e804000000a0000000000000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c01100000252000000000000,Sanwa Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000bd12000003c0000000000000,Sanwa JYP70UR,a:b1,b:b0,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b4,x:b3,y:b2,platform:Windows, +03000000c01100004350000000000000,Sanwa Micro Grip P3,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,x:b3,y:b2,platform:Windows, +03000000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows, +03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows, 03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, -0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, -030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, -03000000a30c00002500000000000000,Sega Genesis Mini 3B controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows, -03000000a30c00002400000000000000,Sega Mega Drive Mini 6B controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows, -03000000341a00000908000000000000,SL-6566,a:b0,b:b1,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:b2,y:b3,platform:Windows, -030000008f0e00000800000000000000,SpeedLink Strike FX,a:b2,b:b1,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:b3,y:b0,platform:Windows, +03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows, +03000000c01100000051000000000000,Satechi Bluetooth Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows, +0300000000050000289b000000000000,Sega Saturn Adapter 2,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000028b3000000000000,Score A,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:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows, +03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows, +03000000120c00001c1e000000000000,SnakeByte GamePad 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000571d00002000000000000000,SNES Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +0300000003040000c197000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows, +03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows, +03000000341a00000908000000000000,Speedlink 6566,a:b0,b:b1,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:b2,y:b3,platform:Windows, +030000008f0e00000800000000000000,Speedlink Strike FX,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000d11800000094000000000000,Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, +03000000de280000fc11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +03000000de280000ff11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, 03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, 03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows, -03000000790000001c18000000000000,STK-7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows, +03000000790000001c18000000000000,STK 7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000381000003014000000000000,Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000381000003114000000000000,Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700003847000000000000,Street Fighter Fighting Stick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows, +030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, 03000000d620000011a7000000000000,Switch,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,platform:Windows, -03000000457500002211000000000000,SZMY-POWER PC Gamepad,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,platform:Windows, -030000004f04000007d0000000000000,T Mini Wireless,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,platform:Windows, -030000004f0400000ab1000000000000,T.16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows, +030000000d0f0000f600000000000000,Switch Hori Pad,a:b0,b:b1,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:b2,y:b3,platform:Windows, +03000000457500002211000000000000,Szmy Power PC Gamepad,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,platform:Windows, +030000004f04000007d0000000000000,TMini Wireless,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,platform:Windows, +030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows, +030000000d0f00007b00000000000000,TAC GEAR,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:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000d814000001a0000000000000,TE Kitty,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,platform:Windows, 03000000fa1900000706000000000000,Team 5,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000790000002601000000000000,TGZ,a:b2,b:b1,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:a5,start:b9,x:b3,y:b0,platform:Windows, 030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, -030000004f04000023b3000000000000,Thrustmaster Dual Trigger 3-in-1,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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000023b3000000000000,Thrustmaster Dual Trigger 3 in 1,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:a5,start:b9,x:b0,y:b3,platform:Windows, 030000004f0400000ed0000000000000,ThrustMaster eSwap PRO 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,platform:Windows, 030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows, 030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, 03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, 03000000d62000006000000000000000,Tournament 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,platform:Windows, +03000000c01100000055000000000000,Tronsmart,a:b2,b:b1,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:b3,y:b0,platform:Windows, 030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Windows, 030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows, +03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows, 03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -030000006e0500001320000000000000,U4113,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,platform:Windows, 03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Windows, -03000000300f00000701000000000000,USB 4-Axis 12-Button Gamepad,a:b2,b:b1,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000341a00002308000000000000,USB gamepad,a:b0,b:b1,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:b2,y:b3,platform:Windows, -030000005509000000b4000000000000,USB gamepad,a:b10,b:b11,back:b5,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,guide:b14,leftshoulder:b8,leftstick:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b4,x:b12,y:b13,platform:Windows, -030000006b1400000203000000000000,USB gamepad,a:b0,b:b1,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:b2,y:b3,platform:Windows, -03000000790000000a00000000000000,USB gamepad,a:b2,b:b1,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:a4,start:b9,x:b3,y:b0,platform:Windows, -03000000f0250000c183000000000000,USB gamepad,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,platform:Windows, -03000000ff1100004133000000000000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,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:b3,y:b0,platform:Windows, +03000000242f00006e00000000000000,USB Game Controller,a:b1,b:b4,back:b10,leftshoulder:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b3,platform:Windows, +03000000b50700001503000000000000,USB Game Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000b404000081c6000000000000,USB Game Controller,a:b2,b:b1,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:a5,start:b9,x:b3,y:b0,platform:Windows, +03000000666600000188000000000000,USB Game Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000666600000288000000000000,USB Game Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000300f00000701000000000000,USB Game Controller,a:b2,b:b1,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000bd12000012d0000000000000,USB Game Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +030000000b0400003065000000000000,USB Game Controller,a:b2,b:b1,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:a5,start:b9,x:b3,y:b0,platform:Windows, +03000000341a00002308000000000000,USB Game Controller,a:b0,b:b1,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:b2,y:b3,platform:Windows, +030000006b1400000203000000000000,USB Game Controller,a:b0,b:b1,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:b2,y:b3,platform:Windows, +03000000790000000a00000000000000,USB Game Controller,a:b2,b:b1,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:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000f0250000c183000000000000,USB Game 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,platform:Windows, +03000000ff1100004133000000000000,USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000632500002305000000000000,USB Vibration Joystick,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000790000001a18000000000000,Venom,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,platform:Windows, 03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00000302000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00000702000000000000,Victrix Pro Fight Stick for PS4,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,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows, +03000000120c0000ab57000000000000,Warrior Joypad JS083,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +030000007e0500003003000000000000,WiiU Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +0300000032150000030a000000000000,Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +0300000032150000140a000000000000,Wolverine,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000016f0000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400009102000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b00008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c62400000053000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700002644000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a5,start:b8,x:b2,y:b3,platform:Windows, +03000000380700002045000000000000,Xbox 360 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:a5,start:b9,x:b0,y:b3,platform:Windows, +030000005e0400001907000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700001647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700002647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700003647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a7,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +030000003807000026b7000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c6240000fdfa000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000000fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000001fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000002e160000efbe000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows, 030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows, +030000005e0400000202000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000005e0400008502000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400008702000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000380700001645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000380700002645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700003645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000380700008645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000120c00001088000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2~,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5~,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000300f00008888000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:b13,dpleft:b10,dpright:b11,dpup:b12,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00006300000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e0000a802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e0000c802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,platform:Windows, +030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000fd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c62400003a54000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400000c0b000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000341a00000608000000000000,Xeox,a:b0,b:b1,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:b2,y:b3,platform:Windows, -03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,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:b2,y:b3,platform:Windows, -03000000ac0500005b05000000000000,Xiaoji Gamesir-G3w,a:b2,b:b1,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:b3,y:b0,platform:Windows, +03000000450c00002043000000000000,Xeox Gamepad SL6556BK,a:b0,b:b1,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:b2,y:b3,platform:Windows, +030000006f0e00000300000000000000,XGear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000ac0500005b05000000000000,Xiaoji Gamesir G3w,a:b2,b:b1,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:b3,y:b0,platform:Windows, 03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000790000004f18000000000000,ZD-T Android,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000120c0000101e000000000000,ZEROPLUS P4 Wired Gamepad,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,platform:Windows, +03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000120c0000101e000000000000,Zeroplus P4 Wired Gamepad,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,platform:Windows, +030000007e0500001720000000000000,Nintendo Switch SNES Controller,a:b0,b:b1,x:b2,y:b3,back:b8,start:b9,-leftx:h0.8,+leftx:h0.2,-lefty:h0.1,+lefty:h0.4,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,platform:Windows, # Mac OS X 030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,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:b3,y:b0,platform:Mac OS X, @@ -369,13 +705,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d000012ab000001000000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00002028000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, 030000003512000012ab000001000000,8BitDo NES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000190000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00001290000001000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00004028000000010000,8Bitdo SN30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,platform:Mac OS X, +03000000c82d00004028000000010000,8Bitdo SN30 GamePad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000260000001000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, @@ -385,42 +723,45 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000a00500003232000009010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X, +03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, 03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000ef0500000300000000020000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X, -03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X, -03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, 03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, 03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000d62000002a79000000010000,BDA PS4 Fightpad,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,platform:Mac OS X, -03000000120c0000200e000000010000,Brook Mars,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,platform:Mac OS X, -03000000120c0000210e000000010000,Brook Mars,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,platform:Mac OS X, +03000000120c0000200e000000010000,Brook Mars 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,platform:Mac OS X, +03000000120c0000210e000000010000,Brook Mars 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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000008305000031b0000000000000,Cideko AK08b,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,platform:Mac OS X, 03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X, 03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,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:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008400000000010000,Fighting Commander,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,platform:Mac OS X, +030000000d0f00008500000000010000,Fighting Commander,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,platform:Mac OS X, +03000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle3:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Mac OS X, 03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X, -03000000ad1b000001f9000000000000,Gamestop BB-070 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,platform:Mac OS X, +03000000ad1b000001f9000000000000,Gamestop BB070 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,platform:Mac OS X, 0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,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:b2,y:b3,platform:Mac OS X, 03000000c01100000140000000010000,GameStop PS4 Fun 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,platform:Mac OS X, 030000006f0e00000102000000000000,GameStop Xbox 360 Wired 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,platform:Mac OS X, 030000007d0400000540000001010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000280400000140000000020000,Gravis Gamepad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000008f0e00000300000007010000,GreenAsia Inc. USB Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X, +030000008f0e00000300000007010000,GreenAsia USB Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X, 030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,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,platform:Mac OS X, -030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,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,platform:Mac OS X, -030000000d0f00004d00000000000000,HORI Gem Pad 3,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,platform:Mac OS X, +030000000d0f00005f00000000010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,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,platform:Mac OS X, +030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,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,platform:Mac OS X, +030000000d0f00004d00000000000000,Hori Gem Pad 3,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,platform:Mac OS X, 030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00006e00000000010000,HORIPAD 4 (PS3),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,platform:Mac OS X, -030000000d0f00006600000000010000,HORIPAD 4 (PS4),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,platform:Mac OS X, -030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,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:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f0000ee00000000010000,HORIPAD mini4,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:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006e00000000010000,Horipad 4 PS3,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,platform:Mac OS X, +030000000d0f00006600000000010000,Horipad 4 PS4,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,platform:Mac OS X, +030000000d0f00006600000000000000,Horipad FPS Plus 4,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:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f0000ee00000000010000,Horipad Mini 4,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:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X, -03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, -03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, +03000000830500006020000000000000,iBuffalo Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, 030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X, 030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000242f00002d00000007010000,JYS Wireless Adapter,a:b2,b:b1,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:b3,y:b0,platform:Mac OS X, @@ -429,7 +770,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006d04000016c2000014040000,Logitech Dual Action,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,platform:Mac OS X, 030000006d04000016c2000000000000,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,platform:Mac OS X, 030000006d04000018c2000000000000,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,platform:Mac OS X, -030000006d04000019c2000005030000,Logitech F710,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,platform:Mac OS X, +030000006d04000019c2000005030000,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,platform:Mac OS X, 030000006d0400001fc2000000000000,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,platform:Mac OS X, 030000006d04000018c2000000010000,Logitech RumblePad 2 USB,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,platform:Mac OS X, 030000006d04000019c2000000000000,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,platform:Mac OS X, @@ -437,7 +778,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),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,platform:Mac OS X, 03000000380700008433000000010000,Mad Catz FightStick TE S+ (PS3),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,platform:Mac OS X, 03000000380700008483000000010000,Mad Catz FightStick TE S+ (PS4),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,platform:Mac OS X, -03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X, +03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,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:b3,y:b0,platform:Mac OS X, 03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X, 0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,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:b3,y:b0,platform:Mac OS X, @@ -445,21 +786,21 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, 03000000790000000018000000010000,Mayflash Wii U Pro Controller Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, 03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, -03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000005e0400002700000001010000,Microsoft SideWinder Plug & Play Game Pad,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,leftx:a0,lefty:a1,righttrigger:b5,x:b2,y:b3,platform:Mac OS X, +03000000d8140000cecf000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000005e0400002700000001010000,Microsoft SideWinder Game Pad,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,leftx:a0,lefty:a1,righttrigger:b5,x:b2,y:b3,platform:Mac OS X, 03000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, -03000000c62400002a89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c62400002b89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c62400002b89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000632500007505000000020000,NEOGEO mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X, 030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000d620000011a7000000020000,Nintendo Switch Core (Plus) Wired 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,platform:Mac OS X, +03000000d620000011a7000000020000,Nintendo Switch Core Plus Wired 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,platform:Mac OS X, 03000000d620000011a7000010050000,Nintendo Switch PowerA Wired 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,platform:Mac OS X, 030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,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:b2,y:b3,platform:Mac OS X, 030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,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:b2,y:b3,platform:Mac OS X, 03000000550900001472000025050000,NVIDIA Controller v01.04,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X, 030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, +030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, 030000004c050000da0c000000010000,Playstation Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 030000004c0500003713000000010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000d62000006dca000000010000,PowerA Pro Ex,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,platform:Mac OS X, @@ -472,15 +813,17 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000004c050000cc09000000010000,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,platform:Mac OS X, 050000004c050000e60c000000010000,PS5 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000008916000000fd000000000000,Razer Onza TE,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,platform:Mac OS X, -03000000321500000204000000010000,Razer Panthera (PS3),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,platform:Mac OS X, -03000000321500000104000000010000,Razer Panthera (PS4),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,platform:Mac OS X, -03000000321500000010000000010000,Razer RAIJU,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,platform:Mac OS X, +03000000321500000204000000010000,Razer Panthera PS3,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,platform:Mac OS X, +03000000321500000104000000010000,Razer Panthera PS4,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,platform:Mac OS X, +03000000321500000010000000010000,Razer Raiju,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,platform:Mac OS X, 03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000321500000011000000010000,Razer Raion Fightpad for PS4,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,platform:Mac OS X, 03000000321500000009000000020000,Razer Serval,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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 030000003215000000090000163a0000,Razer Serval,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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 0300000032150000030a000000000000,Razer Wildcat,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,platform:Mac OS X, -03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X, +03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 030000006b140000010d000000010000,Revolution Pro 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,platform:Mac OS X, 030000006b140000130d000000010000,Revolution Pro Controller 3,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,platform:Mac OS X, @@ -498,10 +841,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, 03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, 03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, +05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, +05000000556e6b6e6f776e2048494400,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, 050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, 03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, 03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, -03000000457500002211000000010000,SZMY-POWER PC Gamepad,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,platform:Mac OS X, +03000000457500002211000000010000,SZMY Power PC Gamepad,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,platform:Mac OS X, 030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X, 030000004f0400000ed0000000020000,ThrustMaster eSwap PRO 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,platform:Mac OS X, 030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X, @@ -513,7 +858,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000791d00000103000009010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, 050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, 050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, -030000005e0400008e02000000000000,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,platform:Mac OS X, +030000005e0400008e02000000000000,Xbox 360 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,platform:Mac OS X, 030000006f0e00000104000000000000,Xbox 360 Wired 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,platform:Mac OS X, 03000000c6240000045d000000000000,Xbox 360 Wired 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,platform:Mac OS X, 030000005e0400000a0b000000000000,Xbox Adaptive 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,platform:Mac OS X, @@ -524,28 +869,33 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000e302000000000000,Xbox One Wired 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,platform:Mac OS X, 030000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000200b000011050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, 030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, 030000005e040000ea02000000000000,Xbox Wireless 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,platform:Mac OS X, 030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,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,platform:Mac OS X, -03000000120c0000101e000000010000,ZEROPLUS P4 Wired Gamepad,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,platform:Mac OS X, +03000000120c0000100e000000010000,Zeroplus P4 Gamepad,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,platform:Mac OS X, +03000000120c0000101e000000010000,Zeroplus P4 Wired Gamepad,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,platform:Mac OS X, # Linux +03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00001038000000010000,8Bitdo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux, 03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, 05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, 03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000190000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00000061000000010000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +030000003512000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, 030000003512000012ab000010010000,8Bitdo SFC30 GamePad,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux, 05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, @@ -566,12 +916,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000005e040000e002000030110000,8BitDo Zero 2 (XInput),a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, 05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, 05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, -03000000c01100000355000011010000,ACRUX USB GAME PAD,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,platform:Linux, +03000000c01100000355000011010000,Acrux Gamepad,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,platform:Linux, 030000006f0e00001302000000010000,Afterglow,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,platform:Linux, 030000006f0e00003901000020060000,Afterglow Controller for Xbox One,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,platform:Linux, 030000006f0e00003901000000430000,Afterglow Prismatic 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,platform:Linux, 030000006f0e00003901000013020000,Afterglow Prismatic Wired Controller 048-007-NA,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,platform:Linux, -03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000100000008200000011010000,Akishop Customs PS360 v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 030000007c1800000006000010010000,Alienware Dual Compatible Game Pad,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:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux, 05000000491900000204000021000000,Amazon Fire Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux, @@ -579,80 +929,86 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, -05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, -05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, +05000000050b00000045000031000000,Asus Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, +05000000050b00000045000040000000,Asus Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, 03000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux, 05000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux, -03000000503200000210000000000000,Atari Game 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:b3,y:b2,platform:Linux, +03000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux, 05000000503200000210000000000000,Atari Game 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:b3,y:b2,platform:Linux, 03000000120c00000500000010010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, 03000000ef0500000300000000010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, -03000000c62400001b89000011010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c62400001b89000011010000,BDA MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000d62000002a79000011010000,BDA PS4 Fightpad,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,platform:Linux, -03000000c21100000791000011010000,Be1 GC101 Controller 1.03 mode,a:b2,b:b1,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:b3,y:b0,platform:Linux, -03000000c31100000791000011010000,Be1 GC101 GAMEPAD 1.03 mode,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000005e0400008e02000003030000,Be1 GC101 Xbox 360 Controller mode,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,platform:Linux, -03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux, -03000000120c0000200e000011010000,Brook Mars,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,platform:Linux, -03000000120c0000210e000011010000,Brook Mars,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,platform:Linux, +03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,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:b3,y:b0,platform:Linux, +03000000c31100000791000011010000,Be1 GC101 GAMEPAD 1.03,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005e0400008e02000003030000,Be1 GC101 Xbox 360,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,platform:Linux, +05000000bc2000000055000001000000,BETOP AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000006b1400000209000011010000,Bigben,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,platform:Linux, +03000000666600006706000000010000,Boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux, +03000000120c0000200e000011010000,Brook Mars 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,platform:Linux, +03000000120c0000210e000011010000,Brook Mars 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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000120c0000f70e000011010000,Brook Universal Fighting Board,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -03000000ffff0000ffff000000010000,Chinese-made Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, 03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,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:b3,y:b0,platform:Linux, 030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux, 03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux, -03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,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:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, -03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, -03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,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:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, +03000000a306000022f6000011010000,Cyborg V3 Rumble Pad,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:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, 030000004f04000004b3000010010000,Dual Power 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, 030000006f0e00003001000001010000,EA Sports 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,platform:Linux, -03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, +03000000c11100000191000011010000,EasySMX,a:b2,b:b1,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:b3,y:b0,platform:Linux, +030000006e0500000320000010010000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, +03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000341a000005f7000010010000,HuiJia GameCube Controller Adpater,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, 03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000ac0500002d0200001b010000,Gamesir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,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:b2,y:b3,platform:Linux, 030000006f0e00000104000000010000,Gamestop Logic3 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,platform:Linux, -030000008f0e00000800000010010000,Gasia Co. Ltd PS(R) Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux, -030000006f0e00001304000000010000,Generic X-Box pad,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,platform:Linux, +030000008f0e00000800000010010000,Gasia PlayStation Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux, +030000006f0e00001304000000010000,Xbox 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,platform:Linux, 03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,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:b2,y:b3,platform:Linux, -03000000f0250000c183000010010000,Goodbetterbest Ltd USB 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,platform:Linux, +03000000f0250000c183000010010000,Goodbetterbest 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,platform:Linux, 0300000079000000d418000000010000,GPD Win 2 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,platform:Linux, 030000007d0400000540000000010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux, -030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000280400000140000000010000,Gravis GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000008f0e00000610000000010000,GreenAsia Electronics Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux, +030000008f0e00001200000010010000,GreenAsia USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,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,platform:Linux, 03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,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:b3,y:b0,platform:Linux, 06000000adde0000efbe000002010000,Hidromancer Game 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,platform:Linux, -03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, -03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,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:b2,y:b3,platform:Linux, -03000000632500002605000010010000,HJD-X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, -030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f0000c100000011010000,HORI CO. LTD. HORIPAD S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,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,platform:Linux, -030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,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,platform:Linux, -030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,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,platform:Linux, -030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00008500000010010000,HORI Fighting Commander,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,platform:Linux, +03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, +03000000c9110000f055000011010000,HJC Game Gamepqd,a:b0,b:b1,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:b2,y:b3,platform:Linux, +03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux, +03000000632500002605000010010000,HJDX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000000d0f00000d00000000010000,Hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, +030000000d0f00001000000011010000,Hori Fighting Stick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f0000c100000011010000,Horipad S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,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,platform:Linux, +030000000d0f00006a00000011010000,Hori Real Arcade Pro 4,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,platform:Linux, +030000000d0f00006b00000011010000,Hori Real Arcade Pro 4,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,platform:Linux, +030000000d0f00002200000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00008500000010010000,Hori Fighting Commander,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,platform:Linux, 030000000d0f00008600000002010000,Hori Fighting Commander,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -030000000d0f00005f00000011010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00005e00000011010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00005001000009040000,Hori Fighting Commander OCTA,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,platform:Linux, 03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,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,platform:Linux, +030000000d0f00003801000011010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Linux, 030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f0000aa00000011010000,HORI Real Arcade Pro,a:b2,b:b1,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:b3,y:b0,platform:Linux, -030000000d0f0000d800000072056800,HORI Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Linux, -030000000d0f00001600000000010000,Hori Real Arcade Pro.EX-SE (Xbox 360),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, -030000000d0f00006e00000011010000,HORIPAD 4 (PS3),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,platform:Linux, -030000000d0f00006600000011010000,HORIPAD 4 (PS4),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,platform:Linux, -030000000d0f0000ee00000011010000,HORIPAD mini4,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:a5,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00006700000001010000,HORIPAD ONE,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,platform:Linux, +030000000d0f0000aa00000011010000,Hori Real Arcade Pro,a:b2,b:b1,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:b3,y:b0,platform:Linux, +030000000d0f0000d800000072056800,Hori Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Linux, +030000000d0f00001600000000010000,Hori Real Arcade Pro EXSE,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, +030000000d0f00006e00000011010000,Horipad 4 PS3,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,platform:Linux, +030000000d0f00006600000011010000,Horipad 4 PS4,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,platform:Linux, +030000000d0f0000ee00000011010000,Horipad Mini 4,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:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006700000001010000,Horipad One,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,platform:Linux, 030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux, 03000000242e00008816000001010000,Hyperkin X91,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,platform:Linux, -03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, -050000006964726f69643a636f6e0000,idroid:con,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,platform:Linux, -03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, -03000000d80400008200000003000000,IMS PCU#0 Gamepad Interface,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux, -03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux, -0500000049190000020400001b010000,Ipega PG-9069 - Bluetooth Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000632500007505000011010000,Ipega PG-9099 - Bluetooth Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux, -030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, +050000006964726f69643a636f6e0000,idroidcon 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,platform:Linux, +03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000d80400008200000003000000,IMS PCU0 Gamepad,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux, +03000000fd0500000030000000010000,InterAct GoPad I73000,a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux, +0500000049190000020400001b010000,Ipega PG 9069 Bluetooth Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000632500007505000011010000,Ipega PG 9099 Bluetooth Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux, 03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, 03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil Pad,a:b2,b:b1,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, @@ -664,7 +1020,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000242f00002d00000011010000,JYS Wireless Adapter,a:b2,b:b1,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:b3,y:b0,platform:Linux, 03000000242f00008a00000011010000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux, 030000006f0e00000103000000020000,Logic3 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,platform:Linux, -030000006d040000d1ca000000000000,Logitech ChillStream,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,platform:Linux, +030000006d040000d1ca000000000000,Logitech Chillstream,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,platform:Linux, 030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,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,platform:Linux, 030000006d04000016c2000010010000,Logitech Dual Action,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,platform:Linux, 030000006d04000016c2000011010000,Logitech Dual Action,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,platform:Linux, @@ -673,24 +1029,25 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 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,platform:Linux, 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,platform:Linux, 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,platform:Linux, -030000006d0400000ac2000010010000,Logitech Inc. WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux, +030000006d0400000ac2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux, 030000006d04000018c2000010010000,Logitech RumblePad 2,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,platform:Linux, 030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux, -050000004d4f435554452d3035305800,M54-PC,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000380700006652000025010000,Mad Catz C.T.R.L.R ,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,platform:Linux, -03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),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,platform:Linux, -03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),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,platform:Linux, +050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,x:b2,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux +050000004d4f435554452d3035305800,Mocute 054X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000380700006652000025010000,Mad Catz CTRLR,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,platform:Linux, +03000000380700005032000011010000,Mad Catz FightPad PRO PS3,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,platform:Linux, +03000000380700005082000011010000,Mad Catz FightPad PRO PS4,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,platform:Linux, 03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, -03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000380700008433000011010000,Mad Catz FightStick TE S+ (PS3),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,platform:Linux, -03000000380700008483000011010000,Mad Catz FightStick TE S+ (PS4),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,platform:Linux, +03000000380700008034000011010000,Mad Catz fightstick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008084000011010000,Mad Catz fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008433000011010000,Mad Catz FightStick TE S PS3,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,platform:Linux, +03000000380700008483000011010000,Mad Catz FightStick TE S PS4,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,platform:Linux, 03000000380700001647000010040000,Mad Catz Wired Xbox 360 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,platform:Linux, -03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 03000000ad1b000016f0000090040000,Mad Catz Xbox 360 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,platform:Linux, 03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000242f0000f700000001010000,Magic-S Pro,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,platform:Linux, +03000000242f0000f700000001010000,Mayflash Magic S Pro,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,platform:Linux, 03000000120c00000500000000010000,Manta Dualshock 2,a:b0,b:b1,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:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 03000000790000004318000010010000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, @@ -700,29 +1057,31 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 0300000025090000e803000001010000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, 03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, -030000005e0400008e02000004010000,Microsoft X-Box 360 pad,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,platform:Linux, -030000005e0400008e02000062230000,Microsoft X-Box 360 pad,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,platform:Linux, -050000005e040000050b000003090000,Microsoft X-Box One Elite 2 pad,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000005e040000e302000003020000,Microsoft X-Box One Elite pad,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,platform:Linux, -030000005e040000d102000001010000,Microsoft X-Box One pad,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,platform:Linux, -030000005e040000dd02000003020000,Microsoft X-Box One pad (Firmware 2015),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,platform:Linux, -030000005e040000d102000003020000,Microsoft X-Box One pad v2,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,platform:Linux, -030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, -030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, -030000005e040000000b000008040000,Microsoft Xbox One Elite 2 pad - Wired,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,platform:Linux, -030000005e040000ea02000008040000,Microsoft Xbox One S pad - Wired,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,platform:Linux, -03000000c62400001a53000000010000,Mini PE,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,platform:Linux, +030000005e0400000700000000010000,Microsoft SideWinder Game Pad USB,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux, +030000005e0400008e02000004010000,Microsoft Xbox 360 pad,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,platform:Linux, +030000005e0400008e02000062230000,Microsoft Xbox 360 pad,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,platform:Linux, +050000005e040000050b000003090000,Microsoft Xbox One Elite 2 pad,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005e040000e302000003020000,Microsoft Xbox One Elite pad,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,platform:Linux, +030000005e040000d102000001010000,Microsoft Xbox One pad,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,platform:Linux, +030000005e040000dd02000003020000,Microsoft Xbox One pad 2015,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,platform:Linux, +030000005e040000d102000003020000,Microsoft Xbox One pad v2,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,platform:Linux, +030000005e0400008502000000010000,Microsoft Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +030000005e0400008902000021010000,Microsoft Xbox pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +030000005e040000000b000008040000,Microsoft Xbox One Elite 2 pad,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,platform:Linux, +030000005e040000ea02000008040000,Microsoft Xbox One S pad,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,platform:Linux, +03000000c62400001a53000000010000,PowerA Mini Pro Ex,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,platform:Linux, 03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, 05000000d6200000e589000001000000,Moga 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, 05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, 05000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, -03000000c62400002b89000011010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000c62400002a89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000c62400001a89000000010000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000250900006688000000010000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, -030000006b140000010c000010010000,NACON GC-400ES,a:b0,b:b1,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:b2,y:b3,platform:Linux, +03000000c62400002b89000011010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000c62400001a89000000010000,MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,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:b2,y:b3,platform:Linux, 030000000d0f00000900000010010000,Natec Genesis P44,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,platform:Linux, -03000000790000004518000010010000,NEXILUX GAMECUBE Controller Adapter,a:b1,b:b0,x:b2,y:b3,start:b9,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,platform:Linux, +030000004f1f00000800000011010000,Neogeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000790000004518000010010000,Nexilux GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux, 060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, 060000007e0500000820000000000000,Nintendo Combined Joy-Cons (joycond),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, @@ -741,36 +1100,42 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux, 05000000550900001472000001000000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux, 03000000451300000830000010010000,NYKO CORE,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:a5,start:b9,x:b0,y:b3,platform:Linux, -19000000010000000100000001010000,odroidgo2_joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux, -19000000010000000200000011000000,odroidgo2_joypad_v11,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux, -030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +19000000010000000100000001010000,odroidgo2 joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux, +19000000010000000200000011000000,odroidgo2 joypad v11,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux, +030000005e0400000202000000010000,Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, 03000000c0160000dc27000001010000,OnyxSoft Dual JoyDivision,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:Linux, 05000000362800000100000002010000,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,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, 05000000362800000100000003010000,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,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, 03000000830500005020000010010000,Padix Co. Ltd. Rockfire PSX/USB Bridge,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Linux, 03000000790000001c18000011010000,PC Game Controller,a:b2,b:b1,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:b3,y:b0,platform:Linux, 03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,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:b3,y:b0,platform:Linux, -030000006f0e0000b802000001010000,PDP AFTERGLOW Wired Xbox One 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,platform:Linux, -030000006f0e0000b802000013020000,PDP AFTERGLOW Wired Xbox One 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,platform:Linux, +030000006f0e0000b802000001010000,PDP Afterglow Wired Xbox One 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,platform:Linux, +030000006f0e0000b802000013020000,PDP Afterglow Wired Xbox One 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,platform:Linux, 030000006f0e00006401000001010000,PDP Battlefield One,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,platform:Linux, -030000006f0e00008001000011010000,PDP CO. LTD. Faceoff Wired Pro Controller for Nintendo Switch,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,platform:Linux, +030000006f0e00008001000011010000,PDP Faceoff Wired Pro Controller for Nintendo Switch,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,platform:Linux, 030000006f0e00003101000000010000,PDP EA Sports 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,platform:Linux, 030000006f0e0000c802000012010000,PDP Kingdom Hearts 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,platform:Linux, 030000006f0e00008701000011010000,PDP Rock Candy Wired Controller for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000c6240000fefa000000010000,Rock Candy Xbox 360 Controller, a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, 030000006f0e00000901000011010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e0000a802000023020000,PDP Wired Controller for Xbox One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 030000006f0e00008501000011010000,PDP Wired Fight Pad Pro for Nintendo Switch,a:b2,b:b1,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:b3,y:b0,platform:Linux, -0500000049190000030400001b010000,PG-9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000491900000204000000000000,PG-9118,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +0500000049190000030400001b010000,Ipega PG9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000491900000204000000000000,Ipega PG9118,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000004c050000da0c000011010000,Playstation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000d9040000160f000000010000,Playstation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, 03000000c62400000053000000010000,PowerA,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,platform:Linux, 03000000c62400003a54000001010000,PowerA 1428124-01,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,platform:Linux, 03000000d62000006dca000011010000,PowerA Pro Ex,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,platform:Linux, 03000000d62000000228000001010000,PowerA Wired Controller for Xbox One,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,platform:Linux, -03000000c62400001a58000001010000,PowerA Xbox One Cabled,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,platform:Linux, +03000000d62000000220000001010000,PowerA Wired Controller for Xbox One and Xbox Series S and X,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, +03000000c62400001a58000001010000,PowerA Xbox One,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,platform:Linux, 03000000c62400001a54000001010000,PowerA Xbox One Mini Wired 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,platform:Linux, +03000000d620000013a7000011010000,Nintendo Switch PowerA Wired Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux, 030000006d040000d2ca000011010000,Precision 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,platform:Linux, +03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,b:b1,a:b0,x:b3,y:b2,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:b6,righttrigger:b7,platform:Linux, +03000000430b00000300000000010000,EMS Production PS2 Adapter,b:b1,a:b2,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux, 03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000341a00003608000011010000,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,platform:Linux, 030000004c0500006802000010010000,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,platform:Linux, @@ -802,18 +1167,20 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000004c050000e60c000011010000,PS5 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 050000004c050000e60c000000010000,PS5 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 03000000ff000000cb01000010010000,PSP,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, -03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux, +03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux, 030000009b2800004200000001010000,Raphnet Technologies Dual NES to USB v2.0,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux, 030000009b2800003200000001010000,Raphnet Technologies GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, 030000009b2800006000000001010000,Raphnet Technologies GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, 030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, 030000008916000001fd000024010000,Razer Onza Classic Edition,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,platform:Linux, 030000008916000000fd000024010000,Razer Onza Tournament Edition,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,platform:Linux, -03000000321500000204000011010000,Razer Panthera (PS3),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,platform:Linux, -03000000321500000104000011010000,Razer Panthera (PS4),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,platform:Linux, +03000000321500000204000011010000,Razer Panthera PS3,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,platform:Linux, +03000000321500000104000011010000,Razer Panthera PS4,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,platform:Linux, 03000000321500000810000011010000,Razer Panthera Evo Arcade Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,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,platform:Linux, -03000000321500000010000011010000,Razer RAIJU,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,platform:Linux, +03000000321500000010000011010000,Razer Rainu,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,platform:Linux, 03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000321500000a10000001000000,Razer Raiju Tournament Edition,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000710000000010000,Razer Raiju Tournament Edition Wired,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 03000000321500000011000011010000,Razer Raion Fightpad for PS4,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,platform:Linux, 030000008916000000fe000024010000,Razer Sabertooth,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,platform:Linux, 03000000c6240000045d000024010000,Razer Sabertooth,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,platform:Linux, @@ -821,7 +1188,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000321500000009000011010000,Razer Serval,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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, 050000003215000000090000163a0000,Razer Serval,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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, 0300000032150000030a000001010000,Razer Wildcat,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,platform:Linux, -03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux, 0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux, 0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, 030000006b140000010d000011010000,Revolution Pro 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,platform:Linux, @@ -837,20 +1204,22 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, 03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, 03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,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:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux, -03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000a306000018f5000010010000,Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, 03000000a306000020f6000011010000,Saitek PS2700 Rumble Pad,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:a4,start:b9,x:b0,y:b3,platform:Linux, 03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux, -03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,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:b3,y:b0,platform:Linux, -03000000632500007505000010010000,SHANWAN PS3/PC Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux, -03000000bc2000000055000010010000,ShanWan PS3/PC Wired GamePad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000005f140000c501000010010000,SHANWAN Trust Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux, +03000000a30c00002500000011010000,Sega Genesis Mini 3B controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux, +030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000f025000021c1000010010000,Shanwan Gioteck PS3 Wired Controller,a:b2,b:b1,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:b3,y:b0,platform:Linux, +03000000632500007505000010010000,Shanwan PS3 PC Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux, +03000000bc2000000055000010010000,Shanwan PS3 PC Wired GamePad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005f140000c501000010010000,Shanwan Trust Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux, 03000000632500002305000010010000,ShanWan USB Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux, -03000000341a00000908000010010000,SL-6566,a:b0,b:b1,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:b2,y:b3,platform:Linux, +03000000341a00000908000010010000,SL6566,a:b0,b:b1,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:b2,y:b3,platform:Linux, 030000004c050000e60c000011810000,Sony DualSense,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -050000004c050000e60c000000810000,Sony DualSense ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000e60c000000810000,Sony DualSense,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, -030000005e0400008e02000073050000,Speedlink TORID Wireless 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,platform:Linux, -030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,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,platform:Linux, +030000005e0400008e02000073050000,Speedlink Torid Wireless 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,platform:Linux, +030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog Gamepad pad,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,platform:Linux, 03000000d11800000094000011010000,Stadia 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, 03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, 03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, @@ -870,13 +1239,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000003b07000004a1000000010000,Suncom SFX Plus for USB,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux, 03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, 0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, -03000000457500002211000010010000,SZMY-POWER CO. LTD. GAMEPAD,a:b2,b:b1,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:b3,y:b0,platform:Linux, -030000008f0e00000d31000010010000,SZMY-POWER CO. LTD. GAMEPAD 3 TURBO,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,platform:Linux, -030000008f0e00001431000010010000,SZMY-POWER CO. LTD. PS3 gamepad,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,platform:Linux, +03000000457500002211000010010000,SZMY Power Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux, +030000008f0e00000d31000010010000,SZMY Power 3 Turbo,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,platform:Linux, +030000008f0e00001431000010010000,SZMY Power PS3 gamepad,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,platform:Linux, 030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, 030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, -030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,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:a5,start:b9,x:b0,y:b3,platform:Linux, -030000004f0400000ed0000011010000,ThrustMaster eSwap PRO 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,platform:Linux, +030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3 in 1,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:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004f0400000ed0000011010000,Thrustmaster eSwap PRO 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,platform:Linux, 03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux, 030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux, 030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux, @@ -887,49 +1256,62 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000004f04000007d0000000010000,Thrustmaster T Mini Wireless,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,platform:Linux, 030000004f04000012b3000010010000,Thrustmaster vibrating gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, 03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, -03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, +03000000d814000007cd000011010000,Toodles 2008 Chimp PC PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, 030000005e0400008e02000070050000,Torid,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,platform:Linux, 03000000c01100000591000011010000,Torid,a:b2,b:b1,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:b3,y:b0,platform:Linux, 03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000790000000600000007010000,USB gamepad,a:b2,b:b1,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:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, 03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, +03000000790000001100000011010000,USB Saturn Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux, +03000000790000002201000011010000,USB Saturn Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, +03000000b40400000a01000000010000,USB Saturn Pad,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux, 030000006f0e00000302000011010000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e00000702000011010000,Victrix Pro Fight Stick for PS4,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,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +05000000ac0500003232000001000000,VR Box Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 03000000791d00000103000010010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 050000000d0f0000f600000001000000,Wireless HORIPAD Switch Pro Controller,a:b0,b:b1,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:b2,y:b3,platform:Linux, -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,platform:Linux, -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,platform:Linux, -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,platform:Linux, -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,platform:Linux, -030000005e040000a102000000010000,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,platform:Linux, -030000005e040000a102000007010000,X360 Wireless 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,platform:Linux, +030000005e0400008e02000010010000,Xbox 360 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,platform:Linux, +030000005e0400008e02000014010000,Xbox 360 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,platform:Linux, +030000005e0400001907000000010000,Xbox 360 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,platform:Linux, +030000005e0400009102000007010000,Xbox 360 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,platform:Linux, +030000005e040000a102000000010000,Xbox 360 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,platform:Linux, +030000005e040000a102000007010000,Xbox 360 Wireless 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,platform:Linux, 0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, -030000005e040000a102000014010000,Xbox 360 Wireless Receiver (XBOX),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,platform:Linux, -0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000014010000,Xbox 360 Wireless Receiver,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,platform:Linux, +0000000058626f782047616d65706100,Xbox 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, 030000005e040000d102000002010000,Xbox One 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,platform:Linux, 050000005e040000fd02000030110000,Xbox One 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,platform:Linux, +050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000005e040000ea02000000000000,Xbox One Wireless 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,platform:Linux, 050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000005e040000ea02000001030000,Xbox One Wireless Controller (Model 1708),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,platform:Linux, +060000005e040000120b000007050000,Xbox One Wireless Controller (Model 1914),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,platform:Linux, 030000005e040000120b000001050000,Xbox Series 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,platform:Linux, 030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000005e040000120b000005050000,XBox Series pad,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,platform:Linux, -030000005e0400008e02000000010000,xbox360 Wireless EasySMX,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,platform:Linux, -03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,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:b2,y:b3,platform:Linux, -03000000ac0500005b05000010010000,Xiaoji Gamesir-G3w,a:b2,b:b1,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:b3,y:b0,platform:Linux, +030000005e040000120b000005050000,Xbox Series 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,platform:Linux, +030000005e0400008e02000000010000,Xbox 360 Wireless EasySMX,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,platform:Linux, +03000000450c00002043000010010000,XEOX Gamepad SL6556 BK,a:b0,b:b1,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:b2,y:b3,platform:Linux, +03000000ac0500005b05000010010000,Xiaoji Gamesir G3w,a:b2,b:b1,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:b3,y:b0,platform:Linux, 05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux, -03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, +03000000c0160000e105000001010000,XinMo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, xinput,XInput 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,platform:Linux, -03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,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,platform:Linux, -03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,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,platform:Linux, +03000000120c0000100e000011010000,Zeroplus P4 Gamepad,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,platform:Linux, +03000000120c0000101e000011010000,Zeroplus P4 Wired Gamepad,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,platform:Linux, # Android +38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android, +33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android, +39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android, +64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android, +66356438346136366337386437653934,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,start:b18,x:b19,y:b2,platform:Android, +66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android, 05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000051060000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, @@ -938,60 +1320,152 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android, +61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android, 05000000c82d000012900000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000062280000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,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,platform:Android, 05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +38303232393133383836366330346462,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +38346630346135363335366265656666,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +66306331643531333230306437353936,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000002600000ffff0f00,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 050000002028000009000000ffff3f00,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 050000003512000020ab000000780f00,8BitDo SNES30 Gamepad,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android, +33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, 05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, 05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -38383337343564366131323064613561,Brook Mars,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, +63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, +32333634613735616163326165323731,Amazon Luna Game Controller,a:b0,b:b1,back:b4,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,x:b2,y:b3,platform:Android, +38383337343564366131323064613561,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +33323763323132376537376266393366,Dual Strike,a:b24,b:b23,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android, +30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android, +05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34323662653333636330306631326233,Google Nexus,a:b0,b:b1,back:b4,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,platform:Android, +35383633353935396534393230616564,Google Stadia Controller,a:b0,b:b1,back:b15,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,platform:Android, 05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, 0500000031366332860c44aadfff0f00,GS Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b3,y:b2,platform:Android, +66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +35623466343433653739346434636330,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +65656436646661313232656661616130,Hori PC Engine Mini Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b18,platform:Android, +31303433326562636431653534636633,Hori Real Arcade Pro 3,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,platform:Android, +64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android, +65346535636333663931613264643164,Joy Con,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android, +33346566643039343630376565326335,Joy Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +35313531613435623366313835326238,Joy Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +39363561613936303237333537383931,Joy Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +38383665633039363066383334653465,Joy Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, +64623163333561643339623235373232,Logitech F310,a:b0,b:b1,back:b4,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,platform:Android, +35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +64396331333230326333313330336533,Logitech F710,a:b0,b:b1,back:b4,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,platform:Android, +30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, +32303165626138343962363666346165,Mars,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +31323564663862633234646330373138,Mega Drive,a:b23,b:b22,leftx:a0,lefty:a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, +37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, +64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Android, 64633436313965656664373634323364,Microsoft X-Box 360 pad,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,x:b2,y:b3,platform:Android, +32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,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,platform:Android, +33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android, 050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android, +34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 37336435666338653565313731303834,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,platform: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,platform:Android, 61363931656135336130663561616264,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,platform:Android, 050000005509000003720000cf7f3f00,NVIDIA Controller v01.01,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,platform:Android, 050000005509000010720000ffff3f00,NVIDIA Controller v01.03,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,platform:Android, 050000005509000014720000df7f3f00,NVIDIA Controller v01.04,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, +61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android, +32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android, +61363034663839376638653463633865,PS3,a:b0,b:b1,back:b15,dpdown:a14,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66366539656564653432353139356536,PS3,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,platform:Android, +66383132326164626636313737373037,PS3,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,platform:Android, 050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,platform:Android, +30303839663330346632363232623138,PS4,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +31326235383662333266633463653332,PS4,a:b1,b:b16,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b17,x:b0,y:b2,platform:Android, +31663838336334393132303338353963,PS4,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34613139376634626133336530386430,PS4,a:b0,b:b1,back:b15,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,platform:Android, +37626233336235343937333961353732,PS4,a:b0,b:b1,back:b15,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,platform:Android, +38393161636261653636653532386639,PS4,a:b0,b:b1,back:b15,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,platform:Android, +63313733393535663339656564343962,PS4,a:b0,b:b1,back:b15,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,platform:Android, +63393662363836383439353064663939,PS4,a:b0,b:b1,back:b4,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,platform:Android, +65366465656364636137653363376531,PS4,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +66613532303965383534396638613230,PS4,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, 030000004c050000cc09000000006800,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Android, 050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Android, 050000004c050000c4050000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, 050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Android, 050000004c050000cc090000fffe3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Android, 050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Android, +31373231336561636235613666323035,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,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,platform:Android, 35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, 050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +62653335326261303663356263626339,PSX,a:b19,b:b1,back:b17,leftshoulder:b9,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android, +64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,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,platform:Android, 62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,platform:Android, 050000003215000007070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,platform:Android, 050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, +61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android, +38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b6,platform:Android, +33373336396634316434323337666361,RumblePad 2,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android, +66386565396238363534313863353065,Sanwa Mobile,a:b21,b:b22,leftshoulder:b23,leftx:a0,lefty:a1,rightshoulder:b24,platform:Android, +32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, +37316565396364386635383230353365,Saturn,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, +38613865396530353338373763623431,Saturn,a:b0,b:b1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android, +61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, +30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,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,x:b2,y:b3,platform:Android, +66633132393363353531373465633064,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,leftshoulder:b20,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android, +62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, 32633532643734376632656664383733,Sony DualSense,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, 61303162353165316365336436343139,Sony DualSense,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android, +63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android, 05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, 05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, +0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android, 050000004f0400000ed00000fffe3f00,ThrustMaster eSwap PRO Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android, +30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b23,paddle2:b24,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b23,paddle2:b24,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +30386438313564306161393537333663,Wii Classic,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +33333034646336346339646538643633,Wii Classic,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, 30306539356238653637313730656134,Wireless HORIPAD Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +30396232393162346330326334636566,Xbox 360,a:b0,b:b1,back:b4,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,platform:Android, +38313038323730383864666463383533,Xbox 360,a:b0,b:b1,back:b4,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,platform:Android, +65353331386662343338643939643636,Xbox 360,a:b0,b:b1,back:b4,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,platform:Android, +65613532386633373963616462363038,Xbox 360,a:b0,b:b1,back:b4,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,platform:Android, 050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Android, +33356661323266333733373865656366,Xbox One Controller,a:b0,b:b1,back:b4,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,platform:Android, +35623965373264386238353433656138,Xbox One Controller,a:b0,b:b1,back:b4,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,platform:Android, 050000005e040000000b000000783f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, 050000005e040000e002000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Android, 050000005e040000ea02000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Android, 050000005e040000fd020000ff7f3f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Android, 050000005e040000e00200000ffe3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android, -050000005e040000fd020000ffff3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000fd020000ffff3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,platform:Android, 050000005e040000120b000000783f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, 050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,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,platform:Android, 65633038363832353634653836396239,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,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,platform:Android, 050000005e04000091020000ff073f00,Xbox Wireless Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, 34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android, +36616131643361333337396261666433,Xbox Wireless Controller,a:b0,b:b1,back:b15,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,platform:Android, 050000001727000044310000ffff3f00,XiaoMi Game Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, # iOS @@ -1017,5 +1491,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS, 050000005e040000050b0000df070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, 050000005e040000050b0000ff070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, 050000005e040000e0020000df070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, 050000005e040000e0020000ff070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, diff --git a/core/input/input.cpp b/core/input/input.cpp index 12028efc56..35ca8aefe6 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -1239,7 +1239,7 @@ void Input::parse_mapping(String p_mapping) { String output = entry[idx].get_slice(":", 0).replace(" ", ""); String input = entry[idx].get_slice(":", 1).replace(" ", ""); ERR_CONTINUE_MSG(output.length() < 1 || input.length() < 2, - String(entry[idx] + "\nInvalid device mapping entry: " + entry[idx])); + vformat("Invalid device mapping entry \"%s\" in mapping:\n%s", entry[idx], p_mapping)); if (output == "platform" || output == "hint") { continue; @@ -1247,7 +1247,8 @@ void Input::parse_mapping(String p_mapping) { JoyAxisRange output_range = FULL_AXIS; if (output[0] == '+' || output[0] == '-') { - ERR_CONTINUE_MSG(output.length() < 2, String(entry[idx] + "\nInvalid output: " + entry[idx])); + ERR_CONTINUE_MSG(output.length() < 2, + vformat("Invalid output entry \"%s\" in mapping:\n%s", entry[idx], p_mapping)); if (output[0] == '+') { output_range = POSITIVE_HALF_AXIS; } else if (output[0] == '-') { @@ -1273,9 +1274,9 @@ void Input::parse_mapping(String p_mapping) { JoyButton output_button = _get_output_button(output); JoyAxis output_axis = _get_output_axis(output); ERR_CONTINUE_MSG(output_button == JOY_BUTTON_INVALID && output_axis == JOY_AXIS_INVALID, - String(entry[idx] + "\nUnrecognised output string: " + output)); + vformat("Unrecognised output string \"%s\" in mapping:\n%s", output, p_mapping)); ERR_CONTINUE_MSG(output_button != JOY_BUTTON_INVALID && output_axis != JOY_AXIS_INVALID, - String("BUG: Output string matched both button and axis: " + output)); + vformat("Output string \"%s\" matched both button and axis in mapping:\n%s", output, p_mapping)); JoyBinding binding; if (output_button != JOY_BUTTON_INVALID) { @@ -1300,13 +1301,13 @@ void Input::parse_mapping(String p_mapping) { break; case 'h': ERR_CONTINUE_MSG(input.length() != 4 || input[2] != '.', - String(entry[idx] + "\nInvalid hat input: " + input)); + vformat("Invalid had input \"%s\" in mapping:\n%s", input, p_mapping)); binding.inputType = TYPE_HAT; binding.input.hat.hat = (HatDir)input.substr(1, 1).to_int(); binding.input.hat.hat_mask = static_cast<HatMask>(input.substr(3).to_int()); break; default: - ERR_CONTINUE_MSG(true, String(entry[idx] + "\nUnrecognised input string: " + input)); + ERR_CONTINUE_MSG(true, vformat("Unrecognized input string \"%s\" in mapping:\n%s", input, p_mapping)); } mapping.bindings.push_back(binding); diff --git a/core/io/resource.h b/core/io/resource.h index 9ccc247887..109c0f6611 100644 --- a/core/io/resource.h +++ b/core/io/resource.h @@ -103,6 +103,7 @@ public: virtual void set_path(const String &p_path, bool p_take_over = false); String get_path() const; + _FORCE_INLINE_ bool is_built_in() const { return path_cache.is_empty() || path_cache.find("::") != -1 || path_cache.begins_with("local://"); } static String generate_scene_unique_id(); void set_scene_unique_id(const String &p_id); diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index cbb033f6c6..a5a195f859 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1572,7 +1572,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia return; // don't save it } - if (res->get_path().length() && res->get_path().find("::") == -1) { + if (!res->is_built_in()) { f->store_32(OBJECT_EXTERNAL_RESOURCE_INDEX); f->store_32(external_resources[res]); } else { @@ -1743,7 +1743,7 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant return; } - if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) { + if (!p_main && (!bundle_resources) && !res->is_built_in()) { if (res->get_path() == path) { ERR_PRINT("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded."); return; @@ -1978,7 +1978,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p Set<String> used_unique_ids; for (RES &r : saved_resources) { - if (r->get_path() == "" || r->get_path().find("::") != -1) { + if (r->is_built_in()) { if (r->get_scene_unique_id() != "") { if (used_unique_ids.has(r->get_scene_unique_id())) { r->set_scene_unique_id(""); @@ -1992,7 +1992,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p Map<RES, int> resource_map; int res_index = 0; for (RES &r : saved_resources) { - if (r->get_path() == "" || r->get_path().find("::") != -1) { + if (r->is_built_in()) { if (r->get_scene_unique_id() == "") { String new_id; diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp index 51a1309f0e..f3e78c0080 100644 --- a/core/math/aabb.cpp +++ b/core/math/aabb.cpp @@ -33,7 +33,7 @@ #include "core/string/print_string.h" #include "core/variant/variant.h" -real_t AABB::get_area() const { +real_t AABB::get_volume() const { return size.x * size.y * size.z; } diff --git a/core/math/aabb.h b/core/math/aabb.h index c458e61475..02ce2501a0 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -46,8 +46,8 @@ public: Vector3 position; Vector3 size; - real_t get_area() const; /// get area - _FORCE_INLINE_ bool has_no_area() const { + real_t get_volume() const; + _FORCE_INLINE_ bool has_no_volume() const { return (size.x <= 0 || size.y <= 0 || size.z <= 0); } diff --git a/core/math/quaternion.h b/core/math/quaternion.h index e20ea74eb4..d8d0c06672 100644 --- a/core/math/quaternion.h +++ b/core/math/quaternion.h @@ -86,13 +86,6 @@ public: void operator*=(const Quaternion &p_q); Quaternion operator*(const Quaternion &p_q) const; - Quaternion operator*(const Vector3 &v) const { - return Quaternion(w * v.x + y * v.z - z * v.y, - w * v.y + z * v.x - x * v.z, - w * v.z + x * v.y - y * v.x, - -x * v.x - y * v.y - z * v.z); - } - _FORCE_INLINE_ Vector3 xform(const Vector3 &v) const { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized."); diff --git a/core/object/object.cpp b/core/object/object.cpp index e7d8b0e543..498f116997 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -645,7 +645,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT)); } if (!metadata.is_empty()) { - p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } if (script_instance && !p_reversed) { p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); @@ -1475,7 +1475,7 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) { return; } - if (!r->get_path().begins_with("res://") || r->get_path().find("::") == -1) { + if (!r->is_built_in()) { return; //not an internal resource } diff --git a/core/object/object.h b/core/object/object.h index 759e2ccdee..218bc26dec 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -137,7 +137,7 @@ enum PropertyUsageFlags { PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK, PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED, - PROPERTY_USAGE_NOEDITOR = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_NETWORK, + PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_NETWORK, }; #define ADD_SIGNAL(m_signal) ::ClassDB::add_signal(get_class_static(), m_signal) diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index b0ce46ca2b..c2449e3ddc 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -549,7 +549,7 @@ void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name, } } if (!found) { - properties.push_back(PropertyInfo(p_value.get_type(), p_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_SCRIPT_VARIABLE)); + properties.push_back(PropertyInfo(p_value.get_type(), p_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_SCRIPT_VARIABLE)); } } diff --git a/core/string/translation.cpp b/core/string/translation.cpp index 6ff31a4a02..b98aad9b58 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -938,7 +938,7 @@ void Translation::_bind_methods() { GDVIRTUAL_BIND(_get_plural_message, "src_message", "src_plural_message", "n", "context"); GDVIRTUAL_BIND(_get_message, "src_message", "context"); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "messages", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_messages", "_get_messages"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "messages", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_messages", "_get_messages"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "locale"), "set_locale", "get_locale"); } diff --git a/core/templates/thread_work_pool.h b/core/templates/thread_work_pool.h index b242648bc8..19096c496a 100644 --- a/core/templates/thread_work_pool.h +++ b/core/templates/thread_work_pool.h @@ -73,6 +73,7 @@ class ThreadWorkPool { ThreadData *threads = nullptr; uint32_t thread_count = 0; + uint32_t threads_working = 0; BaseWork *current_work = nullptr; static void _thread_function(void *p_user); @@ -94,7 +95,9 @@ public: current_work = w; - for (uint32_t i = 0; i < thread_count; i++) { + threads_working = MIN(p_elements, thread_count); + + for (uint32_t i = 0; i < threads_working; i++) { threads[i].work = w; threads[i].start.post(); } @@ -117,19 +120,32 @@ public: void end_work() { ERR_FAIL_COND(current_work == nullptr); - for (uint32_t i = 0; i < thread_count; i++) { + for (uint32_t i = 0; i < threads_working; i++) { threads[i].completed.wait(); threads[i].work = nullptr; } + threads_working = 0; memdelete(current_work); current_work = nullptr; } template <class C, class M, class U> void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { - begin_work(p_elements, p_instance, p_method, p_userdata); - end_work(); + switch (p_elements) { + case 0: + // Nothing to do, so do nothing. + break; + case 1: + // No value in pushing the work to another thread if it's a single job + // and we're going to wait for it to finish. Just run it right here. + (p_instance->*p_method)(0, p_userdata); + break; + default: + // Multiple jobs to do; commence threaded business. + begin_work(p_elements, p_instance, p_method, p_userdata); + end_work(); + } } _FORCE_INLINE_ int get_thread_count() const { return thread_count; } diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 2b1d330942..c3fe443456 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -752,8 +752,9 @@ struct _VariantCall { static PackedInt32Array func_PackedByteArray_decode_s32_array(PackedByteArray *p_instance) { uint64_t size = p_instance->size(); - const uint8_t *r = p_instance->ptr(); PackedInt32Array dest; + ERR_FAIL_COND_V_MSG(size < sizeof(int32_t), dest, "Size didn't match array of size int32_t, maybe you are trying to convert to the wrong type?"); + const uint8_t *r = p_instance->ptr(); dest.resize(size / sizeof(int32_t)); memcpy(dest.ptrw(), r, size); return dest; @@ -761,8 +762,9 @@ struct _VariantCall { static PackedInt64Array func_PackedByteArray_decode_s64_array(PackedByteArray *p_instance) { uint64_t size = p_instance->size(); - const uint8_t *r = p_instance->ptr(); PackedInt64Array dest; + ERR_FAIL_COND_V_MSG(size < sizeof(int64_t), dest, "Size didn't match array of size int64_t, maybe you are trying to convert to the wrong type?"); + const uint8_t *r = p_instance->ptr(); dest.resize(size / sizeof(int64_t)); memcpy(dest.ptrw(), r, size); return dest; @@ -770,8 +772,9 @@ struct _VariantCall { static PackedFloat32Array func_PackedByteArray_decode_float_array(PackedByteArray *p_instance) { uint64_t size = p_instance->size(); - const uint8_t *r = p_instance->ptr(); PackedFloat32Array dest; + ERR_FAIL_COND_V_MSG(size < sizeof(float), dest, "Size didn't match array of size float, maybe you are trying to convert to the wrong type?"); + const uint8_t *r = p_instance->ptr(); dest.resize(size / sizeof(float)); memcpy(dest.ptrw(), r, size); return dest; @@ -779,8 +782,9 @@ struct _VariantCall { static PackedFloat64Array func_PackedByteArray_decode_double_array(PackedByteArray *p_instance) { uint64_t size = p_instance->size(); - const uint8_t *r = p_instance->ptr(); PackedFloat64Array dest; + ERR_FAIL_COND_V_MSG(size < sizeof(double), dest, "Size didn't match array of size double, maybe you are trying to convert to the wrong type?"); + const uint8_t *r = p_instance->ptr(); dest.resize(size / sizeof(double)); memcpy(dest.ptrw(), r, size); return dest; @@ -1748,8 +1752,8 @@ static void _register_variant_builtin_methods() { bind_method(AABB, abs, sarray(), varray()); bind_method(AABB, get_center, sarray(), varray()); - bind_method(AABB, get_area, sarray(), varray()); - bind_method(AABB, has_no_area, sarray(), varray()); + bind_method(AABB, get_volume, sarray(), varray()); + bind_method(AABB, has_no_volume, sarray(), varray()); bind_method(AABB, has_no_surface, sarray(), varray()); bind_method(AABB, has_point, sarray("point"), varray()); bind_method(AABB, is_equal_approx, sarray("aabb"), varray()); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 4b710d5f12..ea49b6b634 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -14,6 +14,26 @@ <return type="Variant" /> <argument index="0" name="x" type="Variant" /> <description> + Returns the absolute value of a [Variant] parameter [code]x[/code] (i.e. non-negative value). Variant types [int], [float] (real), [Vector2], [Vector2i], [Vector3] and [Vector3i] are supported. + [codeblock] + var a = abs(-1) + # a is 1 + + var b = abs(-1.2) + # b is 1.2 + + var c = abs(Vector2(-3.5, -4)) + # c is (3.5, 4) + + var d = abs(Vector2i(-5, -6)) + # d is (5, 6) + + var e = abs(Vector3(-7, 8.5, -3.8)) + # e is (7, 8.5, 3.8) + + var f = abs(Vector3i(-7, -8, -9)) + # f is (7, 8, 9) + [/codeblock] </description> </method> <method name="absf"> @@ -118,6 +138,26 @@ <argument index="1" name="min" type="Variant" /> <argument index="2" name="max" type="Variant" /> <description> + Clamps the [Variant] [code]value[/code] and returns a value not less than [code]min[/code] and not more than [code]max[/code]. Variant types [int], [float] (real), [Vector2], [Vector2i], [Vector3] and [Vector3i] are supported. + [codeblock] + var a = clamp(-10, -1, 5) + # a is -1 + + var b = clamp(8.1, 0.9, 5.5) + # b is 5.5 + + var c = clamp(Vector2(-3.5, -4), Vector2(-3.2, -2), Vector2(2, 6.5)) + # c is (-3.2, -2) + + var d = clamp(Vector2i(7, 8), Vector2i(-3, -2), Vector2i(2, 6)) + # d is (2, 6) + + var e = clamp(Vector3(-7, 8.5, -3.8), Vector3(-3, -2, 5.4), Vector3(-2, 6, -4.1)) + # e is (-3, -2, 5.4) + + var f = clamp(Vector3i(-7, -8, -9), Vector3i(-1, 2, 3), Vector3i(-4, -5, -6)) + # f is (-4, -5, -6) + [/codeblock] </description> </method> <method name="clampf"> @@ -347,6 +387,7 @@ <return type="bool" /> <argument index="0" name="id" type="int" /> <description> + Returns [code]true[/code] if the Object that corresponds to [code]instance_id[/code] is a valid object (e.g. has not been deleted from memory). All Objects have a unique instance ID. </description> </method> <method name="is_instance_valid"> @@ -750,6 +791,14 @@ <return type="Variant" /> <argument index="0" name="x" type="Variant" /> <description> + Returns the sign of [code]x[/code] as same type of [Variant] as [code]x[/code] with each component being -1, 0 and 1 for each negative, zero and positive values respectivelu. Variant types [int], [float] (real), [Vector2], [Vector2i], [Vector3] and [Vector3i] are supported. + [codeblock] + sign(-6.0) # Returns -1 + sign(0.0) # Returns 0 + sign(6.0) # Returns 1 + + sign(Vector3(-6.0, 0.0, 6.0) # Returns (-1, 0, 1) + [/codeblock] </description> </method> <method name="signf"> @@ -2453,7 +2502,7 @@ <constant name="PROPERTY_USAGE_DEFAULT_INTL" value="71" enum="PropertyUsageFlags"> Default usage for translatable strings (storage, editor, network and internationalized). </constant> - <constant name="PROPERTY_USAGE_NOEDITOR" value="5" enum="PropertyUsageFlags"> + <constant name="PROPERTY_USAGE_NO_EDITOR" value="5" enum="PropertyUsageFlags"> Default usage but without showing the property in the editor (storage, network). </constant> <constant name="METHOD_FLAG_NORMAL" value="1" enum="MethodFlags"> diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index d7b7a309ad..f353cd19b8 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -57,12 +57,6 @@ Returns this [AABB] expanded to include a given point. </description> </method> - <method name="get_area" qualifiers="const"> - <return type="float" /> - <description> - Returns the volume of the [AABB]. - </description> - </method> <method name="get_center" qualifiers="const"> <return type="Vector3" /> <description> @@ -119,6 +113,12 @@ Returns the support point in a given direction. This is useful for collision detection algorithms. </description> </method> + <method name="get_volume" qualifiers="const"> + <return type="float" /> + <description> + Returns the volume of the [AABB]. + </description> + </method> <method name="grow" qualifiers="const"> <return type="AABB" /> <argument index="0" name="by" type="float" /> @@ -126,16 +126,16 @@ Returns a copy of the [AABB] grown a given amount of units towards all the sides. </description> </method> - <method name="has_no_area" qualifiers="const"> + <method name="has_no_surface" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if the [AABB] is flat or empty. + Returns [code]true[/code] if the [AABB] is empty. </description> </method> - <method name="has_no_surface" qualifiers="const"> + <method name="has_no_volume" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if the [AABB] is empty. + Returns [code]true[/code] if the [AABB] is flat or empty. </description> </method> <method name="has_point" qualifiers="const"> diff --git a/doc/classes/BitMap.xml b/doc/classes/BitMap.xml index 0997896260..dc655ee3b0 100644 --- a/doc/classes/BitMap.xml +++ b/doc/classes/BitMap.xml @@ -48,7 +48,7 @@ <argument index="0" name="pixels" type="int" /> <argument index="1" name="rect" type="Rect2" /> <description> - Applies morphological dilation to the bitmap. The first argument is the dilation amount, Rect2 is the area where the dilation will be applied. + Applies morphological dilation or erosion to the bitmap. If [code]pixels[/code] is positive, dilation is applied to the bitmap. If [code]pixels[/code] is negative, erosion is applied to the bitmap. [code]rect[/code] defines the area where the morphological operation is applied. Pixels located outside the [code]rect[/code] are unaffected by [method grow_mask]. </description> </method> <method name="opaque_to_polygons" qualifiers="const"> diff --git a/doc/classes/CPUParticles3D.xml b/doc/classes/CPUParticles3D.xml index fe8c354427..ad491465f2 100644 --- a/doc/classes/CPUParticles3D.xml +++ b/doc/classes/CPUParticles3D.xml @@ -126,7 +126,7 @@ Each particle's initial color. To have particle display color in a [BaseMaterial3D] make sure to set [member BaseMaterial3D.vertex_color_use_as_albedo] to [code]true[/code]. </member> <member name="color_ramp" type="Gradient" setter="set_color_ramp" getter="get_color_ramp"> - Each particle's color will vary along this [GradientTexture] over its lifetime (multiplied with [member color]). + Each particle's color will vary along this [GradientTexture1D] over its lifetime (multiplied with [member color]). </member> <member name="damping_curve" type="Curve" setter="set_param_curve" getter="get_param_curve"> Damping will vary along this [Curve]. diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml index 5f342e6dc2..5ae034c3ba 100644 --- a/doc/classes/EditorProperty.xml +++ b/doc/classes/EditorProperty.xml @@ -110,7 +110,7 @@ </signal> <signal name="property_checked"> <argument index="0" name="property" type="StringName" /> - <argument index="1" name="bool" type="String" /> + <argument index="1" name="checked" type="bool" /> <description> Emitted when a property was checked. Used internally. </description> @@ -134,6 +134,14 @@ Emit it if you want to key a property with a single value. </description> </signal> + <signal name="property_pinned"> + <argument index="0" name="property" type="StringName" /> + <argument index="1" name="pinned" type="bool" /> + <description> + Emit it if you want to mark (or unmark) the value of a property for being saved regardless of being equal to the default value. + The default value is the one the property will get when the node is just instantiated and can come from an ancestor scene in the inheritance/instancing chain, a script or a builtin class. + </description> + </signal> <signal name="resource_selected"> <argument index="0" name="path" type="String" /> <argument index="1" name="resource" type="Resource" /> diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index 88c4689b5f..4ea7f67eed 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -39,7 +39,7 @@ The global brightness value of the rendered scene. Effective only if [code]adjustment_enabled[/code] is [code]true[/code]. </member> <member name="adjustment_color_correction" type="Texture" setter="set_adjustment_color_correction" getter="get_adjustment_color_correction"> - The [Texture2D] or [Texture3D] lookup table (LUT) to use for the built-in post-process color grading. Can use a [GradientTexture] for a 1-dimensional LUT, or a [Texture3D] for a more complex LUT. Effective only if [code]adjustment_enabled[/code] is [code]true[/code]. + The [Texture2D] or [Texture3D] lookup table (LUT) to use for the built-in post-process color grading. Can use a [GradientTexture1D] for a 1-dimensional LUT, or a [Texture3D] for a more complex LUT. Effective only if [code]adjustment_enabled[/code] is [code]true[/code]. </member> <member name="adjustment_contrast" type="float" setter="set_adjustment_contrast" getter="get_adjustment_contrast" default="1.0"> The global contrast value of the rendered scene (default value is 1). Effective only if [code]adjustment_enabled[/code] is [code]true[/code]. diff --git a/doc/classes/FontData.xml b/doc/classes/FontData.xml index 04932ddd2d..ccfe861c92 100644 --- a/doc/classes/FontData.xml +++ b/doc/classes/FontData.xml @@ -93,6 +93,24 @@ Returns font descent (number of pixels below the baseline). </description> </method> + <method name="get_font_name" qualifiers="const"> + <return type="String" /> + <description> + Returns font family name. + </description> + </method> + <method name="get_font_style" qualifiers="const"> + <return type="int" /> + <description> + Returns font style flags, see [enum TextServer.FontStyle]. + </description> + </method> + <method name="get_font_style_name" qualifiers="const"> + <return type="String" /> + <description> + Returns font style name. + </description> + </method> <method name="get_glyph_advance" qualifiers="const"> <return type="Vector2" /> <argument index="0" name="cache_index" type="int" /> @@ -463,6 +481,27 @@ Sets the font descent (number of pixels below the baseline). </description> </method> + <method name="set_font_name"> + <return type="void" /> + <argument index="0" name="name" type="String" /> + <description> + Sets the font family name. + </description> + </method> + <method name="set_font_style"> + <return type="void" /> + <argument index="0" name="style" type="int" /> + <description> + Sets the font style flags, see [enum TextServer.FontStyle]. + </description> + </method> + <method name="set_font_style_name"> + <return type="void" /> + <argument index="0" name="name" type="String" /> + <description> + Sets the font style name. + </description> + </method> <method name="set_force_autohinter"> <return type="void" /> <argument index="0" name="force_autohinter" type="bool" /> diff --git a/doc/classes/Gradient.xml b/doc/classes/Gradient.xml index 93cef07b79..baba71b453 100644 --- a/doc/classes/Gradient.xml +++ b/doc/classes/Gradient.xml @@ -51,6 +51,12 @@ Removes the color at the index [code]point[/code]. </description> </method> + <method name="reverse"> + <return type="void" /> + <description> + Reverses/mirrors the gradient. + </description> + </method> <method name="set_color"> <return type="void" /> <argument index="0" name="point" type="int" /> @@ -72,8 +78,22 @@ <member name="colors" type="PackedColorArray" setter="set_colors" getter="get_colors" default="PackedColorArray(0, 0, 0, 1, 1, 1, 1, 1)"> Gradient's colors returned as a [PackedColorArray]. </member> + <member name="interpolation_mode" type="int" setter="set_interpolation_mode" getter="get_interpolation_mode" enum="Gradient.InterpolationMode" default="0"> + Defines how the colors between points of the gradient are interpolated. See [enum InterpolationMode] for available modes. + </member> <member name="offsets" type="PackedFloat32Array" setter="set_offsets" getter="get_offsets" default="PackedFloat32Array(0, 1)"> Gradient's offsets returned as a [PackedFloat32Array]. </member> </members> + <constants> + <constant name="GRADIENT_INTERPOLATE_LINEAR" value="0" enum="InterpolationMode"> + Linear interpolation. + </constant> + <constant name="GRADIENT_INTERPOLATE_CONSTANT" value="1" enum="InterpolationMode"> + Constant interpolation, color changes abruptly at each point and stays uniform between. This might cause visible aliasing when used for a gradient texture in some cases. + </constant> + <constant name="GRADIENT_INTERPOLATE_CUBIC" value="2" enum="InterpolationMode"> + Cubic interpolation. + </constant> + </constants> </class> diff --git a/doc/classes/GradientTexture.xml b/doc/classes/GradientTexture1D.xml index 0f0f0b1a37..223439956c 100644 --- a/doc/classes/GradientTexture.xml +++ b/doc/classes/GradientTexture1D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GradientTexture" inherits="Texture2D" version="4.0"> +<class name="GradientTexture1D" inherits="Texture2D" version="4.0"> <brief_description> Gradient-filled texture. </brief_description> <description> - GradientTexture uses a [Gradient] to fill the texture data. The gradient will be filled from left to right using colors obtained from the gradient. This means the texture does not necessarily represent an exact copy of the gradient, but instead an interpolation of samples obtained from the gradient at fixed steps (see [member width]). + GradientTexture1D uses a [Gradient] to fill the texture data. The gradient will be filled from left to right using colors obtained from the gradient. This means the texture does not necessarily represent an exact copy of the gradient, but instead an interpolation of samples obtained from the gradient at fixed steps (see [member width]). </description> <tutorials> </tutorials> diff --git a/doc/classes/InputEventScreenDrag.xml b/doc/classes/InputEventScreenDrag.xml index 373936225b..f86b5f3b4d 100644 --- a/doc/classes/InputEventScreenDrag.xml +++ b/doc/classes/InputEventScreenDrag.xml @@ -17,7 +17,7 @@ The drag position. </member> <member name="relative" type="Vector2" setter="set_relative" getter="get_relative" default="Vector2(0, 0)"> - The drag position relative to its start position. + The drag position relative to the previous position (position at the last frame). </member> <member name="speed" type="Vector2" setter="set_speed" getter="get_speed" default="Vector2(0, 0)"> The drag speed. diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index 3c349e052f..24ebf08c36 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -194,7 +194,7 @@ The vertical offset of the text's shadow. </theme_item> <theme_item name="shadow_outline_size" data_type="constant" type="int" default="1"> - Shadow outline size. If set to 1 or greater, the shadow will be displayed around the whole text as an outline. + The size of the shadow outline. </theme_item> </theme_items> </class> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index f79ba5a16f..a75bd2f704 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -196,6 +196,9 @@ <member name="expand_to_text_length" type="bool" setter="set_expand_to_text_length_enabled" getter="is_expand_to_text_length_enabled" default="false"> If [code]true[/code], the [LineEdit] width will increase to stay longer than the [member text]. It will [b]not[/b] compress if the [member text] is shortened. </member> + <member name="flat" type="bool" setter="set_flat" getter="is_flat" default="false"> + If [code]true[/code], the [LineEdit] don't display decoration. + </member> <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" override="true" enum="Control.FocusMode" default="2" /> <member name="language" type="String" setter="set_language" getter="get_language" default=""""> Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead. diff --git a/doc/classes/MenuButton.xml b/doc/classes/MenuButton.xml index 41ba1fcd0f..7f9d3d96dc 100644 --- a/doc/classes/MenuButton.xml +++ b/doc/classes/MenuButton.xml @@ -30,6 +30,9 @@ <member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" override="true" enum="BaseButton.ActionMode" default="0" /> <member name="flat" type="bool" setter="set_flat" getter="is_flat" override="true" default="true" /> <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" override="true" enum="Control.FocusMode" default="0" /> + <member name="items_count" type="int" setter="set_item_count" getter="get_item_count" default="0"> + The number of items currently in the list. + </member> <member name="switch_on_hover" type="bool" setter="set_switch_on_hover" getter="is_switch_on_hover" default="false"> If [code]true[/code], when the cursor hovers above another [MenuButton] within the same parent which also has [code]switch_on_hover[/code] enabled, it will close the current [MenuButton] and open the other one. </member> diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml index 618123855f..d0579c6f6f 100644 --- a/doc/classes/PackedScene.xml +++ b/doc/classes/PackedScene.xml @@ -121,5 +121,9 @@ If passed to [method instantiate], provides local scene resources to the local scene. Only the main scene should receive the main edit state. [b]Note:[/b] Only available in editor builds. </constant> + <constant name="GEN_EDIT_STATE_MAIN_INHERITED" value="3" enum="GenEditState"> + It's similar to [constant GEN_EDIT_STATE_MAIN], but for the case where the scene is being instantiated to be the base of another one. + [b]Note:[/b] Only available in editor builds. + </constant> </constants> </class> diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml index 3b583f5c89..2cc0d8f2b0 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticlesMaterial.xml @@ -128,7 +128,7 @@ Each particle's initial color. If the [GPUParticles2D]'s [code]texture[/code] is defined, it will be multiplied by this color. To have particle display color in a [BaseMaterial3D] make sure to set [member BaseMaterial3D.vertex_color_use_as_albedo] to [code]true[/code]. </member> <member name="color_ramp" type="Texture2D" setter="set_color_ramp" getter="get_color_ramp"> - Each particle's color will vary along this [GradientTexture] over its lifetime (multiplied with [member color]). + Each particle's color will vary along this [GradientTexture1D] over its lifetime (multiplied with [member color]). </member> <member name="damping_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture"> Damping will vary along this [CurveTexture]. diff --git a/doc/classes/PhysicsDirectSpaceState2D.xml b/doc/classes/PhysicsDirectSpaceState2D.xml index 887b382267..5892ef266f 100644 --- a/doc/classes/PhysicsDirectSpaceState2D.xml +++ b/doc/classes/PhysicsDirectSpaceState2D.xml @@ -13,7 +13,7 @@ <methods> <method name="cast_motion"> <return type="Array" /> - <argument index="0" name="shape" type="PhysicsShapeQueryParameters2D" /> + <argument index="0" name="parameters" type="PhysicsShapeQueryParameters2D" /> <description> Checks how far a [Shape2D] can move without colliding. All the parameters for the query, including the shape and the motion, are supplied through a [PhysicsShapeQueryParameters2D] object. Returns an array with the safe and unsafe proportions (between 0 and 1) of the motion. The safe proportion is the maximum fraction of the motion that can be made without a collision. The unsafe proportion is the minimum fraction of the distance that must be moved for a collision. If no collision is detected a result of [code][1.0, 1.0][/code] will be returned. @@ -22,7 +22,7 @@ </method> <method name="collide_shape"> <return type="Array" /> - <argument index="0" name="shape" type="PhysicsShapeQueryParameters2D" /> + <argument index="0" name="parameters" type="PhysicsShapeQueryParameters2D" /> <argument index="1" name="max_results" type="int" default="32" /> <description> Checks the intersections of a shape, given through a [PhysicsShapeQueryParameters2D] object, against the space. The resulting array contains a list of points where the shape intersects another. Like with [method intersect_shape], the number of returned results can be limited to save processing time. @@ -31,7 +31,7 @@ </method> <method name="get_rest_info"> <return type="Dictionary" /> - <argument index="0" name="shape" type="PhysicsShapeQueryParameters2D" /> + <argument index="0" name="parameters" type="PhysicsShapeQueryParameters2D" /> <description> Checks the intersections of a shape, given through a [PhysicsShapeQueryParameters2D] object, against the space. If it collides with more than one shape, the nearest one is selected. If the shape did not intersect anything, then an empty dictionary is returned instead. [b]Note:[/b] This method does not take into account the [code]motion[/code] property of the object. The returned object is a dictionary containing the following fields: @@ -45,51 +45,23 @@ </method> <method name="intersect_point"> <return type="Array" /> - <argument index="0" name="point" type="Vector2" /> + <argument index="0" name="parameters" type="PhysicsPointQueryParameters2D" /> <argument index="1" name="max_results" type="int" default="32" /> - <argument index="2" name="exclude" type="Array" default="[]" /> - <argument index="3" name="collision_mask" type="int" default="4294967295" /> - <argument index="4" name="collide_with_bodies" type="bool" default="true" /> - <argument index="5" name="collide_with_areas" type="bool" default="false" /> <description> - Checks whether a point is inside any solid shape. The shapes the point is inside of are returned in an array containing dictionaries with the following fields: + Checks whether a point is inside any solid shape. Position and other parameters are defined through [PhysicsPointQueryParameters2D]. The shapes the point is inside of are returned in an array containing dictionaries with the following fields: [code]collider[/code]: The colliding object. [code]collider_id[/code]: The colliding object's ID. [code]rid[/code]: The intersecting object's [RID]. [code]shape[/code]: The shape index of the colliding shape. - Additionally, the method can take an [code]exclude[/code] array of objects or [RID]s that are to be excluded from collisions, a [code]collision_mask[/code] bitmask representing the physics layers to detect (all layers by default), or booleans to determine if the ray should collide with [PhysicsBody2D]s or [Area2D]s, respectively. - [b]Note:[/b] [ConcavePolygonShape2D]s and [CollisionPolygon2D]s in [code]Segments[/code] build mode are not solid shapes. Therefore, they will not be detected. - </description> - </method> - <method name="intersect_point_on_canvas"> - <return type="Array" /> - <argument index="0" name="point" type="Vector2" /> - <argument index="1" name="canvas_instance_id" type="int" /> - <argument index="2" name="max_results" type="int" default="32" /> - <argument index="3" name="exclude" type="Array" default="[]" /> - <argument index="4" name="collision_mask" type="int" default="4294967295" /> - <argument index="5" name="collide_with_bodies" type="bool" default="true" /> - <argument index="6" name="collide_with_areas" type="bool" default="false" /> - <description> - Checks whether a point is inside any solid shape, in a specific canvas layer given by [code]canvas_instance_id[/code]. The shapes the point is inside of are returned in an array containing dictionaries with the following fields: - [code]collider[/code]: The colliding object. - [code]collider_id[/code]: The colliding object's ID. - [code]rid[/code]: The intersecting object's [RID]. - [code]shape[/code]: The shape index of the colliding shape. - Additionally, the method can take an [code]exclude[/code] array of objects or [RID]s that are to be excluded from collisions, a [code]collision_mask[/code] bitmask representing the physics layers to detect (all layers by default), or booleans to determine if the ray should collide with [PhysicsBody2D]s or [Area2D]s, respectively. + The number of intersections can be limited with the [code]max_results[/code] parameter, to reduce the processing time. [b]Note:[/b] [ConcavePolygonShape2D]s and [CollisionPolygon2D]s in [code]Segments[/code] build mode are not solid shapes. Therefore, they will not be detected. </description> </method> <method name="intersect_ray"> <return type="Dictionary" /> - <argument index="0" name="from" type="Vector2" /> - <argument index="1" name="to" type="Vector2" /> - <argument index="2" name="exclude" type="Array" default="[]" /> - <argument index="3" name="collision_mask" type="int" default="4294967295" /> - <argument index="4" name="collide_with_bodies" type="bool" default="true" /> - <argument index="5" name="collide_with_areas" type="bool" default="false" /> + <argument index="0" name="parameters" type="PhysicsRayQueryParameters2D" /> <description> - Intersects a ray in a given space. The returned object is a dictionary with the following fields: + Intersects a ray in a given space. Ray position and other parameters are defined through [PhysicsRayQueryParameters2D]. The returned object is a dictionary with the following fields: [code]collider[/code]: The colliding object. [code]collider_id[/code]: The colliding object's ID. [code]normal[/code]: The object's surface normal at the intersection point. @@ -97,16 +69,14 @@ [code]rid[/code]: The intersecting object's [RID]. [code]shape[/code]: The shape index of the colliding shape. If the ray did not intersect anything, then an empty dictionary is returned instead. - Additionally, the method can take an [code]exclude[/code] array of objects or [RID]s that are to be excluded from collisions, a [code]collision_mask[/code] bitmask representing the physics layers to detect (all layers by default), or booleans to determine if the ray should collide with [PhysicsBody2D]s or [Area2D]s, respectively. </description> </method> <method name="intersect_shape"> <return type="Array" /> - <argument index="0" name="shape" type="PhysicsShapeQueryParameters2D" /> + <argument index="0" name="parameters" type="PhysicsShapeQueryParameters2D" /> <argument index="1" name="max_results" type="int" default="32" /> <description> - Checks the intersections of a shape, given through a [PhysicsShapeQueryParameters2D] object, against the space. - [b]Note:[/b] This method does not take into account the [code]motion[/code] property of the object. The intersected shapes are returned in an array containing dictionaries with the following fields: + Checks the intersections of a shape, given through a [PhysicsShapeQueryParameters2D] object, against the space. The intersected shapes are returned in an array containing dictionaries with the following fields: [code]collider[/code]: The colliding object. [code]collider_id[/code]: The colliding object's ID. [code]rid[/code]: The intersecting object's [RID]. diff --git a/doc/classes/PhysicsDirectSpaceState3D.xml b/doc/classes/PhysicsDirectSpaceState3D.xml index 8c37072f29..6a7fe46518 100644 --- a/doc/classes/PhysicsDirectSpaceState3D.xml +++ b/doc/classes/PhysicsDirectSpaceState3D.xml @@ -13,8 +13,7 @@ <methods> <method name="cast_motion"> <return type="Array" /> - <argument index="0" name="shape" type="PhysicsShapeQueryParameters3D" /> - <argument index="1" name="motion" type="Vector3" /> + <argument index="0" name="parameters" type="PhysicsShapeQueryParameters3D" /> <description> Checks how far a [Shape3D] can move without colliding. All the parameters for the query, including the shape, are supplied through a [PhysicsShapeQueryParameters3D] object. Returns an array with the safe and unsafe proportions (between 0 and 1) of the motion. The safe proportion is the maximum fraction of the motion that can be made without a collision. The unsafe proportion is the minimum fraction of the distance that must be moved for a collision. If no collision is detected a result of [code][1.0, 1.0][/code] will be returned. @@ -23,16 +22,17 @@ </method> <method name="collide_shape"> <return type="Array" /> - <argument index="0" name="shape" type="PhysicsShapeQueryParameters3D" /> + <argument index="0" name="parameters" type="PhysicsShapeQueryParameters3D" /> <argument index="1" name="max_results" type="int" default="32" /> <description> Checks the intersections of a shape, given through a [PhysicsShapeQueryParameters3D] object, against the space. The resulting array contains a list of points where the shape intersects another. Like with [method intersect_shape], the number of returned results can be limited to save processing time. Returned points are a list of pairs of contact points. For each pair the first one is in the shape passed in [PhysicsShapeQueryParameters3D] object, second one is in the collided shape from the physics space. + [b]Note:[/b] This method does not take into account the [code]motion[/code] property of the object. </description> </method> <method name="get_rest_info"> <return type="Dictionary" /> - <argument index="0" name="shape" type="PhysicsShapeQueryParameters3D" /> + <argument index="0" name="parameters" type="PhysicsShapeQueryParameters3D" /> <description> Checks the intersections of a shape, given through a [PhysicsShapeQueryParameters3D] object, against the space. If it collides with more than one shape, the nearest one is selected. The returned object is a dictionary containing the following fields: [code]collider_id[/code]: The colliding object's ID. @@ -42,18 +42,27 @@ [code]rid[/code]: The intersecting object's [RID]. [code]shape[/code]: The shape index of the colliding shape. If the shape did not intersect anything, then an empty dictionary is returned instead. + [b]Note:[/b] This method does not take into account the [code]motion[/code] property of the object. + </description> + </method> + <method name="intersect_point"> + <return type="Array" /> + <argument index="0" name="parameters" type="PhysicsPointQueryParameters3D" /> + <argument index="1" name="max_results" type="int" default="32" /> + <description> + Checks whether a point is inside any solid shape. Position and other parameters are defined through [PhysicsPointQueryParameters3D]. The shapes the point is inside of are returned in an array containing dictionaries with the following fields: + [code]collider[/code]: The colliding object. + [code]collider_id[/code]: The colliding object's ID. + [code]rid[/code]: The intersecting object's [RID]. + [code]shape[/code]: The shape index of the colliding shape. + The number of intersections can be limited with the [code]max_results[/code] parameter, to reduce the processing time. </description> </method> <method name="intersect_ray"> <return type="Dictionary" /> - <argument index="0" name="from" type="Vector3" /> - <argument index="1" name="to" type="Vector3" /> - <argument index="2" name="exclude" type="Array" default="[]" /> - <argument index="3" name="collision_mask" type="int" default="4294967295" /> - <argument index="4" name="collide_with_bodies" type="bool" default="true" /> - <argument index="5" name="collide_with_areas" type="bool" default="false" /> + <argument index="0" name="parameters" type="PhysicsRayQueryParameters3D" /> <description> - Intersects a ray in a given space. The returned object is a dictionary with the following fields: + Intersects a ray in a given space. Ray position and other parameters are defined through [PhysicsRayQueryParameters3D]. The returned object is a dictionary with the following fields: [code]collider[/code]: The colliding object. [code]collider_id[/code]: The colliding object's ID. [code]normal[/code]: The object's surface normal at the intersection point. @@ -61,12 +70,11 @@ [code]rid[/code]: The intersecting object's [RID]. [code]shape[/code]: The shape index of the colliding shape. If the ray did not intersect anything, then an empty dictionary is returned instead. - Additionally, the method can take an [code]exclude[/code] array of objects or [RID]s that are to be excluded from collisions, a [code]collision_mask[/code] bitmask representing the physics layers to detect (all layers by default), or booleans to determine if the ray should collide with [PhysicsBody3D]s or [Area3D]s, respectively. </description> </method> <method name="intersect_shape"> <return type="Array" /> - <argument index="0" name="shape" type="PhysicsShapeQueryParameters3D" /> + <argument index="0" name="parameters" type="PhysicsShapeQueryParameters3D" /> <argument index="1" name="max_results" type="int" default="32" /> <description> Checks the intersections of a shape, given through a [PhysicsShapeQueryParameters3D] object, against the space. The intersected shapes are returned in an array containing dictionaries with the following fields: @@ -75,6 +83,7 @@ [code]rid[/code]: The intersecting object's [RID]. [code]shape[/code]: The shape index of the colliding shape. The number of intersections can be limited with the [code]max_results[/code] parameter, to reduce the processing time. + [b]Note:[/b] This method does not take into account the [code]motion[/code] property of the object. </description> </method> </methods> diff --git a/doc/classes/PhysicsPointQueryParameters2D.xml b/doc/classes/PhysicsPointQueryParameters2D.xml new file mode 100644 index 0000000000..6acd83b101 --- /dev/null +++ b/doc/classes/PhysicsPointQueryParameters2D.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="PhysicsPointQueryParameters2D" inherits="RefCounted" version="4.0"> + <brief_description> + Parameters to be sent to a 2D point physics query. + </brief_description> + <description> + This class contains the position and other parameters to be used for [method PhysicsDirectSpaceState2D.intersect_point]. + </description> + <tutorials> + </tutorials> + <members> + <member name="canvas_instance_id" type="int" setter="set_canvas_instance_id" getter="get_canvas_instance_id" default="0"> + If different from [code]0[/code], restricts the query to a specific canvas layer specified by its instance id. See [method Object.get_instance_id]. + </member> + <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> + If [code]true[/code], the query will take [Area2D]s into account. + </member> + <member name="collide_with_bodies" type="bool" setter="set_collide_with_bodies" getter="is_collide_with_bodies_enabled" default="true"> + If [code]true[/code], the query will take [PhysicsBody2D]s into account. + </member> + <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295"> + The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + </member> + <member name="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]"> + The list of objects or object [RID]s that will be excluded from collisions. + </member> + <member name="position" type="Vector2" setter="set_position" getter="get_position" default="Vector2(0, 0)"> + The position being queried for, in global coordinates. + </member> + </members> +</class> diff --git a/doc/classes/PhysicsPointQueryParameters3D.xml b/doc/classes/PhysicsPointQueryParameters3D.xml new file mode 100644 index 0000000000..488f56872d --- /dev/null +++ b/doc/classes/PhysicsPointQueryParameters3D.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="PhysicsPointQueryParameters3D" inherits="RefCounted" version="4.0"> + <brief_description> + Parameters to be sent to a 3D point physics query. + </brief_description> + <description> + This class contains the position and other parameters to be used for [method PhysicsDirectSpaceState3D.intersect_point]. + </description> + <tutorials> + </tutorials> + <members> + <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> + If [code]true[/code], the query will take [Area3D]s into account. + </member> + <member name="collide_with_bodies" type="bool" setter="set_collide_with_bodies" getter="is_collide_with_bodies_enabled" default="true"> + If [code]true[/code], the query will take [PhysicsBody3D]s into account. + </member> + <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295"> + The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + </member> + <member name="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]"> + The list of objects or object [RID]s that will be excluded from collisions. + </member> + <member name="position" type="Vector3" setter="set_position" getter="get_position" default="Vector3(0, 0, 0)"> + The position being queried for, in global coordinates. + </member> + </members> +</class> diff --git a/doc/classes/PhysicsRayQueryParameters2D.xml b/doc/classes/PhysicsRayQueryParameters2D.xml new file mode 100644 index 0000000000..0e99e47286 --- /dev/null +++ b/doc/classes/PhysicsRayQueryParameters2D.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="PhysicsRayQueryParameters2D" inherits="RefCounted" version="4.0"> + <brief_description> + Parameters to be sent to a 2D ray physics query. + </brief_description> + <description> + This class contains the ray position and other parameters to be used for [method PhysicsDirectSpaceState2D.intersect_ray]. + </description> + <tutorials> + </tutorials> + <members> + <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> + If [code]true[/code], the query will take [Area2D]s into account. + </member> + <member name="collide_with_bodies" type="bool" setter="set_collide_with_bodies" getter="is_collide_with_bodies_enabled" default="true"> + If [code]true[/code], the query will take [PhysicsBody2D]s into account. + </member> + <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295"> + The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + </member> + <member name="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]"> + The list of objects or object [RID]s that will be excluded from collisions. + </member> + <member name="from" type="Vector2" setter="set_from" getter="get_from" default="Vector2(0, 0)"> + The starting point of the ray being queried for, in global coordinates. + </member> + <member name="to" type="Vector2" setter="set_to" getter="get_to" default="Vector2(0, 0)"> + The ending point of the ray being queried for, in global coordinates. + </member> + </members> +</class> diff --git a/doc/classes/PhysicsRayQueryParameters3D.xml b/doc/classes/PhysicsRayQueryParameters3D.xml new file mode 100644 index 0000000000..dbd09e5128 --- /dev/null +++ b/doc/classes/PhysicsRayQueryParameters3D.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="PhysicsRayQueryParameters3D" inherits="RefCounted" version="4.0"> + <brief_description> + Parameters to be sent to a 3D ray physics query. + </brief_description> + <description> + This class contains the ray position and other parameters to be used for [method PhysicsDirectSpaceState3D.intersect_ray]. + </description> + <tutorials> + </tutorials> + <members> + <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> + If [code]true[/code], the query will take [Area3D]s into account. + </member> + <member name="collide_with_bodies" type="bool" setter="set_collide_with_bodies" getter="is_collide_with_bodies_enabled" default="true"> + If [code]true[/code], the query will take [PhysicsBody3D]s into account. + </member> + <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295"> + The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + </member> + <member name="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]"> + The list of objects or object [RID]s that will be excluded from collisions. + </member> + <member name="from" type="Vector3" setter="set_from" getter="get_from" default="Vector3(0, 0, 0)"> + The starting point of the ray being queried for, in global coordinates. + </member> + <member name="to" type="Vector3" setter="set_to" getter="get_to" default="Vector3(0, 0, 0)"> + The ending point of the ray being queried for, in global coordinates. + </member> + </members> +</class> diff --git a/doc/classes/PhysicsShapeQueryParameters2D.xml b/doc/classes/PhysicsShapeQueryParameters2D.xml index 6035b662ea..abd19f1326 100644 --- a/doc/classes/PhysicsShapeQueryParameters2D.xml +++ b/doc/classes/PhysicsShapeQueryParameters2D.xml @@ -4,7 +4,7 @@ Parameters to be sent to a 2D shape physics query. </brief_description> <description> - This class contains the shape and other parameters for 2D intersection/collision queries. + This class contains the shape and other parameters for [PhysicsDirectSpaceState2D] intersection/collision queries. </description> <tutorials> </tutorials> diff --git a/doc/classes/PhysicsShapeQueryParameters3D.xml b/doc/classes/PhysicsShapeQueryParameters3D.xml index 1a289ff9d0..2dffd5347a 100644 --- a/doc/classes/PhysicsShapeQueryParameters3D.xml +++ b/doc/classes/PhysicsShapeQueryParameters3D.xml @@ -4,7 +4,7 @@ Parameters to be sent to a 3D shape physics query. </brief_description> <description> - This class contains the shape and other parameters for 3D intersection/collision queries. + This class contains the shape and other parameters for [PhysicsDirectSpaceState3D] intersection/collision queries. </description> <tutorials> </tutorials> @@ -24,6 +24,9 @@ <member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.0"> The collision margin for the shape. </member> + <member name="motion" type="Vector3" setter="set_motion" getter="get_motion" default="Vector3(0, 0, 0)"> + The motion of the shape being queried for. + </member> <member name="shape" type="Resource" setter="set_shape" getter="get_shape"> The [Shape3D] that will be used for collision/intersection queries. This stores the actual reference which avoids the shape to be released while being used for queries, so always prefer using this over [member shape_rid]. </member> diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index 2208c12e56..044325afbe 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -199,12 +199,6 @@ Returns the accelerator of the item at index [code]idx[/code]. Accelerators are special combinations of keys that activate the item, no matter which control is focused. </description> </method> - <method name="get_item_count" qualifiers="const"> - <return type="int" /> - <description> - Returns the number of items in the [PopupMenu]. - </description> - </method> <method name="get_item_icon" qualifiers="const"> <return type="Texture2D" /> <argument index="0" name="idx" type="int" /> @@ -511,6 +505,9 @@ <member name="hide_on_state_item_selection" type="bool" setter="set_hide_on_state_item_selection" getter="is_hide_on_state_item_selection" default="false"> If [code]true[/code], hides the [PopupMenu] when a state item is selected. </member> + <member name="items_count" type="int" setter="set_item_count" getter="get_item_count" default="0"> + The number of items currently in the list. + </member> <member name="submenu_popup_delay" type="float" setter="set_submenu_popup_delay" getter="get_submenu_popup_delay" default="0.3"> Sets the delay time in seconds for the submenu item to popup on mouse hovering. If the popup menu is added as a child of another (acting as a submenu), it will inherit the delay time of the parent menu item. </member> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 86e66a5738..68b79ff749 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -2575,12 +2575,9 @@ </method> <method name="request_frame_drawn_callback"> <return type="void" /> - <argument index="0" name="where" type="Object" /> - <argument index="1" name="method" type="StringName" /> - <argument index="2" name="userdata" type="Variant" /> + <argument index="0" name="callable" type="Callable" /> <description> - Schedules a callback to the corresponding named [code]method[/code] on [code]where[/code] after a frame has been drawn. - The callback method must use only 1 argument which will be called with [code]userdata[/code]. + Schedules a callback to the given callable after a frame has been drawn. </description> </method> <method name="scenario_create"> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 0fd25615ba..3255c748b7 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -586,15 +586,15 @@ <theme_item name="selection_color" data_type="color" type="Color" default="Color(0.1, 0.1, 1, 0.8)"> The color of the selection box. </theme_item> - <theme_item name="shadow_as_outline" data_type="constant" type="int" default="0"> - Boolean value. If 1 ([code]true[/code]), the shadow will be displayed around the whole text as an outline. - </theme_item> <theme_item name="shadow_offset_x" data_type="constant" type="int" default="1"> The horizontal offset of the font's shadow. </theme_item> <theme_item name="shadow_offset_y" data_type="constant" type="int" default="1"> The vertical offset of the font's shadow. </theme_item> + <theme_item name="shadow_outline_size" data_type="constant" type="int" default="1"> + The size of the shadow outline. + </theme_item> <theme_item name="table_border" data_type="color" type="Color" default="Color(0, 0, 0, 0)"> The default cell border color. </theme_item> diff --git a/doc/classes/SceneState.xml b/doc/classes/SceneState.xml index 1c3bac9270..9a22b24825 100644 --- a/doc/classes/SceneState.xml +++ b/doc/classes/SceneState.xml @@ -168,5 +168,9 @@ If passed to [method PackedScene.instantiate], provides local scene resources to the local scene. Only the main scene should receive the main edit state. [b]Note:[/b] Only available in editor builds. </constant> + <constant name="GEN_EDIT_STATE_MAIN_INHERITED" value="3" enum="GenEditState"> + If passed to [method PackedScene.instantiate], it's similar to [constant GEN_EDIT_STATE_MAIN], but for the case where the scene is being instantiated to be the base of another one. + [b]Note:[/b] Only available in editor builds. + </constant> </constants> </class> diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml index 5bd6b0572c..a7122b827e 100644 --- a/doc/classes/TextParagraph.xml +++ b/doc/classes/TextParagraph.xml @@ -278,6 +278,9 @@ <member name="align" type="int" setter="set_align" getter="get_align" enum="HAlign" default="0"> Paragraph horizontal alignment. </member> + <member name="custom_punctuation" type="String" setter="set_custom_punctuation" getter="get_custom_punctuation" default=""""> + Custom punctuation character list, used for word breaking. If set to empty string, server defaults are used. + </member> <member name="direction" type="int" setter="set_direction" getter="get_direction" enum="TextServer.Direction" default="0"> Text writing direction. </member> diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index 3e32afe370..e1c05165de 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -254,6 +254,13 @@ Returns source font size used to generate MSDF textures. </description> </method> + <method name="font_get_name" qualifiers="const"> + <return type="String" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Returns font family name. + </description> + </method> <method name="font_get_oversampling" qualifiers="const"> <return type="float" /> <argument index="0" name="font_rid" type="RID" /> @@ -300,6 +307,20 @@ Returns extra spacing added between glyphs in pixels. </description> </method> + <method name="font_get_style" qualifiers="const"> + <return type="int" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Returns font style flags, see [enum FontStyle]. + </description> + </method> + <method name="font_get_style_name" qualifiers="const"> + <return type="String" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Returns font style name. + </description> + </method> <method name="font_get_supported_chars" qualifiers="const"> <return type="String" /> <argument index="0" name="font_rid" type="RID" /> @@ -634,6 +655,14 @@ [b]Note:[/b] MSDF font rendering does not render glyphs with overlapping shapes correctly. Overlapping shapes are not valid per the OpenType standard, but are still commonly found in many font files, especially those converted by Google Fonts. To avoid issues with overlapping glyphs, consider downloading the font file directly from the type foundry instead of relying on Google Fonts. </description> </method> + <method name="font_set_name"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="name" type="String" /> + <description> + Sets the font family name. + </description> + </method> <method name="font_set_oversampling"> <return type="void" /> <argument index="0" name="font_rid" type="RID" /> @@ -670,6 +699,22 @@ Sets extra spacing added between glyphs in pixels. </description> </method> + <method name="font_set_style"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="style" type="int" /> + <description> + Sets the font style flags, see [enum FontStyle]. + </description> + </method> + <method name="font_set_style_name"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="name" type="String" /> + <description> + Set the font style name. + </description> + </method> <method name="font_set_texture_image"> <return type="void" /> <argument index="0" name="font_rid" type="RID" /> @@ -917,6 +962,13 @@ Returns shapes of the carets corresponding to the character offset [code]position[/code] in the text. Returned caret shape is 1 pixel wide rectangle. </description> </method> + <method name="shaped_text_get_custom_punctuation" qualifiers="const"> + <return type="String" /> + <argument index="0" name="shaped" type="RID" /> + <description> + Returns custom punctuation character list, used for word breaking. If set to empty string, server defaults are used. + </description> + </method> <method name="shaped_text_get_descent" qualifiers="const"> <return type="float" /> <argument index="0" name="shaped" type="RID" /> @@ -1167,6 +1219,14 @@ Override ranges should cover full source text without overlaps. BiDi algorithm will be used on each range separately. </description> </method> + <method name="shaped_text_set_custom_punctuation"> + <return type="void" /> + <argument index="0" name="shaped" type="RID" /> + <argument index="1" name="punct" type="String" /> + <description> + Sets custom punctuation character list, used for word breaking. If set to empty string, server defaults are used. + </description> + </method> <method name="shaped_text_set_direction"> <return type="void" /> <argument index="0" name="shaped" type="RID" /> @@ -1402,5 +1462,14 @@ <constant name="SPACING_BOTTOM" value="3" enum="SpacingType"> Spacing at the bottom of the line. </constant> + <constant name="FONT_BOLD" value="1" enum="FontStyle"> + Font is bold. + </constant> + <constant name="FONT_ITALIC" value="2" enum="FontStyle"> + Font is italic or oblique. + </constant> + <constant name="FONT_FIXED_WIDTH" value="4" enum="FontStyle"> + Font have fixed-width characters. + </constant> </constants> </class> diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml index 99382d5463..684a1aa755 100644 --- a/doc/classes/TextServerExtension.xml +++ b/doc/classes/TextServerExtension.xml @@ -254,6 +254,13 @@ Returns source font size used to generate MSDF textures. </description> </method> + <method name="_font_get_name" qualifiers="virtual const"> + <return type="String" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Returns font family name. + </description> + </method> <method name="_font_get_oversampling" qualifiers="virtual const"> <return type="float" /> <argument index="0" name="font_rid" type="RID" /> @@ -300,6 +307,20 @@ Returns extra spacing added between glyphs in pixels. </description> </method> + <method name="_font_get_style" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Returns font style flags, see [enum TextServer.FontStyle]. + </description> + </method> + <method name="_font_get_style_name" qualifiers="virtual const"> + <return type="String" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Returns font style name. + </description> + </method> <method name="_font_get_supported_chars" qualifiers="virtual const"> <return type="String" /> <argument index="0" name="font_rid" type="RID" /> @@ -641,6 +662,14 @@ If set to [code]true[/code], glyphs of all sizes are rendered using single multichannel signed distance field generated from the dynamic font vector data. </description> </method> + <method name="_font_set_name" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="name" type="String" /> + <description> + Sets the font family name. + </description> + </method> <method name="_font_set_oversampling" qualifiers="virtual"> <return type="void" /> <argument index="0" name="font_rid" type="RID" /> @@ -677,6 +706,22 @@ Sets extra spacing added between glyphs in pixels. </description> </method> + <method name="_font_set_style" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="style" type="int" /> + <description> + Sets the font style flags, see [enum TextServer.FontStyle]. + </description> + </method> + <method name="_font_set_style_name" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="name_style" type="String" /> + <description> + Sets the font style name. + </description> + </method> <method name="_font_set_texture_image" qualifiers="virtual"> <return type="void" /> <argument index="0" name="font_rid" type="RID" /> @@ -924,6 +969,13 @@ Returns shapes of the carets corresponding to the character offset [code]position[/code] in the text. Returned caret shape is 1 pixel wide rectangle. </description> </method> + <method name="_shaped_text_get_custom_punctuation" qualifiers="virtual const"> + <return type="String" /> + <argument index="0" name="shaped" type="RID" /> + <description> + Returns custom punctuation character list, used for word breaking. If set to empty string, server defaults are used. + </description> + </method> <method name="_shaped_text_get_descent" qualifiers="virtual const"> <return type="float" /> <argument index="0" name="shaped" type="RID" /> @@ -1176,6 +1228,14 @@ Override ranges should cover full source text without overlaps. BiDi algorithm will be used on each range separately. </description> </method> + <method name="_shaped_text_set_custom_punctuation" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="shaped" type="RID" /> + <argument index="1" name="punct" type="String" /> + <description> + Sets custom punctuation character list, used for word breaking. If set to empty string, server defaults are used. + </description> + </method> <method name="_shaped_text_set_direction" qualifiers="virtual"> <return type="void" /> <argument index="0" name="shaped" type="RID" /> diff --git a/doc/classes/TileMapPattern.xml b/doc/classes/TileMapPattern.xml index 4c46625423..ab7c95bb7b 100644 --- a/doc/classes/TileMapPattern.xml +++ b/doc/classes/TileMapPattern.xml @@ -59,7 +59,7 @@ <method name="remove_cell"> <return type="void" /> <argument index="0" name="coords" type="Vector2i" /> - <argument index="1" name="arg1" type="bool" /> + <argument index="1" name="update_size" type="bool" /> <description> Remove the cell at the given coordinates. </description> diff --git a/doc/classes/VisualShaderNodeParticleEmitter.xml b/doc/classes/VisualShaderNodeParticleEmitter.xml index 03ceb3adea..fa46b25fa9 100644 --- a/doc/classes/VisualShaderNodeParticleEmitter.xml +++ b/doc/classes/VisualShaderNodeParticleEmitter.xml @@ -1,9 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeParticleEmitter" inherits="VisualShaderNode" version="4.0"> <brief_description> + A base class for particle emitters. </brief_description> <description> </description> <tutorials> </tutorials> + <members> + <member name="mode_2d" type="bool" setter="set_mode_2d" getter="is_mode_2d" default="false"> + If [code]true[/code], the result of this emitter is projected to 2D space. By default it is [code]false[/code] and meant for use in 3D space. + </member> + </members> </class> diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index ad9e5f4897..fe8083f218 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -108,7 +108,9 @@ class ClassDef: self.constants = OrderedDict() # type: OrderedDict[str, ConstantDef] self.enums = OrderedDict() # type: OrderedDict[str, EnumDef] self.properties = OrderedDict() # type: OrderedDict[str, PropertyDef] + self.constructors = OrderedDict() # type: OrderedDict[str, List[MethodDef]] self.methods = OrderedDict() # type: OrderedDict[str, List[MethodDef]] + self.operators = OrderedDict() # type: OrderedDict[str, List[MethodDef]] self.signals = OrderedDict() # type: OrderedDict[str, SignalDef] self.theme_items = OrderedDict() # type: OrderedDict[str, ThemeItemDef] self.inherits = None # type: Optional[str] @@ -169,6 +171,34 @@ class State: ) class_def.properties[property_name] = property_def + constructors = class_root.find("constructors") + if constructors is not None: + for constructor in constructors: + assert constructor.tag == "constructor" + + method_name = constructor.attrib["name"] + qualifiers = constructor.get("qualifiers") + + return_element = constructor.find("return") + if return_element is not None: + return_type = TypeName.from_element(return_element) + + else: + return_type = TypeName("void") + + params = parse_arguments(constructor) + + desc_element = constructor.find("description") + method_desc = None + if desc_element is not None: + method_desc = desc_element.text + + method_def = MethodDef(method_name, return_type, params, method_desc, qualifiers) + if method_name not in class_def.constructors: + class_def.constructors[method_name] = [] + + class_def.constructors[method_name].append(method_def) + methods = class_root.find("methods") if methods is not None: for method in methods: @@ -197,6 +227,34 @@ class State: class_def.methods[method_name].append(method_def) + operators = class_root.find("operators") + if operators is not None: + for operator in operators: + assert operator.tag == "operator" + + method_name = operator.attrib["name"] + qualifiers = operator.get("qualifiers") + + return_element = operator.find("return") + if return_element is not None: + return_type = TypeName.from_element(return_element) + + else: + return_type = TypeName("void") + + params = parse_arguments(operator) + + desc_element = operator.find("description") + method_desc = None + if desc_element is not None: + method_desc = desc_element.text + + method_def = MethodDef(method_name, return_type, params, method_desc, qualifiers) + if method_name not in class_def.operators: + class_def.operators[method_name] = [] + + class_def.operators[method_name].append(method_def) + constants = class_root.find("constants") if constants is not None: for constant in constants: @@ -471,13 +529,29 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S ml.append((type_rst, ref, default)) format_table(f, ml, True) - # Methods overview + # Constructors, Methods, Operators overview + if len(class_def.constructors) > 0: + f.write(make_heading("Constructors", "-")) + ml = [] + for method_list in class_def.constructors.values(): + for m in method_list: + ml.append(make_method_signature(class_def, m, "constructor", state)) + format_table(f, ml) + if len(class_def.methods) > 0: f.write(make_heading("Methods", "-")) ml = [] for method_list in class_def.methods.values(): for m in method_list: - ml.append(make_method_signature(class_def, m, True, state)) + ml.append(make_method_signature(class_def, m, "method", state)) + format_table(f, ml) + + if len(class_def.operators) > 0: + f.write(make_heading("Operators", "-")) + ml = [] + for method_list in class_def.operators.values(): + for m in method_list: + ml.append(make_method_signature(class_def, m, "operator", state)) format_table(f, ml) # Theme properties @@ -501,7 +575,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S f.write("----\n\n") f.write(".. _class_{}_signal_{}:\n\n".format(class_name, signal.name)) - _, signature = make_method_signature(class_def, signal, False, state) + _, signature = make_method_signature(class_def, signal, "", state) f.write("- {}\n\n".format(signature)) if signal.description is not None and signal.description.strip() != "": @@ -582,7 +656,27 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S index += 1 - # Method descriptions + # Constructor, Method, Operator descriptions + if len(class_def.constructors) > 0: + f.write(make_heading("Constructor Descriptions", "-")) + index = 0 + + for method_list in class_def.constructors.values(): + for i, m in enumerate(method_list): + if index != 0: + f.write("----\n\n") + + if i == 0: + f.write(".. _class_{}_constructor_{}:\n\n".format(class_name, m.name)) + + ret_type, signature = make_method_signature(class_def, m, "", state) + f.write("- {} {}\n\n".format(ret_type, signature)) + + if m.description is not None and m.description.strip() != "": + f.write(rstize_text(m.description.strip(), state) + "\n\n") + + index += 1 + if len(class_def.methods) > 0: f.write(make_heading("Method Descriptions", "-")) index = 0 @@ -595,7 +689,31 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S if i == 0: f.write(".. _class_{}_method_{}:\n\n".format(class_name, m.name)) - ret_type, signature = make_method_signature(class_def, m, False, state) + ret_type, signature = make_method_signature(class_def, m, "", state) + f.write("- {} {}\n\n".format(ret_type, signature)) + + if m.description is not None and m.description.strip() != "": + f.write(rstize_text(m.description.strip(), state) + "\n\n") + + index += 1 + + if len(class_def.operators) > 0: + f.write(make_heading("Operator Descriptions", "-")) + index = 0 + + for method_list in class_def.operators.values(): + for i, m in enumerate(method_list): + if index != 0: + f.write("----\n\n") + + if i == 0: + f.write( + ".. _class_{}_operator_{}_{}:\n\n".format( + class_name, sanitize_operator_name(m.name, state), m.return_type.type_name + ) + ) + + ret_type, signature = make_method_signature(class_def, m, "", state) f.write("- {} {}\n\n".format(ret_type, signature)) if m.description is not None and m.description.strip() != "": @@ -810,10 +928,20 @@ def rstize_text(text, state): # type: (str, State) -> str ref_type = "" if class_param in state.classes: class_def = state.classes[class_param] + if cmd.startswith("constructor"): + if method_param not in class_def.constructors: + print_error( + "Unresolved constructor '{}', file: {}".format(param, state.current_class), state + ) + ref_type = "_constructor" if cmd.startswith("method"): if method_param not in class_def.methods: print_error("Unresolved method '{}', file: {}".format(param, state.current_class), state) ref_type = "_method" + if cmd.startswith("operator"): + if method_param not in class_def.operators: + print_error("Unresolved operator '{}', file: {}".format(param, state.current_class), state) + ref_type = "_operator" elif cmd.startswith("member"): if method_param not in class_def.properties: @@ -1046,24 +1174,26 @@ def make_enum(t, state): # type: (str, State) -> str def make_method_signature( - class_def, method_def, make_ref, state -): # type: (ClassDef, Union[MethodDef, SignalDef], bool, State) -> Tuple[str, str] + class_def, method_def, ref_type, state +): # type: (ClassDef, Union[MethodDef, SignalDef], str, State) -> Tuple[str, str] ret_type = " " - ref_type = "signal" if isinstance(method_def, MethodDef): ret_type = method_def.return_type.to_rst(state) - ref_type = "method" - - # FIXME: Need to add proper support for operator methods, but generating a unique - # and valid ref for them is not trivial. - if method_def.name.startswith("operator "): - make_ref = False out = "" - if make_ref: - out += ":ref:`{0}<class_{1}_{2}_{0}>` ".format(method_def.name, class_def.name, ref_type) + if ref_type != "": + if ref_type == "operator": + out += ":ref:`{0}<class_{1}_{2}_{3}_{4}>` ".format( + method_def.name, + class_def.name, + ref_type, + sanitize_operator_name(method_def.name, state), + method_def.return_type.type_name, + ) + else: + out += ":ref:`{0}<class_{1}_{2}_{0}>` ".format(method_def.name, class_def.name, ref_type) else: out += "**{}** ".format(method_def.name) @@ -1139,5 +1269,61 @@ def make_link(url, title): # type: (str, str) -> str return "`" + url + " <" + url + ">`__" +def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str + clear_name = dirty_name.replace("operator ", "") + + if clear_name == "!=": + clear_name = "neq" + elif clear_name == "==": + clear_name = "eq" + + elif clear_name == "<": + clear_name = "lt" + elif clear_name == "<=": + clear_name = "lte" + elif clear_name == ">": + clear_name = "gt" + elif clear_name == ">=": + clear_name = "gte" + + elif clear_name == "+": + clear_name = "sum" + elif clear_name == "-": + clear_name = "dif" + elif clear_name == "*": + clear_name = "mul" + elif clear_name == "/": + clear_name = "div" + elif clear_name == "%": + clear_name = "mod" + + elif clear_name == "unary+": + clear_name = "unplus" + elif clear_name == "unary-": + clear_name = "unminus" + + elif clear_name == "<<": + clear_name = "bwsl" + elif clear_name == ">>": + clear_name = "bwsr" + elif clear_name == "&": + clear_name = "bwand" + elif clear_name == "|": + clear_name = "bwor" + elif clear_name == "^": + clear_name = "bwxor" + elif clear_name == "~": + clear_name = "bwnot" + + elif clear_name == "[]": + clear_name = "idx" + + else: + clear_name = "xxx" + print_error("Unsupported operator type '{}', please add the missing rule.".format(dirty_name), state) + + return clear_name + + if __name__ == "__main__": main() diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index 64fc94ea91..1233f0f632 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -34,6 +34,7 @@ #include "core/config/project_settings.h" #include "core/os/os.h" +#include "core/version.h" #ifdef ALSAMIDI_ENABLED #include "drivers/alsa/asound-so_wrap.h" @@ -293,7 +294,17 @@ Error AudioDriverPulseAudio::init() { pa_ml = pa_mainloop_new(); ERR_FAIL_COND_V(pa_ml == nullptr, ERR_CANT_OPEN); - pa_ctx = pa_context_new(pa_mainloop_get_api(pa_ml), "Godot"); + String context_name; + if (Engine::get_singleton()->is_editor_hint()) { + context_name = VERSION_NAME " Editor"; + } else { + context_name = GLOBAL_GET("application/config/name"); + if (context_name.is_empty()) { + context_name = VERSION_NAME " Project"; + } + } + + pa_ctx = pa_context_new(pa_mainloop_get_api(pa_ml), context_name.utf8().ptr()); ERR_FAIL_COND_V(pa_ctx == nullptr, ERR_CANT_OPEN); pa_ready = 0; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 9f049a0e58..4ffa90777c 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -39,6 +39,7 @@ #include "editor_scale.h" #include "editor_settings.h" #include "multi_node_edit.h" +#include "scene/property_utils.h" #include "scene/resources/packed_scene.h" Size2 EditorProperty::get_minimum_size() const { @@ -305,6 +306,20 @@ void EditorProperty::_notification(int p_what) { revert_rect = Rect2(); } + if (!pin_hidden && pinned) { + Ref<Texture2D> pinned_icon = get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")); + int margin_w = get_theme_constant(SNAME("hseparator"), SNAME("Tree")) * 2; + int total_icon_w = margin_w + pinned_icon->get_width(); + int text_w = font->get_string_size(label, font_size, rtl ? HALIGN_RIGHT : HALIGN_LEFT, text_limit - total_icon_w).x; + int y = (size.height - pinned_icon->get_height()) / 2; + if (rtl) { + draw_texture(pinned_icon, Vector2(size.width - ofs - text_w - total_icon_w, y), color); + } else { + draw_texture(pinned_icon, Vector2(ofs + text_w + margin_w, y), color); + } + text_limit -= total_icon_w; + } + int v_ofs = (size.height - font->get_height(font_size)) / 2; if (rtl) { draw_string(font, Point2(size.width - ofs - text_limit, v_ofs + font->get_ascent(font_size)), label, HALIGN_RIGHT, text_limit, font_size, color); @@ -398,177 +413,12 @@ bool EditorProperty::is_read_only() const { return read_only; } -bool EditorPropertyRevert::may_node_be_in_instance(Node *p_node) { - Node *edited_scene = EditorNode::get_singleton()->get_edited_scene(); - - bool might_be = false; - Node *node = p_node; - - while (node) { - if (node == edited_scene) { - if (node->get_scene_inherited_state().is_valid()) { - might_be = true; - break; - } - might_be = false; - break; - } - if (node->get_scene_instance_state().is_valid()) { - might_be = true; - break; - } - node = node->get_owner(); - } - - return might_be; // or might not be -} - -bool EditorPropertyRevert::get_instantiated_node_original_property(Node *p_node, const StringName &p_prop, Variant &value, bool p_check_class_default) { - Node *node = p_node; - Node *orig = node; - - Node *edited_scene = EditorNode::get_singleton()->get_edited_scene(); - - bool found = false; - - while (node) { - Ref<SceneState> ss; - - if (node == edited_scene) { - ss = node->get_scene_inherited_state(); - - } else { - ss = node->get_scene_instance_state(); - } - - if (ss.is_valid()) { - NodePath np = node->get_path_to(orig); - int node_idx = ss->find_node_by_path(np); - if (node_idx >= 0) { - bool lfound = false; - Variant lvar; - lvar = ss->get_property_value(node_idx, p_prop, lfound); - if (lfound) { - found = true; - value = lvar; - } - } - } - if (node == edited_scene) { - //just in case - break; - } - node = node->get_owner(); - } - - if (p_check_class_default && !found && p_node) { - //if not found, try default class value - Variant attempt = ClassDB::class_get_default_property_value(p_node->get_class_name(), p_prop); - if (attempt.get_type() != Variant::NIL) { - found = true; - value = attempt; - } - } - - return found; -} - -bool EditorPropertyRevert::is_node_property_different(Node *p_node, const Variant &p_current, const Variant &p_orig) { - // this is a pretty difficult function, because a property may not be saved but may have - // the flag to not save if one or if zero - - //make sure there is an actual state - { - Node *node = p_node; - if (!node) { - return false; - } - - Node *edited_scene = EditorNode::get_singleton()->get_edited_scene(); - bool found_state = false; - - while (node) { - Ref<SceneState> ss; - - if (node == edited_scene) { - ss = node->get_scene_inherited_state(); - - } else { - ss = node->get_scene_instance_state(); - } - - if (ss.is_valid()) { - found_state = true; - break; - } - if (node == edited_scene) { - //just in case - break; - } - node = node->get_owner(); - } - - if (!found_state) { - return false; //pointless to check if we are not comparing against anything. - } - } - - return is_property_value_different(p_current, p_orig); -} - -bool EditorPropertyRevert::is_property_value_different(const Variant &p_a, const Variant &p_b) { - if (p_a.get_type() == Variant::FLOAT && p_b.get_type() == Variant::FLOAT) { - //this must be done because, as some scenes save as text, there might be a tiny difference in floats due to numerical error - return !Math::is_equal_approx((float)p_a, (float)p_b); - } else { - return p_a != p_b; - } -} - Variant EditorPropertyRevert::get_property_revert_value(Object *p_object, const StringName &p_property) { - // If the object implements property_can_revert, rely on that completely - // (i.e. don't then try to revert to default value - the property_get_revert implementation - // can do that if so desired) if (p_object->has_method("property_can_revert") && p_object->call("property_can_revert", p_property)) { return p_object->call("property_get_revert", p_property); } - Ref<Script> scr = p_object->get_script(); - Node *node = Object::cast_to<Node>(p_object); - if (node && EditorPropertyRevert::may_node_be_in_instance(node)) { - //if this node is an instance or inherits, but it has a script attached which is unrelated - //to the one set for the parent and also has a default value for the property, consider that - //has precedence over the value from the parent, because that is an explicit source of defaults - //closer in the tree to the current node - bool ignore_parent = false; - if (scr.is_valid()) { - Variant sorig; - if (EditorPropertyRevert::get_instantiated_node_original_property(node, "script", sorig) && !scr->inherits_script(sorig)) { - Variant dummy; - if (scr->get_property_default_value(p_property, dummy)) { - ignore_parent = true; - } - } - } - - if (!ignore_parent) { - //check for difference including instantiation - Variant vorig; - if (EditorPropertyRevert::get_instantiated_node_original_property(node, p_property, vorig, false)) { - return vorig; - } - } - } - - if (scr.is_valid()) { - Variant orig_value; - if (scr->get_property_default_value(p_property, orig_value)) { - return orig_value; - } - } - - //report default class value instead - return ClassDB::class_get_default_property_value(p_object->get_class_name(), p_property); + return PropertyUtils::get_property_default_value(p_object, p_property); } bool EditorPropertyRevert::can_property_revert(Object *p_object, const StringName &p_property) { @@ -577,18 +427,25 @@ bool EditorPropertyRevert::can_property_revert(Object *p_object, const StringNam return false; } Variant current_value = p_object->get(p_property); - return EditorPropertyRevert::is_property_value_different(current_value, revert_value); + return PropertyUtils::is_property_value_different(current_value, revert_value); } -void EditorProperty::update_reload_status() { +void EditorProperty::update_revert_and_pin_status() { if (property == StringName()) { return; //no property, so nothing to do } - bool has_reload = EditorPropertyRevert::can_property_revert(object, property); + bool new_pinned = false; + if (can_pin) { + Node *node = Object::cast_to<Node>(object); + CRASH_COND(!node); + new_pinned = node->is_property_pinned(property); + } + bool new_can_revert = EditorPropertyRevert::can_property_revert(object, property) && !is_read_only(); - if (has_reload != can_revert) { - can_revert = has_reload; + if (new_can_revert != can_revert || new_pinned != pinned) { + can_revert = new_can_revert; + pinned = new_pinned; update(); } } @@ -791,7 +648,7 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) { emit_signal(SNAME("property_checked"), property, checked); } } else if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { - _ensure_popup(); + _update_popup(); menu->set_position(get_screen_position() + get_local_mouse_position()); menu->set_size(Vector2(1, 1)); menu->popup(); @@ -914,6 +771,56 @@ float EditorProperty::get_name_split_ratio() const { void EditorProperty::set_object_and_property(Object *p_object, const StringName &p_property) { object = p_object; property = p_property; + _update_pin_flags(); +} + +static bool _is_value_potential_override(Node *p_node, const String &p_property) { + // Consider a value is potentially overriding another if either of the following is true: + // a) The node is foreign (inheriting or an instance), so the original value may come from another scene. + // b) The node belongs to the scene, but the original value comes from somewhere but the builtin class (i.e., a script). + Node *edited_scene = EditorNode::get_singleton()->get_edited_scene(); + Vector<SceneState::PackState> states_stack = PropertyUtils::get_node_states_stack(p_node, edited_scene); + if (states_stack.size()) { + return true; + } else { + bool is_class_default = false; + PropertyUtils::get_property_default_value(p_node, p_property, &states_stack, false, nullptr, &is_class_default); + return !is_class_default; + } +} + +void EditorProperty::_update_pin_flags() { + can_pin = false; + pin_hidden = true; + if (read_only) { + return; + } + if (Node *node = Object::cast_to<Node>(object)) { + // Avoid errors down the road by ignoring nodes which are not part of a scene + if (!node->get_owner()) { + bool is_scene_root = false; + for (int i = 0; i < EditorNode::get_singleton()->get_editor_data().get_edited_scene_count(); ++i) { + if (EditorNode::get_singleton()->get_editor_data().get_edited_scene_root(i) == node) { + is_scene_root = true; + break; + } + } + if (!is_scene_root) { + return; + } + } + if (!_is_value_potential_override(node, property)) { + return; + } + pin_hidden = false; + { + Set<StringName> storable_properties; + node->get_storable_properties(storable_properties); + if (storable_properties.has(node->get_property_store_alias(property))) { + can_pin = true; + } + } + } } Control *EditorProperty::make_custom_tooltip(const String &p_text) const { @@ -955,6 +862,10 @@ void EditorProperty::menu_option(int p_option) { case MENU_COPY_PROPERTY_PATH: { DisplayServer::get_singleton()->clipboard_set(property); } break; + case MENU_PIN_VALUE: { + emit_signal(SNAME("property_pinned"), property, !pinned); + update(); + } break; } } @@ -1003,12 +914,14 @@ void EditorProperty::_bind_methods() { ADD_SIGNAL(MethodInfo("property_keyed", PropertyInfo(Variant::STRING_NAME, "property"))); ADD_SIGNAL(MethodInfo("property_deleted", PropertyInfo(Variant::STRING_NAME, "property"))); ADD_SIGNAL(MethodInfo("property_keyed_with_value", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); - ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::STRING, "bool"))); + ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "checked"))); + ADD_SIGNAL(MethodInfo("property_pinned", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "pinned"))); ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "focusable_idx"))); GDVIRTUAL_BIND(_update_property) + ClassDB::bind_method(D_METHOD("_update_revert_and_pin_status"), &EditorProperty::update_revert_and_pin_status); } EditorProperty::EditorProperty() { @@ -1027,6 +940,9 @@ EditorProperty::EditorProperty() { revert_hover = false; check_hover = false; can_revert = false; + can_pin = false; + pin_hidden = false; + pinned = false; use_folding = false; property_usage = 0; selected = false; @@ -1038,17 +954,29 @@ EditorProperty::EditorProperty() { set_process_unhandled_key_input(true); } -void EditorProperty::_ensure_popup() { +void EditorProperty::_update_popup() { if (menu) { - return; + menu->clear(); + } else { + menu = memnew(PopupMenu); + add_child(menu); + menu->connect("id_pressed", callable_mp(this, &EditorProperty::menu_option)); } - menu = memnew(PopupMenu); menu->add_shortcut(ED_GET_SHORTCUT("property_editor/copy_property"), MENU_COPY_PROPERTY); menu->add_shortcut(ED_GET_SHORTCUT("property_editor/paste_property"), MENU_PASTE_PROPERTY); menu->add_shortcut(ED_GET_SHORTCUT("property_editor/copy_property_path"), MENU_COPY_PROPERTY_PATH); - menu->connect("id_pressed", callable_mp(this, &EditorProperty::menu_option)); menu->set_item_disabled(MENU_PASTE_PROPERTY, is_read_only()); - add_child(menu); + if (!pin_hidden) { + menu->add_separator(); + if (can_pin) { + menu->add_check_item(TTR("Pin value"), MENU_PIN_VALUE); + menu->set_item_checked(menu->get_item_index(MENU_PIN_VALUE), pinned); + menu->set_item_tooltip(menu->get_item_index(MENU_PIN_VALUE), TTR("Pinning a value forces it to be saved even if it's equal to the default.")); + } else { + menu->add_check_item(vformat(TTR("Pin value [Disabled because '%s' is editor-only]"), property), MENU_PIN_VALUE); + menu->set_item_disabled(menu->get_item_index(MENU_PIN_VALUE), true); + } + } } //////////////////////////////////////////////// @@ -2296,6 +2224,7 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), varray(), CONNECT_DEFERRED); ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value)); ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked)); + ep->connect("property_pinned", callable_mp(this, &EditorInspector::_property_pinned)); ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected)); ep->connect("multiple_properties_changed", callable_mp(this, &EditorInspector::_multiple_properties_changed)); ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), varray(), CONNECT_DEFERRED); @@ -2324,7 +2253,8 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit ep->set_read_only(read_only); ep->update_property(); - ep->update_reload_status(); + ep->_update_pin_flags(); + ep->update_revert_and_pin_status(); ep->set_deletable(deletable_properties); ep->update_cache(); } @@ -2877,6 +2807,7 @@ void EditorInspector::update_tree() { ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), varray(), CONNECT_DEFERRED); ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value)); ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked)); + ep->connect("property_pinned", callable_mp(this, &EditorInspector::_property_pinned)); ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected)); ep->connect("multiple_properties_changed", callable_mp(this, &EditorInspector::_multiple_properties_changed)); ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), varray(), CONNECT_DEFERRED); @@ -2887,7 +2818,8 @@ void EditorInspector::update_tree() { ep->set_tooltip(property_prefix + p.name); } ep->update_property(); - ep->update_reload_status(); + ep->_update_pin_flags(); + ep->update_revert_and_pin_status(); ep->update_cache(); if (current_selected && ep->property == current_selected) { @@ -2917,7 +2849,7 @@ void EditorInspector::update_property(const String &p_prop) { for (EditorProperty *E : editor_property_map[p_prop]) { E->update_property(); - E->update_reload_status(); + E->update_revert_and_pin_status(); E->update_cache(); } } @@ -3196,7 +3128,7 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo if (editor_property_map.has(p_name)) { for (EditorProperty *E : editor_property_map[p_name]) { - E->update_reload_status(); + E->update_revert_and_pin_status(); } } } @@ -3295,7 +3227,7 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) { if (editor_property_map.has(p_path)) { for (EditorProperty *E : editor_property_map[p_path]) { E->update_property(); - E->update_reload_status(); + E->update_revert_and_pin_status(); E->update_cache(); } } @@ -3305,6 +3237,35 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) { } } +void EditorInspector::_property_pinned(const String &p_path, bool p_pinned) { + if (!object) { + return; + } + + Node *node = Object::cast_to<Node>(object); + ERR_FAIL_COND(!node); + + if (undo_redo) { + undo_redo->create_action(vformat(p_pinned ? TTR("Pinned %s") : TTR("Unpinned %s"), p_path)); + undo_redo->add_do_method(node, "_set_property_pinned", p_path, p_pinned); + undo_redo->add_undo_method(node, "_set_property_pinned", p_path, !p_pinned); + if (editor_property_map.has(p_path)) { + for (List<EditorProperty *>::Element *E = editor_property_map[p_path].front(); E; E = E->next()) { + undo_redo->add_do_method(E->get(), "_update_revert_and_pin_status"); + undo_redo->add_undo_method(E->get(), "_update_revert_and_pin_status"); + } + } + undo_redo->commit_action(); + } else { + node->set_property_pinned(p_path, p_pinned); + if (editor_property_map.has(p_path)) { + for (List<EditorProperty *>::Element *E = editor_property_map[p_path].front(); E; E = E->next()) { + E->get()->update_revert_and_pin_status(); + } + } + } +} + void EditorInspector::_property_selected(const String &p_path, int p_focusable) { property_selected = p_path; property_focusable = p_focusable; @@ -3375,7 +3336,7 @@ void EditorInspector::_notification(int p_what) { for (EditorProperty *E : F.value) { if (!E->is_cache_valid()) { E->update_property(); - E->update_reload_status(); + E->update_revert_and_pin_status(); E->update_cache(); } } @@ -3397,7 +3358,7 @@ void EditorInspector::_notification(int p_what) { if (editor_property_map.has(prop)) { for (EditorProperty *E : editor_property_map[prop]) { E->update_property(); - E->update_reload_status(); + E->update_revert_and_pin_status(); E->update_cache(); } } @@ -3490,7 +3451,7 @@ void EditorInspector::_update_script_class_properties(const Object &p_object, Li String path = s->get_path(); String name = EditorNode::get_editor_data().script_class_get_name(path); if (name.is_empty()) { - if (!path.is_empty() && path.find("::") == -1) { + if (!s->is_built_in()) { name = path.get_file(); } else { name = TTR("Built-in script"); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 124ea31302..aabb66eeb4 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -43,7 +43,6 @@ class UndoRedo; class EditorPropertyRevert { public: - static bool may_node_be_in_instance(Node *p_node); static bool get_instantiated_node_original_property(Node *p_node, const StringName &p_prop, Variant &value, bool p_check_class_default = true); static bool is_node_property_different(Node *p_node, const Variant &p_current, const Variant &p_orig); static bool is_property_value_different(const Variant &p_a, const Variant &p_b); @@ -60,6 +59,7 @@ public: MENU_COPY_PROPERTY, MENU_PASTE_PROPERTY, MENU_COPY_PROPERTY_PATH, + MENU_PIN_VALUE, }; private: @@ -91,11 +91,14 @@ private: bool delete_hover = false; bool can_revert; + bool can_pin; + bool pin_hidden; + bool pinned; bool use_folding; bool draw_top_bg; - void _ensure_popup(); + void _update_popup(); void _focusable_focused(int p_index); bool selectable; @@ -114,6 +117,8 @@ private: Map<StringName, Variant> cache; GDVIRTUAL0(_update_property) + void _update_pin_flags(); + protected: void _notification(int p_what); static void _bind_methods(); @@ -138,7 +143,7 @@ public: StringName get_edited_property(); virtual void update_property(); - void update_reload_status(); + void update_revert_and_pin_status(); virtual bool use_keying_next() const; @@ -459,8 +464,8 @@ class EditorInspector : public ScrollContainer { void _property_keyed(const String &p_path, bool p_advance); void _property_keyed_with_value(const String &p_path, const Variant &p_value, bool p_advance); void _property_deleted(const String &p_path); - void _property_checked(const String &p_path, bool p_checked); + void _property_pinned(const String &p_path, bool p_pinned); void _resource_selected(const String &p_path, RES p_resource); void _property_selected(const String &p_path, int p_focusable); diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 251e1c2385..5f2f8e91c9 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -45,9 +45,9 @@ void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_f String err_str; if (p_errorexp && p_errorexp[0]) { - err_str = p_errorexp; + err_str = String::utf8(p_errorexp); } else { - err_str = String(p_file) + ":" + itos(p_line) + " - " + String(p_error); + err_str = String::utf8(p_file) + ":" + itos(p_line) + " - " + String::utf8(p_error); } if (p_editor_notify) { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index bb4a05efba..4af7763caa 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -174,6 +174,7 @@ #include "editor/plugins/sprite_frames_editor_plugin.h" #include "editor/plugins/style_box_editor_plugin.h" #include "editor/plugins/sub_viewport_preview_editor_plugin.h" +#include "editor/plugins/text_control_editor_plugin.h" #include "editor/plugins/text_editor.h" #include "editor/plugins/texture_3d_editor_plugin.h" #include "editor/plugins/texture_editor_plugin.h" @@ -1791,7 +1792,7 @@ void EditorNode::_save_all_scenes() { } else { _save_scene_with_preview(scene->get_scene_file_path()); } - } else { + } else if (scene->get_scene_file_path() != "") { all_saved = false; } } @@ -2256,7 +2257,8 @@ void EditorNode::_edit_current() { if (main_plugin) { // special case if use of external editor is true - if (main_plugin->get_name() == "Script" && current_obj->get_class_name() != StringName("VisualScript") && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) { + Resource *res = Object::cast_to<Resource>(current_obj); + if (main_plugin->get_name() == "Script" && current_obj->get_class_name() != StringName("VisualScript") && res && !res->is_built_in() && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) { if (!changing_scene) { main_plugin->edit(current_obj); } @@ -3356,7 +3358,7 @@ void EditorNode::set_edited_scene(Node *p_scene) { if (p_scene) { if (p_scene->get_parent() != scene_root) { - scene_root->add_child(p_scene); + scene_root->add_child(p_scene, true); } } } @@ -3488,7 +3490,7 @@ void EditorNode::set_current_scene(int p_idx) { if (new_scene) { if (new_scene->get_parent() != scene_root) { - scene_root->add_child(new_scene); + scene_root->add_child(new_scene, true); } } @@ -3622,7 +3624,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b sdata->set_path(lpath, true); // take over path } - Node *new_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_MAIN); + Node *new_scene = sdata->instantiate(p_set_inherited ? PackedScene::GEN_EDIT_STATE_MAIN_INHERITED : PackedScene::GEN_EDIT_STATE_MAIN); if (!new_scene) { sdata.unref(); @@ -7009,6 +7011,7 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(GPUParticlesCollisionSDFEditorPlugin(this))); add_editor_plugin(memnew(InputEventEditorPlugin(this))); add_editor_plugin(memnew(SubViewportPreviewEditorPlugin(this))); + add_editor_plugin(memnew(TextControlEditorPlugin(this))); for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) { add_editor_plugin(EditorPlugins::create(i, this)); @@ -7139,8 +7142,6 @@ EditorNode::EditorNode() { _build_icon_type_cache(); - Node::set_human_readable_collision_renaming(true); - pick_main_scene = memnew(ConfirmationDialog); gui_base->add_child(pick_main_scene); pick_main_scene->get_ok_button()->set_text(TTR("Select")); diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index f05c401f1d..4775ca418b 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -84,7 +84,7 @@ void EditorResourcePicker::_update_resource_preview(const String &p_path, const if (p_preview.is_valid()) { preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox(SNAME("normal"))->get_default_margin(SIDE_LEFT) + get_theme_constant(SNAME("hseparation"), SNAME("Button"))); - if (type == "GradientTexture") { + if (type == "GradientTexture1D") { preview_rect->set_stretch_mode(TextureRect::STRETCH_SCALE); assign_button->set_custom_minimum_size(Size2(1, 1)); } else { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 1da9213b89..739fc0e4f5 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -293,8 +293,8 @@ void EditorSettings::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(pi); } - p_list->push_back(PropertyInfo(Variant::ARRAY, "shortcuts", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); //do not edit - p_list->push_back(PropertyInfo(Variant::ARRAY, "builtin_action_overrides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "shortcuts", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); //do not edit + p_list->push_back(PropertyInfo(Variant::ARRAY, "builtin_action_overrides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } void EditorSettings::_add_property_info_bind(const Dictionary &p_info) { diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 06c39a957c..8e8437f1b2 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1207,7 +1207,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0)); theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * EDSCALE); theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * EDSCALE); - theme->set_constant("shadow_as_outline", "RichTextLabel", 0 * EDSCALE); + theme->set_constant("shadow_outline_size", "RichTextLabel", 1 * EDSCALE); theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox()); theme->set_stylebox("normal", "RichTextLabel", style_tree_bg); @@ -1223,7 +1223,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_shadow_color", "Label", Color(0, 0, 0, 0)); theme->set_constant("shadow_offset_x", "Label", 1 * EDSCALE); theme->set_constant("shadow_offset_y", "Label", 1 * EDSCALE); - theme->set_constant("shadow_as_outline", "Label", 0 * EDSCALE); + theme->set_constant("shadow_outline_size", "Label", 1 * EDSCALE); theme->set_constant("line_spacing", "Label", 3 * EDSCALE); // LinkButton diff --git a/editor/editor_toaster.cpp b/editor/editor_toaster.cpp index 22da12b59b..0d9a546b8e 100644 --- a/editor/editor_toaster.cpp +++ b/editor/editor_toaster.cpp @@ -158,11 +158,11 @@ void EditorToaster::_error_handler(void *p_self, const char *p_func, const char if (p_editor_notify || (show_all_setting == 0 && in_dev) || show_all_setting == 1) { String err_str; if (p_errorexp && p_errorexp[0]) { - err_str = p_errorexp; + err_str = String::utf8(p_errorexp); } else { - err_str = String(p_error); + err_str = String::utf8(p_error); } - String tooltip_str = String(p_file) + ":" + itos(p_line); + String tooltip_str = String::utf8(p_file) + ":" + itos(p_line); if (!p_editor_notify) { if (p_type == ERR_HANDLER_WARNING) { diff --git a/editor/icons/GradientTexture.svg b/editor/icons/GradientTexture1D.svg index fa03e69805..fa03e69805 100644 --- a/editor/icons/GradientTexture.svg +++ b/editor/icons/GradientTexture1D.svg diff --git a/editor/icons/InterpCubic.svg b/editor/icons/InterpCubic.svg index ad2ed51ee1..b542986ea6 100644 --- a/editor/icons/InterpCubic.svg +++ b/editor/icons/InterpCubic.svg @@ -1 +1 @@ -<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1050.4c3 0 3-4 6-4s3 4 6 4" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-width="2" transform="translate(0 -1044.4)"/></svg> +<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1050.4c5 0 3-4 6-4s1 4 6 4" fill="none" stroke="#5fb2ff" stroke-linecap="round" stroke-width="2" transform="translate(0 -1044.4)"/></svg> diff --git a/editor/icons/InterpLinear.svg b/editor/icons/InterpLinear.svg index 241a82fc8f..966ddfdc31 100644 --- a/editor/icons/InterpLinear.svg +++ b/editor/icons/InterpLinear.svg @@ -1 +1 @@ -<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1050.4 6-4 6 4" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1044.4)"/></svg> +<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1050.4 6-4 6 4" fill="none" stroke="#ffca5f" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1044.4)"/></svg> diff --git a/editor/icons/InterpWrapClamp.svg b/editor/icons/InterpWrapClamp.svg index 6ba8e78500..b589542019 100644 --- a/editor/icons/InterpWrapClamp.svg +++ b/editor/icons/InterpWrapClamp.svg @@ -1 +1 @@ -<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v6h2v-2.9863-3.0137zm2 3.0137a1.0001 1.0001 0 0 0 .29297.69336l2 2a1 1 0 0 0 1.4141 0 1 1 0 0 0 0-1.4141l-.29297-.29297h3.1719l-.29297.29297a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 .29297-.72266 1.0001 1.0001 0 0 0 -.29297-.69141l-2-2a1 1 0 0 0 -.7207-.29102 1 1 0 0 0 -.69336.29102 1 1 0 0 0 0 1.4141l.29297.29297h-3.1719l.29297-.29297a1 1 0 0 0 0-1.4141 1 1 0 0 0 -.7207-.29102 1 1 0 0 0 -.69336.29102l-2 2a1.0001 1.0001 0 0 0 -.29297.7207zm10-.029297v3.0156h2v-6h-2z" fill="#e0e0e0"/></svg> +<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v6h2v-2.9863-3.0137zm2 3.0137a1.0001 1.0001 0 0 0 .29297.69336l2 2a1 1 0 0 0 1.4141 0 1 1 0 0 0 0-1.4141l-.29297-.29297h3.1719l-.29297.29297a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 .29297-.72266 1.0001 1.0001 0 0 0 -.29297-.69141l-2-2a1 1 0 0 0 -.7207-.29102 1 1 0 0 0 -.69336.29102 1 1 0 0 0 0 1.4141l.29297.29297h-3.1719l.29297-.29297a1 1 0 0 0 0-1.4141 1 1 0 0 0 -.7207-.29102 1 1 0 0 0 -.69336.29102l-2 2a1.0001 1.0001 0 0 0 -.29297.7207zm10-.029297v3.0156h2v-6h-2z" fill="#fc7f7f"/></svg> diff --git a/editor/icons/InterpWrapLoop.svg b/editor/icons/InterpWrapLoop.svg index 57670f97ce..4faf7805f8 100644 --- a/editor/icons/InterpWrapLoop.svg +++ b/editor/icons/InterpWrapLoop.svg @@ -1 +1 @@ -<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 0-3 2 3 2v-1h3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3h-3zm-5 1a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h3v1l3-2-3-2v1h-3a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#e0e0e0"/></svg> +<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 0-3 2 3 2v-1h3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3h-3zm-5 1a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h3v1l3-2-3-2v1h-3a1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#c38ef1"/></svg> diff --git a/editor/icons/ReverseGradient.svg b/editor/icons/ReverseGradient.svg new file mode 100644 index 0000000000..12f80d12dd --- /dev/null +++ b/editor/icons/ReverseGradient.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="b" x1=".26458" x2="3.9688" y1=".79375" y2=".79375" gradientTransform="scale(3.7795)" gradientUnits="userSpaceOnUse"><stop stop-color="#ccc" offset="0"/><stop stop-color="#ccc" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="a" x1=".26458" x2="3.9688" y1="3.4396" y2="3.4396" gradientTransform="matrix(3.7795 0 0 3.7795 -16 -1.1865e-7)" gradientUnits="userSpaceOnUse"><stop stop-color="#ccc" offset="0"/><stop stop-color="#ccc" stop-opacity="0" offset="1"/></linearGradient></defs><g><rect x="1" y="1" width="14" height="4" ry="1" fill="url(#b)"/><rect transform="scale(-1,1)" x="-15" y="11" width="14" height="4" ry="1" fill="url(#a)" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.7795"/><path d="m6 6 2 4 2-4z" fill="#ccc"/></g></svg> diff --git a/editor/icons/TrackCapture.svg b/editor/icons/TrackCapture.svg index aaa4a20e4a..b3d5f09eff 100644 --- a/editor/icons/TrackCapture.svg +++ b/editor/icons/TrackCapture.svg @@ -1 +1 @@ -<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m2.1665128.99764963c-.422625 0-.763672.34104737-.763672.76367187v4.5742187c0 .4226242.341047.7617192.763672.7617192h4.472656c.422625 0 .763672-.339095.763672-.7617192v-.9882812h-3.300781c-.1662 0-.298828-.3390943-.298828-.7617188v-1.2246094c0-.4226244.132628-.7636718.298828-.7636718h3.300781v-.8359375c0-.4226245-.341047-.76367187-.763672-.76367187z"/><path d="m9.1827441 4.7953408c.5166221-1.0415625 1.0955249-2.2117429 1.2864509-2.600401l.347137-.7066511.679654.00665.679654.00665.956945 2.3125c.526319 1.271875 1.007254 2.4334375 1.068744 2.5812497l.1118.26875h-.597215-.597214l-.332849-.6437497-.332849-.64375h-1.133826-1.133825l-.3786749.6561133-.3786747.6561134-.5922856.000137-.592285.000136zm3.1779349-.369483c.0042-.00346-.233487-.4884588-.528245-1.0777779l-.535922-1.0714891-.03691.0875c-.0203.048125-.183516.425-.362699.8375-.179182.4125-.355738.85125-.392346.975-.03661.12375-.07127.2390723-.07703.2562715-.0083.024853.188215.027989.957503.015278.532385-.0088.971429-.018823.975651-.022283z" stroke="#e0e0e0" stroke-width=".803"/></g></svg> +<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e1da5b"><path d="m2.1665128.99764963c-.422625 0-.763672.34104737-.763672.76367187v4.5742187c0 .4226242.341047.7617192.763672.7617192h4.472656c.422625 0 .763672-.339095.763672-.7617192v-.9882812h-3.300781c-.1662 0-.298828-.3390943-.298828-.7617188v-1.2246094c0-.4226244.132628-.7636718.298828-.7636718h3.300781v-.8359375c0-.4226245-.341047-.76367187-.763672-.76367187z"/><path d="m9.1827441 4.7953408c.5166221-1.0415625 1.0955249-2.2117429 1.2864509-2.600401l.347137-.7066511.679654.00665.679654.00665.956945 2.3125c.526319 1.271875 1.007254 2.4334375 1.068744 2.5812497l.1118.26875h-.597215-.597214l-.332849-.6437497-.332849-.64375h-1.133826-1.133825l-.3786749.6561133-.3786747.6561134-.5922856.000137-.592285.000136zm3.1779349-.369483c.0042-.00346-.233487-.4884588-.528245-1.0777779l-.535922-1.0714891-.03691.0875c-.0203.048125-.183516.425-.362699.8375-.179182.4125-.355738.85125-.392346.975-.03661.12375-.07127.2390723-.07703.2562715-.0083.024853.188215.027989.957503.015278.532385-.0088.971429-.018823.975651-.022283z" stroke="#e1da5b" stroke-width=".803"/></g></svg> diff --git a/editor/icons/TrackDiscrete.svg b/editor/icons/TrackDiscrete.svg index d1df4b1667..6498742233 100644 --- a/editor/icons/TrackDiscrete.svg +++ b/editor/icons/TrackDiscrete.svg @@ -1 +1 @@ -<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-6 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-6 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1z" fill="#e0e0e0"/></svg> +<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-6 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-6 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1z" fill="#b9ec41"/></svg> diff --git a/editor/icons/TrackTrigger.svg b/editor/icons/TrackTrigger.svg index 6e46a74121..c403fba59a 100644 --- a/editor/icons/TrackTrigger.svg +++ b/editor/icons/TrackTrigger.svg @@ -1 +1 @@ -<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h2v4h2v-4h2v-2zm13 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-3 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-3 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1z" fill="#e0e0e0"/></svg> +<svg height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h2v4h2v-4h2v-2zm13 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-3 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-3 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1z" fill="#f68f45"/></svg> diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index f9aa550e7d..076c0cc62b 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -314,7 +314,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Node3D *p_parent) { xf = collada.fix_transform(xf) * p_node->post_transform; node->set_transform(xf); - p_parent->add_child(node); + p_parent->add_child(node, true); node->set_owner(scene); if (p_node->empty_draw_type != "") { @@ -1804,7 +1804,7 @@ Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint3 ap->add_animation(name, state.animations[i]); } - state.scene->add_child(ap); + state.scene->add_child(ap, true); ap->set_owner(state.scene); } diff --git a/editor/import/resource_importer_bmfont.cpp b/editor/import/resource_importer_bmfont.cpp index 2e7ef1402b..a64be54f2d 100644 --- a/editor/import/resource_importer_bmfont.cpp +++ b/editor/import/resource_importer_bmfont.cpp @@ -359,6 +359,8 @@ Error ResourceImporterBMFont::import(const String &p_source_file, const String & int height = 0; int ascent = 0; int outline = 0; + uint32_t st_flags = 0; + String font_name; bool packed = false; uint8_t ch[4] = { 0, 0, 0, 0 }; // RGBA @@ -382,13 +384,23 @@ Error ResourceImporterBMFont::import(const String &p_source_file, const String & base_size = f->get_16(); uint8_t flags = f->get_8(); ERR_FAIL_COND_V_MSG(flags & 0x02, ERR_CANT_CREATE, TTR("Non-unicode version of BMFont is not supported.")); + if (flags & (1 << 3)) { + st_flags |= TextServer::FONT_BOLD; + } + if (flags & (1 << 2)) { + st_flags |= TextServer::FONT_ITALIC; + } f->get_8(); // non-unicode charset, skip f->get_16(); // stretch_h, skip f->get_8(); // aa, skip f->get_32(); // padding, skip f->get_16(); // spacing, skip outline = f->get_8(); - // font name, skip + // font name + PackedByteArray name_data; + name_data.resize(block_size - 14); + f->get_buffer(name_data.ptrw(), block_size - 14); + font_name = String::utf8((const char *)name_data.ptr(), block_size - 14); font->set_fixed_size(base_size); } break; case 2: /* common */ { @@ -601,6 +613,19 @@ Error ResourceImporterBMFont::import(const String &p_source_file, const String & if (keys.has("outline")) { outline = keys["outline"].to_int(); } + if (keys.has("bold")) { + if (keys["bold"].to_int()) { + st_flags |= TextServer::FONT_BOLD; + } + } + if (keys.has("italic")) { + if (keys["italic"].to_int()) { + st_flags |= TextServer::FONT_ITALIC; + } + } + if (keys.has("face")) { + font_name = keys["face"]; + } ERR_FAIL_COND_V_MSG((!keys.has("unicode") || keys["unicode"].to_int() != 1), ERR_CANT_CREATE, TTR("Non-unicode version of BMFont is not supported.")); } else if (type == "common") { if (keys.has("lineHeight")) { @@ -778,6 +803,8 @@ Error ResourceImporterBMFont::import(const String &p_source_file, const String & } } + font->set_font_name(font_name); + font->set_font_style(st_flags); font->set_ascent(0, base_size, ascent); font->set_descent(0, base_size, height - ascent); diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index 4f75faedcb..01af75c338 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -448,7 +448,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in ImporterMeshInstance3D *mi = memnew(ImporterMeshInstance3D); mi->set_mesh(mesh); mi->set_name(m->get_name()); - scene->add_child(mi); + scene->add_child(mi, true); mi->set_owner(scene); } diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 7d3b945b04..5efb08b95d 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -502,7 +502,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I sphereShape->set_radius(1); colshape->set_shape(sphereShape); } - sb->add_child(colshape); + sb->add_child(colshape, true); colshape->set_owner(sb->get_owner()); } @@ -528,7 +528,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I rigid_body->set_transform(mi->get_transform()); p_node = rigid_body; mi->set_transform(Transform3D()); - rigid_body->add_child(mi); + rigid_body->add_child(mi, true); mi->set_owner(rigid_body->get_owner()); _add_shapes(rigid_body, shapes); @@ -566,7 +566,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I if (shapes.size()) { StaticBody3D *col = memnew(StaticBody3D); - mi->add_child(col); + mi->add_child(col, true); col->set_owner(mi->get_owner()); _add_shapes(col, shapes); @@ -614,7 +614,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I if (shapes.size()) { StaticBody3D *col = memnew(StaticBody3D); - p_node->add_child(col); + p_node->add_child(col, true); col->set_owner(p_node->get_owner()); _add_shapes(col, shapes); @@ -749,7 +749,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< switch (mesh_physics_mode) { case MESH_PHYSICS_MESH_AND_STATIC_COLLIDER: { StaticBody3D *col = memnew(StaticBody3D); - p_node->add_child(col); + p_node->add_child(col, true); col->set_owner(p_node->get_owner()); col->set_transform(get_collision_shapes_transform(node_settings)); base = col; @@ -761,7 +761,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< rigid_body->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); p_node = rigid_body; mi->set_transform(Transform3D()); - rigid_body->add_child(mi); + rigid_body->add_child(mi, true); mi->set_owner(rigid_body->get_owner()); base = rigid_body; } break; @@ -790,7 +790,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< for (const Ref<Shape3D> &E : shapes) { CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E); - base->add_child(cshape); + base->add_child(cshape, true); cshape->set_owner(base->get_owner()); idx++; @@ -823,7 +823,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< memdelete(p_node); p_node = nmi; } else { - mi->add_child(nmi); + mi->add_child(nmi, true); nmi->set_owner(mi->get_owner()); } } @@ -1431,7 +1431,7 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15)); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "import_script/path", PROPERTY_HINT_FILE, script_ext_hint), "")); - r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "_subresources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), Dictionary())); + r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "_subresources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), Dictionary())); for (int i = 0; i < post_importer_plugins.size(); i++) { post_importer_plugins.write[i]->get_import_options(r_options); @@ -1680,7 +1680,7 @@ void ResourceImporterScene::_add_shapes(Node *p_node, const Vector<Ref<Shape3D>> for (const Ref<Shape3D> &E : p_shapes) { CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E); - p_node->add_child(cshape); + p_node->add_child(cshape, true); cshape->set_owner(p_node->get_owner()); } diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 95a96f9e26..9b9320ad6d 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -327,7 +327,7 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { MeshInstance3D *collider_view = memnew(MeshInstance3D); collider_view->set_name("collider_view"); collider_view->set_visible(false); - mesh_node->add_child(collider_view); + mesh_node->add_child(collider_view, true); collider_view->set_owner(mesh_node); Transform3D accum_xform; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 0e1bdf0155..061483decf 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -2264,9 +2264,9 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } } - if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_ctrl_pressed()) { - add_node_menu->set_position(get_global_transform().xform(get_local_mouse_position())); + if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT) { add_node_menu->set_size(Vector2(1, 1)); + add_node_menu->set_position(get_screen_position() + b->get_position()); add_node_menu->popup(); node_create_position = transform.affine_inverse().xform((get_local_mouse_position())); return true; @@ -5836,7 +5836,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & Ref<Texture2D> texture = Ref<Texture2D>(Object::cast_to<Texture2D>(ResourceCache::get(path))); if (parent) { - editor_data->get_undo_redo().add_do_method(parent, "add_child", child); + editor_data->get_undo_redo().add_do_method(parent, "add_child", child, true); editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene()); editor_data->get_undo_redo().add_do_reference(child); editor_data->get_undo_redo().add_undo_method(parent, "remove_child", child); @@ -6192,14 +6192,14 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte label = memnew(Label); label->add_theme_color_override("font_shadow_color", Color(0, 0, 0, 1)); - label->add_theme_constant_override("shadow_as_outline", 1 * EDSCALE); + label->add_theme_constant_override("shadow_outline_size", 1 * EDSCALE); label->hide(); canvas_item_editor->get_controls_container()->add_child(label); label_desc = memnew(Label); label_desc->add_theme_color_override("font_color", Color(0.6f, 0.6f, 0.6f, 1)); label_desc->add_theme_color_override("font_shadow_color", Color(0.2f, 0.2f, 0.2f, 1)); - label_desc->add_theme_constant_override("shadow_as_outline", 1 * EDSCALE); + label_desc->add_theme_constant_override("shadow_outline_size", 1 * EDSCALE); label_desc->add_theme_constant_override("line_spacing", 0); label_desc->hide(); canvas_item_editor->get_controls_container()->add_child(label_desc); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 4cb2c0a76b..9702c7e734 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -297,12 +297,14 @@ EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() { ////////////////////////////////////////////////////////////////// -void EditorMaterialPreviewPlugin::_preview_done(const Variant &p_udata) { - preview_done.set(); +void EditorMaterialPreviewPlugin::_generate_frame_started() { + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture + + RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_preview_done)); } -void EditorMaterialPreviewPlugin::_bind_methods() { - ClassDB::bind_method("_preview_done", &EditorMaterialPreviewPlugin::_preview_done); +void EditorMaterialPreviewPlugin::_preview_done() { + preview_done.post(); } bool EditorMaterialPreviewPlugin::handles(const String &p_type) const { @@ -320,14 +322,9 @@ Ref<Texture2D> EditorMaterialPreviewPlugin::generate(const RES &p_from, const Si if (material->get_shader_mode() == Shader::MODE_SPATIAL) { RS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid()); - RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_generate_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT); - preview_done.clear(); - RS::get_singleton()->request_frame_drawn_callback(const_cast<EditorMaterialPreviewPlugin *>(this), "_preview_done", Variant()); - - while (!preview_done.is_set()) { - OS::get_singleton()->delay_usec(10); - } + preview_done.wait(); Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture); RS::get_singleton()->mesh_surface_set_material(sphere, 0, RID()); @@ -699,12 +696,14 @@ EditorAudioStreamPreviewPlugin::EditorAudioStreamPreviewPlugin() { /////////////////////////////////////////////////////////////////////////// -void EditorMeshPreviewPlugin::_preview_done(const Variant &p_udata) { - preview_done.set(); +void EditorMeshPreviewPlugin::_generate_frame_started() { + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture + + RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_preview_done)); } -void EditorMeshPreviewPlugin::_bind_methods() { - ClassDB::bind_method("_preview_done", &EditorMeshPreviewPlugin::_preview_done); +void EditorMeshPreviewPlugin::_preview_done() { + preview_done.post(); } bool EditorMeshPreviewPlugin::handles(const String &p_type) const { @@ -735,14 +734,9 @@ Ref<Texture2D> EditorMeshPreviewPlugin::generate(const RES &p_from, const Size2 xform.origin.z -= rot_aabb.size.z * 2; RS::get_singleton()->instance_set_transform(mesh_instance, xform); - RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_generate_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT); - preview_done.clear(); - RS::get_singleton()->request_frame_drawn_callback(const_cast<EditorMeshPreviewPlugin *>(this), "_preview_done", Variant()); - - while (!preview_done.is_set()) { - OS::get_singleton()->delay_usec(10); - } + preview_done.wait(); Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture); ERR_FAIL_COND_V(img.is_null(), Ref<ImageTexture>()); @@ -814,12 +808,14 @@ EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() { /////////////////////////////////////////////////////////////////////////// -void EditorFontPreviewPlugin::_preview_done(const Variant &p_udata) { - preview_done.set(); +void EditorFontPreviewPlugin::_generate_frame_started() { + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture + + RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_preview_done)); } -void EditorFontPreviewPlugin::_bind_methods() { - ClassDB::bind_method("_preview_done", &EditorFontPreviewPlugin::_preview_done); +void EditorFontPreviewPlugin::_preview_done() { + preview_done.post(); } bool EditorFontPreviewPlugin::handles(const String &p_type) const { @@ -857,13 +853,9 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path, font->draw_string(canvas_item, pos, sample, HALIGN_LEFT, -1.f, 50, Color(1, 1, 1)); - preview_done.clear(); - RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture - RS::get_singleton()->request_frame_drawn_callback(const_cast<EditorFontPreviewPlugin *>(this), "_preview_done", Variant()); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_generate_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT); - while (!preview_done.is_set()) { - OS::get_singleton()->delay_usec(10); - } + preview_done.wait(); RS::get_singleton()->canvas_item_clear(canvas_item); diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index 091feae5fb..bf52f5771d 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/editor/plugins/editor_preview_plugins.h @@ -92,12 +92,10 @@ class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator { RID light2; RID light_instance2; RID camera; - mutable SafeFlag preview_done; + Semaphore preview_done; - void _preview_done(const Variant &p_udata); - -protected: - static void _bind_methods(); + void _generate_frame_started(); + void _preview_done(); public: virtual bool handles(const String &p_type) const override; @@ -136,12 +134,10 @@ class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator { RID light2; RID light_instance2; RID camera; - mutable SafeFlag preview_done; - - void _preview_done(const Variant &p_udata); + Semaphore preview_done; -protected: - static void _bind_methods(); + void _generate_frame_started(); + void _preview_done(); public: virtual bool handles(const String &p_type) const override; @@ -158,12 +154,10 @@ class EditorFontPreviewPlugin : public EditorResourcePreviewGenerator { RID viewport_texture; RID canvas; RID canvas_item; - mutable SafeFlag preview_done; + Semaphore preview_done; - void _preview_done(const Variant &p_udata); - -protected: - static void _bind_methods(); + void _generate_frame_started(); + void _preview_done(); public: virtual bool handles(const String &p_type) const override; @@ -177,12 +171,10 @@ public: class EditorTileMapPatternPreviewPlugin : public EditorResourcePreviewGenerator { GDCLASS(EditorTileMapPatternPreviewPlugin, EditorResourcePreviewGenerator); - mutable SafeFlag preview_done; - - void _preview_done(const Variant &p_udata); + Semaphore preview_done; -protected: - static void _bind_methods(); + void _generate_frame_started(); + void _preview_done(); public: virtual bool handles(const String &p_type) const override; diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp index 355bdb69d8..da050abc02 100644 --- a/editor/plugins/gradient_editor_plugin.cpp +++ b/editor/plugins/gradient_editor_plugin.cpp @@ -46,6 +46,8 @@ void GradientEditor::_gradient_changed() { editing = true; Vector<Gradient::Point> points = gradient->get_points(); set_points(points); + set_interpolation_mode(gradient->get_interpolation_mode()); + update(); editing = false; } @@ -55,8 +57,10 @@ void GradientEditor::_ramp_changed() { undo_redo->create_action(TTR("Gradient Edited")); undo_redo->add_do_method(gradient.ptr(), "set_offsets", get_offsets()); undo_redo->add_do_method(gradient.ptr(), "set_colors", get_colors()); + undo_redo->add_do_method(gradient.ptr(), "set_interpolation_mode", get_interpolation_mode()); undo_redo->add_undo_method(gradient.ptr(), "set_offsets", gradient->get_offsets()); undo_redo->add_undo_method(gradient.ptr(), "set_colors", gradient->get_colors()); + undo_redo->add_undo_method(gradient.ptr(), "set_interpolation_mode", gradient->get_interpolation_mode()); undo_redo->commit_action(); editing = false; } @@ -69,6 +73,14 @@ void GradientEditor::set_gradient(const Ref<Gradient> &p_gradient) { connect("ramp_changed", callable_mp(this, &GradientEditor::_ramp_changed)); gradient->connect("changed", callable_mp(this, &GradientEditor::_gradient_changed)); set_points(gradient->get_points()); + set_interpolation_mode(gradient->get_interpolation_mode()); +} + +void GradientEditor::reverse_gradient() { + gradient->reverse(); + set_points(gradient->get_points()); + emit_signal(SNAME("ramp_changed")); + update(); } GradientEditor::GradientEditor() { @@ -77,6 +89,23 @@ GradientEditor::GradientEditor() { /////////////////////// +void GradientReverseButton::_notification(int p_what) { + if (p_what == NOTIFICATION_DRAW) { + Ref<Texture2D> icon = get_theme_icon(SNAME("ReverseGradient"), SNAME("EditorIcons")); + if (is_pressed()) { + draw_texture_rect(icon, Rect2(margin, margin, icon->get_width(), icon->get_height()), false, get_theme_color(SNAME("icon_pressed_color"), SNAME("Button"))); + } else { + draw_texture_rect(icon, Rect2(margin, margin, icon->get_width(), icon->get_height())); + } + } +} + +Size2 GradientReverseButton::get_minimum_size() const { + return (get_theme_icon(SNAME("ReverseGradient"), SNAME("EditorIcons"))->get_size() + Size2(margin * 2, margin * 2)); +} + +/////////////////////// + bool EditorInspectorPluginGradient::can_handle(Object *p_object) { return Object::cast_to<Gradient>(p_object) != nullptr; } @@ -85,9 +114,23 @@ void EditorInspectorPluginGradient::parse_begin(Object *p_object) { Gradient *gradient = Object::cast_to<Gradient>(p_object); Ref<Gradient> g(gradient); - GradientEditor *editor = memnew(GradientEditor); + editor = memnew(GradientEditor); editor->set_gradient(g); add_custom_control(editor); + + reverse_btn = memnew(GradientReverseButton); + + gradient_tools_hbox = memnew(HBoxContainer); + gradient_tools_hbox->add_child(reverse_btn); + + add_custom_control(gradient_tools_hbox); + + reverse_btn->connect("pressed", callable_mp(this, &EditorInspectorPluginGradient::_reverse_button_pressed)); + reverse_btn->set_tooltip(TTR("Reverse/mirror gradient.")); +} + +void EditorInspectorPluginGradient::_reverse_button_pressed() { + editor->reverse_gradient(); } GradientEditorPlugin::GradientEditorPlugin(EditorNode *p_node) { diff --git a/editor/plugins/gradient_editor_plugin.h b/editor/plugins/gradient_editor_plugin.h index bcbb86e422..95b7b466c9 100644 --- a/editor/plugins/gradient_editor_plugin.h +++ b/editor/plugins/gradient_editor_plugin.h @@ -50,12 +50,28 @@ protected: public: virtual Size2 get_minimum_size() const override; void set_gradient(const Ref<Gradient> &p_gradient); + void reverse_gradient(); GradientEditor(); }; +class GradientReverseButton : public BaseButton { + GDCLASS(GradientReverseButton, BaseButton); + + int margin = 2; + + void _notification(int p_what); + virtual Size2 get_minimum_size() const override; +}; + class EditorInspectorPluginGradient : public EditorInspectorPlugin { GDCLASS(EditorInspectorPluginGradient, EditorInspectorPlugin); + GradientEditor *editor; + HBoxContainer *gradient_tools_hbox; + GradientReverseButton *reverse_btn; + + void _reverse_button_pressed(); + public: virtual bool can_handle(Object *p_object) override; virtual void parse_begin(Object *p_object) override; diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index 574d3ef27e..7a85c5167b 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -79,7 +79,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) { Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner(); ur->create_action(TTR("Create Static Trimesh Body")); - ur->add_do_method(node, "add_child", body); + ur->add_do_method(node, "add_child", body, true); ur->add_do_method(body, "set_owner", owner); ur->add_do_method(cshape, "set_owner", owner); ur->add_do_reference(body); @@ -113,7 +113,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) { Node *owner = instance == get_tree()->get_edited_scene_root() ? instance : instance->get_owner(); - ur->add_do_method(instance, "add_child", body); + ur->add_do_method(instance, "add_child", body, true); ur->add_do_method(body, "set_owner", owner); ur->add_do_method(cshape, "set_owner", owner); ur->add_do_reference(body); @@ -146,7 +146,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) { ur->create_action(TTR("Create Trimesh Static Shape")); - ur->add_do_method(node->get_parent(), "add_child", cshape); + ur->add_do_method(node->get_parent(), "add_child", cshape, true); ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1); ur->add_do_method(cshape, "set_owner", owner); ur->add_do_reference(cshape); @@ -185,7 +185,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) { Node *owner = node->get_owner(); - ur->add_do_method(node->get_parent(), "add_child", cshape); + ur->add_do_method(node->get_parent(), "add_child", cshape, true); ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1); ur->add_do_method(cshape, "set_owner", owner); ur->add_do_reference(cshape); @@ -247,7 +247,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) { UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Create Navigation Mesh")); - ur->add_do_method(node, "add_child", nmi); + ur->add_do_method(node, "add_child", nmi, true); ur->add_do_method(nmi, "set_owner", owner); ur->add_do_reference(nmi); @@ -426,7 +426,7 @@ void MeshInstance3DEditor::_create_outline_mesh() { ur->create_action(TTR("Create Outline")); - ur->add_do_method(node, "add_child", mi); + ur->add_do_method(node, "add_child", mi, true); ur->add_do_method(mi, "set_owner", owner); ur->add_do_reference(mi); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index b99ccc1012..fa5381bb10 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -3936,9 +3936,13 @@ Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const Vector3 point = world_pos + world_ray * MAX_DISTANCE; PhysicsDirectSpaceState3D *ss = get_tree()->get_root()->get_world_3d()->get_direct_space_state(); - PhysicsDirectSpaceState3D::RayResult result; - if (ss->intersect_ray(world_pos, world_pos + world_ray * MAX_DISTANCE, result)) { + PhysicsDirectSpaceState3D::RayParameters ray_params; + ray_params.from = world_pos; + ray_params.to = world_pos + world_ray * MAX_DISTANCE; + + PhysicsDirectSpaceState3D::RayResult result; + if (ss->intersect_ray(ray_params, result)) { point = result.position; } @@ -6566,7 +6570,12 @@ void Node3DEditor::snap_selected_nodes_to_floor() { Vector3 to = from - Vector3(0.0, max_snap_height, 0.0); Set<RID> excluded = _get_physics_bodies_rid(sp); - if (ss->intersect_ray(from, to, result, excluded)) { + PhysicsDirectSpaceState3D::RayParameters ray_params; + ray_params.from = from; + ray_params.to = to; + ray_params.exclude = excluded; + + if (ss->intersect_ray(ray_params, result)) { snapped_to_floor = true; } } @@ -6583,7 +6592,12 @@ void Node3DEditor::snap_selected_nodes_to_floor() { Vector3 to = from - Vector3(0.0, max_snap_height, 0.0); Set<RID> excluded = _get_physics_bodies_rid(sp); - if (ss->intersect_ray(from, to, result, excluded)) { + PhysicsDirectSpaceState3D::RayParameters ray_params; + ray_params.from = from; + ray_params.to = to; + ray_params.exclude = excluded; + + if (ss->intersect_ray(ray_params, result)) { Vector3 position_offset = d["position_offset"]; Transform3D new_transform = sp->get_global_transform(); @@ -6636,7 +6650,7 @@ void Node3DEditor::_add_sun_to_scene(bool p_already_added_environment) { Node *new_sun = preview_sun->duplicate(); undo_redo->create_action(TTR("Add Preview Sun to Scene")); - undo_redo->add_do_method(base, "add_child", new_sun); + undo_redo->add_do_method(base, "add_child", new_sun, true); // Move to the beginning of the scene tree since more "global" nodes // generally look better when placed at the top. undo_redo->add_do_method(base, "move_child", new_sun, 0); @@ -6666,7 +6680,7 @@ void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) { new_env->set_environment(preview_environment->get_environment()->duplicate(true)); undo_redo->create_action(TTR("Add Preview Environment to Scene")); - undo_redo->add_do_method(base, "add_child", new_env); + undo_redo->add_do_method(base, "add_child", new_env, true); // Move to the beginning of the scene tree since more "global" nodes // generally look better when placed at the top. undo_redo->add_do_method(base, "move_child", new_env, 0); @@ -7132,7 +7146,7 @@ void Node3DEditor::_update_preview_environment() { } else { if (!preview_sun->get_parent()) { - add_child(preview_sun); + add_child(preview_sun, true); sun_state->hide(); sun_vb->show(); } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 3f98560a2f..aad378ecec 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -227,12 +227,6 @@ void ScriptEditorBase::_bind_methods() { ADD_SIGNAL(MethodInfo("replace_in_files_requested", PropertyInfo(Variant::STRING, "text"))); } -static bool _is_built_in_script(Script *p_script) { - String path = p_script->get_path(); - - return path.find("::") != -1; -} - class EditorScriptCodeCompletionCache : public ScriptCodeCompletionCache { struct Cache { uint64_t time_loaded = 0; @@ -764,7 +758,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { if (p_save && file.is_valid()) { // Do not try to save internal scripts, but prompt to save in-memory // scripts which are not saved to disk yet (have empty path). - if (file->get_path().find("local://") == -1 && file->get_path().find("::") == -1) { + if (file->is_built_in()) { save_current_script(); } } @@ -910,7 +904,7 @@ void ScriptEditor::_resave_scripts(const String &p_str) { RES script = se->get_edited_resource(); - if (script->get_path() == "" || script->get_path().find("local://") != -1 || script->get_path().find("::") != -1) { + if (script->is_built_in()) { continue; //internal script, who cares } @@ -951,7 +945,7 @@ void ScriptEditor::_reload_scripts() { RES edited_res = se->get_edited_resource(); - if (edited_res->get_path() == "" || edited_res->get_path().find("local://") != -1 || edited_res->get_path().find("::") != -1) { + if (edited_res->is_built_in()) { continue; //internal script, who cares } @@ -995,7 +989,7 @@ void ScriptEditor::_res_saved_callback(const Ref<Resource> &p_res) { RES script = se->get_edited_resource(); - if (script->get_path() == "" || script->get_path().find("local://") != -1 || script->get_path().find("::") != -1) { + if (script->is_built_in()) { continue; //internal script, who cares } @@ -1037,7 +1031,7 @@ bool ScriptEditor::_test_script_times_on_disk(RES p_for_script) { continue; } - if (edited_res->get_path() == "" || edited_res->get_path().find("local://") != -1 || edited_res->get_path().find("::") != -1) { + if (edited_res->is_built_in()) { continue; //internal script, who cares } @@ -1624,7 +1618,7 @@ void ScriptEditor::close_builtin_scripts_from_scene(const String &p_scene) { continue; } - if (script->get_path().find("::") != -1 && script->get_path().begins_with(p_scene)) { //is an internal script and belongs to scene being closed + if (script->is_built_in() && script->get_path().begins_with(p_scene)) { //is an internal script and belongs to scene being closed _close_tab(i); i--; } @@ -2180,9 +2174,10 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra Ref<Script> script = p_resource; // Don't open dominant script if using an external editor. - const bool use_external_editor = + bool use_external_editor = EditorSettings::get_singleton()->get("text_editor/external/use_external_editor") || (script.is_valid() && script->get_language()->overrides_external_editor()); + use_external_editor = use_external_editor && !(script.is_valid() && script->is_built_in()); // Ignore external editor for built-in scripts. const bool open_dominant = EditorSettings::get_singleton()->get("text_editor/behavior/files/open_dominant_script_on_scene_change"); const bool should_open = (open_dominant && !use_external_editor) || !EditorNode::get_singleton()->is_changing_scene(); @@ -2450,7 +2445,7 @@ void ScriptEditor::save_all_scripts() { se->apply_code(); } - if (edited_res->get_path() != "" && edited_res->get_path().find("local://") == -1 && edited_res->get_path().find("::") == -1) { + if (!edited_res->is_built_in()) { Ref<TextFile> text_file = edited_res; Ref<Script> script = edited_res; @@ -2570,7 +2565,7 @@ void ScriptEditor::_add_callback(Object *p_obj, const String &p_function, const script_list->select(script_list->find_metadata(i)); // Save the current script so the changes can be picked up by an external editor. - if (!_is_built_in_script(script.ptr())) { // But only if it's not built-in script. + if (!script.ptr()->is_built_in()) { // But only if it's not built-in script. save_current_script(); } @@ -3346,9 +3341,10 @@ Array ScriptEditor::_get_open_script_editors() const { void ScriptEditor::set_scene_root_script(Ref<Script> p_script) { // Don't open dominant script if using an external editor. - const bool use_external_editor = + bool use_external_editor = EditorSettings::get_singleton()->get("text_editor/external/use_external_editor") || (p_script.is_valid() && p_script->get_language()->overrides_external_editor()); + use_external_editor = use_external_editor && !(p_script.is_valid() && p_script->is_built_in()); // Ignore external editor for built-in scripts. const bool open_dominant = EditorSettings::get_singleton()->get("text_editor/behavior/files/open_dominant_script_on_scene_change"); if (open_dominant && !use_external_editor && p_script.is_valid()) { @@ -3858,7 +3854,7 @@ void ScriptEditorPlugin::edit(Object *p_object) { Script *p_script = Object::cast_to<Script>(p_object); String res_path = p_script->get_path().get_slice("::", 0); - if (_is_built_in_script(p_script)) { + if (p_script->is_built_in()) { if (ResourceLoader::get_resource_type(res_path) == "PackedScene") { if (!EditorNode::get_singleton()->is_scene_open(res_path)) { EditorNode::get_singleton()->load_scene(res_path); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 219498b5e7..24cdc06d78 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -375,7 +375,7 @@ void ScriptTextEditor::ensure_focus() { String ScriptTextEditor::get_name() { String name; - if (script->get_path().find("local://") == -1 && script->get_path().find("::") == -1) { + if (!script->is_built_in()) { name = script->get_path().get_file(); if (is_unsaved()) { if (script->get_path().is_empty()) { @@ -658,7 +658,7 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo continue; } - if (script->get_path() == "" || script->get_path().find("local://") != -1 || script->get_path().find("::") != -1) { + if (script->is_built_in()) { continue; //internal script, who cares, though weird } diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 2731582288..9d2b4c88c5 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -482,8 +482,7 @@ void ShaderEditor::_check_for_external_edit() { return; } - // internal shader. - if (shader->get_path() == "" || shader->get_path().find("local://") != -1 || shader->get_path().find("::") != -1) { + if (shader->is_built_in()) { return; } @@ -530,7 +529,7 @@ void ShaderEditor::save_external_data(const String &p_str) { } apply_shaders(); - if (shader->get_path() != "" && shader->get_path().find("local://") == -1 && shader->get_path().find("::") == -1) { + if (!shader->is_built_in()) { //external shader, save it ResourceSaver::save(shader->get_path(), shader); } diff --git a/editor/plugins/text_control_editor_plugin.cpp b/editor/plugins/text_control_editor_plugin.cpp new file mode 100644 index 0000000000..c878c83430 --- /dev/null +++ b/editor/plugins/text_control_editor_plugin.cpp @@ -0,0 +1,375 @@ +/*************************************************************************/ +/* text_control_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "text_control_editor_plugin.h" + +#include "editor/editor_scale.h" + +void TextControlEditor::_notification(int p_notification) { + switch (p_notification) { + case NOTIFICATION_ENTER_TREE: { + if (!EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts))) { + EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts), make_binds("")); + } + [[fallthrough]]; + } + case NOTIFICATION_THEME_CHANGED: { + clear_formatting->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); + } break; + case NOTIFICATION_EXIT_TREE: { + if (EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts))) { + EditorFileSystem::get_singleton()->disconnect("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts)); + } + } break; + default: + break; + } +} + +void TextControlEditor::_find_resources(EditorFileSystemDirectory *p_dir) { + for (int i = 0; i < p_dir->get_subdir_count(); i++) { + _find_resources(p_dir->get_subdir(i)); + } + + for (int i = 0; i < p_dir->get_file_count(); i++) { + if (p_dir->get_file_type(i) == "FontData") { + Ref<FontData> fd = ResourceLoader::load(p_dir->get_file_path(i)); + if (fd.is_valid()) { + String name = fd->get_font_name(); + String sty = fd->get_font_style_name(); + if (sty.is_empty()) { + sty = "Default"; + } + fonts[name][sty] = p_dir->get_file_path(i); + } + } + } +} + +void TextControlEditor::_reload_fonts(const String &p_path) { + fonts.clear(); + _find_resources(EditorFileSystem::get_singleton()->get_filesystem()); + _update_control(); +} + +void TextControlEditor::_update_fonts_menu() { + font_list->clear(); + font_list->add_item(TTR("[Theme Default]"), FONT_INFO_THEME_DEFAULT); + if (custom_font.is_valid()) { + font_list->add_item(TTR("[Custom Font]"), FONT_INFO_USER_CUSTOM); + } + + int id = FONT_INFO_ID; + for (Map<String, Map<String, String>>::Element *E = fonts.front(); E; E = E->next()) { + font_list->add_item(E->key(), id++); + } + + if (font_list->get_item_count() > 1) { + font_list->show(); + } else { + font_list->hide(); + } +} + +void TextControlEditor::_update_styles_menu() { + font_style_list->clear(); + if ((font_list->get_selected_id() >= FONT_INFO_ID)) { + const String &name = font_list->get_item_text(font_list->get_selected()); + for (Map<String, String>::Element *E = fonts[name].front(); E; E = E->next()) { + font_style_list->add_item(E->key()); + } + } else { + font_style_list->add_item("Default"); + } + + if (font_style_list->get_item_count() > 1) { + font_style_list->show(); + } else { + font_style_list->hide(); + } +} + +void TextControlEditor::_update_control() { + if (edited_control) { + // Get override names. + if (edited_control->is_class("RichTextLabel")) { + edited_color = "default_color"; + edited_font = "normal_font"; + edited_font_size = "normal_font_size"; + } else { + edited_color = "font_color"; + edited_font = "font"; + edited_font_size = "font_size"; + } + + // Get font override. + Ref<Font> font; + if (edited_control->has_theme_font_override(edited_font)) { + font = edited_control->get_theme_font(edited_font); + } + if (font.is_valid()) { + if (font->get_data_count() != 1) { + // Composite font, save it to "custom_font" to allow undoing font change. + custom_font = font; + _update_fonts_menu(); + font_list->select(FONT_INFO_USER_CUSTOM); + _update_styles_menu(); + font_style_list->select(0); + } else { + // Single face font, search for the font with matching name and style. + String name = font->get_data(0)->get_font_name(); + String style = font->get_data(0)->get_font_style_name(); + if (fonts.has(name) && fonts[name].has(style)) { + _update_fonts_menu(); + for (int i = 0; i < font_list->get_item_count(); i++) { + if (font_list->get_item_text(i) == name) { + font_list->select(i); + break; + } + } + _update_styles_menu(); + for (int i = 0; i < font_style_list->get_item_count(); i++) { + if (font_style_list->get_item_text(i) == style) { + font_style_list->select(i); + break; + } + } + } else { + // Unknown font, save it to "custom_font" to allow undoing font change. + custom_font = font; + _update_fonts_menu(); + font_list->select(FONT_INFO_USER_CUSTOM); + _update_styles_menu(); + font_style_list->select(0); + } + } + } else { + // No font override, select "Theme Default". + _update_fonts_menu(); + font_list->select(FONT_INFO_THEME_DEFAULT); + _update_styles_menu(); + font_style_list->select(0); + } + + // Get other theme overrides. + font_size_list->set_value(edited_control->get_theme_font_size(edited_font_size)); + outline_size_list->set_value(edited_control->get_theme_constant("outline_size")); + + font_color_picker->set_pick_color(edited_control->get_theme_color(edited_color)); + outline_color_picker->set_pick_color(edited_control->get_theme_color("font_outline_color")); + } +} + +void TextControlEditor::_font_selected(int p_id) { + _update_styles_menu(); + _set_font(); +} + +void TextControlEditor::_font_style_selected(int p_id) { + _set_font(); +} + +void TextControlEditor::_set_font() { + if (edited_control) { + if (font_list->get_selected_id() == FONT_INFO_THEME_DEFAULT) { + // Remove font override. + edited_control->remove_theme_font_override(edited_font); + return; + } else if (font_list->get_selected_id() == FONT_INFO_USER_CUSTOM) { + // Restore "custom_font". + edited_control->add_theme_font_override(edited_font, custom_font); + return; + } else { + // Load new font resource using selected name and style. + String name = font_list->get_item_text(font_list->get_selected()); + String sty = font_style_list->get_item_text(font_style_list->get_selected()); + if (sty.is_empty()) { + sty = "Default"; + } + if (fonts.has(name)) { + Ref<FontData> fd = ResourceLoader::load(fonts[name][sty]); + if (fd.is_valid()) { + Ref<Font> f; + f.instantiate(); + f->add_data(fd); + edited_control->add_theme_font_override(edited_font, f); + } + } + } + } +} + +void TextControlEditor::_font_size_selected(double p_size) { + if (edited_control) { + edited_control->add_theme_font_size_override(edited_font_size, p_size); + } +} + +void TextControlEditor::_outline_size_selected(double p_size) { + if (edited_control) { + edited_control->add_theme_constant_override("outline_size", p_size); + } +} + +void TextControlEditor::_font_color_changed(const Color &p_color) { + if (edited_control) { + edited_control->add_theme_color_override(edited_color, p_color); + } +} + +void TextControlEditor::_outline_color_changed(const Color &p_color) { + if (edited_control) { + edited_control->add_theme_color_override("font_outline_color", p_color); + } +} + +void TextControlEditor::_clear_formatting() { + if (edited_control) { + edited_control->begin_bulk_theme_override(); + edited_control->remove_theme_font_override(edited_font); + edited_control->remove_theme_font_size_override(edited_font_size); + edited_control->remove_theme_color_override(edited_color); + edited_control->remove_theme_color_override("font_outline_color"); + edited_control->remove_theme_constant_override("outline_size"); + edited_control->end_bulk_theme_override(); + _update_control(); + } +} + +void TextControlEditor::edit(Object *p_object) { + Control *ctrl = Object::cast_to<Control>(p_object); + if (!ctrl) { + edited_control = nullptr; + custom_font = Ref<Font>(); + } else { + edited_control = ctrl; + custom_font = Ref<Font>(); + _update_control(); + } +} + +bool TextControlEditor::handles(Object *p_object) const { + Control *ctrl = Object::cast_to<Control>(p_object); + if (!ctrl) { + return false; + } else { + bool valid = false; + ctrl->get("text", &valid); + return valid; + } +} + +TextControlEditor::TextControlEditor() { + add_child(memnew(VSeparator)); + + font_list = memnew(OptionButton); + font_list->set_flat(true); + font_list->set_tooltip(TTR("Font")); + add_child(font_list); + font_list->connect("item_selected", callable_mp(this, &TextControlEditor::_font_selected)); + + font_style_list = memnew(OptionButton); + font_style_list->set_flat(true); + font_style_list->set_tooltip(TTR("Font style")); + font_style_list->set_toggle_mode(true); + add_child(font_style_list); + font_style_list->connect("item_selected", callable_mp(this, &TextControlEditor::_font_style_selected)); + + font_size_list = memnew(SpinBox); + font_size_list->set_tooltip(TTR("Font Size")); + font_size_list->get_line_edit()->add_theme_constant_override("minimum_character_width", 2); + font_size_list->set_min(6); + font_size_list->set_step(1); + font_size_list->set_max(96); + font_size_list->get_line_edit()->set_flat(true); + add_child(font_size_list); + font_size_list->connect("value_changed", callable_mp(this, &TextControlEditor::_font_size_selected)); + + font_color_picker = memnew(ColorPickerButton); + font_color_picker->set_custom_minimum_size(Size2(20, 0) * EDSCALE); + font_color_picker->set_flat(true); + font_color_picker->set_tooltip(TTR("Text Color")); + add_child(font_color_picker); + font_color_picker->connect("color_changed", callable_mp(this, &TextControlEditor::_font_color_changed)); + + add_child(memnew(VSeparator)); + + outline_size_list = memnew(SpinBox); + outline_size_list->set_tooltip(TTR("Outline Size")); + outline_size_list->get_line_edit()->add_theme_constant_override("minimum_character_width", 2); + outline_size_list->set_min(0); + outline_size_list->set_step(1); + outline_size_list->set_max(96); + outline_size_list->get_line_edit()->set_flat(true); + add_child(outline_size_list); + outline_size_list->connect("value_changed", callable_mp(this, &TextControlEditor::_outline_size_selected)); + + outline_color_picker = memnew(ColorPickerButton); + outline_color_picker->set_custom_minimum_size(Size2(20, 0) * EDSCALE); + outline_color_picker->set_flat(true); + outline_color_picker->set_tooltip(TTR("Outline Color")); + add_child(outline_color_picker); + outline_color_picker->connect("color_changed", callable_mp(this, &TextControlEditor::_outline_color_changed)); + + add_child(memnew(VSeparator)); + + clear_formatting = memnew(Button); + clear_formatting->set_flat(true); + clear_formatting->set_tooltip(TTR("Clear Formatting")); + add_child(clear_formatting); + clear_formatting->connect("pressed", callable_mp(this, &TextControlEditor::_clear_formatting)); +} + +/*************************************************************************/ + +void TextControlEditorPlugin::edit(Object *p_object) { + text_ctl_editor->edit(p_object); +} + +bool TextControlEditorPlugin::handles(Object *p_object) const { + return text_ctl_editor->handles(p_object); +} + +void TextControlEditorPlugin::make_visible(bool p_visible) { + if (p_visible) { + text_ctl_editor->show(); + } else { + text_ctl_editor->hide(); + text_ctl_editor->edit(nullptr); + } +} + +TextControlEditorPlugin::TextControlEditorPlugin(EditorNode *p_node) { + editor = p_node; + text_ctl_editor = memnew(TextControlEditor); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(text_ctl_editor); + + text_ctl_editor->hide(); +} diff --git a/editor/plugins/text_control_editor_plugin.h b/editor/plugins/text_control_editor_plugin.h new file mode 100644 index 0000000000..7f4aa3754c --- /dev/null +++ b/editor/plugins/text_control_editor_plugin.h @@ -0,0 +1,119 @@ +/*************************************************************************/ +/* text_control_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXT_CONTROL_EDITOR_PLUGIN_H +#define TEXT_CONTROL_EDITOR_PLUGIN_H + +#include "canvas_item_editor_plugin.h" +#include "editor/editor_file_system.h" +#include "editor/editor_inspector.h" +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "scene/gui/color_rect.h" +#include "scene/gui/menu_button.h" +#include "scene/gui/option_button.h" +#include "scene/gui/popup_menu.h" + +/*************************************************************************/ + +class TextControlEditor : public HBoxContainer { + GDCLASS(TextControlEditor, HBoxContainer); + + enum FontInfoID { + FONT_INFO_THEME_DEFAULT = 0, + FONT_INFO_USER_CUSTOM = 1, + FONT_INFO_ID = 100, + }; + + Map<String, Map<String, String>> fonts; + + OptionButton *font_list = nullptr; + SpinBox *font_size_list = nullptr; + OptionButton *font_style_list = nullptr; + ColorPickerButton *font_color_picker = nullptr; + SpinBox *outline_size_list = nullptr; + ColorPickerButton *outline_color_picker = nullptr; + Button *clear_formatting = nullptr; + + Control *edited_control = nullptr; + String edited_color; + String edited_font; + String edited_font_size; + Ref<Font> custom_font; + +protected: + void _notification(int p_notification); + static void _bind_methods(){}; + + void _find_resources(EditorFileSystemDirectory *p_dir); + void _reload_fonts(const String &p_path); + + void _update_fonts_menu(); + void _update_styles_menu(); + void _update_control(); + + void _font_selected(int p_id); + void _font_style_selected(int p_id); + void _set_font(); + + void _font_size_selected(double p_size); + void _outline_size_selected(double p_size); + + void _font_color_changed(const Color &p_color); + void _outline_color_changed(const Color &p_color); + + void _clear_formatting(); + +public: + void edit(Object *p_object); + bool handles(Object *p_object) const; + + TextControlEditor(); +}; + +/*************************************************************************/ + +class TextControlEditorPlugin : public EditorPlugin { + GDCLASS(TextControlEditorPlugin, EditorPlugin); + + TextControlEditor *text_ctl_editor; + EditorNode *editor; + +public: + virtual String get_name() const override { return "TextControlFontEditor"; } + bool has_main_screen() const override { return false; } + virtual void edit(Object *p_object) override; + virtual bool handles(Object *p_object) const override; + virtual void make_visible(bool p_visible) override; + + TextControlEditorPlugin(EditorNode *p_node); +}; + +#endif // TEXT_CONTROL_EDITOR_PLUGIN_H diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 1fc7eb98e0..3b45f32927 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -65,7 +65,7 @@ void TextEditor::_load_theme_settings() { String TextEditor::get_name() { String name; - if (text_file->get_path().find("local://") == -1 && text_file->get_path().find("::") == -1) { + if (!text_file->is_built_in()) { name = text_file->get_path().get_file(); if (is_unsaved()) { if (text_file->get_path().is_empty()) { diff --git a/editor/plugins/texture_3d_editor_plugin.cpp b/editor/plugins/texture_3d_editor_plugin.cpp index bd1923f4ab..b4e394a1c0 100644 --- a/editor/plugins/texture_3d_editor_plugin.cpp +++ b/editor/plugins/texture_3d_editor_plugin.cpp @@ -173,7 +173,7 @@ Texture3DEditor::Texture3DEditor() { info->set_v_grow_direction(GROW_DIRECTION_BEGIN); info->add_theme_color_override("font_color", Color(1, 1, 1, 1)); info->add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.5)); - info->add_theme_constant_override("shadow_as_outline", 1); + info->add_theme_constant_override("shadow_outline_size", 1); info->add_theme_constant_override("shadow_offset_x", 2); info->add_theme_constant_override("shadow_offset_y", 2); diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp index b9ec6bf5ab..e25b0270b4 100644 --- a/editor/plugins/texture_editor_plugin.cpp +++ b/editor/plugins/texture_editor_plugin.cpp @@ -101,7 +101,7 @@ TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) { metadata_label->add_theme_color_override("font_outline_color", Color::named("black")); metadata_label->add_theme_constant_override("outline_size", 2 * EDSCALE); - metadata_label->add_theme_constant_override("shadow_as_outline", 1); + metadata_label->add_theme_constant_override("shadow_outline_size", 1); metadata_label->set_h_size_flags(Control::SIZE_SHRINK_END); metadata_label->set_v_size_flags(Control::SIZE_SHRINK_END); diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp index 424e018a47..ee62138d12 100644 --- a/editor/plugins/texture_layered_editor_plugin.cpp +++ b/editor/plugins/texture_layered_editor_plugin.cpp @@ -249,7 +249,7 @@ TextureLayeredEditor::TextureLayeredEditor() { info->set_v_grow_direction(GROW_DIRECTION_BEGIN); info->add_theme_color_override("font_color", Color(1, 1, 1, 1)); info->add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.5)); - info->add_theme_constant_override("shadow_as_outline", 1); + info->add_theme_constant_override("shadow_outline_size", 1); info->add_theme_constant_override("shadow_offset_x", 2); info->add_theme_constant_override("shadow_offset_y", 2); diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp index f1918073fb..47dfc57b0f 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.cpp +++ b/editor/plugins/tiles/tiles_editor_plugin.cpp @@ -47,8 +47,12 @@ TilesEditorPlugin *TilesEditorPlugin::singleton = nullptr; -void TilesEditorPlugin::_pattern_preview_done(const Variant &p_udata) { - pattern_preview_done.set(); +void TilesEditorPlugin::_preview_frame_started() { + RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_pattern_preview_done)); +} + +void TilesEditorPlugin::_pattern_preview_done() { + pattern_preview_done.post(); } void TilesEditorPlugin::_thread_func(void *ud) { @@ -112,12 +116,9 @@ void TilesEditorPlugin::_thread() { // Add the viewport at the lasst moment to avoid rendering too early. EditorNode::get_singleton()->add_child(viewport); - pattern_preview_done.clear(); - RS::get_singleton()->request_frame_drawn_callback(const_cast<TilesEditorPlugin *>(this), "_pattern_preview_done", Variant()); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_preview_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT); - while (!pattern_preview_done.is_set()) { - OS::get_singleton()->delay_usec(10); - } + pattern_preview_done.wait(); Ref<Image> image = viewport->get_texture()->get_image(); Ref<ImageTexture> image_texture; @@ -274,10 +275,6 @@ bool TilesEditorPlugin::handles(Object *p_object) const { return p_object->is_class("TileMap") || p_object->is_class("TileSet"); } -void TilesEditorPlugin::_bind_methods() { - ClassDB::bind_method(D_METHOD("_pattern_preview_done", "pattern"), &TilesEditorPlugin::_pattern_preview_done); -} - TilesEditorPlugin::TilesEditorPlugin(EditorNode *p_node) { set_process_internal(true); diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h index dd52bdc31a..33493040f6 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.h +++ b/editor/plugins/tiles/tiles_editor_plugin.h @@ -77,14 +77,14 @@ private: Thread pattern_preview_thread; SafeFlag pattern_thread_exit; SafeFlag pattern_thread_exited; - mutable SafeFlag pattern_preview_done; - void _pattern_preview_done(const Variant &p_udata); + Semaphore pattern_preview_done; + void _preview_frame_started(); + void _pattern_preview_done(); static void _thread_func(void *ud); void _thread(); protected: void _notification(int p_what); - static void _bind_methods(); public: _FORCE_INLINE_ static TilesEditorPlugin *get_singleton() { return singleton; } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index c06eafae50..10a9b2bb10 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -4977,7 +4977,7 @@ public: } } - void setup(Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, Ref<VisualShaderNode> p_node) { + void setup(Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, const Map<StringName, String> &p_overrided_names, Ref<VisualShaderNode> p_node) { parent_resource = p_parent_resource; updating = false; node = p_node; @@ -4993,7 +4993,11 @@ public: Label *prop_name = memnew(Label); String prop_name_str = p_names[i]; - prop_name_str = prop_name_str.capitalize() + ":"; + if (p_overrided_names.has(p_names[i])) { + prop_name_str = p_overrided_names[p_names[i]] + ":"; + } else { + prop_name_str = prop_name_str.capitalize() + ":"; + } prop_name->set_text(prop_name_str); prop_name->set_visible(false); hbox->add_child(prop_name); @@ -5085,7 +5089,7 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par properties.push_back(pinfo[i].name); } VisualShaderNodePluginDefaultEditor *editor = memnew(VisualShaderNodePluginDefaultEditor); - editor->setup(p_parent_resource, editors, properties, p_node); + editor->setup(p_parent_resource, editors, properties, p_node->get_editable_properties_names(), p_node); return editor; } diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index db560af657..62c5cc5cc1 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -1671,7 +1671,7 @@ void CustomPropertyEditor::_focus_exit() { } void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings) { - Ref<StyleBox> sb = action_buttons[0]->get_theme_stylebox(SNAME("panel")); + Ref<StyleBox> sb = action_buttons[0]->get_theme_stylebox(SNAME("button")); int margin_top = sb->get_margin(SIDE_TOP); int margin_left = sb->get_margin(SIDE_LEFT); int margin_bottom = sb->get_margin(SIDE_BOTTOM); @@ -1804,26 +1804,18 @@ CustomPropertyEditor::CustomPropertyEditor() { } text_edit = memnew(TextEdit); - add_child(text_edit); + value_vbox->add_child(text_edit); text_edit->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5); + text_edit->set_v_size_flags(Control::SIZE_EXPAND_FILL); text_edit->set_offset(SIDE_BOTTOM, -30); text_edit->hide(); text_edit->connect("text_changed", callable_mp(this, &CustomPropertyEditor::_text_edit_changed)); - for (int i = 0; i < MAX_ACTION_BUTTONS; i++) { - action_buttons[i] = memnew(Button); - action_buttons[i]->hide(); - add_child(action_buttons[i]); - Vector<Variant> binds; - binds.push_back(i); - action_buttons[i]->connect("pressed", callable_mp(this, &CustomPropertyEditor::_action_pressed), binds); - } - color_picker = nullptr; file = memnew(EditorFileDialog); - add_child(file); + value_vbox->add_child(file); file->hide(); file->connect("file_selected", callable_mp(this, &CustomPropertyEditor::_file_selected)); @@ -1831,46 +1823,58 @@ CustomPropertyEditor::CustomPropertyEditor() { error = memnew(ConfirmationDialog); error->set_title(TTR("Error!")); - add_child(error); + value_vbox->add_child(error); scene_tree = memnew(SceneTreeDialog); - add_child(scene_tree); + value_vbox->add_child(scene_tree); scene_tree->connect("selected", callable_mp(this, &CustomPropertyEditor::_node_path_selected)); scene_tree->get_scene_tree()->set_show_enabled_subscene(true); texture_preview = memnew(TextureRect); - add_child(texture_preview); + value_vbox->add_child(texture_preview); texture_preview->hide(); easing_draw = memnew(Control); - add_child(easing_draw); + value_vbox->add_child(easing_draw); easing_draw->hide(); easing_draw->connect("draw", callable_mp(this, &CustomPropertyEditor::_draw_easing)); easing_draw->connect("gui_input", callable_mp(this, &CustomPropertyEditor::_drag_easing)); easing_draw->set_default_cursor_shape(Control::CURSOR_MOVE); type_button = memnew(MenuButton); - add_child(type_button); + value_vbox->add_child(type_button); type_button->hide(); type_button->get_popup()->connect("id_pressed", callable_mp(this, &CustomPropertyEditor::_type_create_selected)); menu = memnew(PopupMenu); // menu->set_pass_on_modal_close_click(false); - add_child(menu); + value_vbox->add_child(menu); menu->connect("id_pressed", callable_mp(this, &CustomPropertyEditor::_menu_option)); evaluator = nullptr; spinbox = memnew(SpinBox); - add_child(spinbox); + value_vbox->add_child(spinbox); spinbox->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5); spinbox->connect("value_changed", callable_mp(this, &CustomPropertyEditor::_range_modified)); slider = memnew(HSlider); - add_child(slider); + value_vbox->add_child(slider); slider->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5); slider->connect("value_changed", callable_mp(this, &CustomPropertyEditor::_range_modified)); + action_hboxes = memnew(HBoxContainer); + action_hboxes->set_alignment(BoxContainer::ALIGN_CENTER); + value_vbox->add_child(action_hboxes); + for (int i = 0; i < MAX_ACTION_BUTTONS; i++) { + action_buttons[i] = memnew(Button); + action_buttons[i]->hide(); + action_hboxes->add_child(action_buttons[i]); + Vector<Variant> binds; + binds.push_back(i); + action_buttons[i]->connect("pressed", callable_mp(this, &CustomPropertyEditor::_action_pressed), binds); + } + create_dialog = nullptr; property_select = nullptr; } diff --git a/editor/property_editor.h b/editor/property_editor.h index 23771b7494..2565c6ee27 100644 --- a/editor/property_editor.h +++ b/editor/property_editor.h @@ -110,6 +110,7 @@ class CustomPropertyEditor : public PopupPanel { int focused_value_editor; Label *value_label[MAX_VALUE_EDITORS]; HScrollBar *scroll[4]; + HBoxContainer *action_hboxes; Button *action_buttons[MAX_ACTION_BUTTONS]; MenuButton *type_button; Vector<String> inheritors_array; diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index 2792c193d9..f5b70504fa 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -461,7 +461,7 @@ String RenameDialog::_substitute(const String &subject, const Node *node, int co void RenameDialog::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type) { RenameDialog *self = (RenameDialog *)p_self; - String source_file(p_file); + String source_file = String::utf8(p_file); // Only show first error that is related to "regex" if (self->has_errors || source_file.find("regex") < 0) { @@ -470,9 +470,9 @@ void RenameDialog::_error_handler(void *p_self, const char *p_func, const char * String err_str; if (p_errorexp && p_errorexp[0]) { - err_str = p_errorexp; + err_str = String::utf8(p_errorexp); } else { - err_str = p_error; + err_str = String::utf8(p_error); } self->has_errors = true; diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 336a0e4c37..921befbb6b 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -47,6 +47,7 @@ #include "editor/plugins/script_editor_plugin.h" #include "editor/shader_create_dialog.h" #include "scene/main/window.h" +#include "scene/property_utils.h" #include "scene/resources/packed_scene.h" #include "servers/display_server.h" #include "servers/rendering_server.h" @@ -2153,7 +2154,7 @@ void SceneTreeDock::_do_create(Node *p_parent) { editor_data->get_undo_redo().create_action(TTR("Create Node")); if (edited_scene) { - editor_data->get_undo_redo().add_do_method(p_parent, "add_child", child); + editor_data->get_undo_redo().add_do_method(p_parent, "add_child", child, true); editor_data->get_undo_redo().add_do_method(child, "set_owner", edited_scene); editor_data->get_undo_redo().add_do_method(editor_selection, "clear"); editor_data->get_undo_redo().add_do_method(editor_selection, "add_node", child); @@ -3132,7 +3133,9 @@ void SceneTreeDock::_clear_clipboard() { void SceneTreeDock::_create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap) { List<PropertyInfo> props; p_node->get_property_list(&props); - bool is_instantiated = EditorPropertyRevert::may_node_be_in_instance(p_node); + + Vector<SceneState::PackState> states_stack; + bool states_stack_ready = false; for (const PropertyInfo &E : props) { if (!(E.usage & PROPERTY_USAGE_STORAGE)) { @@ -3143,16 +3146,17 @@ void SceneTreeDock::_create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap) if (v.is_ref()) { RES res = v; if (res.is_valid()) { - if (is_instantiated) { - Variant orig; - if (EditorPropertyRevert::get_instantiated_node_original_property(p_node, E.name, orig)) { - if (!EditorPropertyRevert::is_node_property_different(p_node, v, orig)) { - continue; - } - } + if (!states_stack_ready) { + states_stack = PropertyUtils::get_node_states_stack(p_node); + states_stack_ready = true; + } + + Variant orig = PropertyUtils::get_property_default_value(p_node, E.name, &states_stack); + if (!PropertyUtils::is_property_value_different(v, orig)) { + continue; } - if ((res->get_path() == "" || res->get_path().find("::") > -1) && !r_remap.has(res)) { + if (res->is_built_in() && !r_remap.has(res)) { _create_remap_for_resource(res, r_remap); } } @@ -3179,7 +3183,7 @@ void SceneTreeDock::_create_remap_for_resource(RES p_resource, Map<RES, RES> &r_ if (v.is_ref()) { RES res = v; if (res.is_valid()) { - if ((res->get_path() == "" || res->get_path().find("::") > -1) && !r_remap.has(res)) { + if (res->is_built_in() && !r_remap.has(res)) { _create_remap_for_resource(res, r_remap); } } diff --git a/misc/dist/osx_tools.app/Contents/Resources/af.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/af.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/af.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/az.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/az.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/az.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/br.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/br.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/br.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/da.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/da.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/da.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/de.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/de.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/de.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/el.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/el.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/el.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/es.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/es.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/es.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/et.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/et.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/et.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/he.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/he.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/he.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/id.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/id.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/id.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/is.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/is.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/is.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/it.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/it.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/it.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/km.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/km.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/km.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/or.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/or.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/or.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/si.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/si.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/si.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/te.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/te.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/te.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/th.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/th.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/th.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings diff --git a/misc/dist/osx_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings b/misc/dist/osx_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/misc/dist/osx_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 863936ab8c..b9be7535dc 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -572,9 +572,9 @@ void CSGShape3D::_validate_property(PropertyInfo &property) const { bool is_collision_prefixed = property.name.begins_with("collision_"); if ((is_collision_prefixed || property.name.begins_with("use_collision")) && is_inside_tree() && !is_root_shape()) { //hide collision if not root - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } else if (is_collision_prefixed && !bool(get("use_collision"))) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } GeometryInstance3D::_validate_property(property); } diff --git a/modules/fbx/editor_scene_importer_fbx.cpp b/modules/fbx/editor_scene_importer_fbx.cpp index 9bdeafbf91..b11c145599 100644 --- a/modules/fbx/editor_scene_importer_fbx.cpp +++ b/modules/fbx/editor_scene_importer_fbx.cpp @@ -843,7 +843,7 @@ Node3D *EditorSceneFormatImporterFBX::_generate_scene( if (state.animation_player == nullptr) { print_verbose("Creating animation player"); state.animation_player = memnew(AnimationPlayer); - state.root->add_child(state.animation_player); + state.root->add_child(state.animation_player, true); state.animation_player->set_owner(state.root_owner); } diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h index 5390d30c9f..bc53a4001d 100644 --- a/modules/gdnative/include/nativescript/godot_nativescript.h +++ b/modules/gdnative/include/nativescript/godot_nativescript.h @@ -102,7 +102,7 @@ typedef enum { GODOT_PROPERTY_USAGE_DEFAULT = GODOT_PROPERTY_USAGE_STORAGE | GODOT_PROPERTY_USAGE_EDITOR | GODOT_PROPERTY_USAGE_NETWORK, GODOT_PROPERTY_USAGE_DEFAULT_INTL = GODOT_PROPERTY_USAGE_STORAGE | GODOT_PROPERTY_USAGE_EDITOR | GODOT_PROPERTY_USAGE_NETWORK | GODOT_PROPERTY_USAGE_INTERNATIONALIZED, - GODOT_PROPERTY_USAGE_NOEDITOR = GODOT_PROPERTY_USAGE_STORAGE | GODOT_PROPERTY_USAGE_NETWORK, + GODOT_PROPERTY_USAGE_NO_EDITOR = GODOT_PROPERTY_USAGE_STORAGE | GODOT_PROPERTY_USAGE_NETWORK, } godot_nativescript_property_usage_flags; typedef struct { diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp index 4c9bfb395d..e249363016 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp +++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp @@ -341,7 +341,7 @@ void VideoStreamGDNative::_bind_methods() { ClassDB::bind_method(D_METHOD("set_file", "file"), &VideoStreamGDNative::set_file); ClassDB::bind_method(D_METHOD("get_file"), &VideoStreamGDNative::get_file); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "file", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_file", "get_file"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "file", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_file", "get_file"); } void VideoStreamGDNative::set_audio_track(int p_track) { diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 631ee4d895..5b476cda01 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -98,6 +98,7 @@ [codeblock] [{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}] [/codeblock] + [b]Note:[/b] Not supported for calling from threads. Instead, this will return an empty array. </description> </method> <method name="inst2dict"> @@ -160,17 +161,24 @@ <method name="print_debug" qualifiers="vararg"> <return type="void" /> <description> - Like [method @GlobalScope.print], but prints only when used in debug mode. + Like [method @GlobalScope.print], but includes the current stack frame when running with the debugger turned on. + Output in the console would look something like this: + [codeblock] + Test print + At: res://test.gd:15:_process() + [/codeblock] + [b]Note:[/b] Not supported for calling from threads. Instead of the stack frame, this will print the thread ID. </description> </method> <method name="print_stack"> <return type="void" /> <description> - Prints a stack track at code location, only works when running with debugger turned on. + Prints a stack trace at the current code location. Only works when running with debugger turned on. Output in the console would look something like this: [codeblock] Frame 0 - res://test.gd:16 in function '_process' [/codeblock] + [b]Note:[/b] Not supported for calling from threads. Instead of the stack trace, this will print the thread ID. </description> </method> <method name="range" qualifiers="vararg"> diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 2e55506fd4..e4d3ed118c 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -979,7 +979,7 @@ bool GDScript::_set(const StringName &p_name, const Variant &p_value) { } void GDScript::_get_property_list(List<PropertyInfo> *p_properties) const { - p_properties->push_back(PropertyInfo(Variant::STRING, "script/source", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_properties->push_back(PropertyInfo(Variant::STRING, "script/source", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } void GDScript::_bind_methods() { @@ -1257,6 +1257,8 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { call(member->setter, &val, 1, err); if (err.error == Callable::CallError::CALL_OK) { return true; //function exists, call was successful + } else { + return false; } } else { if (member->data_type.has_type) { diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index f1b0079536..e997d3a51e 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -437,9 +437,13 @@ struct GDScriptUtilityFunctionsDefinitions { str += p_args[i]->operator String(); } - ScriptLanguage *script = GDScriptLanguage::get_singleton(); - if (script->debug_get_stack_level_count() > 0) { - str += "\n At: " + script->debug_get_stack_level_source(0) + ":" + itos(script->debug_get_stack_level_line(0)) + ":" + script->debug_get_stack_level_function(0) + "()"; + if (Thread::get_caller_id() == Thread::get_main_id()) { + ScriptLanguage *script = GDScriptLanguage::get_singleton(); + if (script->debug_get_stack_level_count() > 0) { + str += "\n At: " + script->debug_get_stack_level_source(0) + ":" + itos(script->debug_get_stack_level_line(0)) + ":" + script->debug_get_stack_level_function(0) + "()"; + } + } else { + str += "\n At: Cannot retrieve debug info outside the main thread. Thread ID: " + itos(Thread::get_caller_id()); } print_line(str); @@ -448,15 +452,24 @@ struct GDScriptUtilityFunctionsDefinitions { static inline void print_stack(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { VALIDATE_ARG_COUNT(0); + if (Thread::get_caller_id() != Thread::get_main_id()) { + print_line("Cannot retrieve debug info outside the main thread. Thread ID: " + itos(Thread::get_caller_id())); + return; + } ScriptLanguage *script = GDScriptLanguage::get_singleton(); for (int i = 0; i < script->debug_get_stack_level_count(); i++) { print_line("Frame " + itos(i) + " - " + script->debug_get_stack_level_source(i) + ":" + itos(script->debug_get_stack_level_line(i)) + " in function '" + script->debug_get_stack_level_function(i) + "'"); }; + *r_ret = Variant(); } static inline void get_stack(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { VALIDATE_ARG_COUNT(0); + if (Thread::get_caller_id() != Thread::get_main_id()) { + *r_ret = Array(); + return; + } ScriptLanguage *script = GDScriptLanguage::get_singleton(); Array ret; diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index f4c0c4d9bb..80f4721e2d 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -269,7 +269,7 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p if (j > 0) { symbol.detail += ", "; } - symbol.detail += m.signal->parameters[i]->identifier->name; + symbol.detail += m.signal->parameters[j]->identifier->name; } symbol.detail += ")"; diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index a5e56640ed..ced80e26b5 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -5605,7 +5605,7 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent // Bone Attachment - Parent Case BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent); - scene_parent->add_child(bone_attachment); + scene_parent->add_child(bone_attachment, true); bone_attachment->set_owner(scene_root); // There is no gltf_node that represent this, so just directly create a unique name @@ -5628,7 +5628,7 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent current_node = _generate_spatial(state, scene_parent, node_index); } - scene_parent->add_child(current_node); + scene_parent->add_child(current_node, true); if (current_node != scene_root) { current_node->set_owner(scene_root); } @@ -5658,7 +5658,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scen // Bone Attachment - Direct Parented Skeleton Case BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent); - scene_parent->add_child(bone_attachment); + scene_parent->add_child(bone_attachment, true); bone_attachment->set_owner(scene_root); // There is no gltf_node that represent this, so just directly create a unique name @@ -5672,7 +5672,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scen // Add it to the scene if it has not already been added if (skeleton->get_parent() == nullptr) { - scene_parent->add_child(skeleton); + scene_parent->add_child(skeleton, true); skeleton->set_owner(scene_root); } } @@ -5686,7 +5686,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scen // Bone Attachment - Same Node Case BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, node_index); - scene_parent->add_child(bone_attachment); + scene_parent->add_child(bone_attachment, true); bone_attachment->set_owner(scene_root); // There is no gltf_node that represent this, so just directly create a unique name @@ -5706,7 +5706,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scen current_node = _generate_light(state, scene_parent, node_index); } - scene_parent->add_child(current_node); + scene_parent->add_child(current_node, true); if (current_node != scene_root) { current_node->set_owner(scene_root); } @@ -6220,7 +6220,7 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_roo ERR_CONTINUE_MSG(skeleton == nullptr, vformat("Unable to find Skeleton for node %d skin %d", node_i, skin_i)); mi->get_parent()->remove_child(mi); - skeleton->add_child(mi); + skeleton->add_child(mi, true); mi->set_owner(skeleton->get_owner()); mi->set_skin(state->skins.write[skin_i]->godot_skin); @@ -6900,7 +6900,7 @@ Node *GLTFDocument::import_scene_gltf(const String &p_path, uint32_t p_flags, in gltf_document->_process_mesh_instances(r_state, root); if (r_state->animations.size()) { AnimationPlayer *ap = memnew(AnimationPlayer); - root->add_child(ap); + root->add_child(ap, true); ap->set_owner(root); for (int i = 0; i < r_state->animations.size(); i++) { gltf_document->_import_animation(r_state, ap, i, p_bake_fps); diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp index 17ce051b67..49e9f5f97e 100644 --- a/modules/minimp3/audio_stream_mp3.cpp +++ b/modules/minimp3/audio_stream_mp3.cpp @@ -228,9 +228,9 @@ void AudioStreamMP3::_bind_methods() { ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamMP3::set_loop_offset); ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamMP3::get_loop_offset); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_loop", "has_loop"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "loop_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_loop_offset", "get_loop_offset"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_data", "get_data"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_loop", "has_loop"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "loop_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_loop_offset", "get_loop_offset"); } AudioStreamMP3::AudioStreamMP3() { diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 6970349414..d9b291489b 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -2981,7 +2981,7 @@ bool CSharpScript::_set(const StringName &p_name, const Variant &p_value) { } void CSharpScript::_get_property_list(List<PropertyInfo> *p_properties) const { - p_properties->push_back(PropertyInfo(Variant::STRING, CSharpLanguage::singleton->string_names._script_source, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_properties->push_back(PropertyInfo(Variant::STRING, CSharpLanguage::singleton->string_names._script_source, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } void CSharpScript::_bind_methods() { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs index 1694ac0320..c18f818ed2 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs @@ -472,26 +472,22 @@ namespace Godot return new Quaternion(-left.x, -left.y, -left.z, -left.w); } - public static Quaternion operator *(Quaternion left, Vector3 right) + public static Vector3 operator *(Quaternion quat, Vector3 vec) { - return new Quaternion - ( - (left.w * right.x) + (left.y * right.z) - (left.z * right.y), - (left.w * right.y) + (left.z * right.x) - (left.x * right.z), - (left.w * right.z) + (left.x * right.y) - (left.y * right.x), - -(left.x * right.x) - (left.y * right.y) - (left.z * right.z) - ); +#if DEBUG + if (!quat.IsNormalized()) + { + throw new InvalidOperationException("Quaternion is not normalized."); + } +#endif + var u = new Vector3(quat.x, quat.y, quat.z); + Vector3 uv = u.Cross(vec); + return vec + (((uv * quat.w) + u.Cross(uv)) * 2); } - public static Quaternion operator *(Vector3 left, Quaternion right) + public static Vector3 operator *(Vector3 vec, Quaternion quat) { - return new Quaternion - ( - (right.w * left.x) + (right.y * left.z) - (right.z * left.y), - (right.w * left.y) + (right.z * left.x) - (right.x * left.z), - (right.w * left.z) + (right.x * left.y) - (right.y * left.x), - -(right.x * left.x) - (right.y * left.y) - (right.z * left.z) - ); + return quat.Inverse() * vec; } public static Quaternion operator *(Quaternion left, real_t right) diff --git a/modules/ogg/ogg_packet_sequence.cpp b/modules/ogg/ogg_packet_sequence.cpp index b7a3ad2876..abb2b67ab0 100644 --- a/modules/ogg/ogg_packet_sequence.cpp +++ b/modules/ogg/ogg_packet_sequence.cpp @@ -127,9 +127,9 @@ void OGGPacketSequence::_bind_methods() { ClassDB::bind_method(D_METHOD("get_length"), &OGGPacketSequence::get_length); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "packet_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_packet_data", "get_packet_data"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "granule_positions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_packet_granule_positions", "get_packet_granule_positions"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sampling_rate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_sampling_rate", "get_sampling_rate"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "packet_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_data", "get_packet_data"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "granule_positions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_granule_positions", "get_packet_granule_positions"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sampling_rate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_sampling_rate", "get_sampling_rate"); } bool OGGPacketSequencePlayback::next_ogg_packet(ogg_packet **p_packet) const { diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml index 8a10411cf6..16fea228b1 100644 --- a/modules/opensimplex/doc_classes/NoiseTexture.xml +++ b/modules/opensimplex/doc_classes/NoiseTexture.xml @@ -8,8 +8,9 @@ NoiseTexture can also generate normal map textures. The class uses [Thread]s to generate the texture data internally, so [method Texture2D.get_image] may return [code]null[/code] if the generation process has not completed yet. In that case, you need to wait for the texture to be generated before accessing the image and the generated byte data: [codeblock] - var texture = preload("res://noise.tres") - yield(texture, "changed") + var texture = NoiseTexture.new() + texture.noise = OpenSimplexNoise.new() + await texture.changed var image = texture.get_image() var data = image.get_data() [/codeblock] diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp index 9db3f3d5fd..e36dcfcea5 100644 --- a/modules/opensimplex/noise_texture.cpp +++ b/modules/opensimplex/noise_texture.cpp @@ -80,7 +80,7 @@ void NoiseTexture::_bind_methods() { void NoiseTexture::_validate_property(PropertyInfo &property) const { if (property.name == "bump_strength") { if (!as_normal_map) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } } diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 129bc6af0b..1a0b0e357d 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -1279,6 +1279,23 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced fd->underline_thickness = (FT_MulFix(fd->face->underline_thickness, fd->face->size->metrics.y_scale) / 64.0) / fd->oversampling * fd->scale; if (!p_font_data->face_init) { + // Get style flags and name. + if (fd->face->family_name != nullptr) { + p_font_data->font_name = String::utf8((const char *)fd->face->family_name); + } + if (fd->face->style_name != nullptr) { + p_font_data->style_name = String::utf8((const char *)fd->face->style_name); + } + p_font_data->style_flags = 0; + if (fd->face->style_flags & FT_STYLE_FLAG_BOLD) { + p_font_data->style_flags |= FONT_BOLD; + } + if (fd->face->style_flags & FT_STYLE_FLAG_ITALIC) { + p_font_data->style_flags |= FONT_ITALIC; + } + if (fd->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) { + p_font_data->style_flags |= FONT_FIXED_WIDTH; + } // Get supported scripts from OpenType font data. p_font_data->supported_scripts.clear(); unsigned int count = hb_ot_layout_table_get_script_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GSUB, 0, nullptr, nullptr); @@ -1648,6 +1665,66 @@ void TextServerAdvanced::font_set_data_ptr(RID p_font_rid, const uint8_t *p_data fd->data_size = p_data_size; } +void TextServerAdvanced::font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); + fd->style_flags = p_style; +} + +uint32_t /*FontStyle*/ TextServerAdvanced::font_get_style(RID p_font_rid) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, 0); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0); + return fd->style_flags; +} + +void TextServerAdvanced::font_set_style_name(RID p_font_rid, const String &p_name) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); + fd->style_name = p_name; +} + +String TextServerAdvanced::font_get_style_name(RID p_font_rid) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, String()); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), String()); + return fd->style_name; +} + +void TextServerAdvanced::font_set_name(RID p_font_rid, const String &p_name) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); + fd->font_name = p_name; +} + +String TextServerAdvanced::font_get_name(RID p_font_rid) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, String()); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), String()); + return fd->font_name; +} + void TextServerAdvanced::font_set_antialiased(RID p_font_rid, bool p_antialiased) { FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); @@ -2931,6 +3008,27 @@ TextServer::Direction TextServerAdvanced::shaped_text_get_direction(RID p_shaped return sd->direction; } +void TextServerAdvanced::shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) { + _THREAD_SAFE_METHOD_ + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND(!sd); + + if (sd->custom_punct != p_punct) { + if (sd->parent != RID()) { + full_copy(sd); + } + sd->custom_punct = p_punct; + invalidate(sd); + } +} + +String TextServerAdvanced::shaped_text_get_custom_punctuation(RID p_shaped) const { + _THREAD_SAFE_METHOD_ + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V(!sd, String()); + return sd->custom_punct; +} + void TextServerAdvanced::shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) { ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND(!sd); @@ -3230,6 +3328,7 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng new_sd->orientation = sd->orientation; new_sd->direction = sd->direction; + new_sd->custom_punct = sd->custom_punct; new_sd->para_direction = sd->para_direction; new_sd->line_breaks_valid = sd->line_breaks_valid; new_sd->justification_ops_valid = sd->justification_ops_valid; @@ -3810,6 +3909,9 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) { const char32_t *ch = sd->text.ptr(); Glyph *sd_glyphs = sd->glyphs.ptrw(); + int c_punct_size = sd->custom_punct.length(); + const char32_t *c_punct = sd->custom_punct.ptr(); + for (i = 0; i < sd_size; i++) { if (sd_glyphs[i].count > 0) { char32_t c = ch[sd_glyphs[i].start - sd->start]; @@ -3822,12 +3924,21 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) { if (is_whitespace(c)) { sd_glyphs[i].flags |= GRAPHEME_IS_SPACE; } + if (c_punct_size == 0) { + if (u_ispunct(c) && c != 0x005F) { + sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION; + } + } else { + for (int j = 0; j < c_punct_size; j++) { + if (c_punct[j] == c) { + sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION; + break; + } + } + } if (is_underscore(c)) { sd_glyphs[i].flags |= GRAPHEME_IS_UNDERSCORE; } - if (u_ispunct(c) && c != 0x005F) { - sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION; - } if (breaks.has(sd->glyphs[i].start)) { if (breaks[sd->glyphs[i].start]) { sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_HARD; diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 15f3a7f1a9..eb8316b200 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -177,6 +177,10 @@ class TextServerAdvanced : public TextServer { Dictionary variation_coordinates; float oversampling = 0.f; + uint32_t style_flags = 0; + String font_name; + String style_name; + Map<Vector2i, FontDataForSizeAdvanced *> cache; bool face_init = false; @@ -321,6 +325,15 @@ public: virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) override; virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) override; + virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) override; + virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const override; + + virtual void font_set_style_name(RID p_font_rid, const String &p_name) override; + virtual String font_get_style_name(RID p_font_rid) const override; + + virtual void font_set_name(RID p_font_rid, const String &p_name) override; + virtual String font_get_name(RID p_font_rid) const override; + virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) override; virtual bool font_is_antialiased(RID p_font_rid) const override; @@ -450,6 +463,9 @@ public: virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override; + virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) override; + virtual String shaped_text_get_custom_punctuation(RID p_shaped) const override; + virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index e0e77ff753..43a636e484 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -736,6 +736,23 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback fd->underline_thickness = (FT_MulFix(fd->face->underline_thickness, fd->face->size->metrics.y_scale) / 64.0) / fd->oversampling * fd->scale; if (!p_font_data->face_init) { + // Get style flags and name. + if (fd->face->family_name != nullptr) { + p_font_data->font_name = String::utf8((const char *)fd->face->family_name); + } + if (fd->face->style_name != nullptr) { + p_font_data->style_name = String::utf8((const char *)fd->face->style_name); + } + p_font_data->style_flags = 0; + if (fd->face->style_flags & FT_STYLE_FLAG_BOLD) { + p_font_data->style_flags |= FONT_BOLD; + } + if (fd->face->style_flags & FT_STYLE_FLAG_ITALIC) { + p_font_data->style_flags |= FONT_ITALIC; + } + if (fd->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) { + p_font_data->style_flags |= FONT_FIXED_WIDTH; + } // Read OpenType variations. p_font_data->supported_varaitions.clear(); if (fd->face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) { @@ -826,6 +843,66 @@ void TextServerFallback::font_set_data_ptr(RID p_font_rid, const uint8_t *p_data fd->data_size = p_data_size; } +void TextServerFallback::font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); + fd->style_flags = p_style; +} + +uint32_t /*FontStyle*/ TextServerFallback::font_get_style(RID p_font_rid) const { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, 0); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0); + return fd->style_flags; +} + +void TextServerFallback::font_set_style_name(RID p_font_rid, const String &p_name) { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); + fd->style_name = p_name; +} + +String TextServerFallback::font_get_style_name(RID p_font_rid) const { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, String()); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), String()); + return fd->style_name; +} + +void TextServerFallback::font_set_name(RID p_font_rid, const String &p_name) { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); + fd->font_name = p_name; +} + +String TextServerFallback::font_get_name(RID p_font_rid) const { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, String()); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), String()); + return fd->font_name; +} + void TextServerFallback::font_set_antialiased(RID p_font_rid, bool p_antialiased) { FontDataFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); @@ -2030,6 +2107,27 @@ TextServer::Direction TextServerFallback::shaped_text_get_direction(RID p_shaped return TextServer::DIRECTION_LTR; } +void TextServerFallback::shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) { + _THREAD_SAFE_METHOD_ + ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND(!sd); + + if (sd->custom_punct != p_punct) { + if (sd->parent != RID()) { + full_copy(sd); + } + sd->custom_punct = p_punct; + invalidate(sd); + } +} + +String TextServerFallback::shaped_text_get_custom_punctuation(RID p_shaped) const { + _THREAD_SAFE_METHOD_ + const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V(!sd, String()); + return sd->custom_punct; +} + void TextServerFallback::shaped_text_set_orientation(RID p_shaped, TextServer::Orientation p_orientation) { ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND(!sd); @@ -2332,6 +2430,7 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng new_sd->orientation = sd->orientation; new_sd->direction = sd->direction; + new_sd->custom_punct = sd->custom_punct; new_sd->para_direction = sd->para_direction; new_sd->line_breaks_valid = sd->line_breaks_valid; new_sd->justification_ops_valid = sd->justification_ops_valid; @@ -2615,27 +2714,41 @@ bool TextServerFallback::shaped_text_update_breaks(RID p_shaped) { } int sd_size = sd->glyphs.size(); + Glyph *sd_glyphs = sd->glyphs.ptrw(); + + int c_punct_size = sd->custom_punct.length(); + const char32_t *c_punct = sd->custom_punct.ptr(); + for (int i = 0; i < sd_size; i++) { - if (sd->glyphs[i].count > 0) { - char32_t c = sd->text[sd->glyphs[i].start]; - if (is_punct(c)) { - sd->glyphs.write[i].flags |= GRAPHEME_IS_PUNCTUATION; + if (sd_glyphs[i].count > 0) { + char32_t c = sd->text[sd_glyphs[i].start]; + if (c_punct_size == 0) { + if (is_punct(c)) { + sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION; + } + } else { + for (int j = 0; j < c_punct_size; j++) { + if (c_punct[j] == c) { + sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION; + break; + } + } } if (is_underscore(c)) { sd->glyphs.write[i].flags |= GRAPHEME_IS_UNDERSCORE; } if (is_whitespace(c) && !is_linebreak(c)) { - sd->glyphs.write[i].flags |= GRAPHEME_IS_SPACE; - sd->glyphs.write[i].flags |= GRAPHEME_IS_BREAK_SOFT; + sd_glyphs[i].flags |= GRAPHEME_IS_SPACE; + sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_SOFT; } if (is_linebreak(c)) { - sd->glyphs.write[i].flags |= GRAPHEME_IS_BREAK_HARD; + sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_HARD; } if (c == 0x0009 || c == 0x000b) { - sd->glyphs.write[i].flags |= GRAPHEME_IS_TAB; + sd_glyphs[i].flags |= GRAPHEME_IS_TAB; } - i += (sd->glyphs[i].count - 1); + i += (sd_glyphs[i].count - 1); } } sd->line_breaks_valid = true; diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index fb7de8f443..2f495115e0 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -142,6 +142,10 @@ class TextServerFallback : public TextServer { Dictionary variation_coordinates; float oversampling = 0.f; + uint32_t style_flags = 0; + String font_name; + String style_name; + Map<Vector2i, FontDataForSizeFallback *> cache; bool face_init = false; @@ -234,6 +238,15 @@ public: virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) override; virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) override; + virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) override; + virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const override; + + virtual void font_set_style_name(RID p_font_rid, const String &p_name) override; + virtual String font_get_style_name(RID p_font_rid) const override; + + virtual void font_set_name(RID p_font_rid, const String &p_name) override; + virtual String font_get_name(RID p_font_rid) const override; + virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) override; virtual bool font_is_antialiased(RID p_font_rid) const override; @@ -361,6 +374,9 @@ public: virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override; + virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) override; + virtual String shaped_text_get_custom_punctuation(RID p_shaped) const override; + virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index ef434f107e..4f5ae4afb0 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -673,7 +673,7 @@ void VideoStreamTheora::_bind_methods() { ClassDB::bind_method(D_METHOD("set_file", "file"), &VideoStreamTheora::set_file); ClassDB::bind_method(D_METHOD("get_file"), &VideoStreamTheora::get_file); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "file", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_file", "get_file"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "file", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_file", "get_file"); } //////////// diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 01fc7cfca0..700cc85672 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -113,7 +113,7 @@ void VisualScriptNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_default_input_values", "values"), &VisualScriptNode::_set_default_input_values); ClassDB::bind_method(D_METHOD("_get_default_input_values"), &VisualScriptNode::_get_default_input_values); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_default_input_values", "_get_default_input_values"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_default_input_values", "_get_default_input_values"); ADD_SIGNAL(MethodInfo("ports_changed")); } @@ -1172,7 +1172,7 @@ void VisualScript::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_data", "data"), &VisualScript::_set_data); ClassDB::bind_method(D_METHOD("_get_data"), &VisualScript::_get_data); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); ADD_SIGNAL(MethodInfo("node_ports_changed", PropertyInfo(Variant::INT, "id"))); } diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index b23374bfb1..7b4fbc67fc 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -1676,6 +1676,128 @@ String VisualScriptEditor::_validate_name(const String &p_name) const { return valid; } +void VisualScriptEditor::_on_nodes_copy() { + clipboard->nodes.clear(); + clipboard->data_connections.clear(); + clipboard->sequence_connections.clear(); + + for (int i = 0; i < graph->get_child_count(); i++) { + GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); + if (gn) { + if (gn->is_selected()) { + int id = gn->get_name().operator String().to_int(); + Ref<VisualScriptNode> node = script->get_node(id); + if (Object::cast_to<VisualScriptFunction>(*node)) { + EditorNode::get_singleton()->show_warning(TTR("Can't copy the function node.")); + return; + } + if (node.is_valid()) { + clipboard->nodes[id] = node->duplicate(true); + clipboard->nodes_positions[id] = script->get_node_position(id); + } + } + } + } + + if (clipboard->nodes.is_empty()) { + return; + } + + List<VisualScript::SequenceConnection> sequence_connections; + script->get_sequence_connection_list(&sequence_connections); + + for (const VisualScript::SequenceConnection &E : sequence_connections) { + if (clipboard->nodes.has(E.from_node) && clipboard->nodes.has(E.to_node)) { + clipboard->sequence_connections.insert(E); + } + } + + List<VisualScript::DataConnection> data_connections; + script->get_data_connection_list(&data_connections); + + for (const VisualScript::DataConnection &E : data_connections) { + if (clipboard->nodes.has(E.from_node) && clipboard->nodes.has(E.to_node)) { + clipboard->data_connections.insert(E); + } + } +} + +void VisualScriptEditor::_on_nodes_paste() { + if (clipboard->nodes.is_empty()) { + EditorNode::get_singleton()->show_warning(TTR("Clipboard is empty!")); + return; + } + + Map<int, int> remap; + + undo_redo->create_action(TTR("Paste VisualScript Nodes")); + int idc = script->get_available_id() + 1; + + Set<int> to_select; + + Set<Vector2> existing_positions; + + { + List<int> nodes; + script->get_node_list(&nodes); + for (int &E : nodes) { + Vector2 pos = script->get_node_position(E).snapped(Vector2(2, 2)); + existing_positions.insert(pos); + } + } + + bool first_paste = true; + Vector2 position_offset = Vector2(0, 0); + + for (KeyValue<int, Ref<VisualScriptNode>> &E : clipboard->nodes) { + Ref<VisualScriptNode> node = E.value->duplicate(); + + int new_id = idc++; + to_select.insert(new_id); + + remap[E.key] = new_id; + + Vector2 paste_pos = clipboard->nodes_positions[E.key]; + + if (first_paste) { + position_offset = _get_pos_in_graph(mouse_up_position - graph->get_global_position()) - paste_pos; + first_paste = false; + } + + paste_pos += position_offset; + + while (existing_positions.has(paste_pos.snapped(Vector2(2, 2)))) { + paste_pos += Vector2(20, 20) * EDSCALE; + } + + undo_redo->add_do_method(script.ptr(), "add_node", new_id, node, paste_pos); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); + } + + for (Set<VisualScript::SequenceConnection>::Element *E = clipboard->sequence_connections.front(); E; E = E->next()) { + undo_redo->add_do_method(script.ptr(), "sequence_connect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); + undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); + } + + for (Set<VisualScript::DataConnection>::Element *E = clipboard->data_connections.front(); E; E = E->next()) { + undo_redo->add_do_method(script.ptr(), "data_connect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); + undo_redo->add_undo_method(script.ptr(), "data_disconnect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); + } + + undo_redo->add_do_method(this, "_update_graph"); + undo_redo->add_undo_method(this, "_update_graph"); + + undo_redo->commit_action(); + + for (int i = 0; i < graph->get_child_count(); i++) { + GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); + if (gn) { + int id = gn->get_name().operator String().to_int(); + gn->set_selected(to_select.has(id)); + } + } +} + void VisualScriptEditor::_on_nodes_delete() { // Delete all the selected nodes. @@ -2073,20 +2195,20 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da Ref<VisualScriptNode> vnode; if (use_set) { - Ref<VisualScriptVariableSet> vnodes; - vnodes.instantiate(); - vnodes->set_variable(d["variable"]); - vnode = vnodes; + Ref<VisualScriptPropertySet> pset; + pset.instantiate(); + vnode = pset; } else { - Ref<VisualScriptVariableGet> vnodeg; - vnodeg.instantiate(); - vnodeg->set_variable(d["variable"]); - vnode = vnodeg; + Ref<VisualScriptPropertyGet> pget; + pget.instantiate(); + vnode = pget; } int new_id = script->get_available_id(); - undo_redo->create_action(TTR("Add Node")); + undo_redo->add_do_method(vnode.ptr(), "set_property", d["variable"]); + undo_redo->add_do_method(vnode.ptr(), "set_base_script", script->get_path()); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, vnode, pos); undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); undo_redo->add_do_method(this, "_update_graph"); @@ -2329,12 +2451,14 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da pget.instantiate(); pget->set_call_mode(VisualScriptPropertyGet::CALL_MODE_INSTANCE); pget->set_base_type(obj->get_class()); - vnode = pget; } undo_redo->add_do_method(script.ptr(), "add_node", base_id, vnode, pos); undo_redo->add_do_method(vnode.ptr(), "set_property", d["property"]); + if (!obj->get_script().is_null()) { + undo_redo->add_do_method(vnode.ptr(), "set_base_script", Ref<Script>(obj->get_script())->get_path()); + } if (!use_get) { undo_redo->add_do_method(vnode.ptr(), "set_default_input_value", 0, d["value"]); } @@ -2365,7 +2489,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da pset->set_call_mode(VisualScriptPropertySet::CALL_MODE_NODE_PATH); pset->set_base_path(sn->get_path_to(node)); } - vnode = pset; } else { Ref<VisualScriptPropertyGet> pget; @@ -2380,9 +2503,13 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } undo_redo->add_do_method(script.ptr(), "add_node", base_id, vnode, pos); undo_redo->add_do_method(vnode.ptr(), "set_property", d["property"]); + if (!obj->get_script().is_null()) { + undo_redo->add_do_method(vnode.ptr(), "set_base_script", Ref<Script>(obj->get_script())->get_path()); + } if (!use_get) { undo_redo->add_do_method(vnode.ptr(), "set_default_input_value", 0, d["value"]); } + undo_redo->add_undo_method(script.ptr(), "remove_node", base_id); undo_redo->add_do_method(this, "_update_graph"); @@ -2460,7 +2587,7 @@ void VisualScriptEditor::reload_text() { String VisualScriptEditor::get_name() { String name; - if (script->get_path().find("local://") == -1 && script->get_path().find("::") == -1) { + if (!script->is_built_in()) { name = script->get_path().get_file(); if (is_unsaved()) { if (script->get_path().is_empty()) { @@ -3739,120 +3866,15 @@ void VisualScriptEditor::_menu_option(int p_what) { case EDIT_FIND_NODE_TYPE: { _generic_search(script->get_instance_base_type()); } break; - case EDIT_COPY_NODES: + case EDIT_COPY_NODES: { + _on_nodes_copy(); + } break; case EDIT_CUT_NODES: { - clipboard->nodes.clear(); - clipboard->data_connections.clear(); - clipboard->sequence_connections.clear(); - - for (int i = 0; i < graph->get_child_count(); i++) { - GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); - if (gn) { - if (gn->is_selected()) { - int id = gn->get_name().operator String().to_int(); - Ref<VisualScriptNode> node = script->get_node(id); - if (Object::cast_to<VisualScriptFunction>(*node)) { - EditorNode::get_singleton()->show_warning(TTR("Can't copy the function node.")); - return; - } - if (node.is_valid()) { - clipboard->nodes[id] = node->duplicate(true); - clipboard->nodes_positions[id] = script->get_node_position(id); - } - } - } - } - - if (clipboard->nodes.is_empty()) { - break; - } - - List<VisualScript::SequenceConnection> sequence_connections; - script->get_sequence_connection_list(&sequence_connections); - - for (const VisualScript::SequenceConnection &E : sequence_connections) { - if (clipboard->nodes.has(E.from_node) && clipboard->nodes.has(E.to_node)) { - clipboard->sequence_connections.insert(E); - } - } - - List<VisualScript::DataConnection> data_connections; - script->get_data_connection_list(&data_connections); - - for (const VisualScript::DataConnection &E : data_connections) { - if (clipboard->nodes.has(E.from_node) && clipboard->nodes.has(E.to_node)) { - clipboard->data_connections.insert(E); - } - } - if (p_what == EDIT_CUT_NODES) { - _on_nodes_delete(); // oh yeah, also delete on cut - } - + _on_nodes_copy(); + _on_nodes_delete(); } break; case EDIT_PASTE_NODES: { - if (clipboard->nodes.is_empty()) { - EditorNode::get_singleton()->show_warning(TTR("Clipboard is empty!")); - break; - } - - Map<int, int> remap; - - undo_redo->create_action(TTR("Paste VisualScript Nodes")); - int idc = script->get_available_id() + 1; - - Set<int> to_select; - - Set<Vector2> existing_positions; - - { - List<int> nodes; - script->get_node_list(&nodes); - for (int &E : nodes) { - Vector2 pos = script->get_node_position(E).snapped(Vector2(2, 2)); - existing_positions.insert(pos); - } - } - - for (KeyValue<int, Ref<VisualScriptNode>> &E : clipboard->nodes) { - Ref<VisualScriptNode> node = E.value->duplicate(); - - int new_id = idc++; - to_select.insert(new_id); - - remap[E.key] = new_id; - - Vector2 paste_pos = clipboard->nodes_positions[E.key]; - - while (existing_positions.has(paste_pos.snapped(Vector2(2, 2)))) { - paste_pos += Vector2(20, 20) * EDSCALE; - } - - undo_redo->add_do_method(script.ptr(), "add_node", new_id, node, paste_pos); - undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); - } - - for (Set<VisualScript::SequenceConnection>::Element *E = clipboard->sequence_connections.front(); E; E = E->next()) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); - } - - for (Set<VisualScript::DataConnection>::Element *E = clipboard->data_connections.front(); E; E = E->next()) { - undo_redo->add_do_method(script.ptr(), "data_connect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); - undo_redo->add_undo_method(script.ptr(), "data_disconnect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); - } - - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - - undo_redo->commit_action(); - - for (int i = 0; i < graph->get_child_count(); i++) { - GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); - if (gn) { - int id = gn->get_name().operator String().to_int(); - gn->set_selected(to_select.has(id)); - } - } + _on_nodes_paste(); } break; case EDIT_CREATE_FUNCTION: { // Create Function. @@ -4334,6 +4356,8 @@ VisualScriptEditor::VisualScriptEditor() { graph->connect("node_selected", callable_mp(this, &VisualScriptEditor::_node_selected)); graph->connect("begin_node_move", callable_mp(this, &VisualScriptEditor::_begin_node_move)); graph->connect("end_node_move", callable_mp(this, &VisualScriptEditor::_end_node_move)); + graph->connect("copy_nodes_request", callable_mp(this, &VisualScriptEditor::_on_nodes_copy)); + graph->connect("paste_nodes_request", callable_mp(this, &VisualScriptEditor::_on_nodes_paste)); graph->connect("delete_nodes_request", callable_mp(this, &VisualScriptEditor::_on_nodes_delete)); graph->connect("duplicate_nodes_request", callable_mp(this, &VisualScriptEditor::_on_nodes_duplicate)); graph->connect("gui_input", callable_mp(this, &VisualScriptEditor::_graph_gui_input)); diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 19f5aabac9..9467c2dea4 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -253,6 +253,8 @@ class VisualScriptEditor : public ScriptEditorBase { void _node_item_selected(); void _node_item_unselected(); + void _on_nodes_copy(); + void _on_nodes_paste(); void _on_nodes_delete(); void _on_nodes_duplicate(); diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index 99b7275008..55c707890f 100644 --- a/modules/visual_script/visual_script_expression.cpp +++ b/modules/visual_script/visual_script_expression.cpp @@ -136,7 +136,7 @@ void VisualScriptExpression::_get_property_list(List<PropertyInfo> *p_list) cons argt += "," + Variant::get_type_name(Variant::Type(i)); } - p_list->push_back(PropertyInfo(Variant::STRING, "expression", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING, "expression", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); p_list->push_back(PropertyInfo(Variant::INT, "out_type", PROPERTY_HINT_ENUM, argt)); p_list->push_back(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,64,1")); p_list->push_back(PropertyInfo(Variant::BOOL, "sequenced")); diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 205918a5f0..a2ad38bf01 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -514,7 +514,7 @@ Dictionary VisualScriptFunctionCall::_get_argument_cache() const { void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const { if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } @@ -696,7 +696,7 @@ void VisualScriptFunctionCall::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "singleton"), "set_singleton", "get_singleton"); ADD_PROPERTY(PropertyInfo(Variant::INT, "basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path"); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "argument_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_argument_cache", "_get_argument_cache"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "argument_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_argument_cache", "_get_argument_cache"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "function"), "set_function", "get_function"); //when set, if loaded properly, will override argument count. ADD_PROPERTY(PropertyInfo(Variant::INT, "use_default_args"), "set_use_default_args", "get_use_default_args"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "validate"), "set_validate", "get_validate"); @@ -1282,7 +1282,7 @@ VisualScriptPropertySet::AssignOp VisualScriptPropertySet::get_assign_op() const void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } @@ -1420,7 +1420,7 @@ void VisualScriptPropertySet::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "set_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type"), "set_call_mode", "get_call_mode"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "type_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_type_cache", "_get_type_cache"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_type_cache", "_get_type_cache"); ADD_PROPERTY(PropertyInfo(Variant::INT, "basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "property"), "set_property", "get_property"); @@ -1988,7 +1988,7 @@ StringName VisualScriptPropertyGet::get_index() const { void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } @@ -2122,7 +2122,7 @@ void VisualScriptPropertyGet::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "set_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type"), "set_call_mode", "get_call_mode"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "type_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_type_cache", "_get_type_cache"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_type_cache", "_get_type_cache"); ADD_PROPERTY(PropertyInfo(Variant::INT, "basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "property"), "set_property", "get_property"); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index ef77c0cef3..471d8ef0ae 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -3415,8 +3415,8 @@ void VisualScriptConstructor::_bind_methods() { ClassDB::bind_method(D_METHOD("set_constructor", "constructor"), &VisualScriptConstructor::set_constructor); ClassDB::bind_method(D_METHOD("get_constructor"), &VisualScriptConstructor::get_constructor); - ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_constructor_type", "get_constructor_type"); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "constructor", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_constructor", "get_constructor"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_constructor_type", "get_constructor_type"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "constructor", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_constructor", "get_constructor"); } VisualScriptConstructor::VisualScriptConstructor() { @@ -3958,7 +3958,7 @@ void VisualScriptDeconstruct::_bind_methods() { } ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt), "set_deconstruct_type", "get_deconstruct_type"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "elem_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_elem_cache", "_get_elem_cache"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "elem_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_elem_cache", "_get_elem_cache"); } VisualScriptDeconstruct::VisualScriptDeconstruct() { diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp index c62de64a85..4b89c9ccd0 100644 --- a/modules/visual_script/visual_script_yield_nodes.cpp +++ b/modules/visual_script/visual_script_yield_nodes.cpp @@ -186,7 +186,7 @@ void VisualScriptYield::_bind_methods() { ClassDB::bind_method(D_METHOD("set_wait_time", "sec"), &VisualScriptYield::set_wait_time); ClassDB::bind_method(D_METHOD("get_wait_time"), &VisualScriptYield::get_wait_time); - ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Frame,Physics Frame,Time", PROPERTY_USAGE_NOEDITOR), "set_yield_mode", "get_yield_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Frame,Physics Frame,Time", PROPERTY_USAGE_NO_EDITOR), "set_yield_mode", "get_yield_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wait_time"), "set_wait_time", "get_wait_time"); BIND_ENUM_CONSTANT(YIELD_FRAME); @@ -415,7 +415,7 @@ VisualScriptYieldSignal::CallMode VisualScriptYieldSignal::get_call_mode() const void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const { if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } } diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp index e4a80c339f..d913c115d9 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp @@ -425,7 +425,7 @@ void AudioStreamOGGVorbis::_bind_methods() { ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamOGGVorbis::set_loop_offset); ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamOGGVorbis::get_loop_offset); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packet_sequence", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_packet_sequence", "get_packet_sequence"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packet_sequence", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_sequence", "get_packet_sequence"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "loop_offset"), "set_loop_offset", "get_loop_offset"); } diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle index 3fafdf8573..2a2850df0f 100644 --- a/platform/android/java/app/config.gradle +++ b/platform/android/java/app/config.gradle @@ -1,8 +1,8 @@ ext.versions = [ androidGradlePlugin: '7.0.3', compileSdk : 30, - minSdk : 19, - targetSdk : 30, + minSdk : 19, // Also update 'platform/android/java/lib/AndroidManifest.xml#minSdkVersion' value + targetSdk : 30, // Also update 'platform/android/java/lib/AndroidManifest.xml#targetSdkVersion' value buildTools : '30.0.3', kotlinVersion : '1.5.10', fragmentVersion : '1.3.6', diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml index 3034794d69..2de62271c4 100644 --- a/platform/android/java/lib/AndroidManifest.xml +++ b/platform/android/java/lib/AndroidManifest.xml @@ -4,6 +4,9 @@ android:versionCode="1" android:versionName="1.0"> + <!-- Should match the mindSdk and targetSdk values in platform/android/java/app/config.gradle --> + <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="30" /> + <application> <!-- Records the version of the Godot library --> diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp index 0559c8130f..7450215cfb 100644 --- a/platform/iphone/export/export_plugin.cpp +++ b/platform/iphone/export/export_plugin.cpp @@ -1685,8 +1685,10 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p archive_args.push_back("archive"); archive_args.push_back("-archivePath"); archive_args.push_back(archive_path); - err = OS::get_singleton()->execute("xcodebuild", archive_args); + String archive_str; + err = OS::get_singleton()->execute("xcodebuild", archive_args, &archive_str, nullptr, true); ERR_FAIL_COND_V(err, err); + print_line("xcodebuild (.xcarchive):\n" + archive_str); if (ep.step("Making .ipa", 4)) { return ERR_SKIP; @@ -1700,8 +1702,10 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p export_args.push_back("-allowProvisioningUpdates"); export_args.push_back("-exportPath"); export_args.push_back(dest_dir); - err = OS::get_singleton()->execute("xcodebuild", export_args); + String export_str; + err = OS::get_singleton()->execute("xcodebuild", export_args, &export_str, nullptr, true); ERR_FAIL_COND_V(err, err); + print_line("xcodebuild (.ipa):\n" + export_str); #else print_line(".ipa can only be built on macOS. Leaving Xcode project without building the package."); #endif diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index e98d114267..9349d378d0 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -733,6 +733,16 @@ Size2i DisplayServerX11::screen_get_size(int p_screen) const { return _screen_get_rect(p_screen).size; } +bool g_bad_window = false; +int bad_window_error_handler(Display *display, XErrorEvent *error) { + if (error->error_code == BadWindow) { + g_bad_window = true; + } else { + ERR_PRINT("Unhandled XServer error code: " + itos(error->error_code)); + } + return 0; +} + Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const { _THREAD_SAFE_METHOD_ @@ -869,7 +879,13 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const { if (desktop_valid) { use_simple_method = false; + // Handle bad window errors silently because there's no other way to check + // that one of the windows has been destroyed in the meantime. + int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&bad_window_error_handler); + for (unsigned long win_index = 0; win_index < clients_len; ++win_index) { + g_bad_window = false; + // Remove strut size from desktop size to get a more accurate result. bool strut_found = false; unsigned long strut_len = 0; @@ -881,7 +897,7 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const { } } // Fallback to older strut property. - if (!strut_found) { + if (!g_bad_window && !strut_found) { Atom strut_prop = XInternAtom(x11_display, "_NET_WM_STRUT", True); if (strut_prop != None) { if (XGetWindowProperty(x11_display, windows_data[win_index], strut_prop, 0, LONG_MAX, False, XA_CARDINAL, &type, &format, &strut_len, &remaining, &strut_data) == Success) { @@ -889,7 +905,7 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const { } } } - if (strut_found && (format == 32) && (strut_len >= 4) && strut_data) { + if (!g_bad_window && strut_found && (format == 32) && (strut_len >= 4) && strut_data) { long *struts = (long *)strut_data; long left = struts[0]; @@ -961,6 +977,9 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const { XFree(strut_data); } } + + // Restore default error handler. + XSetErrorHandler(oldHandler); } } } @@ -3666,11 +3685,18 @@ void DisplayServerX11::process_events() { } break; case KeyPress: case KeyRelease: { +#ifdef DISPLAY_SERVER_X11_DEBUG_LOGS_ENABLED + if (event.type == KeyPress) { + DEBUG_LOG_X11("[%u] KeyPress window=%lu (%u), keycode=%u, time=%lu \n", frame, event.xkey.window, window_id, event.xkey.keycode, event.xkey.time); + } else { + DEBUG_LOG_X11("[%u] KeyRelease window=%lu (%u), keycode=%u, time=%lu \n", frame, event.xkey.window, window_id, event.xkey.keycode, event.xkey.time); + } +#endif last_timestamp = event.xkey.time; // key event is a little complex, so // it will be handled in its own function. - _handle_key_event(window_id, (XKeyEvent *)&event, events, event_index); + _handle_key_event(window_id, &event.xkey, events, event_index); } break; case SelectionNotify: diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index a862f14efb..03301af0af 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -289,14 +289,6 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) { Callable::CallError ce; wd.rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce); } - - if (OS_OSX::get_singleton()->get_main_loop()) { - Main::force_redraw(); - //Event retrieval blocks until resize is over. Call Main::iteration() directly. - if (!Main::is_iterating()) { //avoid cyclic loop - Main::iteration(); - } - } } - (void)windowDidMove:(NSNotification *)notification { diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp index 1e80dcd97b..a88f7bb332 100644 --- a/platform/osx/export/export_plugin.cpp +++ b/platform/osx/export/export_plugin.cpp @@ -1048,8 +1048,21 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String 0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions 0); - Vector<uint8_t> array = FileAccess::get_file_as_array(dir.plus_file(f)); - zipWriteInFileInZip(p_zip, array.ptr(), array.size()); + FileAccessRef fa = FileAccess::open(dir.plus_file(f), FileAccess::READ); + if (!fa) { + ERR_FAIL_MSG("Can't open file to read from path '" + String(dir.plus_file(f)) + "'."); + } + const int bufsize = 16384; + uint8_t buf[bufsize]; + + while (true) { + uint64_t got = fa->get_buffer(buf, bufsize); + if (got == 0) { + break; + } + zipWriteInFileInZip(p_zip, buf, got); + } + zipCloseFileInZip(p_zip); } } diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index fc78fb28a8..7e02f4e154 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -57,6 +57,8 @@ class OS_OSX : public OS_Unix { MainLoop *main_loop; + static void pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context); + public: String open_with_filename; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 307ab03c48..45a81be80a 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -549,14 +549,31 @@ Error OS_OSX::create_process(const String &p_path, const List<String> &p_argumen } } +void OS_OSX::pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context) { + // Prevent main loop from sleeping and redraw window during resize / modal popups. + + if (get_singleton()->get_main_loop()) { + Main::force_redraw(); + if (!Main::is_iterating()) { // Avoid cyclic loop. + Main::iteration(); + } + } + + CFRunLoopWakeUp(CFRunLoopGetCurrent()); // Prevent main loop from sleeping. +} + void OS_OSX::run() { force_quit = false; - if (!main_loop) + if (!main_loop) { return; + } main_loop->initialize(); + CFRunLoopObserverRef pre_wait_observer = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, true, 0, &pre_wait_observer_cb, nullptr); + CFRunLoopAddObserver(CFRunLoopGetCurrent(), pre_wait_observer, kCFRunLoopCommonModes); + bool quit = false; while (!force_quit && !quit) { @try { @@ -572,6 +589,10 @@ void OS_OSX::run() { ERR_PRINT("NSException: " + String([exception reason].UTF8String)); } }; + + CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), pre_wait_observer, kCFRunLoopCommonModes); + CFRelease(pre_wait_observer); + main_loop->finalize(); } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 22c0219ea6..2c21390d73 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -447,7 +447,7 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, ZeroMemory(&pi.pi, sizeof(pi.pi)); LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si; - int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi); + int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi); ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command); WaitForSingleObject(pi.pi.hProcess, INFINITE); @@ -475,7 +475,7 @@ Error OS_Windows::create_process(const String &p_path, const List<String> &p_arg ZeroMemory(&pi.pi, sizeof(pi.pi)); LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si; - int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi); + int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi); ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command); ProcessID pid = pi.pi.dwProcessId; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index f73d52152e..24da2ce9ce 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -112,7 +112,13 @@ StringName AudioStreamPlayer2D::_get_actual_bus() { PhysicsDirectSpaceState2D *space_state = PhysicsServer2D::get_singleton()->space_get_direct_state(world_2d->get_space()); PhysicsDirectSpaceState2D::ShapeResult sr[MAX_INTERSECT_AREAS]; - int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask, false, true); + PhysicsDirectSpaceState2D::PointParameters point_params; + point_params.position = global_pos; + point_params.collision_mask = area_mask; + point_params.collide_with_bodies = false; + point_params.collide_with_areas = true; + + int areas = space_state->intersect_point(point_params, sr, MAX_INTERSECT_AREAS); for (int i = 0; i < areas; i++) { Area2D *area2d = Object::cast_to<Area2D>(sr[i].collider); diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 8195d98f55..b4ee85120e 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -660,7 +660,7 @@ bool Camera2D::is_margin_drawing_enabled() const { void Camera2D::_validate_property(PropertyInfo &property) const { if (!smoothing_enabled && property.name == "smoothing_speed") { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } } diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index bf26ec1f20..80c17b6e88 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -1168,7 +1168,7 @@ void CPUParticles2D::convert_from_particles(Node *p_particles) { set_color(material->get_color()); - Ref<GradientTexture> gt = material->get_color_ramp(); + Ref<GradientTexture1D> gt = material->get_color_ramp(); if (gt.is_valid()) { set_color_ramp(gt->get_gradient()); } diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 1853b3428c..66c0f979ae 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -221,7 +221,7 @@ real_t Light2D::get_shadow_smooth() const { void Light2D::_validate_property(PropertyInfo &property) const { if (!shadow && (property.name == "shadow_color" || property.name == "shadow_filter" || property.name == "shadow_filter_smooth" || property.name == "shadow_item_cull_mask")) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } } diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index 4cfc7fe89e..8802a1098a 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -46,7 +46,7 @@ void NavigationObstacle2D::_bind_methods() { void NavigationObstacle2D::_validate_property(PropertyInfo &p_property) const { if (p_property.name == "radius") { if (estimate_radius) { - p_property.usage = PROPERTY_USAGE_NOEDITOR; + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } } diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index cbf0d50c4e..bdb6cda5af 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -346,9 +346,9 @@ void NavigationPolygon::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_outlines", "outlines"), &NavigationPolygon::_set_outlines); ClassDB::bind_method(D_METHOD("_get_outlines"), &NavigationPolygon::_get_outlines); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines"); } void NavigationRegion2D::set_enabled(bool p_enabled) { diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 11790b4cda..a43d498a62 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1049,7 +1049,7 @@ void RigidDynamicBody2D::_bind_methods() { void RigidDynamicBody2D::_validate_property(PropertyInfo &property) const { if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) { if (property.name == "center_of_mass") { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } } @@ -1715,9 +1715,9 @@ void CharacterBody2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Free", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_motion_velocity", "get_motion_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_motion_velocity", "get_motion_velocity"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_max_slides", "get_max_slides"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides"); ADD_GROUP("Free Mode", "free_mode_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "free_mode_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians", PROPERTY_USAGE_DEFAULT), "set_free_mode_min_slide_angle", "get_free_mode_min_slide_angle"); @@ -1744,11 +1744,11 @@ void CharacterBody2D::_bind_methods() { void CharacterBody2D::_validate_property(PropertyInfo &property) const { if (motion_mode == MOTION_MODE_FREE) { if (property.name.begins_with("floor_") || property.name == "up_direction" || property.name == "slide_on_ceiling") { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } else { if (property.name == "free_mode_min_slide_angle") { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } } diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 510746c53f..f00959bbb6 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -92,7 +92,7 @@ bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toler void Polygon2D::_validate_property(PropertyInfo &property) const { if (!invert && property.name == "invert_border") { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } } @@ -662,7 +662,7 @@ void Polygon2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "uv"), "set_uv", "get_uv"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "vertex_colors"), "set_vertex_colors", "get_vertex_colors"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons"), "set_polygons", "get_polygons"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_bones", "_get_bones"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "_set_bones", "_get_bones"); ADD_PROPERTY(PropertyInfo(Variant::INT, "internal_vertex_count", PROPERTY_HINT_RANGE, "0,1000"), "set_internal_vertex_count", "get_internal_vertex_count"); } diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 0a8e9e2a58..7af91f3a8d 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -192,7 +192,16 @@ void RayCast2D::_update_raycast_state() { PhysicsDirectSpaceState2D::RayResult rr; bool prev_collision_state = collided; - if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, collide_with_bodies, collide_with_areas)) { + + PhysicsDirectSpaceState2D::RayParameters ray_params; + ray_params.from = gt.get_origin(); + ray_params.to = gt.xform(to); + ray_params.exclude = exclude; + ray_params.collision_mask = collision_mask; + ray_params.collide_with_bodies = collide_with_bodies; + ray_params.collide_with_areas = collide_with_areas; + + if (dss->intersect_ray(ray_params, rr)) { collided = true; against = rr.collider_id; collision_point = rr.position; diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp index 5761f19a53..b2302d09db 100644 --- a/scene/2d/sprite_2d.cpp +++ b/scene/2d/sprite_2d.cpp @@ -385,7 +385,7 @@ void Sprite2D::_validate_property(PropertyInfo &property) const { } if (!region_enabled && (property.name == "region_rect" || property.name == "region_filter_clip")) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } } diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 770cb75bab..8af7637ffd 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -2710,7 +2710,7 @@ bool TileMap::_get(const StringName &p_name, Variant &r_ret) const { } void TileMap::_get_property_list(List<PropertyInfo> *p_list) const { - p_list->push_back(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::NIL, "Layers", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (unsigned int i = 0; i < layers.size(); i++) { p_list->push_back(PropertyInfo(Variant::STRING, vformat("layer_%d/name", i), PROPERTY_HINT_NONE)); @@ -2719,7 +2719,7 @@ void TileMap::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::BOOL, vformat("layer_%d/y_sort_enabled", i), PROPERTY_HINT_NONE)); p_list->push_back(PropertyInfo(Variant::INT, vformat("layer_%d/y_sort_origin", i), PROPERTY_HINT_NONE)); p_list->push_back(PropertyInfo(Variant::INT, vformat("layer_%d/z_index", i), PROPERTY_HINT_NONE)); - p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("layer_%d/tile_data", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("layer_%d/tile_data", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } } diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index b5e4eac5d5..34f748b197 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -327,7 +327,13 @@ Area3D *AudioStreamPlayer3D::_get_overriding_area() { PhysicsDirectSpaceState3D::ShapeResult sr[MAX_INTERSECT_AREAS]; - int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask, false, true); + PhysicsDirectSpaceState3D::PointParameters point_params; + point_params.position = global_pos; + point_params.collision_mask = area_mask; + point_params.collide_with_bodies = false; + point_params.collide_with_areas = true; + + int areas = space_state->intersect_point(point_params, sr, MAX_INTERSECT_AREAS); for (int i = 0; i < areas; i++) { if (!sr[i].collider) { diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index af3b3ae5bc..cc5b7078e3 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -60,15 +60,15 @@ void Camera3D::_update_camera_mode() { void Camera3D::_validate_property(PropertyInfo &p_property) const { if (p_property.name == "fov") { if (mode != PROJECTION_PERSPECTIVE) { - p_property.usage = PROPERTY_USAGE_NOEDITOR; + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } else if (p_property.name == "size") { if (mode != PROJECTION_ORTHOGONAL && mode != PROJECTION_FRUSTUM) { - p_property.usage = PROPERTY_USAGE_NOEDITOR; + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } else if (p_property.name == "frustum_offset") { if (mode != PROJECTION_FRUSTUM) { - p_property.usage = PROPERTY_USAGE_NOEDITOR; + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index 5f13ed3c66..d347d24c2c 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -1328,7 +1328,7 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) { set_color(material->get_color()); - Ref<GradientTexture> gt = material->get_color_ramp(); + Ref<GradientTexture1D> gt = material->get_color_ramp(); if (gt.is_valid()) { set_color_ramp(gt->get_gradient()); } diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp index e3c63d62f9..c9f634a5e5 100644 --- a/scene/3d/decal.cpp +++ b/scene/3d/decal.cpp @@ -158,7 +158,7 @@ Vector<Face3> Decal::get_faces(uint32_t p_usage_flags) const { void Decal::_validate_property(PropertyInfo &property) const { if (!distance_fade_enabled && (property.name == "distance_fade_begin" || property.name == "distance_fade_length")) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } VisualInstance3D::_validate_property(property); } diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index fbdbd79c0c..5d9ae019c2 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -197,7 +197,7 @@ bool Light3D::is_editor_only() const { void Light3D::_validate_property(PropertyInfo &property) const { if (!shadow && (property.name == "shadow_color" || property.name == "shadow_bias" || property.name == "shadow_normal_bias" || property.name == "shadow_reverse_cull_face" || property.name == "shadow_transmittance_bias" || property.name == "shadow_fog_fade" || property.name == "shadow_blur")) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } if (get_light_type() != RS::LIGHT_DIRECTIONAL && property.name == "light_angular_distance") { @@ -379,12 +379,12 @@ bool DirectionalLight3D::is_sky_only() const { void DirectionalLight3D::_validate_property(PropertyInfo &property) const { if (shadow_mode == SHADOW_ORTHOGONAL && (property.name == "directional_shadow_split_1" || property.name == "directional_shadow_blend_splits")) { // Split 2 and split blending are only used with the PSSM 2 Splits and PSSM 4 Splits shadow modes. - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } if ((shadow_mode == SHADOW_ORTHOGONAL || shadow_mode == SHADOW_PARALLEL_2_SPLITS) && (property.name == "directional_shadow_split_2" || property.name == "directional_shadow_split_3")) { // Splits 3 and 4 are only used with the PSSM 4 Splits shadow mode. - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } if (property.name == "light_size" || property.name == "light_projector" || property.name == "light_specular") { diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 3bcb6add76..1b5d4ad243 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -200,9 +200,9 @@ void LightmapGIData::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_probe_data"), &LightmapGIData::_get_probe_data); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered"), "set_light_texture", "get_light_texture"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data"); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data"); } LightmapGIData::LightmapGIData() { diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp index c148f95461..ae686143e4 100644 --- a/scene/3d/mesh_instance_3d.cpp +++ b/scene/3d/mesh_instance_3d.cpp @@ -244,7 +244,7 @@ Node *MeshInstance3D::create_trimesh_collision_node() { StaticBody3D *static_body = memnew(StaticBody3D); CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(shape); - static_body->add_child(cshape); + static_body->add_child(cshape, true); return static_body; } @@ -253,7 +253,7 @@ void MeshInstance3D::create_trimesh_collision() { ERR_FAIL_COND(!static_body); static_body->set_name(String(get_name()) + "_col"); - add_child(static_body); + add_child(static_body, true); if (get_owner()) { CollisionShape3D *cshape = Object::cast_to<CollisionShape3D>(static_body->get_child(0)); static_body->set_owner(get_owner()); @@ -274,7 +274,7 @@ Node *MeshInstance3D::create_convex_collision_node(bool p_clean, bool p_simplify StaticBody3D *static_body = memnew(StaticBody3D); CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(shape); - static_body->add_child(cshape); + static_body->add_child(cshape, true); return static_body; } @@ -283,7 +283,7 @@ void MeshInstance3D::create_convex_collision(bool p_clean, bool p_simplify) { ERR_FAIL_COND(!static_body); static_body->set_name(String(get_name()) + "_col"); - add_child(static_body); + add_child(static_body, true); if (get_owner()) { CollisionShape3D *cshape = Object::cast_to<CollisionShape3D>(static_body->get_child(0)); static_body->set_owner(get_owner()); @@ -306,7 +306,7 @@ Node *MeshInstance3D::create_multiple_convex_collisions_node() { for (int i = 0; i < shapes.size(); i++) { CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(shapes[i]); - static_body->add_child(cshape); + static_body->add_child(cshape, true); } return static_body; } @@ -316,7 +316,7 @@ void MeshInstance3D::create_multiple_convex_collisions() { ERR_FAIL_COND(!static_body); static_body->set_name(String(get_name()) + "_col"); - add_child(static_body); + add_child(static_body, true); if (get_owner()) { static_body->set_owner(get_owner()); int count = static_body->get_child_count(); @@ -460,7 +460,7 @@ void MeshInstance3D::create_debug_tangents() { MeshInstance3D *mi = memnew(MeshInstance3D); mi->set_mesh(am); mi->set_name("DebugTangents"); - add_child(mi); + add_child(mi, true); #ifdef TOOLS_ENABLED if (is_inside_tree() && this == get_tree()->get_edited_scene_root()) { diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index ef15a6319e..f9fff802e0 100644 --- a/scene/3d/navigation_obstacle_3d.cpp +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -47,7 +47,7 @@ void NavigationObstacle3D::_bind_methods() { void NavigationObstacle3D::_validate_property(PropertyInfo &p_property) const { if (p_property.name == "radius") { if (estimate_radius) { - p_property.usage = PROPERTY_USAGE_NOEDITOR; + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } } diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 1265679b36..b7b88c7135 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -943,7 +943,7 @@ void Node3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_edit_mode", PROPERTY_HINT_ENUM, "Euler,Quaternion,Basis"), "set_rotation_edit_mode", "get_rotation_edit_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_order", PROPERTY_HINT_ENUM, "XYZ,XZY,YXZ,YZX,ZXY,ZYX"), "set_rotation_order", "get_rotation_order"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level"); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_transform", "get_transform"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_transform", "get_transform"); ADD_GROUP("Visibility", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "visibility_parent", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GeometryInstance3D"), "set_visibility_parent", "get_visibility_parent"); diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp index f3e174c01b..6c548edc74 100644 --- a/scene/3d/occluder_instance_3d.cpp +++ b/scene/3d/occluder_instance_3d.cpp @@ -130,8 +130,8 @@ void Occluder3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_indices", "indices"), &Occluder3D::set_indices); ClassDB::bind_method(D_METHOD("get_indices"), &Occluder3D::get_indices); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_vertices", "get_vertices"); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "indices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_indices", "get_indices"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_vertices", "get_vertices"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "indices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_indices", "get_indices"); } Occluder3D::Occluder3D() { diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index edd720117a..d0506227b4 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -1085,7 +1085,7 @@ void RigidDynamicBody3D::_bind_methods() { void RigidDynamicBody3D::_validate_property(PropertyInfo &property) const { if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) { if (property.name == "center_of_mass") { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } PhysicsBody3D::_validate_property(property); @@ -1933,8 +1933,8 @@ void CharacterBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Free", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_direction"), "set_up_direction", "get_up_direction"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_motion_velocity", "get_motion_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_max_slides", "get_max_slides"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_motion_velocity", "get_motion_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides"); ADD_GROUP("Free Mode", "free_mode_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wall_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians", PROPERTY_USAGE_DEFAULT), "set_wall_min_slide_angle", "get_wall_min_slide_angle"); ADD_GROUP("Floor", "floor_"); @@ -1960,7 +1960,7 @@ void CharacterBody3D::_bind_methods() { void CharacterBody3D::_validate_property(PropertyInfo &property) const { if (motion_mode == MOTION_MODE_FREE) { if (property.name.begins_with("floor_") || property.name == "up_direction" || property.name == "slide_on_ceiling") { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } PhysicsBody3D::_validate_property(property); diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp index fd4c6e7416..646f659996 100644 --- a/scene/3d/ray_cast_3d.cpp +++ b/scene/3d/ray_cast_3d.cpp @@ -212,9 +212,16 @@ void RayCast3D::_update_raycast_state() { to = Vector3(0, 0.01, 0); } - PhysicsDirectSpaceState3D::RayResult rr; + PhysicsDirectSpaceState3D::RayParameters ray_params; + ray_params.from = gt.get_origin(); + ray_params.to = gt.xform(to); + ray_params.exclude = exclude; + ray_params.collision_mask = collision_mask; + ray_params.collide_with_bodies = collide_with_bodies; + ray_params.collide_with_areas = collide_with_areas; - if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, collide_with_bodies, collide_with_areas)) { + PhysicsDirectSpaceState3D::RayResult rr; + if (dss->intersect_ray(ray_params, rr)) { collided = true; against = rr.collider_id; collision_point = rr.position; diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index 29c382cd05..40d4d822c9 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -185,7 +185,7 @@ Vector<Face3> ReflectionProbe::get_faces(uint32_t p_usage_flags) const { void ReflectionProbe::_validate_property(PropertyInfo &property) const { if (property.name == "interior/ambient_color" || property.name == "interior/ambient_color_energy") { if (ambient_mode != AMBIENT_COLOR) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } VisualInstance3D::_validate_property(property); diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index e3744ad5e9..d4d3c0ebe1 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -155,13 +155,13 @@ bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const { void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const { for (int i = 0; i < bones.size(); i++) { String prep = "bones/" + itos(i) + "/"; - p_list->push_back(PropertyInfo(Variant::STRING, prep + "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prep + "rest", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::QUATERNION, prep + "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING, prep + "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prep + "rest", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::QUATERNION, prep + "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } #ifndef _3D_DISABLED diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp index 116cab19b1..0b5af8823b 100644 --- a/scene/3d/spring_arm_3d.cpp +++ b/scene/3d/spring_arm_3d.cpp @@ -149,10 +149,24 @@ void SpringArm3D::process_spring() { //use camera rotation, but spring arm position Transform3D base_transform = camera->get_global_transform(); base_transform.origin = get_global_transform().origin; - get_world_3d()->get_direct_space_state()->cast_motion(camera->get_pyramid_shape_rid(), base_transform, motion, 0, motion_delta, motion_delta_unsafe, excluded_objects, mask); + + PhysicsDirectSpaceState3D::ShapeParameters shape_params; + shape_params.shape_rid = camera->get_pyramid_shape_rid(); + shape_params.transform = base_transform; + shape_params.motion = motion; + shape_params.exclude = excluded_objects; + shape_params.collision_mask = mask; + + get_world_3d()->get_direct_space_state()->cast_motion(shape_params, motion_delta, motion_delta_unsafe); } else { + PhysicsDirectSpaceState3D::RayParameters ray_params; + ray_params.from = get_global_transform().origin; + ray_params.to = get_global_transform().origin + motion; + ray_params.exclude = excluded_objects; + ray_params.collision_mask = mask; + PhysicsDirectSpaceState3D::RayResult r; - bool intersected = get_world_3d()->get_direct_space_state()->intersect_ray(get_global_transform().origin, get_global_transform().origin + motion, r, excluded_objects, mask); + bool intersected = get_world_3d()->get_direct_space_state()->intersect_ray(ray_params, r); if (intersected) { real_t dist = get_global_transform().origin.distance_to(r.position); dist -= margin; @@ -160,7 +174,14 @@ void SpringArm3D::process_spring() { } } } else { - get_world_3d()->get_direct_space_state()->cast_motion(shape->get_rid(), get_global_transform(), motion, 0, motion_delta, motion_delta_unsafe, excluded_objects, mask); + PhysicsDirectSpaceState3D::ShapeParameters shape_params; + shape_params.shape_rid = shape->get_rid(); + shape_params.transform = get_global_transform(); + shape_params.motion = motion; + shape_params.exclude = excluded_objects; + shape_params.collision_mask = mask; + + get_world_3d()->get_direct_space_state()->cast_motion(shape_params, motion_delta, motion_delta_unsafe); } current_spring_length = spring_length * motion_delta; diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index 61cba17cde..90db093137 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -407,7 +407,13 @@ real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState3D *s) { PhysicsDirectSpaceState3D *ss = s->get_space_state(); - bool col = ss->intersect_ray(source, target, rr, exclude, get_collision_mask()); + PhysicsDirectSpaceState3D::RayParameters ray_params; + ray_params.from = source; + ray_params.to = target; + ray_params.exclude = exclude; + ray_params.collision_mask = get_collision_mask(); + + bool col = ss->intersect_ray(ray_params, rr); wheel.m_raycastInfo.m_groundObject = nullptr; diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp index f0cf8f5016..c7108cbae0 100644 --- a/scene/3d/voxel_gi.cpp +++ b/scene/3d/voxel_gi.cpp @@ -225,7 +225,7 @@ void VoxelGIData::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_data", "data"), &VoxelGIData::_set_data); ClassDB::bind_method(D_METHOD("_get_data"), &VoxelGIData::_get_data); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_dynamic_range", "get_dynamic_range"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_energy", "get_energy"); @@ -403,7 +403,7 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) { if (p_create_visual_debug) { MultiMeshInstance3D *mmi = memnew(MultiMeshInstance3D); mmi->set_multimesh(baker.create_debug_multimesh()); - add_child(mmi); + add_child(mmi, true); #ifdef TOOLS_ENABLED if (is_inside_tree() && get_tree()->get_edited_scene_root() == this) { mmi->set_owner(this); diff --git a/scene/animation/animation_blend_space_1d.cpp b/scene/animation/animation_blend_space_1d.cpp index 0167992baf..9a71e7bf55 100644 --- a/scene/animation/animation_blend_space_1d.cpp +++ b/scene/animation/animation_blend_space_1d.cpp @@ -81,14 +81,14 @@ void AnimationNodeBlendSpace1D::_bind_methods() { ClassDB::bind_method(D_METHOD("_add_blend_point", "index", "node"), &AnimationNodeBlendSpace1D::_add_blend_point); for (int i = 0; i < MAX_BLEND_POINTS; i++) { - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "blend_point_" + itos(i) + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_add_blend_point", "get_blend_point_node", i); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "blend_point_" + itos(i) + "/pos", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_blend_point_position", "get_blend_point_position", i); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "blend_point_" + itos(i) + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_add_blend_point", "get_blend_point_node", i); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "blend_point_" + itos(i) + "/pos", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_blend_point_position", "get_blend_point_position", i); } - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_min_space", "get_min_space"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_max_space", "get_max_space"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_snap", "get_snap"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "value_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_value_label", "get_value_label"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_min_space", "get_min_space"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_space", "get_max_space"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_snap", "get_snap"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "value_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_value_label", "get_value_label"); } void AnimationNodeBlendSpace1D::get_child_nodes(List<ChildNode> *r_child_nodes) { diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index 145e7c605b..b91a2869e4 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -639,21 +639,21 @@ void AnimationNodeBlendSpace2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_triangles"), &AnimationNodeBlendSpace2D::_update_triangles); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_auto_triangles", "get_auto_triangles"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_auto_triangles", "get_auto_triangles"); for (int i = 0; i < MAX_BLEND_POINTS; i++) { - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "blend_point_" + itos(i) + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_add_blend_point", "get_blend_point_node", i); - ADD_PROPERTYI(PropertyInfo(Variant::VECTOR2, "blend_point_" + itos(i) + "/pos", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_blend_point_position", "get_blend_point_position", i); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "blend_point_" + itos(i) + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_add_blend_point", "get_blend_point_node", i); + ADD_PROPERTYI(PropertyInfo(Variant::VECTOR2, "blend_point_" + itos(i) + "/pos", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_blend_point_position", "get_blend_point_position", i); } - ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_triangles", "_get_triangles"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_triangles", "_get_triangles"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "min_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_min_space", "get_min_space"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_max_space", "get_max_space"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_snap", "get_snap"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "x_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_x_label", "get_x_label"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "y_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_y_label", "get_y_label"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry", PROPERTY_USAGE_NOEDITOR), "set_blend_mode", "get_blend_mode"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "min_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_min_space", "get_min_space"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_space", "get_max_space"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_snap", "get_snap"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "x_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_x_label", "get_x_label"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "y_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_y_label", "get_y_label"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry", PROPERTY_USAGE_NO_EDITOR), "set_blend_mode", "get_blend_mode"); ADD_SIGNAL(MethodInfo("triangles_updated")); BIND_ENUM_CONSTANT(BLEND_MODE_INTERPOLATED); diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 10a66386eb..d18e1a92d8 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -1112,12 +1112,12 @@ void AnimationNodeBlendTree::_get_property_list(List<PropertyInfo> *p_list) cons for (const StringName &E : names) { String name = E; if (name != "output") { - p_list->push_back(PropertyInfo(Variant::OBJECT, "nodes/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "nodes/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NO_EDITOR)); } - p_list->push_back(PropertyInfo(Variant::VECTOR2, "nodes/" + name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "nodes/" + name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } - p_list->push_back(PropertyInfo(Variant::ARRAY, "node_connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "node_connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } void AnimationNodeBlendTree::reset_state() { @@ -1152,7 +1152,7 @@ void AnimationNodeBlendTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_graph_offset", "offset"), &AnimationNodeBlendTree::set_graph_offset); ClassDB::bind_method(D_METHOD("get_graph_offset"), &AnimationNodeBlendTree::get_graph_offset); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_graph_offset", "get_graph_offset"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_graph_offset", "get_graph_offset"); BIND_CONSTANT(CONNECTION_OK); BIND_CONSTANT(CONNECTION_ERROR_NO_INPUT); diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 81ecb50ea0..b5d7a0555e 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -909,14 +909,14 @@ void AnimationNodeStateMachine::_get_property_list(List<PropertyInfo> *p_list) c names.sort_custom<StringName::AlphCompare>(); for (const StringName &name : names) { - p_list->push_back(PropertyInfo(Variant::OBJECT, "states/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "states/" + name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "states/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "states/" + name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } - p_list->push_back(PropertyInfo(Variant::ARRAY, "transitions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::STRING_NAME, "start_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::STRING_NAME, "end_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "transitions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING_NAME, "start_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING_NAME, "end_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } void AnimationNodeStateMachine::reset_state() { diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 26caf826a7..f91422ac1a 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -174,9 +174,9 @@ void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const { List<PropertyInfo> anim_names; for (const KeyValue<StringName, AnimationData> &E : animation_set) { - anim_names.push_back(PropertyInfo(Variant::OBJECT, "anims/" + String(E.key), PROPERTY_HINT_RESOURCE_TYPE, "Animation", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE)); + anim_names.push_back(PropertyInfo(Variant::OBJECT, "anims/" + String(E.key), PROPERTY_HINT_RESOURCE_TYPE, "Animation", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE)); if (E.value.next != StringName()) { - anim_names.push_back(PropertyInfo(Variant::STRING, "next/" + String(E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + anim_names.push_back(PropertyInfo(Variant::STRING, "next/" + String(E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } } @@ -186,7 +186,7 @@ void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(E); } - p_list->push_back(PropertyInfo(Variant::ARRAY, "blend_times", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "blend_times", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } void AnimationPlayer::advance(float p_time) { @@ -1813,7 +1813,7 @@ void AnimationPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_node"), "set_root", "get_root"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "current_animation", PROPERTY_HINT_ENUM, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ANIMATE_AS_TRIGGER), "set_current_animation", "get_current_animation"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "assigned_animation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_assigned_animation", "get_assigned_animation"); - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "autoplay", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_autoplay", "get_autoplay"); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "autoplay", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_autoplay", "get_autoplay"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reset_on_save", PROPERTY_HINT_NONE, ""), "set_reset_on_save_enabled", "is_reset_on_save_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "current_animation_length", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_current_animation_length"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "current_animation_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_current_animation_position"); diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index ccb5fa9472..4b71fe7a01 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -425,8 +425,8 @@ void AnimationNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_parameter", "name", "value"), &AnimationNode::set_parameter); ClassDB::bind_method(D_METHOD("get_parameter", "name"), &AnimationNode::get_parameter); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_filter_enabled", "is_filter_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "filters", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_filters", "_get_filters"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_filter_enabled", "is_filter_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "filters", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_filters", "_get_filters"); GDVIRTUAL_BIND(_get_child_nodes); GDVIRTUAL_BIND(_get_parameter_list); diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index cf2df4e1a2..cb9f13e970 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -354,7 +354,7 @@ MarginContainer *VBoxContainer::add_margin_child(const String &p_label, Control add_child(l, false, INTERNAL_MODE_FRONT); MarginContainer *mc = memnew(MarginContainer); mc->add_theme_constant_override("margin_left", 0); - mc->add_child(p_control); + mc->add_child(p_control, true); add_child(mc, false, INTERNAL_MODE_FRONT); if (p_expand) { mc->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index 5d024d3be7..e5b23d8006 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -39,6 +39,10 @@ GradientEdit::GradientEdit() { picker = memnew(ColorPicker); popup->add_child(picker); + gradient_cache.instantiate(); + preview_texture.instantiate(); + + preview_texture->set_width(1024); add_child(popup, false, INTERNAL_MODE_FRONT); } @@ -47,7 +51,7 @@ int GradientEdit::_get_point_from_pos(int x) { int total_w = get_size().width - get_size().height - draw_spacing; float min_distance = 1e20; for (int i = 0; i < points.size(); i++) { - //Check if we clicked at point + // Check if we clicked at point. float distance = ABS(x - points[i].offset * total_w); float min = (draw_point_width / 2 * 1.7); //make it easier to grab if (distance <= min && distance < min_distance) { @@ -94,14 +98,14 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; - //Show color picker on double click. + // Show color picker on double click. if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_double_click() && mb->is_pressed()) { grabbed = _get_point_from_pos(mb->get_position().x); _show_color_picker(); accept_event(); } - //Delete point on right click + // Delete point on right click. if (mb.is_valid() && mb->get_button_index() == 2 && mb->is_pressed()) { grabbed = _get_point_from_pos(mb->get_position().x); if (grabbed != -1) { @@ -114,20 +118,20 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { } } - //Hold alt key to duplicate selected color + // Hold alt key to duplicate selected color. if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && mb->is_alt_pressed()) { int x = mb->get_position().x; grabbed = _get_point_from_pos(x); if (grabbed != -1) { int total_w = get_size().width - get_size().height - draw_spacing; - Gradient::Point newPoint = points[grabbed]; - newPoint.offset = CLAMP(x / float(total_w), 0, 1); + Gradient::Point new_point = points[grabbed]; + new_point.offset = CLAMP(x / float(total_w), 0, 1); - points.push_back(newPoint); + points.push_back(new_point); points.sort(); for (int i = 0; i < points.size(); ++i) { - if (points[i].offset == newPoint.offset) { + if (points[i].offset == new_point.offset) { grabbed = i; break; } @@ -138,7 +142,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { } } - //select + // Select. if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { update(); int x = mb->get_position().x; @@ -158,16 +162,16 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { return; } - //insert - Gradient::Point newPoint; - newPoint.offset = CLAMP(x / float(total_w), 0, 1); + // Insert point. + Gradient::Point new_point; + new_point.offset = CLAMP(x / float(total_w), 0, 1); Gradient::Point prev; Gradient::Point next; int pos = -1; for (int i = 0; i < points.size(); i++) { - if (points[i].offset < newPoint.offset) { + if (points[i].offset < new_point.offset) { pos = i; } } @@ -191,12 +195,12 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { prev = points[pos]; } - newPoint.color = prev.color.lerp(next.color, (newPoint.offset - prev.offset) / (next.offset - prev.offset)); + new_point.color = prev.color.lerp(next.color, (new_point.offset - prev.offset) / (next.offset - prev.offset)); - points.push_back(newPoint); + points.push_back(new_point); points.sort(); for (int i = 0; i < points.size(); i++) { - if (points[i].offset == newPoint.offset) { + if (points[i].offset == new_point.offset) { grabbed = i; break; } @@ -223,7 +227,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { float newofs = CLAMP(x / float(total_w), 0, 1); // Snap to "round" coordinates if holding Ctrl. - // Be more precise if holding Shift as well + // Be more precise if holding Shift as well. if (mm->is_ctrl_pressed()) { newofs = Math::snapped(newofs, mm->is_shift_pressed() ? 0.025 : 0.1); } else if (mm->is_shift_pressed()) { @@ -299,57 +303,22 @@ void GradientEdit::_notification(int p_what) { int h = get_size().y; if (w == 0 || h == 0) { - return; //Safety check. We have division by 'h'. And in any case there is nothing to draw with such size + return; // Safety check. We have division by 'h'. And in any case there is nothing to draw with such size. } int total_w = get_size().width - get_size().height - draw_spacing; - //Draw checker pattern for ramp + // Draw checker pattern for ramp. draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(0, 0, total_w, h), true); - //Draw color ramp - Gradient::Point prev; - prev.offset = 0; - if (points.size() == 0) { - prev.color = Color(0, 0, 0); //Draw black rectangle if we have no points - } else { - prev.color = points[0].color; //Extend color of first point to the beginning. - } + // Draw color ramp. - for (int i = -1; i < points.size(); i++) { - Gradient::Point next; - //If there is no next point - if (i + 1 == points.size()) { - if (points.size() == 0) { - next.color = Color(0, 0, 0); //Draw black rectangle if we have no points - } else { - next.color = points[i].color; //Extend color of last point to the end. - } - next.offset = 1; - } else { - next = points[i + 1]; - } + gradient_cache->set_points(points); + gradient_cache->set_interpolation_mode(interpolation_mode); + preview_texture->set_gradient(gradient_cache); + draw_texture_rect(preview_texture, Rect2(0, 0, total_w, h)); - if (prev.offset == next.offset) { - prev = next; - continue; - } - - Vector<Vector2> points; - Vector<Color> colors; - points.push_back(Vector2(prev.offset * total_w, h)); - points.push_back(Vector2(prev.offset * total_w, 0)); - points.push_back(Vector2(next.offset * total_w, 0)); - points.push_back(Vector2(next.offset * total_w, h)); - colors.push_back(prev.color); - colors.push_back(prev.color); - colors.push_back(next.color); - colors.push_back(next.color); - draw_primitive(points, colors, Vector<Point2>()); - prev = next; - } - - //Draw point markers + // Draw point markers. for (int i = 0; i < points.size(); i++) { Color col = points[i].color.inverted(); col.a = 0.9; @@ -383,7 +352,7 @@ void GradientEdit::_notification(int p_what) { draw_line(Vector2(total_w + draw_spacing, h), Vector2(total_w + draw_spacing + h, 0), Color(1, 1, 1, 0.6)); } - //Draw borders around color ramp if in focus + // Draw borders around color ramp if in focus. if (has_focus()) { draw_line(Vector2(-1, -1), Vector2(total_w + 1, -1), Color(1, 1, 1, 0.6)); draw_line(Vector2(total_w + 1, -1), Vector2(total_w + 1, h + 1), Color(1, 1, 1, 0.6)); @@ -448,12 +417,21 @@ void GradientEdit::set_points(Vector<Gradient::Point> &p_points) { } points.clear(); points = p_points; + points.sort(); } Vector<Gradient::Point> &GradientEdit::get_points() { return points; } +void GradientEdit::set_interpolation_mode(Gradient::InterpolationMode p_interp_mode) { + interpolation_mode = p_interp_mode; +} + +Gradient::InterpolationMode GradientEdit::get_interpolation_mode() { + return interpolation_mode; +} + void GradientEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("ramp_changed")); } diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h index f3a39daaf6..66b60d87c7 100644 --- a/scene/gui/gradient_edit.h +++ b/scene/gui/gradient_edit.h @@ -45,6 +45,10 @@ class GradientEdit : public Control { bool grabbing = false; int grabbed = -1; Vector<Gradient::Point> points; + Gradient::InterpolationMode interpolation_mode = Gradient::GRADIENT_INTERPOLATE_LINEAR; + + Ref<Gradient> gradient_cache; + Ref<GradientTexture1D> preview_texture; // Make sure to use the scaled value below. const int BASE_SPACING = 3; @@ -69,6 +73,9 @@ public: Vector<Color> get_colors() const; void set_points(Vector<Gradient::Point> &p_points); Vector<Gradient::Point> &get_points(); + void set_interpolation_mode(Gradient::InterpolationMode p_interp_mode); + Gradient::InterpolationMode get_interpolation_mode(); + virtual Size2 get_minimum_size() const override; GradientEdit(); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 4215c9aff4..8470003b3e 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "item_list.h" + #include "core/config/project_settings.h" #include "core/os/os.h" #include "core/string/translation.h" @@ -1605,7 +1606,7 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("move_item", "from_idx", "to_idx"), &ItemList::move_item); - ClassDB::bind_method(D_METHOD("set_item_count"), &ItemList::set_item_count); + ClassDB::bind_method(D_METHOD("set_item_count", "count"), &ItemList::set_item_count); ClassDB::bind_method(D_METHOD("get_item_count"), &ItemList::get_item_count); ClassDB::bind_method(D_METHOD("remove_item", "idx"), &ItemList::remove_item); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index b8cb618171..50908f6a77 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -243,11 +243,9 @@ inline void draw_glyph_outline(const Glyph &p_gl, const RID &p_canvas, const Col if (p_gl.font_rid != RID()) { if (p_font_shadow_color.a > 0) { TS->font_draw_glyph(p_gl.font_rid, p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + shadow_ofs, p_gl.index, p_font_shadow_color); - if (p_shadow_outline_size > 0) { - TS->font_draw_glyph_outline(p_gl.font_rid, p_canvas, p_gl.font_size, p_shadow_outline_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + Vector2(-shadow_ofs.x, shadow_ofs.y), p_gl.index, p_font_shadow_color); - TS->font_draw_glyph_outline(p_gl.font_rid, p_canvas, p_gl.font_size, p_shadow_outline_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + Vector2(shadow_ofs.x, -shadow_ofs.y), p_gl.index, p_font_shadow_color); - TS->font_draw_glyph_outline(p_gl.font_rid, p_canvas, p_gl.font_size, p_shadow_outline_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + Vector2(-shadow_ofs.x, -shadow_ofs.y), p_gl.index, p_font_shadow_color); - } + } + if (p_font_shadow_color.a > 0 && p_shadow_outline_size > 0) { + TS->font_draw_glyph_outline(p_gl.font_rid, p_canvas, p_gl.font_size, p_shadow_outline_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + shadow_ofs, p_gl.index, p_font_shadow_color); } if (p_font_outline_color.a != 0.0 && p_outline_size > 0) { TS->font_draw_glyph_outline(p_gl.font_rid, p_canvas, p_gl.font_size, p_outline_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off), p_gl.index, p_font_outline_color); @@ -397,7 +395,7 @@ void Label::_notification(int p_what) { int ellipsis_gl_size = TS->shaped_text_get_ellipsis_glyph_count(lines_rid[i]); // Draw outline. Note: Do not merge this into the single loop with the main text, to prevent overlaps. - if (font_shadow_color.a > 0 || (font_outline_color.a != 0.0 && outline_size > 0)) { + if ((outline_size > 0 && font_outline_color.a != 0) || (font_shadow_color.a != 0)) { Vector2 offset = ofs; // Draw RTL ellipsis string when necessary. if (rtl && ellipsis_pos >= 0) { diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 8c33d306a1..15fd22ced5 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -664,7 +664,9 @@ void LineEdit::_notification(int p_what) { } Ref<Font> font = get_theme_font(SNAME("font")); - style->draw(ci, Rect2(Point2(), size)); + if (!flat) { + style->draw(ci, Rect2(Point2(), size)); + } if (has_focus()) { get_theme_stylebox(SNAME("focus"))->draw(ci, Rect2(Point2(), size)); @@ -1966,6 +1968,17 @@ Ref<Texture2D> LineEdit::get_right_icon() { return right_icon; } +void LineEdit::set_flat(bool p_enabled) { + if (flat != p_enabled) { + flat = p_enabled; + update(); + } +} + +bool LineEdit::is_flat() const { + return flat; +} + void LineEdit::_text_changed() { _emit_text_change(); _clear_redo(); @@ -2135,7 +2148,7 @@ void LineEdit::_get_property_list(List<PropertyInfo> *p_list) const { void LineEdit::_validate_property(PropertyInfo &property) const { if (!caret_blink_enabled && property.name == "caret_blink_speed") { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } } @@ -2214,6 +2227,8 @@ void LineEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("is_deselect_on_focus_loss_enabled"), &LineEdit::is_deselect_on_focus_loss_enabled); ClassDB::bind_method(D_METHOD("set_right_icon", "icon"), &LineEdit::set_right_icon); ClassDB::bind_method(D_METHOD("get_right_icon"), &LineEdit::get_right_icon); + ClassDB::bind_method(D_METHOD("set_flat", "enabled"), &LineEdit::set_flat); + ClassDB::bind_method(D_METHOD("is_flat"), &LineEdit::is_flat); ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "new_text"))); ADD_SIGNAL(MethodInfo("text_change_rejected", PropertyInfo(Variant::STRING, "rejected_substring"))); @@ -2269,6 +2284,7 @@ void LineEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_on_focus_loss_enabled"), "set_deselect_on_focus_loss_enabled", "is_deselect_on_focus_loss_enabled"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_right_icon", "get_right_icon"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_control_chars"), "set_draw_control_chars", "get_draw_control_chars"); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 3364e02e01..2ec7f08865 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -130,6 +130,7 @@ private: bool middle_mouse_paste_enabled = true; Ref<Texture2D> right_icon; + bool flat = false; struct Selection { int begin = 0; @@ -332,6 +333,9 @@ public: void set_right_icon(const Ref<Texture2D> &p_icon); Ref<Texture2D> get_right_icon(); + void set_flat(bool p_enabled); + bool is_flat() const; + virtual bool is_text_field() const override; void show_virtual_keyboard(); diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index ceb2092e3a..39c7b04955 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -110,14 +110,6 @@ PopupMenu *MenuButton::get_popup() const { return popup; } -void MenuButton::_set_items(const Array &p_items) { - popup->set("items", p_items); -} - -Array MenuButton::_get_items() const { - return popup->get("items"); -} - void MenuButton::set_switch_on_hover(bool p_enabled) { switch_on_hover = p_enabled; } @@ -126,6 +118,16 @@ bool MenuButton::is_switch_on_hover() { return switch_on_hover; } +void MenuButton::set_item_count(int p_count) { + ERR_FAIL_COND(p_count < 0); + popup->set_item_count(p_count); + notify_property_list_changed(); +} + +int MenuButton::get_item_count() const { + return popup->get_item_count(); +} + void MenuButton::_notification(int p_what) { switch (p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { @@ -146,16 +148,66 @@ void MenuButton::_notification(int p_what) { } } +bool MenuButton::_set(const StringName &p_name, const Variant &p_value) { + Vector<String> components = String(p_name).split("/", true, 2); + if (components.size() >= 2 && components[0] == "popup") { + bool valid; + popup->set(String(p_name).trim_prefix("popup/"), p_value, &valid); + return valid; + } + return false; +} + +bool MenuButton::_get(const StringName &p_name, Variant &r_ret) const { + Vector<String> components = String(p_name).split("/", true, 2); + if (components.size() >= 2 && components[0] == "popup") { + bool valid; + r_ret = popup->get(String(p_name).trim_prefix("popup/"), &valid); + return valid; + } + return false; +} + +void MenuButton::_get_property_list(List<PropertyInfo> *p_list) const { + for (int i = 0; i < popup->get_item_count(); i++) { + p_list->push_back(PropertyInfo(Variant::STRING, vformat("popup/item_%d/text", i))); + + PropertyInfo pi = PropertyInfo(Variant::OBJECT, vformat("popup/item_%d/icon", i), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"); + pi.usage &= ~(popup->get_item_icon(i).is_null() ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::INT, vformat("popup/item_%d/checkable", i), PROPERTY_HINT_ENUM, "No,As checkbox,As radio button"); + pi.usage &= ~(!popup->is_item_checkable(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/checked", i)); + pi.usage &= ~(!popup->is_item_checked(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::INT, vformat("popup/item_%d/id", i), PROPERTY_HINT_RANGE, "1,10,1,or_greater"); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/disabled", i)); + pi.usage &= ~(!popup->is_item_disabled(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/separator", i)); + pi.usage &= ~(!popup->is_item_separator(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + } +} + void MenuButton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_popup"), &MenuButton::get_popup); - ClassDB::bind_method(D_METHOD("_set_items"), &MenuButton::_set_items); - ClassDB::bind_method(D_METHOD("_get_items"), &MenuButton::_get_items); ClassDB::bind_method(D_METHOD("set_switch_on_hover", "enable"), &MenuButton::set_switch_on_hover); ClassDB::bind_method(D_METHOD("is_switch_on_hover"), &MenuButton::is_switch_on_hover); ClassDB::bind_method(D_METHOD("set_disable_shortcuts", "disabled"), &MenuButton::set_disable_shortcuts); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); + ClassDB::bind_method(D_METHOD("set_item_count", "count"), &MenuButton::set_item_count); + ClassDB::bind_method(D_METHOD("get_item_count"), &MenuButton::get_item_count); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "switch_on_hover"), "set_switch_on_hover", "is_switch_on_hover"); + ADD_ARRAY_COUNT("Items", "items_count", "set_item_count", "get_item_count", "popup/item_"); ADD_SIGNAL(MethodInfo("about_to_popup")); } diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h index 730495b65d..455b7dc870 100644 --- a/scene/gui/menu_button.h +++ b/scene/gui/menu_button.h @@ -44,15 +44,15 @@ class MenuButton : public Button { Vector2i mouse_pos_adjusted; - Array _get_items() const; - void _set_items(const Array &p_items); - virtual void gui_input(const Ref<InputEvent> &p_event) override; void _popup_visibility_changed(bool p_visible); protected: void _notification(int p_what); + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; static void _bind_methods(); virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override; @@ -64,6 +64,9 @@ public: bool is_switch_on_hover(); void set_disable_shortcuts(bool p_disabled); + void set_item_count(int p_count); + int get_item_count() const; + MenuButton(); ~MenuButton(); }; diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index c00c040048..dcf3cfeb09 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -332,7 +332,7 @@ void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_items"), &OptionButton::_set_items); ClassDB::bind_method(D_METHOD("_get_items"), &OptionButton::_get_items); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); // "selected" property must come after "items", otherwise GH-10213 occurs. ADD_PROPERTY(PropertyInfo(Variant::INT, "selected"), "_select_int", "get_selected"); ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "index"))); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index c0a559e624..54af9f3885 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -820,6 +820,7 @@ void PopupMenu::add_item(const String &p_label, int p_id, uint32_t p_accel) { _shape_item(items.size() - 1); control->update(); child_controls_changed(); + notify_property_list_changed(); } void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, uint32_t p_accel) { @@ -830,6 +831,7 @@ void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_labe _shape_item(items.size() - 1); control->update(); child_controls_changed(); + notify_property_list_changed(); } void PopupMenu::add_check_item(const String &p_label, int p_id, uint32_t p_accel) { @@ -1271,6 +1273,14 @@ int PopupMenu::get_current_index() const { return mouse_over; } +void PopupMenu::set_item_count(int p_count) { + ERR_FAIL_COND(p_count < 0); + items.resize(p_count); + control->update(); + child_controls_changed(); + notify_property_list_changed(); +} + int PopupMenu::get_item_count() const { return items.size(); } @@ -1420,27 +1430,7 @@ void PopupMenu::clear() { mouse_over = -1; control->update(); child_controls_changed(); -} - -Array PopupMenu::_get_items() const { - Array items; - for (int i = 0; i < get_item_count(); i++) { - items.push_back(get_item_text(i)); - items.push_back(get_item_icon(i)); - // For compatibility, use false/true for no/checkbox and integers for other values - int ct = this->items[i].checkable_type; - items.push_back(Variant(ct <= Item::CHECKABLE_TYPE_CHECK_BOX ? is_item_checkable(i) : ct)); - items.push_back(is_item_checked(i)); - items.push_back(is_item_disabled(i)); - - items.push_back(get_item_id(i)); - items.push_back(get_item_accelerator(i)); - items.push_back(get_item_metadata(i)); - items.push_back(get_item_submenu(i)); - items.push_back(is_item_separator(i)); - } - - return items; + notify_property_list_changed(); } void PopupMenu::_ref_shortcut(Ref<Shortcut> p_sc) { @@ -1461,45 +1451,6 @@ void PopupMenu::_unref_shortcut(Ref<Shortcut> p_sc) { } } -void PopupMenu::_set_items(const Array &p_items) { - ERR_FAIL_COND(p_items.size() % 10); - clear(); - - for (int i = 0; i < p_items.size(); i += 10) { - String text = p_items[i + 0]; - Ref<Texture2D> icon = p_items[i + 1]; - // For compatibility, use false/true for no/checkbox and integers for other values - bool checkable = p_items[i + 2]; - bool radio_checkable = (int)p_items[i + 2] == Item::CHECKABLE_TYPE_RADIO_BUTTON; - bool checked = p_items[i + 3]; - bool disabled = p_items[i + 4]; - - int id = p_items[i + 5]; - int accel = p_items[i + 6]; - Variant meta = p_items[i + 7]; - String subm = p_items[i + 8]; - bool sep = p_items[i + 9]; - - int idx = get_item_count(); - add_item(text, id); - set_item_icon(idx, icon); - if (checkable) { - if (radio_checkable) { - set_item_as_radio_checkable(idx, true); - } else { - set_item_as_checkable(idx, true); - } - } - set_item_checked(idx, checked); - set_item_disabled(idx, disabled); - set_item_id(idx, id); - set_item_metadata(idx, meta); - set_item_as_separator(idx, sep); - set_item_accelerator(idx, accel); - set_item_submenu(idx, subm); - } -} - // Hide on item selection determines whether or not the popup will close after item selection void PopupMenu::set_hide_on_item_selection(bool p_enabled) { hide_on_item_selection = p_enabled; @@ -1581,6 +1532,145 @@ void PopupMenu::take_mouse_focus() { } } +bool PopupMenu::_set(const StringName &p_name, const Variant &p_value) { + Vector<String> components = String(p_name).split("/", true, 2); + if (components.size() >= 2 && components[0].begins_with("item_") && components[0].trim_prefix("item_").is_valid_int()) { + int item_index = components[0].trim_prefix("item_").to_int(); + String property = components[1]; + if (property == "text") { + set_item_text(item_index, p_value); + return true; + } else if (property == "icon") { + set_item_icon(item_index, p_value); + return true; + } else if (property == "checkable") { + bool radio_checkable = (int)p_value == Item::CHECKABLE_TYPE_RADIO_BUTTON; + if (radio_checkable) { + set_item_as_radio_checkable(item_index, true); + } else { + bool checkable = p_value; + set_item_as_checkable(item_index, checkable); + } + return true; + } else if (property == "checked") { + set_item_checked(item_index, p_value); + return true; + } else if (property == "id") { + set_item_id(item_index, p_value); + return true; + } else if (components[1] == "disabled") { + set_item_disabled(item_index, p_value); + return true; + } else if (property == "separator") { + set_item_as_separator(item_index, p_value); + return true; + } + } +#ifndef DISABLE_DEPRECATED + // Compatibility. + if (p_name == "items") { + Array arr = p_value; + ERR_FAIL_COND_V(arr.size() % 10, false); + clear(); + + for (int i = 0; i < arr.size(); i += 10) { + String text = arr[i + 0]; + Ref<Texture2D> icon = arr[i + 1]; + // For compatibility, use false/true for no/checkbox and integers for other values + bool checkable = arr[i + 2]; + bool radio_checkable = (int)arr[i + 2] == Item::CHECKABLE_TYPE_RADIO_BUTTON; + bool checked = arr[i + 3]; + bool disabled = arr[i + 4]; + + int id = arr[i + 5]; + int accel = arr[i + 6]; + Variant meta = arr[i + 7]; + String subm = arr[i + 8]; + bool sep = arr[i + 9]; + + int idx = get_item_count(); + add_item(text, id); + set_item_icon(idx, icon); + if (checkable) { + if (radio_checkable) { + set_item_as_radio_checkable(idx, true); + } else { + set_item_as_checkable(idx, true); + } + } + set_item_checked(idx, checked); + set_item_disabled(idx, disabled); + set_item_id(idx, id); + set_item_metadata(idx, meta); + set_item_as_separator(idx, sep); + set_item_accelerator(idx, accel); + set_item_submenu(idx, subm); + } + } +#endif + return false; +} + +bool PopupMenu::_get(const StringName &p_name, Variant &r_ret) const { + Vector<String> components = String(p_name).split("/", true, 2); + if (components.size() >= 2 && components[0].begins_with("item_") && components[0].trim_prefix("item_").is_valid_int()) { + int item_index = components[0].trim_prefix("item_").to_int(); + String property = components[1]; + if (property == "text") { + r_ret = get_item_text(item_index); + return true; + } else if (property == "icon") { + r_ret = get_item_icon(item_index); + return true; + } else if (property == "checkable") { + r_ret = this->items[item_index].checkable_type; + return true; + } else if (property == "checked") { + r_ret = is_item_checked(item_index); + return true; + } else if (property == "id") { + r_ret = get_item_id(item_index); + return true; + } else if (components[1] == "disabled") { + r_ret = is_item_disabled(item_index); + return true; + } else if (property == "separator") { + r_ret = is_item_separator(item_index); + return true; + } + } + return false; +} + +void PopupMenu::_get_property_list(List<PropertyInfo> *p_list) const { + for (int i = 0; i < items.size(); i++) { + p_list->push_back(PropertyInfo(Variant::STRING, vformat("item_%d/text", i))); + + PropertyInfo pi = PropertyInfo(Variant::OBJECT, vformat("item_%d/icon", i), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"); + pi.usage &= ~(get_item_icon(i).is_null() ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::INT, vformat("item_%d/checkable", i), PROPERTY_HINT_ENUM, "No,As checkbox,As radio button"); + pi.usage &= ~(!is_item_checkable(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::BOOL, vformat("item_%d/checked", i)); + pi.usage &= ~(!is_item_checked(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::INT, vformat("item_%d/id", i), PROPERTY_HINT_RANGE, "1,10,1,or_greater"); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::BOOL, vformat("item_%d/disabled", i)); + pi.usage &= ~(!is_item_disabled(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::BOOL, vformat("item_%d/separator", i)); + pi.usage &= ~(!is_item_separator(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + } +} + void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("add_item", "label", "id", "accel"), &PopupMenu::add_item, DEFVAL(-1), DEFVAL(0)); ClassDB::bind_method(D_METHOD("add_icon_item", "texture", "label", "id", "accel"), &PopupMenu::add_icon_item, DEFVAL(-1), DEFVAL(0)); @@ -1643,6 +1733,7 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("get_item_shortcut", "idx"), &PopupMenu::get_item_shortcut); ClassDB::bind_method(D_METHOD("get_current_index"), &PopupMenu::get_current_index); + ClassDB::bind_method(D_METHOD("set_item_count", "count"), &PopupMenu::set_item_count); ClassDB::bind_method(D_METHOD("get_item_count"), &PopupMenu::get_item_count); ClassDB::bind_method(D_METHOD("remove_item", "idx"), &PopupMenu::remove_item); @@ -1650,9 +1741,6 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("add_separator", "label", "id"), &PopupMenu::add_separator, DEFVAL(String()), DEFVAL(-1)); ClassDB::bind_method(D_METHOD("clear"), &PopupMenu::clear); - ClassDB::bind_method(D_METHOD("_set_items"), &PopupMenu::_set_items); - ClassDB::bind_method(D_METHOD("_get_items"), &PopupMenu::_get_items); - ClassDB::bind_method(D_METHOD("set_hide_on_item_selection", "enable"), &PopupMenu::set_hide_on_item_selection); ClassDB::bind_method(D_METHOD("is_hide_on_item_selection"), &PopupMenu::is_hide_on_item_selection); @@ -1668,13 +1756,14 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("set_allow_search", "allow"), &PopupMenu::set_allow_search); ClassDB::bind_method(D_METHOD("get_allow_search"), &PopupMenu::get_allow_search); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_item_selection"), "set_hide_on_item_selection", "is_hide_on_item_selection"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_checkable_item_selection"), "set_hide_on_checkable_item_selection", "is_hide_on_checkable_item_selection"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "submenu_popup_delay"), "set_submenu_popup_delay", "get_submenu_popup_delay"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_search"), "set_allow_search", "get_allow_search"); + ADD_ARRAY_COUNT("Items", "items_count", "set_item_count", "get_item_count", "item_"); + ADD_SIGNAL(MethodInfo("id_pressed", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("id_focused", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("index_pressed", PropertyInfo(Variant::INT, "index"))); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 428076c6da..80874ca1e0 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -117,9 +117,6 @@ class PopupMenu : public Popup { bool hide_on_multistate_item_selection = false; Vector2 moved; - Array _get_items() const; - void _set_items(const Array &p_items); - Map<Ref<Shortcut>, int> shortcut_refcount; void _ref_shortcut(Ref<Shortcut> p_sc); @@ -141,6 +138,9 @@ class PopupMenu : public Popup { protected: void _notification(int p_what); + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; static void _bind_methods(); public: @@ -213,6 +213,8 @@ public: int get_item_state(int p_idx) const; int get_current_index() const; + + void set_item_count(int p_count); int get_item_count() const; bool activate_item_by_event(const Ref<InputEvent> &p_event, bool p_for_global_only = false); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index f1efbbda98..308880ef18 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -621,7 +621,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> } } -int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, bool p_shadow_as_outline, const Point2 &p_shadow_ofs) { +int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, int p_shadow_outline_size, const Point2 &p_shadow_ofs) { Vector2 off; ERR_FAIL_COND_V(p_frame == nullptr, 0); @@ -804,7 +804,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } for (int j = 0; j < frame->lines.size(); j++) { - _draw_line(frame, j, p_ofs + rect.position + off + Vector2(0, frame->lines[j].offset.y), rect.size.x, p_base_color, p_outline_size, p_outline_color, p_font_shadow_color, p_shadow_as_outline, p_shadow_ofs); + _draw_line(frame, j, p_ofs + rect.position + off + Vector2(0, frame->lines[j].offset.y), rect.size.x, p_base_color, p_outline_size, p_outline_color, p_font_shadow_color, p_shadow_outline_size, p_shadow_ofs); } idx++; } @@ -824,7 +824,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o Item *it = _get_item_at_pos(it_from, it_to, glyphs[i].start); int size = _find_outline_size(it, p_outline_size); Color font_color = _find_outline_color(it, p_outline_color); - if (size <= 0) { + Color font_shadow_color = p_font_shadow_color; + if ((size <= 0 || font_color.a == 0) && (font_shadow_color.a == 0)) { gloff.x += glyphs[i].advance; continue; } @@ -871,9 +872,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o faded_visibility = faded_visibility < 0.0f ? 0.0f : faded_visibility; } font_color.a = faded_visibility; + font_shadow_color.a = faded_visibility; } - bool visible = (font_color.a != 0); + bool visible = (font_color.a != 0) || (font_shadow_color.a != 0); for (int j = 0; j < fx_stack.size(); j++) { ItemFX *item_fx = fx_stack[j]; @@ -942,18 +944,19 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } } - Point2 shadow_ofs(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y"))); - // Draw glyph outlines. for (int j = 0; j < glyphs[i].repeat; j++) { if (visible) { if (frid != RID()) { - if (p_shadow_as_outline) { - TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff + Vector2(-shadow_ofs.x, shadow_ofs.y), gl, p_font_shadow_color); - TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff + Vector2(shadow_ofs.x, -shadow_ofs.y), gl, p_font_shadow_color); - TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff + Vector2(-shadow_ofs.x, -shadow_ofs.y), gl, p_font_shadow_color); + if (font_shadow_color.a > 0) { + TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, font_shadow_color); + } + if (font_shadow_color.a > 0 && p_shadow_outline_size > 0) { + TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, p_shadow_outline_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, font_shadow_color); + } + if (font_color.a != 0.0 && size > 0) { + TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff, gl, font_color); } - TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff, gl, font_color); } } gloff.x += glyphs[i].advance; @@ -1470,7 +1473,7 @@ void RichTextLabel::_notification(int p_what) { Color outline_color = get_theme_color(SNAME("font_outline_color")); int outline_size = get_theme_constant(SNAME("outline_size")); Color font_shadow_color = get_theme_color(SNAME("font_shadow_color")); - bool use_outline = get_theme_constant(SNAME("shadow_as_outline")); + int shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size")); Point2 shadow_ofs(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y"))); visible_paragraph_count = 0; @@ -1480,7 +1483,7 @@ void RichTextLabel::_notification(int p_what) { Point2 ofs = text_rect.get_position() + Vector2(0, main->lines[from_line].offset.y - vofs); while (ofs.y < size.height && from_line < main->lines.size()) { visible_paragraph_count++; - visible_line_count += _draw_line(main, from_line, ofs, text_rect.size.x, base_color, outline_size, outline_color, font_shadow_color, use_outline, shadow_ofs); + visible_line_count += _draw_line(main, from_line, ofs, text_rect.size.x, base_color, outline_size, outline_color, font_shadow_color, shadow_outline_size, shadow_ofs); ofs.y += main->lines[from_line].text_buf->get_size().y + get_theme_constant(SNAME("line_separation")); from_line++; } diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index f3c4c11cc8..5b58f14d96 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -412,7 +412,7 @@ private: void _shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width, int *r_char_offset); void _resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width); - int _draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, bool p_shadow_as_outline, const Point2 &shadow_ofs); + int _draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, int p_shadow_outline_size, const Point2 &p_shadow_ofs); float _find_click_in_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Point2i &p_click, ItemFrame **r_click_frame = nullptr, int *r_click_line = nullptr, Item **r_click_item = nullptr, int *r_click_char = nullptr); String _roman(int p_num, bool p_capitalize) const; diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 26bff4494b..cd7534f73c 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -256,7 +256,7 @@ void CanvasLayer::_update_follow_viewport(bool p_force_exit) { void CanvasLayer::_validate_property(PropertyInfo &property) const { if (!follow_viewport && property.name == "follow_viewport_scale") { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } } diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 189aebb47d..3be73af861 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -908,17 +908,12 @@ void Node::set_name(const String &p_name) { } } -static bool node_hrcr = false; static SafeRefCount node_hrcr_count; void Node::init_node_hrcr() { node_hrcr_count.init(1); } -void Node::set_human_readable_collision_renaming(bool p_enabled) { - node_hrcr = p_enabled; -} - #ifdef TOOLS_ENABLED String Node::validate_child_name(Node *p_child) { StringName name = p_child->data.name; @@ -930,9 +925,8 @@ String Node::validate_child_name(Node *p_child) { void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) { /* Make sure the name is unique */ - if (node_hrcr || p_force_human_readable) { + if (p_force_human_readable) { //this approach to autoset node names is human readable but very slow - //it's turned on while running in the editor StringName name = p_child->data.name; _generate_serial_child_name(p_child, name); @@ -1899,6 +1893,56 @@ Node *Node::get_deepest_editable_node(Node *p_start_node) const { return node; } +#ifdef TOOLS_ENABLED +void Node::set_property_pinned(const String &p_property, bool p_pinned) { + bool current_pinned = false; + bool has_pinned = has_meta("_edit_pinned_properties_"); + Array pinned; + String psa = get_property_store_alias(p_property); + if (has_pinned) { + pinned = get_meta("_edit_pinned_properties_"); + current_pinned = pinned.has(psa); + } + + if (current_pinned != p_pinned) { + if (p_pinned) { + pinned.append(psa); + if (!has_pinned) { + set_meta("_edit_pinned_properties_", pinned); + } + } else { + pinned.erase(psa); + if (pinned.is_empty()) { + remove_meta("_edit_pinned_properties_"); + } + } + } +} + +bool Node::is_property_pinned(const StringName &p_property) const { + if (!has_meta("_edit_pinned_properties_")) { + return false; + } + Array pinned = get_meta("_edit_pinned_properties_"); + String psa = get_property_store_alias(p_property); + return pinned.has(psa); +} + +StringName Node::get_property_store_alias(const StringName &p_property) const { + return p_property; +} +#endif + +void Node::get_storable_properties(Set<StringName> &r_storable_properties) const { + List<PropertyInfo> pi; + get_property_list(&pi); + for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) { + if ((E->get().usage & PROPERTY_USAGE_STORAGE)) { + r_storable_properties.insert(E->get().name); + } + } +} + String Node::to_string() { if (get_script_instance()) { bool valid; @@ -2750,7 +2794,11 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_import_path", "import_path"), &Node::set_import_path); ClassDB::bind_method(D_METHOD("_get_import_path"), &Node::get_import_path); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "_import_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_import_path", "_get_import_path"); +#ifdef TOOLS_ENABLED + ClassDB::bind_method(D_METHOD("_set_property_pinned", "property", "pinned"), &Node::set_property_pinned); +#endif + + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "_import_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_import_path", "_get_import_path"); { MethodInfo mi; diff --git a/scene/main/node.h b/scene/main/node.h index e59a7a390a..2dd32a2e1d 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -363,6 +363,13 @@ public: bool is_editable_instance(const Node *p_node) const; Node *get_deepest_editable_node(Node *p_start_node) const; +#ifdef TOOLS_ENABLED + void set_property_pinned(const String &p_property, bool p_pinned); + bool is_property_pinned(const StringName &p_property) const; + virtual StringName get_property_store_alias(const StringName &p_property) const; +#endif + void get_storable_properties(Set<StringName> &r_storable_properties) const; + virtual String to_string() override; /* NOTIFICATIONS */ @@ -437,7 +444,6 @@ public: void queue_delete(); //hacks for speed - static void set_human_readable_collision_renaming(bool p_enabled); static void init_node_hrcr(); void force_parent_owned() { data.parent_owned = true; } //hack to avoid duplicate nodes diff --git a/scene/main/resource_preloader.cpp b/scene/main/resource_preloader.cpp index f4c90ee668..c44b55284d 100644 --- a/scene/main/resource_preloader.cpp +++ b/scene/main/resource_preloader.cpp @@ -147,7 +147,7 @@ void ResourcePreloader::_bind_methods() { ClassDB::bind_method(D_METHOD("get_resource", "name"), &ResourcePreloader::get_resource); ClassDB::bind_method(D_METHOD("get_resource_list"), &ResourcePreloader::_get_resource_list); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "resources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_resources", "_get_resources"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "resources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_resources", "_get_resources"); } ResourcePreloader::ResourcePreloader() { diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index cdf1f495e4..31e8c20991 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -638,7 +638,13 @@ void Viewport::_process_picking() { Vector2 point = canvas_transform.affine_inverse().xform(pos); - int rc = ss2d->intersect_point_on_canvas(point, canvas_layer_id, res, 64, Set<RID>(), 0xFFFFFFFF, true, true, true); + PhysicsDirectSpaceState2D::PointParameters point_params; + point_params.position = point; + point_params.canvas_instance_id = canvas_layer_id; + point_params.collide_with_areas = true; + point_params.pick_point = true; + + int rc = ss2d->intersect_point(point_params, res, 64); for (int i = 0; i < rc; i++) { if (res[i].collider_id.is_valid() && res[i].collider) { CollisionObject2D *co = Object::cast_to<CollisionObject2D>(res[i].collider); @@ -719,7 +725,13 @@ void Viewport::_process_picking() { PhysicsDirectSpaceState3D *space = PhysicsServer3D::get_singleton()->space_get_direct_state(find_world_3d()->get_space()); if (space) { - bool col = space->intersect_ray(from, from + dir * far, result, Set<RID>(), 0xFFFFFFFF, true, true, true); + PhysicsDirectSpaceState3D::RayParameters ray_params; + ray_params.from = from; + ray_params.to = from + dir * far; + ray_params.collide_with_areas = true; + ray_params.pick_ray = true; + + bool col = space->intersect_ray(ray_params, result); ObjectID new_collider; if (col) { CollisionObject3D *co = Object::cast_to<CollisionObject3D>(result.collider); diff --git a/scene/property_utils.cpp b/scene/property_utils.cpp new file mode 100644 index 0000000000..79821b8399 --- /dev/null +++ b/scene/property_utils.cpp @@ -0,0 +1,185 @@ +/*************************************************************************/ +/* property_utils.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "property_utils.h" + +#include "core/config/engine.h" +#include "core/templates/local_vector.h" +#include "editor/editor_node.h" +#include "scene/resources/packed_scene.h" + +bool PropertyUtils::is_property_value_different(const Variant &p_a, const Variant &p_b) { + if (p_a.get_type() == Variant::FLOAT && p_b.get_type() == Variant::FLOAT) { + //this must be done because, as some scenes save as text, there might be a tiny difference in floats due to numerical error + return !Math::is_equal_approx((float)p_a, (float)p_b); + } else { + // For our purposes, treating null object as NIL is the right thing to do + const Variant &a = p_a.get_type() == Variant::OBJECT && (Object *)p_a == nullptr ? Variant() : p_a; + const Variant &b = p_b.get_type() == Variant::OBJECT && (Object *)p_b == nullptr ? Variant() : p_b; + return a != b; + } +} + +Variant PropertyUtils::get_property_default_value(const Object *p_object, const StringName &p_property, const Vector<SceneState::PackState> *p_states_stack_cache, bool p_update_exports, const Node *p_owner, bool *r_is_class_default) { + // This function obeys the way property values are set when an object is instantiated, + // which is the following (the latter wins): + // 1. Default value from builtin class + // 2. Default value from script exported variable (from the topmost script) + // 3. Value overrides from the instantiation/inheritance stack + + if (r_is_class_default) { + *r_is_class_default = false; + } + + Ref<Script> topmost_script; + + if (const Node *node = Object::cast_to<Node>(p_object)) { + // Check inheritance/instantiation ancestors + const Vector<SceneState::PackState> &states_stack = p_states_stack_cache ? *p_states_stack_cache : PropertyUtils::get_node_states_stack(node, p_owner); + for (int i = 0; i < states_stack.size(); ++i) { + const SceneState::PackState &ia = states_stack[i]; + bool found = false; + Variant value_in_ancestor = ia.state->get_property_value(ia.node, p_property, found); + if (found) { + return value_in_ancestor; + } + // Save script for later + bool has_script = false; + Variant script = ia.state->get_property_value(ia.node, SNAME("script"), has_script); + if (has_script) { + Ref<Script> scr = script; + if (scr.is_valid()) { + topmost_script = scr; + } + } + } + } + + // Let's see what default is set by the topmost script having a default, if any + if (topmost_script.is_null()) { + topmost_script = p_object->get_script(); + } + if (topmost_script.is_valid()) { + // Should be called in the editor only and not at runtime, + // otherwise it can cause problems because of missing instance state support + if (p_update_exports && Engine::get_singleton()->is_editor_hint()) { + topmost_script->update_exports(); + } + Variant default_value; + if (topmost_script->get_property_default_value(p_property, default_value)) { + return default_value; + } + } + + // Fall back to the default from the native class + if (r_is_class_default) { + *r_is_class_default = true; + } + return ClassDB::class_get_default_property_value(p_object->get_class_name(), p_property); +} + +// Like SceneState::PackState, but using a raw pointer to avoid the cost of +// updating the reference count during the internal work of the functions below +namespace { +struct _FastPackState { + SceneState *state = nullptr; + int node = -1; +}; +} // namespace + +static bool _collect_inheritance_chain(const Ref<SceneState> &p_state, const NodePath &p_path, LocalVector<_FastPackState> &r_states_stack) { + bool found = false; + + LocalVector<_FastPackState> inheritance_states; + + Ref<SceneState> state = p_state; + while (state.is_valid()) { + int node = state->find_node_by_path(p_path); + if (node >= 0) { + // This one has state for this node + inheritance_states.push_back({ state.ptr(), node }); + found = true; + } + state = state->get_base_scene_state(); + } + + for (int i = inheritance_states.size() - 1; i >= 0; --i) { + r_states_stack.push_back(inheritance_states[i]); + } + + return found; +} + +Vector<SceneState::PackState> PropertyUtils::get_node_states_stack(const Node *p_node, const Node *p_owner, bool *r_instantiated_by_owner) { + if (r_instantiated_by_owner) { + *r_instantiated_by_owner = true; + } + + LocalVector<_FastPackState> states_stack; + { + const Node *owner = p_owner; +#ifdef TOOLS_ENABLED + if (!p_owner && Engine::get_singleton()->is_editor_hint()) { + owner = EditorNode::get_singleton()->get_edited_scene(); + } +#endif + + const Node *n = p_node; + while (n) { + if (n == owner) { + const Ref<SceneState> &state = n->get_scene_inherited_state(); + if (_collect_inheritance_chain(state, n->get_path_to(p_node), states_stack)) { + if (r_instantiated_by_owner) { + *r_instantiated_by_owner = false; + } + } + break; + } else if (n->get_scene_file_path() != String()) { + const Ref<SceneState> &state = n->get_scene_instance_state(); + _collect_inheritance_chain(state, n->get_path_to(p_node), states_stack); + } + n = n->get_owner(); + } + } + + // Convert to the proper type for returning, inverting the vector on the go + // (it was more convenient to fill the vector in reverse order) + Vector<SceneState::PackState> states_stack_ret; + { + states_stack_ret.resize(states_stack.size()); + _FastPackState *ps = states_stack.ptr(); + for (int i = states_stack.size() - 1; i >= 0; --i) { + states_stack_ret.write[i].state.reference_ptr(ps->state); + states_stack_ret.write[i].node = ps->node; + ++ps; + } + } + return states_stack_ret; +} diff --git a/scene/property_utils.h b/scene/property_utils.h new file mode 100644 index 0000000000..fde9163548 --- /dev/null +++ b/scene/property_utils.h @@ -0,0 +1,51 @@ +/*************************************************************************/ +/* property_utils.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PROPERTY_UTILS_H +#define PROPERTY_UTILS_H + +#include "scene/main/node.h" +#include "scene/resources/packed_scene.h" + +class PropertyUtils { +public: + static bool is_property_value_different(const Variant &p_a, const Variant &p_b); + // Gets the most pure default value, the one that would be set when the node has just been instantiated + static Variant get_property_default_value(const Object *p_object, const StringName &p_property, const Vector<SceneState::PackState> *p_states_stack_cache = nullptr, bool p_update_exports = false, const Node *p_owner = nullptr, bool *r_is_class_default = nullptr); + + // Gets the instance/inheritance states of this node, in order of precedence, + // that is, from the topmost (the most able to override values) to the lowermost + // (Note that in nested instancing the one with the greatest precedence is the furthest + // in the tree, since every owner found while traversing towards the root gets a chance + // to override property values.) + static Vector<SceneState::PackState> get_node_states_stack(const Node *p_node, const Node *p_owner = nullptr, bool *r_instantiated_by_owner = nullptr); +}; + +#endif // PROPERTY_UTILS_H diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index d44cd7ca63..c193850a78 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -791,7 +791,7 @@ void register_scene_types() { GDREGISTER_CLASS(MeshTexture); GDREGISTER_CLASS(CurveTexture); GDREGISTER_CLASS(CurveXYZTexture); - GDREGISTER_CLASS(GradientTexture); + GDREGISTER_CLASS(GradientTexture1D); GDREGISTER_CLASS(GradientTexture2D); GDREGISTER_CLASS(ProxyTexture); GDREGISTER_CLASS(AnimatedTexture); @@ -922,6 +922,7 @@ void register_scene_types() { ClassDB::add_compatibility_class("EditorSpatialGizmo", "EditorNode3DGizmo"); ClassDB::add_compatibility_class("EditorSpatialGizmoPlugin", "EditorNode3DGizmoPlugin"); ClassDB::add_compatibility_class("Generic6DOFJoint", "Generic6DOFJoint3D"); + ClassDB::add_compatibility_class("GradientTexture", "GradientTexture1D"); ClassDB::add_compatibility_class("HeightMapShape", "HeightMapShape3D"); ClassDB::add_compatibility_class("HingeJoint", "HingeJoint3D"); ClassDB::add_compatibility_class("Joint", "Joint3D"); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 06ce993cc7..71d2774335 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -799,19 +799,19 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { void Animation::_get_property_list(List<PropertyInfo> *p_list) const { if (compression.enabled) { - p_list->push_back(PropertyInfo(Variant::DICTIONARY, "_compression", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::DICTIONARY, "_compression", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } for (int i = 0; i < tracks.size(); i++) { - p_list->push_back(PropertyInfo(Variant::STRING, "tracks/" + itos(i) + "/type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/imported", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::NODE_PATH, "tracks/" + itos(i) + "/path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::STRING, "tracks/" + itos(i) + "/type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/imported", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::NODE_PATH, "tracks/" + itos(i) + "/path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); if (track_is_compressed(i)) { - p_list->push_back(PropertyInfo(Variant::INT, "tracks/" + itos(i) + "/compressed_track", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::INT, "tracks/" + itos(i) + "/compressed_track", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } else { - p_list->push_back(PropertyInfo(Variant::INT, "tracks/" + itos(i) + "/interp", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/loop_wrap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::ARRAY, "tracks/" + itos(i) + "/keys", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::INT, "tracks/" + itos(i) + "/interp", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/loop_wrap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "tracks/" + itos(i) + "/keys", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } } } diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index d018103e64..5cfc4a9d40 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -636,7 +636,7 @@ void AudioStreamSample::_bind_methods() { ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamSample::save_to_wav); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_data", "get_data"); ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format"); ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "Disabled,Forward,Ping-Pong,Backward"), "set_loop_mode", "get_loop_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_begin"), "set_loop_begin", "get_loop_begin"); diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index 49ed9dcb82..16f1507c34 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -674,7 +674,7 @@ void BitMap::_bind_methods() { ClassDB::bind_method(D_METHOD("grow_mask", "pixels", "rect"), &BitMap::grow_mask); ClassDB::bind_method(D_METHOD("opaque_to_polygons", "rect", "epsilon"), &BitMap::_opaque_to_polygons_bind, DEFVAL(2.0)); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); } BitMap::BitMap() {} diff --git a/scene/resources/camera_effects.cpp b/scene/resources/camera_effects.cpp index b633196424..0df372ea1b 100644 --- a/scene/resources/camera_effects.cpp +++ b/scene/resources/camera_effects.cpp @@ -149,7 +149,7 @@ void CameraEffects::_validate_property(PropertyInfo &property) const { if ((!dof_blur_far_enabled && (property.name == "dof_blur_far_distance" || property.name == "dof_blur_far_transition")) || (!dof_blur_near_enabled && (property.name == "dof_blur_near_distance" || property.name == "dof_blur_near_transition")) || (!override_exposure_enabled && property.name == "override_exposure")) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } } diff --git a/scene/resources/concave_polygon_shape_3d.cpp b/scene/resources/concave_polygon_shape_3d.cpp index 3fed700383..03854683bd 100644 --- a/scene/resources/concave_polygon_shape_3d.cpp +++ b/scene/resources/concave_polygon_shape_3d.cpp @@ -108,7 +108,7 @@ void ConcavePolygonShape3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_backface_collision_enabled", "enabled"), &ConcavePolygonShape3D::set_backface_collision_enabled); ClassDB::bind_method(D_METHOD("is_backface_collision_enabled"), &ConcavePolygonShape3D::is_backface_collision_enabled); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_faces", "get_faces"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_faces", "get_faces"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "backface_collision"), "set_backface_collision_enabled", "is_backface_collision_enabled"); } diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 9dc76dcf44..b530a72033 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -522,7 +522,7 @@ void Curve::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_min_value", "get_min_value"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_max_value", "get_max_value"); ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_resolution", PROPERTY_HINT_RANGE, "1,1000,1"), "set_bake_resolution", "get_bake_resolution"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); ADD_SIGNAL(MethodInfo(SIGNAL_RANGE_CHANGED)); @@ -1006,7 +1006,7 @@ void Curve2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_data"), &Curve2D::_set_data); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_interval", PROPERTY_HINT_RANGE, "0.01,512,0.01"), "set_bake_interval", "get_bake_interval"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); } Curve2D::Curve2D() { @@ -1699,7 +1699,7 @@ void Curve3D::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_data"), &Curve3D::_set_data); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_interval", PROPERTY_HINT_RANGE, "0.01,512,0.01"), "set_bake_interval", "get_bake_interval"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); ADD_GROUP("Up Vector", "up_vector_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "up_vector_enabled"), "set_up_vector_enabled", "is_up_vector_enabled"); diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index f21a070133..a1d76ef352 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -940,7 +940,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * scale); theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * scale); - theme->set_constant("shadow_as_outline", "RichTextLabel", 0 * scale); + theme->set_constant("shadow_outline_size", "RichTextLabel", 1 * scale); theme->set_constant("line_separation", "RichTextLabel", 0 * scale); theme->set_constant("table_hseparation", "RichTextLabel", 3 * scale); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 9f8e89564d..4c25ed589b 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -917,7 +917,7 @@ float Environment::get_adjustment_saturation() const { void Environment::set_adjustment_color_correction(Ref<Texture> p_color_correction) { adjustment_color_correction = p_color_correction; - Ref<GradientTexture> grad_tex = p_color_correction; + Ref<GradientTexture1D> grad_tex = p_color_correction; if (grad_tex.is_valid()) { if (!grad_tex->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &Environment::_update_adjustment))) { grad_tex->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Environment::_update_adjustment)); @@ -954,39 +954,39 @@ void Environment::_update_adjustment() { void Environment::_validate_property(PropertyInfo &property) const { if (property.name == "sky" || property.name == "sky_custom_fov" || property.name == "sky_rotation" || property.name == "ambient_light/sky_contribution") { if (bg_mode != BG_SKY && ambient_source != AMBIENT_SOURCE_SKY && reflection_source != REFLECTION_SOURCE_SKY) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } if (property.name == "fog_aerial_perspective") { if (bg_mode != BG_SKY) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } if (property.name == "glow_intensity" && glow_blend_mode == GLOW_BLEND_MODE_MIX) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } if (property.name == "glow_mix" && glow_blend_mode != GLOW_BLEND_MODE_MIX) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } if (property.name == "background_color") { if (bg_mode != BG_COLOR && ambient_source != AMBIENT_SOURCE_COLOR) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } if (property.name == "background_canvas_max_layer") { if (bg_mode != BG_CANVAS) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } if (property.name == "background_camera_feed_id") { if (bg_mode != BG_CAMERA_FEED) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } } @@ -1018,7 +1018,7 @@ void Environment::_validate_property(PropertyInfo &property) const { String enabled = prefix + "enabled"; if (property.name.begins_with(prefix) && property.name != enabled && !bool(get(enabled))) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; return; } @@ -1031,7 +1031,7 @@ void Environment::_validate_property(PropertyInfo &property) const { String prefix = String(*prefixes); if (property.name.begins_with(prefix)) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; return; } diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 819ae95715..d9de47afc7 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -70,6 +70,15 @@ void FontData::_bind_methods() { ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &FontData::set_antialiased); ClassDB::bind_method(D_METHOD("is_antialiased"), &FontData::is_antialiased); + ClassDB::bind_method(D_METHOD("set_font_name", "name"), &FontData::set_font_name); + ClassDB::bind_method(D_METHOD("get_font_name"), &FontData::get_font_name); + + ClassDB::bind_method(D_METHOD("set_font_style_name", "name"), &FontData::set_font_style_name); + ClassDB::bind_method(D_METHOD("get_font_style_name"), &FontData::get_font_style_name); + + ClassDB::bind_method(D_METHOD("set_font_style", "style"), &FontData::set_font_style); + ClassDB::bind_method(D_METHOD("get_font_style"), &FontData::get_font_style); + ClassDB::bind_method(D_METHOD("set_multichannel_signed_distance_field", "msdf"), &FontData::set_multichannel_signed_distance_field); ClassDB::bind_method(D_METHOD("is_multichannel_signed_distance_field"), &FontData::is_multichannel_signed_distance_field); @@ -190,6 +199,15 @@ bool FontData::_set(const StringName &p_name, const Variant &p_value) { } else if (tokens[0] == "antialiased") { set_antialiased(p_value); return true; + } else if (tokens[0] == "font_name") { + set_font_name(p_value); + return true; + } else if (tokens[0] == "style_name") { + set_font_style_name(p_value); + return true; + } else if (tokens[0] == "font_style") { + set_font_style(p_value); + return true; } else if (tokens[0] == "multichannel_signed_distance_field") { set_multichannel_signed_distance_field(p_value); return true; @@ -295,6 +313,15 @@ bool FontData::_get(const StringName &p_name, Variant &r_ret) const { } else if (tokens[0] == "antialiased") { r_ret = is_antialiased(); return true; + } else if (tokens[0] == "font_name") { + r_ret = get_font_name(); + return true; + } else if (tokens[0] == "style_name") { + r_ret = get_font_style_name(); + return true; + } else if (tokens[0] == "font_style") { + r_ret = get_font_style(); + return true; } else if (tokens[0] == "multichannel_signed_distance_field") { r_ret = is_multichannel_signed_distance_field(); return true; @@ -394,6 +421,9 @@ bool FontData::_get(const StringName &p_name, Variant &r_ret) const { void FontData::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); + p_list->push_back(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); + p_list->push_back(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); + p_list->push_back(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); p_list->push_back(PropertyInfo(Variant::BOOL, "antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); p_list->push_back(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); p_list->push_back(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); @@ -510,6 +540,36 @@ PackedByteArray FontData::get_data() const { return data; } +void FontData::set_font_name(const String &p_name) { + _ensure_rid(0); + TS->font_set_name(cache[0], p_name); +} + +String FontData::get_font_name() const { + _ensure_rid(0); + return TS->font_get_name(cache[0]); +} + +void FontData::set_font_style_name(const String &p_name) { + _ensure_rid(0); + TS->font_set_style_name(cache[0], p_name); +} + +String FontData::get_font_style_name() const { + _ensure_rid(0); + return TS->font_get_style_name(cache[0]); +} + +void FontData::set_font_style(uint32_t p_style) { + _ensure_rid(0); + TS->font_set_style(cache[0], p_style); +} + +uint32_t FontData::get_font_style() const { + _ensure_rid(0); + return TS->font_get_style(cache[0]); +} + void FontData::set_antialiased(bool p_antialiased) { if (antialiased != p_antialiased) { antialiased = p_antialiased; diff --git a/scene/resources/font.h b/scene/resources/font.h index e1f1f6d742..4d9ee72c84 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -79,6 +79,15 @@ public: virtual PackedByteArray get_data() const; // Common properties. + virtual void set_font_name(const String &p_name); + virtual String get_font_name() const; + + virtual void set_font_style_name(const String &p_name); + virtual String get_font_style_name() const; + + virtual void set_font_style(uint32_t p_style); + virtual uint32_t get_font_style() const; + virtual void set_antialiased(bool p_antialiased); virtual bool is_antialiased() const; diff --git a/scene/resources/gradient.cpp b/scene/resources/gradient.cpp index 7b9b942142..4559b4ce0a 100644 --- a/scene/resources/gradient.cpp +++ b/scene/resources/gradient.cpp @@ -51,6 +51,8 @@ void Gradient::_bind_methods() { ClassDB::bind_method(D_METHOD("set_offset", "point", "offset"), &Gradient::set_offset); ClassDB::bind_method(D_METHOD("get_offset", "point"), &Gradient::get_offset); + ClassDB::bind_method(D_METHOD("reverse"), &Gradient::reverse); + ClassDB::bind_method(D_METHOD("set_color", "point", "color"), &Gradient::set_color); ClassDB::bind_method(D_METHOD("get_color", "point"), &Gradient::get_color); @@ -64,8 +66,18 @@ void Gradient::_bind_methods() { ClassDB::bind_method(D_METHOD("set_colors", "colors"), &Gradient::set_colors); ClassDB::bind_method(D_METHOD("get_colors"), &Gradient::get_colors); + ClassDB::bind_method(D_METHOD("set_interpolation_mode", "interpolation_mode"), &Gradient::set_interpolation_mode); + ClassDB::bind_method(D_METHOD("get_interpolation_mode"), &Gradient::get_interpolation_mode); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "interpolation_mode", PROPERTY_HINT_ENUM, "Linear,Constant,Cubic"), "set_interpolation_mode", "get_interpolation_mode"); + + ADD_GROUP("Raw data", ""); ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT32_ARRAY, "offsets"), "set_offsets", "get_offsets"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "colors"), "set_colors", "get_colors"); + + BIND_ENUM_CONSTANT(GRADIENT_INTERPOLATE_LINEAR); + BIND_ENUM_CONSTANT(GRADIENT_INTERPOLATE_CONSTANT); + BIND_ENUM_CONSTANT(GRADIENT_INTERPOLATE_CUBIC); } Vector<float> Gradient::get_offsets() const { @@ -86,6 +98,15 @@ Vector<Color> Gradient::get_colors() const { return colors; } +void Gradient::set_interpolation_mode(Gradient::InterpolationMode p_interp_mode) { + interpolation_mode = p_interp_mode; + emit_signal(CoreStringNames::get_singleton()->changed); +} + +Gradient::InterpolationMode Gradient::get_interpolation_mode() { + return interpolation_mode; +} + void Gradient::set_offsets(const Vector<float> &p_offsets) { points.resize(p_offsets.size()); for (int i = 0; i < points.size(); i++) { @@ -127,6 +148,15 @@ void Gradient::remove_point(int p_index) { emit_signal(CoreStringNames::get_singleton()->changed); } +void Gradient::reverse() { + for (int i = 0; i < points.size(); i++) { + points.write[i].offset = 1.0 - points[i].offset; + } + + _update_sorting(); + emit_signal(CoreStringNames::get_singleton()->changed); +} + void Gradient::set_points(Vector<Gradient::Point> &p_points) { points = p_points; is_sorted = false; diff --git a/scene/resources/gradient.h b/scene/resources/gradient.h index cf5b179c45..eb438d0bba 100644 --- a/scene/resources/gradient.h +++ b/scene/resources/gradient.h @@ -38,6 +38,12 @@ class Gradient : public Resource { OBJ_SAVE_TYPE(Gradient); public: + enum InterpolationMode { + GRADIENT_INTERPOLATE_LINEAR, + GRADIENT_INTERPOLATE_CONSTANT, + GRADIENT_INTERPOLATE_CUBIC, + }; + struct Point { float offset = 0.0; Color color; @@ -49,6 +55,8 @@ public: private: Vector<Point> points; bool is_sorted = true; + InterpolationMode interpolation_mode = GRADIENT_INTERPOLATE_LINEAR; + _FORCE_INLINE_ void _update_sorting() { if (!is_sorted) { points.sort(); @@ -65,9 +73,9 @@ public: void add_point(float p_offset, const Color &p_color); void remove_point(int p_index); - void set_points(Vector<Point> &p_points); Vector<Point> &get_points(); + void reverse(); void set_offset(int pos, const float offset); float get_offset(int pos); @@ -81,6 +89,13 @@ public: void set_colors(const Vector<Color> &p_colors); Vector<Color> get_colors() const; + void set_interpolation_mode(InterpolationMode p_interp_mode); + InterpolationMode get_interpolation_mode(); + + _FORCE_INLINE_ float cubic_interpolate(float p0, float p1, float p2, float p3, float x) { + return p1 + 0.5 * x * (p2 - p0 + x * (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3 + x * (3.0 * (p1 - p2) + p3 - p0))); + } + _FORCE_INLINE_ Color get_color_at_offset(float p_offset) { if (points.is_empty()) { return Color(0, 0, 0, 1); @@ -88,7 +103,7 @@ public: _update_sorting(); - //binary search + // Binary search. int low = 0; int high = points.size() - 1; int middle = 0; @@ -111,7 +126,7 @@ public: } } - //return interpolated value + // Return interpolated value. if (points[middle].offset > p_offset) { middle--; } @@ -125,10 +140,44 @@ public: } const Point &pointFirst = points[first]; const Point &pointSecond = points[second]; - return pointFirst.color.lerp(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset)); + + switch (interpolation_mode) { + case GRADIENT_INTERPOLATE_LINEAR: { + return pointFirst.color.lerp(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset)); + } break; + case GRADIENT_INTERPOLATE_CONSTANT: { + return pointFirst.color; + } break; + case GRADIENT_INTERPOLATE_CUBIC: { + int p0 = first - 1; + int p3 = second + 1; + if (p3 >= points.size()) { + p3 = second; + } + if (p0 < 0) { + p0 = first; + } + const Point &pointP0 = points[p0]; + const Point &pointP3 = points[p3]; + + float x = (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset); + float r = cubic_interpolate(pointP0.color.r, pointFirst.color.r, pointSecond.color.r, pointP3.color.r, x); + float g = cubic_interpolate(pointP0.color.g, pointFirst.color.g, pointSecond.color.g, pointP3.color.g, x); + float b = cubic_interpolate(pointP0.color.b, pointFirst.color.b, pointSecond.color.b, pointP3.color.b, x); + float a = cubic_interpolate(pointP0.color.a, pointFirst.color.a, pointSecond.color.a, pointP3.color.a, x); + + return Color(r, g, b, a); + } break; + default: { + // Fallback to linear interpolation. + return pointFirst.color.lerp(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset)); + } + } } int get_points_count() const; }; +VARIANT_ENUM_CAST(Gradient::InterpolationMode); + #endif // GRADIENT_H diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index 076b8312b6..7afa4c91f0 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -1243,5 +1243,5 @@ void ImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &ImporterMesh::set_lightmap_size_hint); ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &ImporterMesh::get_lightmap_size_hint); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "_set_data", "_get_data"); } diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index e01be7cc84..8399b14a56 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -1695,7 +1695,7 @@ BaseMaterial3D::TextureFilter BaseMaterial3D::get_texture_filter() const { void BaseMaterial3D::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const { if (property.name.begins_with(text) && property.name != text + "_enabled" && !features[feature]) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } } @@ -1729,23 +1729,23 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const { } if (property.name == "billboard_keep_scale" && billboard_mode == BILLBOARD_DISABLED) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } if (property.name == "grow_amount" && !grow_enabled) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } if (property.name == "point_size" && !flags[FLAG_USE_POINT_SIZE]) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } if (property.name == "proximity_fade_distance" && !proximity_fade_enabled) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } if ((property.name == "distance_fade_max_distance" || property.name == "distance_fade_min_distance") && distance_fade == DISTANCE_FADE_DISABLED) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } // you can only enable anti-aliasing (in materials) on alpha scissor and alpha hash diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 7ffe0b03e1..51b4e1fbd8 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -1842,8 +1842,8 @@ void ArrayMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_surfaces", "surfaces"), &ArrayMesh::_set_surfaces); ClassDB::bind_method(D_METHOD("_get_surfaces"), &ArrayMesh::_get_surfaces); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "_blend_shape_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_blend_shape_names", "_get_blend_shape_names"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_surfaces", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_surfaces", "_get_surfaces"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "_blend_shape_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_blend_shape_names", "_get_blend_shape_names"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_surfaces", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_surfaces", "_get_surfaces"); ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_shape_mode", PROPERTY_HINT_ENUM, "Normalized,Relative"), "set_blend_shape_mode", "get_blend_shape_mode"); ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shadow_mesh", PROPERTY_HINT_RESOURCE_TYPE, "ArrayMesh"), "set_shadow_mesh", "get_shadow_mesh"); diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp index d87056f55d..db091ec37b 100644 --- a/scene/resources/navigation_mesh.cpp +++ b/scene/resources/navigation_mesh.cpp @@ -477,8 +477,8 @@ void NavigationMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationMesh::_set_polygons); ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationMesh::_get_polygons); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons"); ADD_PROPERTY(PropertyInfo(Variant::INT, "sample_partition_type/sample_partition_type", PROPERTY_HINT_ENUM, "Watershed,Monotone,Layers"), "set_sample_partition_type", "get_sample_partition_type"); ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Both"), "set_parsed_geometry_type", "get_parsed_geometry_type"); diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 60cda637ca..f43715a463 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -34,10 +34,12 @@ #include "core/config/project_settings.h" #include "core/core_string_names.h" #include "core/io/resource_loader.h" +#include "editor/editor_inspector.h" #include "scene/2d/node_2d.h" #include "scene/3d/node_3d.h" #include "scene/gui/control.h" #include "scene/main/instance_placeholder.h" +#include "scene/property_utils.h" #define PACKED_SCENE_VERSION 2 @@ -45,6 +47,30 @@ bool SceneState::can_instantiate() const { return nodes.size() > 0; } +static Array _sanitize_node_pinned_properties(Node *p_node) { + if (!p_node->has_meta("_edit_pinned_properties_")) { + return Array(); + } + Array pinned = p_node->get_meta("_edit_pinned_properties_"); + if (pinned.is_empty()) { + return Array(); + } + Set<StringName> storable_properties; + p_node->get_storable_properties(storable_properties); + int i = 0; + do { + if (storable_properties.has(pinned[i])) { + i++; + } else { + pinned.remove(i); + } + } while (i < pinned.size()); + if (pinned.is_empty()) { + p_node->remove_meta("_edit_pinned_properties_"); + } + return pinned; +} + Node *SceneState::instantiate(GenEditState p_edit_state) const { // nodes where instancing failed (because something is missing) List<Node *> stray_instances; @@ -227,7 +253,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { } else { Node *base = i == 0 ? node : ret_nodes[0]; - if (p_edit_state == GEN_EDIT_STATE_MAIN) { + if (p_edit_state == GEN_EDIT_STATE_MAIN || p_edit_state == GEN_EDIT_STATE_MAIN_INHERITED) { //for the main scene, use the resource as is res->configure_for_local_scene(base, resources_local_to_scene); resources_local_to_scene[res] = res; @@ -291,6 +317,13 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { } } + // we only want to deal with pinned flag if instancing as pure main (no instance, no inheriting) + if (p_edit_state == GEN_EDIT_STATE_MAIN) { + _sanitize_node_pinned_properties(node); + } else { + node->remove_meta("_edit_pinned_properties_"); + } + ret_nodes[i] = node; if (node && gen_node_path_cache && ret_nodes[0]) { @@ -415,61 +448,22 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map // with the instance states, we can query for identical properties/groups // and only save what has changed - List<PackState> pack_state_stack; - - bool instantiated_by_owner = true; - - { - Node *n = p_node; - - while (n) { - if (n == p_owner) { - Ref<SceneState> state = n->get_scene_inherited_state(); - if (state.is_valid()) { - int node = state->find_node_by_path(n->get_path_to(p_node)); - if (node >= 0) { - //this one has state for this node, save - PackState ps; - ps.node = node; - ps.state = state; - pack_state_stack.push_back(ps); - instantiated_by_owner = false; - } - } - - if (p_node->get_scene_file_path() != String() && p_node->get_owner() == p_owner && instantiated_by_owner) { - if (p_node->get_scene_instance_load_placeholder()) { - //it's a placeholder, use the placeholder path - nd.instance = _vm_get_variant(p_node->get_scene_file_path(), variant_map); - nd.instance |= FLAG_INSTANCE_IS_PLACEHOLDER; - } else { - //must instance ourselves - Ref<PackedScene> instance = ResourceLoader::load(p_node->get_scene_file_path()); - if (!instance.is_valid()) { - return ERR_CANT_OPEN; - } + bool instantiated_by_owner = false; + Vector<SceneState::PackState> states_stack = PropertyUtils::get_node_states_stack(p_node, p_owner, &instantiated_by_owner); - nd.instance = _vm_get_variant(instance, variant_map); - } - } - n = nullptr; - } else { - if (n->get_scene_file_path() != String()) { - //is an instance - Ref<SceneState> state = n->get_scene_instance_state(); - if (state.is_valid()) { - int node = state->find_node_by_path(n->get_path_to(p_node)); - if (node >= 0) { - //this one has state for this node, save - PackState ps; - ps.node = node; - ps.state = state; - pack_state_stack.push_back(ps); - } - } - } - n = n->get_owner(); + if (p_node->get_scene_file_path() != String() && p_node->get_owner() == p_owner && instantiated_by_owner) { + if (p_node->get_scene_instance_load_placeholder()) { + //it's a placeholder, use the placeholder path + nd.instance = _vm_get_variant(p_node->get_scene_file_path(), variant_map); + nd.instance |= FLAG_INSTANCE_IS_PLACEHOLDER; + } else { + //must instance ourselves + Ref<PackedScene> instance = ResourceLoader::load(p_node->get_scene_file_path()); + if (!instance.is_valid()) { + return ERR_CANT_OPEN; } + + nd.instance = _vm_get_variant(instance, variant_map); } } @@ -478,88 +472,37 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map List<PropertyInfo> plist; p_node->get_property_list(&plist); - StringName type = p_node->get_class(); - Ref<Script> script = p_node->get_script(); - if (Engine::get_singleton()->is_editor_hint() && script.is_valid()) { - // Should be called in the editor only and not at runtime, - // otherwise it can cause problems because of missing instance state support. - script->update_exports(); - } + Array pinned_props = _sanitize_node_pinned_properties(p_node); for (const PropertyInfo &E : plist) { if (!(E.usage & PROPERTY_USAGE_STORAGE)) { continue; } - String name = E.name; - Variant value = p_node->get(E.name); - - bool isdefault = false; - Variant default_value = ClassDB::class_get_default_property_value(type, name); - - if (default_value.get_type() != Variant::NIL) { - isdefault = bool(Variant::evaluate(Variant::OP_EQUAL, value, default_value)); - } + Variant forced_value; - if (!isdefault && script.is_valid() && script->get_property_default_value(name, default_value)) { - isdefault = bool(Variant::evaluate(Variant::OP_EQUAL, value, default_value)); - } - // the version above makes more sense, because it does not rely on placeholder or usage flag - // in the script, just the default value function. - // if (E.usage & PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE) { - // isdefault = true; //is script default value - // } - - if (pack_state_stack.size()) { - // we are on part of an instantiated subscene - // or part of instantiated scene. - // only save what has been changed - // only save changed properties in instance - - if ((E.usage & PROPERTY_USAGE_NO_INSTANCE_STATE) || E.name == "__meta__") { - //property has requested that no instance state is saved, sorry - //also, meta won't be overridden or saved + // If instance or inheriting, not saving if property requested so, or it's meta + if (states_stack.size()) { + if ((E.usage & PROPERTY_USAGE_NO_INSTANCE_STATE)) { continue; } - - bool exists = false; - Variant original; - - for (List<PackState>::Element *F = pack_state_stack.back(); F; F = F->prev()) { - //check all levels of pack to see if the property exists somewhere - const PackState &ps = F->get(); - - original = ps.state->get_property_value(ps.node, E.name, exists); - if (exists) { - break; - } - } - - if (exists) { - //check if already exists and did not change - if (value.get_type() == Variant::FLOAT && original.get_type() == Variant::FLOAT) { - //this must be done because, as some scenes save as text, there might be a tiny difference in floats due to numerical error - float a = value; - float b = original; - - if (Math::is_equal_approx(a, b)) { - continue; - } - } else if (bool(Variant::evaluate(Variant::OP_EQUAL, value, original))) { - continue; + // Meta is normally not saved in instances/inherited (see GH-12838), but we need to save the pinned list + if (E.name == "__meta__") { + if (pinned_props.size()) { + Dictionary meta_override; + meta_override["_edit_pinned_properties_"] = pinned_props; + forced_value = meta_override; } } + } - if (!exists && isdefault) { - //does not exist in original node, but it's the default value - //so safe to skip too. - continue; - } + StringName name = E.name; + Variant value = forced_value.get_type() == Variant::NIL ? p_node->get(name) : forced_value; - } else { - if (isdefault) { - //it's the default value, no point in saving it + if (!pinned_props.has(name) && forced_value.get_type() == Variant::NIL) { + Variant default_value = PropertyUtils::get_property_default_value(p_node, name, &states_stack, true); + if (!PropertyUtils::is_property_value_different(value, default_value)) { continue; } } @@ -585,10 +528,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map */ bool skip = false; - for (const PackState &F : pack_state_stack) { + for (const SceneState::PackState &ia : states_stack) { //check all levels of pack to see if the group was added somewhere - const PackState &ps = F; - if (ps.state->is_node_in_group(ps.node, gi.name)) { + if (ia.state->is_node_in_group(ia.node, gi.name)) { skip = true; break; } @@ -618,7 +560,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map // Save the right type. If this node was created by an instance // then flag that the node should not be created but reused - if (pack_state_stack.is_empty() && !is_editable_instance) { + if (states_stack.is_empty() && !is_editable_instance) { //this node is not part of an instancing process, so save the type nd.type = _nm_get_string(p_node->get_class(), name_map); } else { @@ -635,7 +577,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map bool save_node = nd.properties.size() || nd.groups.size(); // some local properties or groups exist save_node = save_node || p_node == p_owner; // owner is always saved - save_node = save_node || (p_node->get_owner() == p_owner && instantiated_by_owner); //part of scene and not instantiated + save_node = save_node || (p_node->get_owner() == p_owner && instantiated_by_owner); //part of scene and not instanced int idx = nodes.size(); int parent_node = NO_PARENT_SAVED; @@ -932,7 +874,7 @@ void SceneState::clear() { base_scene_idx = -1; } -Ref<SceneState> SceneState::_get_base_scene_state() const { +Ref<SceneState> SceneState::get_base_scene_state() const { if (base_scene_idx >= 0) { Ref<PackedScene> ps = variants[base_scene_idx]; if (ps.is_valid()) { @@ -947,8 +889,8 @@ int SceneState::find_node_by_path(const NodePath &p_node) const { ERR_FAIL_COND_V_MSG(node_path_cache.size() == 0, -1, "This operation requires the node cache to have been built."); if (!node_path_cache.has(p_node)) { - if (_get_base_scene_state().is_valid()) { - int idx = _get_base_scene_state()->find_node_by_path(p_node); + if (get_base_scene_state().is_valid()) { + int idx = get_base_scene_state()->find_node_by_path(p_node); if (idx != -1) { int rkey = _find_base_scene_node_remap_key(idx); if (rkey == -1) { @@ -963,11 +905,11 @@ int SceneState::find_node_by_path(const NodePath &p_node) const { int nid = node_path_cache[p_node]; - if (_get_base_scene_state().is_valid() && !base_scene_node_remap.has(nid)) { + if (get_base_scene_state().is_valid() && !base_scene_node_remap.has(nid)) { //for nodes that _do_ exist in current scene, still try to look for //the node in the instantiated scene, as a property may be missing //from the local one - int idx = _get_base_scene_state()->find_node_by_path(p_node); + int idx = get_base_scene_state()->find_node_by_path(p_node); if (idx != -1) { base_scene_node_remap[nid] = idx; } @@ -1007,7 +949,7 @@ Variant SceneState::get_property_value(int p_node, const StringName &p_property, //property not found, try on instance if (base_scene_node_remap.has(p_node)) { - return _get_base_scene_state()->get_property_value(base_scene_node_remap[p_node], p_property, found); + return get_base_scene_state()->get_property_value(base_scene_node_remap[p_node], p_property, found); } return Variant(); @@ -1026,7 +968,7 @@ bool SceneState::is_node_in_group(int p_node, const StringName &p_group) const { } if (base_scene_node_remap.has(p_node)) { - return _get_base_scene_state()->is_node_in_group(base_scene_node_remap[p_node], p_group); + return get_base_scene_state()->is_node_in_group(base_scene_node_remap[p_node], p_group); } return false; @@ -1065,7 +1007,7 @@ bool SceneState::is_connection(int p_node, const StringName &p_signal, int p_to_ } if (base_scene_node_remap.has(p_node) && base_scene_node_remap.has(p_to_node)) { - return _get_base_scene_state()->is_connection(base_scene_node_remap[p_node], p_signal, base_scene_node_remap[p_to_node], p_to_method); + return get_base_scene_state()->is_connection(base_scene_node_remap[p_node], p_signal, base_scene_node_remap[p_to_node], p_to_method); } return false; @@ -1488,7 +1430,7 @@ bool SceneState::has_connection(const NodePath &p_node_from, const StringName &p } } - ss = ss->_get_base_scene_state(); + ss = ss->get_base_scene_state(); } while (ss.is_valid()); return false; @@ -1610,6 +1552,7 @@ void SceneState::_bind_methods() { BIND_ENUM_CONSTANT(GEN_EDIT_STATE_DISABLED); BIND_ENUM_CONSTANT(GEN_EDIT_STATE_INSTANCE); BIND_ENUM_CONSTANT(GEN_EDIT_STATE_MAIN); + BIND_ENUM_CONSTANT(GEN_EDIT_STATE_MAIN_INHERITED); } SceneState::SceneState() { @@ -1651,7 +1594,7 @@ Node *PackedScene::instantiate(GenEditState p_edit_state) const { s->set_scene_instance_state(state); } - if (get_path() != "" && get_path().find("::") == -1) { + if (!is_built_in()) { s->set_scene_file_path(get_path()); } @@ -1701,6 +1644,7 @@ void PackedScene::_bind_methods() { BIND_ENUM_CONSTANT(GEN_EDIT_STATE_DISABLED); BIND_ENUM_CONSTANT(GEN_EDIT_STATE_INSTANCE); BIND_ENUM_CONSTANT(GEN_EDIT_STATE_MAIN); + BIND_ENUM_CONSTANT(GEN_EDIT_STATE_MAIN_INHERITED); } PackedScene::PackedScene() { diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index 55708f7914..a03da558e4 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -69,11 +69,6 @@ class SceneState : public RefCounted { Vector<int> groups; }; - struct PackState { - Ref<SceneState> state; - int node = -1; - }; - Vector<NodeData> nodes; struct ConnectionData { @@ -94,8 +89,6 @@ class SceneState : public RefCounted { uint64_t last_modified_time = 0; - _FORCE_INLINE_ Ref<SceneState> _get_base_scene_state() const; - static bool disable_placeholders; Vector<String> _get_node_groups(int p_idx) const; @@ -117,6 +110,12 @@ public: GEN_EDIT_STATE_DISABLED, GEN_EDIT_STATE_INSTANCE, GEN_EDIT_STATE_MAIN, + GEN_EDIT_STATE_MAIN_INHERITED, + }; + + struct PackState { + Ref<SceneState> state; + int node = -1; }; static void set_disable_placeholders(bool p_disable); @@ -139,6 +138,8 @@ public: bool can_instantiate() const; Node *instantiate(GenEditState p_edit_state) const; + Ref<SceneState> get_base_scene_state() const; + //unbuild API int get_node_count() const; @@ -207,6 +208,7 @@ public: GEN_EDIT_STATE_DISABLED, GEN_EDIT_STATE_INSTANCE, GEN_EDIT_STATE_MAIN, + GEN_EDIT_STATE_MAIN_INHERITED, }; Error pack(Node *p_scene); diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index d9ec0bfd69..e77f5a0be7 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -1413,7 +1413,7 @@ void ParticlesMaterial::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "scale_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture,CurveXYZTexture"), "set_param_texture", "get_param_texture", PARAM_SCALE); ADD_GROUP("Color", ""); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture1D"), "set_color_ramp", "get_color_ramp"); ADD_GROUP("Hue Variation", "hue_"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_min", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param_min", "get_param_min", PARAM_HUE_VARIATION); diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index 4dd3c874cb..ec2022ed2f 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -556,7 +556,7 @@ void PolygonPathFinder::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_data"), &PolygonPathFinder::_set_data); ClassDB::bind_method(D_METHOD("_get_data"), &PolygonPathFinder::_get_data); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); } PolygonPathFinder::PolygonPathFinder() { diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index 77d915aef9..ea3b72af1b 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -1492,7 +1492,7 @@ String ResourceFormatSaverTextInstance::_write_resource(const RES &res) { } else { if (internal_resources.has(res)) { return "SubResource( \"" + internal_resources[res] + "\" )"; - } else if (res->get_path().length() && res->get_path().find("::") == -1) { + } else if (!res->is_built_in()) { if (res->get_path() == local_path) { //circular reference attempt return "null"; } @@ -1515,7 +1515,7 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, return; } - if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) { + if (!p_main && (!bundle_resources) && !res->is_built_in()) { if (res->get_path() == local_path) { ERR_PRINT("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded."); return; @@ -1728,7 +1728,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) { RES res = E->get(); - if (E->next() && (res->get_path() == "" || res->get_path().find("::") != -1)) { + if (E->next() && res->is_built_in()) { if (res->get_scene_unique_id() != "") { if (used_unique_ids.has(res->get_scene_unique_id())) { res->set_scene_unique_id(""); // Repeated. diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 4ba8d4d494..9fab5791d6 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -145,7 +145,7 @@ void Shader::_bind_methods() { ClassDB::bind_method(D_METHOD("has_param", "name"), &Shader::has_param); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_code", "get_code"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_code", "get_code"); BIND_ENUM_CONSTANT(MODE_SPATIAL); BIND_ENUM_CONSTANT(MODE_CANVAS_ITEM); diff --git a/scene/resources/skeleton_modification_2d_jiggle.cpp b/scene/resources/skeleton_modification_2d_jiggle.cpp index 84abc9d020..31045455a3 100644 --- a/scene/resources/skeleton_modification_2d_jiggle.cpp +++ b/scene/resources/skeleton_modification_2d_jiggle.cpp @@ -194,9 +194,13 @@ void SkeletonModification2DJiggle::_execute_jiggle_joint(int p_joint_idx, Node2D PhysicsDirectSpaceState2D *space_state = PhysicsServer2D::get_singleton()->space_get_direct_state(world_2d->get_space()); PhysicsDirectSpaceState2D::RayResult ray_result; + PhysicsDirectSpaceState2D::RayParameters ray_params; + ray_params.from = operation_bone_trans.get_origin(); + ray_params.to = jiggle_data_chain[p_joint_idx].dynamic_position; + ray_params.collision_mask = collision_mask; + // Add exception support? - bool ray_hit = space_state->intersect_ray(operation_bone_trans.get_origin(), jiggle_data_chain[p_joint_idx].dynamic_position, - ray_result, Set<RID>(), collision_mask); + bool ray_hit = space_state->intersect_ray(ray_params, ray_result); if (ray_hit) { jiggle_data_chain.write[p_joint_idx].dynamic_position = jiggle_data_chain[p_joint_idx].last_noncollision_position; diff --git a/scene/resources/skeleton_modification_3d_jiggle.cpp b/scene/resources/skeleton_modification_3d_jiggle.cpp index a6bcb0176a..2535f2b987 100644 --- a/scene/resources/skeleton_modification_3d_jiggle.cpp +++ b/scene/resources/skeleton_modification_3d_jiggle.cpp @@ -206,8 +206,12 @@ void SkeletonModification3DJiggle::_execute_jiggle_joint(int p_joint_idx, Node3D Transform3D new_bone_trans_world = stack->skeleton->global_pose_to_world_transform(new_bone_trans); Transform3D dynamic_position_world = stack->skeleton->global_pose_to_world_transform(Transform3D(Basis(), jiggle_data_chain[p_joint_idx].dynamic_position)); - bool ray_hit = space_state->intersect_ray(new_bone_trans_world.origin, dynamic_position_world.get_origin(), - ray_result, Set<RID>(), collision_mask); + PhysicsDirectSpaceState3D::RayParameters ray_params; + ray_params.from = new_bone_trans_world.origin; + ray_params.to = dynamic_position_world.get_origin(); + ray_params.collision_mask = collision_mask; + + bool ray_hit = space_state->intersect_ray(ray_params, ray_result); if (ray_hit) { jiggle_data_chain[p_joint_idx].dynamic_position = jiggle_data_chain[p_joint_idx].last_noncollision_position; diff --git a/scene/resources/skin.cpp b/scene/resources/skin.cpp index 710612ae05..15cdb86bab 100644 --- a/scene/resources/skin.cpp +++ b/scene/resources/skin.cpp @@ -133,7 +133,7 @@ void Skin::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::INT, "bind_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater")); for (int i = 0; i < get_bind_count(); i++) { p_list->push_back(PropertyInfo(Variant::STRING_NAME, "bind/" + itos(i) + "/name")); - p_list->push_back(PropertyInfo(Variant::INT, "bind/" + itos(i) + "/bone", PROPERTY_HINT_RANGE, "0,16384,1,or_greater", get_bind_name(i) != StringName() ? PROPERTY_USAGE_NOEDITOR : PROPERTY_USAGE_DEFAULT)); + p_list->push_back(PropertyInfo(Variant::INT, "bind/" + itos(i) + "/bone", PROPERTY_HINT_RANGE, "0,16384,1,or_greater", get_bind_name(i) != StringName() ? PROPERTY_USAGE_NO_EDITOR : PROPERTY_USAGE_DEFAULT)); p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, "bind/" + itos(i) + "/pose")); } } diff --git a/scene/resources/sprite_frames.cpp b/scene/resources/sprite_frames.cpp index 01afb00283..5524d59dc7 100644 --- a/scene/resources/sprite_frames.cpp +++ b/scene/resources/sprite_frames.cpp @@ -233,7 +233,7 @@ void SpriteFrames::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_animations"), &SpriteFrames::_set_animations); ClassDB::bind_method(D_METHOD("_get_animations"), &SpriteFrames::_get_animations); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations"); //compatibility + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations"); //compatibility } SpriteFrames::SpriteFrames() { diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index 3381043d29..b960944d99 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -790,7 +790,7 @@ float StyleBoxFlat::get_style_margin(Side p_side) const { void StyleBoxFlat::_validate_property(PropertyInfo &property) const { if (!anti_aliased && property.name == "anti_aliasing_size") { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NO_EDITOR; } } diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp index fae1de94d3..1b7fc64267 100644 --- a/scene/resources/text_paragraph.cpp +++ b/scene/resources/text_paragraph.cpp @@ -38,6 +38,11 @@ void TextParagraph::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "direction", PROPERTY_HINT_ENUM, "Auto,Light-to-right,Right-to-left"), "set_direction", "get_direction"); + ClassDB::bind_method(D_METHOD("set_custom_punctuation", "custom_punctuation"), &TextParagraph::set_custom_punctuation); + ClassDB::bind_method(D_METHOD("get_custom_punctuation"), &TextParagraph::get_custom_punctuation); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "custom_punctuation"), "set_custom_punctuation", "get_custom_punctuation"); + ClassDB::bind_method(D_METHOD("set_orientation", "orientation"), &TextParagraph::set_orientation); ClassDB::bind_method(D_METHOD("get_orientation"), &TextParagraph::get_orientation); @@ -304,6 +309,15 @@ TextServer::Direction TextParagraph::get_direction() const { return TS->shaped_text_get_direction(rid); } +void TextParagraph::set_custom_punctuation(const String &p_punct) { + TS->shaped_text_set_custom_punctuation(rid, p_punct); + lines_dirty = true; +} + +String TextParagraph::get_custom_punctuation() const { + return TS->shaped_text_get_custom_punctuation(rid); +} + void TextParagraph::set_orientation(TextServer::Orientation p_orientation) { TS->shaped_text_set_orientation(rid, p_orientation); TS->shaped_text_set_orientation(dropcap_rid, p_orientation); diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h index 701c9a17cd..4c4af43d14 100644 --- a/scene/resources/text_paragraph.h +++ b/scene/resources/text_paragraph.h @@ -96,6 +96,9 @@ public: void set_bidi_override(const Array &p_override); + void set_custom_punctuation(const String &p_punct); + String get_custom_punctuation() const; + bool set_dropcap(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Dictionary &p_opentype_features = Dictionary(), const String &p_language = ""); void clear_dropcap(); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 485074e283..311bd9524b 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -1729,53 +1729,53 @@ CurveXYZTexture::~CurveXYZTexture() { ////////////////// -GradientTexture::GradientTexture() { +GradientTexture1D::GradientTexture1D() { _queue_update(); } -GradientTexture::~GradientTexture() { +GradientTexture1D::~GradientTexture1D() { if (texture.is_valid()) { RS::get_singleton()->free(texture); } } -void GradientTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_gradient", "gradient"), &GradientTexture::set_gradient); - ClassDB::bind_method(D_METHOD("get_gradient"), &GradientTexture::get_gradient); +void GradientTexture1D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_gradient", "gradient"), &GradientTexture1D::set_gradient); + ClassDB::bind_method(D_METHOD("get_gradient"), &GradientTexture1D::get_gradient); - ClassDB::bind_method(D_METHOD("set_width", "width"), &GradientTexture::set_width); + ClassDB::bind_method(D_METHOD("set_width", "width"), &GradientTexture1D::set_width); // The `get_width()` method is already exposed by the parent class Texture2D. - ClassDB::bind_method(D_METHOD("set_use_hdr", "enabled"), &GradientTexture::set_use_hdr); - ClassDB::bind_method(D_METHOD("is_using_hdr"), &GradientTexture::is_using_hdr); + ClassDB::bind_method(D_METHOD("set_use_hdr", "enabled"), &GradientTexture1D::set_use_hdr); + ClassDB::bind_method(D_METHOD("is_using_hdr"), &GradientTexture1D::is_using_hdr); - ClassDB::bind_method(D_METHOD("_update"), &GradientTexture::_update); + ClassDB::bind_method(D_METHOD("_update"), &GradientTexture1D::_update); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient"); ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr"), "set_use_hdr", "is_using_hdr"); } -void GradientTexture::set_gradient(Ref<Gradient> p_gradient) { +void GradientTexture1D::set_gradient(Ref<Gradient> p_gradient) { if (p_gradient == gradient) { return; } if (gradient.is_valid()) { - gradient->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &GradientTexture::_update)); + gradient->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &GradientTexture1D::_update)); } gradient = p_gradient; if (gradient.is_valid()) { - gradient->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &GradientTexture::_update)); + gradient->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &GradientTexture1D::_update)); } _update(); emit_changed(); } -Ref<Gradient> GradientTexture::get_gradient() const { +Ref<Gradient> GradientTexture1D::get_gradient() const { return gradient; } -void GradientTexture::_queue_update() { +void GradientTexture1D::_queue_update() { if (update_pending) { return; } @@ -1784,7 +1784,7 @@ void GradientTexture::_queue_update() { call_deferred(SNAME("_update")); } -void GradientTexture::_update() { +void GradientTexture1D::_update() { update_pending = false; if (gradient.is_null()) { @@ -1839,17 +1839,17 @@ void GradientTexture::_update() { emit_changed(); } -void GradientTexture::set_width(int p_width) { +void GradientTexture1D::set_width(int p_width) { ERR_FAIL_COND(p_width <= 0); width = p_width; _queue_update(); } -int GradientTexture::get_width() const { +int GradientTexture1D::get_width() const { return width; } -void GradientTexture::set_use_hdr(bool p_enabled) { +void GradientTexture1D::set_use_hdr(bool p_enabled) { if (p_enabled == use_hdr) { return; } @@ -1858,11 +1858,11 @@ void GradientTexture::set_use_hdr(bool p_enabled) { _queue_update(); } -bool GradientTexture::is_using_hdr() const { +bool GradientTexture1D::is_using_hdr() const { return use_hdr; } -Ref<Image> GradientTexture::get_image() const { +Ref<Image> GradientTexture1D::get_image() const { if (!texture.is_valid()) { return Ref<Image>(); } @@ -2871,15 +2871,6 @@ RID CameraTexture::get_rid() const { } } -void CameraTexture::set_flags(uint32_t p_flags) { - // not supported -} - -uint32_t CameraTexture::get_flags() const { - // not supported - return 0; -} - Ref<Image> CameraTexture::get_image() const { // not (yet) supported return Ref<Image>(); diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 51567124c6..5b69711de6 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -669,8 +669,8 @@ public: ~CurveXYZTexture(); }; -class GradientTexture : public Texture2D { - GDCLASS(GradientTexture, Texture2D); +class GradientTexture1D : public Texture2D { + GDCLASS(GradientTexture1D, Texture2D); public: struct Point { @@ -710,8 +710,8 @@ public: virtual Ref<Image> get_image() const override; - GradientTexture(); - virtual ~GradientTexture(); + GradientTexture1D(); + virtual ~GradientTexture1D(); }; class GradientTexture2D : public Texture2D { @@ -900,9 +900,6 @@ public: virtual RID get_rid() const override; virtual bool has_alpha() const override; - virtual void set_flags(uint32_t p_flags); - virtual uint32_t get_flags() const; - virtual Ref<Image> get_image() const override; void set_camera_feed_id(int p_new_id); diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 9306d19520..5256803d56 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -203,7 +203,7 @@ bool TileMapPattern::_get(const StringName &p_name, Variant &r_ret) const { } void TileMapPattern::_get_property_list(List<PropertyInfo> *p_list) const { - p_list->push_back(PropertyInfo(Variant::OBJECT, "tile_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "tile_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } void TileMapPattern::_bind_methods() { @@ -212,7 +212,7 @@ void TileMapPattern::_bind_methods() { ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE)); ClassDB::bind_method(D_METHOD("has_cell", "coords"), &TileMapPattern::has_cell); - ClassDB::bind_method(D_METHOD("remove_cell", "coords"), &TileMapPattern::remove_cell); + ClassDB::bind_method(D_METHOD("remove_cell", "coords", "update_size"), &TileMapPattern::remove_cell); ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMapPattern::get_cell_source_id); ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords"), &TileMapPattern::get_cell_atlas_coords); ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords"), &TileMapPattern::get_cell_alternative_tile); @@ -3124,19 +3124,19 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { // Sources. // Note: sources have to be listed in at the end as some TileData rely on the TileSet properties being initialized first. for (const KeyValue<int, Ref<TileSetSource>> &E_source : sources) { - p_list->push_back(PropertyInfo(Variant::INT, vformat("sources/%d", E_source.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::INT, vformat("sources/%d", E_source.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } // Tile Proxies. // Note: proxies need to be set after sources are set. p_list->push_back(PropertyInfo(Variant::NIL, "Tile Proxies", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); - p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/source_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/coords_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/alternative_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/source_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/coords_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/alternative_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); // Patterns. for (unsigned int pattern_index = 0; pattern_index < patterns.size(); pattern_index++) { - p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("pattern_%d", pattern_index), PROPERTY_HINT_RESOURCE_TYPE, "TileMapPattern", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("pattern_%d", pattern_index), PROPERTY_HINT_RESOURCE_TYPE, "TileMapPattern", PROPERTY_USAGE_NO_EDITOR)); } } @@ -3737,35 +3737,35 @@ void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const { List<PropertyInfo> tile_property_list; // size_in_atlas - property_info = PropertyInfo(Variant::VECTOR2I, "size_in_atlas", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR); + property_info = PropertyInfo(Variant::VECTOR2I, "size_in_atlas", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR); if (E_tile.value.size_in_atlas == Vector2i(1, 1)) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } tile_property_list.push_back(property_info); // next_alternative_id - property_info = PropertyInfo(Variant::INT, "next_alternative_id", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR); + property_info = PropertyInfo(Variant::INT, "next_alternative_id", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR); if (E_tile.value.next_alternative_id == 1) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } tile_property_list.push_back(property_info); // animation_columns. - property_info = PropertyInfo(Variant::INT, "animation_columns", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR); + property_info = PropertyInfo(Variant::INT, "animation_columns", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR); if (E_tile.value.animation_columns == 0) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } tile_property_list.push_back(property_info); // animation_separation. - property_info = PropertyInfo(Variant::INT, "animation_separation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR); + property_info = PropertyInfo(Variant::INT, "animation_separation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR); if (E_tile.value.animation_separation == Vector2i()) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } tile_property_list.push_back(property_info); // animation_speed. - property_info = PropertyInfo(Variant::FLOAT, "animation_speed", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR); + property_info = PropertyInfo(Variant::FLOAT, "animation_speed", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR); if (E_tile.value.animation_speed == 1.0) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } @@ -3777,7 +3777,7 @@ void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const { // animation_frame_*. bool store_durations = tiles[E_tile.key].animation_frames_durations.size() >= 2; for (int i = 0; i < (int)tiles[E_tile.key].animation_frames_durations.size(); i++) { - property_info = PropertyInfo(Variant::FLOAT, vformat("animation_frame_%d/duration", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR); + property_info = PropertyInfo(Variant::FLOAT, vformat("animation_frame_%d/duration", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR); if (!store_durations) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } @@ -3786,7 +3786,7 @@ void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const { for (const KeyValue<int, TileData *> &E_alternative : E_tile.value.alternatives) { // Add a dummy property to show the alternative exists. - tile_property_list.push_back(PropertyInfo(Variant::INT, vformat("%d", E_alternative.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + tile_property_list.push_back(PropertyInfo(Variant::INT, vformat("%d", E_alternative.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); // Get the alternative tile's properties and append them to the list of properties. List<PropertyInfo> alternative_property_list; @@ -4205,10 +4205,10 @@ void TileSetAtlasSource::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture_region_size", "texture_region_size"), &TileSetAtlasSource::set_texture_region_size); ClassDB::bind_method(D_METHOD("get_texture_region_size"), &TileSetAtlasSource::get_texture_region_size); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_NOEDITOR), "set_texture", "get_texture"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_margins", "get_margins"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_separation", "get_separation"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "texture_region_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_texture_region_size", "get_texture_region_size"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_NO_EDITOR), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_margins", "get_margins"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_separation", "get_separation"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "texture_region_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_texture_region_size", "get_texture_region_size"); // Base tiles ClassDB::bind_method(D_METHOD("create_tile", "atlas_coords", "size"), &TileSetAtlasSource::create_tile, DEFVAL(Vector2i(1, 1))); diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index fd785631a8..0aa79b8ceb 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -199,6 +199,10 @@ Vector<StringName> VisualShaderNode::get_editable_properties() const { return Vector<StringName>(); } +Map<StringName, String> VisualShaderNode::get_editable_properties_names() const { + return Map<StringName, String>(); +} + Array VisualShaderNode::get_default_input_values() const { Array ret; for (const KeyValue<int, Variant> &E : default_input_values) { @@ -246,8 +250,8 @@ void VisualShaderNode::_bind_methods() { ClassDB::bind_method(D_METHOD("get_default_input_values"), &VisualShaderNode::get_default_input_values); ADD_PROPERTY(PropertyInfo(Variant::INT, "output_port_for_preview"), "set_output_port_for_preview", "get_output_port_for_preview"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_default_input_values", "get_default_input_values"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "expanded_output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_output_ports_expanded", "_get_output_ports_expanded"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_default_input_values", "get_default_input_values"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "expanded_output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_output_ports_expanded", "_get_output_ports_expanded"); ADD_SIGNAL(MethodInfo("editor_refresh_request")); BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR); @@ -431,7 +435,7 @@ void VisualShaderNodeCustom::_bind_methods() { ClassDB::bind_method(D_METHOD("_is_initialized"), &VisualShaderNodeCustom::_is_initialized); ClassDB::bind_method(D_METHOD("_set_input_port_default_value", "port", "value"), &VisualShaderNodeCustom::_set_input_port_default_value); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "initialized", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_initialized", "_is_initialized"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "initialized", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_initialized", "_is_initialized"); } VisualShaderNodeCustom::VisualShaderNodeCustom() { @@ -1291,20 +1295,20 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { prop_name += "/" + itos(E.key); if (E.key != NODE_ID_OUTPUT) { - p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "VisualShaderNode", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE)); + p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "VisualShaderNode", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE)); } - p_list->push_back(PropertyInfo(Variant::VECTOR2, prop_name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, prop_name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); if (Object::cast_to<VisualShaderNodeGroupBase>(E.value.node.ptr()) != nullptr) { - p_list->push_back(PropertyInfo(Variant::VECTOR2, prop_name + "/size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/input_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, prop_name + "/size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/input_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } if (Object::cast_to<VisualShaderNodeExpression>(E.value.node.ptr()) != nullptr) { - p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/expression", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/expression", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } } - p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "nodes/" + String(type_string[i]) + "/connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "nodes/" + String(type_string[i]) + "/connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } } @@ -1922,6 +1926,10 @@ void VisualShader::_update_shader() const { global_compute_code += " return mat4(vec4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0), vec4(oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0), vec4(oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0), vec4(0, 0, 0, 1));\n"; global_compute_code += "}\n\n"; + global_compute_code += "vec2 __get_random_unit_vec2(inout uint seed) {\n"; + global_compute_code += " return normalize(vec2(__rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed)));\n"; + global_compute_code += "}\n\n"; + global_compute_code += "vec3 __get_random_unit_vec3(inout uint seed) {\n"; global_compute_code += " return normalize(vec3(__rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed)));\n"; global_compute_code += "}\n\n"; @@ -2017,8 +2025,8 @@ void VisualShader::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_shader"), &VisualShader::_update_shader); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_graph_offset", "get_graph_offset"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "engine_version", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_engine_version", "get_engine_version"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_graph_offset", "get_graph_offset"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "engine_version", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_engine_version", "get_engine_version"); ADD_PROPERTY_DEFAULT("code", ""); // Inherited from Shader, prevents showing default code as override in docs. @@ -2850,7 +2858,7 @@ void VisualShaderNodeUniformRef::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_uniform_type"), &VisualShaderNodeUniformRef::_get_uniform_type); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "uniform_name", PROPERTY_HINT_ENUM, ""), "set_uniform_name", "get_uniform_name"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "uniform_type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_uniform_type", "_get_uniform_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "uniform_type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_uniform_type", "_get_uniform_type"); } Vector<StringName> VisualShaderNodeUniformRef::get_editable_properties() const { diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 19530e5a34..7743affba7 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -272,6 +272,7 @@ public: void set_disabled(bool p_disabled = true); virtual Vector<StringName> get_editable_properties() const; + virtual Map<StringName, String> get_editable_properties_names() const; virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp index 18b933e5cf..ada91cec1e 100644 --- a/scene/resources/visual_shader_particle_nodes.cpp +++ b/scene/resources/visual_shader_particle_nodes.cpp @@ -51,6 +51,38 @@ bool VisualShaderNodeParticleEmitter::has_output_port_preview(int p_port) const return false; } +void VisualShaderNodeParticleEmitter::set_mode_2d(bool p_enabled) { + mode_2d = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeParticleEmitter::is_mode_2d() const { + return mode_2d; +} + +Vector<StringName> VisualShaderNodeParticleEmitter::get_editable_properties() const { + Vector<StringName> props; + props.push_back("mode_2d"); + return props; +} + +Map<StringName, String> VisualShaderNodeParticleEmitter::get_editable_properties_names() const { + Map<StringName, String> names; + names.insert("mode_2d", TTR("2D Mode")); + return names; +} + +bool VisualShaderNodeParticleEmitter::is_show_prop_names() const { + return true; +} + +void VisualShaderNodeParticleEmitter::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mode_2d", "enabled"), &VisualShaderNodeParticleEmitter::set_mode_2d); + ClassDB::bind_method(D_METHOD("is_mode_2d"), &VisualShaderNodeParticleEmitter::is_mode_2d); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_2d"), "set_mode_2d", "is_mode_2d"); +} + VisualShaderNodeParticleEmitter::VisualShaderNodeParticleEmitter() { } @@ -79,15 +111,27 @@ String VisualShaderNodeParticleSphereEmitter::get_input_port_name(int p_port) co String VisualShaderNodeParticleSphereEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code; + + code += "vec2 __get_random_point_in_circle(inout uint seed, float radius, float inner_radius) {\n"; + code += " return __get_random_unit_vec2(seed) * __randf_range(seed, inner_radius, radius);\n"; + code += "}\n\n"; + code += "vec3 __get_random_point_in_sphere(inout uint seed, float radius, float inner_radius) {\n"; code += " return __get_random_unit_vec3(seed) * __randf_range(seed, inner_radius, radius);\n"; code += "}\n\n"; + return code; } String VisualShaderNodeParticleSphereEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; - code += " " + p_output_vars[0] + " = __get_random_point_in_sphere(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n"; + + if (mode_2d) { + code += " " + p_output_vars[0] + " = vec3(__get_random_point_in_circle(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + "), 0.0);\n"; + } else { + code += " " + p_output_vars[0] + " = __get_random_point_in_sphere(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n"; + } + return code; } @@ -122,16 +166,27 @@ String VisualShaderNodeParticleBoxEmitter::get_input_port_name(int p_port) const String VisualShaderNodeParticleBoxEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code; - code += "vec3 __get_random_point_in_box(inout uint seed, vec3 extents) {\n"; + + code += "vec2 __get_random_point_in_box2d(inout uint seed, vec2 extents) {\n"; + code += " vec2 half_extents = extents / 2.0;\n"; + code += " return vec2(__randf_range(seed, -half_extents.x, half_extents.x), __randf_range(seed, -half_extents.y, half_extents.y));\n"; + code += "}\n\n"; + + code += "vec3 __get_random_point_in_box3d(inout uint seed, vec3 extents) {\n"; code += " vec3 half_extents = extents / 2.0;\n"; code += " return vec3(__randf_range(seed, -half_extents.x, half_extents.x), __randf_range(seed, -half_extents.y, half_extents.y), __randf_range(seed, -half_extents.z, half_extents.z));\n"; code += "}\n\n"; + return code; } String VisualShaderNodeParticleBoxEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; - code += " " + p_output_vars[0] + " = __get_random_point_in_box(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ");\n"; + if (mode_2d) { + code += " " + p_output_vars[0] + " = vec3(__get_random_point_in_box2d(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ".xy), 0.0);\n"; + } else { + code += " " + p_output_vars[0] + " = __get_random_point_in_box3d(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ");\n"; + } return code; } @@ -166,17 +221,31 @@ String VisualShaderNodeParticleRingEmitter::get_input_port_name(int p_port) cons String VisualShaderNodeParticleRingEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code; - code += "vec3 __get_random_point_on_ring(inout uint seed, float radius, float inner_radius, float height) {\n"; - code += " float angle = __rand_from_seed(seed) * PI * 2.0;\n"; + + code += "vec2 __get_random_point_on_ring2d(inout uint seed, float radius, float inner_radius) {\n"; + code += " float angle = __rand_from_seed(seed) * TAU;\n"; + code += " vec2 ring = vec2(sin(angle), cos(angle)) * __randf_range(seed, inner_radius, radius);\n"; + code += " return vec2(ring.x, ring.y);\n"; + code += "}\n\n"; + + code += "vec3 __get_random_point_on_ring3d(inout uint seed, float radius, float inner_radius, float height) {\n"; + code += " float angle = __rand_from_seed(seed) * TAU;\n"; code += " vec2 ring = vec2(sin(angle), cos(angle)) * __randf_range(seed, inner_radius, radius);\n"; code += " return vec3(ring.x, __randf_range(seed, min(0.0, height), max(0.0, height)), ring.y);\n"; code += "}\n\n"; + return code; } String VisualShaderNodeParticleRingEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; - code = " " + p_output_vars[0] + " = __get_random_point_on_ring(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ", " + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ");\n"; + + if (mode_2d) { + code = " " + p_output_vars[0] + " = vec3(__get_random_point_on_ring2d(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + "), 0.0);\n"; + } else { + code = " " + p_output_vars[0] + " = __get_random_point_on_ring3d(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ", " + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ");\n"; + } + return code; } diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h index b8bc7992cc..0b1fa277de 100644 --- a/scene/resources/visual_shader_particle_nodes.h +++ b/scene/resources/visual_shader_particle_nodes.h @@ -38,12 +38,23 @@ class VisualShaderNodeParticleEmitter : public VisualShaderNode { GDCLASS(VisualShaderNodeParticleEmitter, VisualShaderNode); +protected: + bool mode_2d = false; + static void _bind_methods(); + public: virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; virtual bool has_output_port_preview(int p_port) const override; + void set_mode_2d(bool p_enabled); + bool is_mode_2d() const; + + Vector<StringName> get_editable_properties() const override; + Map<StringName, String> get_editable_properties_names() const override; + bool is_show_prop_names() const override; + VisualShaderNodeParticleEmitter(); }; diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index ab704c6f78..774a5b1da0 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1864,16 +1864,16 @@ bool AudioBusLayout::_get(const StringName &p_name, Variant &r_ret) const { void AudioBusLayout::_get_property_list(List<PropertyInfo> *p_list) const { for (int i = 0; i < buses.size(); i++) { - p_list->push_back(PropertyInfo(Variant::STRING, "bus/" + itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/solo", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/mute", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/bypass_fx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::FLOAT, "bus/" + itos(i) + "/volume_db", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::FLOAT, "bus/" + itos(i) + "/send", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::STRING, "bus/" + itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/solo", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/mute", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/bypass_fx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::FLOAT, "bus/" + itos(i) + "/volume_db", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::FLOAT, "bus/" + itos(i) + "/send", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); for (int j = 0; j < buses[i].effects.size(); j++) { - p_list->push_back(PropertyInfo(Variant::OBJECT, "bus/" + itos(i) + "/effect/" + itos(j) + "/effect", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/effect/" + itos(j) + "/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "bus/" + itos(i) + "/effect/" + itos(j) + "/effect", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/effect/" + itos(j) + "/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } } } diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index d72014a8ed..5c189aa06a 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -54,13 +54,13 @@ _FORCE_INLINE_ static bool _can_collide_with(GodotCollisionObject2D *p_object, u return true; } -int GodotPhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) { +int GodotPhysicsDirectSpaceState2D::intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) { if (p_result_max <= 0) { return 0; } Rect2 aabb; - aabb.position = p_point - Vector2(0.00001, 0.00001); + aabb.position = p_parameters.position - Vector2(0.00001, 0.00001); aabb.size = Vector2(0.00002, 0.00002); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -68,21 +68,21 @@ int GodotPhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point int cc = 0; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; - if (p_pick_point && !col_obj->is_pickable()) { + if (p_parameters.pick_point && !col_obj->is_pickable()) { continue; } - if (p_filter_by_canvas && col_obj->get_canvas_instance_id() != p_canvas_instance_id) { + if (p_parameters.canvas_instance_id.is_valid() && col_obj->get_canvas_instance_id() != p_parameters.canvas_instance_id) { continue; } @@ -90,7 +90,7 @@ int GodotPhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point GodotShape2D *shape = col_obj->get_shape(shape_idx); - Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_point); + Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_parameters.position); if (!shape->contains_point(local_point)) { continue; @@ -113,21 +113,13 @@ int GodotPhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point return cc; } -int GodotPhysicsDirectSpaceState2D::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) { - return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point); -} - -int GodotPhysicsDirectSpaceState2D::intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) { - return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point, true, p_canvas_instance_id); -} - -bool GodotPhysicsDirectSpaceState2D::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +bool GodotPhysicsDirectSpaceState2D::intersect_ray(const RayParameters &p_parameters, RayResult &r_result) { ERR_FAIL_COND_V(space->locked, false); Vector2 begin, end; Vector2 normal; - begin = p_from; - end = p_to; + begin = p_parameters.from; + end = p_parameters.to; normal = (end - begin).normalized(); int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -141,11 +133,11 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const Vector2 &p_from, const real_t min_d = 1e10; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } @@ -157,12 +149,6 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const Vector2 &p_from, const Vector2 local_from = inv_xform.xform(begin); Vector2 local_to = inv_xform.xform(end); - /*local_from = col_obj->get_inv_transform().xform(begin); - local_from = col_obj->get_shape_inv_transform(shape_idx).xform(local_from); - - local_to = col_obj->get_inv_transform().xform(end); - local_to = col_obj->get_shape_inv_transform(shape_idx).xform(local_to);*/ - const GodotShape2D *shape = col_obj->get_shape(shape_idx); Vector2 shape_point, shape_normal; @@ -200,16 +186,17 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const Vector2 &p_from, const return true; } -int GodotPhysicsDirectSpaceState2D::intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +int GodotPhysicsDirectSpaceState2D::intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) { if (p_result_max <= 0) { return 0; } - GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - Rect2 aabb = p_xform.xform(shape->get_aabb()); - aabb = aabb.grow(p_margin); + Rect2 aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -220,18 +207,18 @@ int GodotPhysicsDirectSpaceState2D::intersect_shape(const RID &p_shape, const Tr break; } - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; int shape_idx = space->intersection_query_subindex_results[i]; - if (!GodotCollisionSolver2D::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), nullptr, nullptr, nullptr, p_margin)) { + if (!GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), nullptr, nullptr, nullptr, p_parameters.margin)) { continue; } @@ -248,13 +235,13 @@ int GodotPhysicsDirectSpaceState2D::intersect_shape(const RID &p_shape, const Tr return cc; } -bool GodotPhysicsDirectSpaceState2D::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState2D::cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe) { + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, false); - Rect2 aabb = p_xform.xform(shape->get_aabb()); - aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion - aabb = aabb.grow(p_margin); + Rect2 aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -262,11 +249,11 @@ bool GodotPhysicsDirectSpaceState2D::cast_motion(const RID &p_shape, const Trans real_t best_unsafe = 1; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; //ignore excluded } @@ -275,16 +262,16 @@ bool GodotPhysicsDirectSpaceState2D::cast_motion(const RID &p_shape, const Trans Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? - if (!GodotCollisionSolver2D::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) { + if (!GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_parameters.margin)) { continue; } //test initial overlap, ignore objects it's inside of. - if (GodotCollisionSolver2D::solve(shape, p_xform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) { + if (GodotCollisionSolver2D::solve(shape, p_parameters.transform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_parameters.margin)) { continue; } - Vector2 mnormal = p_motion.normalized(); + Vector2 mnormal = p_parameters.motion.normalized(); //just do kinematic solving real_t low = 0.0; @@ -294,7 +281,7 @@ bool GodotPhysicsDirectSpaceState2D::cast_motion(const RID &p_shape, const Trans real_t fraction = low + (hi - low) * fraction_coeff; Vector2 sep = mnormal; //important optimization for this to work fast enough - bool collided = GodotCollisionSolver2D::solve(shape, p_xform, p_motion * fraction, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, &sep, p_margin); + bool collided = GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion * fraction, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, &sep, p_parameters.margin); if (collided) { hi = fraction; @@ -331,17 +318,17 @@ bool GodotPhysicsDirectSpaceState2D::cast_motion(const RID &p_shape, const Trans return true; } -bool GodotPhysicsDirectSpaceState2D::collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +bool GodotPhysicsDirectSpaceState2D::collide_shape(const ShapeParameters &p_parameters, Vector2 *r_results, int p_result_max, int &r_result_count) { if (p_result_max <= 0) { return false; } - GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - Rect2 aabb = p_shape_xform.xform(shape->get_aabb()); - aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion - aabb = aabb.grow(p_margin); + Rect2 aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -358,13 +345,13 @@ bool GodotPhysicsDirectSpaceState2D::collide_shape(RID p_shape, const Transform2 GodotPhysicsServer2D::CollCbkData *cbkptr = &cbk; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude.has(col_obj->get_self())) { continue; } @@ -373,7 +360,7 @@ bool GodotPhysicsDirectSpaceState2D::collide_shape(RID p_shape, const Transform2 cbk.valid_dir = Vector2(); cbk.valid_depth = 0; - if (GodotCollisionSolver2D::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, nullptr, p_margin)) { + if (GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, nullptr, p_parameters.margin)) { collided = cbk.amount > 0; } } @@ -432,15 +419,15 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, rd->best_local_shape = rd->local_shape; } -bool GodotPhysicsDirectSpaceState2D::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState2D::rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) { + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; + real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; - Rect2 aabb = p_shape_xform.xform(shape->get_aabb()); - aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion - aabb = aabb.grow(p_margin); + Rect2 aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -451,13 +438,13 @@ bool GodotPhysicsDirectSpaceState2D::rest_info(RID p_shape, const Transform2D &p rcd.min_allowed_depth = min_contact_depth; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude.has(col_obj->get_self())) { continue; } @@ -467,7 +454,7 @@ bool GodotPhysicsDirectSpaceState2D::rest_info(RID p_shape, const Transform2D &p rcd.object = col_obj; rcd.shape = shape_idx; rcd.local_shape = 0; - bool sc = GodotCollisionSolver2D::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, nullptr, p_margin); + bool sc = GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, nullptr, p_parameters.margin); if (!sc) { continue; } diff --git a/servers/physics_2d/godot_space_2d.h b/servers/physics_2d/godot_space_2d.h index 97e2928a9d..b155a834b6 100644 --- a/servers/physics_2d/godot_space_2d.h +++ b/servers/physics_2d/godot_space_2d.h @@ -45,18 +45,15 @@ class GodotPhysicsDirectSpaceState2D : public PhysicsDirectSpaceState2D { GDCLASS(GodotPhysicsDirectSpaceState2D, PhysicsDirectSpaceState2D); - int _intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID()); - public: GodotSpace2D *space = nullptr; - virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override; - virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override; - virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; + virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override; + virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override; + virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override; + virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe) override; + virtual bool collide_shape(const ShapeParameters &p_parameters, Vector2 *r_results, int p_result_max, int &r_result_count) override; + virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override; GodotPhysicsDirectSpaceState2D() {} }; diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index 3010315571..84ec0e3c63 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -255,11 +255,7 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta, int p_iterations) // Warning: _solve_island modifies the constraint islands for optimization purpose, // their content is not reliable after these calls and shouldn't be used anymore. - if (island_count > 1) { - work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr); - } else if (island_count > 0) { - _solve_island(0); - } + work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr); { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); diff --git a/servers/physics_3d/godot_collision_object_3d.cpp b/servers/physics_3d/godot_collision_object_3d.cpp index 80a3d18ce0..deb058b3ac 100644 --- a/servers/physics_3d/godot_collision_object_3d.cpp +++ b/servers/physics_3d/godot_collision_object_3d.cpp @@ -171,7 +171,7 @@ void GodotCollisionObject3D::_update_shapes() { s.aabb_cache = shape_aabb; Vector3 scale = xform.get_basis().get_scale(); - s.area_cache = s.shape->get_area() * scale.x * scale.y * scale.z; + s.area_cache = s.shape->get_volume() * scale.x * scale.y * scale.z; if (s.bpid == 0) { s.bpid = space->get_broadphase()->create(this, i, shape_aabb, _static); diff --git a/servers/physics_3d/godot_shape_3d.h b/servers/physics_3d/godot_shape_3d.h index 8822d9487b..1bbcd903f7 100644 --- a/servers/physics_3d/godot_shape_3d.h +++ b/servers/physics_3d/godot_shape_3d.h @@ -64,7 +64,7 @@ public: FEATURE_CIRCLE, }; - virtual real_t get_area() const { return aabb.get_area(); } + virtual real_t get_volume() const { return aabb.get_volume(); } _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } _FORCE_INLINE_ RID get_self() const { return self; } @@ -120,7 +120,7 @@ class GodotWorldBoundaryShape3D : public GodotShape3D { public: Plane get_plane() const; - virtual real_t get_area() const override { return INFINITY; } + virtual real_t get_volume() const override { return INFINITY; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_WORLD_BOUNDARY; } virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; @@ -147,7 +147,7 @@ public: real_t get_length() const; bool get_slide_on_slope() const; - virtual real_t get_area() const override { return 0.0; } + virtual real_t get_volume() const override { return 0.0; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_SEPARATION_RAY; } virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; @@ -173,7 +173,7 @@ class GodotSphereShape3D : public GodotShape3D { public: real_t get_radius() const; - virtual real_t get_area() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius; } + virtual real_t get_volume() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_SPHERE; } @@ -198,7 +198,7 @@ class GodotBoxShape3D : public GodotShape3D { public: _FORCE_INLINE_ Vector3 get_half_extents() const { return half_extents; } - virtual real_t get_area() const override { return 8 * half_extents.x * half_extents.y * half_extents.z; } + virtual real_t get_volume() const override { return 8 * half_extents.x * half_extents.y * half_extents.z; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_BOX; } @@ -227,7 +227,7 @@ public: _FORCE_INLINE_ real_t get_height() const { return height; } _FORCE_INLINE_ real_t get_radius() const { return radius; } - virtual real_t get_area() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius + (height - radius * 2.0) * Math_PI * radius * radius; } + virtual real_t get_volume() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius + (height - radius * 2.0) * Math_PI * radius * radius; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CAPSULE; } @@ -256,7 +256,7 @@ public: _FORCE_INLINE_ real_t get_height() const { return height; } _FORCE_INLINE_ real_t get_radius() const { return radius; } - virtual real_t get_area() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; } + virtual real_t get_volume() const override { return height * Math_PI * radius * radius; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CYLINDER; } diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index 750bf3a16d..77b37a2353 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -57,9 +57,9 @@ _FORCE_INLINE_ static bool _can_collide_with(GodotCollisionObject3D *p_object, u return true; } -int GodotPhysicsDirectSpaceState3D::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +int GodotPhysicsDirectSpaceState3D::intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) { ERR_FAIL_COND_V(space->locked, false); - int amount = space->broadphase->cull_point(p_point, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_point(p_parameters.position, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); int cc = 0; //Transform3D ai = p_xform.affine_inverse(); @@ -69,13 +69,13 @@ int GodotPhysicsDirectSpaceState3D::intersect_point(const Vector3 &p_point, Shap break; } - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } //area can't be picked by ray (default) - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } @@ -85,7 +85,7 @@ int GodotPhysicsDirectSpaceState3D::intersect_point(const Vector3 &p_point, Shap Transform3D inv_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); inv_xform.affine_invert(); - if (!col_obj->get_shape(shape_idx)->intersect_point(inv_xform.xform(p_point))) { + if (!col_obj->get_shape(shape_idx)->intersect_point(inv_xform.xform(p_parameters.position))) { continue; } @@ -104,13 +104,13 @@ int GodotPhysicsDirectSpaceState3D::intersect_point(const Vector3 &p_point, Shap return cc; } -bool GodotPhysicsDirectSpaceState3D::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) { +bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parameters, RayResult &r_result) { ERR_FAIL_COND_V(space->locked, false); Vector3 begin, end; Vector3 normal; - begin = p_from; - end = p_to; + begin = p_parameters.from; + end = p_parameters.to; normal = (end - begin).normalized(); int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -124,15 +124,15 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const Vector3 &p_from, const real_t min_d = 1e10; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_pick_ray && !(space->intersection_query_results[i]->is_ray_pickable())) { + if (p_parameters.pick_ray && !(space->intersection_query_results[i]->is_ray_pickable())) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } @@ -183,15 +183,15 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const Vector3 &p_from, const return true; } -int GodotPhysicsDirectSpaceState3D::intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +int GodotPhysicsDirectSpaceState3D::intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) { if (p_result_max <= 0) { return 0; } - GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - AABB aabb = p_xform.xform(shape->get_aabb()); + AABB aabb = p_parameters.transform.xform(shape->get_aabb()); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -204,20 +204,20 @@ int GodotPhysicsDirectSpaceState3D::intersect_shape(const RID &p_shape, const Tr break; } - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } //area can't be picked by ray (default) - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; int shape_idx = space->intersection_query_subindex_results[i]; - if (!GodotCollisionSolver3D::solve_static(shape, p_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), nullptr, nullptr, nullptr, p_margin, 0)) { + if (!GodotCollisionSolver3D::solve_static(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), nullptr, nullptr, nullptr, p_parameters.margin, 0)) { continue; } @@ -238,36 +238,36 @@ int GodotPhysicsDirectSpaceState3D::intersect_shape(const RID &p_shape, const Tr return cc; } -bool GodotPhysicsDirectSpaceState3D::cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) { - GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState3D::cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info) { + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, false); - AABB aabb = p_xform.xform(shape->get_aabb()); - aabb = aabb.merge(AABB(aabb.position + p_motion, aabb.size)); //motion - aabb = aabb.grow(p_margin); + AABB aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.merge(AABB(aabb.position + p_parameters.motion, aabb.size)); //motion + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); real_t best_safe = 1; real_t best_unsafe = 1; - Transform3D xform_inv = p_xform.affine_inverse(); + Transform3D xform_inv = p_parameters.transform.affine_inverse(); GodotMotionShape3D mshape; mshape.shape = shape; - mshape.motion = xform_inv.basis.xform(p_motion); + mshape.motion = xform_inv.basis.xform(p_parameters.motion); bool best_first = true; - Vector3 motion_normal = p_motion.normalized(); + Vector3 motion_normal = p_parameters.motion.normalized(); Vector3 closest_A, closest_B; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; //ignore excluded } @@ -279,14 +279,14 @@ bool GodotPhysicsDirectSpaceState3D::cast_motion(const RID &p_shape, const Trans Transform3D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? - if (GodotCollisionSolver3D::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { + if (GodotCollisionSolver3D::solve_distance(&mshape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { continue; } //test initial overlap, ignore objects it's inside of. sep_axis = motion_normal; - if (!GodotCollisionSolver3D::solve_distance(shape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { + if (!GodotCollisionSolver3D::solve_distance(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { continue; } @@ -297,11 +297,11 @@ bool GodotPhysicsDirectSpaceState3D::cast_motion(const RID &p_shape, const Trans for (int j = 0; j < 8; j++) { //steps should be customizable.. real_t fraction = low + (hi - low) * fraction_coeff; - mshape.motion = xform_inv.basis.xform(p_motion * fraction); + mshape.motion = xform_inv.basis.xform(p_parameters.motion * fraction); Vector3 lA, lB; Vector3 sep = motion_normal; //important optimization for this to work fast enough - bool collided = !GodotCollisionSolver3D::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, aabb, &sep); + bool collided = !GodotCollisionSolver3D::solve_distance(&mshape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, aabb, &sep); if (collided) { hi = fraction; @@ -357,16 +357,16 @@ bool GodotPhysicsDirectSpaceState3D::cast_motion(const RID &p_shape, const Trans return true; } -bool GodotPhysicsDirectSpaceState3D::collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +bool GodotPhysicsDirectSpaceState3D::collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) { if (p_result_max <= 0) { return false; } - GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - AABB aabb = p_shape_xform.xform(shape->get_aabb()); - aabb = aabb.grow(p_margin); + AABB aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -382,19 +382,19 @@ bool GodotPhysicsDirectSpaceState3D::collide_shape(RID p_shape, const Transform3 GodotPhysicsServer3D::CollCbkData *cbkptr = &cbk; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude.has(col_obj->get_self())) { continue; } int shape_idx = space->intersection_query_subindex_results[i]; - if (GodotCollisionSolver3D::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) { + if (GodotCollisionSolver3D::solve_static(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_parameters.margin)) { collided = true; } } @@ -487,14 +487,14 @@ static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vect rd->best_result.local_shape = rd->local_shape; } -bool GodotPhysicsDirectSpaceState3D::rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState3D::rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) { + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; + real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; - AABB aabb = p_shape_xform.xform(shape->get_aabb()); - aabb = aabb.grow(p_margin); + AABB aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -502,13 +502,13 @@ bool GodotPhysicsDirectSpaceState3D::rest_info(RID p_shape, const Transform3D &p rcd.min_allowed_depth = min_contact_depth; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude.has(col_obj->get_self())) { continue; } @@ -516,7 +516,7 @@ bool GodotPhysicsDirectSpaceState3D::rest_info(RID p_shape, const Transform3D &p rcd.object = col_obj; rcd.shape = shape_idx; - bool sc = GodotCollisionSolver3D::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin); + bool sc = GodotCollisionSolver3D::solve_static(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_parameters.margin); if (!sc) { continue; } diff --git a/servers/physics_3d/godot_space_3d.h b/servers/physics_3d/godot_space_3d.h index 3b36dd346c..aa5e965751 100644 --- a/servers/physics_3d/godot_space_3d.h +++ b/servers/physics_3d/godot_space_3d.h @@ -49,12 +49,12 @@ class GodotPhysicsDirectSpaceState3D : public PhysicsDirectSpaceState3D { public: GodotSpace3D *space; - virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) override; - virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) override; - virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; + virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override; + virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override; + virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override; + virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info = nullptr) override; + virtual bool collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) override; + virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override; virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override; GodotPhysicsDirectSpaceState3D(); diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index a8654c617b..331d65df49 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -359,11 +359,7 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta, int p_iterations) // Warning: _solve_island modifies the constraint islands for optimization purpose, // their content is not reliable after these calls and shouldn't be used anymore. - if (island_count > 1) { - work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr); - } else if (island_count > 0) { - _solve_island(0); - } + work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr); { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index a9d83d567a..fa89ccec65 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -136,95 +136,132 @@ PhysicsDirectBodyState2D::PhysicsDirectBodyState2D() {} /////////////////////////////////////////////////////// -void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape_ref) { - ERR_FAIL_COND(p_shape_ref.is_null()); - shape_ref = p_shape_ref; - shape = p_shape_ref->get_rid(); -} - -RES PhysicsShapeQueryParameters2D::get_shape() const { - return shape_ref; -} - -void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) { - if (shape != p_shape) { - shape_ref = RES(); - shape = p_shape; +void PhysicsRayQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); + for (int i = 0; i < p_exclude.size(); i++) { + parameters.exclude.insert(p_exclude[i]); } } -RID PhysicsShapeQueryParameters2D::get_shape_rid() const { - return shape; +Vector<RID> PhysicsRayQueryParameters2D::get_exclude() const { + Vector<RID> ret; + ret.resize(parameters.exclude.size()); + int idx = 0; + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + ret.write[idx++] = E->get(); + } + return ret; } -void PhysicsShapeQueryParameters2D::set_transform(const Transform2D &p_transform) { - transform = p_transform; -} +void PhysicsRayQueryParameters2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters2D::set_from); + ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters2D::get_from); -Transform2D PhysicsShapeQueryParameters2D::get_transform() const { - return transform; -} + ClassDB::bind_method(D_METHOD("set_to", "to"), &PhysicsRayQueryParameters2D::set_to); + ClassDB::bind_method(D_METHOD("get_to"), &PhysicsRayQueryParameters2D::get_to); -void PhysicsShapeQueryParameters2D::set_motion(const Vector2 &p_motion) { - motion = p_motion; -} + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsRayQueryParameters2D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsRayQueryParameters2D::get_collision_mask); -Vector2 PhysicsShapeQueryParameters2D::get_motion() const { - return motion; -} + ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsRayQueryParameters2D::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsRayQueryParameters2D::get_exclude); -void PhysicsShapeQueryParameters2D::set_margin(real_t p_margin) { - margin = p_margin; -} + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsRayQueryParameters2D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsRayQueryParameters2D::is_collide_with_bodies_enabled); -real_t PhysicsShapeQueryParameters2D::get_margin() const { - return margin; -} + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters2D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters2D::is_collide_with_areas_enabled); -void PhysicsShapeQueryParameters2D::set_collision_mask(uint32_t p_collision_mask) { - collision_mask = p_collision_mask; + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "from"), "set_from", "get_from"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "to"), "set_to", "get_to"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); } -uint32_t PhysicsShapeQueryParameters2D::get_collision_mask() const { - return collision_mask; -} +/////////////////////////////////////////////////////// -void PhysicsShapeQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { - exclude.clear(); +void PhysicsPointQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); + parameters.exclude.insert(p_exclude[i]); } } -Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const { +Vector<RID> PhysicsPointQueryParameters2D::get_exclude() const { Vector<RID> ret; - ret.resize(exclude.size()); + ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = exclude.front(); E; E = E->next()) { + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; } -void PhysicsShapeQueryParameters2D::set_collide_with_bodies(bool p_enable) { - collide_with_bodies = p_enable; +void PhysicsPointQueryParameters2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_position", "position"), &PhysicsPointQueryParameters2D::set_position); + ClassDB::bind_method(D_METHOD("get_position"), &PhysicsPointQueryParameters2D::get_position); + + ClassDB::bind_method(D_METHOD("set_canvas_instance_id", "canvas_instance_id"), &PhysicsPointQueryParameters2D::set_canvas_instance_id); + ClassDB::bind_method(D_METHOD("get_canvas_instance_id"), &PhysicsPointQueryParameters2D::get_canvas_instance_id); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsPointQueryParameters2D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsPointQueryParameters2D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsPointQueryParameters2D::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsPointQueryParameters2D::get_exclude); + + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsPointQueryParameters2D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsPointQueryParameters2D::is_collide_with_bodies_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsPointQueryParameters2D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsPointQueryParameters2D::is_collide_with_areas_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_instance_id", PROPERTY_HINT_OBJECT_ID), "set_canvas_instance_id", "get_canvas_instance_id"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); +} + +/////////////////////////////////////////////////////// + +void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape_ref) { + ERR_FAIL_COND(p_shape_ref.is_null()); + shape_ref = p_shape_ref; + parameters.shape_rid = p_shape_ref->get_rid(); } -bool PhysicsShapeQueryParameters2D::is_collide_with_bodies_enabled() const { - return collide_with_bodies; +void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) { + if (parameters.shape_rid != p_shape) { + shape_ref = RES(); + parameters.shape_rid = p_shape; + } } -void PhysicsShapeQueryParameters2D::set_collide_with_areas(bool p_enable) { - collide_with_areas = p_enable; +void PhysicsShapeQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); + for (int i = 0; i < p_exclude.size(); i++) { + parameters.exclude.insert(p_exclude[i]); + } } -bool PhysicsShapeQueryParameters2D::is_collide_with_areas_enabled() const { - return collide_with_areas; +Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const { + Vector<RID> ret; + ret.resize(parameters.exclude.size()); + int idx = 0; + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + ret.write[idx++] = E->get(); + } + return ret; } void PhysicsShapeQueryParameters2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters2D::set_shape); ClassDB::bind_method(D_METHOD("get_shape"), &PhysicsShapeQueryParameters2D::get_shape); + ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters2D::set_shape_rid); ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters2D::get_shape_rid); @@ -250,7 +287,7 @@ void PhysicsShapeQueryParameters2D::_bind_methods() { ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsShapeQueryParameters2D::is_collide_with_areas_enabled); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::RID) + ":"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape"); @@ -260,36 +297,58 @@ void PhysicsShapeQueryParameters2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); } -Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { - RayResult inters; - Set<RID> exclude; - for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); - } +/////////////////////////////////////////////////////// - bool res = intersect_ray(p_from, p_to, inters, exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); +Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Ref<PhysicsRayQueryParameters2D> &p_ray_query) { + ERR_FAIL_COND_V(!p_ray_query.is_valid(), Dictionary()); + + RayResult result; + bool res = intersect_ray(p_ray_query->get_parameters(), result); if (!res) { return Dictionary(); } Dictionary d; - d["position"] = inters.position; - d["normal"] = inters.normal; - d["collider_id"] = inters.collider_id; - d["collider"] = inters.collider; - d["shape"] = inters.shape; - d["rid"] = inters.rid; + d["position"] = result.position; + d["normal"] = result.normal; + d["collider_id"] = result.collider_id; + d["collider"] = result.collider; + d["shape"] = result.shape; + d["rid"] = result.rid; return d; } +Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results) { + Vector<ShapeResult> ret; + ret.resize(p_max_results); + + int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size()); + + if (rc == 0) { + return Array(); + } + + Array r; + r.resize(rc); + for (int i = 0; i < rc; i++) { + Dictionary d; + d["rid"] = ret[i].rid; + d["collider_id"] = ret[i].collider_id; + d["collider"] = ret[i].collider; + d["shape"] = ret[i].shape; + r[i] = d; + } + return r; +} + Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); Vector<ShapeResult> sr; sr.resize(p_max_results); - int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size()); Array ret; ret.resize(rc); for (int i = 0; i < rc; i++) { @@ -308,7 +367,7 @@ Array PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParamet ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); real_t closest_safe, closest_unsafe; - bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe); if (!res) { return Array(); } @@ -319,54 +378,13 @@ Array PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParamet return ret; } -Array PhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) { - Set<RID> exclude; - for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); - } - - Vector<ShapeResult> ret; - ret.resize(p_max_results); - - int rc; - if (p_filter_by_canvas) { - rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); - } else { - rc = intersect_point_on_canvas(p_point, p_canvas_instance_id, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); - } - - if (rc == 0) { - return Array(); - } - - Array r; - r.resize(rc); - for (int i = 0; i < rc; i++) { - Dictionary d; - d["rid"] = ret[i].rid; - d["collider_id"] = ret[i].collider_id; - d["collider"] = ret[i].collider; - d["shape"] = ret[i].shape; - r[i] = d; - } - return r; -} - -Array PhysicsDirectSpaceState2D::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { - return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); -} - -Array PhysicsDirectSpaceState2D::_intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { - return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas, true, p_canvas_intance_id); -} - Array PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); Vector<Vector2> ret; ret.resize(p_max_results * 2); int rc = 0; - bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc); if (!res) { return Array(); } @@ -383,7 +401,7 @@ Dictionary PhysicsDirectSpaceState2D::_get_rest_info(const Ref<PhysicsShapeQuery ShapeRestInfo sri; - bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = rest_info(p_shape_query->get_parameters(), &sri); Dictionary r; if (!res) { return r; @@ -403,13 +421,12 @@ PhysicsDirectSpaceState2D::PhysicsDirectSpaceState2D() { } void PhysicsDirectSpaceState2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_ray, DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_intersect_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &PhysicsDirectSpaceState2D::_cast_motion); - ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_collide_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &PhysicsDirectSpaceState2D::_get_rest_info); + ClassDB::bind_method(D_METHOD("intersect_point", "parameters", "max_results"), &PhysicsDirectSpaceState2D::_intersect_point, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("intersect_ray", "parameters"), &PhysicsDirectSpaceState2D::_intersect_ray); + ClassDB::bind_method(D_METHOD("intersect_shape", "parameters", "max_results"), &PhysicsDirectSpaceState2D::_intersect_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("cast_motion", "parameters"), &PhysicsDirectSpaceState2D::_cast_motion); + ClassDB::bind_method(D_METHOD("collide_shape", "parameters", "max_results"), &PhysicsDirectSpaceState2D::_collide_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("get_rest_info", "parameters"), &PhysicsDirectSpaceState2D::_get_rest_info); } /////////////////////////////// @@ -475,7 +492,7 @@ void PhysicsTestMotionParameters2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects"); } diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index cb86aedeaf..fec03a8111 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -95,60 +95,15 @@ public: PhysicsDirectBodyState2D(); }; -//used for script -class PhysicsShapeQueryParameters2D : public RefCounted { - GDCLASS(PhysicsShapeQueryParameters2D, RefCounted); - friend class PhysicsDirectSpaceState2D; - - RES shape_ref; - RID shape; - Transform2D transform; - Vector2 motion; - real_t margin = 0.0; - Set<RID> exclude; - uint32_t collision_mask = UINT32_MAX; - - bool collide_with_bodies = true; - bool collide_with_areas = false; - -protected: - static void _bind_methods(); - -public: - void set_shape(const RES &p_shape_ref); - RES get_shape() const; - void set_shape_rid(const RID &p_shape); - RID get_shape_rid() const; - - void set_transform(const Transform2D &p_transform); - Transform2D get_transform() const; - - void set_motion(const Vector2 &p_motion); - Vector2 get_motion() const; - - void set_margin(real_t p_margin); - real_t get_margin() const; - - void set_collision_mask(uint32_t p_mask); - uint32_t get_collision_mask() const; - - void set_collide_with_bodies(bool p_enable); - bool is_collide_with_bodies_enabled() const; - - void set_collide_with_areas(bool p_enable); - bool is_collide_with_areas_enabled() const; - - void set_exclude(const Vector<RID> &p_exclude); - Vector<RID> get_exclude() const; -}; +class PhysicsRayQueryParameters2D; +class PhysicsPointQueryParameters2D; +class PhysicsShapeQueryParameters2D; class PhysicsDirectSpaceState2D : public Object { GDCLASS(PhysicsDirectSpaceState2D, Object); - Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclud, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID()); + Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters2D> &p_ray_query); + Array _intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results = 32); Array _intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32); Array _cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query); Array _collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32); @@ -158,6 +113,16 @@ protected: static void _bind_methods(); public: + struct RayParameters { + Vector2 from; + Vector2 to; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; + + bool collide_with_bodies = true; + bool collide_with_areas = false; + }; + struct RayResult { Vector2 position; Vector2 normal; @@ -167,7 +132,7 @@ public: int shape = 0; }; - virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) = 0; struct ShapeResult { RID rid; @@ -176,14 +141,31 @@ public: int shape = 0; }; - virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0; - virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0; + struct PointParameters { + Vector2 position; + ObjectID canvas_instance_id; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; + + bool collide_with_bodies = true; + bool collide_with_areas = false; - virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + bool pick_point = false; + }; + + virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0; - virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + struct ShapeParameters { + RID shape_rid; + Transform2D transform; + Vector2 motion; + real_t margin = 0.0; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; - virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + bool collide_with_bodies = true; + bool collide_with_areas = false; + }; struct ShapeRestInfo { Vector2 point; @@ -191,10 +173,13 @@ public: RID rid; ObjectID collider_id; int shape = 0; - Vector2 linear_velocity; //velocity at contact point + Vector2 linear_velocity; // Velocity at contact point. }; - virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0; + virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe) = 0; + virtual bool collide_shape(const ShapeParameters &p_parameters, Vector2 *r_results, int p_result_max, int &r_result_count) = 0; + virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) = 0; PhysicsDirectSpaceState2D(); }; @@ -593,6 +578,107 @@ public: ~PhysicsServer2D(); }; +class PhysicsRayQueryParameters2D : public RefCounted { + GDCLASS(PhysicsRayQueryParameters2D, RefCounted); + + PhysicsDirectSpaceState2D::RayParameters parameters; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState2D::RayParameters &get_parameters() const { return parameters; } + + void set_from(const Vector2 &p_from) { parameters.from = p_from; } + const Vector2 &get_from() const { return parameters.from; } + + void set_to(const Vector2 &p_to) { parameters.to = p_to; } + const Vector2 &get_to() const { return parameters.to; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + +class PhysicsPointQueryParameters2D : public RefCounted { + GDCLASS(PhysicsPointQueryParameters2D, RefCounted); + + PhysicsDirectSpaceState2D::PointParameters parameters; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState2D::PointParameters &get_parameters() const { return parameters; } + + void set_position(const Vector2 &p_position) { parameters.position = p_position; } + const Vector2 &get_position() const { return parameters.position; } + + void set_canvas_instance_id(ObjectID p_canvas_instance_id) { parameters.canvas_instance_id = p_canvas_instance_id; } + ObjectID get_canvas_instance_id() const { return parameters.canvas_instance_id; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + +class PhysicsShapeQueryParameters2D : public RefCounted { + GDCLASS(PhysicsShapeQueryParameters2D, RefCounted); + + PhysicsDirectSpaceState2D::ShapeParameters parameters; + + RES shape_ref; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState2D::ShapeParameters &get_parameters() const { return parameters; } + + void set_shape(const RES &p_shape_ref); + RES get_shape() const { return shape_ref; } + + void set_shape_rid(const RID &p_shape); + RID get_shape_rid() const { return parameters.shape_rid; } + + void set_transform(const Transform2D &p_transform) { parameters.transform = p_transform; } + const Transform2D &get_transform() const { return parameters.transform; } + + void set_motion(const Vector2 &p_motion) { parameters.motion = p_motion; } + const Vector2 &get_motion() const { return parameters.motion; } + + void set_margin(real_t p_margin) { parameters.margin = p_margin; } + real_t get_margin() const { return parameters.margin; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + class PhysicsTestMotionParameters2D : public RefCounted { GDCLASS(PhysicsTestMotionParameters2D, RefCounted); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index fb1e9f1f89..eb52cbfe5a 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -139,93 +139,137 @@ PhysicsDirectBodyState3D::PhysicsDirectBodyState3D() {} /////////////////////////////////////////////////////// -void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape_ref) { - ERR_FAIL_COND(p_shape_ref.is_null()); - shape_ref = p_shape_ref; - shape = p_shape_ref->get_rid(); -} - -RES PhysicsShapeQueryParameters3D::get_shape() const { - return shape_ref; +void PhysicsRayQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); + for (int i = 0; i < p_exclude.size(); i++) { + parameters.exclude.insert(p_exclude[i]); + } } -void PhysicsShapeQueryParameters3D::set_shape_rid(const RID &p_shape) { - if (shape != p_shape) { - shape_ref = RES(); - shape = p_shape; +Vector<RID> PhysicsRayQueryParameters3D::get_exclude() const { + Vector<RID> ret; + ret.resize(parameters.exclude.size()); + int idx = 0; + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + ret.write[idx++] = E->get(); } + return ret; } -RID PhysicsShapeQueryParameters3D::get_shape_rid() const { - return shape; -} +void PhysicsRayQueryParameters3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters3D::set_from); + ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters3D::get_from); -void PhysicsShapeQueryParameters3D::set_transform(const Transform3D &p_transform) { - transform = p_transform; -} + ClassDB::bind_method(D_METHOD("set_to", "to"), &PhysicsRayQueryParameters3D::set_to); + ClassDB::bind_method(D_METHOD("get_to"), &PhysicsRayQueryParameters3D::get_to); -Transform3D PhysicsShapeQueryParameters3D::get_transform() const { - return transform; -} + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsRayQueryParameters3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsRayQueryParameters3D::get_collision_mask); -void PhysicsShapeQueryParameters3D::set_margin(real_t p_margin) { - margin = p_margin; -} + ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsRayQueryParameters3D::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsRayQueryParameters3D::get_exclude); -real_t PhysicsShapeQueryParameters3D::get_margin() const { - return margin; -} + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsRayQueryParameters3D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsRayQueryParameters3D::is_collide_with_bodies_enabled); -void PhysicsShapeQueryParameters3D::set_collision_mask(uint32_t p_collision_mask) { - collision_mask = p_collision_mask; -} + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters3D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters3D::is_collide_with_areas_enabled); -uint32_t PhysicsShapeQueryParameters3D::get_collision_mask() const { - return collision_mask; + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "from"), "set_from", "get_from"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "to"), "set_to", "get_to"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); } -void PhysicsShapeQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) { - exclude.clear(); +/////////////////////////////////////////////////////// + +void PhysicsPointQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); + parameters.exclude.insert(p_exclude[i]); } } -Vector<RID> PhysicsShapeQueryParameters3D::get_exclude() const { +Vector<RID> PhysicsPointQueryParameters3D::get_exclude() const { Vector<RID> ret; - ret.resize(exclude.size()); + ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = exclude.front(); E; E = E->next()) { + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; } -void PhysicsShapeQueryParameters3D::set_collide_with_bodies(bool p_enable) { - collide_with_bodies = p_enable; +void PhysicsPointQueryParameters3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_position", "position"), &PhysicsPointQueryParameters3D::set_position); + ClassDB::bind_method(D_METHOD("get_position"), &PhysicsPointQueryParameters3D::get_position); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsPointQueryParameters3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsPointQueryParameters3D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsPointQueryParameters3D::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsPointQueryParameters3D::get_exclude); + + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsPointQueryParameters3D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsPointQueryParameters3D::is_collide_with_bodies_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsPointQueryParameters3D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsPointQueryParameters3D::is_collide_with_areas_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); } -bool PhysicsShapeQueryParameters3D::is_collide_with_bodies_enabled() const { - return collide_with_bodies; +/////////////////////////////////////////////////////// + +void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape_ref) { + ERR_FAIL_COND(p_shape_ref.is_null()); + shape_ref = p_shape_ref; + parameters.shape_rid = p_shape_ref->get_rid(); } -void PhysicsShapeQueryParameters3D::set_collide_with_areas(bool p_enable) { - collide_with_areas = p_enable; +void PhysicsShapeQueryParameters3D::set_shape_rid(const RID &p_shape) { + if (parameters.shape_rid != p_shape) { + shape_ref = RES(); + parameters.shape_rid = p_shape; + } } -bool PhysicsShapeQueryParameters3D::is_collide_with_areas_enabled() const { - return collide_with_areas; +void PhysicsShapeQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); + for (int i = 0; i < p_exclude.size(); i++) { + parameters.exclude.insert(p_exclude[i]); + } +} + +Vector<RID> PhysicsShapeQueryParameters3D::get_exclude() const { + Vector<RID> ret; + ret.resize(parameters.exclude.size()); + int idx = 0; + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + ret.write[idx++] = E->get(); + } + return ret; } void PhysicsShapeQueryParameters3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters3D::set_shape); ClassDB::bind_method(D_METHOD("get_shape"), &PhysicsShapeQueryParameters3D::get_shape); + ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters3D::set_shape_rid); ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters3D::get_shape_rid); ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsShapeQueryParameters3D::set_transform); ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsShapeQueryParameters3D::get_transform); + ClassDB::bind_method(D_METHOD("set_motion", "motion"), &PhysicsShapeQueryParameters3D::set_motion); + ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsShapeQueryParameters3D::get_motion); + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &PhysicsShapeQueryParameters3D::set_margin); ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsShapeQueryParameters3D::get_margin); @@ -242,8 +286,9 @@ void PhysicsShapeQueryParameters3D::_bind_methods() { ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsShapeQueryParameters3D::is_collide_with_areas_enabled); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::RID) + ":"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform"), "set_transform", "get_transform"); @@ -253,36 +298,56 @@ void PhysicsShapeQueryParameters3D::_bind_methods() { ///////////////////////////////////// -Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - RayResult inters; - Set<RID> exclude; - for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); - } +Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Ref<PhysicsRayQueryParameters3D> &p_ray_query) { + ERR_FAIL_COND_V(!p_ray_query.is_valid(), Dictionary()); - bool res = intersect_ray(p_from, p_to, inters, exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas); + RayResult result; + bool res = intersect_ray(p_ray_query->get_parameters(), result); if (!res) { return Dictionary(); } Dictionary d; - d["position"] = inters.position; - d["normal"] = inters.normal; - d["collider_id"] = inters.collider_id; - d["collider"] = inters.collider; - d["shape"] = inters.shape; - d["rid"] = inters.rid; + d["position"] = result.position; + d["normal"] = result.normal; + d["collider_id"] = result.collider_id; + d["collider"] = result.collider; + d["shape"] = result.shape; + d["rid"] = result.rid; return d; } +Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results) { + Vector<ShapeResult> ret; + ret.resize(p_max_results); + + int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size()); + + if (rc == 0) { + return Array(); + } + + Array r; + r.resize(rc); + for (int i = 0; i < rc; i++) { + Dictionary d; + d["rid"] = ret[i].rid; + d["collider_id"] = ret[i].collider_id; + d["collider"] = ret[i].collider; + d["shape"] = ret[i].shape; + r[i] = d; + } + return r; +} + Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); Vector<ShapeResult> sr; sr.resize(p_max_results); - int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size()); Array ret; ret.resize(rc); for (int i = 0; i < rc; i++) { @@ -297,11 +362,11 @@ Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryPar return ret; } -Array PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, const Vector3 &p_motion) { +Array PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); real_t closest_safe = 1.0f, closest_unsafe = 1.0f; - bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe); if (!res) { return Array(); } @@ -318,7 +383,7 @@ Array PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParam Vector<Vector3> ret; ret.resize(p_max_results * 2); int rc = 0; - bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc); if (!res) { return Array(); } @@ -335,7 +400,7 @@ Dictionary PhysicsDirectSpaceState3D::_get_rest_info(const Ref<PhysicsShapeQuery ShapeRestInfo sri; - bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = rest_info(p_shape_query->get_parameters(), &sri); Dictionary r; if (!res) { return r; @@ -355,11 +420,12 @@ PhysicsDirectSpaceState3D::PhysicsDirectSpaceState3D() { } void PhysicsDirectSpaceState3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState3D::_intersect_ray, DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState3D::_intersect_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("cast_motion", "shape", "motion"), &PhysicsDirectSpaceState3D::_cast_motion); - ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState3D::_collide_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &PhysicsDirectSpaceState3D::_get_rest_info); + ClassDB::bind_method(D_METHOD("intersect_point", "parameters", "max_results"), &PhysicsDirectSpaceState3D::_intersect_point, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("intersect_ray", "parameters"), &PhysicsDirectSpaceState3D::_intersect_ray); + ClassDB::bind_method(D_METHOD("intersect_shape", "parameters", "max_results"), &PhysicsDirectSpaceState3D::_intersect_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("cast_motion", "parameters"), &PhysicsDirectSpaceState3D::_cast_motion); + ClassDB::bind_method(D_METHOD("collide_shape", "parameters", "max_results"), &PhysicsDirectSpaceState3D::_collide_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("get_rest_info", "parameters"), &PhysicsDirectSpaceState3D::_get_rest_info); } /////////////////////////////// @@ -429,7 +495,7 @@ void PhysicsTestMotionParameters3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_collisions"), "set_max_collisions", "get_max_collisions"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects"); } diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 56a0febd37..b5113fd35f 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -97,55 +97,18 @@ public: PhysicsDirectBodyState3D(); }; -class PhysicsShapeQueryParameters3D : public RefCounted { - GDCLASS(PhysicsShapeQueryParameters3D, RefCounted); - friend class PhysicsDirectSpaceState3D; - - RES shape_ref; - RID shape; - Transform3D transform; - real_t margin = 0.0; - Set<RID> exclude; - uint32_t collision_mask = UINT32_MAX; - - bool collide_with_bodies = true; - bool collide_with_areas = false; - -protected: - static void _bind_methods(); - -public: - void set_shape(const RES &p_shape_ref); - RES get_shape() const; - void set_shape_rid(const RID &p_shape); - RID get_shape_rid() const; - - void set_transform(const Transform3D &p_transform); - Transform3D get_transform() const; - - void set_margin(real_t p_margin); - real_t get_margin() const; - - void set_collision_mask(uint32_t p_collision_mask); - uint32_t get_collision_mask() const; - - void set_exclude(const Vector<RID> &p_exclude); - Vector<RID> get_exclude() const; - - void set_collide_with_bodies(bool p_enable); - bool is_collide_with_bodies_enabled() const; - - void set_collide_with_areas(bool p_enable); - bool is_collide_with_areas_enabled() const; -}; +class PhysicsRayQueryParameters3D; +class PhysicsPointQueryParameters3D; +class PhysicsShapeQueryParameters3D; class PhysicsDirectSpaceState3D : public Object { GDCLASS(PhysicsDirectSpaceState3D, Object); private: - Dictionary _intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters3D> &p_ray_query); + Array _intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results = 32); Array _intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32); - Array _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, const Vector3 &p_motion); + Array _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query); Array _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32); Dictionary _get_rest_info(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query); @@ -153,27 +116,58 @@ protected: static void _bind_methods(); public: - struct ShapeResult { + struct RayParameters { + Vector3 from; + Vector3 to; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; + + bool collide_with_bodies = true; + bool collide_with_areas = false; + + bool pick_ray = false; + }; + + struct RayResult { + Vector3 position; + Vector3 normal; RID rid; ObjectID collider_id; Object *collider = nullptr; int shape = 0; }; - virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) = 0; - struct RayResult { - Vector3 position; - Vector3 normal; + struct ShapeResult { RID rid; ObjectID collider_id; Object *collider = nullptr; int shape = 0; }; - virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0; + struct PointParameters { + Vector3 position; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; + + bool collide_with_bodies = true; + bool collide_with_areas = false; + }; - virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0; + + struct ShapeParameters { + RID shape_rid; + Transform3D transform; + Vector3 motion; + real_t margin = 0.0; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; + + bool collide_with_bodies = true; + bool collide_with_areas = false; + }; struct ShapeRestInfo { Vector3 point; @@ -181,14 +175,13 @@ public: RID rid; ObjectID collider_id; int shape = 0; - Vector3 linear_velocity; //velocity at contact point + Vector3 linear_velocity; // Velocity at contact point. }; - virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) = 0; - - virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - - virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0; + virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info = nullptr) = 0; + virtual bool collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) = 0; + virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) = 0; virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const = 0; @@ -786,6 +779,104 @@ public: ~PhysicsServer3D(); }; +class PhysicsRayQueryParameters3D : public RefCounted { + GDCLASS(PhysicsRayQueryParameters3D, RefCounted); + + PhysicsDirectSpaceState3D::RayParameters parameters; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState3D::RayParameters &get_parameters() const { return parameters; } + + void set_from(const Vector3 &p_from) { parameters.from = p_from; } + const Vector3 &get_from() const { return parameters.from; } + + void set_to(const Vector3 &p_to) { parameters.to = p_to; } + const Vector3 &get_to() const { return parameters.to; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + +class PhysicsPointQueryParameters3D : public RefCounted { + GDCLASS(PhysicsPointQueryParameters3D, RefCounted); + + PhysicsDirectSpaceState3D::PointParameters parameters; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState3D::PointParameters &get_parameters() const { return parameters; } + + void set_position(const Vector3 &p_position) { parameters.position = p_position; } + const Vector3 &get_position() const { return parameters.position; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + +class PhysicsShapeQueryParameters3D : public RefCounted { + GDCLASS(PhysicsShapeQueryParameters3D, RefCounted); + + PhysicsDirectSpaceState3D::ShapeParameters parameters; + + RES shape_ref; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState3D::ShapeParameters &get_parameters() const { return parameters; } + + void set_shape(const RES &p_shape_ref); + RES get_shape() const { return shape_ref; } + + void set_shape_rid(const RID &p_shape); + RID get_shape_rid() const { return parameters.shape_rid; } + + void set_transform(const Transform3D &p_transform) { parameters.transform = p_transform; } + const Transform3D &get_transform() const { return parameters.transform; } + + void set_motion(const Vector3 &p_motion) { parameters.motion = p_motion; } + const Vector3 &get_motion() const { return parameters.motion; } + + void set_margin(real_t p_margin) { parameters.margin = p_margin; } + real_t get_margin() const { return parameters.margin; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + class PhysicsTestMotionParameters3D : public RefCounted { GDCLASS(PhysicsTestMotionParameters3D, RefCounted); diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 8be9c2114f..7004b2317c 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -209,13 +209,17 @@ void register_server_types() { GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2D); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2D); + GDREGISTER_CLASS(PhysicsRayQueryParameters2D); + GDREGISTER_CLASS(PhysicsPointQueryParameters2D); + GDREGISTER_CLASS(PhysicsShapeQueryParameters2D); GDREGISTER_CLASS(PhysicsTestMotionParameters2D); GDREGISTER_CLASS(PhysicsTestMotionResult2D); - GDREGISTER_CLASS(PhysicsShapeQueryParameters2D); - GDREGISTER_CLASS(PhysicsShapeQueryParameters3D); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3D); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3D); + GDREGISTER_CLASS(PhysicsRayQueryParameters3D); + GDREGISTER_CLASS(PhysicsPointQueryParameters3D); + GDREGISTER_CLASS(PhysicsShapeQueryParameters3D); GDREGISTER_CLASS(PhysicsTestMotionParameters3D); GDREGISTER_CLASS(PhysicsTestMotionResult3D); diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h index da614877c4..2cf7821668 100644 --- a/servers/rendering/rendering_device_binds.h +++ b/servers/rendering/rendering_device_binds.h @@ -427,7 +427,7 @@ protected: ClassDB::bind_method(D_METHOD("_set_versions", "versions"), &RDShaderFile::_set_versions); ClassDB::bind_method(D_METHOD("_get_versions"), &RDShaderFile::_get_versions); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_versions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_versions", "_get_versions"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_versions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_versions", "_get_versions"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_error"), "set_base_error", "get_base_error"); } }; diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 107c9f8040..2ce9a20b6b 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -64,14 +64,8 @@ void RenderingServerDefault::_free(RID p_rid) { /* EVENT QUEUING */ -void RenderingServerDefault::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) { - ERR_FAIL_NULL(p_where); - FrameDrawnCallbacks fdc; - fdc.object = p_where->get_instance_id(); - fdc.method = p_method; - fdc.param = p_userdata; - - frame_drawn_callbacks.push_back(fdc); +void RenderingServerDefault::request_frame_drawn_callback(const Callable &p_callable) { + frame_drawn_callbacks.push_back(p_callable); } void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { @@ -103,15 +97,13 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { RSG::scene->update_visibility_notifiers(); while (frame_drawn_callbacks.front()) { - Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object); - if (obj) { - Callable::CallError ce; - const Variant *v = &frame_drawn_callbacks.front()->get().param; - obj->call(frame_drawn_callbacks.front()->get().method, &v, 1, ce); - if (ce.error != Callable::CallError::CALL_OK) { - String err = Variant::get_call_error_text(obj, frame_drawn_callbacks.front()->get().method, &v, 1, ce); - ERR_PRINT("Error calling frame drawn function: " + err); - } + Callable c = frame_drawn_callbacks.front()->get(); + Variant result; + Callable::CallError ce; + c.call(nullptr, 0, result, ce); + if (ce.error != Callable::CallError::CALL_OK) { + String err = Variant::get_callable_error_text(c, nullptr, 0, ce); + ERR_PRINT("Error calling frame drawn function: " + err); } frame_drawn_callbacks.pop_front(); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index a25bd3dae5..9a592a9265 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -58,13 +58,7 @@ class RenderingServerDefault : public RenderingServer { static int changes; RID test_cube; - struct FrameDrawnCallbacks { - ObjectID object; - StringName method; - Variant param; - }; - - List<FrameDrawnCallbacks> frame_drawn_callbacks; + List<Callable> frame_drawn_callbacks; static void _changes_changed() {} @@ -880,7 +874,7 @@ public: /* EVENT QUEUING */ - virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) override; + virtual void request_frame_drawn_callback(const Callable &p_callable) override; virtual void draw(bool p_swap_buffers, double frame_step) override; virtual void sync() override; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 1b16949768..cdf7fa530e 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2701,7 +2701,7 @@ void RenderingServer::_bind_methods() { /* Misc */ - ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "where", "method", "userdata"), &RenderingServer::request_frame_drawn_callback); + ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "callable"), &RenderingServer::request_frame_drawn_callback); ClassDB::bind_method(D_METHOD("has_changed"), &RenderingServer::has_changed); ClassDB::bind_method(D_METHOD("get_rendering_info", "info"), &RenderingServer::get_rendering_info); ClassDB::bind_method(D_METHOD("get_video_adapter_name"), &RenderingServer::get_video_adapter_name); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 3125268e1c..f35a633bf3 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1435,10 +1435,10 @@ public: virtual void free(RID p_rid) = 0; ///< free RIDs associated with the rendering server - virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) = 0; - /* EVENT QUEUING */ + virtual void request_frame_drawn_callback(const Callable &p_callable) = 0; + virtual void draw(bool p_swap_buffers = true, double frame_step = 0.0) = 0; virtual void sync() = 0; virtual bool has_changed() const = 0; diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index a44fee7c95..0a7523e33a 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -55,6 +55,15 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(_font_set_data, "font_rid", "data"); GDVIRTUAL_BIND(_font_set_data_ptr, "font_rid", "data_ptr", "data_size"); + GDVIRTUAL_BIND(_font_set_style, "font_rid", "style"); + GDVIRTUAL_BIND(_font_get_style, "font_rid"); + + GDVIRTUAL_BIND(_font_set_name, "font_rid", "name"); + GDVIRTUAL_BIND(_font_get_name, "font_rid"); + + GDVIRTUAL_BIND(_font_set_style_name, "font_rid", "name_style"); + GDVIRTUAL_BIND(_font_get_style_name, "font_rid"); + GDVIRTUAL_BIND(_font_set_antialiased, "font_rid", "antialiased"); GDVIRTUAL_BIND(_font_is_antialiased, "font_rid"); @@ -185,6 +194,9 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(_shaped_text_set_bidi_override, "shaped", "override"); + GDVIRTUAL_BIND(_shaped_text_set_custom_punctuation, "shaped", "punct"); + GDVIRTUAL_BIND(_shaped_text_get_custom_punctuation, "shaped"); + GDVIRTUAL_BIND(_shaped_text_set_orientation, "shaped", "orientation"); GDVIRTUAL_BIND(_shaped_text_get_orientation, "shaped"); @@ -368,6 +380,42 @@ void TextServerExtension::font_set_data_ptr(RID p_font_rid, const uint8_t *p_dat GDVIRTUAL_CALL(_font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size); } +void TextServerExtension::font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) { + GDVIRTUAL_CALL(_font_set_style, p_font_rid, p_style); +} + +uint32_t /*FontStyle*/ TextServerExtension::font_get_style(RID p_font_rid) const { + uint32_t ret; + if (GDVIRTUAL_CALL(_font_get_style, p_font_rid, ret)) { + return ret; + } + return 0; +} + +void TextServerExtension::font_set_style_name(RID p_font_rid, const String &p_name) { + GDVIRTUAL_CALL(_font_set_style_name, p_font_rid, p_name); +} + +String TextServerExtension::font_get_style_name(RID p_font_rid) const { + String ret; + if (GDVIRTUAL_CALL(_font_get_style_name, p_font_rid, ret)) { + return ret; + } + return String(); +} + +void TextServerExtension::font_set_name(RID p_font_rid, const String &p_name) { + GDVIRTUAL_CALL(_font_set_name, p_font_rid, p_name); +} + +String TextServerExtension::font_get_name(RID p_font_rid) const { + String ret; + if (GDVIRTUAL_CALL(_font_get_name, p_font_rid, ret)) { + return ret; + } + return String(); +} + void TextServerExtension::font_set_antialiased(RID p_font_rid, bool p_antialiased) { GDVIRTUAL_CALL(_font_set_antialiased, p_font_rid, p_antialiased); } @@ -906,6 +954,18 @@ void TextServerExtension::shaped_text_set_bidi_override(RID p_shaped, const Arra GDVIRTUAL_CALL(_shaped_text_set_bidi_override, p_shaped, p_override); } +void TextServerExtension::shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) { + GDVIRTUAL_CALL(_shaped_text_set_custom_punctuation, p_shaped, p_punct); +} + +String TextServerExtension::shaped_text_get_custom_punctuation(RID p_shaped) const { + String ret; + if (GDVIRTUAL_CALL(_shaped_text_get_custom_punctuation, p_shaped, ret)) { + return ret; + } + return String(); +} + void TextServerExtension::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) { GDVIRTUAL_CALL(_shaped_text_set_preserve_invalid, p_shaped, p_enabled); } diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index 954b2cf660..e419b4055d 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -84,6 +84,21 @@ public: GDVIRTUAL2(_font_set_data, RID, const PackedByteArray &); GDVIRTUAL3(_font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, uint64_t); + virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) override; + virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const override; + GDVIRTUAL2(_font_set_style, RID, uint32_t); + GDVIRTUAL1RC(uint32_t, _font_get_style, RID); + + virtual void font_set_name(RID p_font_rid, const String &p_name) override; + virtual String font_get_name(RID p_font_rid) const override; + GDVIRTUAL2(_font_set_name, RID, const String &); + GDVIRTUAL1RC(String, _font_get_name, RID); + + virtual void font_set_style_name(RID p_font_rid, const String &p_name) override; + virtual String font_get_style_name(RID p_font_rid) const override; + GDVIRTUAL2(_font_set_style_name, RID, const String &); + GDVIRTUAL1RC(String, _font_get_style_name, RID); + virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) override; virtual bool font_is_antialiased(RID p_font_rid) const override; GDVIRTUAL2(_font_set_antialiased, RID, bool); @@ -301,6 +316,11 @@ public: virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override; GDVIRTUAL2(_shaped_text_set_bidi_override, RID, const Array &); + virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) override; + virtual String shaped_text_get_custom_punctuation(RID p_shaped) const override; + GDVIRTUAL2(_shaped_text_set_custom_punctuation, RID, String); + GDVIRTUAL1RC(String, _shaped_text_get_custom_punctuation, RID); + virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation); diff --git a/servers/text_server.cpp b/servers/text_server.cpp index af4718678e..9034239fe0 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -208,6 +208,15 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("font_set_data", "font_rid", "data"), &TextServer::font_set_data); + ClassDB::bind_method(D_METHOD("font_set_style", "font_rid", "style"), &TextServer::font_set_style); + ClassDB::bind_method(D_METHOD("font_get_style", "font_rid"), &TextServer::font_get_style); + + ClassDB::bind_method(D_METHOD("font_set_name", "font_rid", "name"), &TextServer::font_set_name); + ClassDB::bind_method(D_METHOD("font_get_name", "font_rid"), &TextServer::font_get_name); + + ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name); + ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name); + ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased); ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased); @@ -338,6 +347,9 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("shaped_text_set_bidi_override", "shaped", "override"), &TextServer::shaped_text_set_bidi_override); + ClassDB::bind_method(D_METHOD("shaped_text_set_custom_punctuation", "shaped", "punct"), &TextServer::shaped_text_set_custom_punctuation); + ClassDB::bind_method(D_METHOD("shaped_text_get_custom_punctuation", "shaped"), &TextServer::shaped_text_get_custom_punctuation); + ClassDB::bind_method(D_METHOD("shaped_text_set_orientation", "shaped", "orientation"), &TextServer::shaped_text_set_orientation, DEFVAL(ORIENTATION_HORIZONTAL)); ClassDB::bind_method(D_METHOD("shaped_text_get_orientation", "shaped"), &TextServer::shaped_text_get_orientation); @@ -470,11 +482,16 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CONIC); BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CUBIC); - /* Font Spacing*/ + /* Font Spacing */ BIND_ENUM_CONSTANT(SPACING_GLYPH); BIND_ENUM_CONSTANT(SPACING_SPACE); BIND_ENUM_CONSTANT(SPACING_TOP); BIND_ENUM_CONSTANT(SPACING_BOTTOM); + + /* Font Style */ + BIND_ENUM_CONSTANT(FONT_BOLD); + BIND_ENUM_CONSTANT(FONT_ITALIC); + BIND_ENUM_CONSTANT(FONT_FIXED_WIDTH); } Vector2 TextServer::get_hex_code_box_size(int p_size, char32_t p_index) const { diff --git a/servers/text_server.h b/servers/text_server.h index a5484d8fbd..4f55f881e6 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -125,6 +125,12 @@ public: SPACING_BOTTOM, }; + enum FontStyle { + FONT_BOLD = 1 << 0, + FONT_ITALIC = 1 << 1, + FONT_FIXED_WIDTH = 1 << 2, + }; + void _draw_hex_code_box_number(RID p_canvas, int p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const; protected: @@ -144,6 +150,7 @@ protected: int end = 0; // Substring end offset in the parent string. String text; + String custom_punct; TextServer::Direction direction = DIRECTION_LTR; // Desired text direction. TextServer::Orientation orientation = ORIENTATION_HORIZONTAL; @@ -224,6 +231,15 @@ public: virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) = 0; virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) = 0; + virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) = 0; + virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const = 0; + + virtual void font_set_name(RID p_font_rid, const String &p_name) = 0; + virtual String font_get_name(RID p_font_rid) const = 0; + + virtual void font_set_style_name(RID p_font_rid, const String &p_name) = 0; + virtual String font_get_style_name(RID p_font_rid) const = 0; + virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) = 0; virtual bool font_is_antialiased(RID p_font_rid) const = 0; @@ -354,6 +370,9 @@ public: virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) = 0; + virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) = 0; + virtual String shaped_text_get_custom_punctuation(RID p_shaped) const = 0; + virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0; virtual Orientation shaped_text_get_orientation(RID p_shaped) const = 0; @@ -535,6 +554,7 @@ VARIANT_ENUM_CAST(TextServer::Hinting); VARIANT_ENUM_CAST(TextServer::Feature); VARIANT_ENUM_CAST(TextServer::ContourPointTag); VARIANT_ENUM_CAST(TextServer::SpacingType); +VARIANT_ENUM_CAST(TextServer::FontStyle); GDVIRTUAL_NATIVE_PTR(Glyph); GDVIRTUAL_NATIVE_PTR(Glyph *); diff --git a/tests/test_aabb.h b/tests/test_aabb.h index 2724d9481a..0312e185a1 100644 --- a/tests/test_aabb.h +++ b/tests/test_aabb.h @@ -90,38 +90,38 @@ TEST_CASE("[AABB] Basic setters") { "set_size() should result in the expected AABB."); } -TEST_CASE("[AABB] Area getters") { +TEST_CASE("[AABB] Volume getters") { AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6)); CHECK_MESSAGE( - Math::is_equal_approx(aabb.get_area(), 120), - "get_area() should return the expected value with positive size."); + Math::is_equal_approx(aabb.get_volume(), 120), + "get_volume() should return the expected value with positive size."); CHECK_MESSAGE( - !aabb.has_no_area(), - "Non-empty volumetric AABB should have an area."); + !aabb.has_no_volume(), + "Non-empty volumetric AABB should have a volume."); aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(-4, 5, 6)); CHECK_MESSAGE( - Math::is_equal_approx(aabb.get_area(), -120), - "get_area() should return the expected value with negative size (1 component)."); + Math::is_equal_approx(aabb.get_volume(), -120), + "get_volume() should return the expected value with negative size (1 component)."); aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(-4, -5, 6)); CHECK_MESSAGE( - Math::is_equal_approx(aabb.get_area(), 120), - "get_area() should return the expected value with negative size (2 components)."); + Math::is_equal_approx(aabb.get_volume(), 120), + "get_volume() should return the expected value with negative size (2 components)."); aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(-4, -5, -6)); CHECK_MESSAGE( - Math::is_equal_approx(aabb.get_area(), -120), - "get_area() should return the expected value with negative size (3 components)."); + Math::is_equal_approx(aabb.get_volume(), -120), + "get_volume() should return the expected value with negative size (3 components)."); aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 0, 6)); CHECK_MESSAGE( - aabb.has_no_area(), - "Non-empty flat AABB should not have an area."); + aabb.has_no_volume(), + "Non-empty flat AABB should not have a volume."); CHECK_MESSAGE( - AABB().has_no_area(), - "Empty AABB should not have an area."); + AABB().has_no_volume(), + "Empty AABB should not have a volume."); } TEST_CASE("[AABB] Surface getters") { diff --git a/thirdparty/README.md b/thirdparty/README.md index 3ba5504920..25d2e1cfe3 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -189,7 +189,7 @@ Files extracted from upstream source: ## harfbuzz - Upstream: https://github.com/harfbuzz/harfbuzz -- Version: 3.0.0 (9c387e20d65a7a366ac270d789f6ad266014c9e0, 2021) +- Version: 3.1.1 (cd5c6cd0419ac5e4de975d6c476fb760bf06d2ce, 2021) - License: MIT Files extracted from upstream source: diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh index cd36fc8953..b52844e75d 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh @@ -82,7 +82,7 @@ struct BaselineTableFormat2Part } protected: - HBGlyphID stdGlyph; /* The specific glyph index number in this + HBGlyphID16 stdGlyph; /* The specific glyph index number in this * font that is used to set the baseline values. * This is the standard glyph. * This glyph must contain a set of control points @@ -105,7 +105,7 @@ struct BaselineTableFormat3Part } protected: - HBGlyphID stdGlyph; /* ditto */ + HBGlyphID16 stdGlyph; /* ditto */ HBUINT16 ctlPoints[32]; /* ditto */ Lookup<HBUINT16> lookupTable; /* Lookup table that maps glyphs to their diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh index e70ce97174..1dcbe92904 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh @@ -96,8 +96,8 @@ struct LookupSegmentSingle return_trace (c->check_struct (this) && value.sanitize (c, base)); } - HBGlyphID last; /* Last GlyphID in this segment */ - HBGlyphID first; /* First GlyphID in this segment */ + HBGlyphID16 last; /* Last GlyphID in this segment */ + HBGlyphID16 first; /* First GlyphID in this segment */ T value; /* The lookup value (only one) */ public: DEFINE_SIZE_STATIC (4 + T::static_size); @@ -162,11 +162,11 @@ struct LookupSegmentArray TRACE_SANITIZE (this); return_trace (c->check_struct (this) && first <= last && - valuesZ.sanitize (c, base, last - first + 1, hb_forward<Ts> (ds)...)); + valuesZ.sanitize (c, base, last - first + 1, std::forward<Ts> (ds)...)); } - HBGlyphID last; /* Last GlyphID in this segment */ - HBGlyphID first; /* First GlyphID in this segment */ + HBGlyphID16 last; /* Last GlyphID in this segment */ + HBGlyphID16 first; /* First GlyphID in this segment */ NNOffset16To<UnsizedArrayOf<T>> valuesZ; /* A 16-bit offset from the start of * the table to the data. */ @@ -225,7 +225,7 @@ struct LookupSingle return_trace (c->check_struct (this) && value.sanitize (c, base)); } - HBGlyphID glyph; /* Last GlyphID */ + HBGlyphID16 glyph; /* Last GlyphID */ T value; /* The lookup value (only one) */ public: DEFINE_SIZE_STATIC (2 + T::static_size); @@ -287,7 +287,7 @@ struct LookupFormat8 protected: HBUINT16 format; /* Format identifier--format = 8 */ - HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */ + HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */ HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last * glyph minus the value of firstGlyph plus 1). */ UnsizedArrayOf<T> @@ -329,7 +329,7 @@ struct LookupFormat10 protected: HBUINT16 format; /* Format identifier--format = 8 */ HBUINT16 valueSize; /* Byte size of each value. */ - HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */ + HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */ HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last * glyph minus the value of firstGlyph plus 1). */ UnsizedArrayOf<HBUINT8> @@ -661,7 +661,7 @@ struct ClassTable return_trace (c->check_struct (this) && classArray.sanitize (c)); } protected: - HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */ + HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */ Array16Of<HBUCHAR> classArray; /* The class codes (indexed by glyph index minus * firstGlyph). */ public: diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh index 556d4ad75b..d745c11431 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh @@ -100,7 +100,7 @@ struct UnconditionalAddGlyphAction protected: ActionSubrecordHeader header; - HBGlyphID addGlyph; /* Glyph that should be added if the distance factor + HBGlyphID16 addGlyph; /* Glyph that should be added if the distance factor * is growing. */ public: @@ -121,11 +121,11 @@ struct ConditionalAddGlyphAction HBFixed substThreshold; /* Distance growth factor (in ems) at which * this glyph is replaced and the growth factor * recalculated. */ - HBGlyphID addGlyph; /* Glyph to be added as kashida. If this value is + HBGlyphID16 addGlyph; /* Glyph to be added as kashida. If this value is * 0xFFFF, no extra glyph will be added. Note that * generally when a glyph is added, justification * will need to be redone. */ - HBGlyphID substGlyph; /* Glyph to be substituted for this glyph if the + HBGlyphID16 substGlyph; /* Glyph to be substituted for this glyph if the * growth factor equals or exceeds the value of * substThreshold. */ public: @@ -170,7 +170,7 @@ struct RepeatedAddGlyphAction ActionSubrecordHeader header; HBUINT16 flags; /* Currently unused; set to 0. */ - HBGlyphID glyph; /* Glyph that should be added if the distance factor + HBGlyphID16 glyph; /* Glyph that should be added if the distance factor * is growing. */ public: DEFINE_SIZE_STATIC (10); diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh index d0eacf0e61..0354b47d5a 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh @@ -82,8 +82,8 @@ struct KernPair } protected: - HBGlyphID left; - HBGlyphID right; + HBGlyphID16 left; + HBGlyphID16 right; FWORD value; public: DEFINE_SIZE_STATIC (6); @@ -775,11 +775,11 @@ struct KerxSubTable unsigned int subtable_type = get_type (); TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { - case 0: return_trace (c->dispatch (u.format0, hb_forward<Ts> (ds)...)); - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...)); - case 4: return_trace (c->dispatch (u.format4, hb_forward<Ts> (ds)...)); - case 6: return_trace (c->dispatch (u.format6, hb_forward<Ts> (ds)...)); + case 0: return_trace (c->dispatch (u.format0, std::forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); + case 6: return_trace (c->dispatch (u.format6, std::forward<Ts> (ds)...)); default: return_trace (c->default_return_value ()); } } diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh index a807bdcfc5..b77c1f4d44 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh @@ -243,21 +243,21 @@ struct ContextualSubtable if (buffer->idx == buffer->len && !mark_set) return; - const HBGlyphID *replacement; + const HBGlyphID16 *replacement; replacement = nullptr; if (Types::extended) { if (entry.data.markIndex != 0xFFFF) { - const Lookup<HBGlyphID> &lookup = subs[entry.data.markIndex]; + const Lookup<HBGlyphID16> &lookup = subs[entry.data.markIndex]; replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs); } } else { unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint; - const UnsizedArrayOf<HBGlyphID> &subs_old = (const UnsizedArrayOf<HBGlyphID> &) subs; + const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs; replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; if (!replacement->sanitize (&c->sanitizer) || !*replacement) replacement = nullptr; @@ -278,14 +278,14 @@ struct ContextualSubtable { if (entry.data.currentIndex != 0xFFFF) { - const Lookup<HBGlyphID> &lookup = subs[entry.data.currentIndex]; + const Lookup<HBGlyphID16> &lookup = subs[entry.data.currentIndex]; replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs); } } else { unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint; - const UnsizedArrayOf<HBGlyphID> &subs_old = (const UnsizedArrayOf<HBGlyphID> &) subs; + const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs; replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; if (!replacement->sanitize (&c->sanitizer) || !*replacement) replacement = nullptr; @@ -315,7 +315,7 @@ struct ContextualSubtable bool has_glyph_classes; unsigned int mark; const ContextualSubtable *table; - const UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false> &subs; + const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, false> &subs; }; bool apply (hb_aat_apply_context_t *c) const @@ -359,7 +359,7 @@ struct ContextualSubtable protected: StateTable<Types, EntryData> machine; - NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false>, HBUINT> + NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, false>, HBUINT> substitutionTables; public: DEFINE_SIZE_STATIC (20); @@ -531,7 +531,7 @@ struct LigatureSubtable if (action & (LigActionStore | LigActionLast)) { ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ); - const HBGlyphID &ligatureData = ligature[ligature_idx]; + const HBGlyphID16 &ligatureData = ligature[ligature_idx]; if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break; hb_codepoint_t lig = ligatureData; @@ -565,7 +565,7 @@ struct LigatureSubtable const LigatureSubtable *table; const UnsizedArrayOf<HBUINT32> &ligAction; const UnsizedArrayOf<HBUINT16> &component; - const UnsizedArrayOf<HBGlyphID> &ligature; + const UnsizedArrayOf<HBGlyphID16> &ligature; unsigned int match_length; unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; }; @@ -597,7 +597,7 @@ struct LigatureSubtable ligAction; /* Offset to the ligature action table. */ NNOffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT> component; /* Offset to the component table. */ - NNOffsetTo<UnsizedArrayOf<HBGlyphID>, HBUINT> + NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT> ligature; /* Offset to the actual ligature lists. */ public: DEFINE_SIZE_STATIC (28); @@ -620,7 +620,7 @@ struct NoncontextualSubtable unsigned int count = c->buffer->len; for (unsigned int i = 0; i < count; i++) { - const HBGlyphID *replacement = substitute.get_value (info[i].codepoint, num_glyphs); + const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs); if (replacement) { info[i].codepoint = *replacement; @@ -641,7 +641,7 @@ struct NoncontextualSubtable } protected: - Lookup<HBGlyphID> substitute; + Lookup<HBGlyphID16> substitute; public: DEFINE_SIZE_MIN (2); }; @@ -744,7 +744,7 @@ struct InsertionSubtable unsigned int count = (flags & MarkedInsertCount); if (unlikely ((buffer->max_ops -= count) <= 0)) return; unsigned int start = entry.data.markedInsertIndex; - const HBGlyphID *glyphs = &insertionAction[start]; + const HBGlyphID16 *glyphs = &insertionAction[start]; if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0; bool before = flags & MarkedInsertBefore; @@ -772,7 +772,7 @@ struct InsertionSubtable unsigned int count = (flags & CurrentInsertCount) >> 5; if (unlikely ((buffer->max_ops -= count) <= 0)) return; unsigned int start = entry.data.currentInsertIndex; - const HBGlyphID *glyphs = &insertionAction[start]; + const HBGlyphID16 *glyphs = &insertionAction[start]; if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0; bool before = flags & CurrentInsertBefore; @@ -810,7 +810,7 @@ struct InsertionSubtable private: hb_aat_apply_context_t *c; unsigned int mark; - const UnsizedArrayOf<HBGlyphID> &insertionAction; + const UnsizedArrayOf<HBGlyphID16> &insertionAction; }; bool apply (hb_aat_apply_context_t *c) const @@ -836,7 +836,7 @@ struct InsertionSubtable protected: StateTable<Types, EntryData> machine; - NNOffsetTo<UnsizedArrayOf<HBGlyphID>, HBUINT> + NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT> insertionAction; /* Byte offset from stateHeader to the start of * the insertion glyph table. */ public: @@ -906,11 +906,11 @@ struct ChainSubtable unsigned int subtable_type = get_type (); TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { - case Rearrangement: return_trace (c->dispatch (u.rearrangement, hb_forward<Ts> (ds)...)); - case Contextual: return_trace (c->dispatch (u.contextual, hb_forward<Ts> (ds)...)); - case Ligature: return_trace (c->dispatch (u.ligature, hb_forward<Ts> (ds)...)); - case Noncontextual: return_trace (c->dispatch (u.noncontextual, hb_forward<Ts> (ds)...)); - case Insertion: return_trace (c->dispatch (u.insertion, hb_forward<Ts> (ds)...)); + case Rearrangement: return_trace (c->dispatch (u.rearrangement, std::forward<Ts> (ds)...)); + case Contextual: return_trace (c->dispatch (u.contextual, std::forward<Ts> (ds)...)); + case Ligature: return_trace (c->dispatch (u.ligature, std::forward<Ts> (ds)...)); + case Noncontextual: return_trace (c->dispatch (u.noncontextual, std::forward<Ts> (ds)...)); + case Insertion: return_trace (c->dispatch (u.insertion, std::forward<Ts> (ds)...)); default: return_trace (c->default_return_value ()); } } diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh index bbe097fe01..446d87e28b 100644 --- a/thirdparty/harfbuzz/src/hb-algs.hh +++ b/thirdparty/harfbuzz/src/hb-algs.hh @@ -34,6 +34,9 @@ #include "hb-null.hh" #include "hb-number.hh" +#include <algorithm> +#include <initializer_list> +#include <new> /* * Flags @@ -125,7 +128,7 @@ struct BEInt<Type, 2> template <typename Type> struct BEInt<Type, 3> { - static_assert (!hb_is_signed (Type), ""); + static_assert (!std::is_signed<Type>::value, ""); public: BEInt () = default; constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF), @@ -179,7 +182,7 @@ struct { /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */ template <typename T> constexpr auto - operator () (T&& v) const HB_AUTO_RETURN ( hb_forward<T> (v) ) + operator () (T&& v) const HB_AUTO_RETURN ( std::forward<T> (v) ) } HB_FUNCOBJ (hb_identity); struct @@ -203,7 +206,7 @@ HB_FUNCOBJ (hb_ridentity); struct { template <typename T> constexpr bool - operator () (T&& v) const { return bool (hb_forward<T> (v)); } + operator () (T&& v) const { return bool (std::forward<T> (v)); } } HB_FUNCOBJ (hb_bool); @@ -215,7 +218,7 @@ struct impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) template <typename T, - hb_enable_if (hb_is_integral (T))> constexpr auto + hb_enable_if (std::is_integral<T>::value)> constexpr auto impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN ( /* Knuth's multiplicative method: */ @@ -237,26 +240,26 @@ struct /* Pointer-to-member-function. */ template <typename Appl, typename T, typename ...Ts> auto impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN - ((hb_deref (hb_forward<T> (v)).*hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...)) + ((hb_deref (std::forward<T> (v)).*std::forward<Appl> (a)) (std::forward<Ts> (ds)...)) /* Pointer-to-member. */ template <typename Appl, typename T> auto impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN - ((hb_deref (hb_forward<T> (v))).*hb_forward<Appl> (a)) + ((hb_deref (std::forward<T> (v))).*std::forward<Appl> (a)) /* Operator(). */ template <typename Appl, typename ...Ts> auto impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN - (hb_deref (hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...)) + (hb_deref (std::forward<Appl> (a)) (std::forward<Ts> (ds)...)) public: template <typename Appl, typename ...Ts> auto operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN ( - impl (hb_forward<Appl> (a), + impl (std::forward<Appl> (a), hb_prioritize, - hb_forward<Ts> (ds)...) + std::forward<Ts> (ds)...) ) } HB_FUNCOBJ (hb_invoke); @@ -275,9 +278,9 @@ struct hb_partial_t hb_declval (V), hb_declval (Ts)...)) { - return hb_invoke (hb_forward<Appl> (a), - hb_forward<V> (v), - hb_forward<Ts> (ds)...); + return hb_invoke (std::forward<Appl> (a), + std::forward<V> (v), + std::forward<Ts> (ds)...); } template <typename T0, typename ...Ts, unsigned P = Pos, @@ -287,10 +290,10 @@ struct hb_partial_t hb_declval (V), hb_declval (Ts)...)) { - return hb_invoke (hb_forward<Appl> (a), - hb_forward<T0> (d0), - hb_forward<V> (v), - hb_forward<Ts> (ds)...); + return hb_invoke (std::forward<Appl> (a), + std::forward<T0> (d0), + std::forward<V> (v), + std::forward<Ts> (ds)...); } private: @@ -324,14 +327,14 @@ auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN #define HB_PARTIALIZE(Pos) \ template <typename _T> \ decltype(auto) operator () (_T&& _v) const \ - { return hb_partial<Pos> (this, hb_forward<_T> (_v)); } \ + { return hb_partial<Pos> (this, std::forward<_T> (_v)); } \ static_assert (true, "") #else /* https://github.com/harfbuzz/harfbuzz/issues/1724 */ #define HB_PARTIALIZE(Pos) \ template <typename _T> \ auto operator () (_T&& _v) const HB_AUTO_RETURN \ - (hb_partial<Pos> (+this, hb_forward<_T> (_v))) \ + (hb_partial<Pos> (+this, std::forward<_T> (_v))) \ static_assert (true, "") #endif @@ -343,22 +346,22 @@ struct template <typename Pred, typename Val> auto impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN ( - hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v)) + hb_deref (std::forward<Pred> (p)).has (std::forward<Val> (v)) ) template <typename Pred, typename Val> auto impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN ( - hb_invoke (hb_forward<Pred> (p), - hb_forward<Val> (v)) + hb_invoke (std::forward<Pred> (p), + std::forward<Val> (v)) ) public: template <typename Pred, typename Val> auto operator () (Pred&& p, Val &&v) const HB_RETURN (bool, - impl (hb_forward<Pred> (p), - hb_forward<Val> (v), + impl (std::forward<Pred> (p), + std::forward<Val> (v), hb_prioritize) ) } @@ -371,22 +374,22 @@ struct template <typename Pred, typename Val> auto impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN ( - hb_has (hb_forward<Pred> (p), - hb_forward<Val> (v)) + hb_has (std::forward<Pred> (p), + std::forward<Val> (v)) ) template <typename Pred, typename Val> auto impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN ( - hb_forward<Pred> (p) == hb_forward<Val> (v) + std::forward<Pred> (p) == std::forward<Val> (v) ) public: template <typename Pred, typename Val> auto operator () (Pred&& p, Val &&v) const HB_RETURN (bool, - impl (hb_forward<Pred> (p), - hb_forward<Val> (v), + impl (std::forward<Pred> (p), + std::forward<Val> (v), hb_prioritize) ) } @@ -399,20 +402,20 @@ struct template <typename Proj, typename Val> auto impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN ( - hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v)) + hb_deref (std::forward<Proj> (f)).get (std::forward<Val> (v)) ) template <typename Proj, typename Val> auto impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN ( - hb_invoke (hb_forward<Proj> (f), - hb_forward<Val> (v)) + hb_invoke (std::forward<Proj> (f), + std::forward<Val> (v)) ) template <typename Proj, typename Val> auto impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN ( - hb_forward<Proj> (f)[hb_forward<Val> (v)] + std::forward<Proj> (f)[std::forward<Val> (v)] ) public: @@ -420,8 +423,8 @@ struct template <typename Proj, typename Val> auto operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN ( - impl (hb_forward<Proj> (f), - hb_forward<Val> (v), + impl (std::forward<Proj> (f), + std::forward<Val> (v), hb_prioritize) ) } @@ -434,19 +437,19 @@ struct template <typename T1, typename T2> auto impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN ( - hb_forward<T2> (v2).cmp (hb_forward<T1> (v1)) == 0 + std::forward<T2> (v2).cmp (std::forward<T1> (v1)) == 0 ) template <typename T1, typename T2> auto impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN ( - hb_forward<T1> (v1).cmp (hb_forward<T2> (v2)) == 0 + std::forward<T1> (v1).cmp (std::forward<T2> (v2)) == 0 ) template <typename T1, typename T2> auto impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN ( - hb_forward<T1> (v1) == hb_forward<T2> (v2) + std::forward<T1> (v1) == std::forward<T2> (v2) ) public: @@ -454,8 +457,8 @@ struct template <typename T1, typename T2> auto operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN ( - impl (hb_forward<T1> (v1), - hb_forward<T2> (v2), + impl (std::forward<T1> (v1), + std::forward<T2> (v2), hb_prioritize) ) } @@ -515,24 +518,34 @@ struct { template <typename T, typename T2> constexpr auto operator () (T&& a, T2&& b) const HB_AUTO_RETURN - (a <= b ? hb_forward<T> (a) : hb_forward<T2> (b)) + (a <= b ? std::forward<T> (a) : std::forward<T2> (b)) } HB_FUNCOBJ (hb_min); struct { template <typename T, typename T2> constexpr auto operator () (T&& a, T2&& b) const HB_AUTO_RETURN - (a >= b ? hb_forward<T> (a) : hb_forward<T2> (b)) + (a >= b ? std::forward<T> (a) : std::forward<T2> (b)) } HB_FUNCOBJ (hb_max); struct { template <typename T, typename T2, typename T3> constexpr auto operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN - (hb_min (hb_max (hb_forward<T> (x), hb_forward<T2> (min)), hb_forward<T3> (max))) + (hb_min (hb_max (std::forward<T> (x), std::forward<T2> (min)), std::forward<T3> (max))) } HB_FUNCOBJ (hb_clamp); +struct +{ + template <typename T> void + operator () (T& a, T& b) const + { + using std::swap; // allow ADL + swap (a, b); + } +} +HB_FUNCOBJ (hb_swap); /* * Bithacks. @@ -795,7 +808,7 @@ hb_ceil_to_4 (unsigned int v) template <typename T> static inline bool hb_in_range (T u, T lo, T hi) { - static_assert (!hb_is_signed<T>::value, ""); + static_assert (!std::is_signed<T>::value, ""); /* The casts below are important as if T is smaller than int, * the subtract results will become a signed int! */ diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh index ab0dd6ebe3..dd61509b2e 100644 --- a/thirdparty/harfbuzz/src/hb-array.hh +++ b/thirdparty/harfbuzz/src/hb-array.hh @@ -50,10 +50,10 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> /* * Constructors. */ - hb_array_t () : arrayZ (nullptr), length (0), backwards_length (0) {} - hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_), backwards_length (0) {} + hb_array_t () = default; + hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {} template <unsigned int length_> - hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_), backwards_length (0) {} + hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {} template <typename U, hb_enable_if (hb_is_cr_convertible(U, Type))> @@ -281,9 +281,9 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> */ public: - Type *arrayZ; - unsigned int length; - unsigned int backwards_length; + Type *arrayZ = nullptr; + unsigned int length = 0; + unsigned int backwards_length = 0; }; template <typename T> inline hb_array_t<T> hb_array (T *array, unsigned int length) @@ -302,7 +302,7 @@ struct hb_sorted_array_t : static constexpr bool is_random_access_iterator = true; static constexpr bool is_sorted_iterator = true; - hb_sorted_array_t () : hb_array_t<Type> () {} + hb_sorted_array_t () = default; hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {} template <unsigned int length_> hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {} diff --git a/thirdparty/harfbuzz/src/hb-atomic.hh b/thirdparty/harfbuzz/src/hb-atomic.hh index 93265f655f..e640d1b586 100644 --- a/thirdparty/harfbuzz/src/hb-atomic.hh +++ b/thirdparty/harfbuzz/src/hb-atomic.hh @@ -102,20 +102,12 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N) #define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N)) -#elif defined(HB_NO_MT) +#else /* defined(HB_NO_MT) */ #define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V)) - #define _hb_memory_barrier() do {} while (0) - #define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) - -#else - -#error "Could not find any system to define atomic_int macros." -#error "Check hb-atomic.hh for possible resolutions." - #endif diff --git a/thirdparty/harfbuzz/src/hb-bimap.hh b/thirdparty/harfbuzz/src/hb-bimap.hh index d409880751..d466af8b60 100644 --- a/thirdparty/harfbuzz/src/hb-bimap.hh +++ b/thirdparty/harfbuzz/src/hb-bimap.hh @@ -33,15 +33,14 @@ /* Bi-directional map */ struct hb_bimap_t { - hb_bimap_t () { init (); } - ~hb_bimap_t () { fini (); } - + /* XXX(remove) */ void init () { forw_map.init (); back_map.init (); } + /* XXX(remove) */ void fini () { forw_map.fini (); @@ -99,14 +98,6 @@ struct hb_bimap_t /* Inremental bimap: only lhs is given, rhs is incrementally assigned */ struct hb_inc_bimap_t : hb_bimap_t { - hb_inc_bimap_t () { init (); } - - void init () - { - hb_bimap_t::init (); - next_value = 0; - } - /* Add a mapping from lhs to rhs with a unique value if lhs is unknown. * Return the rhs value as the result. */ @@ -165,7 +156,7 @@ struct hb_inc_bimap_t : hb_bimap_t } protected: - unsigned int next_value; + unsigned int next_value = 0; }; #endif /* HB_BIMAP_HH */ diff --git a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh index f48b72fe63..0832b0fc23 100644 --- a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh +++ b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh @@ -35,10 +35,20 @@ struct hb_bit_set_invertible_t { hb_bit_set_t s; - bool inverted; - - hb_bit_set_invertible_t () { init (); } - ~hb_bit_set_invertible_t () { fini (); } + bool inverted = false; + + hb_bit_set_invertible_t () = default; + hb_bit_set_invertible_t (hb_bit_set_invertible_t& o) = default; + hb_bit_set_invertible_t (hb_bit_set_invertible_t&& o) = default; + hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default; + hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& o) = default; + friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b) + { + if (likely (!a.s.successful || !b.s.successful)) + return; + hb_swap (a.inverted, b.inverted); + hb_swap (a.s, b.s); + } void init () { s.init (); inverted = false; } void fini () { s.fini (); } diff --git a/thirdparty/harfbuzz/src/hb-bit-set.hh b/thirdparty/harfbuzz/src/hb-bit-set.hh index c21778d88e..a471ee48b5 100644 --- a/thirdparty/harfbuzz/src/hb-bit-set.hh +++ b/thirdparty/harfbuzz/src/hb-bit-set.hh @@ -35,13 +35,22 @@ struct hb_bit_set_t { - hb_bit_set_t () { init (); } - ~hb_bit_set_t () { fini (); } + hb_bit_set_t () = default; + ~hb_bit_set_t () = default; hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other); } - void operator= (const hb_bit_set_t& other) { set (other); } - // TODO Add move construtor/assign - // TODO Add constructor for Iterator; with specialization for (sorted) vector / array? + hb_bit_set_t ( hb_bit_set_t&& other) : hb_bit_set_t () { hb_swap (*this, other); } + hb_bit_set_t& operator= (const hb_bit_set_t& other) { set (other); return *this; } + hb_bit_set_t& operator= (hb_bit_set_t&& other) { hb_swap (*this, other); return *this; } + friend void swap (hb_bit_set_t &a, hb_bit_set_t &b) + { + if (likely (!a.successful || !b.successful)) + return; + hb_swap (a.population, b.population); + hb_swap (a.last_page_lookup, b.last_page_lookup); + hb_swap (a.page_map, b.page_map); + hb_swap (a.pages, b.pages); + } void init () { @@ -67,9 +76,9 @@ struct hb_bit_set_t uint32_t index; }; - bool successful; /* Allocations successful */ - mutable unsigned int population; - mutable unsigned int last_page_lookup; + bool successful = true; /* Allocations successful */ + mutable unsigned int population = 0; + mutable unsigned int last_page_lookup = 0; hb_sorted_vector_t<page_map_t> page_map; hb_vector_t<page_t> pages; diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc index c6591ca230..b4f7f72374 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.cc +++ b/thirdparty/harfbuzz/src/hb-buffer.cc @@ -224,6 +224,7 @@ hb_buffer_t::reset () flags = HB_BUFFER_FLAG_DEFAULT; replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; invisible = 0; + not_found = 0; clear (); } @@ -608,6 +609,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) = HB_BUFFER_CLUSTER_LEVEL_DEFAULT, HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, 0, /* invisible */ + 0, /* not_found */ HB_BUFFER_SCRATCH_FLAG_DEFAULT, HB_BUFFER_MAX_LEN_DEFAULT, HB_BUFFER_MAX_OPS_DEFAULT, @@ -1158,6 +1160,46 @@ hb_buffer_get_invisible_glyph (hb_buffer_t *buffer) return buffer->invisible; } +/** + * hb_buffer_set_not_found_glyph: + * @buffer: An #hb_buffer_t + * @not_found: the not-found #hb_codepoint_t + * + * Sets the #hb_codepoint_t that replaces characters not found in + * the font during shaping. + * + * The not-found glyph defaults to zero, sometimes knows as the + * ".notdef" glyph. This API allows for differentiating the two. + * + * Since: 3.1.0 + **/ +void +hb_buffer_set_not_found_glyph (hb_buffer_t *buffer, + hb_codepoint_t not_found) +{ + if (unlikely (hb_object_is_immutable (buffer))) + return; + + buffer->not_found = not_found; +} + +/** + * hb_buffer_get_not_found_glyph: + * @buffer: An #hb_buffer_t + * + * See hb_buffer_set_not_found_glyph(). + * + * Return value: + * The @buffer not-found #hb_codepoint_t + * + * Since: 3.1.0 + **/ +hb_codepoint_t +hb_buffer_get_not_found_glyph (hb_buffer_t *buffer) +{ + return buffer->not_found; +} + /** * hb_buffer_reset: diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h index 865ccb2273..a183cb9d4a 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.h +++ b/thirdparty/harfbuzz/src/hb-buffer.h @@ -383,6 +383,13 @@ hb_buffer_set_invisible_glyph (hb_buffer_t *buffer, HB_EXTERN hb_codepoint_t hb_buffer_get_invisible_glyph (hb_buffer_t *buffer); +HB_EXTERN void +hb_buffer_set_not_found_glyph (hb_buffer_t *buffer, + hb_codepoint_t not_found); + +HB_EXTERN hb_codepoint_t +hb_buffer_get_not_found_glyph (hb_buffer_t *buffer); + HB_EXTERN void hb_buffer_reset (hb_buffer_t *buffer); diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh index 8635ebd35f..bde28933e4 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.hh +++ b/thirdparty/harfbuzz/src/hb-buffer.hh @@ -93,6 +93,7 @@ struct hb_buffer_t hb_buffer_cluster_level_t cluster_level; hb_codepoint_t replacement; /* U+FFFD or something else. */ hb_codepoint_t invisible; /* 0 or something else. */ + hb_codepoint_t not_found; /* 0 or something else. */ hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ unsigned int max_len; /* Maximum allowed len. */ int max_ops; /* Maximum allowed operations. */ diff --git a/thirdparty/harfbuzz/src/hb-debug.hh b/thirdparty/harfbuzz/src/hb-debug.hh index f80c8980ba..3ac7440e80 100644 --- a/thirdparty/harfbuzz/src/hb-debug.hh +++ b/thirdparty/harfbuzz/src/hb-debug.hh @@ -302,7 +302,7 @@ struct hb_auto_trace_t { if (unlikely (returned)) { fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n"); - return hb_forward<T> (v); + return std::forward<T> (v); } _hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1, @@ -311,7 +311,7 @@ struct hb_auto_trace_t if (plevel) --*plevel; plevel = nullptr; returned = true; - return hb_forward<T> (v); + return std::forward<T> (v); } private: @@ -333,7 +333,7 @@ struct hb_auto_trace_t<0, ret_t> template <typename T> T ret (T&& v, const char *func HB_UNUSED = nullptr, - unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); } + unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); } }; /* For disabled tracing; optimize out everything. @@ -343,7 +343,7 @@ struct hb_no_trace_t { template <typename T> T ret (T&& v, const char *func HB_UNUSED = nullptr, - unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); } + unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); } }; #define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__) diff --git a/thirdparty/harfbuzz/src/hb-directwrite.cc b/thirdparty/harfbuzz/src/hb-directwrite.cc index 8f6d73b639..db7b53b259 100644 --- a/thirdparty/harfbuzz/src/hb-directwrite.cc +++ b/thirdparty/harfbuzz/src/hb-directwrite.cc @@ -43,6 +43,14 @@ * Functions for using HarfBuzz with DirectWrite fonts. **/ +/* Declare object creator for dynamic support of DWRITE */ +typedef HRESULT (* WINAPI t_DWriteCreateFactory)( + DWRITE_FACTORY_TYPE factoryType, + REFIID iid, + IUnknown **factory +); + + /* * DirectWrite font stream helpers */ @@ -137,6 +145,7 @@ public: struct hb_directwrite_face_data_t { + HMODULE dwrite_dll; IDWriteFactory *dwriteFactory; IDWriteFontFile *fontFile; DWriteFontFileStream *fontFileStream; @@ -158,12 +167,33 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) return nullptr; \ } HB_STMT_END + data->dwrite_dll = LoadLibrary (TEXT ("DWRITE")); + if (unlikely (!data->dwrite_dll)) + FAIL ("Cannot find DWrite.DLL"); + + t_DWriteCreateFactory p_DWriteCreateFactory; + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif + + p_DWriteCreateFactory = (t_DWriteCreateFactory) + GetProcAddress (data->dwrite_dll, "DWriteCreateFactory"); + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + + if (unlikely (!p_DWriteCreateFactory)) + FAIL ("Cannot find DWriteCreateFactory()."); + HRESULT hr; // TODO: factory and fontFileLoader should be cached separately IDWriteFactory* dwriteFactory; - hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), - (IUnknown**) &dwriteFactory); + hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), + (IUnknown**) &dwriteFactory); if (unlikely (hr != S_OK)) FAIL ("Failed to run DWriteCreateFactory()."); @@ -227,6 +257,8 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data) delete data->fontFileStream; if (data->faceBlob) hb_blob_destroy (data->faceBlob); + if (data->dwrite_dll) + FreeLibrary (data->dwrite_dll); if (data) delete data; } diff --git a/thirdparty/harfbuzz/src/hb-dispatch.hh b/thirdparty/harfbuzz/src/hb-dispatch.hh index 4b2b65a8de..37ca681465 100644 --- a/thirdparty/harfbuzz/src/hb-dispatch.hh +++ b/thirdparty/harfbuzz/src/hb-dispatch.hh @@ -50,7 +50,7 @@ struct hb_dispatch_context_t bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; } template <typename T, typename ...Ts> return_t dispatch (const T &obj, Ts&&... ds) - { return obj.dispatch (thiz (), hb_forward<Ts> (ds)...); } + { return obj.dispatch (thiz (), std::forward<Ts> (ds)...); } static return_t no_dispatch_return_value () { return Context::default_return_value (); } static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; } unsigned debug_depth = 0; diff --git a/thirdparty/harfbuzz/src/hb-font.hh b/thirdparty/harfbuzz/src/hb-font.hh index 8fc7f44d44..1b7f445e8b 100644 --- a/thirdparty/harfbuzz/src/hb-font.hh +++ b/thirdparty/harfbuzz/src/hb-font.hh @@ -217,9 +217,10 @@ struct hb_font_t } hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, - hb_codepoint_t *glyph) + hb_codepoint_t *glyph, + hb_codepoint_t not_found = 0) { - *glyph = 0; + *glyph = not_found; return klass->get.f.nominal_glyph (this, user_data, unicode, glyph, klass->user_data.nominal_glyph); @@ -238,9 +239,10 @@ struct hb_font_t } hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, - hb_codepoint_t *glyph) + hb_codepoint_t *glyph, + hb_codepoint_t not_found = 0) { - *glyph = 0; + *glyph = not_found; return klass->get.f.variation_glyph (this, user_data, unicode, variation_selector, glyph, klass->user_data.variation_glyph); @@ -618,9 +620,7 @@ struct hb_font_t } hb_position_t em_mult (int16_t v, int64_t mult) - { - return (hb_position_t) ((v * mult) >> 16); - } + { return (hb_position_t) ((v * mult + 32768) >> 16); } hb_position_t em_scalef (float v, int scale) { return (hb_position_t) roundf (v * scale / face->get_upem ()); } float em_fscale (int16_t v, int scale) diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh index b8c4472636..87b8ed880d 100644 --- a/thirdparty/harfbuzz/src/hb-iter.hh +++ b/thirdparty/harfbuzz/src/hb-iter.hh @@ -162,7 +162,7 @@ struct { template <typename T> hb_iter_type<T> operator () (T&& c) const - { return hb_deref (hb_forward<T> (c)).iter (); } + { return hb_deref (std::forward<T> (c)).iter (); } /* Specialization for C arrays. */ @@ -353,7 +353,7 @@ static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable). template <typename Lhs, typename Rhs, hb_requires (hb_is_iterator (Lhs))> static inline auto -operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (hb_forward<Rhs> (rhs) (hb_forward<Lhs> (lhs))) +operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (std::forward<Rhs> (rhs) (std::forward<Lhs> (lhs))) /* hb_map(), hb_filter(), hb_reduce() */ @@ -674,8 +674,8 @@ struct hb_iota_iter_t : template <typename S2 = S> auto inc (hb_type_identity<S2> s, hb_priority<1>) - -> hb_void_t<decltype (hb_invoke (hb_forward<S2> (s), hb_declval<T&> ()))> - { v = hb_invoke (hb_forward<S2> (s), v); } + -> hb_void_t<decltype (hb_invoke (std::forward<S2> (s), hb_declval<T&> ()))> + { v = hb_invoke (std::forward<S2> (s), v); } void inc (S s, hb_priority<0>) @@ -874,7 +874,7 @@ struct Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (!hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it))) + if (!hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it))) return false; return true; } @@ -891,7 +891,7 @@ struct Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it))) + if (hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it))) return true; return false; } @@ -908,7 +908,7 @@ struct Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it))) + if (hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it))) return false; return true; } diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh index dcd5267d74..bb4a0eb5d1 100644 --- a/thirdparty/harfbuzz/src/hb-map.hh +++ b/thirdparty/harfbuzz/src/hb-map.hh @@ -35,16 +35,35 @@ */ template <typename K, typename V, - K kINVALID = hb_is_pointer (K) ? 0 : hb_is_signed (K) ? hb_int_min (K) : (K) -1, - V vINVALID = hb_is_pointer (V) ? 0 : hb_is_signed (V) ? hb_int_min (V) : (V) -1> + K kINVALID = hb_is_pointer (K) ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1, + V vINVALID = hb_is_pointer (V) ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1> struct hb_hashmap_t { - HB_DELETE_COPY_ASSIGN (hb_hashmap_t); + static constexpr K INVALID_KEY = kINVALID; + static constexpr V INVALID_VALUE = vINVALID; + hb_hashmap_t () { init (); } ~hb_hashmap_t () { fini (); } - static_assert (hb_is_integral (K) || hb_is_pointer (K), ""); - static_assert (hb_is_integral (V) || hb_is_pointer (V), ""); + hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { hb_copy (o, *this); } + hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); } + hb_hashmap_t& operator= (const hb_hashmap_t& o) { hb_copy (o, *this); return *this; } + hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; } + + hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t () + { + for (auto&& item : lst) + set (item.first, item.second); + } + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> + hb_hashmap_t (const Iterable &o) : hb_hashmap_t () + { + hb_copy (o, *this); + } + + static_assert (std::is_integral<K>::value || hb_is_pointer (K), ""); + static_assert (std::is_integral<V>::value || hb_is_pointer (V), ""); struct item_t { @@ -70,6 +89,16 @@ struct hb_hashmap_t unsigned int prime; item_t *items; + friend void swap (hb_hashmap_t& a, hb_hashmap_t& b) + { + if (unlikely (!a.successful || !b.successful)) + return; + hb_swap (a.population, b.population); + hb_swap (a.occupancy, b.occupancy); + hb_swap (a.mask, b.mask); + hb_swap (a.prime, b.prime); + hb_swap (a.items, b.items); + } void init_shallow () { successful = true; @@ -133,17 +162,15 @@ struct hb_hashmap_t if (old_items[i].is_real ()) set_with_hash (old_items[i].key, old_items[i].hash, - old_items[i].value); + std::move (old_items[i].value)); hb_free (old_items); return true; } - bool set (K key, V value) - { - return set_with_hash (key, hb_hash (key), value); - } + bool set (K key, const V& value) { return set_with_hash (key, hb_hash (key), value); } + bool set (K key, V&& value) { return set_with_hash (key, hb_hash (key), std::move (value)); } V get (K key) const { @@ -213,7 +240,8 @@ struct hb_hashmap_t protected: - bool set_with_hash (K key, uint32_t hash, V value) + template <typename VV> + bool set_with_hash (K key, uint32_t hash, VV&& value) { if (unlikely (!successful)) return false; if (unlikely (key == kINVALID)) return true; @@ -321,7 +349,22 @@ struct hb_hashmap_t struct hb_map_t : hb_hashmap_t<hb_codepoint_t, hb_codepoint_t, HB_MAP_VALUE_INVALID, - HB_MAP_VALUE_INVALID> {}; - + HB_MAP_VALUE_INVALID> +{ + using hashmap = hb_hashmap_t<hb_codepoint_t, + hb_codepoint_t, + HB_MAP_VALUE_INVALID, + HB_MAP_VALUE_INVALID>; + + hb_map_t () = default; + ~hb_map_t () = default; + hb_map_t (hb_map_t& o) = default; + hb_map_t& operator= (const hb_map_t& other) = default; + hb_map_t& operator= (hb_map_t&& other) = default; + hb_map_t (std::initializer_list<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> lst) : hashmap (lst) {} + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> + hb_map_t (const Iterable &o) : hashmap (o) {} +}; #endif /* HB_MAP_HH */ diff --git a/thirdparty/harfbuzz/src/hb-meta.hh b/thirdparty/harfbuzz/src/hb-meta.hh index a714bc2bf0..0ea5774a9f 100644 --- a/thirdparty/harfbuzz/src/hb-meta.hh +++ b/thirdparty/harfbuzz/src/hb-meta.hh @@ -29,6 +29,9 @@ #include "hb.hh" +#include <type_traits> +#include <utility> + /* * C++ template meta-programming & fundamentals used with them. @@ -129,40 +132,7 @@ template <typename T> using hb_add_pointer = decltype (_hb_try_add_pointer<T> (h /* TODO Add feature-parity to std::decay. */ template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>; - -template<bool B, class T, class F> -struct _hb_conditional { typedef T type; }; -template<class T, class F> -struct _hb_conditional<false, T, F> { typedef F type; }; -template<bool B, class T, class F> -using hb_conditional = typename _hb_conditional<B, T, F>::type; - - -template <typename From, typename To> -struct hb_is_convertible -{ - private: - static constexpr bool from_void = hb_is_same (void, hb_decay<From>); - static constexpr bool to_void = hb_is_same (void, hb_decay<To> ); - static constexpr bool either_void = from_void || to_void; - static constexpr bool both_void = from_void && to_void; - - static hb_true_type impl2 (hb_conditional<to_void, int, To>); - - template <typename T> - static auto impl (hb_priority<1>) -> decltype (impl2 (hb_declval (T))); - template <typename T> - static hb_false_type impl (hb_priority<0>); - public: - static constexpr bool value = both_void || - (!either_void && - decltype (impl<hb_conditional<from_void, int, From>> (hb_prioritize))::value); -}; -#define hb_is_convertible(From,To) hb_is_convertible<From, To>::value - -template <typename Base, typename Derived> -using hb_is_base_of = hb_is_convertible<hb_decay<Derived> *, hb_decay<Base> *>; -#define hb_is_base_of(Base,Derived) hb_is_base_of<Base, Derived>::value +#define hb_is_convertible(From,To) std::is_convertible<From, To>::value template <typename From, typename To> using hb_is_cr_convertible = hb_bool_constant< @@ -172,20 +142,11 @@ using hb_is_cr_convertible = hb_bool_constant< >; #define hb_is_cr_convertible(From,To) hb_is_cr_convertible<From, To>::value -/* std::move and std::forward */ - -template <typename T> -static constexpr hb_remove_reference<T>&& hb_move (T&& t) { return (hb_remove_reference<T>&&) (t); } - -template <typename T> -static constexpr T&& hb_forward (hb_remove_reference<T>& t) { return (T&&) t; } -template <typename T> -static constexpr T&& hb_forward (hb_remove_reference<T>&& t) { return (T&&) t; } struct { template <typename T> constexpr auto - operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v)) + operator () (T&& v) const HB_AUTO_RETURN (std::forward<T> (v)) template <typename T> constexpr auto operator () (T *v) const HB_AUTO_RETURN (*v) @@ -195,7 +156,7 @@ HB_FUNCOBJ (hb_deref); struct { template <typename T> constexpr auto - operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v)) + operator () (T&& v) const HB_AUTO_RETURN (std::forward<T> (v)) template <typename T> constexpr auto operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v)) @@ -226,50 +187,6 @@ struct hb_reference_wrapper<T&> /* Type traits */ -template <typename T> -using hb_is_integral = hb_bool_constant< - hb_is_same (hb_decay<T>, char) || - hb_is_same (hb_decay<T>, signed char) || - hb_is_same (hb_decay<T>, unsigned char) || - hb_is_same (hb_decay<T>, signed int) || - hb_is_same (hb_decay<T>, unsigned int) || - hb_is_same (hb_decay<T>, signed short) || - hb_is_same (hb_decay<T>, unsigned short) || - hb_is_same (hb_decay<T>, signed long) || - hb_is_same (hb_decay<T>, unsigned long) || - hb_is_same (hb_decay<T>, signed long long) || - hb_is_same (hb_decay<T>, unsigned long long) || - false ->; -#define hb_is_integral(T) hb_is_integral<T>::value -template <typename T> -using hb_is_floating_point = hb_bool_constant< - hb_is_same (hb_decay<T>, float) || - hb_is_same (hb_decay<T>, double) || - hb_is_same (hb_decay<T>, long double) || - false ->; -#define hb_is_floating_point(T) hb_is_floating_point<T>::value -template <typename T> -using hb_is_arithmetic = hb_bool_constant< - hb_is_integral (T) || - hb_is_floating_point (T) || - false ->; -#define hb_is_arithmetic(T) hb_is_arithmetic<T>::value - - -template <typename T, bool is_arithmetic> struct hb_is_signed_; -template <typename T> struct hb_is_signed_<T, false> : hb_false_type {}; -template <typename T> struct hb_is_signed_<T, true> : hb_bool_constant<(T) -1 < (T) 0> {}; -template <typename T> struct hb_is_signed : hb_is_signed_<T, hb_is_arithmetic (T)> {}; -#define hb_is_signed(T) hb_is_signed<T>::value -template <typename T, bool is_arithmetic> struct hb_is_unsigned_; -template <typename T> struct hb_is_unsigned_<T, false> : hb_false_type {}; -template <typename T> struct hb_is_unsigned_<T, true> : hb_bool_constant<(T) 0 < (T) -1> {}; -template <typename T> struct hb_is_unsigned : hb_is_unsigned_<T, hb_is_arithmetic (T)> {}; -#define hb_is_unsigned(T) hb_is_unsigned<T>::value - template <typename T> struct hb_int_min; template <> struct hb_int_min<char> : hb_integral_constant<char, CHAR_MIN> {}; template <> struct hb_int_min<signed char> : hb_integral_constant<signed char, SCHAR_MIN> {}; @@ -309,108 +226,6 @@ template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigne TypeName(const TypeName&) = delete; \ void operator=(const TypeName&) = delete -template <typename T, typename> -struct _hb_is_destructible : hb_false_type {}; -template <typename T> -struct _hb_is_destructible<T, hb_void_t<decltype (hb_declval (T).~T ())>> : hb_true_type {}; -template <typename T> -using hb_is_destructible = _hb_is_destructible<T, void>; -#define hb_is_destructible(T) hb_is_destructible<T>::value - -template <typename T, typename, typename ...Ts> -struct _hb_is_constructible : hb_false_type {}; -template <typename T, typename ...Ts> -struct _hb_is_constructible<T, hb_void_t<decltype (T (hb_declval (Ts)...))>, Ts...> : hb_true_type {}; -template <typename T, typename ...Ts> -using hb_is_constructible = _hb_is_constructible<T, void, Ts...>; -#define hb_is_constructible(...) hb_is_constructible<__VA_ARGS__>::value - -template <typename T> -using hb_is_default_constructible = hb_is_constructible<T>; -#define hb_is_default_constructible(T) hb_is_default_constructible<T>::value - -template <typename T> -using hb_is_copy_constructible = hb_is_constructible<T, hb_add_lvalue_reference<hb_add_const<T>>>; -#define hb_is_copy_constructible(T) hb_is_copy_constructible<T>::value - -template <typename T> -using hb_is_move_constructible = hb_is_constructible<T, hb_add_rvalue_reference<hb_add_const<T>>>; -#define hb_is_move_constructible(T) hb_is_move_constructible<T>::value - -template <typename T, typename U, typename> -struct _hb_is_assignable : hb_false_type {}; -template <typename T, typename U> -struct _hb_is_assignable<T, U, hb_void_t<decltype (hb_declval (T) = hb_declval (U))>> : hb_true_type {}; -template <typename T, typename U> -using hb_is_assignable = _hb_is_assignable<T, U, void>; -#define hb_is_assignable(T,U) hb_is_assignable<T, U>::value - -template <typename T> -using hb_is_copy_assignable = hb_is_assignable<hb_add_lvalue_reference<T>, - hb_add_lvalue_reference<hb_add_const<T>>>; -#define hb_is_copy_assignable(T) hb_is_copy_assignable<T>::value - -template <typename T> -using hb_is_move_assignable = hb_is_assignable<hb_add_lvalue_reference<T>, - hb_add_rvalue_reference<T>>; -#define hb_is_move_assignable(T) hb_is_move_assignable<T>::value - -/* Trivial versions. */ - -template <typename T> union hb_trivial { T value; }; - -template <typename T> -using hb_is_trivially_destructible= hb_is_destructible<hb_trivial<T>>; -#define hb_is_trivially_destructible(T) hb_is_trivially_destructible<T>::value - -/* Don't know how to do the following. */ -//template <typename T, typename ...Ts> -//using hb_is_trivially_constructible= hb_is_constructible<hb_trivial<T>, hb_trivial<Ts>...>; -//#define hb_is_trivially_constructible(...) hb_is_trivially_constructible<__VA_ARGS__>::value - -template <typename T> -using hb_is_trivially_default_constructible= hb_is_default_constructible<hb_trivial<T>>; -#define hb_is_trivially_default_constructible(T) hb_is_trivially_default_constructible<T>::value - -template <typename T> -using hb_is_trivially_copy_constructible= hb_is_copy_constructible<hb_trivial<T>>; -#define hb_is_trivially_copy_constructible(T) hb_is_trivially_copy_constructible<T>::value - -template <typename T> -using hb_is_trivially_move_constructible= hb_is_move_constructible<hb_trivial<T>>; -#define hb_is_trivially_move_constructible(T) hb_is_trivially_move_constructible<T>::value - -/* Don't know how to do the following. */ -//template <typename T, typename U> -//using hb_is_trivially_assignable= hb_is_assignable<hb_trivial<T>, hb_trivial<U>>; -//#define hb_is_trivially_assignable(T,U) hb_is_trivially_assignable<T, U>::value - -template <typename T> -using hb_is_trivially_copy_assignable= hb_is_copy_assignable<hb_trivial<T>>; -#define hb_is_trivially_copy_assignable(T) hb_is_trivially_copy_assignable<T>::value - -template <typename T> -using hb_is_trivially_move_assignable= hb_is_move_assignable<hb_trivial<T>>; -#define hb_is_trivially_move_assignable(T) hb_is_trivially_move_assignable<T>::value - -template <typename T> -using hb_is_trivially_copyable= hb_bool_constant< - hb_is_trivially_destructible (T) && - (!hb_is_move_assignable (T) || hb_is_trivially_move_assignable (T)) && - (!hb_is_move_constructible (T) || hb_is_trivially_move_constructible (T)) && - (!hb_is_copy_assignable (T) || hb_is_trivially_copy_assignable (T)) && - (!hb_is_copy_constructible (T) || hb_is_trivially_copy_constructible (T)) && - true ->; -#define hb_is_trivially_copyable(T) hb_is_trivially_copyable<T>::value - -template <typename T> -using hb_is_trivial= hb_bool_constant< - hb_is_trivially_copyable (T) && - hb_is_trivially_default_constructible (T) ->; -#define hb_is_trivial(T) hb_is_trivial<T>::value - /* hb_unwrap_type (T) * If T has no T::type, returns T. Otherwise calls itself on T::type recursively. */ diff --git a/thirdparty/harfbuzz/src/hb-mutex.hh b/thirdparty/harfbuzz/src/hb-mutex.hh index a9227a741d..6914b22450 100644 --- a/thirdparty/harfbuzz/src/hb-mutex.hh +++ b/thirdparty/harfbuzz/src/hb-mutex.hh @@ -47,7 +47,7 @@ /* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */ -#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__)) +#elif !defined(HB_NO_MT) && !defined(HB_MUTEX_IMPL_STD_MUTEX) && (defined(HAVE_PTHREAD) || defined(__APPLE__)) #include <pthread.h> typedef pthread_mutex_t hb_mutex_impl_t; @@ -57,7 +57,7 @@ typedef pthread_mutex_t hb_mutex_impl_t; #define hb_mutex_impl_finish(M) pthread_mutex_destroy (M) -#elif !defined(HB_NO_MT) && defined(_WIN32) +#elif !defined(HB_NO_MT) && !defined(HB_MUTEX_IMPL_STD_MUTEX) && defined(_WIN32) typedef CRITICAL_SECTION hb_mutex_impl_t; #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -70,7 +70,17 @@ typedef CRITICAL_SECTION hb_mutex_impl_t; #define hb_mutex_impl_finish(M) DeleteCriticalSection (M) -#elif defined(HB_NO_MT) +#elif !defined(HB_NO_MT) + +#include <mutex> +typedef std::mutex hb_mutex_impl_t; +#define hb_mutex_impl_init(M) HB_STMT_START { new (M) hb_mutex_impl_t; } HB_STMT_END +#define hb_mutex_impl_lock(M) (M)->lock () +#define hb_mutex_impl_unlock(M) (M)->unlock () +#define hb_mutex_impl_finish(M) HB_STMT_START { (M)->~hb_mutex_impl_t(); } HB_STMT_END + + +#else /* defined(HB_NO_MT) */ typedef int hb_mutex_impl_t; #define hb_mutex_impl_init(M) HB_STMT_START {} HB_STMT_END @@ -79,22 +89,21 @@ typedef int hb_mutex_impl_t; #define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END -#else - -#error "Could not find any system to define mutex macros." -#error "Check hb-mutex.hh for possible resolutions." - #endif struct hb_mutex_t { - hb_mutex_impl_t m; - - void init () { hb_mutex_impl_init (&m); } - void lock () { hb_mutex_impl_lock (&m); } - void unlock () { hb_mutex_impl_unlock (&m); } - void fini () { hb_mutex_impl_finish (&m); } + /* Create space for, but do not initialize m. */ + alignas(hb_mutex_impl_t) char m[sizeof (hb_mutex_impl_t)]; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" + void init () { hb_mutex_impl_init ((hb_mutex_impl_t *) m); } + void lock () { hb_mutex_impl_lock ((hb_mutex_impl_t *) m); } + void unlock () { hb_mutex_impl_unlock ((hb_mutex_impl_t *) m); } + void fini () { hb_mutex_impl_finish ((hb_mutex_impl_t *) m); } +#pragma GCC diagnostic pop }; struct hb_lock_t diff --git a/thirdparty/harfbuzz/src/hb-open-type.hh b/thirdparty/harfbuzz/src/hb-open-type.hh index 49653ce97e..7e524177f6 100644 --- a/thirdparty/harfbuzz/src/hb-open-type.hh +++ b/thirdparty/harfbuzz/src/hb-open-type.hh @@ -64,7 +64,7 @@ struct IntType IntType& operator = (Type i) { v = i; return *this; } /* For reason we define cast out operator for signed/unsigned, instead of Type, see: * https://github.com/harfbuzz/harfbuzz/pull/2875/commits/09836013995cab2b9f07577a179ad7b024130467 */ - operator hb_conditional<hb_is_signed (Type), signed, unsigned> () const { return v; } + operator typename std::conditional<std::is_signed<Type>::value, signed, unsigned>::type () const { return v; } bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } bool operator != (const IntType &o) const { return !(*this == o); } @@ -86,7 +86,7 @@ struct IntType return pb->cmp (*pa); } template <typename Type2, - hb_enable_if (hb_is_integral (Type2) && + hb_enable_if (std::is_integral<Type2>::value && sizeof (Type2) < sizeof (int) && sizeof (Type) < sizeof (int))> int cmp (Type2 a) const @@ -122,6 +122,15 @@ typedef IntType<int32_t> HBINT32; /* 32-bit signed integer. */ * Works for unsigned, but not signed, since we rely on compiler for sign-extension. */ typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */ +/* 15-bit unsigned number; top bit used for extension. */ +struct HBUINT15 : HBUINT16 +{ + /* TODO Flesh out; actually mask top bit. */ + HBUINT15& operator = (uint16_t i ) { HBUINT16::operator= (i); return *this; } + public: + DEFINE_SIZE_STATIC (2); +}; + /* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */ typedef HBINT16 FWORD; @@ -182,9 +191,9 @@ struct Tag : HBUINT32 }; /* Glyph index number, same as uint16 (length = 16 bits) */ -struct HBGlyphID : HBUINT16 +struct HBGlyphID16 : HBUINT16 { - HBGlyphID& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; } + HBGlyphID16& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; } }; /* Script/language-system/feature index */ @@ -332,7 +341,7 @@ struct OffsetTo : Offset<OffsetType, has_null> s->push (); - bool ret = c->dispatch (src_base+src, hb_forward<Ts> (ds)...); + bool ret = c->dispatch (src_base+src, std::forward<Ts> (ds)...); if (ret || !has_null) s->add_link (*this, s->pop_pack ()); @@ -349,7 +358,7 @@ struct OffsetTo : Offset<OffsetType, has_null> *this = 0; Type* obj = c->push<Type> (); - bool ret = obj->serialize (c, hb_forward<Ts> (ds)...); + bool ret = obj->serialize (c, std::forward<Ts> (ds)...); if (ret) c->add_link (*this, c->pop_pack ()); @@ -375,7 +384,7 @@ struct OffsetTo : Offset<OffsetType, has_null> c->push (); - bool ret = c->copy (src_base+src, hb_forward<Ts> (ds)...); + bool ret = c->copy (src_base+src, std::forward<Ts> (ds)...); c->add_link (*this, c->pop_pack (), whence, dst_bias); @@ -401,7 +410,7 @@ struct OffsetTo : Offset<OffsetType, has_null> TRACE_SANITIZE (this); return_trace (sanitize_shallow (c, base) && (this->is_null () || - c->dispatch (StructAtOffset<Type> (base, *this), hb_forward<Ts> (ds)...) || + c->dispatch (StructAtOffset<Type> (base, *this), std::forward<Ts> (ds)...) || neuter (c))); } @@ -509,9 +518,9 @@ struct UnsizedArrayOf { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c, count))) return_trace (false); - if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); + if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true); for (unsigned int i = 0; i < count; i++) - if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...))) + if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...))) return_trace (false); return_trace (true); } @@ -556,7 +565,7 @@ struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_ { TRACE_SANITIZE (this); return_trace ((UnsizedArray16OfOffsetTo<Type, OffsetType, has_null> - ::sanitize (c, count, this, hb_forward<Ts> (ds)...))); + ::sanitize (c, count, this, std::forward<Ts> (ds)...))); } }; @@ -698,10 +707,10 @@ struct ArrayOf { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); - if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); + if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true); unsigned int count = len; for (unsigned int i = 0; i < count; i++) - if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...))) + if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...))) return_trace (false); return_trace (true); } @@ -759,7 +768,7 @@ struct List16OfOffset16To : Array16OfOffset16To<Type> bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); - return_trace (Array16OfOffset16To<Type>::sanitize (c, this, hb_forward<Ts> (ds)...)); + return_trace (Array16OfOffset16To<Type>::sanitize (c, this, std::forward<Ts> (ds)...)); } }; @@ -826,10 +835,10 @@ struct HeadlessArrayOf { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); - if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); + if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true); unsigned int count = get_length (); for (unsigned int i = 0; i < count; i++) - if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...))) + if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...))) return_trace (false); return_trace (true); } @@ -875,10 +884,10 @@ struct ArrayOfM1 { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); - if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); + if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true); unsigned int count = lenM1 + 1; for (unsigned int i = 0; i < count; i++) - if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...))) + if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...))) return_trace (false); return_trace (true); } @@ -1061,10 +1070,10 @@ struct VarSizedBinSearchArrayOf { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); - if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); + if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true); unsigned int count = get_length (); for (unsigned int i = 0; i < count; i++) - if (unlikely (!(*this)[i].sanitize (c, hb_forward<Ts> (ds)...))) + if (unlikely (!(*this)[i].sanitize (c, std::forward<Ts> (ds)...))) return_trace (false); return_trace (true); } diff --git a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh index eaaf5e12ec..180c87cb89 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh @@ -373,7 +373,7 @@ struct Dict : UnsizedByteStr { TRACE_SERIALIZE (this); for (unsigned int i = 0; i < dictval.get_count (); i++) - if (unlikely (!opszr.serialize (c, dictval[i], hb_forward<Ts> (ds)...))) + if (unlikely (!opszr.serialize (c, dictval[i], std::forward<Ts> (ds)...))) return_trace (false); return_trace (true); diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh index b904bb46a8..c8a2af1e82 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh @@ -604,7 +604,7 @@ struct CmapSubtableTrimmed UINT length; /* Byte length of this subtable. */ UINT language; /* Ignore. */ UINT startCharCode; /* First character code covered. */ - ArrayOf<HBGlyphID, UINT> + ArrayOf<HBGlyphID16, UINT> glyphIdArray; /* Array of glyph index values for character * codes in the range. */ public: @@ -900,7 +900,7 @@ struct UVSMapping } HBUINT24 unicodeValue; /* Base Unicode value of the UVS */ - HBGlyphID glyphID; /* Glyph ID of the UVS */ + HBGlyphID16 glyphID; /* Glyph ID of the UVS */ public: DEFINE_SIZE_STATIC (5); }; diff --git a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh index 6c31d1b53e..14459914ee 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh @@ -508,8 +508,8 @@ struct IndexSubtableRecord offset, length, format); } - HBGlyphID firstGlyphIndex; - HBGlyphID lastGlyphIndex; + HBGlyphID16 firstGlyphIndex; + HBGlyphID16 lastGlyphIndex; Offset32To<IndexSubtable> offsetToSubtable; public: DEFINE_SIZE_STATIC (8); @@ -679,8 +679,8 @@ struct BitmapSizeTable HBUINT32 colorRef; SBitLineMetrics horizontal; SBitLineMetrics vertical; - HBGlyphID startGlyphIndex; - HBGlyphID endGlyphIndex; + HBGlyphID16 startGlyphIndex; + HBGlyphID16 endGlyphIndex; HBUINT8 ppemX; HBUINT8 ppemY; HBUINT8 bitDepth; diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh index 007ff3f47b..03476faba7 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh @@ -30,6 +30,7 @@ #include "hb-open-type.hh" #include "hb-ot-layout-common.hh" +#include "hb-ot-var-common.hh" /* * COLR -- Color @@ -42,7 +43,7 @@ #endif #ifndef COLRV1_ENABLE_SUBSETTING -#define COLRV1_ENABLE_SUBSETTING 0 +#define COLRV1_ENABLE_SUBSETTING 1 #endif namespace OT { @@ -121,7 +122,7 @@ struct LayerRecord } public: - HBGlyphID glyphId; /* Glyph ID of layer glyph */ + HBGlyphID16 glyphId; /* Glyph ID of layer glyph */ Index colorIdx; /* Index value to use with a * selected color palette. * An index value of 0xFFFF @@ -148,7 +149,7 @@ struct BaseGlyphRecord } public: - HBGlyphID glyphId; /* Glyph ID of reference glyph */ + HBGlyphID16 glyphId; /* Glyph ID of reference glyph */ HBUINT16 firstLayerIdx; /* Index (from beginning of * the Layer Records) to the * layer record. There will be @@ -163,15 +164,31 @@ struct BaseGlyphRecord template <typename T> struct Variable { + Variable<T>* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + return_trace (c->embed (this)); + } + + void closurev1 (hb_colrv1_closure_context_t* c) const + { value.closurev1 (c); } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + if (!value.subset (c)) return_trace (false); + return_trace (c->serializer->embed (varIdxBase)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); + return_trace (c->check_struct (this) && value.sanitize (c)); } protected: T value; - VarIdx varIdx; + VarIdx varIdxBase; public: DEFINE_SIZE_STATIC (4 + T::static_size); }; @@ -179,51 +196,46 @@ struct Variable template <typename T> struct NoVariable { - bool sanitize (hb_sanitize_context_t *c) const + NoVariable<T>* copy (hb_serialize_context_t *c) const { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); + TRACE_SERIALIZE (this); + return_trace (c->embed (this)); } - T value; - public: - DEFINE_SIZE_STATIC (T::static_size); -}; - -// Color structures + void closurev1 (hb_colrv1_closure_context_t* c) const + { value.closurev1 (c); } -template <template<typename> class Var> -struct ColorIndex -{ bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - auto *out = c->serializer->embed (*this); - if (unlikely (!out)) return_trace (false); - return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex), - HB_SERIALIZE_ERROR_INT_OVERFLOW)); + return_trace (value.subset (c)); } bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); + return_trace (c->check_struct (this) && value.sanitize (c)); } - HBUINT16 paletteIndex; - Var<F2DOT14> alpha; + T value; public: - DEFINE_SIZE_STATIC (2 + Var<F2DOT14>::static_size); + DEFINE_SIZE_STATIC (T::static_size); }; -template <template<typename> class Var> +// Color structures + struct ColorStop { + void closurev1 (hb_colrv1_closure_context_t* c) const + { c->add_palette_index (paletteIndex); } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - if (unlikely (!c->serializer->embed (stopOffset))) return_trace (false); - return_trace (color.subset (c)); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex), + HB_SERIALIZE_ERROR_INT_OVERFLOW)); } bool sanitize (hb_sanitize_context_t *c) const @@ -232,10 +244,11 @@ struct ColorStop return_trace (c->check_struct (this)); } - Var<F2DOT14> stopOffset; - ColorIndex<Var> color; + F2DOT14 stopOffset; + HBUINT16 paletteIndex; + F2DOT14 alpha; public: - DEFINE_SIZE_STATIC (Var<F2DOT14>::static_size + ColorIndex<Var>::static_size); + DEFINE_SIZE_STATIC (2 + 2 * F2DOT14::static_size); }; struct Extend : HBUINT8 @@ -252,6 +265,12 @@ struct Extend : HBUINT8 template <template<typename> class Var> struct ColorLine { + void closurev1 (hb_colrv1_closure_context_t* c) const + { + for (const auto &stop : stops.iter ()) + stop.closurev1 (c); + } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); @@ -276,8 +295,8 @@ struct ColorLine stops.sanitize (c)); } - Extend extend; - Array16Of<ColorStop<Var>> stops; + Extend extend; + Array16Of<Var<ColorStop>> stops; public: DEFINE_SIZE_ARRAY_SIZED (3, stops); }; @@ -331,7 +350,6 @@ struct CompositeMode : HBUINT8 DEFINE_SIZE_STATIC (1); }; -template <template<typename> class Var> struct Affine2x3 { bool sanitize (hb_sanitize_context_t *c) const @@ -340,14 +358,14 @@ struct Affine2x3 return_trace (c->check_struct (this)); } - Var<HBFixed> xx; - Var<HBFixed> yx; - Var<HBFixed> xy; - Var<HBFixed> yy; - Var<HBFixed> dx; - Var<HBFixed> dy; + HBFixed xx; + HBFixed yx; + HBFixed xy; + HBFixed yy; + HBFixed dx; + HBFixed dy; public: - DEFINE_SIZE_STATIC (6 * Var<HBFixed>::static_size); + DEFINE_SIZE_STATIC (6 * HBFixed::static_size); }; struct PaintColrLayers @@ -373,22 +391,23 @@ struct PaintColrLayers HBUINT8 format; /* format = 1 */ HBUINT8 numLayers; - HBUINT32 firstLayerIndex; /* index into COLRv1::layersV1 */ + HBUINT32 firstLayerIndex; /* index into COLRv1::layerList */ public: DEFINE_SIZE_STATIC (6); }; -template <template<typename> class Var> struct PaintSolid { void closurev1 (hb_colrv1_closure_context_t* c) const - { c->add_palette_index (color.paletteIndex); } + { c->add_palette_index (paletteIndex); } bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - if (unlikely (!c->serializer->embed (format))) return_trace (false); - return_trace (color.subset (c)); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex), + HB_SERIALIZE_ERROR_INT_OVERFLOW)); } bool sanitize (hb_sanitize_context_t *c) const @@ -397,20 +416,18 @@ struct PaintSolid return_trace (c->check_struct (this)); } - HBUINT8 format; /* format = 2(noVar) or 3(Var)*/ - ColorIndex<Var> color; + HBUINT8 format; /* format = 2(noVar) or 3(Var)*/ + HBUINT16 paletteIndex; + F2DOT14 alpha; public: - DEFINE_SIZE_STATIC (1 + ColorIndex<Var>::static_size); + DEFINE_SIZE_STATIC (3 + F2DOT14::static_size); }; template <template<typename> class Var> struct PaintLinearGradient { void closurev1 (hb_colrv1_closure_context_t* c) const - { - for (const auto &stop : (this+colorLine).stops.iter ()) - c->add_palette_index (stop.color.paletteIndex); - } + { (this+colorLine).closurev1 (c); } bool subset (hb_subset_context_t *c) const { @@ -430,19 +447,22 @@ struct PaintLinearGradient HBUINT8 format; /* format = 4(noVar) or 5 (Var) */ Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintLinearGradient * table) to ColorLine subtable. */ - Var<FWORD> x0; - Var<FWORD> y0; - Var<FWORD> x1; - Var<FWORD> y1; - Var<FWORD> x2; - Var<FWORD> y2; + FWORD x0; + FWORD y0; + FWORD x1; + FWORD y1; + FWORD x2; + FWORD y2; public: - DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size); + DEFINE_SIZE_STATIC (4 + 6 * FWORD::static_size); }; template <template<typename> class Var> struct PaintRadialGradient { + void closurev1 (hb_colrv1_closure_context_t* c) const + { (this+colorLine).closurev1 (c); } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); @@ -452,12 +472,6 @@ struct PaintRadialGradient return_trace (out->colorLine.serialize_subset (c, colorLine, this)); } - void closurev1 (hb_colrv1_closure_context_t* c) const - { - for (const auto &stop : (this+colorLine).stops.iter ()) - c->add_palette_index (stop.color.paletteIndex); - } - bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -467,19 +481,22 @@ struct PaintRadialGradient HBUINT8 format; /* format = 6(noVar) or 7 (Var) */ Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintRadialGradient * table) to ColorLine subtable. */ - Var<FWORD> x0; - Var<FWORD> y0; - Var<UFWORD> radius0; - Var<FWORD> x1; - Var<FWORD> y1; - Var<UFWORD> radius1; + FWORD x0; + FWORD y0; + UFWORD radius0; + FWORD x1; + FWORD y1; + UFWORD radius1; public: - DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size); + DEFINE_SIZE_STATIC (4 + 6 * FWORD::static_size); }; template <template<typename> class Var> struct PaintSweepGradient { + void closurev1 (hb_colrv1_closure_context_t* c) const + { (this+colorLine).closurev1 (c); } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); @@ -489,12 +506,6 @@ struct PaintSweepGradient return_trace (out->colorLine.serialize_subset (c, colorLine, this)); } - void closurev1 (hb_colrv1_closure_context_t* c) const - { - for (const auto &stop : (this+colorLine).stops.iter ()) - c->add_palette_index (stop.color.paletteIndex); - } - bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -504,12 +515,12 @@ struct PaintSweepGradient HBUINT8 format; /* format = 8(noVar) or 9 (Var) */ Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintSweepGradient * table) to ColorLine subtable. */ - Var<FWORD> centerX; - Var<FWORD> centerY; - Var<HBFixed> startAngle; - Var<HBFixed> endAngle; + FWORD centerX; + FWORD centerY; + F2DOT14 startAngle; + F2DOT14 endAngle; public: - DEFINE_SIZE_STATIC (2 * Var<FWORD>::static_size + 2 * Var<HBFixed>::static_size); + DEFINE_SIZE_STATIC (4 + 2 * FWORD::static_size + 2 * F2DOT14::static_size); }; struct Paint; @@ -580,24 +591,25 @@ struct PaintTransform TRACE_SUBSET (this); auto *out = c->serializer->embed (this); if (unlikely (!out)) return_trace (false); - + if (!out->transform.serialize_copy (c->serializer, transform, this)) return_trace (false); return_trace (out->src.serialize_subset (c, src, this)); } bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && src.sanitize (c, this)); + return_trace (c->check_struct (this) && + src.sanitize (c, this) && + transform.sanitize (c, this)); } - HBUINT8 format; /* format = 12(noVar) or 13 (Var) */ - Offset24To<Paint> src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */ - Affine2x3<Var> transform; + HBUINT8 format; /* format = 12(noVar) or 13 (Var) */ + Offset24To<Paint> src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */ + Offset24To<Var<Affine2x3>> transform; public: - DEFINE_SIZE_STATIC (4 + Affine2x3<Var>::static_size); + DEFINE_SIZE_STATIC (7); }; -template <template<typename> class Var> struct PaintTranslate { HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; @@ -619,14 +631,13 @@ struct PaintTranslate HBUINT8 format; /* format = 14(noVar) or 15 (Var) */ Offset24To<Paint> src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */ - Var<HBFixed> dx; - Var<HBFixed> dy; + FWORD dx; + FWORD dy; public: - DEFINE_SIZE_STATIC (4 + Var<HBFixed>::static_size); + DEFINE_SIZE_STATIC (4 + 2 * FWORD::static_size); }; -template <template<typename> class Var> -struct PaintRotate +struct PaintScale { HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; @@ -646,15 +657,150 @@ struct PaintRotate } HBUINT8 format; /* format = 16 (noVar) or 17(Var) */ + Offset24To<Paint> src; /* Offset (from beginning of PaintScale table) to Paint subtable. */ + F2DOT14 scaleX; + F2DOT14 scaleY; + public: + DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size); +}; + +struct PaintScaleAroundCenter +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 18 (noVar) or 19(Var) */ + Offset24To<Paint> src; /* Offset (from beginning of PaintScaleAroundCenter table) to Paint subtable. */ + F2DOT14 scaleX; + F2DOT14 scaleY; + FWORD centerX; + FWORD centerY; + public: + DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size + 2 * FWORD::static_size); +}; + +struct PaintScaleUniform +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 20 (noVar) or 21(Var) */ + Offset24To<Paint> src; /* Offset (from beginning of PaintScaleUniform table) to Paint subtable. */ + F2DOT14 scale; + public: + DEFINE_SIZE_STATIC (4 + F2DOT14::static_size); +}; + +struct PaintScaleUniformAroundCenter +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 22 (noVar) or 23(Var) */ + Offset24To<Paint> src; /* Offset (from beginning of PaintScaleUniformAroundCenter table) to Paint subtable. */ + F2DOT14 scale; + FWORD centerX; + FWORD centerY; + public: + DEFINE_SIZE_STATIC (4 + F2DOT14::static_size + 2 * FWORD::static_size); +}; + +struct PaintRotate +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 24 (noVar) or 25(Var) */ Offset24To<Paint> src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */ - Var<HBFixed> angle; - Var<HBFixed> centerX; - Var<HBFixed> centerY; + F2DOT14 angle; public: - DEFINE_SIZE_STATIC (4 + 3 * Var<HBFixed>::static_size); + DEFINE_SIZE_STATIC (4 + F2DOT14::static_size); +}; + +struct PaintRotateAroundCenter +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 26 (noVar) or 27(Var) */ + Offset24To<Paint> src; /* Offset (from beginning of PaintRotateAroundCenter table) to Paint subtable. */ + F2DOT14 angle; + FWORD centerX; + FWORD centerY; + public: + DEFINE_SIZE_STATIC (4 + F2DOT14::static_size + 2 * FWORD::static_size); }; -template <template<typename> class Var> struct PaintSkew { HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; @@ -674,14 +820,41 @@ struct PaintSkew return_trace (c->check_struct (this) && src.sanitize (c, this)); } - HBUINT8 format; /* format = 18(noVar) or 19 (Var) */ + HBUINT8 format; /* format = 28(noVar) or 29 (Var) */ Offset24To<Paint> src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */ - Var<HBFixed> xSkewAngle; - Var<HBFixed> ySkewAngle; - Var<HBFixed> centerX; - Var<HBFixed> centerY; + F2DOT14 xSkewAngle; + F2DOT14 ySkewAngle; public: - DEFINE_SIZE_STATIC (4 + 4 * Var<HBFixed>::static_size); + DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size); +}; + +struct PaintSkewAroundCenter +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 30(noVar) or 31 (Var) */ + Offset24To<Paint> src; /* Offset (from beginning of PaintSkewAroundCenter table) to Paint subtable. */ + F2DOT14 xSkewAngle; + F2DOT14 ySkewAngle; + FWORD centerX; + FWORD centerY; + public: + DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size + 2 * FWORD::static_size); }; struct PaintComposite @@ -706,7 +879,7 @@ struct PaintComposite backdrop.sanitize (c, this)); } - HBUINT8 format; /* format = 20 */ + HBUINT8 format; /* format = 32 */ Offset24To<Paint> src; /* Offset (from beginning of PaintComposite table) to source Paint subtable. */ CompositeMode mode; /* If mode is unrecognized use COMPOSITE_CLEAR */ Offset24To<Paint> backdrop; /* Offset (from beginning of PaintComposite table) to backdrop Paint subtable. */ @@ -714,6 +887,179 @@ struct PaintComposite DEFINE_SIZE_STATIC (8); }; +struct ClipBoxFormat1 +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + HBUINT8 format; /* format = 1(noVar) or 2(Var)*/ + FWORD xMin; + FWORD yMin; + FWORD xMax; + FWORD yMax; + public: + DEFINE_SIZE_STATIC (1 + 4 * FWORD::static_size); +}; + +struct ClipBoxFormat2 : Variable<ClipBoxFormat1> {}; + +struct ClipBox +{ + ClipBox* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + switch (u.format) { + case 1: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format1))); + case 2: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format2))); + default:return_trace (nullptr); + } + } + + template <typename context_t, typename ...Ts> + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { + TRACE_DISPATCH (this, u.format); + if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + default:return_trace (c->default_return_value ()); + } + } + + protected: + union { + HBUINT8 format; /* Format identifier */ + ClipBoxFormat1 format1; + ClipBoxFormat2 format2; + } u; +}; + +struct ClipRecord +{ + ClipRecord* copy (hb_serialize_context_t *c, const void *base) const + { + TRACE_SERIALIZE (this); + auto *out = c->embed (this); + if (unlikely (!out)) return_trace (nullptr); + if (!out->clipBox.serialize_copy (c, clipBox, base)) return_trace (nullptr); + return_trace (out); + } + + bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && clipBox.sanitize (c, base)); + } + + public: + HBUINT16 startGlyphID; // first gid clip applies to + HBUINT16 endGlyphID; // last gid clip applies to, inclusive + Offset24To<ClipBox> clipBox; // Box or VarBox + public: + DEFINE_SIZE_STATIC (7); +}; + +struct ClipList +{ + unsigned serialize_clip_records (hb_serialize_context_t *c, + const hb_set_t& gids, + const hb_map_t& gid_offset_map) const + { + TRACE_SERIALIZE (this); + if (gids.is_empty () || + gid_offset_map.get_population () != gids.get_population ()) + return_trace (0); + + unsigned count = 0; + + hb_codepoint_t start_gid= gids.get_min (); + hb_codepoint_t prev_gid = start_gid; + + unsigned offset = gid_offset_map.get (start_gid); + unsigned prev_offset = offset; + for (const hb_codepoint_t _ : gids.iter ()) + { + if (_ == start_gid) continue; + + offset = gid_offset_map.get (_); + if (_ == prev_gid + 1 && offset == prev_offset) + { + prev_gid = _; + continue; + } + + ClipRecord record; + record.startGlyphID = start_gid; + record.endGlyphID = prev_gid; + record.clipBox = prev_offset; + + if (!c->copy (record, this)) return_trace (0); + count++; + + start_gid = _; + prev_gid = _; + prev_offset = offset; + } + + //last one + { + ClipRecord record; + record.startGlyphID = start_gid; + record.endGlyphID = prev_gid; + record.clipBox = prev_offset; + if (!c->copy (record, this)) return_trace (0); + count++; + } + return_trace (count); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + if (!c->serializer->check_assign (out->format, format, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); + + const hb_set_t& glyphset = *c->plan->_glyphset; + const hb_map_t &glyph_map = *c->plan->glyph_map; + + hb_map_t new_gid_offset_map; + hb_set_t new_gids; + for (const ClipRecord& record : clips.iter ()) + { + unsigned start_gid = record.startGlyphID; + unsigned end_gid = record.endGlyphID; + for (unsigned gid = start_gid; gid <= end_gid; gid++) + { + if (!glyphset.has (gid) || !glyph_map.has (gid)) continue; + unsigned new_gid = glyph_map.get (gid); + new_gid_offset_map.set (new_gid, record.clipBox); + new_gids.add (new_gid); + } + } + + unsigned count = serialize_clip_records (c->serializer, new_gids, new_gid_offset_map); + if (!count) return_trace (false); + return_trace (c->serializer->check_assign (out->clips.len, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && clips.sanitize (c, this)); + } + + HBUINT8 format; // Set to 1. + Array32Of<ClipRecord> clips; // Clip records, sorted by startGlyphID + public: + DEFINE_SIZE_ARRAY_SIZED (5, clips); +}; + struct Paint { template <typename context_t, typename ...Ts> @@ -722,57 +1068,81 @@ struct Paint TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.paintformat1, hb_forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.paintformat2, hb_forward<Ts> (ds)...)); - case 3: return_trace (c->dispatch (u.paintformat3, hb_forward<Ts> (ds)...)); - case 4: return_trace (c->dispatch (u.paintformat4, hb_forward<Ts> (ds)...)); - case 5: return_trace (c->dispatch (u.paintformat5, hb_forward<Ts> (ds)...)); - case 6: return_trace (c->dispatch (u.paintformat6, hb_forward<Ts> (ds)...)); - case 7: return_trace (c->dispatch (u.paintformat7, hb_forward<Ts> (ds)...)); - case 8: return_trace (c->dispatch (u.paintformat8, hb_forward<Ts> (ds)...)); - case 9: return_trace (c->dispatch (u.paintformat9, hb_forward<Ts> (ds)...)); - case 10: return_trace (c->dispatch (u.paintformat10, hb_forward<Ts> (ds)...)); - case 11: return_trace (c->dispatch (u.paintformat11, hb_forward<Ts> (ds)...)); - case 12: return_trace (c->dispatch (u.paintformat12, hb_forward<Ts> (ds)...)); - case 13: return_trace (c->dispatch (u.paintformat13, hb_forward<Ts> (ds)...)); - case 14: return_trace (c->dispatch (u.paintformat14, hb_forward<Ts> (ds)...)); - case 15: return_trace (c->dispatch (u.paintformat15, hb_forward<Ts> (ds)...)); - case 16: return_trace (c->dispatch (u.paintformat16, hb_forward<Ts> (ds)...)); - case 17: return_trace (c->dispatch (u.paintformat17, hb_forward<Ts> (ds)...)); - case 18: return_trace (c->dispatch (u.paintformat18, hb_forward<Ts> (ds)...)); - case 19: return_trace (c->dispatch (u.paintformat19, hb_forward<Ts> (ds)...)); - case 20: return_trace (c->dispatch (u.paintformat20, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.paintformat1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.paintformat2, std::forward<Ts> (ds)...)); + case 3: return_trace (c->dispatch (u.paintformat3, std::forward<Ts> (ds)...)); + case 4: return_trace (c->dispatch (u.paintformat4, std::forward<Ts> (ds)...)); + case 5: return_trace (c->dispatch (u.paintformat5, std::forward<Ts> (ds)...)); + case 6: return_trace (c->dispatch (u.paintformat6, std::forward<Ts> (ds)...)); + case 7: return_trace (c->dispatch (u.paintformat7, std::forward<Ts> (ds)...)); + case 8: return_trace (c->dispatch (u.paintformat8, std::forward<Ts> (ds)...)); + case 9: return_trace (c->dispatch (u.paintformat9, std::forward<Ts> (ds)...)); + case 10: return_trace (c->dispatch (u.paintformat10, std::forward<Ts> (ds)...)); + case 11: return_trace (c->dispatch (u.paintformat11, std::forward<Ts> (ds)...)); + case 12: return_trace (c->dispatch (u.paintformat12, std::forward<Ts> (ds)...)); + case 13: return_trace (c->dispatch (u.paintformat13, std::forward<Ts> (ds)...)); + case 14: return_trace (c->dispatch (u.paintformat14, std::forward<Ts> (ds)...)); + case 15: return_trace (c->dispatch (u.paintformat15, std::forward<Ts> (ds)...)); + case 16: return_trace (c->dispatch (u.paintformat16, std::forward<Ts> (ds)...)); + case 17: return_trace (c->dispatch (u.paintformat17, std::forward<Ts> (ds)...)); + case 18: return_trace (c->dispatch (u.paintformat18, std::forward<Ts> (ds)...)); + case 19: return_trace (c->dispatch (u.paintformat19, std::forward<Ts> (ds)...)); + case 20: return_trace (c->dispatch (u.paintformat20, std::forward<Ts> (ds)...)); + case 21: return_trace (c->dispatch (u.paintformat21, std::forward<Ts> (ds)...)); + case 22: return_trace (c->dispatch (u.paintformat22, std::forward<Ts> (ds)...)); + case 23: return_trace (c->dispatch (u.paintformat23, std::forward<Ts> (ds)...)); + case 24: return_trace (c->dispatch (u.paintformat24, std::forward<Ts> (ds)...)); + case 25: return_trace (c->dispatch (u.paintformat25, std::forward<Ts> (ds)...)); + case 26: return_trace (c->dispatch (u.paintformat26, std::forward<Ts> (ds)...)); + case 27: return_trace (c->dispatch (u.paintformat27, std::forward<Ts> (ds)...)); + case 28: return_trace (c->dispatch (u.paintformat28, std::forward<Ts> (ds)...)); + case 29: return_trace (c->dispatch (u.paintformat29, std::forward<Ts> (ds)...)); + case 30: return_trace (c->dispatch (u.paintformat30, std::forward<Ts> (ds)...)); + case 31: return_trace (c->dispatch (u.paintformat31, std::forward<Ts> (ds)...)); + case 32: return_trace (c->dispatch (u.paintformat32, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } protected: union { - HBUINT8 format; - PaintColrLayers paintformat1; - PaintSolid<NoVariable> paintformat2; - PaintSolid<Variable> paintformat3; - PaintLinearGradient<NoVariable> paintformat4; - PaintLinearGradient<Variable> paintformat5; - PaintRadialGradient<NoVariable> paintformat6; - PaintRadialGradient<Variable> paintformat7; - PaintSweepGradient<NoVariable> paintformat8; - PaintSweepGradient<Variable> paintformat9; - PaintGlyph paintformat10; - PaintColrGlyph paintformat11; - PaintTransform<NoVariable> paintformat12; - PaintTransform<Variable> paintformat13; - PaintTranslate<NoVariable> paintformat14; - PaintTranslate<Variable> paintformat15; - PaintRotate<NoVariable> paintformat16; - PaintRotate<Variable> paintformat17; - PaintSkew<NoVariable> paintformat18; - PaintSkew<Variable> paintformat19; - PaintComposite paintformat20; + HBUINT8 format; + PaintColrLayers paintformat1; + PaintSolid paintformat2; + Variable<PaintSolid> paintformat3; + PaintLinearGradient<NoVariable> paintformat4; + Variable<PaintLinearGradient<Variable>> paintformat5; + PaintRadialGradient<NoVariable> paintformat6; + Variable<PaintRadialGradient<Variable>> paintformat7; + PaintSweepGradient<NoVariable> paintformat8; + Variable<PaintSweepGradient<Variable>> paintformat9; + PaintGlyph paintformat10; + PaintColrGlyph paintformat11; + PaintTransform<NoVariable> paintformat12; + PaintTransform<Variable> paintformat13; + PaintTranslate paintformat14; + Variable<PaintTranslate> paintformat15; + PaintScale paintformat16; + Variable<PaintScale> paintformat17; + PaintScaleAroundCenter paintformat18; + Variable<PaintScaleAroundCenter> paintformat19; + PaintScaleUniform paintformat20; + Variable<PaintScaleUniform> paintformat21; + PaintScaleUniformAroundCenter paintformat22; + Variable<PaintScaleUniformAroundCenter> paintformat23; + PaintRotate paintformat24; + Variable<PaintRotate> paintformat25; + PaintRotateAroundCenter paintformat26; + Variable<PaintRotateAroundCenter> paintformat27; + PaintSkew paintformat28; + Variable<PaintSkew> paintformat29; + PaintSkewAroundCenter paintformat30; + Variable<PaintSkewAroundCenter> paintformat31; + PaintComposite paintformat32; } u; }; -struct BaseGlyphV1Record +struct BaseGlyphPaintRecord { int cmp (hb_codepoint_t g) const { return g < glyphId ? -1 : g > glyphId ? 1 : 0; } @@ -797,14 +1167,14 @@ struct BaseGlyphV1Record } public: - HBGlyphID glyphId; /* Glyph ID of reference glyph */ - Offset32To<Paint> paint; /* Offset (from beginning of BaseGlyphV1Record array) to Paint, + HBGlyphID16 glyphId; /* Glyph ID of reference glyph */ + Offset32To<Paint> paint; /* Offset (from beginning of BaseGlyphPaintRecord array) to Paint, * Typically PaintColrLayers */ public: DEFINE_SIZE_STATIC (6); }; -struct BaseGlyphV1List : SortedArray32Of<BaseGlyphV1Record> +struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord> { bool subset (hb_subset_context_t *c) const { @@ -828,11 +1198,11 @@ struct BaseGlyphV1List : SortedArray32Of<BaseGlyphV1Record> bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (SortedArray32Of<BaseGlyphV1Record>::sanitize (c, this)); + return_trace (SortedArray32Of<BaseGlyphPaintRecord>::sanitize (c, this)); } }; -struct LayerV1List : Array32OfOffset32To<Paint> +struct LayerList : Array32OfOffset32To<Paint> { const Paint& get_paint (unsigned i) const { return this+(*this)[i]; } @@ -952,24 +1322,24 @@ struct COLR hb_set_t visited_glyphs; hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices); - const BaseGlyphV1List &baseglyphV1_records = this+baseGlyphsV1List; + const BaseGlyphList &baseglyph_paintrecords = this+baseGlyphList; - for (const BaseGlyphV1Record &baseglyphV1record: baseglyphV1_records.iter ()) + for (const BaseGlyphPaintRecord &baseglyph_paintrecord: baseglyph_paintrecords.iter ()) { - unsigned gid = baseglyphV1record.glyphId; + unsigned gid = baseglyph_paintrecord.glyphId; if (!glyphset->has (gid)) continue; - const Paint &paint = &baseglyphV1_records+baseglyphV1record.paint; + const Paint &paint = &baseglyph_paintrecords+baseglyph_paintrecord.paint; paint.dispatch (&c); } hb_set_union (glyphset, &visited_glyphs); } - const LayerV1List& get_layerV1List () const - { return (this+layersV1); } + const LayerList& get_layerList () const + { return (this+layerList); } - const BaseGlyphV1List& get_baseglyphV1List () const - { return (this+baseGlyphsV1List); } + const BaseGlyphList& get_baseglyphList () const + { return (this+baseGlyphList); } bool sanitize (hb_sanitize_context_t *c) const { @@ -979,8 +1349,10 @@ struct COLR (this+layersZ).sanitize (c, numLayers) && (version == 0 || (COLRV1_ENABLE_SUBSETTING && version == 1 && - baseGlyphsV1List.sanitize (c, this) && - layersV1.sanitize (c, this) && + baseGlyphList.sanitize (c, this) && + layerList.sanitize (c, this) && + clipList.sanitize (c, this) && + varIdxMap.sanitize (c, this) && varStore.sanitize (c, this)))); } @@ -996,19 +1368,17 @@ struct COLR if (unlikely (base_it.len () != layer_it.len ())) return_trace (false); - if (unlikely (!c->extend_min (this))) return_trace (false); this->version = version; numLayers = 0; numBaseGlyphs = base_it.len (); - if (base_it.len () == 0) + if (numBaseGlyphs == 0) { baseGlyphsZ = 0; layersZ = 0; return_trace (true); } - baseGlyphsZ = COLR::min_size; - layersZ = COLR::min_size + numBaseGlyphs * BaseGlyphRecord::min_size; + c->push (); for (const hb_item_type<BaseIterator> _ : + base_it.iter ()) { auto* record = c->embed (_); @@ -1016,10 +1386,14 @@ struct COLR record->firstLayerIdx = numLayers; numLayers += record->numLayers; } + c->add_link (baseGlyphsZ, c->pop_pack ()); + c->push (); for (const hb_item_type<LayerIterator>& _ : + layer_it.iter ()) _.as_array ().copy (c); + c->add_link (layersZ, c->pop_pack ()); + return_trace (true); } @@ -1033,9 +1407,9 @@ struct COLR return record; } - const BaseGlyphV1Record* get_base_glyphV1_record (hb_codepoint_t gid) const + const BaseGlyphPaintRecord* get_base_glyph_paintrecord (hb_codepoint_t gid) const { - const BaseGlyphV1Record* record = &(this+baseGlyphsV1List).bsearch ((unsigned) gid); + const BaseGlyphPaintRecord* record = &(this+baseGlyphList).bsearch ((unsigned) gid); if ((record && (hb_codepoint_t) record->glyphId != gid)) record = nullptr; return record; @@ -1101,23 +1475,26 @@ struct COLR return_trace (false); COLR *colr_prime = c->serializer->start_embed<COLR> (); - bool ret = colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it); + if (unlikely (!c->serializer->extend_min (colr_prime))) return_trace (false); + + if (version == 0) + return_trace (colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)); - if (version == 0) return_trace (ret); auto snap = c->serializer->snapshot (); - if (!c->serializer->allocate_size<void> (3 * HBUINT32::static_size)) return_trace (false); - if (!colr_prime->baseGlyphsV1List.serialize_subset (c, baseGlyphsV1List, this)) + if (!c->serializer->allocate_size<void> (5 * HBUINT32::static_size)) return_trace (false); + if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this)) { if (c->serializer->in_error ()) return_trace (false); //no more COLRv1 glyphs: downgrade to version 0 c->serializer->revert (snap); - colr_prime->version = 0; - return_trace (true); + return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it)); } - if (!colr_prime->layersV1.serialize_subset (c, layersV1, this)) return_trace (false); + if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false); - colr_prime->varStore = 0; + colr_prime->layerList.serialize_subset (c, layerList, this); + colr_prime->clipList.serialize_subset (c, clipList, this); + colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this); //TODO: subset varStore once it's implemented in fonttools return_trace (true); } @@ -1131,8 +1508,10 @@ struct COLR layersZ; /* Offset to Layer Records. */ HBUINT16 numLayers; /* Number of Layer Records. */ // Version-1 additions - Offset32To<BaseGlyphV1List> baseGlyphsV1List; - Offset32To<LayerV1List> layersV1; + Offset32To<BaseGlyphList> baseGlyphList; + Offset32To<LayerList> layerList; + Offset32To<ClipList> clipList; // Offset to ClipList table (may be NULL) + Offset32To<DeltaSetIndexMap> varIdxMap; // Offset to DeltaSetIndexMap table (may be NULL) Offset32To<VariationStore> varStore; public: DEFINE_SIZE_MIN (14); diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh b/thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh index 4124efe0b1..ca85ba6ad6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh @@ -40,7 +40,7 @@ namespace OT { HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) const { c->add_layer_indices (firstLayerIndex, numLayers); - const LayerV1List &paint_offset_lists = c->get_colr_table ()->get_layerV1List (); + const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList (); for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++) { const Paint &paint = hb_addressof (paint_offset_lists) + paint_offset_lists[i]; @@ -57,37 +57,44 @@ HB_INTERNAL void PaintGlyph::closurev1 (hb_colrv1_closure_context_t* c) const HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) const { const COLR *colr_table = c->get_colr_table (); - const BaseGlyphV1Record* baseglyphV1_record = colr_table->get_base_glyphV1_record (gid); - if (!baseglyphV1_record) return; + const BaseGlyphPaintRecord* baseglyph_paintrecord = colr_table->get_base_glyph_paintrecord (gid); + if (!baseglyph_paintrecord) return; c->add_glyph (gid); - const BaseGlyphV1List &baseglyphV1_list = colr_table->get_baseglyphV1List (); - (&baseglyphV1_list+baseglyphV1_record->paint).dispatch (c); + const BaseGlyphList &baseglyph_list = colr_table->get_baseglyphList (); + (&baseglyph_list+baseglyph_paintrecord->paint).dispatch (c); } template <template<typename> class Var> HB_INTERNAL void PaintTransform<Var>::closurev1 (hb_colrv1_closure_context_t* c) const -{ - (this+src).dispatch (c); -} +{ (this+src).dispatch (c); } -template <template<typename> class Var> -HB_INTERNAL void PaintTranslate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const -{ - (this+src).dispatch (c); -} +HB_INTERNAL void PaintTranslate::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } -template <template<typename> class Var> -HB_INTERNAL void PaintRotate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const -{ - (this+src).dispatch (c); -} +HB_INTERNAL void PaintScale::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } -template <template<typename> class Var> -HB_INTERNAL void PaintSkew<Var>::closurev1 (hb_colrv1_closure_context_t* c) const -{ - (this+src).dispatch (c); -} +HB_INTERNAL void PaintScaleAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintScaleUniform::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintScaleUniformAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintRotate::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintRotateAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintSkew::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintSkewAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const { diff --git a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh index ff7b9b2d25..6b419ea1ac 100644 --- a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh @@ -388,7 +388,7 @@ struct glyf protected: HBUINT16 flags; - HBGlyphID glyphIndex; + HBGlyphID16 glyphIndex; public: DEFINE_SIZE_MIN (4); }; @@ -1118,7 +1118,7 @@ struct glyf while (it) { auto item = *(it++); - operation_count += + operation_count = add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count); } diff --git a/thirdparty/harfbuzz/src/hb-ot-head-table.hh b/thirdparty/harfbuzz/src/hb-ot-head-table.hh index ac588e3af6..20991aab2b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-head-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-head-table.hh @@ -72,12 +72,14 @@ struct head UNDERLINE = 1u<<2, OUTLINE = 1u<<3, SHADOW = 1u<<4, - CONDENSED = 1u<<5 + CONDENSED = 1u<<5, + EXPANDED = 1u<<6, }; bool is_bold () const { return macStyle & BOLD; } bool is_italic () const { return macStyle & ITALIC; } bool is_condensed () const { return macStyle & CONDENSED; } + bool is_expanded () const { return macStyle & EXPANDED; } bool sanitize (hb_sanitize_context_t *c) const { diff --git a/thirdparty/harfbuzz/src/hb-ot-kern-table.hh b/thirdparty/harfbuzz/src/hb-ot-kern-table.hh index 3563cab8bd..ffa11bc249 100644 --- a/thirdparty/harfbuzz/src/hb-ot-kern-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-kern-table.hh @@ -134,11 +134,11 @@ struct KernSubTable switch (subtable_type) { case 0: return_trace (c->dispatch (u.format0)); #ifndef HB_NO_AAT_SHAPE - case 1: return_trace (u.header.apple ? c->dispatch (u.format1, hb_forward<Ts> (ds)...) : c->default_return_value ()); + case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ()); #endif case 2: return_trace (c->dispatch (u.format2)); #ifndef HB_NO_AAT_SHAPE - case 3: return_trace (u.header.apple ? c->dispatch (u.format3, hb_forward<Ts> (ds)...) : c->default_return_value ()); + case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ()); #endif default: return_trace (c->default_return_value ()); } @@ -325,9 +325,9 @@ struct kern unsigned int subtable_type = get_type (); TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { - case 0: return_trace (c->dispatch (u.ot, hb_forward<Ts> (ds)...)); + case 0: return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...)); #ifndef HB_NO_AAT_SHAPE - case 1: return_trace (c->dispatch (u.aat, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...)); #endif default: return_trace (c->default_return_value ()); } diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh index 492947751e..eb4c3b46e2 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh @@ -73,7 +73,7 @@ struct BaseCoordFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ FWORD coordinate; /* X or Y value, in design units */ - HBGlyphID referenceGlyph; /* Glyph ID of control glyph */ + HBGlyphID16 referenceGlyph; /* Glyph ID of control glyph */ HBUINT16 coordPoint; /* Index of contour point on the * reference glyph */ public: diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh index 65f499a00d..5d98278bed 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh @@ -89,7 +89,7 @@ static inline void ClassDef_serialize (hb_serialize_context_t *c, static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, const hb_map_t &gid_klass_map, - hb_sorted_vector_t<HBGlyphID> &glyphs, + hb_sorted_vector_t<HBGlyphID16> &glyphs, const hb_set_t &klasses, bool use_class_zero, hb_map_t *klass_map /*INOUT*/); @@ -237,9 +237,9 @@ struct subset_offset_array_t template <typename T> bool operator () (T&& offset) { + auto snap = subset_context->serializer->snapshot (); auto *o = out.serialize_append (subset_context->serializer); if (unlikely (!o)) return false; - auto snap = subset_context->serializer->snapshot (); bool ret = o->serialize_subset (subset_context, offset, base); if (!ret) { @@ -268,9 +268,9 @@ struct subset_offset_array_arg_t template <typename T> bool operator () (T&& offset) { + auto snap = subset_context->serializer->snapshot (); auto *o = out.serialize_append (subset_context->serializer); if (unlikely (!o)) return false; - auto snap = subset_context->serializer->snapshot (); bool ret = o->serialize_subset (subset_context, offset, base, arg); if (!ret) { @@ -346,6 +346,43 @@ struct } HB_FUNCOBJ (subset_record_array); + +template<typename OutputArray> +struct serialize_math_record_array_t +{ + serialize_math_record_array_t (hb_serialize_context_t *serialize_context_, + OutputArray& out_, + const void *base_) : serialize_context (serialize_context_), + out (out_), base (base_) {} + + template <typename T> + bool operator () (T&& record) + { + if (!serialize_context->copy (record, base)) return false; + out.len++; + return true; + } + + private: + hb_serialize_context_t *serialize_context; + OutputArray &out; + const void *base; +}; + +/* + * Helper to serialize an array of MATH records. + */ +struct +{ + template<typename OutputArray> + serialize_math_record_array_t<OutputArray> + operator () (hb_serialize_context_t *serialize_context, OutputArray& out, + const void *base) const + { return serialize_math_record_array_t<OutputArray> (serialize_context, out, base); } + +} +HB_FUNCOBJ (serialize_math_record_array); + /* * * OpenType Layout Common Table Formats @@ -508,8 +545,8 @@ struct RangeRecord bool collect_coverage (set_t *glyphs) const { return glyphs->add_range (first, last); } - HBGlyphID first; /* First GlyphID in the range */ - HBGlyphID last; /* Last GlyphID in the range */ + HBGlyphID16 first; /* First GlyphID in the range */ + HBGlyphID16 last; /* Last GlyphID in the range */ HBUINT16 value; /* Value */ public: DEFINE_SIZE_STATIC (6); @@ -1249,7 +1286,7 @@ struct Lookup TRACE_DISPATCH (this, lookup_type); unsigned int count = get_subtable_count (); for (unsigned int i = 0; i < count; i++) { - typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, hb_forward<Ts> (ds)...); + typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, std::forward<Ts> (ds)...); if (c->stop_sublookup_iteration (r)) return_trace (r); } @@ -1299,7 +1336,7 @@ struct Lookup outMarkFilteringSet = markFilteringSet; } - return_trace (true); + return_trace (out->subTable.len); } template <typename TSubTable> @@ -1454,7 +1491,7 @@ struct CoverageFormat1 protected: HBUINT16 coverageFormat; /* Format identifier--format = 1 */ - SortedArray16Of<HBGlyphID> + SortedArray16Of<HBGlyphID16> glyphArray; /* Array of GlyphIDs--in numerical order */ public: DEFINE_SIZE_ARRAY (4, glyphArray); @@ -1832,7 +1869,7 @@ Coverage_serialize (hb_serialize_context_t *c, static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, const hb_map_t &gid_klass_map, - hb_sorted_vector_t<HBGlyphID> &glyphs, + hb_sorted_vector_t<HBGlyphID16> &glyphs, const hb_set_t &klasses, bool use_class_zero, hb_map_t *klass_map /*INOUT*/) @@ -1859,7 +1896,7 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, auto it = + glyphs.iter () - | hb_map_retains_sorting ([&] (const HBGlyphID& gid) -> hb_pair_t<hb_codepoint_t, unsigned> + | hb_map_retains_sorting ([&] (const HBGlyphID16& gid) -> hb_pair_t<hb_codepoint_t, unsigned> { unsigned new_klass = klass_map->get (gid_klass_map[gid]); return hb_pair ((hb_codepoint_t)gid, new_klass); @@ -1926,7 +1963,7 @@ struct ClassDefFormat1 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; - hb_sorted_vector_t<HBGlyphID> glyphs; + hb_sorted_vector_t<HBGlyphID16> glyphs; hb_set_t orig_klasses; hb_map_t gid_org_klass_map; @@ -2044,9 +2081,25 @@ struct ClassDefFormat1 intersect_glyphs->add (startGlyph + i); } + void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const + { + if (glyphs->is_empty ()) return; + hb_codepoint_t end_glyph = startGlyph + classValue.len - 1; + if (glyphs->get_min () < startGlyph || + glyphs->get_max () > end_glyph) + intersect_classes->add (0); + + for (const auto& _ : + hb_enumerate (classValue)) + { + hb_codepoint_t g = startGlyph + _.first; + if (glyphs->has (g)) + intersect_classes->add (_.second); + } + } + protected: HBUINT16 classFormat; /* Format identifier--format = 1 */ - HBGlyphID startGlyph; /* First GlyphID of the classValueArray */ + HBGlyphID16 startGlyph; /* First GlyphID of the classValueArray */ Array16Of<HBUINT16> classValue; /* Array of Class Values--one per GlyphID */ public: @@ -2128,7 +2181,7 @@ struct ClassDefFormat2 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; - hb_sorted_vector_t<HBGlyphID> glyphs; + hb_sorted_vector_t<HBGlyphID16> glyphs; hb_set_t orig_klasses; hb_map_t gid_org_klass_map; @@ -2277,6 +2330,31 @@ struct ClassDefFormat2 } } + void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const + { + if (glyphs->is_empty ()) return; + + unsigned count = rangeRecord.len; + hb_codepoint_t g = HB_SET_VALUE_INVALID; + for (unsigned int i = 0; i < count; i++) + { + if (!hb_set_next (glyphs, &g)) + break; + if (g < rangeRecord[i].first) + { + intersect_classes->add (0); + break; + } + g = rangeRecord[i].last; + } + if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g)) + intersect_classes->add (0); + + for (const RangeRecord& record : rangeRecord.iter ()) + if (record.intersects (glyphs)) + intersect_classes->add (record.value); + } + protected: HBUINT16 classFormat; /* Format identifier--format = 2 */ SortedArray16Of<RangeRecord> @@ -2429,6 +2507,16 @@ struct ClassDef } } + void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const + { + switch (u.format) { + case 1: return u.format1.intersected_classes (glyphs, intersect_classes); + case 2: return u.format2.intersected_classes (glyphs, intersect_classes); + default:return; + } + } + + protected: union { HBUINT16 format; /* Format identifier */ @@ -2543,7 +2631,7 @@ struct VarRegionList public: HBUINT16 axisCount; - HBUINT16 regionCount; + HBUINT15 regionCount; protected: UnsizedArrayOf<VarRegionAxis> axesZ; @@ -2947,7 +3035,7 @@ struct Condition TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh index 31a4a3e84c..aea644f3e1 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh @@ -84,7 +84,7 @@ struct AttachList bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); @@ -248,9 +248,9 @@ struct CaretValue TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...)); - case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -371,7 +371,7 @@ struct LigCaretList bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh index 1e305518f5..a8fb5c7acb 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh @@ -1050,8 +1050,8 @@ struct SinglePos TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -1144,7 +1144,7 @@ struct PairValueRecord } protected: - HBGlyphID secondGlyph; /* GlyphID of second glyph in the + HBGlyphID16 secondGlyph; /* GlyphID of second glyph in the * pair--first glyph is listed in the * Coverage table */ ValueRecord values; /* Positioning data for the first glyph @@ -1220,9 +1220,9 @@ struct PairSet record_size); if (record) { - /* Note the intentional use of "|" instead of short-circuit "||". */ - if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) | - valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos])) + bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); + bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); + if (applied_first || applied_second) buffer->unsafe_to_break (buffer->idx, pos + 1); if (len2) pos++; @@ -1386,9 +1386,9 @@ struct PairPosFormat1 | hb_filter (glyphset, hb_first) | hb_filter ([this, c, out] (const Offset16To<PairSet>& _) { + auto snap = c->serializer->snapshot (); auto *o = out->pairSet.serialize_append (c->serializer); if (unlikely (!o)) return false; - auto snap = c->serializer->snapshot (); bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat); if (!ret) { @@ -1560,9 +1560,9 @@ struct PairPosFormat2 if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false); const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; - /* Note the intentional use of "|" instead of short-circuit "||". */ - if (valueFormat1.apply_value (c, this, v, buffer->cur_pos()) | - valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx])) + bool applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos()); + bool applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); + if (applied_first || applied_second) buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1); buffer->idx = skippy_iter.idx; @@ -1702,8 +1702,8 @@ struct PairPos TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -1959,7 +1959,7 @@ struct CursivePos TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -2194,7 +2194,7 @@ struct MarkBasePos TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -2434,7 +2434,7 @@ struct MarkLigPos TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -2653,7 +2653,7 @@ struct MarkMarkPos TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -2704,15 +2704,15 @@ struct PosLookupSubTable { TRACE_DISPATCH (this, lookup_type); switch (lookup_type) { - case Single: return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...)); - case Pair: return_trace (u.pair.dispatch (c, hb_forward<Ts> (ds)...)); - case Cursive: return_trace (u.cursive.dispatch (c, hb_forward<Ts> (ds)...)); - case MarkBase: return_trace (u.markBase.dispatch (c, hb_forward<Ts> (ds)...)); - case MarkLig: return_trace (u.markLig.dispatch (c, hb_forward<Ts> (ds)...)); - case MarkMark: return_trace (u.markMark.dispatch (c, hb_forward<Ts> (ds)...)); - case Context: return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...)); - case ChainContext: return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...)); - case Extension: return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...)); + case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...)); + case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...)); + case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...)); + case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...)); + case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...)); + case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...)); + case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...)); + case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...)); + case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...)); default: return_trace (c->default_return_value ()); } } @@ -2800,7 +2800,7 @@ struct PosLookup : Lookup template <typename context_t, typename ...Ts> typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const - { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); } + { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); } bool subset (hb_subset_context_t *c) const { return Lookup::subset<SubTable> (c); } diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh index 393ada1351..710c5fbbb9 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh @@ -225,7 +225,7 @@ struct SingleSubstFormat2 + hb_zip (this+coverage, substitute) | hb_filter (glyphset, hb_first) | hb_filter (glyphset, hb_second) - | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t + | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t { return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) ; @@ -245,7 +245,7 @@ struct SingleSubstFormat2 Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - Array16Of<HBGlyphID> + Array16Of<HBGlyphID16> substitute; /* Array of substitute * GlyphIDs--ordered by Coverage Index */ public: @@ -290,8 +290,8 @@ struct SingleSubst TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -391,7 +391,7 @@ struct Sequence } protected: - Array16Of<HBGlyphID> + Array16Of<HBGlyphID16> substitute; /* String of GlyphIDs to substitute */ public: DEFINE_SIZE_ARRAY (2, substitute); @@ -443,9 +443,9 @@ struct MultipleSubstFormat1 } bool serialize (hb_serialize_context_t *c, - hb_sorted_array_t<const HBGlyphID> glyphs, + hb_sorted_array_t<const HBGlyphID16> glyphs, hb_array_t<const unsigned int> substitute_len_list, - hb_array_t<const HBGlyphID> substitute_glyphs_list) + hb_array_t<const HBGlyphID16> substitute_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); @@ -504,9 +504,9 @@ struct MultipleSubstFormat1 struct MultipleSubst { bool serialize (hb_serialize_context_t *c, - hb_sorted_array_t<const HBGlyphID> glyphs, + hb_sorted_array_t<const HBGlyphID16> glyphs, hb_array_t<const unsigned int> substitute_len_list, - hb_array_t<const HBGlyphID> substitute_glyphs_list) + hb_array_t<const HBGlyphID16> substitute_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); @@ -524,7 +524,7 @@ struct MultipleSubst TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -624,7 +624,7 @@ struct AlternateSet } protected: - Array16Of<HBGlyphID> + Array16Of<HBGlyphID16> alternates; /* Array of alternate GlyphIDs--in * arbitrary order */ public: @@ -686,9 +686,9 @@ struct AlternateSubstFormat1 } bool serialize (hb_serialize_context_t *c, - hb_sorted_array_t<const HBGlyphID> glyphs, + hb_sorted_array_t<const HBGlyphID16> glyphs, hb_array_t<const unsigned int> alternate_len_list, - hb_array_t<const HBGlyphID> alternate_glyphs_list) + hb_array_t<const HBGlyphID16> alternate_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); @@ -747,9 +747,9 @@ struct AlternateSubstFormat1 struct AlternateSubst { bool serialize (hb_serialize_context_t *c, - hb_sorted_array_t<const HBGlyphID> glyphs, + hb_sorted_array_t<const HBGlyphID16> glyphs, hb_array_t<const unsigned int> alternate_len_list, - hb_array_t<const HBGlyphID> alternate_glyphs_list) + hb_array_t<const HBGlyphID16> alternate_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); @@ -767,7 +767,7 @@ struct AlternateSubst TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -861,13 +861,15 @@ struct Ligature return_trace (true); } - bool subset (hb_subset_context_t *c) const + bool subset (hb_subset_context_t *c, unsigned coverage_idx) const { TRACE_SUBSET (this); const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false); + // Ensure Coverage table is always packed after this. + c->serializer->add_virtual_link (coverage_idx); auto it = + hb_iter (component) @@ -888,8 +890,8 @@ struct Ligature } protected: - HBGlyphID ligGlyph; /* GlyphID of ligature to substitute */ - HeadlessArrayOf<HBGlyphID> + HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */ + HeadlessArrayOf<HBGlyphID16> component; /* Array of component GlyphIDs--start * with the second component--ordered * in writing direction */ @@ -949,9 +951,9 @@ struct LigatureSet } bool serialize (hb_serialize_context_t *c, - hb_array_t<const HBGlyphID> ligatures, + hb_array_t<const HBGlyphID16> ligatures, hb_array_t<const unsigned int> component_count_list, - hb_array_t<const HBGlyphID> &component_list /* Starting from second for each ligature */) + hb_array_t<const HBGlyphID16> &component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); @@ -968,16 +970,21 @@ struct LigatureSet return_trace (true); } - bool subset (hb_subset_context_t *c) const + bool subset (hb_subset_context_t *c, unsigned coverage_idx) const { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + hb_iter (ligature) - | hb_filter (subset_offset_array (c, out->ligature, this)) + | hb_filter (subset_offset_array (c, out->ligature, this, coverage_idx)) | hb_drain ; + + if (bool (out->ligature)) + // Ensure Coverage table is always packed after this. + c->serializer->add_virtual_link (coverage_idx); + return_trace (bool (out->ligature)); } @@ -1059,11 +1066,11 @@ struct LigatureSubstFormat1 } bool serialize (hb_serialize_context_t *c, - hb_sorted_array_t<const HBGlyphID> first_glyphs, + hb_sorted_array_t<const HBGlyphID16> first_glyphs, hb_array_t<const unsigned int> ligature_per_first_glyph_count_list, - hb_array_t<const HBGlyphID> ligatures_list, + hb_array_t<const HBGlyphID16> ligatures_list, hb_array_t<const unsigned int> component_count_list, - hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */) + hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); @@ -1092,15 +1099,38 @@ struct LigatureSubstFormat1 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); out->format = format; - hb_sorted_vector_t<hb_codepoint_t> new_coverage; - + hb_zip (this+coverage, ligatureSet) + // Due to a bug in some older versions of windows 7 the Coverage table must be + // packed after the LigatureSet and Ligature tables, so serialize Coverage first + // which places it last in the packed order. + hb_set_t new_coverage; + + hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this))) | hb_filter (glyphset, hb_first) - | hb_filter (subset_offset_array (c, out->ligatureSet, this), hb_second) + | hb_filter ([&] (const LigatureSet& _) { + return _.intersects (&glyphset); + }, hb_second) | hb_map (hb_first) - | hb_map (glyph_map) - | hb_sink (new_coverage) + | hb_sink (new_coverage); + + if (!c->serializer->push<Coverage> () + ->serialize (c->serializer, + + new_coverage.iter () | hb_map_retains_sorting (glyph_map))) + { + c->serializer->pop_discard (); + return_trace (false); + } + + unsigned coverage_idx = c->serializer->pop_pack (); + c->serializer->add_link (out->coverage, coverage_idx); + + + hb_zip (this+coverage, ligatureSet) + | hb_filter (new_coverage, hb_first) + | hb_map (hb_second) + // to ensure that the repacker always orders the coverage table after the LigatureSet + // and LigatureSubtable's they will be linked to the Coverage table via a virtual link + // the coverage table object idx is passed down to facilitate this. + | hb_apply (subset_offset_array (c, out->ligatureSet, this, coverage_idx)) ; - out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); + return_trace (bool (new_coverage)); } @@ -1125,11 +1155,11 @@ struct LigatureSubstFormat1 struct LigatureSubst { bool serialize (hb_serialize_context_t *c, - hb_sorted_array_t<const HBGlyphID> first_glyphs, + hb_sorted_array_t<const HBGlyphID16> first_glyphs, hb_array_t<const unsigned int> ligature_per_first_glyph_count_list, - hb_array_t<const HBGlyphID> ligatures_list, + hb_array_t<const HBGlyphID16> ligatures_list, hb_array_t<const unsigned int> component_count_list, - hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */) + hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); @@ -1152,7 +1182,7 @@ struct LigatureSubst TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -1208,7 +1238,7 @@ struct ReverseChainSingleSubstFormat1 if (!intersects (c->glyphs)) return; const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); - const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead); + const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); + hb_zip (this+coverage, substitute) | hb_filter (c->parent_active_glyphs (), hb_first) @@ -1234,7 +1264,7 @@ struct ReverseChainSingleSubstFormat1 for (unsigned int i = 0; i < count; i++) if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return; - const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead); + const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); count = substitute.len; c->output->add_array (substitute.arrayZ, substitute.len); } @@ -1254,7 +1284,7 @@ struct ReverseChainSingleSubstFormat1 if (likely (index == NOT_COVERED)) return_trace (false); const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); - const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead); + const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); if (unlikely (index >= substitute.len)) return_trace (false); @@ -1317,7 +1347,7 @@ struct ReverseChainSingleSubstFormat1 if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false); if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false); - auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID>> (); + auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID16>> (); auto substitutes = + coverage_subst_iter | hb_map (hb_second) @@ -1342,13 +1372,13 @@ struct ReverseChainSingleSubstFormat1 const hb_map_t &glyph_map = *c->plan->glyph_map; const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); - const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead); + const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); auto it = + hb_zip (this+coverage, substitute) | hb_filter (glyphset, hb_first) | hb_filter (glyphset, hb_second) - | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t + | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t { return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) ; @@ -1363,7 +1393,7 @@ struct ReverseChainSingleSubstFormat1 const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); if (!lookahead.sanitize (c, this)) return_trace (false); - const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead); + const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); return_trace (substitute.sanitize (c)); } @@ -1380,7 +1410,7 @@ struct ReverseChainSingleSubstFormat1 lookaheadX; /* Array of coverage tables * in lookahead sequence, in glyph * sequence order */ - Array16Of<HBGlyphID> + Array16Of<HBGlyphID16> substituteX; /* Array of substitute * GlyphIDs--ordered by Coverage Index */ public: @@ -1395,7 +1425,7 @@ struct ReverseChainSingleSubst TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -1434,14 +1464,14 @@ struct SubstLookupSubTable { TRACE_DISPATCH (this, lookup_type); switch (lookup_type) { - case Single: return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...)); - case Multiple: return_trace (u.multiple.dispatch (c, hb_forward<Ts> (ds)...)); - case Alternate: return_trace (u.alternate.dispatch (c, hb_forward<Ts> (ds)...)); - case Ligature: return_trace (u.ligature.dispatch (c, hb_forward<Ts> (ds)...)); - case Context: return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...)); - case ChainContext: return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...)); - case Extension: return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...)); - case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, hb_forward<Ts> (ds)...)); + case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...)); + case Multiple: return_trace (u.multiple.dispatch (c, std::forward<Ts> (ds)...)); + case Alternate: return_trace (u.alternate.dispatch (c, std::forward<Ts> (ds)...)); + case Ligature: return_trace (u.ligature.dispatch (c, std::forward<Ts> (ds)...)); + case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...)); + case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...)); + case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...)); + case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, std::forward<Ts> (ds)...)); default: return_trace (c->default_return_value ()); } } @@ -1561,8 +1591,8 @@ struct SubstLookup : Lookup bool serialize_single (hb_serialize_context_t *c, uint32_t lookup_props, - hb_sorted_array_t<const HBGlyphID> glyphs, - hb_array_t<const HBGlyphID> substitutes) + hb_sorted_array_t<const HBGlyphID16> glyphs, + hb_array_t<const HBGlyphID16> substitutes) { TRACE_SERIALIZE (this); if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false); @@ -1577,9 +1607,9 @@ struct SubstLookup : Lookup bool serialize_multiple (hb_serialize_context_t *c, uint32_t lookup_props, - hb_sorted_array_t<const HBGlyphID> glyphs, + hb_sorted_array_t<const HBGlyphID16> glyphs, hb_array_t<const unsigned int> substitute_len_list, - hb_array_t<const HBGlyphID> substitute_glyphs_list) + hb_array_t<const HBGlyphID16> substitute_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false); @@ -1598,9 +1628,9 @@ struct SubstLookup : Lookup bool serialize_alternate (hb_serialize_context_t *c, uint32_t lookup_props, - hb_sorted_array_t<const HBGlyphID> glyphs, + hb_sorted_array_t<const HBGlyphID16> glyphs, hb_array_t<const unsigned int> alternate_len_list, - hb_array_t<const HBGlyphID> alternate_glyphs_list) + hb_array_t<const HBGlyphID16> alternate_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false); @@ -1620,11 +1650,11 @@ struct SubstLookup : Lookup bool serialize_ligature (hb_serialize_context_t *c, uint32_t lookup_props, - hb_sorted_array_t<const HBGlyphID> first_glyphs, + hb_sorted_array_t<const HBGlyphID16> first_glyphs, hb_array_t<const unsigned int> ligature_per_first_glyph_count_list, - hb_array_t<const HBGlyphID> ligatures_list, + hb_array_t<const HBGlyphID16> ligatures_list, hb_array_t<const unsigned int> component_count_list, - hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */) + hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false); @@ -1667,7 +1697,7 @@ struct SubstLookup : Lookup template <typename context_t, typename ...Ts> typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const - { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); } + { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); } bool subset (hb_subset_context_t *c) const { return Lookup::subset<SubTable> (c); } diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh index 626abc5577..c0ed2bcc03 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh @@ -1210,15 +1210,14 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c, struct LookupRecord { - LookupRecord* copy (hb_serialize_context_t *c, - const hb_map_t *lookup_map) const + bool serialize (hb_serialize_context_t *c, + const hb_map_t *lookup_map) const { TRACE_SERIALIZE (this); auto *out = c->embed (*this); - if (unlikely (!out)) return_trace (nullptr); + if (unlikely (!out)) return_trace (false); - out->lookupListIndex = hb_map_get (lookup_map, lookupListIndex); - return_trace (out); + return_trace (c->check_assign (out->lookupListIndex, lookup_map->get (lookupListIndex), HB_SERIALIZE_ERROR_INT_OVERFLOW)); } bool sanitize (hb_sanitize_context_t *c) const @@ -1235,6 +1234,24 @@ struct LookupRecord DEFINE_SIZE_STATIC (4); }; +static unsigned serialize_lookuprecord_array (hb_serialize_context_t *c, + const hb_array_t<const LookupRecord> lookupRecords, + const hb_map_t *lookup_map) +{ + unsigned count = 0; + for (const LookupRecord& r : lookupRecords) + { + if (!lookup_map->has (r.lookupListIndex)) + continue; + + if (!r.serialize (c, lookup_map)) + return 0; + + count++; + } + return count; +} + enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 }; static void context_closure_recurse_lookups (hb_closure_context_t *c, @@ -1605,8 +1622,6 @@ struct Rule if (unlikely (!c->extend_min (out))) return_trace (false); out->inputCount = inputCount; - out->lookupCount = lookupCount; - const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1); for (const auto org : input) { @@ -1617,17 +1632,9 @@ struct Rule const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (inputZ.as_array ((inputCount ? inputCount - 1 : 0))); - for (unsigned i = 0; i < (unsigned) lookupCount; i++) - { - if (!lookup_map->has (lookupRecord[i].lookupListIndex)) - { - out->lookupCount--; - continue; - } - c->copy (lookupRecord[i], lookup_map); - } - return_trace (true); + unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (lookupCount), lookup_map); + return_trace (c->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); } bool subset (hb_subset_context_t *c, @@ -1752,10 +1759,10 @@ struct RuleSet for (const Offset16To<Rule>& _ : rule) { if (!_) continue; + auto o_snap = c->serializer->snapshot (); auto *o = out->rule.serialize_append (c->serializer); if (unlikely (!o)) continue; - auto o_snap = c->serializer->snapshot (); if (!o->serialize_subset (c, _, this, lookup_map, klass_map)) { out->rule.pop (); @@ -1943,12 +1950,20 @@ struct ContextFormat2 &class_def }; + hb_set_t retained_coverage_glyphs; + (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs); + + hb_set_t coverage_glyph_classes; + class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes); + + return + hb_iter (ruleSet) | hb_map (hb_add (this)) | hb_enumerate | hb_map ([&] (const hb_pair_t<unsigned, const RuleSet &> p) { return class_def.intersects_class (glyphs, p.first) && + coverage_glyph_classes.has (p.first) && p.second.intersects (glyphs, lookup_context); }) | hb_any ; @@ -2069,9 +2084,16 @@ struct ContextFormat2 hb_map_t klass_map; out->classDef.serialize_subset (c, classDef, this, &klass_map); + const hb_set_t* glyphset = c->plan->glyphset_gsub (); + hb_set_t retained_coverage_glyphs; + (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs); + + hb_set_t coverage_glyph_classes; + (this+classDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes); + const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; bool ret = true; - int non_zero_index = 0, index = 0; + int non_zero_index = -1, index = 0; for (const auto& _ : + hb_enumerate (ruleSet) | hb_filter (klass_map, hb_first)) { @@ -2082,13 +2104,14 @@ struct ContextFormat2 break; } - if (o->serialize_subset (c, _.second, this, lookup_map, &klass_map)) + if (coverage_glyph_classes.has (_.first) && + o->serialize_subset (c, _.second, this, lookup_map, &klass_map)) non_zero_index = index; index++; } - if (!ret) return_trace (ret); + if (!ret || non_zero_index == -1) return_trace (false); //prune empty trailing ruleSets --index; @@ -2226,7 +2249,6 @@ struct ContextFormat3 out->format = format; out->glyphCount = glyphCount; - out->lookupCount = lookupCount; auto coverages = coverageZ.as_array (glyphCount); @@ -2238,19 +2260,12 @@ struct ContextFormat3 if (!o->serialize_subset (c, offset, this)) return_trace (false); } - const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount)); + const UnsizedArrayOf<LookupRecord>& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount)); const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; - for (unsigned i = 0; i < (unsigned) lookupCount; i++) - { - if (!lookup_map->has (lookupRecord[i].lookupListIndex)) - { - out->lookupCount--; - continue; - } - c->serializer->copy (lookupRecord[i], lookup_map); - } - return_trace (true); + + unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (lookupCount), lookup_map); + return_trace (c->serializer->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); } bool sanitize (hb_sanitize_context_t *c) const @@ -2289,9 +2304,9 @@ struct Context TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...)); - case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -2539,15 +2554,15 @@ struct ChainRule c->copy ((HBUINT16) g); } - ChainRule* copy (hb_serialize_context_t *c, - const hb_map_t *lookup_map, - const hb_map_t *backtrack_map, - const hb_map_t *input_map = nullptr, - const hb_map_t *lookahead_map = nullptr) const + bool serialize (hb_serialize_context_t *c, + const hb_map_t *lookup_map, + const hb_map_t *backtrack_map, + const hb_map_t *input_map = nullptr, + const hb_map_t *lookahead_map = nullptr) const { TRACE_SERIALIZE (this); auto *out = c->start_embed (this); - if (unlikely (!out)) return_trace (nullptr); + if (unlikely (!out)) return_trace (false); const hb_map_t *mapping = backtrack_map; serialize_array (c, backtrack.len, + backtrack.iter () @@ -2566,19 +2581,10 @@ struct ChainRule const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead); HBUINT16* lookupCount = c->embed (&(lookupRecord.len)); - if (!lookupCount) return_trace (nullptr); + if (!lookupCount) return_trace (false); - for (unsigned i = 0; i < lookupRecord.len; i++) - { - if (!lookup_map->has (lookupRecord[i].lookupListIndex)) - { - (*lookupCount)--; - continue; - } - if (!c->copy (lookupRecord[i], lookup_map)) return_trace (nullptr); - } - - return_trace (out); + unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (), lookup_map); + return_trace (c->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); } bool subset (hb_subset_context_t *c, @@ -2600,7 +2606,7 @@ struct ChainRule !hb_all (lookahead, glyphset)) return_trace (false); - copy (c->serializer, lookup_map, c->plan->glyph_map); + serialize (c->serializer, lookup_map, c->plan->glyph_map); } else { @@ -2609,7 +2615,7 @@ struct ChainRule !hb_all (lookahead, lookahead_map)) return_trace (false); - copy (c->serializer, lookup_map, backtrack_map, input_map, lookahead_map); + serialize (c->serializer, lookup_map, backtrack_map, input_map, lookahead_map); } return_trace (true); @@ -2724,10 +2730,10 @@ struct ChainRuleSet for (const Offset16To<ChainRule>& _ : rule) { if (!_) continue; + auto o_snap = c->serializer->snapshot (); auto *o = out->rule.serialize_append (c->serializer); if (unlikely (!o)) continue; - auto o_snap = c->serializer->snapshot (); if (!o->serialize_subset (c, _, this, lookup_map, backtrack_klass_map, @@ -2920,12 +2926,19 @@ struct ChainContextFormat2 &lookahead_class_def} }; + hb_set_t retained_coverage_glyphs; + (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs); + + hb_set_t coverage_glyph_classes; + input_class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes); + return + hb_iter (ruleSet) | hb_map (hb_add (this)) | hb_enumerate | hb_map ([&] (const hb_pair_t<unsigned, const ChainRuleSet &> p) { return input_class_def.intersects_class (glyphs, p.first) && + coverage_glyph_classes.has (p.first) && p.second.intersects (glyphs, lookup_context); }) | hb_any ; @@ -3080,13 +3093,19 @@ struct ChainContextFormat2 lookahead_klass_map))) return_trace (false); + const hb_set_t* glyphset = c->plan->glyphset_gsub (); + hb_set_t retained_coverage_glyphs; + (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs); + + hb_set_t coverage_glyph_classes; + (this+inputClassDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes); + int non_zero_index = -1, index = 0; bool ret = true; const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; auto last_non_zero = c->serializer->snapshot (); - for (const Offset16To<ChainRuleSet>& _ : + hb_enumerate (ruleSet) - | hb_filter (input_klass_map, hb_first) - | hb_map (hb_second)) + for (const auto& _ : + hb_enumerate (ruleSet) + | hb_filter (input_klass_map, hb_first)) { auto *o = out->ruleSet.serialize_append (c->serializer); if (unlikely (!o)) @@ -3094,7 +3113,8 @@ struct ChainContextFormat2 ret = false; break; } - if (o->serialize_subset (c, _, this, + if (coverage_glyph_classes.has (_.first) && + o->serialize_subset (c, _.second, this, lookup_map, &backtrack_klass_map, &input_klass_map, @@ -3107,7 +3127,7 @@ struct ChainContextFormat2 index++; } - if (!ret) return_trace (ret); + if (!ret || non_zero_index == -1) return_trace (false); // prune empty trailing ruleSets if (index > non_zero_index) { @@ -3318,22 +3338,12 @@ struct ChainContextFormat3 const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead); const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; - hb_set_t lookup_indices; - for (unsigned i = 0; i < (unsigned) lookupRecord.len; i++) - if (lookup_map->has (lookupRecord[i].lookupListIndex)) - lookup_indices.add (i); - HBUINT16 lookupCount; - lookupCount = lookup_indices.get_population (); - if (!c->serializer->copy (lookupCount)) return_trace (false); + HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookupRecord.len); + if (!lookupCount) return_trace (false); - for (unsigned i : lookup_indices.iter ()) - { - if (!c->serializer->copy (lookupRecord[i], lookup_map)) - return_trace (false); - } - - return_trace (true); + unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (), lookup_map); + return_trace (c->serializer->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); } bool sanitize (hb_sanitize_context_t *c) const @@ -3378,9 +3388,9 @@ struct ChainContext TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); - case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...)); - case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -3409,7 +3419,7 @@ struct ExtensionFormat1 { TRACE_DISPATCH (this, format); if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ()); - return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type (), hb_forward<Ts> (ds)...)); + return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type (), std::forward<Ts> (ds)...)); } void collect_variation_indices (hb_collect_variation_indices_context_t *c) const @@ -3489,7 +3499,7 @@ struct Extension TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); switch (u.format) { - case 1: return_trace (u.format1.dispatch (c, hb_forward<Ts> (ds)...)); + case 1: return_trace (u.format1.dispatch (c, std::forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } @@ -3678,57 +3688,72 @@ struct GSUBGPOS const hb_set_t *feature_indices, hb_map_t *duplicate_feature_map /* OUT */) const { + if (feature_indices->is_empty ()) return; + hb_hashmap_t<hb_tag_t, hb_set_t *, (unsigned)-1, nullptr> unique_features; //find out duplicate features after subset - unsigned prev = 0xFFFFu; for (unsigned i : feature_indices->iter ()) { - if (prev == 0xFFFFu) + hb_tag_t t = get_feature_tag (i); + if (t == unique_features.INVALID_KEY) continue; + if (!unique_features.has (t)) { + hb_set_t* indices = hb_set_create (); + if (unlikely (indices == hb_set_get_empty () || + !unique_features.set (t, indices))) + { + hb_set_destroy (indices); + for (auto _ : unique_features.iter ()) + hb_set_destroy (_.second); + return; + } + if (unique_features.get (t)) + unique_features.get (t)->add (i); duplicate_feature_map->set (i, i); - prev = i; continue; } - hb_tag_t t = get_feature_tag (i); - hb_tag_t prev_t = get_feature_tag (prev); - if (t != prev_t) + bool found = false; + + hb_set_t* same_tag_features = unique_features.get (t); + for (unsigned other_f_index : same_tag_features->iter ()) { - duplicate_feature_map->set (i, i); - prev = i; - continue; - } + const Feature& f = get_feature (i); + const Feature& other_f = get_feature (other_f_index); - const Feature& f = get_feature (i); - const Feature& prev_f = get_feature (prev); + auto f_iter = + + hb_iter (f.lookupIndex) + | hb_filter (lookup_indices) + ; - auto f_iter = - + hb_iter (f.lookupIndex) - | hb_filter (lookup_indices) - ; + auto other_f_iter = + + hb_iter (other_f.lookupIndex) + | hb_filter (lookup_indices) + ; - auto prev_iter = - + hb_iter (prev_f.lookupIndex) - | hb_filter (lookup_indices) - ; + bool is_equal = true; + for (; f_iter && other_f_iter; f_iter++, other_f_iter++) + { + unsigned a = *f_iter; + unsigned b = *other_f_iter; + if (a != b) { is_equal = false; break; } + } - if (f_iter.len () != prev_iter.len ()) - { - duplicate_feature_map->set (i, i); - prev = i; - continue; - } + if (is_equal == false || f_iter || other_f_iter) continue; - bool is_equal = true; - for (auto _ : + hb_zip (f_iter, prev_iter)) - if (_.first != _.second) { is_equal = false; break; } + found = true; + duplicate_feature_map->set (i, other_f_index); + break; + } - if (is_equal == true) duplicate_feature_map->set (i, prev); - else + if (found == false) { + same_tag_features->add (i); duplicate_feature_map->set (i, i); - prev = i; } } + + for (auto _ : unique_features.iter ()) + hb_set_destroy (_.second); } void prune_features (const hb_map_t *lookup_indices, /* IN */ diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-jstf-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-jstf-table.hh index 3b2293dff0..a1c125b11b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-jstf-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-jstf-table.hh @@ -136,7 +136,7 @@ struct JstfLangSys : List16OfOffset16To<JstfPriority> * ExtenderGlyphs -- Extender Glyph Table */ -typedef SortedArray16Of<HBGlyphID> ExtenderGlyphs; +typedef SortedArray16Of<HBGlyphID16> ExtenderGlyphs; /* diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc index 0454af2063..fbdedd0e20 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.cc +++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc @@ -613,7 +613,7 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face, * hb_ot_layout_table_find_feature: * @face: #hb_face_t to work upon * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS - * @feature_tag: The #hb_tag_t og the requested feature tag + * @feature_tag: The #hb_tag_t of the requested feature tag * @feature_index: (out): The index of the requested feature * * Fetches the index for a given feature tag in the specified face's GSUB table @@ -688,8 +688,8 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face, * * Return value: %true if the language tag is found, %false otherwise * - * Since: ?? - * Deprecated: ?? + * Since: 0.6.0 + * Deprecated: 2.0.0 **/ hb_bool_t hb_ot_layout_script_find_language (hb_face_t *face, @@ -717,10 +717,14 @@ hb_ot_layout_script_find_language (hb_face_t *face, * @language_tags: The array of language tags * @language_index: (out): The index of the requested language * - * Fetches the index of a given language tag in the specified face's GSUB table - * or GPOS table, underneath the specified script index. + * Fetches the index of the first language tag fom @language_tags that is present + * in the specified face's GSUB or GPOS table, underneath the specified script + * index. * - * Return value: %true if the language tag is found, %false otherwise + * If none of the given language tags is found, %false is returned and + * @language_index is set to the default language index. + * + * Return value: %true if one of the given language tags is found, %false otherwise * * Since: 2.0.0 **/ @@ -746,7 +750,8 @@ hb_ot_layout_script_select_language (hb_face_t *face, if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index)) return false; - if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX; + if (language_index) + *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX; return false; } @@ -1013,24 +1018,15 @@ struct hb_collect_features_context_t } has_feature_filter = true; + hb_set_t features_set; for (; *features; features++) - { - hb_tag_t tag = *features; - unsigned index; - g.find_feature_index (tag, &index); - if (index == OT::Index::NOT_FOUND_INDEX) continue; + features_set.add (*features); - feature_indices_filter.add(index); - for (int i = (int) index - 1; i >= 0; i--) - { - if (g.get_feature_tag (i) != tag) break; - feature_indices_filter.add(i); - } - for (unsigned i = index + 1; i < g.get_feature_count (); i++) - { - if (g.get_feature_tag (i) != tag) break; + for (unsigned i = 0; i < g.get_feature_count (); i++) + { + hb_tag_t tag = g.get_feature_tag (i); + if (features_set.has (tag)) feature_indices_filter.add(i); - } } } @@ -2011,14 +2007,14 @@ struct hb_get_glyph_alternates_dispatch_t : private: template <typename T, typename ...Ts> auto _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN - ( obj.get_glyph_alternates (hb_forward<Ts> (ds)...) ) + ( obj.get_glyph_alternates (std::forward<Ts> (ds)...) ) template <typename T, typename ...Ts> auto _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN ( default_return_value () ) public: template <typename T, typename ...Ts> auto dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN - ( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) ) + ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) ) }; /** diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh index bcc014ee98..b15d053835 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh @@ -187,7 +187,7 @@ _hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, * - General_Category: 5 bits. * - A bit each for: * * Is it Default_Ignorable(); we have a modified Default_Ignorable(). - * * Whether it's one of the three Mongolian Free Variation Selectors, + * * Whether it's one of the four Mongolian Free Variation Selectors, * CGJ, or other characters that are hidden but should not be ignored * like most other Default_Ignorable()s do during matching. * * Whether it's a grapheme continuation. @@ -202,7 +202,7 @@ _hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, enum hb_unicode_props_flags_t { UPROPS_MASK_GEN_CAT = 0x001Fu, UPROPS_MASK_IGNORABLE = 0x0020u, - UPROPS_MASK_HIDDEN = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3, or TAG characters */ + UPROPS_MASK_HIDDEN = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..4, or TAG characters */ UPROPS_MASK_CONTINUATION=0x0080u, /* If GEN_CAT=FORMAT, top byte masks: */ @@ -236,7 +236,7 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer) * FVSes are GC=Mn, we have use a separate bit to remember them. * Fixes: * https://github.com/harfbuzz/harfbuzz/issues/234 */ - else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN; + else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x180Bu, 0x180Du, 0x180Fu, 0x180Fu))) props |= UPROPS_MASK_HIDDEN; /* TAG characters need similar treatment. Fixes: * https://github.com/harfbuzz/harfbuzz/issues/463 */ else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN; diff --git a/thirdparty/harfbuzz/src/hb-ot-math-table.hh b/thirdparty/harfbuzz/src/hb-ot-math-table.hh index 5916ad29f2..c2e365dbd6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-math-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-math-table.hh @@ -41,6 +41,16 @@ struct MathValueRecord hb_position_t get_y_value (hb_font_t *font, const void *base) const { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); } + MathValueRecord* copy (hb_serialize_context_t *c, const void *base) const + { + TRACE_SERIALIZE (this); + auto *out = c->embed (this); + if (unlikely (!out)) return_trace (nullptr); + out->deviceTable.serialize_copy (c, deviceTable, base, 0, hb_serialize_context_t::Head); + + return_trace (out); + } + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -59,6 +69,29 @@ struct MathValueRecord struct MathConstants { + MathConstants* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + auto *out = c->start_embed (this); + if (unlikely (!out)) return_trace (nullptr); + + HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2); + if (unlikely (!p)) return_trace (nullptr); + memcpy (p, percentScaleDown, HBINT16::static_size * 2); + + HBUINT16 *m = c->allocate_size<HBUINT16> (HBUINT16::static_size * 2); + if (unlikely (!m)) return_trace (nullptr); + memcpy (m, minHeight, HBUINT16::static_size * 2); + + unsigned count = ARRAY_LENGTH (mathValueRecords); + for (unsigned i = 0; i < count; i++) + if (!c->copy (mathValueRecords[i], this)) + return_trace (nullptr); + + if (!c->embed (radicalDegreeBottomRaisePercent)) return_trace (nullptr); + return_trace (out); + } + bool sanitize_math_value_records (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -165,6 +198,28 @@ struct MathConstants struct MathItalicsCorrectionInfo { + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->_glyphset_mathed; + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + hb_sorted_vector_t<hb_codepoint_t> new_coverage; + + hb_zip (this+coverage, italicsCorrection) + | hb_filter (glyphset, hb_first) + | hb_filter (serialize_math_record_array (c->serializer, out->italicsCorrection, this), hb_second) + | hb_map (hb_first) + | hb_map (glyph_map) + | hb_sink (new_coverage) + ; + + out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -196,6 +251,28 @@ struct MathItalicsCorrectionInfo struct MathTopAccentAttachment { + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->_glyphset_mathed; + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + hb_sorted_vector_t<hb_codepoint_t> new_coverage; + + hb_zip (this+topAccentCoverage, topAccentAttachment) + | hb_filter (glyphset, hb_first) + | hb_filter (serialize_math_record_array (c->serializer, out->topAccentAttachment, this), hb_second) + | hb_map (hb_first) + | hb_map (glyph_map) + | hb_sink (new_coverage) + ; + + out->topAccentCoverage.serialize_serialize (c->serializer, new_coverage.iter ()); + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -229,6 +306,22 @@ struct MathTopAccentAttachment struct MathKern { + MathKern* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + auto *out = c->start_embed (this); + if (unlikely (!out)) return_trace (nullptr); + + if (unlikely (!c->embed (heightCount))) return_trace (nullptr); + + unsigned count = 2 * heightCount + 1; + for (unsigned i = 0; i < count; i++) + if (!c->copy (mathValueRecordsZ.arrayZ[i], this)) + return_trace (nullptr); + + return_trace (out); + } + bool sanitize_math_value_records (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -295,6 +388,19 @@ struct MathKern struct MathKernInfoRecord { + MathKernInfoRecord* copy (hb_serialize_context_t *c, const void *base) const + { + TRACE_SERIALIZE (this); + auto *out = c->embed (this); + if (unlikely (!out)) return_trace (nullptr); + + unsigned count = ARRAY_LENGTH (mathKern); + for (unsigned i = 0; i < count; i++) + out->mathKern[i].serialize_copy (c, mathKern[i], base, 0, hb_serialize_context_t::Head); + + return_trace (out); + } + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -328,6 +434,28 @@ struct MathKernInfoRecord struct MathKernInfo { + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->_glyphset_mathed; + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + hb_sorted_vector_t<hb_codepoint_t> new_coverage; + + hb_zip (this+mathKernCoverage, mathKernInfoRecords) + | hb_filter (glyphset, hb_first) + | hb_filter (serialize_math_record_array (c->serializer, out->mathKernInfoRecords, this), hb_second) + | hb_map (hb_first) + | hb_map (glyph_map) + | hb_sink (new_coverage) + ; + + out->mathKernCoverage.serialize_serialize (c->serializer, new_coverage.iter ()); + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -365,6 +493,30 @@ struct MathKernInfo struct MathGlyphInfo { + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + + out->mathItalicsCorrectionInfo.serialize_subset (c, mathItalicsCorrectionInfo, this); + out->mathTopAccentAttachment.serialize_subset (c, mathTopAccentAttachment, this); + + const hb_set_t &glyphset = *c->plan->_glyphset_mathed; + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto it = + + hb_iter (this+extendedShapeCoverage) + | hb_filter (glyphset) + | hb_map_retains_sorting (glyph_map) + ; + + out->extendedShapeCoverage.serialize_serialize (c->serializer, it); + + out->mathKernInfo.serialize_subset (c, mathKernInfo, this); + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -420,14 +572,27 @@ struct MathGlyphVariantRecord { friend struct MathGlyphConstruction; + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + const hb_map_t& glyph_map = *c->plan->glyph_map; + return_trace (c->serializer->check_assign (out->variantGlyph, glyph_map.get (variantGlyph), HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } + void closure_glyphs (hb_set_t *variant_glyphs) const + { variant_glyphs->add (variantGlyph); } + protected: - HBGlyphID variantGlyph; /* Glyph ID for the variant. */ + HBGlyphID16 variantGlyph; /* Glyph ID for the variant. */ HBUINT16 advanceMeasurement; /* Advance width/height, in design units, of the * variant, in the direction of requested * glyph extension. */ @@ -450,6 +615,16 @@ struct PartFlags : HBUINT16 struct MathGlyphPartRecord { + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + const hb_map_t& glyph_map = *c->plan->glyph_map; + return_trace (c->serializer->check_assign (out->glyph, glyph_map.get (glyph), HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -474,8 +649,11 @@ struct MathGlyphPartRecord (partFlags & PartFlags::Defined); } + void closure_glyphs (hb_set_t *variant_glyphs) const + { variant_glyphs->add (glyph); } + protected: - HBGlyphID glyph; /* Glyph ID for the part. */ + HBGlyphID16 glyph; /* Glyph ID for the part. */ HBUINT16 startConnectorLength; /* Advance width/ height of the straight bar * connector material, in design units, is at @@ -497,6 +675,20 @@ struct MathGlyphPartRecord struct MathGlyphAssembly { + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out)) return_trace (false); + + if (!c->serializer->copy (italicsCorrection, this)) return_trace (false); + if (!c->serializer->copy<HBUINT16> (partRecords.len)) return_trace (false); + + for (const auto& record : partRecords.iter ()) + if (!record.subset (c)) return_trace (false); + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -526,6 +718,12 @@ struct MathGlyphAssembly return partRecords.len; } + void closure_glyphs (hb_set_t *variant_glyphs) const + { + for (const auto& _ : partRecords.iter ()) + _.closure_glyphs (variant_glyphs); + } + protected: MathValueRecord italicsCorrection; @@ -543,6 +741,22 @@ struct MathGlyphAssembly struct MathGlyphConstruction { + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + out->glyphAssembly.serialize_subset (c, glyphAssembly, this); + + if (!c->serializer->check_assign (out->mathGlyphVariantRecord.len, mathGlyphVariantRecord.len, HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + for (const auto& record : mathGlyphVariantRecord.iter ()) + if (!record.subset (c)) return_trace (false); + + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -569,6 +783,14 @@ struct MathGlyphConstruction return mathGlyphVariantRecord.len; } + void closure_glyphs (hb_set_t *variant_glyphs) const + { + (this+glyphAssembly).closure_glyphs (variant_glyphs); + + for (const auto& _ : mathGlyphVariantRecord.iter ()) + _.closure_glyphs (variant_glyphs); + } + protected: /* Offset to MathGlyphAssembly table for this shape - from the beginning of MathGlyphConstruction table. May be NULL. */ @@ -583,6 +805,91 @@ struct MathGlyphConstruction struct MathVariants { + void closure_glyphs (const hb_set_t *glyph_set, + hb_set_t *variant_glyphs) const + { + const hb_array_t<const Offset16To<MathGlyphConstruction>> glyph_construction_offsets = glyphConstruction.as_array (vertGlyphCount + horizGlyphCount); + + if (vertGlyphCoverage) + { + const auto vert_offsets = glyph_construction_offsets.sub_array (0, vertGlyphCount); + + hb_zip (this+vertGlyphCoverage, vert_offsets) + | hb_filter (glyph_set, hb_first) + | hb_map (hb_second) + | hb_map (hb_add (this)) + | hb_apply ([=] (const MathGlyphConstruction &_) { _.closure_glyphs (variant_glyphs); }) + ; + } + + if (horizGlyphCoverage) + { + const auto hori_offsets = glyph_construction_offsets.sub_array (vertGlyphCount, horizGlyphCount); + + hb_zip (this+horizGlyphCoverage, hori_offsets) + | hb_filter (glyph_set, hb_first) + | hb_map (hb_second) + | hb_map (hb_add (this)) + | hb_apply ([=] (const MathGlyphConstruction &_) { _.closure_glyphs (variant_glyphs); }) + ; + } + } + + void collect_coverage_and_indices (hb_sorted_vector_t<hb_codepoint_t>& new_coverage, + const Offset16To<Coverage>& coverage, + unsigned i, + unsigned end_index, + hb_set_t& indices, + const hb_set_t& glyphset, + const hb_map_t& glyph_map) const + { + if (!coverage) return; + + for (const auto _ : (this+coverage).iter ()) + { + if (i >= end_index) return; + if (glyphset.has (_)) + { + unsigned new_gid = glyph_map.get (_); + new_coverage.push (new_gid); + indices.add (i); + } + i++; + } + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->_glyphset_mathed; + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + if (!c->serializer->check_assign (out->minConnectorOverlap, minConnectorOverlap, HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + + hb_sorted_vector_t<hb_codepoint_t> new_vert_coverage; + hb_sorted_vector_t<hb_codepoint_t> new_hori_coverage; + hb_set_t indices; + collect_coverage_and_indices (new_vert_coverage, vertGlyphCoverage, 0, vertGlyphCount, indices, glyphset, glyph_map); + collect_coverage_and_indices (new_hori_coverage, horizGlyphCoverage, vertGlyphCount, vertGlyphCount + horizGlyphCount, indices, glyphset, glyph_map); + + if (!c->serializer->check_assign (out->vertGlyphCount, new_vert_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + if (!c->serializer->check_assign (out->horizGlyphCount, new_hori_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + + for (unsigned i : indices.iter ()) + { + auto *o = c->serializer->embed (glyphConstruction[i]); + if (!o) return_trace (false); + o->serialize_subset (c, glyphConstruction[i], this); + } + + out->vertGlyphCoverage.serialize_serialize (c->serializer, new_vert_coverage.iter ()); + out->horizGlyphCoverage.serialize_serialize (c->serializer, new_hori_coverage.iter ()); + return_trace (true); + } + bool sanitize_offsets (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -690,6 +997,28 @@ struct MATH bool has_data () const { return version.to_int (); } + void closure_glyphs (hb_set_t *glyph_set) const + { + if (mathVariants) + { + hb_set_t variant_glyphs; + (this+mathVariants).closure_glyphs (glyph_set, &variant_glyphs); + hb_set_union (glyph_set, &variant_glyphs); + } + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + + out->mathConstants.serialize_copy (c->serializer, mathConstants, this, 0, hb_serialize_context_t::Head); + out->mathGlyphInfo.serialize_subset (c, mathGlyphInfo, this); + out->mathVariants.serialize_subset (c, mathVariants, this); + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/thirdparty/harfbuzz/src/hb-ot-name.h b/thirdparty/harfbuzz/src/hb-ot-name.h index 9359014c8a..1ea4b55e5c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-name.h +++ b/thirdparty/harfbuzz/src/hb-ot-name.h @@ -36,12 +36,42 @@ HB_BEGIN_DECLS /** * hb_ot_name_id_t: + * @HB_OT_NAME_ID_COPYRIGHT: Copyright notice + * @HB_OT_NAME_ID_FONT_FAMILY: Font Family name + * @HB_OT_NAME_ID_FONT_SUBFAMILY: Font Subfamily name + * @HB_OT_NAME_ID_UNIQUE_ID: Unique font identifier + * @HB_OT_NAME_ID_FULL_NAME: Full font name that reflects + * all family and relevant subfamily descriptors + * @HB_OT_NAME_ID_VERSION_STRING: Version string + * @HB_OT_NAME_ID_POSTSCRIPT_NAME: PostScript name for the font + * @HB_OT_NAME_ID_TRADEMARK: Trademark + * @HB_OT_NAME_ID_MANUFACTURER: Manufacturer Name + * @HB_OT_NAME_ID_DESIGNER: Designer + * @HB_OT_NAME_ID_DESCRIPTION: Description + * @HB_OT_NAME_ID_VENDOR_URL: URL of font vendor + * @HB_OT_NAME_ID_DESIGNER_URL: URL of typeface designer + * @HB_OT_NAME_ID_LICENSE: License Description + * @HB_OT_NAME_ID_LICENSE_URL: URL where additional licensing + * information can be found + * @HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY: Typographic Family name + * @HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY: Typographic Subfamily name + * @HB_OT_NAME_ID_MAC_FULL_NAME: Compatible Full Name for MacOS + * @HB_OT_NAME_ID_SAMPLE_TEXT: Sample text + * @HB_OT_NAME_ID_CID_FINDFONT_NAME: PostScript CID findfont name + * @HB_OT_NAME_ID_WWS_FAMILY: WWS Family Name + * @HB_OT_NAME_ID_WWS_SUBFAMILY: WWS Subfamily Name + * @HB_OT_NAME_ID_LIGHT_BACKGROUND: Light Background Palette + * @HB_OT_NAME_ID_DARK_BACKGROUND: Dark Background Palette + * @HB_OT_NAME_ID_VARIATIONS_PS_PREFIX: Variations PostScript Name Prefix * @HB_OT_NAME_ID_INVALID: Value to represent a nonexistent name ID. * * An integral type representing an OpenType 'name' table name identifier. * There are predefined name IDs, as well as name IDs return from other * API. These can be used to fetch name strings from a font face. * + * For more information on these fields, see the + * [OpenType spec](https://docs.microsoft.com/en-us/typography/opentype/spec/name#name-ids). + * * Since: 2.0.0 **/ enum diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh index 2b3b134ae3..78f46c1cac 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh @@ -49,8 +49,8 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS hb_font_t *font, unsigned int feature_index) { - OT::HBGlyphID glyphs[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1]; - OT::HBGlyphID substitutes[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1]; + OT::HBGlyphID16 glyphs[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1]; + OT::HBGlyphID16 substitutes[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1]; unsigned int num_glyphs = 0; /* Populate arrays */ @@ -78,7 +78,7 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS /* Bubble-sort or something equally good! * May not be good-enough for presidential candidate interviews, but good-enough for us... */ hb_stable_sort (&glyphs[0], num_glyphs, - (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID::cmp, + (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID16::cmp, &substitutes[0]); @@ -99,15 +99,15 @@ static OT::SubstLookup * arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font) { - OT::HBGlyphID first_glyphs[ARRAY_LENGTH_CONST (ligature_table)]; + OT::HBGlyphID16 first_glyphs[ARRAY_LENGTH_CONST (ligature_table)]; unsigned int first_glyphs_indirection[ARRAY_LENGTH_CONST (ligature_table)]; unsigned int ligature_per_first_glyph_count_list[ARRAY_LENGTH_CONST (first_glyphs)]; unsigned int num_first_glyphs = 0; /* We know that all our ligatures are 2-component */ - OT::HBGlyphID ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)]; + OT::HBGlyphID16 ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)]; unsigned int component_count_list[ARRAY_LENGTH_CONST (ligature_list)]; - OT::HBGlyphID component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */]; + OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */]; unsigned int num_ligatures = 0; /* Populate arrays */ @@ -125,7 +125,7 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN num_first_glyphs++; } hb_stable_sort (&first_glyphs[0], num_first_glyphs, - (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID::cmp, + (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID16::cmp, &first_glyphs_indirection[0]); /* Now that the first-glyphs are sorted, walk again, populate ligatures. */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc index 1f8c1410fc..222c5d6b71 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc @@ -349,7 +349,7 @@ mongolian_variation_selectors (hb_buffer_t *buffer) unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 1; i < count; i++) - if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x180Bu, 0x180Du))) + if (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0x180Bu, 0x180Du, 0x180Fu, 0x180Fu))) info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action(); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc index 0983a32848..4a8781c8f8 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc @@ -202,9 +202,6 @@ collect_features_indic (hb_ot_shape_planner_t *plan) for (; i < INDIC_NUM_FEATURES; i++) map->add_feature (indic_features[i]); - map->enable_feature (HB_TAG('c','a','l','t')); - map->enable_feature (HB_TAG('c','l','i','g')); - map->add_gsub_pause (_hb_clear_syllables); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh index e24d68a8b5..35bfbb64d5 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh @@ -49,13 +49,15 @@ enum khmer_category_t //OT_VPst = 29, }; +using khmer_position_t = indic_position_t; + static inline void set_khmer_properties (hb_glyph_info_t &info) { hb_codepoint_t u = info.codepoint; unsigned int type = hb_indic_get_categories (u); khmer_category_t cat = (khmer_category_t) (type & 0xFFu); - indic_position_t pos = (indic_position_t) (type >> 8); + khmer_position_t pos = (khmer_position_t) (type >> 8); /* diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh index c09497896d..f4ef33004d 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh @@ -51,6 +51,7 @@ enum myanmar_syllable_type_t { #define myanmar_syllable_machine_ex_H 4u #define myanmar_syllable_machine_ex_IV 2u #define myanmar_syllable_machine_ex_MH 21u +#define myanmar_syllable_machine_ex_ML 33u #define myanmar_syllable_machine_ex_MR 22u #define myanmar_syllable_machine_ex_MW 23u #define myanmar_syllable_machine_ex_MY 24u @@ -67,35 +68,36 @@ enum myanmar_syllable_type_t { #define myanmar_syllable_machine_ex_ZWNJ 5u -#line 71 "hb-ot-shape-complex-myanmar-machine.hh" +#line 72 "hb-ot-shape-complex-myanmar-machine.hh" static const unsigned char _myanmar_syllable_machine_trans_keys[] = { - 1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, - 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, - 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, - 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, - 3u, 29u, 3u, 29u, 1u, 16u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, - 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, - 3u, 29u, 1u, 32u, 1u, 32u, 8u, 8u, 0 + 1u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, + 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u, + 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u, 3u, 33u, + 3u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, + 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u, + 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u, + 3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 1u, 33u, 1u, 32u, 8u, 8u, + 0 }; static const char _myanmar_syllable_machine_key_spans[] = { - 32, 28, 25, 4, 25, 23, 21, 21, - 27, 27, 27, 27, 16, 27, 27, 27, - 27, 27, 28, 27, 27, 27, 27, 27, - 25, 4, 25, 23, 21, 21, 27, 27, - 27, 27, 16, 28, 27, 27, 27, 27, - 27, 28, 27, 27, 27, 27, 27, 28, - 27, 32, 32, 1 + 33, 31, 25, 4, 25, 23, 21, 21, + 31, 27, 27, 27, 31, 16, 31, 31, + 27, 27, 27, 28, 27, 31, 31, 31, + 31, 31, 25, 4, 25, 23, 21, 21, + 31, 27, 27, 27, 31, 16, 31, 31, + 31, 27, 27, 27, 28, 27, 31, 31, + 31, 31, 31, 31, 31, 33, 32, 1 }; static const short _myanmar_syllable_machine_index_offsets[] = { - 0, 33, 62, 88, 93, 119, 143, 165, - 187, 215, 243, 271, 299, 316, 344, 372, - 400, 428, 456, 485, 513, 541, 569, 597, - 625, 651, 656, 682, 706, 728, 750, 778, - 806, 834, 862, 879, 908, 936, 964, 992, - 1020, 1048, 1077, 1105, 1133, 1161, 1189, 1217, - 1246, 1274, 1307, 1340 + 0, 34, 66, 92, 97, 123, 147, 169, + 191, 223, 251, 279, 307, 339, 356, 388, + 420, 448, 476, 504, 533, 561, 593, 625, + 657, 689, 721, 747, 752, 778, 802, 824, + 846, 878, 906, 934, 962, 994, 1011, 1043, + 1075, 1107, 1135, 1163, 1191, 1220, 1248, 1280, + 1312, 1344, 1376, 1408, 1440, 1472, 1506, 1539 }; static const char _myanmar_syllable_machine_indicies[] = { @@ -103,192 +105,217 @@ static const char _myanmar_syllable_machine_indicies[] = { 0, 6, 1, 0, 0, 0, 0, 7, 0, 8, 9, 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1, - 0, 22, 23, 24, 24, 21, 25, 21, - 26, 21, 21, 21, 21, 21, 21, 21, - 27, 21, 21, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 21, 24, 24, - 21, 25, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 38, 21, 21, 21, 21, - 21, 21, 32, 21, 21, 21, 36, 21, - 24, 24, 21, 25, 21, 24, 24, 21, - 25, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, - 21, 32, 21, 21, 21, 36, 21, 39, - 21, 24, 24, 21, 25, 21, 32, 21, - 21, 21, 21, 21, 21, 21, 40, 21, - 21, 21, 21, 21, 21, 32, 21, 24, - 24, 21, 25, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 40, 21, 21, 21, - 21, 21, 21, 32, 21, 24, 24, 21, - 25, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, - 21, 32, 21, 22, 21, 24, 24, 21, - 25, 21, 26, 21, 21, 21, 21, 21, - 21, 21, 41, 21, 21, 41, 21, 21, - 21, 32, 42, 21, 21, 36, 21, 22, - 21, 24, 24, 21, 25, 21, 26, 21, - 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 32, 21, 21, - 21, 36, 21, 22, 21, 24, 24, 21, - 25, 21, 26, 21, 21, 21, 21, 21, - 21, 21, 41, 21, 21, 21, 21, 21, - 21, 32, 42, 21, 21, 36, 21, 22, - 21, 24, 24, 21, 25, 21, 26, 21, - 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 32, 42, 21, - 21, 36, 21, 1, 1, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 1, 21, 22, 21, 24, 24, - 21, 25, 21, 26, 21, 21, 21, 21, - 21, 21, 21, 27, 21, 21, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 21, - 22, 21, 24, 24, 21, 25, 21, 26, - 21, 21, 21, 21, 21, 21, 21, 43, - 21, 21, 21, 21, 21, 21, 32, 33, - 34, 35, 36, 21, 22, 21, 24, 24, - 21, 25, 21, 26, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 32, 33, 34, 35, 36, 21, - 22, 21, 24, 24, 21, 25, 21, 26, - 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 32, 33, - 34, 21, 36, 21, 22, 21, 24, 24, - 21, 25, 21, 26, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 32, 21, 34, 21, 36, 21, - 22, 21, 24, 24, 21, 25, 21, 26, - 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 32, 33, - 34, 35, 36, 43, 21, 22, 21, 24, - 24, 21, 25, 21, 26, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 28, - 21, 30, 21, 32, 33, 34, 35, 36, - 21, 22, 21, 24, 24, 21, 25, 21, - 26, 21, 21, 21, 21, 21, 21, 21, - 43, 21, 21, 28, 21, 21, 21, 32, - 33, 34, 35, 36, 21, 22, 21, 24, - 24, 21, 25, 21, 26, 21, 21, 21, - 21, 21, 21, 21, 44, 21, 21, 28, - 29, 30, 21, 32, 33, 34, 35, 36, - 21, 22, 21, 24, 24, 21, 25, 21, - 26, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 28, 29, 30, 21, 32, - 33, 34, 35, 36, 21, 22, 23, 24, - 24, 21, 25, 21, 26, 21, 21, 21, - 21, 21, 21, 21, 27, 21, 21, 28, - 29, 30, 31, 32, 33, 34, 35, 36, - 21, 46, 46, 45, 5, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 47, 45, - 45, 45, 45, 45, 45, 14, 45, 45, - 45, 18, 45, 46, 46, 45, 5, 45, - 46, 46, 45, 5, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 14, 45, 45, 45, - 18, 45, 48, 45, 46, 46, 45, 5, - 45, 14, 45, 45, 45, 45, 45, 45, - 45, 49, 45, 45, 45, 45, 45, 45, - 14, 45, 46, 46, 45, 5, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 49, - 45, 45, 45, 45, 45, 45, 14, 45, - 46, 46, 45, 5, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 14, 45, 2, 45, - 46, 46, 45, 5, 45, 6, 45, 45, - 45, 45, 45, 45, 45, 50, 45, 45, - 50, 45, 45, 45, 14, 51, 45, 45, - 18, 45, 2, 45, 46, 46, 45, 5, - 45, 6, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 14, 45, 45, 45, 18, 45, 2, 45, - 46, 46, 45, 5, 45, 6, 45, 45, - 45, 45, 45, 45, 45, 50, 45, 45, - 45, 45, 45, 45, 14, 51, 45, 45, - 18, 45, 2, 45, 46, 46, 45, 5, - 45, 6, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 14, 51, 45, 45, 18, 45, 52, 52, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 52, 45, 2, - 3, 46, 46, 45, 5, 45, 6, 45, - 45, 45, 45, 45, 45, 45, 8, 45, - 45, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 45, 2, 45, 46, 46, - 45, 5, 45, 6, 45, 45, 45, 45, - 45, 45, 45, 8, 45, 45, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 45, - 2, 45, 46, 46, 45, 5, 45, 6, - 45, 45, 45, 45, 45, 45, 45, 53, - 45, 45, 45, 45, 45, 45, 14, 15, - 16, 17, 18, 45, 2, 45, 46, 46, - 45, 5, 45, 6, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 14, 15, 16, 17, 18, 45, - 2, 45, 46, 46, 45, 5, 45, 6, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 14, 15, - 16, 45, 18, 45, 2, 45, 46, 46, - 45, 5, 45, 6, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 14, 45, 16, 45, 18, 45, - 2, 45, 46, 46, 45, 5, 45, 6, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 14, 15, - 16, 17, 18, 53, 45, 2, 45, 46, - 46, 45, 5, 45, 6, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 10, - 45, 12, 45, 14, 15, 16, 17, 18, - 45, 2, 45, 46, 46, 45, 5, 45, - 6, 45, 45, 45, 45, 45, 45, 45, - 53, 45, 45, 10, 45, 45, 45, 14, - 15, 16, 17, 18, 45, 2, 45, 46, - 46, 45, 5, 45, 6, 45, 45, 45, - 45, 45, 45, 45, 54, 45, 45, 10, - 11, 12, 45, 14, 15, 16, 17, 18, - 45, 2, 45, 46, 46, 45, 5, 45, - 6, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 10, 11, 12, 45, 14, - 15, 16, 17, 18, 45, 2, 3, 46, - 46, 45, 5, 45, 6, 45, 45, 45, - 45, 45, 45, 45, 8, 45, 45, 10, - 11, 12, 13, 14, 15, 16, 17, 18, - 45, 22, 23, 24, 24, 21, 25, 21, - 26, 21, 21, 21, 21, 21, 21, 21, - 55, 21, 21, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 21, 22, 56, - 24, 24, 21, 25, 21, 26, 21, 21, - 21, 21, 21, 21, 21, 27, 21, 21, - 28, 29, 30, 31, 32, 33, 34, 35, - 36, 21, 1, 1, 2, 3, 46, 46, - 45, 5, 45, 6, 1, 45, 45, 45, - 45, 1, 45, 8, 45, 45, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, - 45, 1, 45, 1, 1, 57, 57, 57, - 57, 57, 57, 57, 57, 1, 57, 57, - 57, 57, 1, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 1, 57, 58, 57, 0 + 21, 0, 23, 24, 25, 25, 22, 26, + 22, 27, 22, 22, 22, 22, 22, 22, + 22, 28, 22, 22, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 22, 22, + 39, 22, 25, 25, 22, 26, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 40, + 22, 22, 22, 22, 22, 22, 33, 22, + 22, 22, 37, 22, 25, 25, 22, 26, + 22, 25, 25, 22, 26, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 33, 22, 22, + 22, 37, 22, 41, 22, 25, 25, 22, + 26, 22, 33, 22, 22, 22, 22, 22, + 22, 22, 42, 22, 22, 22, 22, 22, + 22, 33, 22, 25, 25, 22, 26, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 42, 22, 22, 22, 22, 22, 22, 33, + 22, 25, 25, 22, 26, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 33, 22, 23, + 22, 25, 25, 22, 26, 22, 27, 22, + 22, 22, 22, 22, 22, 22, 43, 22, + 22, 44, 22, 22, 22, 33, 45, 22, + 22, 37, 22, 22, 22, 43, 22, 23, + 22, 25, 25, 22, 26, 22, 27, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 33, 22, 22, + 22, 37, 22, 23, 22, 25, 25, 22, + 26, 22, 27, 22, 22, 22, 22, 22, + 22, 22, 43, 22, 22, 22, 22, 22, + 22, 33, 45, 22, 22, 37, 22, 23, + 22, 25, 25, 22, 26, 22, 27, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 33, 45, 22, + 22, 37, 22, 23, 22, 25, 25, 22, + 26, 22, 27, 22, 22, 22, 22, 22, + 22, 22, 43, 22, 22, 22, 22, 22, + 22, 33, 45, 22, 22, 37, 22, 22, + 22, 43, 22, 1, 1, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 1, 22, 23, 22, 25, 25, + 22, 26, 22, 27, 22, 22, 22, 22, + 22, 22, 22, 28, 22, 22, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 22, + 22, 22, 39, 22, 23, 22, 25, 25, + 22, 26, 22, 27, 22, 22, 22, 22, + 22, 22, 22, 46, 22, 22, 22, 22, + 22, 22, 33, 34, 35, 36, 37, 22, + 22, 22, 39, 22, 23, 22, 25, 25, + 22, 26, 22, 27, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 33, 34, 35, 36, 37, 22, + 23, 22, 25, 25, 22, 26, 22, 27, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 33, 34, + 35, 22, 37, 22, 23, 22, 25, 25, + 22, 26, 22, 27, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 33, 22, 35, 22, 37, 22, + 23, 22, 25, 25, 22, 26, 22, 27, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 33, 34, + 35, 36, 37, 46, 22, 23, 22, 25, + 25, 22, 26, 22, 27, 22, 22, 22, + 22, 22, 22, 22, 46, 22, 22, 22, + 22, 22, 22, 33, 34, 35, 36, 37, + 22, 23, 22, 25, 25, 22, 26, 22, + 27, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 29, 22, 31, 22, 33, + 34, 35, 36, 37, 22, 22, 22, 39, + 22, 23, 22, 25, 25, 22, 26, 22, + 27, 22, 22, 22, 22, 22, 22, 22, + 46, 22, 22, 29, 22, 22, 22, 33, + 34, 35, 36, 37, 22, 22, 22, 39, + 22, 23, 22, 25, 25, 22, 26, 22, + 27, 22, 22, 22, 22, 22, 22, 22, + 47, 22, 22, 29, 30, 31, 22, 33, + 34, 35, 36, 37, 22, 22, 22, 39, + 22, 23, 22, 25, 25, 22, 26, 22, + 27, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 29, 30, 31, 22, 33, + 34, 35, 36, 37, 22, 22, 22, 39, + 22, 23, 24, 25, 25, 22, 26, 22, + 27, 22, 22, 22, 22, 22, 22, 22, + 28, 22, 22, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 22, 22, 22, 39, + 22, 49, 49, 48, 5, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 50, 48, + 48, 48, 48, 48, 48, 14, 48, 48, + 48, 18, 48, 49, 49, 48, 5, 48, + 49, 49, 48, 5, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 14, 48, 48, 48, + 18, 48, 51, 48, 49, 49, 48, 5, + 48, 14, 48, 48, 48, 48, 48, 48, + 48, 52, 48, 48, 48, 48, 48, 48, + 14, 48, 49, 49, 48, 5, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 52, + 48, 48, 48, 48, 48, 48, 14, 48, + 49, 49, 48, 5, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 14, 48, 2, 48, + 49, 49, 48, 5, 48, 6, 48, 48, + 48, 48, 48, 48, 48, 53, 48, 48, + 54, 48, 48, 48, 14, 55, 48, 48, + 18, 48, 48, 48, 53, 48, 2, 48, + 49, 49, 48, 5, 48, 6, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 14, 48, 48, 48, + 18, 48, 2, 48, 49, 49, 48, 5, + 48, 6, 48, 48, 48, 48, 48, 48, + 48, 53, 48, 48, 48, 48, 48, 48, + 14, 55, 48, 48, 18, 48, 2, 48, + 49, 49, 48, 5, 48, 6, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 14, 55, 48, 48, + 18, 48, 2, 48, 49, 49, 48, 5, + 48, 6, 48, 48, 48, 48, 48, 48, + 48, 53, 48, 48, 48, 48, 48, 48, + 14, 55, 48, 48, 18, 48, 48, 48, + 53, 48, 56, 56, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 56, 48, 2, 3, 49, 49, 48, + 5, 48, 6, 48, 48, 48, 48, 48, + 48, 48, 8, 48, 48, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 48, + 48, 21, 48, 2, 48, 49, 49, 48, + 5, 48, 6, 48, 48, 48, 48, 48, + 48, 48, 8, 48, 48, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 48, 48, + 48, 21, 48, 2, 48, 49, 49, 48, + 5, 48, 6, 48, 48, 48, 48, 48, + 48, 48, 57, 48, 48, 48, 48, 48, + 48, 14, 15, 16, 17, 18, 48, 48, + 48, 21, 48, 2, 48, 49, 49, 48, + 5, 48, 6, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 14, 15, 16, 17, 18, 48, 2, + 48, 49, 49, 48, 5, 48, 6, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 14, 15, 16, + 48, 18, 48, 2, 48, 49, 49, 48, + 5, 48, 6, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 14, 48, 16, 48, 18, 48, 2, + 48, 49, 49, 48, 5, 48, 6, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 14, 15, 16, + 17, 18, 57, 48, 2, 48, 49, 49, + 48, 5, 48, 6, 48, 48, 48, 48, + 48, 48, 48, 57, 48, 48, 48, 48, + 48, 48, 14, 15, 16, 17, 18, 48, + 2, 48, 49, 49, 48, 5, 48, 6, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 10, 48, 12, 48, 14, 15, + 16, 17, 18, 48, 48, 48, 21, 48, + 2, 48, 49, 49, 48, 5, 48, 6, + 48, 48, 48, 48, 48, 48, 48, 57, + 48, 48, 10, 48, 48, 48, 14, 15, + 16, 17, 18, 48, 48, 48, 21, 48, + 2, 48, 49, 49, 48, 5, 48, 6, + 48, 48, 48, 48, 48, 48, 48, 58, + 48, 48, 10, 11, 12, 48, 14, 15, + 16, 17, 18, 48, 48, 48, 21, 48, + 2, 48, 49, 49, 48, 5, 48, 6, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 10, 11, 12, 48, 14, 15, + 16, 17, 18, 48, 48, 48, 21, 48, + 2, 3, 49, 49, 48, 5, 48, 6, + 48, 48, 48, 48, 48, 48, 48, 8, + 48, 48, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 48, 48, 48, 21, 48, + 23, 24, 25, 25, 22, 26, 22, 27, + 22, 22, 22, 22, 22, 22, 22, 59, + 22, 22, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 22, 22, 39, 22, + 23, 60, 25, 25, 22, 26, 22, 27, + 22, 22, 22, 22, 22, 22, 22, 28, + 22, 22, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 22, 22, 22, 39, 22, + 1, 1, 2, 3, 49, 49, 48, 5, + 48, 6, 1, 48, 48, 48, 48, 1, + 48, 8, 48, 48, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 48, 1, + 21, 48, 1, 1, 61, 61, 61, 61, + 61, 61, 61, 61, 1, 61, 61, 61, + 61, 1, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, + 61, 1, 61, 62, 61, 0 }; static const char _myanmar_syllable_machine_trans_targs[] = { - 0, 1, 24, 34, 0, 25, 31, 47, - 36, 50, 37, 42, 43, 44, 27, 39, - 40, 41, 30, 46, 51, 0, 2, 12, - 0, 3, 9, 13, 14, 19, 20, 21, - 5, 16, 17, 18, 8, 23, 4, 6, - 7, 10, 11, 15, 22, 0, 0, 26, - 28, 29, 32, 33, 35, 38, 45, 48, - 49, 0, 0 + 0, 1, 26, 37, 0, 27, 33, 51, + 39, 54, 40, 46, 47, 48, 29, 42, + 43, 44, 32, 50, 55, 45, 0, 2, + 13, 0, 3, 9, 14, 15, 21, 22, + 23, 5, 17, 18, 19, 8, 25, 20, + 4, 6, 7, 10, 12, 11, 16, 24, + 0, 0, 28, 30, 31, 34, 36, 35, + 38, 41, 49, 52, 53, 0, 0 }; static const char _myanmar_syllable_machine_trans_actions[] = { 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 5, 0, 0, - 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 10 + 7, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 10 }; static const char _myanmar_syllable_machine_to_state_actions[] = { @@ -298,7 +325,7 @@ static const char _myanmar_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0 }; static const char _myanmar_syllable_machine_from_state_actions[] = { @@ -308,17 +335,17 @@ static const char _myanmar_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0 }; static const short _myanmar_syllable_machine_eof_trans[] = { - 0, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 22, - 22, 46, 58, 58 + 0, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 23, 23, 49, 62, 62 }; static const int myanmar_syllable_machine_start = 0; @@ -332,7 +359,7 @@ static const int myanmar_syllable_machine_en_main = 0; -#line 101 "hb-ot-shape-complex-myanmar-machine.rl" +#line 102 "hb-ot-shape-complex-myanmar-machine.rl" #define found_syllable(syllable_type) \ @@ -351,7 +378,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 355 "hb-ot-shape-complex-myanmar-machine.hh" +#line 382 "hb-ot-shape-complex-myanmar-machine.hh" { cs = myanmar_syllable_machine_start; ts = 0; @@ -359,7 +386,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) act = 0; } -#line 121 "hb-ot-shape-complex-myanmar-machine.rl" +#line 122 "hb-ot-shape-complex-myanmar-machine.rl" p = 0; @@ -367,7 +394,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 371 "hb-ot-shape-complex-myanmar-machine.hh" +#line 398 "hb-ot-shape-complex-myanmar-machine.hh" { int _slen; int _trans; @@ -381,7 +408,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 385 "hb-ot-shape-complex-myanmar-machine.hh" +#line 412 "hb-ot-shape-complex-myanmar-machine.hh" } _keys = _myanmar_syllable_machine_trans_keys + (cs<<1); @@ -400,38 +427,38 @@ _eof_trans: switch ( _myanmar_syllable_machine_trans_actions[_trans] ) { case 6: -#line 93 "hb-ot-shape-complex-myanmar-machine.rl" +#line 94 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (myanmar_consonant_syllable); }} break; case 4: -#line 94 "hb-ot-shape-complex-myanmar-machine.rl" +#line 95 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }} break; case 10: -#line 95 "hb-ot-shape-complex-myanmar-machine.rl" +#line 96 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (myanmar_punctuation_cluster); }} break; case 8: -#line 96 "hb-ot-shape-complex-myanmar-machine.rl" +#line 97 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (myanmar_broken_cluster); }} break; case 3: -#line 97 "hb-ot-shape-complex-myanmar-machine.rl" +#line 98 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }} break; case 5: -#line 93 "hb-ot-shape-complex-myanmar-machine.rl" +#line 94 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }} break; case 7: -#line 96 "hb-ot-shape-complex-myanmar-machine.rl" +#line 97 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (myanmar_broken_cluster); }} break; case 9: -#line 97 "hb-ot-shape-complex-myanmar-machine.rl" +#line 98 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }} break; -#line 435 "hb-ot-shape-complex-myanmar-machine.hh" +#line 462 "hb-ot-shape-complex-myanmar-machine.hh" } _again: @@ -440,7 +467,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 444 "hb-ot-shape-complex-myanmar-machine.hh" +#line 471 "hb-ot-shape-complex-myanmar-machine.hh" } if ( ++p != pe ) @@ -456,7 +483,7 @@ _again: } -#line 129 "hb-ot-shape-complex-myanmar-machine.rl" +#line 130 "hb-ot-shape-complex-myanmar-machine.rl" } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc index 6e92a9b0ae..e6ae75e8f2 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc @@ -185,7 +185,7 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer, info[i].myanmar_position() = POS_BASE_C; i++; } - indic_position_t pos = POS_AFTER_MAIN; + myanmar_position_t pos = POS_AFTER_MAIN; /* The following loop may be ugly, but it implements all of * Myanmar reordering! */ for (; i < end; i++) diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh index a6d68aae57..7fbca3878f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh @@ -56,8 +56,10 @@ enum myanmar_category_t { OT_VS = 30, /* Variation selectors */ OT_P = 31, /* Punctuation */ OT_D = 32, /* Digits except zero */ + OT_ML = 33, /* Various consonant medial types */ }; +using myanmar_position_t = indic_position_t; static inline void set_myanmar_properties (hb_glyph_info_t &info) @@ -65,7 +67,7 @@ set_myanmar_properties (hb_glyph_info_t &info) hb_codepoint_t u = info.codepoint; unsigned int type = hb_indic_get_categories (u); unsigned int cat = type & 0xFFu; - indic_position_t pos = (indic_position_t) (type >> 8); + myanmar_position_t pos = (myanmar_position_t) (type >> 8); /* Myanmar * https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze @@ -114,10 +116,14 @@ set_myanmar_properties (hb_glyph_info_t &info) cat = OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */ break; - case 0x103Eu: case 0x1060u: + case 0x103Eu: cat = OT_MH; break; + case 0x1060u: + cat = OT_ML; + break; + case 0x103Cu: cat = OT_MR; break; diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh index bb046a72ec..c3920b2cc6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh @@ -41,7 +41,6 @@ #define USE(Cat) use_syllable_machine_ex_##Cat enum use_syllable_type_t { - use_independent_cluster, use_virama_terminated_cluster, use_sakot_terminated_cluster, use_standard_cluster, @@ -54,8 +53,9 @@ enum use_syllable_type_t { }; -#line 58 "hb-ot-shape-complex-use-machine.hh" +#line 57 "hb-ot-shape-complex-use-machine.hh" #define use_syllable_machine_ex_B 1u +#define use_syllable_machine_ex_CGJ 6u #define use_syllable_machine_ex_CMAbv 31u #define use_syllable_machine_ex_CMBlw 32u #define use_syllable_machine_ex_CS 43u @@ -78,7 +78,6 @@ enum use_syllable_type_t { #define use_syllable_machine_ex_N 4u #define use_syllable_machine_ex_O 0u #define use_syllable_machine_ex_R 18u -#define use_syllable_machine_ex_S 19u #define use_syllable_machine_ex_SB 51u #define use_syllable_machine_ex_SE 52u #define use_syllable_machine_ex_SMAbv 41u @@ -96,280 +95,278 @@ enum use_syllable_type_t { #define use_syllable_machine_ex_ZWNJ 14u -#line 100 "hb-ot-shape-complex-use-machine.hh" +#line 99 "hb-ot-shape-complex-use-machine.hh" static const unsigned char _use_syllable_machine_trans_keys[] = { - 1u, 1u, 1u, 1u, 0u, 51u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 23u, 48u, + 0u, 51u, 41u, 42u, 42u, 42u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, - 11u, 48u, 1u, 48u, 13u, 13u, 4u, 4u, 11u, 48u, 41u, 42u, 42u, 42u, 11u, 48u, - 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, - 24u, 48u, 24u, 48u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, - 22u, 48u, 11u, 48u, 1u, 48u, 1u, 1u, 4u, 4u, 13u, 13u, 1u, 48u, 11u, 48u, - 41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u, 0 + 11u, 48u, 1u, 48u, 13u, 13u, 4u, 4u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, + 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, + 24u, 48u, 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, + 22u, 48u, 11u, 48u, 1u, 48u, 4u, 4u, 13u, 13u, 1u, 48u, 11u, 48u, 41u, 42u, + 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u, 0 }; static const char _use_syllable_machine_key_spans[] = { - 1, 1, 52, 38, 38, 1, 27, 26, + 52, 2, 1, 38, 38, 1, 27, 26, 24, 23, 22, 2, 1, 25, 25, 25, 1, 25, 26, 26, 26, 27, 27, 27, - 38, 48, 1, 1, 38, 2, 1, 38, - 27, 26, 24, 23, 22, 2, 1, 25, - 25, 25, 25, 26, 26, 26, 27, 27, - 27, 38, 48, 1, 1, 1, 48, 38, - 2, 1, 5, 3, 4, 3 + 38, 48, 1, 1, 38, 38, 1, 27, + 26, 24, 23, 22, 2, 1, 25, 25, + 25, 1, 25, 26, 26, 26, 27, 27, + 27, 38, 48, 1, 1, 48, 38, 2, + 1, 5, 3, 4, 3 }; static const short _use_syllable_machine_index_offsets[] = { - 0, 2, 4, 57, 96, 135, 137, 165, - 192, 217, 241, 264, 267, 269, 295, 321, - 347, 349, 375, 402, 429, 456, 484, 512, - 540, 579, 628, 630, 632, 671, 674, 676, - 715, 743, 770, 795, 819, 842, 845, 847, - 873, 899, 925, 951, 978, 1005, 1032, 1060, - 1088, 1116, 1155, 1204, 1206, 1208, 1210, 1259, - 1298, 1301, 1303, 1309, 1313, 1318 + 0, 53, 56, 58, 97, 136, 138, 166, + 193, 218, 242, 265, 268, 270, 296, 322, + 348, 350, 376, 403, 430, 457, 485, 513, + 541, 580, 629, 631, 633, 672, 711, 713, + 741, 768, 793, 817, 840, 843, 845, 871, + 897, 923, 925, 951, 978, 1005, 1032, 1060, + 1088, 1116, 1155, 1204, 1206, 1208, 1257, 1296, + 1299, 1301, 1307, 1311, 1316 }; static const char _use_syllable_machine_indicies[] = { - 1, 0, 2, 0, 3, 4, 5, 5, - 6, 7, 5, 5, 5, 5, 5, 1, - 8, 9, 5, 5, 5, 5, 10, 11, - 5, 5, 12, 13, 14, 15, 16, 17, - 18, 12, 19, 20, 21, 22, 23, 24, - 5, 25, 26, 27, 5, 28, 29, 30, - 31, 32, 33, 34, 8, 35, 5, 36, - 5, 38, 39, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 40, 41, 42, 43, - 44, 45, 46, 40, 47, 4, 48, 49, - 50, 51, 37, 52, 53, 54, 37, 37, - 37, 37, 55, 56, 57, 58, 39, 37, - 38, 39, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 40, 41, 42, 43, 44, - 45, 46, 40, 47, 48, 48, 49, 50, - 51, 37, 52, 53, 54, 37, 37, 37, - 37, 55, 56, 57, 58, 39, 37, 38, - 59, 40, 41, 42, 43, 44, 37, 37, - 37, 37, 37, 37, 49, 50, 51, 37, - 52, 53, 54, 37, 37, 37, 37, 41, - 56, 57, 58, 60, 37, 41, 42, 43, - 44, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 52, 53, 54, 37, 37, - 37, 37, 37, 56, 57, 58, 60, 37, - 42, 43, 44, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 56, 57, 58, - 37, 43, 44, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 56, 57, 58, - 37, 44, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 56, 57, 58, 37, - 56, 57, 37, 57, 37, 42, 43, 44, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 52, 53, 54, 37, 37, 37, - 37, 37, 56, 57, 58, 60, 37, 42, - 43, 44, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 53, 54, 37, - 37, 37, 37, 37, 56, 57, 58, 60, - 37, 42, 43, 44, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 54, 37, 37, 37, 37, 37, 56, 57, - 58, 60, 37, 62, 61, 42, 43, 44, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 56, 57, 58, 60, 37, 41, - 42, 43, 44, 37, 37, 37, 37, 37, - 37, 49, 50, 51, 37, 52, 53, 54, - 37, 37, 37, 37, 41, 56, 57, 58, - 60, 37, 41, 42, 43, 44, 37, 37, - 37, 37, 37, 37, 37, 50, 51, 37, - 52, 53, 54, 37, 37, 37, 37, 41, - 56, 57, 58, 60, 37, 41, 42, 43, - 44, 37, 37, 37, 37, 37, 37, 37, - 37, 51, 37, 52, 53, 54, 37, 37, - 37, 37, 41, 56, 57, 58, 60, 37, - 40, 41, 42, 43, 44, 37, 46, 40, - 37, 37, 37, 49, 50, 51, 37, 52, - 53, 54, 37, 37, 37, 37, 41, 56, - 57, 58, 60, 37, 40, 41, 42, 43, - 44, 37, 37, 40, 37, 37, 37, 49, - 50, 51, 37, 52, 53, 54, 37, 37, - 37, 37, 41, 56, 57, 58, 60, 37, - 40, 41, 42, 43, 44, 45, 46, 40, - 37, 37, 37, 49, 50, 51, 37, 52, - 53, 54, 37, 37, 37, 37, 41, 56, - 57, 58, 60, 37, 38, 39, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 40, - 41, 42, 43, 44, 45, 46, 40, 47, - 37, 48, 49, 50, 51, 37, 52, 53, - 54, 37, 37, 37, 37, 55, 56, 57, - 58, 39, 37, 38, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, - 59, 41, 42, 43, 44, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 52, - 53, 54, 59, 59, 59, 59, 59, 56, - 57, 58, 60, 59, 64, 63, 6, 65, - 38, 39, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 40, 41, 42, 43, 44, - 45, 46, 40, 47, 4, 48, 49, 50, - 51, 37, 52, 53, 54, 37, 11, 66, - 37, 55, 56, 57, 58, 39, 37, 11, - 66, 67, 66, 67, 1, 69, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 12, - 13, 14, 15, 16, 17, 18, 12, 19, - 21, 21, 22, 23, 24, 68, 25, 26, - 27, 68, 68, 68, 68, 31, 32, 33, - 34, 69, 68, 12, 13, 14, 15, 16, - 68, 68, 68, 68, 68, 68, 22, 23, - 24, 68, 25, 26, 27, 68, 68, 68, - 68, 13, 32, 33, 34, 70, 68, 13, - 14, 15, 16, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 25, 26, 27, - 68, 68, 68, 68, 68, 32, 33, 34, - 70, 68, 14, 15, 16, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 32, - 33, 34, 68, 15, 16, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 32, - 33, 34, 68, 16, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 32, 33, - 34, 68, 32, 33, 68, 33, 68, 14, - 15, 16, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 25, 26, 27, 68, - 68, 68, 68, 68, 32, 33, 34, 70, - 68, 14, 15, 16, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 26, - 27, 68, 68, 68, 68, 68, 32, 33, - 34, 70, 68, 14, 15, 16, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 27, 68, 68, 68, 68, 68, - 32, 33, 34, 70, 68, 14, 15, 16, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 32, 33, 34, 70, 68, 13, - 14, 15, 16, 68, 68, 68, 68, 68, - 68, 22, 23, 24, 68, 25, 26, 27, - 68, 68, 68, 68, 13, 32, 33, 34, - 70, 68, 13, 14, 15, 16, 68, 68, - 68, 68, 68, 68, 68, 23, 24, 68, - 25, 26, 27, 68, 68, 68, 68, 13, - 32, 33, 34, 70, 68, 13, 14, 15, - 16, 68, 68, 68, 68, 68, 68, 68, - 68, 24, 68, 25, 26, 27, 68, 68, - 68, 68, 13, 32, 33, 34, 70, 68, - 12, 13, 14, 15, 16, 68, 18, 12, - 68, 68, 68, 22, 23, 24, 68, 25, - 26, 27, 68, 68, 68, 68, 13, 32, - 33, 34, 70, 68, 12, 13, 14, 15, - 16, 68, 68, 12, 68, 68, 68, 22, - 23, 24, 68, 25, 26, 27, 68, 68, - 68, 68, 13, 32, 33, 34, 70, 68, - 12, 13, 14, 15, 16, 17, 18, 12, - 68, 68, 68, 22, 23, 24, 68, 25, - 26, 27, 68, 68, 68, 68, 13, 32, - 33, 34, 70, 68, 1, 69, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 12, - 13, 14, 15, 16, 17, 18, 12, 19, - 68, 21, 22, 23, 24, 68, 25, 26, - 27, 68, 68, 68, 68, 31, 32, 33, - 34, 69, 68, 1, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 13, 14, 15, 16, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 25, - 26, 27, 68, 68, 68, 68, 68, 32, - 33, 34, 70, 68, 1, 71, 72, 68, - 9, 68, 4, 68, 68, 68, 4, 68, - 68, 68, 68, 68, 1, 69, 9, 68, - 68, 68, 68, 68, 68, 68, 68, 12, - 13, 14, 15, 16, 17, 18, 12, 19, - 20, 21, 22, 23, 24, 68, 25, 26, - 27, 68, 28, 29, 68, 31, 32, 33, - 34, 69, 68, 1, 69, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 12, 13, - 14, 15, 16, 17, 18, 12, 19, 20, - 21, 22, 23, 24, 68, 25, 26, 27, - 68, 68, 68, 68, 31, 32, 33, 34, - 69, 68, 28, 29, 68, 29, 68, 4, - 71, 71, 71, 4, 71, 74, 73, 35, - 73, 35, 74, 73, 74, 73, 35, 73, - 36, 73, 0 + 0, 1, 2, 2, 3, 4, 2, 2, + 2, 2, 2, 5, 6, 7, 2, 2, + 2, 2, 8, 2, 2, 2, 9, 10, + 11, 12, 13, 14, 15, 9, 16, 17, + 18, 19, 20, 21, 2, 22, 23, 24, + 2, 25, 26, 27, 28, 29, 30, 31, + 6, 32, 2, 33, 2, 0, 35, 34, + 35, 34, 37, 38, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 39, 40, 41, + 42, 43, 44, 45, 39, 46, 1, 47, + 48, 49, 50, 36, 51, 52, 53, 36, + 36, 36, 36, 54, 55, 56, 57, 38, + 36, 37, 38, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 39, 40, 41, 42, + 43, 44, 45, 39, 46, 47, 47, 48, + 49, 50, 36, 51, 52, 53, 36, 36, + 36, 36, 54, 55, 56, 57, 38, 36, + 37, 58, 39, 40, 41, 42, 43, 36, + 36, 36, 36, 36, 36, 48, 49, 50, + 36, 51, 52, 53, 36, 36, 36, 36, + 40, 55, 56, 57, 59, 36, 40, 41, + 42, 43, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 51, 52, 53, 36, + 36, 36, 36, 36, 55, 56, 57, 59, + 36, 41, 42, 43, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 55, 56, + 57, 36, 42, 43, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 55, 56, + 57, 36, 43, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 55, 56, 57, + 36, 55, 56, 36, 56, 36, 41, 42, + 43, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 51, 52, 53, 36, 36, + 36, 36, 36, 55, 56, 57, 59, 36, + 41, 42, 43, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 52, 53, + 36, 36, 36, 36, 36, 55, 56, 57, + 59, 36, 41, 42, 43, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 53, 36, 36, 36, 36, 36, 55, + 56, 57, 59, 36, 61, 60, 41, 42, + 43, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 55, 56, 57, 59, 36, + 40, 41, 42, 43, 36, 36, 36, 36, + 36, 36, 48, 49, 50, 36, 51, 52, + 53, 36, 36, 36, 36, 40, 55, 56, + 57, 59, 36, 40, 41, 42, 43, 36, + 36, 36, 36, 36, 36, 36, 49, 50, + 36, 51, 52, 53, 36, 36, 36, 36, + 40, 55, 56, 57, 59, 36, 40, 41, + 42, 43, 36, 36, 36, 36, 36, 36, + 36, 36, 50, 36, 51, 52, 53, 36, + 36, 36, 36, 40, 55, 56, 57, 59, + 36, 39, 40, 41, 42, 43, 36, 45, + 39, 36, 36, 36, 48, 49, 50, 36, + 51, 52, 53, 36, 36, 36, 36, 40, + 55, 56, 57, 59, 36, 39, 40, 41, + 42, 43, 36, 36, 39, 36, 36, 36, + 48, 49, 50, 36, 51, 52, 53, 36, + 36, 36, 36, 40, 55, 56, 57, 59, + 36, 39, 40, 41, 42, 43, 44, 45, + 39, 36, 36, 36, 48, 49, 50, 36, + 51, 52, 53, 36, 36, 36, 36, 40, + 55, 56, 57, 59, 36, 37, 38, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 39, 40, 41, 42, 43, 44, 45, 39, + 46, 36, 47, 48, 49, 50, 36, 51, + 52, 53, 36, 36, 36, 36, 54, 55, + 56, 57, 38, 36, 37, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 40, 41, 42, 43, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, + 51, 52, 53, 58, 58, 58, 58, 58, + 55, 56, 57, 59, 58, 63, 62, 3, + 64, 37, 38, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 39, 40, 41, 42, + 43, 44, 45, 39, 46, 1, 47, 48, + 49, 50, 36, 51, 52, 53, 36, 0, + 35, 36, 54, 55, 56, 57, 38, 36, + 5, 6, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 9, 10, 11, 12, 13, + 14, 15, 9, 16, 18, 18, 19, 20, + 21, 65, 22, 23, 24, 65, 65, 65, + 65, 28, 29, 30, 31, 6, 65, 5, + 65, 9, 10, 11, 12, 13, 65, 65, + 65, 65, 65, 65, 19, 20, 21, 65, + 22, 23, 24, 65, 65, 65, 65, 10, + 29, 30, 31, 66, 65, 10, 11, 12, + 13, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 22, 23, 24, 65, 65, + 65, 65, 65, 29, 30, 31, 66, 65, + 11, 12, 13, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 29, 30, 31, + 65, 12, 13, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 29, 30, 31, + 65, 13, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 29, 30, 31, 65, + 29, 30, 65, 30, 65, 11, 12, 13, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 22, 23, 24, 65, 65, 65, + 65, 65, 29, 30, 31, 66, 65, 11, + 12, 13, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 23, 24, 65, + 65, 65, 65, 65, 29, 30, 31, 66, + 65, 11, 12, 13, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 24, 65, 65, 65, 65, 65, 29, 30, + 31, 66, 65, 67, 65, 11, 12, 13, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 29, 30, 31, 66, 65, 10, + 11, 12, 13, 65, 65, 65, 65, 65, + 65, 19, 20, 21, 65, 22, 23, 24, + 65, 65, 65, 65, 10, 29, 30, 31, + 66, 65, 10, 11, 12, 13, 65, 65, + 65, 65, 65, 65, 65, 20, 21, 65, + 22, 23, 24, 65, 65, 65, 65, 10, + 29, 30, 31, 66, 65, 10, 11, 12, + 13, 65, 65, 65, 65, 65, 65, 65, + 65, 21, 65, 22, 23, 24, 65, 65, + 65, 65, 10, 29, 30, 31, 66, 65, + 9, 10, 11, 12, 13, 65, 15, 9, + 65, 65, 65, 19, 20, 21, 65, 22, + 23, 24, 65, 65, 65, 65, 10, 29, + 30, 31, 66, 65, 9, 10, 11, 12, + 13, 65, 65, 9, 65, 65, 65, 19, + 20, 21, 65, 22, 23, 24, 65, 65, + 65, 65, 10, 29, 30, 31, 66, 65, + 9, 10, 11, 12, 13, 14, 15, 9, + 65, 65, 65, 19, 20, 21, 65, 22, + 23, 24, 65, 65, 65, 65, 10, 29, + 30, 31, 66, 65, 5, 6, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 9, + 10, 11, 12, 13, 14, 15, 9, 16, + 65, 18, 19, 20, 21, 65, 22, 23, + 24, 65, 65, 65, 65, 28, 29, 30, + 31, 6, 65, 5, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, + 65, 10, 11, 12, 13, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 22, + 23, 24, 65, 65, 65, 65, 65, 29, + 30, 31, 66, 65, 68, 65, 7, 65, + 1, 65, 65, 65, 1, 65, 65, 65, + 65, 65, 5, 6, 7, 65, 65, 65, + 65, 65, 65, 65, 65, 9, 10, 11, + 12, 13, 14, 15, 9, 16, 17, 18, + 19, 20, 21, 65, 22, 23, 24, 65, + 25, 26, 65, 28, 29, 30, 31, 6, + 65, 5, 6, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 9, 10, 11, 12, + 13, 14, 15, 9, 16, 17, 18, 19, + 20, 21, 65, 22, 23, 24, 65, 65, + 65, 65, 28, 29, 30, 31, 6, 65, + 25, 26, 65, 26, 65, 1, 69, 69, + 69, 1, 69, 71, 70, 32, 70, 32, + 71, 70, 71, 70, 32, 70, 33, 70, + 0 }; static const char _use_syllable_machine_trans_targs[] = { - 2, 31, 42, 2, 3, 2, 26, 28, - 51, 52, 54, 29, 32, 33, 34, 35, - 36, 46, 47, 48, 55, 49, 43, 44, - 45, 39, 40, 41, 56, 57, 58, 50, - 37, 38, 2, 59, 61, 2, 4, 5, - 6, 7, 8, 9, 10, 21, 22, 23, - 24, 18, 19, 20, 13, 14, 15, 25, - 11, 12, 2, 2, 16, 2, 17, 2, - 27, 2, 30, 2, 2, 0, 1, 2, - 53, 2, 60 + 1, 3, 0, 26, 28, 29, 30, 51, + 53, 31, 32, 33, 34, 35, 46, 47, + 48, 54, 49, 43, 44, 45, 38, 39, + 40, 55, 56, 57, 50, 36, 37, 0, + 58, 60, 0, 2, 0, 4, 5, 6, + 7, 8, 9, 10, 21, 22, 23, 24, + 18, 19, 20, 13, 14, 15, 25, 11, + 12, 0, 0, 16, 0, 17, 0, 27, + 0, 0, 41, 42, 52, 0, 0, 59 }; static const char _use_syllable_machine_trans_actions[] = { - 1, 2, 2, 5, 0, 6, 0, 0, - 0, 0, 2, 0, 2, 2, 0, 0, - 0, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 0, 0, 0, 2, - 0, 0, 7, 0, 0, 8, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 10, 0, 11, 0, 12, - 0, 13, 0, 14, 15, 0, 0, 16, - 0, 17, 0 + 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 5, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 8, 0, 9, 0, 10, 0, + 11, 12, 0, 0, 0, 13, 14, 0 }; static const char _use_syllable_machine_to_state_actions[] = { - 0, 0, 3, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0 }; static const char _use_syllable_machine_from_state_actions[] = { - 0, 0, 4, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0 }; static const short _use_syllable_machine_eof_trans[] = { - 1, 1, 0, 38, 38, 60, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, - 62, 38, 38, 38, 38, 38, 38, 38, - 38, 60, 64, 66, 38, 68, 68, 69, - 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 72, 69, 69, 69, 69, - 69, 69, 72, 74, 74, 74 + 0, 35, 35, 37, 37, 59, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, + 61, 37, 37, 37, 37, 37, 37, 37, + 37, 59, 63, 65, 37, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, + 66, 70, 71, 71, 71 }; -static const int use_syllable_machine_start = 2; -static const int use_syllable_machine_first_final = 2; +static const int use_syllable_machine_start = 0; +static const int use_syllable_machine_first_final = 0; static const int use_syllable_machine_error = -1; -static const int use_syllable_machine_en_main = 2; +static const int use_syllable_machine_en_main = 0; -#line 59 "hb-ot-shape-complex-use-machine.rl" +#line 58 "hb-ot-shape-complex-use-machine.rl" -#line 176 "hb-ot-shape-complex-use-machine.rl" +#line 179 "hb-ot-shape-complex-use-machine.rl" #define found_syllable(syllable_type) \ @@ -422,8 +419,8 @@ HB_FUNCOBJ (machine_index); static bool -not_standard_default_ignorable (const hb_glyph_info_t &i) -{ return !(i.use_category() == USE(O) && _hb_glyph_info_is_default_ignorable (&i)); } +not_ccs_default_ignorable (const hb_glyph_info_t &i) +{ return !(i.use_category() == USE(CGJ) && _hb_glyph_info_is_default_ignorable (&i)); } static inline void find_syllables_use (hb_buffer_t *buffer) @@ -432,13 +429,13 @@ find_syllables_use (hb_buffer_t *buffer) auto p = + hb_iter (info, buffer->len) | hb_enumerate - | hb_filter ([] (const hb_glyph_info_t &i) { return not_standard_default_ignorable (i); }, + | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); }, hb_second) | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p) { if (p.second.use_category() == USE(ZWNJ)) for (unsigned i = p.first + 1; i < buffer->len; ++i) - if (not_standard_default_ignorable (info[i])) + if (not_ccs_default_ignorable (info[i])) return !_hb_glyph_info_is_unicode_mark (&info[i]); return true; }) @@ -452,7 +449,7 @@ find_syllables_use (hb_buffer_t *buffer) unsigned int act HB_UNUSED; int cs; -#line 456 "hb-ot-shape-complex-use-machine.hh" +#line 453 "hb-ot-shape-complex-use-machine.hh" { cs = use_syllable_machine_start; ts = 0; @@ -460,12 +457,12 @@ find_syllables_use (hb_buffer_t *buffer) act = 0; } -#line 260 "hb-ot-shape-complex-use-machine.rl" +#line 263 "hb-ot-shape-complex-use-machine.rl" unsigned int syllable_serial = 1; -#line 469 "hb-ot-shape-complex-use-machine.hh" +#line 466 "hb-ot-shape-complex-use-machine.hh" { int _slen; int _trans; @@ -475,11 +472,11 @@ find_syllables_use (hb_buffer_t *buffer) goto _test_eof; _resume: switch ( _use_syllable_machine_from_state_actions[cs] ) { - case 4: + case 2: #line 1 "NONE" {ts = p;} break; -#line 483 "hb-ot-shape-complex-use-machine.hh" +#line 480 "hb-ot-shape-complex-use-machine.hh" } _keys = _use_syllable_machine_trans_keys + (cs<<1); @@ -497,76 +494,64 @@ _eof_trans: goto _again; switch ( _use_syllable_machine_trans_actions[_trans] ) { - case 2: -#line 1 "NONE" - {te = p+1;} - break; - case 5: -#line 163 "hb-ot-shape-complex-use-machine.rl" - {te = p+1;{ found_syllable (use_independent_cluster); }} - break; - case 9: -#line 166 "hb-ot-shape-complex-use-machine.rl" + case 7: +#line 169 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (use_standard_cluster); }} break; - case 7: -#line 171 "hb-ot-shape-complex-use-machine.rl" + case 4: +#line 174 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (use_broken_cluster); }} break; - case 6: -#line 172 "hb-ot-shape-complex-use-machine.rl" + case 3: +#line 175 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (use_non_cluster); }} break; - case 10: -#line 164 "hb-ot-shape-complex-use-machine.rl" + case 8: +#line 167 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_virama_terminated_cluster); }} break; - case 11: -#line 165 "hb-ot-shape-complex-use-machine.rl" + case 9: +#line 168 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }} break; - case 8: -#line 166 "hb-ot-shape-complex-use-machine.rl" + case 6: +#line 169 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_standard_cluster); }} break; - case 13: -#line 167 "hb-ot-shape-complex-use-machine.rl" + case 11: +#line 170 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }} break; - case 12: -#line 168 "hb-ot-shape-complex-use-machine.rl" + case 10: +#line 171 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_numeral_cluster); }} break; - case 14: -#line 169 "hb-ot-shape-complex-use-machine.rl" + case 5: +#line 172 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_symbol_cluster); }} break; - case 17: -#line 170 "hb-ot-shape-complex-use-machine.rl" + case 14: +#line 173 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_hieroglyph_cluster); }} break; - case 15: -#line 171 "hb-ot-shape-complex-use-machine.rl" + case 12: +#line 174 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_broken_cluster); }} break; - case 16: -#line 172 "hb-ot-shape-complex-use-machine.rl" + case 13: +#line 175 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_non_cluster); }} break; - case 1: -#line 171 "hb-ot-shape-complex-use-machine.rl" - {{p = ((te))-1;}{ found_syllable (use_broken_cluster); }} - break; -#line 561 "hb-ot-shape-complex-use-machine.hh" +#line 546 "hb-ot-shape-complex-use-machine.hh" } _again: switch ( _use_syllable_machine_to_state_actions[cs] ) { - case 3: + case 1: #line 1 "NONE" {ts = 0;} break; -#line 570 "hb-ot-shape-complex-use-machine.hh" +#line 555 "hb-ot-shape-complex-use-machine.hh" } if ( ++p != pe ) @@ -582,7 +567,7 @@ _again: } -#line 265 "hb-ot-shape-complex-use-machine.rl" +#line 268 "hb-ot-shape-complex-use-machine.rl" } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh index 7903a0ef89..7a3a995c8c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh @@ -2,7 +2,7 @@ /* * The following table is generated by running: * - * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt ArabicShaping.txt Blocks.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt + * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt * * on files with these headers: * @@ -12,22 +12,28 @@ * # Date: 2021-05-22, 01:01:00 GMT [KW, RP] * # ArabicShaping-14.0.0.txt * # Date: 2021-05-21, 01:54:00 GMT [KW, RP] + * # DerivedCoreProperties-14.0.0.txt + * # Date: 2021-08-12, 23:12:53 GMT * # Blocks-14.0.0.txt * # Date: 2021-01-22, 23:29:00 GMT [KW] + * # Scripts-14.0.0.txt + * # Date: 2021-07-10, 00:35:31 GMT * # Override values For Indic_Syllabic_Category * # Not derivable * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17 - * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25 - * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24 - * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28 + * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25 + * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24 + * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28 + * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25 * # Override values For Indic_Positional_Category * # Not derivable * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17 - * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25 + * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25 * # Ammended for Unicode 10.0 by Andrew Glass 2018-09-21 - * # Updated for L2/19-083 by Andrew Glass 2019-05-06 - * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30 - * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28 + * # Updated for L2/19-083 by Andrew Glass 2019-05-06 + * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30 + * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28 + * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28 * UnicodeData.txt does not have a header. */ @@ -41,6 +47,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-macros" #define B USE(B) /* BASE */ +#define CGJ USE(CGJ) /* CGJ */ #define CS USE(CS) /* CONS_WITH_STACKER */ #define G USE(G) /* HIEROGLYPH */ #define GB USE(GB) /* BASE_OTHER */ @@ -51,7 +58,6 @@ #define N USE(N) /* BASE_NUM */ #define O USE(O) /* OTHER */ #define R USE(R) /* REPHA */ -#define S USE(S) /* SYM */ #define SB USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */ #define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */ #define SUB USE(SUB) /* CONS_SUB */ @@ -101,14 +107,20 @@ static const uint8_t use_table[] = { /* 00C0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* 00D0 */ O, O, O, O, O, O, O, GB, -#define use_offset_0x0640u 80 +#define use_offset_0x0348u 80 + + + /* Combining Diacritical Marks */ + O, O, O, O, O, O, O, CGJ, + +#define use_offset_0x0640u 88 /* Arabic */ /* 0640 */ B, O, O, O, O, O, O, O, -#define use_offset_0x07c8u 88 +#define use_offset_0x07c8u 96 /* NKo */ @@ -117,7 +129,7 @@ static const uint8_t use_table[] = { /* 07E0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, /* 07F0 */ VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, O, O, O, B, O, O, VMAbv, O, O, -#define use_offset_0x0840u 144 +#define use_offset_0x0840u 152 /* Mandaic */ @@ -125,7 +137,7 @@ static const uint8_t use_table[] = { /* 0840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0850 */ B, B, B, B, B, B, B, B, B, CMBlw, CMBlw, CMBlw, O, O, O, O, -#define use_offset_0x0900u 176 +#define use_offset_0x0900u 184 /* Devanagari */ @@ -238,7 +250,7 @@ static const uint8_t use_table[] = { /* 0DE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, /* 0DF0 */ O, O, VPst, VPst, O, O, O, O, -#define use_offset_0x0f00u 1448 +#define use_offset_0x0f00u 1456 /* Tibetan */ @@ -257,7 +269,7 @@ static const uint8_t use_table[] = { /* 0FB0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, O, O, /* 0FC0 */ O, O, O, O, O, O, FBlw, O, -#define use_offset_0x1000u 1648 +#define use_offset_0x1000u 1656 /* Myanmar */ @@ -273,7 +285,7 @@ static const uint8_t use_table[] = { /* 1080 */ B, B, MBlw, VPst, VPre, VAbv, VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw, B, VMPst, /* 1090 */ B, B, B, B, B, B, B, B, B, B, VMPst, VMPst, VPst, VAbv, O, O, -#define use_offset_0x1700u 1808 +#define use_offset_0x1700u 1816 /* Tagalog */ @@ -301,7 +313,7 @@ static const uint8_t use_table[] = { /* 1780 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 17A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 17B0 */ B, B, B, B, O, O, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre, + /* 17B0 */ B, B, B, B, CGJ, CGJ, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre, /* 17C0 */ VPre, VPre, VPre, VPre, VPre, VPre, VMAbv, VMPst, VPst, VMAbv, VMAbv, FMAbv, FAbv, CMAbv, FMAbv, VMAbv, /* 17D0 */ FMAbv, VAbv, H, FMAbv, O, O, O, O, O, O, O, O, B, FMAbv, O, O, /* 17E0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, @@ -309,7 +321,7 @@ static const uint8_t use_table[] = { /* Mongolian */ - /* 1800 */ B, O, O, O, O, O, O, B, O, O, B, O, O, O, O, O, + /* 1800 */ B, O, O, O, O, O, O, B, O, O, B, CGJ, CGJ, CGJ, O, CGJ, /* 1810 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* 1820 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1830 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, @@ -321,7 +333,7 @@ static const uint8_t use_table[] = { /* 1890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 18A0 */ B, B, B, B, B, B, B, B, B, CMBlw, B, O, O, O, O, O, -#define use_offset_0x1900u 2240 +#define use_offset_0x1900u 2248 /* Limbu */ @@ -365,7 +377,7 @@ static const uint8_t use_table[] = { /* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, /* 1A90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x1b00u 2656 +#define use_offset_0x1b00u 2664 /* Balinese */ @@ -376,7 +388,7 @@ static const uint8_t use_table[] = { /* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre, /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, B, O, O, O, /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, GB, GB, O, O, GB, - /* 1B60 */ O, S, GB, S, S, S, S, S, GB, S, S, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv, + /* 1B60 */ O, O, GB, O, O, O, O, O, GB, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv, /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, O, /* Sundanese */ @@ -401,7 +413,7 @@ static const uint8_t use_table[] = { /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FMAbv, CMBlw, O, O, O, O, O, O, O, O, /* 1C40 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, B, B, -#define use_offset_0x1cd0u 2992 +#define use_offset_0x1cd0u 3000 /* Vedic Extensions */ @@ -410,20 +422,20 @@ static const uint8_t use_table[] = { /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O, /* 1CF0 */ O, O, O, O, VMAbv, CS, CS, VMPst, VMAbv, VMAbv, GB, O, O, O, O, O, -#define use_offset_0x1df8u 3040 +#define use_offset_0x1df8u 3048 /* Combining Diacritical Marks Supplement */ O, O, O, FMAbv, O, O, O, O, -#define use_offset_0x2008u 3048 +#define use_offset_0x2008u 3056 /* General Punctuation */ - O, O, O, O, ZWNJ, O, O, O, + O, O, O, O, ZWNJ, CGJ, O, O, /* 2010 */ GB, GB, GB, GB, GB, O, O, O, -#define use_offset_0x2070u 3064 +#define use_offset_0x2070u 3072 /* Superscripts and Subscripts */ @@ -431,20 +443,20 @@ static const uint8_t use_table[] = { /* 2070 */ O, O, O, O, FMPst, O, O, O, O, O, O, O, O, O, O, O, /* 2080 */ O, O, FMPst, FMPst, FMPst, O, O, O, -#define use_offset_0x20f0u 3088 +#define use_offset_0x20f0u 3096 /* Combining Diacritical Marks for Symbols */ /* 20F0 */ VMAbv, O, O, O, O, O, O, O, -#define use_offset_0x25c8u 3096 +#define use_offset_0x25c8u 3104 /* Geometric Shapes */ O, O, O, O, B, O, O, O, -#define use_offset_0x2d30u 3104 +#define use_offset_0x2d30u 3112 /* Tifinagh */ @@ -455,7 +467,7 @@ static const uint8_t use_table[] = { /* 2D60 */ B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, B, /* 2D70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, H, -#define use_offset_0xa800u 3184 +#define use_offset_0xa800u 3192 /* Syloti Nagri */ @@ -542,7 +554,7 @@ static const uint8_t use_table[] = { /* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst, /* AAF0 */ O, O, O, O, O, VMPst, H, O, -#define use_offset_0xabc0u 3944 +#define use_offset_0xabc0u 3952 /* Meetei Mayek */ @@ -552,7 +564,25 @@ static const uint8_t use_table[] = { /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, O, O, /* ABF0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x10a00u 4008 +#define use_offset_0xfe00u 4016 + + + /* Variation Selectors */ + + /* FE00 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + +#define use_offset_0x10570u 4032 + + + /* Vithkuqi */ + + /* 10570 */ B, B, B, B, B, B, B, B, B, B, B, O, B, B, B, B, + /* 10580 */ B, B, B, B, B, B, B, B, B, B, B, O, B, B, B, B, + /* 10590 */ B, B, B, O, B, B, O, B, B, B, B, B, B, B, B, B, + /* 105A0 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 105B0 */ B, B, O, B, B, B, B, B, B, B, O, B, B, O, O, O, + +#define use_offset_0x10a00u 4112 /* Kharoshthi */ @@ -563,16 +593,16 @@ static const uint8_t use_table[] = { /* 10A30 */ B, B, B, B, B, B, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H, /* 10A40 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, -#define use_offset_0x10ac0u 4088 +#define use_offset_0x10ac0u 4192 /* Manichaean */ /* 10AC0 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B, /* 10AD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10AE0 */ B, B, B, B, B, CMBlw, CMBlw, O, + /* 10AE0 */ B, B, B, B, B, CMBlw, CMBlw, O, O, O, O, B, B, B, B, B, -#define use_offset_0x10b80u 4128 +#define use_offset_0x10b80u 4240 /* Psalter Pahlavi */ @@ -581,7 +611,7 @@ static const uint8_t use_table[] = { /* 10B90 */ B, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* 10BA0 */ O, O, O, O, O, O, O, O, O, B, B, B, B, B, B, O, -#define use_offset_0x10d00u 4176 +#define use_offset_0x10d00u 4288 /* Hanifi Rohingya */ @@ -591,7 +621,7 @@ static const uint8_t use_table[] = { /* 10D20 */ B, B, B, B, VMAbv, VMAbv, VMAbv, CMAbv, O, O, O, O, O, O, O, O, /* 10D30 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x10e80u 4240 +#define use_offset_0x10e80u 4352 /* Yezidi */ @@ -601,17 +631,22 @@ static const uint8_t use_table[] = { /* 10EA0 */ B, B, B, B, B, B, B, B, B, B, O, VAbv, VAbv, O, O, O, /* 10EB0 */ B, B, O, O, O, O, O, O, -#define use_offset_0x10f30u 4296 +#define use_offset_0x10f30u 4408 /* Sogdian */ /* 10F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 10F40 */ B, B, B, B, B, B, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, - /* 10F50 */ VMBlw, B, B, B, B, O, O, O, + /* 10F50 */ VMBlw, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O, + /* 10F60 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, -#define use_offset_0x10fb0u 4336 + /* Old Uyghur */ + /* 10F70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 10F80 */ B, B, CMBlw, CMBlw, CMBlw, CMBlw, O, O, O, O, O, O, O, O, O, O, + /* 10F90 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 10FA0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Chorasmian */ @@ -627,7 +662,7 @@ static const uint8_t use_table[] = { /* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, - /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, HVM, O, O, O, O, O, O, O, O, O, + /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, O, O, /* 11050 */ O, O, N, N, N, N, N, N, N, N, N, N, N, N, N, N, /* 11060 */ N, N, N, N, N, N, B, B, B, B, B, B, B, B, B, B, /* 11070 */ VAbv, B, B, VAbv, VAbv, B, O, O, O, O, O, O, O, O, O, HN, @@ -640,7 +675,7 @@ static const uint8_t use_table[] = { /* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O, /* 110C0 */ O, O, VBlw, O, O, O, O, O, -#define use_offset_0x11100u 4616 +#define use_offset_0x11100u 4816 /* Chakma */ @@ -678,7 +713,7 @@ static const uint8_t use_table[] = { /* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw, /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, O, -#define use_offset_0x11280u 4936 +#define use_offset_0x11280u 5136 /* Multani */ @@ -706,7 +741,7 @@ static const uint8_t use_table[] = { /* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, -#define use_offset_0x11400u 5184 +#define use_offset_0x11400u 5384 /* Newa */ @@ -729,7 +764,7 @@ static const uint8_t use_table[] = { /* 114C0 */ VMAbv, VMAbv, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O, /* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x11580u 5408 +#define use_offset_0x11580u 5608 /* Siddham */ @@ -773,7 +808,7 @@ static const uint8_t use_table[] = { /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, /* 11740 */ B, B, B, B, B, B, B, O, -#define use_offset_0x11800u 5864 +#define use_offset_0x11800u 6064 /* Dogra */ @@ -783,7 +818,7 @@ static const uint8_t use_table[] = { /* 11820 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPre, VPst, VBlw, /* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, O, O, O, O, -#define use_offset_0x11900u 5928 +#define use_offset_0x11900u 6128 /* Dives Akuru */ @@ -795,7 +830,7 @@ static const uint8_t use_table[] = { /* 11940 */ MPst, R, MPst, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, /* 11950 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x119a0u 6024 +#define use_offset_0x119a0u 6224 /* Nandinagari */ @@ -823,7 +858,7 @@ static const uint8_t use_table[] = { /* 11A80 */ B, B, B, B, R, R, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, H, O, O, O, B, O, O, -#define use_offset_0x11c00u 6280 +#define use_offset_0x11c00u 6480 /* Bhaiksuki */ @@ -844,7 +879,7 @@ static const uint8_t use_table[] = { /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, O, -#define use_offset_0x11d00u 6464 +#define use_offset_0x11d00u 6664 /* Masaram Gondi */ @@ -864,7 +899,7 @@ static const uint8_t use_table[] = { /* 11D90 */ VAbv, VAbv, O, VPst, VPst, VMAbv, VMPst, H, O, O, O, O, O, O, O, O, /* 11DA0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x11ee0u 6640 +#define use_offset_0x11ee0u 6840 /* Makasar */ @@ -872,85 +907,92 @@ static const uint8_t use_table[] = { /* 11EE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11EF0 */ B, B, GB, VAbv, VBlw, VPre, VPst, O, -#define use_offset_0x13000u 6664 +#define use_offset_0x13000u 6864 /* Egyptian Hieroglyphs */ - /* 13000 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13010 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13020 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13030 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13040 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13050 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13060 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13070 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13080 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13090 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 130A0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 130B0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 130C0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 130D0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 130E0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 130F0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13100 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13110 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13120 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13130 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13140 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13150 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13160 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13170 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13180 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13190 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 131A0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 131B0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 131C0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 131D0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 131E0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 131F0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13200 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13210 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13220 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13230 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13240 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13250 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13260 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13270 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13280 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13290 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 132A0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 132B0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 132C0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 132D0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 132E0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 132F0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13300 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13310 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13320 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13330 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13340 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13350 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13360 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13370 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13380 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13390 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 133A0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 133B0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 133C0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 133D0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 133E0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 133F0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13400 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13410 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - /* 13420 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, O, + /* 13000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13030 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13040 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13050 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13060 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13070 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13080 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 130A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 130B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 130C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 130D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 130E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 130F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13130 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13140 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13170 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13180 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 131A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 131B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 131C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 131D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 131E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 131F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13210 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13220 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13230 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13240 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13250 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13260 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13270 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13280 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 132A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 132B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 132C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 132D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 132E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 132F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13300 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13310 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13320 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13330 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13340 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13350 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13360 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13370 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13380 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13390 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 133A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 133B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 133C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 133D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 133E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 133F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 13420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, /* Egyptian Hieroglyph Format Controls */ - /* 13430 */ J, J, J, J, J, J, J, SB, SE, O, O, O, O, O, O, O, + /* 13430 */ H, H, H, H, H, H, H, B, B, O, O, O, O, O, O, O, + +#define use_offset_0x16ac0u 7952 -#define use_offset_0x16b00u 7752 + /* Tangsa */ + + /* 16AC0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 16AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 16AE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 16AF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Pahawh Hmong */ @@ -959,7 +1001,7 @@ static const uint8_t use_table[] = { /* 16B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 16B30 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, -#define use_offset_0x16f00u 7808 +#define use_offset_0x16f00u 8072 /* Miao */ @@ -975,14 +1017,14 @@ static const uint8_t use_table[] = { /* 16F80 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, O, O, O, O, O, O, O, VMBlw, /* 16F90 */ VMBlw, VMBlw, VMBlw, O, O, O, O, O, -#define use_offset_0x16fe0u 7960 +#define use_offset_0x16fe0u 8224 /* Ideographic Symbols and Punctuation */ /* 16FE0 */ O, O, O, O, B, O, O, O, -#define use_offset_0x18b00u 7968 +#define use_offset_0x18b00u 8232 /* Khitan Small Script */ @@ -1018,7 +1060,7 @@ static const uint8_t use_table[] = { /* 18CC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 18CD0 */ B, B, B, B, B, B, O, O, -#define use_offset_0x1bc00u 8440 +#define use_offset_0x1bc00u 8704 /* Duployan */ @@ -1034,7 +1076,7 @@ static const uint8_t use_table[] = { /* 1BC80 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, /* 1BC90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, CMBlw, CMBlw, O, -#define use_offset_0x1e100u 8600 +#define use_offset_0x1e100u 8864 /* Nyiakeng Puachue Hmong */ @@ -1045,8 +1087,14 @@ static const uint8_t use_table[] = { /* 1E130 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, O, O, /* 1E140 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, B, B, -#define use_offset_0x1e2c0u 8680 +#define use_offset_0x1e290u 8944 + + + /* Toto */ + /* 1E290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 1E2A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, O, + /* 1E2B0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Wancho */ @@ -1055,7 +1103,7 @@ static const uint8_t use_table[] = { /* 1E2E0 */ B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv, /* 1E2F0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x1e900u 8744 +#define use_offset_0x1e900u 9056 /* Adlam */ @@ -1067,7 +1115,28 @@ static const uint8_t use_table[] = { /* 1E940 */ B, B, B, B, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, B, O, O, O, O, /* 1E950 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -}; /* Table items: 8840; occupancy: 79% */ +#define use_offset_0xe0100u 9152 + + + /* Variation Selectors Supplement */ + + /* E0100 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E0110 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E0120 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E0130 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E0140 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E0150 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E0160 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E0170 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E0180 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E0190 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E01A0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E01B0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E01C0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E01D0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + /* E01E0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, + +}; /* Table items: 9392; occupancy: 79% */ static inline uint8_t hb_use_get_category (hb_codepoint_t u) @@ -1077,6 +1146,7 @@ hb_use_get_category (hb_codepoint_t u) case 0x0u: if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u]; if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u]; + if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u]; if (hb_in_range<hb_codepoint_t> (u, 0x0640u, 0x0647u)) return use_table[u - 0x0640u + use_offset_0x0640u]; if (hb_in_range<hb_codepoint_t> (u, 0x07C8u, 0x07FFu)) return use_table[u - 0x07C8u + use_offset_0x07c8u]; if (hb_in_range<hb_codepoint_t> (u, 0x0840u, 0x085Fu)) return use_table[u - 0x0840u + use_offset_0x0840u]; @@ -1106,18 +1176,22 @@ hb_use_get_category (hb_codepoint_t u) if (hb_in_range<hb_codepoint_t> (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u]; break; + case 0xFu: + if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u]; + break; + case 0x10u: + if (hb_in_range<hb_codepoint_t> (u, 0x10570u, 0x105BFu)) return use_table[u - 0x10570u + use_offset_0x10570u]; if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A4Fu)) return use_table[u - 0x10A00u + use_offset_0x10a00u]; - if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AE7u)) return use_table[u - 0x10AC0u + use_offset_0x10ac0u]; + if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return use_table[u - 0x10AC0u + use_offset_0x10ac0u]; if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return use_table[u - 0x10B80u + use_offset_0x10b80u]; if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D3Fu)) return use_table[u - 0x10D00u + use_offset_0x10d00u]; if (hb_in_range<hb_codepoint_t> (u, 0x10E80u, 0x10EB7u)) return use_table[u - 0x10E80u + use_offset_0x10e80u]; - if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10F57u)) return use_table[u - 0x10F30u + use_offset_0x10f30u]; - if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x110C7u)) return use_table[u - 0x10FB0u + use_offset_0x10fb0u]; + if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u]; break; case 0x11u: - if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x110C7u)) return use_table[u - 0x10FB0u + use_offset_0x10fb0u]; + if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u]; if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u]; if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u]; if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u]; @@ -1135,7 +1209,7 @@ hb_use_get_category (hb_codepoint_t u) break; case 0x16u: - if (hb_in_range<hb_codepoint_t> (u, 0x16B00u, 0x16B37u)) return use_table[u - 0x16B00u + use_offset_0x16b00u]; + if (hb_in_range<hb_codepoint_t> (u, 0x16AC0u, 0x16B37u)) return use_table[u - 0x16AC0u + use_offset_0x16ac0u]; if (hb_in_range<hb_codepoint_t> (u, 0x16F00u, 0x16F97u)) return use_table[u - 0x16F00u + use_offset_0x16f00u]; if (hb_in_range<hb_codepoint_t> (u, 0x16FE0u, 0x16FE7u)) return use_table[u - 0x16FE0u + use_offset_0x16fe0u]; break; @@ -1150,10 +1224,14 @@ hb_use_get_category (hb_codepoint_t u) case 0x1Eu: if (hb_in_range<hb_codepoint_t> (u, 0x1E100u, 0x1E14Fu)) return use_table[u - 0x1E100u + use_offset_0x1e100u]; - if (hb_in_range<hb_codepoint_t> (u, 0x1E2C0u, 0x1E2FFu)) return use_table[u - 0x1E2C0u + use_offset_0x1e2c0u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1E290u, 0x1E2FFu)) return use_table[u - 0x1E290u + use_offset_0x1e290u]; if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E95Fu)) return use_table[u - 0x1E900u + use_offset_0x1e900u]; break; + case 0xE0u: + if (hb_in_range<hb_codepoint_t> (u, 0xE0100u, 0xE01EFu)) return use_table[u - 0xE0100u + use_offset_0xe0100u]; + break; + default: break; } @@ -1161,6 +1239,7 @@ hb_use_get_category (hb_codepoint_t u) } #undef B +#undef CGJ #undef CS #undef G #undef GB @@ -1171,7 +1250,6 @@ hb_use_get_category (hb_codepoint_t u) #undef N #undef O #undef R -#undef S #undef SB #undef SE #undef SUB diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc index 1e4804c4a2..70b637933d 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc @@ -257,7 +257,6 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, use_syllable_type_t syllable_type = (use_syllable_type_t) (info[start].syllable() & 0x0F); switch (syllable_type) { - case use_independent_cluster: case use_symbol_cluster: case use_hieroglyph_cluster: case use_non_cluster: diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc index 778b5b8bd8..839cc9122c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc @@ -171,7 +171,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor hb_codepoint_t u = buffer->cur().codepoint; hb_codepoint_t glyph = 0; - if (shortest && c->font->get_nominal_glyph (u, &glyph)) + if (shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found)) { next_char (buffer, glyph); return; @@ -183,7 +183,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor return; } - if (!shortest && c->font->get_nominal_glyph (u, &glyph)) + if (!shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found)) { next_char (buffer, glyph); return; @@ -312,6 +312,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, buffer, font, buffer->unicode, + buffer->not_found, plan->shaper->decompose ? plan->shaper->decompose : decompose_unicode, plan->shaper->compose ? plan->shaper->compose : compose_unicode }; diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.hh b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.hh index 04f1a80091..12c78a2352 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.hh @@ -56,6 +56,7 @@ struct hb_ot_shape_normalize_context_t hb_buffer_t *buffer; hb_font_t *font; hb_unicode_funcs_t *unicode; + const hb_codepoint_t not_found; bool (*decompose) (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t ab, hb_codepoint_t *a, diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc index 0e215c24f7..4e8a4bc3d1 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc @@ -150,23 +150,25 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, */ #ifndef HB_NO_AAT_SHAPE - bool has_gsub = hb_ot_layout_has_substitution (face); + bool has_kerx = hb_aat_layout_has_positioning (face); + bool has_gsub = !apply_morx && hb_ot_layout_has_substitution (face); #endif bool has_gpos = !disable_gpos && hb_ot_layout_has_positioning (face); if (false) ; #ifndef HB_NO_AAT_SHAPE - else if (hb_aat_layout_has_positioning (face) && !(has_gsub && has_gpos)) + /* Prefer GPOS over kerx if GSUB is present; + * https://github.com/harfbuzz/harfbuzz/issues/3008 */ + else if (has_kerx && !(has_gsub && has_gpos)) plan.apply_kerx = true; #endif - else if (!apply_morx && has_gpos) + else if (has_gpos) plan.apply_gpos = true; if (!plan.apply_kerx && (!has_gpos_kern || !plan.apply_gpos)) { - /* Apparently Apple applies kerx if GPOS kern was not applied. */ #ifndef HB_NO_AAT_SHAPE - if (hb_aat_layout_has_positioning (face)) + if (has_kerx) plan.apply_kerx = true; else #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-var-common.hh b/thirdparty/harfbuzz/src/hb-ot-var-common.hh new file mode 100644 index 0000000000..0eafb949d5 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-ot-var-common.hh @@ -0,0 +1,264 @@ +/* + * Copyright © 2021 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + */ + +#ifndef HB_OT_VAR_COMMON_HH +#define HB_OT_VAR_COMMON_HH + +#include "hb-ot-layout-common.hh" + + +namespace OT { + +struct DeltaSetIndexMapFormat0 +{ + friend struct DeltaSetIndexMap; + + private: + DeltaSetIndexMapFormat0* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + auto *out = c->start_embed (this); + if (unlikely (!out)) return_trace (nullptr); + + unsigned total_size = min_size + mapCount * get_width (); + HBUINT8 *p = c->allocate_size<HBUINT8> (total_size); + if (unlikely (!p)) return_trace (nullptr); + + memcpy (p, this, HBUINT8::static_size * total_size); + return_trace (out); + } + + template <typename T> + bool serialize (hb_serialize_context_t *c, const T &plan) + { + unsigned int width = plan.get_width (); + unsigned int inner_bit_count = plan.get_inner_bit_count (); + const hb_array_t<const uint32_t> output_map = plan.get_output_map (); + + TRACE_SERIALIZE (this); + if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0)))) + return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); + + entryFormat = ((width-1)<<4)|(inner_bit_count-1); + mapCount = output_map.length; + HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length); + if (unlikely (!p)) return_trace (false); + for (unsigned int i = 0; i < output_map.length; i++) + { + unsigned int v = output_map[i]; + unsigned int outer = v >> 16; + unsigned int inner = v & 0xFFFF; + unsigned int u = (outer << inner_bit_count) | inner; + for (unsigned int w = width; w > 0;) + { + p[--w] = u; + u >>= 8; + } + p += width; + } + return_trace (true); + } + + uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */ + { + /* If count is zero, pass value unchanged. This takes + * care of direct mapping for advance map. */ + if (!mapCount) + return v; + + if (v >= mapCount) + v = mapCount - 1; + + unsigned int u = 0; + { /* Fetch it. */ + unsigned int w = get_width (); + const HBUINT8 *p = mapDataZ.arrayZ + w * v; + for (; w; w--) + u = (u << 8) + *p++; + } + + { /* Repack it. */ + unsigned int n = get_inner_bit_count (); + unsigned int outer = u >> n; + unsigned int inner = u & ((1 << n) - 1); + u = (outer<<16) | inner; + } + + return u; + } + + unsigned get_map_count () const { return mapCount; } + unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; } + unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; } + + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_range (mapDataZ.arrayZ, + mapCount, + get_width ())); + } + + protected: + HBUINT8 format; /* Format identifier--format = 0 */ + HBUINT8 entryFormat; /* A packed field that describes the compressed + * representation of delta-set indices. */ + HBUINT16 mapCount; /* The number of mapping entries. */ + UnsizedArrayOf<HBUINT8> + mapDataZ; /* The delta-set index mapping data. */ + + public: + DEFINE_SIZE_ARRAY (4, mapDataZ); +}; + +struct DeltaSetIndexMapFormat1 +{ + friend struct DeltaSetIndexMap; + + private: + DeltaSetIndexMapFormat1* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + auto *out = c->start_embed (this); + if (unlikely (!out)) return_trace (nullptr); + + unsigned total_size = min_size + mapCount * get_width (); + HBUINT8 *p = c->allocate_size<HBUINT8> (total_size); + if (unlikely (!p)) return_trace (nullptr); + + memcpy (p, this, HBUINT8::static_size * total_size); + return_trace (out); + } + + unsigned get_map_count () const { return mapCount; } + unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; } + unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_range (mapDataZ.arrayZ, + mapCount, + get_width ())); + } + + protected: + HBUINT8 format; /* Format identifier--format = 1 */ + HBUINT8 entryFormat; /* A packed field that describes the compressed + * representation of delta-set indices. */ + HBUINT32 mapCount; /* The number of mapping entries. */ + UnsizedArrayOf<HBUINT8> + mapDataZ; /* The delta-set index mapping data. */ + + public: + DEFINE_SIZE_ARRAY (6, mapDataZ); +}; + +struct DeltaSetIndexMap +{ + template <typename T> + bool serialize (hb_serialize_context_t *c, const T &plan) + { + TRACE_SERIALIZE (this); + switch (u.format) { + case 0: return_trace (u.format0.serialize (c, plan)); + default:return_trace (false); + } + } + + uint32_t map (unsigned v) const + { + switch (u.format) { + case 0: return (u.format0.map (v)); + default:return v; + } + } + + unsigned get_map_count () const + { + switch (u.format) { + case 0: return u.format0.get_map_count (); + case 1: return u.format1.get_map_count (); + default:return 0; + } + } + + unsigned get_width () const + { + switch (u.format) { + case 0: return u.format0.get_width (); + case 1: return u.format1.get_width (); + default:return 0; + } + } + + unsigned get_inner_bit_count () const + { + switch (u.format) { + case 0: return u.format0.get_inner_bit_count (); + case 1: return u.format1.get_inner_bit_count (); + default:return 0; + } + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) { + case 0: return_trace (u.format0.sanitize (c)); + case 1: return_trace (u.format1.sanitize (c)); + default:return_trace (true); + } + } + + DeltaSetIndexMap* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + switch (u.format) { + case 0: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c))); + case 1: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c))); + default:return_trace (nullptr); + } + } + + protected: + union { + HBUINT8 format; /* Format identifier */ + DeltaSetIndexMapFormat0 format0; + DeltaSetIndexMapFormat1 format1; + } u; + public: + DEFINE_SIZE_UNION (1, format); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_COMMON_HH */ diff --git a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh index 72217e7f29..074b6a3785 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh @@ -28,97 +28,11 @@ #define HB_OT_VAR_HVAR_TABLE_HH #include "hb-ot-layout-common.hh" - +#include "hb-ot-var-common.hh" namespace OT { -struct DeltaSetIndexMap -{ - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - c->check_range (mapDataZ.arrayZ, - mapCount, - get_width ())); - } - - template <typename T> - bool serialize (hb_serialize_context_t *c, const T &plan) - { - unsigned int width = plan.get_width (); - unsigned int inner_bit_count = plan.get_inner_bit_count (); - const hb_array_t<const uint32_t> output_map = plan.get_output_map (); - - TRACE_SERIALIZE (this); - if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0)))) - return_trace (false); - if (unlikely (!c->extend_min (this))) return_trace (false); - - format = ((width-1)<<4)|(inner_bit_count-1); - mapCount = output_map.length; - HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length); - if (unlikely (!p)) return_trace (false); - for (unsigned int i = 0; i < output_map.length; i++) - { - unsigned int v = output_map[i]; - unsigned int outer = v >> 16; - unsigned int inner = v & 0xFFFF; - unsigned int u = (outer << inner_bit_count) | inner; - for (unsigned int w = width; w > 0;) - { - p[--w] = u; - u >>= 8; - } - p += width; - } - return_trace (true); - } - - uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */ - { - /* If count is zero, pass value unchanged. This takes - * care of direct mapping for advance map. */ - if (!mapCount) - return v; - - if (v >= mapCount) - v = mapCount - 1; - - unsigned int u = 0; - { /* Fetch it. */ - unsigned int w = get_width (); - const HBUINT8 *p = mapDataZ.arrayZ + w * v; - for (; w; w--) - u = (u << 8) + *p++; - } - - { /* Repack it. */ - unsigned int n = get_inner_bit_count (); - unsigned int outer = u >> n; - unsigned int inner = u & ((1 << n) - 1); - u = (outer<<16) | inner; - } - - return u; - } - - unsigned int get_map_count () const { return mapCount; } - unsigned int get_width () const { return ((format >> 4) & 3) + 1; } - unsigned int get_inner_bit_count () const { return (format & 0xF) + 1; } - - protected: - HBUINT16 format; /* A packed field that describes the compressed - * representation of delta-set indices. */ - HBUINT16 mapCount; /* The number of mapping entries. */ - UnsizedArrayOf<HBUINT8> - mapDataZ; /* The delta-set index mapping data. */ - - public: - DEFINE_SIZE_ARRAY (4, mapDataZ); -}; - struct index_map_subset_plan_t { enum index_map_index_t { diff --git a/thirdparty/harfbuzz/src/hb-ot-vorg-table.hh b/thirdparty/harfbuzz/src/hb-ot-vorg-table.hh index efa7737d6f..811e13919e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-vorg-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-vorg-table.hh @@ -48,7 +48,7 @@ struct VertOriginMetric } public: - HBGlyphID glyph; + HBGlyphID16 glyph; FWORD vertOriginY; public: diff --git a/thirdparty/harfbuzz/src/hb-repacker.hh b/thirdparty/harfbuzz/src/hb-repacker.hh index b02128b5c4..26faa56ea8 100644 --- a/thirdparty/harfbuzz/src/hb-repacker.hh +++ b/thirdparty/harfbuzz/src/hb-repacker.hh @@ -33,6 +33,10 @@ #include "hb-serialize.hh" #include "hb-vector.hh" +/* + * For a detailed writeup on the overflow resolution algorithm see: + * docs/repacker.md + */ struct graph_t { @@ -40,23 +44,58 @@ struct graph_t { vertex_t () : distance (0), - incoming_edges (0), + space (0), + parents (), start (0), end (0), priority(0) {} - void fini () { obj.fini (); } + void fini () { + obj.fini (); + parents.fini (); + } hb_serialize_context_t::object_t obj; int64_t distance; - unsigned incoming_edges; + int64_t space; + hb_vector_t<unsigned> parents; unsigned start; unsigned end; unsigned priority; bool is_shared () const { - return incoming_edges > 1; + return parents.length > 1; + } + + unsigned incoming_edges () const + { + return parents.length; + } + + void remove_parent (unsigned parent_index) + { + for (unsigned i = 0; i < parents.length; i++) + { + if (parents[i] != parent_index) continue; + parents.remove (i); + break; + } + } + + void remap_parents (const hb_vector_t<unsigned>& id_map) + { + for (unsigned i = 0; i < parents.length; i++) + parents[i] = id_map[parents[i]]; + } + + void remap_parent (unsigned old_index, unsigned new_index) + { + for (unsigned i = 0; i < parents.length; i++) + { + if (parents[i] == old_index) + parents[i] = new_index; + } } bool is_leaf () const @@ -77,7 +116,7 @@ struct graph_t int64_t modified_distance = hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFF); - return (modified_distance << 24) | (0x00FFFFFF & order); + return (modified_distance << 22) | (0x003FFFFF & order); } int64_t distance_modifier () const @@ -91,34 +130,7 @@ struct graph_t struct overflow_record_t { unsigned parent; - const hb_serialize_context_t::object_t::link_t* link; - }; - - struct clone_buffer_t - { - clone_buffer_t () : head (nullptr), tail (nullptr) {} - - bool copy (const hb_serialize_context_t::object_t& object) - { - fini (); - unsigned size = object.tail - object.head; - head = (char*) hb_malloc (size); - if (!head) return false; - - memcpy (head, object.head, size); - tail = head + size; - return true; - } - - char* head; - char* tail; - - void fini () - { - if (!head) return; - hb_free (head); - head = nullptr; - } + unsigned child; }; /* @@ -129,11 +141,12 @@ struct graph_t * serializer */ graph_t (const hb_vector_t<hb_serialize_context_t::object_t *>& objects) - : edge_count_invalid (true), + : parents_invalid (true), distance_invalid (true), positions_invalid (true), successful (true) { + num_roots_for_space_.push (1); bool removed_nil = false; for (unsigned i = 0; i < objects.length; i++) { @@ -160,12 +173,13 @@ struct graph_t ~graph_t () { vertices_.fini_deep (); - clone_buffers_.fini_deep (); } bool in_error () const { - return !successful || vertices_.in_error () || clone_buffers_.in_error (); + return !successful || + vertices_.in_error () || + num_roots_for_space_.in_error (); } const vertex_t& root () const @@ -226,12 +240,13 @@ struct graph_t hb_vector_t<unsigned> queue; hb_vector_t<vertex_t> sorted_graph; + if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return; hb_vector_t<unsigned> id_map; if (unlikely (!check_success (id_map.resize (vertices_.length)))) return; hb_vector_t<unsigned> removed_edges; if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return; - update_incoming_edge_count (); + update_parents (); queue.push (root_idx ()); int new_id = vertices_.length - 1; @@ -242,12 +257,12 @@ struct graph_t queue.remove (0); vertex_t& next = vertices_[next_id]; - sorted_graph.push (next); + sorted_graph[new_id] = next; id_map[next_id] = new_id--; for (const auto& link : next.obj.links) { removed_edges[link.objidx]++; - if (!(vertices_[link.objidx].incoming_edges - removed_edges[link.objidx])) + if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx])) queue.push (link.objidx); } } @@ -255,14 +270,11 @@ struct graph_t check_success (!queue.in_error ()); check_success (!sorted_graph.in_error ()); if (!check_success (new_id == -1)) - DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected."); - - remap_obj_indices (id_map, &sorted_graph); + print_orphaned_nodes (); - sorted_graph.as_array ().reverse (); + remap_all_obj_indices (id_map, &sorted_graph); - vertices_.fini_deep (); - vertices_ = sorted_graph; + hb_swap (vertices_, sorted_graph); sorted_graph.fini_deep (); } @@ -283,12 +295,13 @@ struct graph_t hb_priority_queue_t queue; hb_vector_t<vertex_t> sorted_graph; + if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return; hb_vector_t<unsigned> id_map; if (unlikely (!check_success (id_map.resize (vertices_.length)))) return; hb_vector_t<unsigned> removed_edges; if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return; - update_incoming_edge_count (); + update_parents (); queue.insert (root ().modified_distance (0), root_idx ()); int new_id = root_idx (); @@ -298,12 +311,12 @@ struct graph_t unsigned next_id = queue.pop_minimum().second; vertex_t& next = vertices_[next_id]; - sorted_graph.push (next); + sorted_graph[new_id] = next; id_map[next_id] = new_id--; for (const auto& link : next.obj.links) { removed_edges[link.objidx]++; - if (!(vertices_[link.objidx].incoming_edges - removed_edges[link.objidx])) + if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx])) // Add the order that the links were encountered to the priority. // This ensures that ties between priorities objects are broken in a consistent // way. More specifically this is set up so that if a set of objects have the same @@ -317,66 +330,264 @@ struct graph_t check_success (!queue.in_error ()); check_success (!sorted_graph.in_error ()); if (!check_success (new_id == -1)) - DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected."); - - remap_obj_indices (id_map, &sorted_graph); + print_orphaned_nodes (); - sorted_graph.as_array ().reverse (); + remap_all_obj_indices (id_map, &sorted_graph); - vertices_.fini_deep (); - vertices_ = sorted_graph; + hb_swap (vertices_, sorted_graph); sorted_graph.fini_deep (); } /* - * Creates a copy of child and re-assigns the link from - * parent to the clone. The copy is a shallow copy, objects - * linked from child are not duplicated. + * Assign unique space numbers to each connected subgraph of 32 bit offset(s). */ - void duplicate (unsigned parent_idx, unsigned child_idx) + bool assign_32bit_spaces () { - DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d", - parent_idx, child_idx); + unsigned root_index = root_idx (); + hb_set_t visited; + hb_set_t roots; + for (unsigned i = 0; i <= root_index; i++) + { + for (auto& l : vertices_[i].obj.links) + { + if (l.width == 4 && !l.is_signed) + { + roots.add (l.objidx); + find_subgraph (l.objidx, visited); + } + } + } + + // Mark everything not in the subgraphs of 32 bit roots as visited. + // This prevents 32 bit subgraphs from being connected via nodes not in the 32 bit subgraphs. + visited.invert (); + + if (!roots) return false; + + while (roots) + { + unsigned next = HB_SET_VALUE_INVALID; + if (!roots.next (&next)) break; + + hb_set_t connected_roots; + find_connected_nodes (next, roots, visited, connected_roots); + isolate_subgraph (connected_roots); + + unsigned next_space = this->next_space (); + num_roots_for_space_.push (0); + for (unsigned root : connected_roots) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Subgraph %u gets space %u", root, next_space); + vertices_[root].space = next_space; + num_roots_for_space_[next_space] = num_roots_for_space_[next_space] + 1; + distance_invalid = true; + positions_invalid = true; + } + + // TODO(grieger): special case for GSUB/GPOS use extension promotions to move 16 bit space + // into the 32 bit space as needed, instead of using isolation. + } + + return true; + } + + /* + * Isolates the subgraph of nodes reachable from root. Any links to nodes in the subgraph + * that originate from outside of the subgraph will be removed by duplicating the linked to + * object. + * + * Indices stored in roots will be updated if any of the roots are duplicated to new indices. + */ + bool isolate_subgraph (hb_set_t& roots) + { + update_parents (); + hb_hashmap_t<unsigned, unsigned> subgraph; + + // incoming edges to root_idx should be all 32 bit in length so we don't need to de-dup these + // set the subgraph incoming edge count to match all of root_idx's incoming edges + hb_set_t parents; + for (unsigned root_idx : roots) + { + subgraph.set (root_idx, wide_parents (root_idx, parents)); + find_subgraph (root_idx, subgraph); + } + + unsigned original_root_idx = root_idx (); + hb_hashmap_t<unsigned, unsigned> index_map; + bool made_changes = false; + for (auto entry : subgraph.iter ()) + { + const auto& node = vertices_[entry.first]; + unsigned subgraph_incoming_edges = entry.second; + + if (subgraph_incoming_edges < node.incoming_edges ()) + { + // Only de-dup objects with incoming links from outside the subgraph. + made_changes = true; + duplicate_subgraph (entry.first, index_map); + } + } + + if (!made_changes) + return false; + if (original_root_idx != root_idx () + && parents.has (original_root_idx)) + { + // If the root idx has changed since parents was determined, update root idx in parents + parents.add (root_idx ()); + parents.del (original_root_idx); + } + + auto new_subgraph = + + subgraph.keys () + | hb_map([&] (unsigned node_idx) { + if (index_map.has (node_idx)) return index_map[node_idx]; + return node_idx; + }) + ; + + remap_obj_indices (index_map, new_subgraph); + remap_obj_indices (index_map, parents.iter (), true); + + // Update roots set with new indices as needed. + unsigned next = HB_SET_VALUE_INVALID; + while (roots.next (&next)) + { + if (index_map.has (next)) + { + roots.del (next); + roots.add (index_map[next]); + } + } + + return true; + } + + void find_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& subgraph) + { + for (const auto& link : vertices_[node_idx].obj.links) + { + if (subgraph.has (link.objidx)) + { + subgraph.set (link.objidx, subgraph[link.objidx] + 1); + continue; + } + subgraph.set (link.objidx, 1); + find_subgraph (link.objidx, subgraph); + } + } + + void find_subgraph (unsigned node_idx, hb_set_t& subgraph) + { + if (subgraph.has (node_idx)) return; + subgraph.add (node_idx); + for (const auto& link : vertices_[node_idx].obj.links) + find_subgraph (link.objidx, subgraph); + } + + /* + * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign + * links. index_map is updated with mappings from old id to new id. If a duplication has already + * been performed for a given index, then it will be skipped. + */ + void duplicate_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& index_map) + { + if (index_map.has (node_idx)) + return; + + index_map.set (node_idx, duplicate (node_idx)); + for (const auto& l : object (node_idx).links) { + duplicate_subgraph (l.objidx, index_map); + } + } + + /* + * Creates a copy of node_idx and returns it's new index. + */ + unsigned duplicate (unsigned node_idx) + { positions_invalid = true; + distance_invalid = true; auto* clone = vertices_.push (); - auto& child = vertices_[child_idx]; - clone_buffer_t* buffer = clone_buffers_.push (); - if (vertices_.in_error () - || clone_buffers_.in_error () - || !check_success (buffer->copy (child.obj))) { - return; + auto& child = vertices_[node_idx]; + if (vertices_.in_error ()) { + return -1; } - clone->obj.head = buffer->head; - clone->obj.tail = buffer->tail; + clone->obj.head = child.obj.head; + clone->obj.tail = child.obj.tail; clone->distance = child.distance; + clone->space = child.space; + clone->parents.reset (); + unsigned clone_idx = vertices_.length - 2; for (const auto& l : child.obj.links) + { clone->obj.links.push (l); + vertices_[l.objidx].parents.push (clone_idx); + } check_success (!clone->obj.links.in_error ()); + // The last object is the root of the graph, so swap back the root to the end. + // The root's obj idx does change, however since it's root nothing else refers to it. + // all other obj idx's will be unaffected. + vertex_t root = vertices_[vertices_.length - 2]; + vertices_[clone_idx] = *clone; + vertices_[vertices_.length - 1] = root; + + // Since the root moved, update the parents arrays of all children on the root. + for (const auto& l : root.obj.links) + vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ()); + + return clone_idx; + } + + /* + * Creates a copy of child and re-assigns the link from + * parent to the clone. The copy is a shallow copy, objects + * linked from child are not duplicated. + */ + bool duplicate (unsigned parent_idx, unsigned child_idx) + { + update_parents (); + + unsigned links_to_child = 0; + for (const auto& l : vertices_[parent_idx].obj.links) + { + if (l.objidx == child_idx) links_to_child++; + } + + if (vertices_[child_idx].incoming_edges () <= links_to_child) + { + // Can't duplicate this node, doing so would orphan the original one as all remaining links + // to child are from parent. + DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d", + parent_idx, child_idx); + return false; + } + + DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d", + parent_idx, child_idx); + + unsigned clone_idx = duplicate (child_idx); + if (clone_idx == (unsigned) -1) return false; + // duplicate shifts the root node idx, so if parent_idx was root update it. + if (parent_idx == clone_idx) parent_idx++; + auto& parent = vertices_[parent_idx]; - unsigned clone_idx = vertices_.length - 2; for (unsigned i = 0; i < parent.obj.links.length; i++) { auto& l = parent.obj.links[i]; - if (l.objidx == child_idx) - { - l.objidx = clone_idx; - clone->incoming_edges++; - child.incoming_edges--; - } + if (l.objidx != child_idx) + continue; + + reassign_link (l, parent_idx, clone_idx); } - // The last object is the root of the graph, so swap back the root to the end. - // The root's obj idx does change, however since it's root nothing else refers to it. - // all other obj idx's will be unaffected. - vertex_t root = vertices_[vertices_.length - 2]; - vertices_[vertices_.length - 2] = *clone; - vertices_[vertices_.length - 1] = root; + return true; } /* @@ -414,7 +625,7 @@ struct graph_t overflow_record_t r; r.parent = parent_idx; - r.link = &link; + r.child = link.objidx; overflows->push (r); } } @@ -423,48 +634,134 @@ struct graph_t return overflows->length; } + void print_orphaned_nodes () + { + if (!DEBUG_ENABLED(SUBSET_REPACK)) return; + + DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected."); + parents_invalid = true; + update_parents(); + + for (unsigned i = 0; i < root_idx (); i++) + { + const auto& v = vertices_[i]; + if (!v.parents) + DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i); + } + } + void print_overflows (const hb_vector_t<overflow_record_t>& overflows) { if (!DEBUG_ENABLED(SUBSET_REPACK)) return; - update_incoming_edge_count (); + update_parents (); for (const auto& o : overflows) { - const auto& child = vertices_[o.link->objidx]; - DEBUG_MSG (SUBSET_REPACK, nullptr, " overflow from %d => %d (%d incoming , %d outgoing)", + const auto& parent = vertices_[o.parent]; + const auto& child = vertices_[o.child]; + DEBUG_MSG (SUBSET_REPACK, nullptr, + " overflow from " + "%4d (%4d in, %4d out, space %2d) => " + "%4d (%4d in, %4d out, space %2d)", o.parent, - o.link->objidx, - child.incoming_edges, - child.obj.links.length); + parent.incoming_edges (), + parent.obj.links.length, + space_for (o.parent), + o.child, + child.incoming_edges (), + child.obj.links.length, + space_for (o.child)); } } + unsigned num_roots_for_space (unsigned space) const + { + return num_roots_for_space_[space]; + } + + unsigned next_space () const + { + return num_roots_for_space_.length; + } + + void move_to_new_space (unsigned index) + { + auto& node = vertices_[index]; + num_roots_for_space_.push (1); + num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1; + node.space = num_roots_for_space_.length - 1; + } + + unsigned space_for (unsigned index, unsigned* root = nullptr) const + { + const auto& node = vertices_[index]; + if (node.space) + { + if (root != nullptr) + *root = index; + return node.space; + } + + if (!node.parents) + { + if (root) + *root = index; + return 0; + } + + return space_for (node.parents[0], root); + } + void err_other_error () { this->successful = false; } private: + /* + * Returns the numbers of incoming edges that are 32bits wide. + */ + unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const + { + unsigned count = 0; + hb_set_t visited; + for (unsigned p : vertices_[node_idx].parents) + { + if (visited.has (p)) continue; + visited.add (p); + + for (const auto& l : vertices_[p].obj.links) + { + if (l.objidx == node_idx && l.width == 4 && !l.is_signed) + { + count++; + parents.add (p); + } + } + } + return count; + } + bool check_success (bool success) { return this->successful && (success || (err_other_error (), false)); } /* * Creates a map from objid to # of incoming edges. */ - void update_incoming_edge_count () + void update_parents () { - if (!edge_count_invalid) return; + if (!parents_invalid) return; for (unsigned i = 0; i < vertices_.length; i++) - vertices_[i].incoming_edges = 0; + vertices_[i].parents.reset (); - for (const vertex_t& v : vertices_) + for (unsigned p = 0; p < vertices_.length; p++) { - for (auto& l : v.obj.links) + for (auto& l : vertices_[p].obj.links) { - vertices_[l.objidx].incoming_edges++; + vertices_[l.objidx].parents.push (p); } } - edge_count_invalid = false; + parents_invalid = false; } /* @@ -515,23 +812,25 @@ struct graph_t hb_priority_queue_t queue; queue.insert (0, vertices_.length - 1); - hb_set_t visited; + hb_vector_t<bool> visited; + visited.resize (vertices_.length); while (!queue.in_error () && !queue.is_empty ()) { unsigned next_idx = queue.pop_minimum ().second; - if (visited.has (next_idx)) continue; + if (visited[next_idx]) continue; const auto& next = vertices_[next_idx]; int64_t next_distance = vertices_[next_idx].distance; - visited.add (next_idx); + visited[next_idx] = true; for (const auto& link : next.obj.links) { - if (visited.has (link.objidx)) continue; + if (visited[link.objidx]) continue; const auto& child = vertices_[link.objidx].obj; - int64_t child_weight = child.tail - child.head + - ((int64_t) 1 << (link.width * 8)); + unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide + int64_t child_weight = (child.tail - child.head) + + ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1); int64_t child_distance = next_distance + child_weight; if (child_distance < vertices_[link.objidx].distance) @@ -545,7 +844,7 @@ struct graph_t check_success (!queue.in_error ()); if (!check_success (queue.is_empty ())) { - DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected."); + print_orphaned_nodes (); return; } @@ -576,6 +875,10 @@ struct graph_t bool is_valid_offset (int64_t offset, const hb_serialize_context_t::object_t::link_t& link) const { + if (unlikely (!link.width)) + // Virtual links can't overflow. + return link.is_signed || offset >= 0; + if (link.is_signed) { if (link.width == 4) @@ -595,13 +898,50 @@ struct graph_t } /* + * Updates a link in the graph to point to a different object. Corrects the + * parents vector on the previous and new child nodes. + */ + void reassign_link (hb_serialize_context_t::object_t::link_t& link, + unsigned parent_idx, + unsigned new_idx) + { + unsigned old_idx = link.objidx; + link.objidx = new_idx; + vertices_[old_idx].remove_parent (parent_idx); + vertices_[new_idx].parents.push (parent_idx); + } + + /* + * Updates all objidx's in all links using the provided mapping. Corrects incoming edge counts. + */ + template<typename Iterator, hb_requires (hb_is_iterator (Iterator))> + void remap_obj_indices (const hb_hashmap_t<unsigned, unsigned>& id_map, + Iterator subgraph, + bool only_wide = false) + { + if (!id_map) return; + for (unsigned i : subgraph) + { + for (unsigned j = 0; j < vertices_[i].obj.links.length; j++) + { + auto& link = vertices_[i].obj.links[j]; + if (!id_map.has (link.objidx)) continue; + if (only_wide && !(link.width == 4 && !link.is_signed)) continue; + + reassign_link (link, i, id_map[link.objidx]); + } + } + } + + /* * Updates all objidx's in all links using the provided mapping. */ - void remap_obj_indices (const hb_vector_t<unsigned>& id_map, - hb_vector_t<vertex_t>* sorted_graph) const + void remap_all_obj_indices (const hb_vector_t<unsigned>& id_map, + hb_vector_t<vertex_t>* sorted_graph) const { for (unsigned i = 0; i < sorted_graph->length; i++) { + (*sorted_graph)[i].remap_parents (id_map); for (unsigned j = 0; j < (*sorted_graph)[i].obj.links.length; j++) { auto& link = (*sorted_graph)[i].obj.links[j]; @@ -631,6 +971,9 @@ struct graph_t { switch (link.width) { + case 0: + // Virtual links aren't serialized. + return; case 4: if (link.is_signed) { @@ -656,17 +999,120 @@ struct graph_t } } + /* + * Finds all nodes in targets that are reachable from start_idx, nodes in visited will be skipped. + * For this search the graph is treated as being undirected. + * + * Connected targets will be added to connected and removed from targets. All visited nodes + * will be added to visited. + */ + void find_connected_nodes (unsigned start_idx, + hb_set_t& targets, + hb_set_t& visited, + hb_set_t& connected) + { + if (visited.has (start_idx)) return; + visited.add (start_idx); + + if (targets.has (start_idx)) + { + targets.del (start_idx); + connected.add (start_idx); + } + + const auto& v = vertices_[start_idx]; + + // Graph is treated as undirected so search children and parents of start_idx + for (const auto& l : v.obj.links) + find_connected_nodes (l.objidx, targets, visited, connected); + + for (unsigned p : v.parents) + find_connected_nodes (p, targets, visited, connected); + } + public: // TODO(garretrieger): make private, will need to move most of offset overflow code into graph. hb_vector_t<vertex_t> vertices_; private: - hb_vector_t<clone_buffer_t> clone_buffers_; - bool edge_count_invalid; + bool parents_invalid; bool distance_invalid; bool positions_invalid; bool successful; + hb_vector_t<unsigned> num_roots_for_space_; }; +static bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows, + graph_t& sorted_graph) +{ + for (int i = overflows.length - 1; i >= 0; i--) + { + const graph_t::overflow_record_t& r = overflows[i]; + unsigned root = 0; + unsigned space = sorted_graph.space_for (r.parent, &root); + if (!space) continue; + if (sorted_graph.num_roots_for_space (space) <= 1) continue; + + DEBUG_MSG (SUBSET_REPACK, nullptr, "Overflow in space %d moving subgraph %d to space %d.", + space, + root, + sorted_graph.next_space ()); + + hb_set_t roots; + roots.add (root); + sorted_graph.isolate_subgraph (roots); + for (unsigned new_root : roots) + sorted_graph.move_to_new_space (new_root); + return true; + } + return false; +} + +static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows, + hb_set_t& priority_bumped_parents, + graph_t& sorted_graph) +{ + bool resolution_attempted = false; + + // Try resolving the furthest overflows first. + for (int i = overflows.length - 1; i >= 0; i--) + { + const graph_t::overflow_record_t& r = overflows[i]; + const auto& child = sorted_graph.vertices_[r.child]; + if (child.is_shared ()) + { + // The child object is shared, we may be able to eliminate the overflow + // by duplicating it. + if (!sorted_graph.duplicate (r.parent, r.child)) continue; + return true; + } + + if (child.is_leaf () && !priority_bumped_parents.has (r.parent)) + { + // This object is too far from it's parent, attempt to move it closer. + // + // TODO(garretrieger): initially limiting this to leaf's since they can be + // moved closer with fewer consequences. However, this can + // likely can be used for non-leafs as well. + // TODO(garretrieger): add a maximum priority, don't try to raise past this. + // TODO(garretrieger): also try lowering priority of the parent. Make it + // get placed further up in the ordering, closer to it's children. + // this is probably preferable if the total size of the parent object + // is < then the total size of the children (and the parent can be moved). + // Since in that case moving the parent will cause a smaller increase in + // the length of other offsets. + sorted_graph.raise_childrens_priority (r.parent); + priority_bumped_parents.add (r.parent); + resolution_attempted = true; + continue; + } + + // TODO(garretrieger): add additional offset resolution strategies + // - Promotion to extension lookups. + // - Table splitting. + } + + return resolution_attempted; +} /* * Attempts to modify the topological sorting of the provided object graph to @@ -677,10 +1123,15 @@ struct graph_t * If necessary the structure of the graph may be modified in ways that do not * affect the functionality of the graph. For example shared objects may be * duplicated. + * + * For a detailed writeup describing how the algorithm operates see: + * docs/repacker.md */ inline void hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed, - hb_serialize_context_t* c) { + hb_tag_t table_tag, + hb_serialize_context_t* c, + unsigned max_rounds = 10) { // Kahn sort is ~twice as fast as shortest distance sort and works for many fonts // so try it first to save time. graph_t sorted_graph (packed); @@ -693,68 +1144,36 @@ hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& pac sorted_graph.sort_shortest_distance (); + if ((table_tag == HB_OT_TAG_GPOS + || table_tag == HB_OT_TAG_GSUB) + && sorted_graph.will_overflow ()) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Assigning spaces to 32 bit subgraphs."); + if (sorted_graph.assign_32bit_spaces ()) + sorted_graph.sort_shortest_distance (); + } + unsigned round = 0; hb_vector_t<graph_t::overflow_record_t> overflows; // TODO(garretrieger): select a good limit for max rounds. while (!sorted_graph.in_error () && sorted_graph.will_overflow (&overflows) - && round++ < 10) { - DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Over flow resolution round %d ===", round); + && round++ < max_rounds) { + DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Overflow resolution round %d ===", round); sorted_graph.print_overflows (overflows); - bool resolution_attempted = false; hb_set_t priority_bumped_parents; - // Try resolving the furthest overflows first. - for (int i = overflows.length - 1; i >= 0; i--) + + if (!_try_isolating_subgraphs (overflows, sorted_graph)) { - const graph_t::overflow_record_t& r = overflows[i]; - const auto& child = sorted_graph.vertices_[r.link->objidx]; - if (child.is_shared ()) + if (!_process_overflows (overflows, priority_bumped_parents, sorted_graph)) { - // The child object is shared, we may be able to eliminate the overflow - // by duplicating it. - sorted_graph.duplicate (r.parent, r.link->objidx); - resolution_attempted = true; - - // Stop processing overflows for this round so that object order can be - // updated to account for the newly added object. + DEBUG_MSG (SUBSET_REPACK, nullptr, "No resolution available :("); break; } - - if (child.is_leaf () && !priority_bumped_parents.has (r.parent)) - { - // This object is too far from it's parent, attempt to move it closer. - // - // TODO(garretrieger): initially limiting this to leaf's since they can be - // moved closer with fewer consequences. However, this can - // likely can be used for non-leafs as well. - // TODO(garretrieger): add a maximum priority, don't try to raise past this. - // TODO(garretrieger): also try lowering priority of the parent. Make it - // get placed further up in the ordering, closer to it's children. - // this is probably preferable if the total size of the parent object - // is < then the total size of the children (and the parent can be moved). - // Since in that case moving the parent will cause a smaller increase in - // the length of other offsets. - sorted_graph.raise_childrens_priority (r.parent); - priority_bumped_parents.add (r.parent); - resolution_attempted = true; - continue; - } - - // TODO(garretrieger): add additional offset resolution strategies - // - Promotion to extension lookups. - // - Table splitting. - } - - if (resolution_attempted) - { - sorted_graph.sort_shortest_distance (); - continue; } - DEBUG_MSG (SUBSET_REPACK, nullptr, "No resolution available :("); - c->err (HB_SERIALIZE_ERROR_OFFSET_OVERFLOW); - return; + sorted_graph.sort_shortest_distance (); } if (sorted_graph.in_error ()) @@ -762,8 +1181,14 @@ hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& pac c->err (HB_SERIALIZE_ERROR_OTHER); return; } + + if (sorted_graph.will_overflow ()) + { + c->err (HB_SERIALIZE_ERROR_OFFSET_OVERFLOW); + DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed."); + return; + } sorted_graph.serialize (c); } - #endif /* HB_REPACKER_HH */ diff --git a/thirdparty/harfbuzz/src/hb-sanitize.hh b/thirdparty/harfbuzz/src/hb-sanitize.hh index 56c46015a6..2e536c7a81 100644 --- a/thirdparty/harfbuzz/src/hb-sanitize.hh +++ b/thirdparty/harfbuzz/src/hb-sanitize.hh @@ -145,14 +145,14 @@ struct hb_sanitize_context_t : private: template <typename T, typename ...Ts> auto _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN - ( obj.sanitize (this, hb_forward<Ts> (ds)...) ) + ( obj.sanitize (this, std::forward<Ts> (ds)...) ) template <typename T, typename ...Ts> auto _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN - ( obj.dispatch (this, hb_forward<Ts> (ds)...) ) + ( obj.dispatch (this, std::forward<Ts> (ds)...) ) public: template <typename T, typename ...Ts> auto dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN - ( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) ) + ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) ) void init (hb_blob_t *b) diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh index 7212d9872a..57689916f6 100644 --- a/thirdparty/harfbuzz/src/hb-serialize.hh +++ b/thirdparty/harfbuzz/src/hb-serialize.hh @@ -189,8 +189,8 @@ struct hb_serialize_context_t { return check_success (!hb_deref (obj).in_error ()); } template <typename T1, typename... Ts> bool propagate_error (T1 &&o1, Ts&&... os) - { return propagate_error (hb_forward<T1> (o1)) && - propagate_error (hb_forward<Ts> (os)...); } + { return propagate_error (std::forward<T1> (o1)) && + propagate_error (std::forward<Ts> (os)...); } /* To be called around main operation. */ template <typename Type> @@ -358,6 +358,35 @@ struct hb_serialize_context_t assert (packed.tail ()->head == tail); } + // Adds a virtual link from the current object to objidx. A virtual link is not associated with + // an actual offset field. They are solely used to enforce ordering constraints between objects. + // Adding a virtual link from object a to object b will ensure that object b is always packed after + // object a in the final serialized order. + // + // This is useful in certain situtations where there needs to be a specific ordering in the + // final serialization. Such as when platform bugs require certain orderings, or to provide + // guidance to the repacker for better offset overflow resolution. + void add_virtual_link (objidx_t objidx) + { + if (unlikely (in_error ())) return; + + if (!objidx) + return; + + assert (current); + + auto& link = *current->links.push (); + if (current->links.in_error ()) + err (HB_SERIALIZE_ERROR_OTHER); + + link.width = 0; + link.objidx = objidx; + link.is_signed = 0; + link.whence = 0; + link.position = 0; + link.bias = 0; + } + template <typename T> void add_link (T &ofs, objidx_t objidx, whence_t whence = Head, @@ -376,11 +405,22 @@ struct hb_serialize_context_t err (HB_SERIALIZE_ERROR_OTHER); link.width = sizeof (T); - link.is_signed = hb_is_signed (hb_unwrap_type (T)); + link.objidx = objidx; + if (unlikely (!sizeof (T))) + { + // This link is not associated with an actual offset and exists merely to enforce + // an ordering constraint. + link.is_signed = 0; + link.whence = 0; + link.position = 0; + link.bias = 0; + return; + } + + link.is_signed = std::is_signed<hb_unwrap_type (T)>::value; link.whence = (unsigned) whence; link.position = (const char *) &ofs - current->head; link.bias = bias; - link.objidx = objidx; } unsigned to_bias (const void *base) const @@ -402,6 +442,8 @@ struct hb_serialize_context_t for (const object_t* parent : ++hb_iter (packed)) for (const object_t::link_t &link : parent->links) { + if (unlikely (!link.width)) continue; // Don't need to resolve virtual offsets + const object_t* child = packed[link.objidx]; if (unlikely (!child)) { err (HB_SERIALIZE_ERROR_OTHER); return; } unsigned offset = 0; @@ -494,7 +536,7 @@ struct hb_serialize_context_t template <typename Type, typename ...Ts> auto _copy (const Type &src, hb_priority<1>, Ts&&... ds) HB_RETURN - (Type *, src.copy (this, hb_forward<Ts> (ds)...)) + (Type *, src.copy (this, std::forward<Ts> (ds)...)) template <typename Type> auto _copy (const Type &src, hb_priority<0>) -> decltype (&(hb_declval<Type> () = src)) @@ -509,16 +551,16 @@ struct hb_serialize_context_t * instead of memcpy(). */ template <typename Type, typename ...Ts> Type *copy (const Type &src, Ts&&... ds) - { return _copy (src, hb_prioritize, hb_forward<Ts> (ds)...); } + { return _copy (src, hb_prioritize, std::forward<Ts> (ds)...); } template <typename Type, typename ...Ts> Type *copy (const Type *src, Ts&&... ds) - { return copy (*src, hb_forward<Ts> (ds)...); } + { return copy (*src, std::forward<Ts> (ds)...); } template<typename Iterator, hb_requires (hb_is_iterator (Iterator)), typename ...Ts> void copy_all (Iterator it, Ts&&... ds) - { for (decltype (*it) _ : it) copy (_, hb_forward<Ts> (ds)...); } + { for (decltype (*it) _ : it) copy (_, std::forward<Ts> (ds)...); } template <typename Type> hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; } @@ -546,10 +588,10 @@ struct hb_serialize_context_t template <typename Type, typename ...Ts> Type *extend (Type *obj, Ts&&... ds) - { return extend_size (obj, obj->get_size (hb_forward<Ts> (ds)...)); } + { return extend_size (obj, obj->get_size (std::forward<Ts> (ds)...)); } template <typename Type, typename ...Ts> Type *extend (Type &obj, Ts&&... ds) - { return extend (hb_addressof (obj), hb_forward<Ts> (ds)...); } + { return extend (hb_addressof (obj), std::forward<Ts> (ds)...); } /* Output routines. */ hb_bytes_t copy_bytes () const diff --git a/thirdparty/harfbuzz/src/hb-set-digest.hh b/thirdparty/harfbuzz/src/hb-set-digest.hh index 1ef1ba5fb2..7d4979b73b 100644 --- a/thirdparty/harfbuzz/src/hb-set-digest.hh +++ b/thirdparty/harfbuzz/src/hb-set-digest.hh @@ -168,15 +168,17 @@ struct hb_set_digest_combiner_t * There is not much science to this: it's a result of intuition * and testing. */ -typedef hb_set_digest_combiner_t -< - hb_set_digest_lowest_bits_t<unsigned long, 4>, +using hb_set_digest_t = hb_set_digest_combiner_t < - hb_set_digest_lowest_bits_t<unsigned long, 0>, - hb_set_digest_lowest_bits_t<unsigned long, 9> + hb_set_digest_lowest_bits_t<unsigned long, 4>, + hb_set_digest_combiner_t + < + hb_set_digest_lowest_bits_t<unsigned long, 0>, + hb_set_digest_lowest_bits_t<unsigned long, 9> + > > -> hb_set_digest_t; +; #endif /* HB_SET_DIGEST_HH */ diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh index 437e234361..8841427189 100644 --- a/thirdparty/harfbuzz/src/hb-set.hh +++ b/thirdparty/harfbuzz/src/hb-set.hh @@ -42,9 +42,22 @@ struct hb_sparseset_t ~hb_sparseset_t () { fini (); } hb_sparseset_t (const hb_sparseset_t& other) : hb_sparseset_t () { set (other); } - void operator= (const hb_sparseset_t& other) { set (other); } - // TODO Add move construtor/assign - // TODO Add constructor for Iterator + hb_sparseset_t (hb_sparseset_t&& other) : hb_sparseset_t () { s = std::move (other.s); } + hb_sparseset_t& operator= (const hb_sparseset_t& other) { set (other); return *this; } + hb_sparseset_t& operator= (hb_sparseset_t&& other) { hb_swap (*this, other); return *this; } + friend void swap (hb_sparseset_t& a, hb_sparseset_t& b) { hb_swap (a.s, b.s); } + + hb_sparseset_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t () + { + for (auto&& item : lst) + add (item); + } + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> + hb_sparseset_t (const Iterable &o) : hb_sparseset_t () + { + hb_copy (o, *this); + } void init_shallow () { s.init (); } void init () @@ -140,7 +153,18 @@ struct hb_sparseset_t operator iter_t () const { return iter (); } }; -struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t> {}; +struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t> +{ + hb_set_t () = default; + ~hb_set_t () = default; + hb_set_t (hb_set_t& o) = default; + hb_set_t& operator= (const hb_set_t& other) = default; + hb_set_t& operator= (hb_set_t&& other) = default; + hb_set_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t<hb_bit_set_invertible_t> (lst) {} + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> + hb_set_t (const Iterable &o) : hb_sparseset_t<hb_bit_set_invertible_t> (o) {} +}; static_assert (hb_set_t::INVALID == HB_SET_VALUE_INVALID, ""); diff --git a/thirdparty/harfbuzz/src/hb-style.cc b/thirdparty/harfbuzz/src/hb-style.cc index dfb1017c88..f1b44cea53 100644 --- a/thirdparty/harfbuzz/src/hb-style.cc +++ b/thirdparty/harfbuzz/src/hb-style.cc @@ -113,7 +113,9 @@ hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag) case HB_STYLE_TAG_WIDTH: return face->table.OS2->has_data () ? face->table.OS2->get_width () - : (face->table.head->is_condensed () ? 75 : 100); + : (face->table.head->is_condensed () ? 75 : + face->table.head->is_expanded () ? 125 : + 100); case HB_STYLE_TAG_WEIGHT: return face->table.OS2->has_data () ? face->table.OS2->usWeightClass diff --git a/thirdparty/harfbuzz/src/hb-subset-input.hh b/thirdparty/harfbuzz/src/hb-subset-input.hh index a3e28b0562..07c0e22676 100644 --- a/thirdparty/harfbuzz/src/hb-subset-input.hh +++ b/thirdparty/harfbuzz/src/hb-subset-input.hh @@ -42,17 +42,19 @@ struct hb_subset_input_t { hb_object_header_t header; + struct sets_t { + hb_set_t *glyphs; + hb_set_t *unicodes; + hb_set_t *no_subset_tables; + hb_set_t *drop_tables; + hb_set_t *name_ids; + hb_set_t *name_languages; + hb_set_t *layout_features; + }; + union { - struct { - hb_set_t *glyphs; - hb_set_t *unicodes; - hb_set_t *no_subset_tables; - hb_set_t *drop_tables; - hb_set_t *name_ids; - hb_set_t *name_languages; - hb_set_t *layout_features; - } sets; - hb_set_t* set_ptrs[sizeof (sets) / sizeof (hb_set_t*)]; + sets_t sets; + hb_set_t* set_ptrs[sizeof (sets_t) / sizeof (hb_set_t*)]; }; unsigned flags; diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc index 677df35fad..1e195ff660 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.cc +++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc @@ -38,6 +38,7 @@ #include "hb-ot-color-colrv1-closure.hh" #include "hb-ot-var-fvar-table.hh" #include "hb-ot-stat-table.hh" +#include "hb-ot-math-table.hh" typedef hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> script_langsys_map; @@ -221,6 +222,50 @@ _cmap_closure (hb_face_t *face, cmap.fini (); } +static void _colr_closure (hb_face_t *face, + hb_map_t *layers_map, + hb_map_t *palettes_map, + hb_set_t *glyphs_colred) +{ + OT::COLR::accelerator_t colr; + colr.init (face); + if (!colr.is_valid ()) return; + + unsigned iteration_count = 0; + hb_set_t palette_indices, layer_indices; + unsigned glyphs_num; + { + glyphs_num = glyphs_colred->get_population (); + + // Collect all glyphs referenced by COLRv0 + hb_set_t glyphset_colrv0; + for (hb_codepoint_t gid : glyphs_colred->iter ()) + colr.closure_glyphs (gid, &glyphset_colrv0); + + glyphs_colred->union_ (glyphset_colrv0); + + //closure for COLRv1 + colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices); + } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES && + glyphs_num != glyphs_colred->get_population ()); + + colr.closure_V0palette_indices (glyphs_colred, &palette_indices); + _remap_indexes (&layer_indices, layers_map); + _remap_palette_indexes (&palette_indices, palettes_map); + colr.fini (); +} + +static inline void +_math_closure (hb_face_t *face, + hb_set_t *glyphset) +{ + hb_blob_ptr_t<OT::MATH> math = hb_sanitize_context_t ().reference_table<OT::MATH> (face); + if (math->has_data ()) + math->closure_glyphs (glyphset); + math.destroy (); +} + + static inline void _remove_invalid_gids (hb_set_t *glyphs, unsigned int num_glyphs) @@ -301,12 +346,10 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, #ifndef HB_NO_SUBSET_CFF OT::cff1::accelerator_t cff; #endif - OT::COLR::accelerator_t colr; glyf.init (plan->source); #ifndef HB_NO_SUBSET_CFF cff.init (plan->source); #endif - colr.init (plan->source); plan->_glyphset_gsub->add (0); // Not-def @@ -334,30 +377,17 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, #endif _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ()); - // Collect all glyphs referenced by COLRv0 - hb_set_t* cur_glyphset = plan->_glyphset_gsub; - hb_set_t glyphset_colrv0; - if (colr.is_valid ()) - { - glyphset_colrv0.union_ (*cur_glyphset); - for (hb_codepoint_t gid : cur_glyphset->iter ()) - colr.closure_glyphs (gid, &glyphset_colrv0); - cur_glyphset = &glyphset_colrv0; - } + hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub); + _math_closure (plan->source, plan->_glyphset_mathed); + _remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ()); - hb_set_t palette_indices; - colr.closure_V0palette_indices (cur_glyphset, &palette_indices); - - hb_set_t layer_indices; - colr.closure_forV1 (cur_glyphset, &layer_indices, &palette_indices); - _remap_indexes (&layer_indices, plan->colrv1_layers); - _remap_palette_indexes (&palette_indices, plan->colr_palettes); - colr.fini (); - _remove_invalid_gids (cur_glyphset, plan->source->get_num_glyphs ()); + hb_set_t cur_glyphset = *plan->_glyphset_mathed; + _colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset); + _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ()); // Populate a full set of glyphs to retain by adding all referenced // composite glyphs. - for (hb_codepoint_t gid : cur_glyphset->iter ()) + for (hb_codepoint_t gid : cur_glyphset.iter ()) { glyf.add_gid_and_children (gid, plan->_glyphset); #ifndef HB_NO_SUBSET_CFF @@ -468,6 +498,7 @@ hb_subset_plan_create (hb_face_t *face, plan->_glyphset = hb_set_create (); plan->_glyphset_gsub = hb_set_create (); + plan->_glyphset_mathed = hb_set_create (); plan->codepoint_to_glyph = hb_map_create (); plan->glyph_map = hb_map_create (); plan->reverse_glyph_map = hb_map_create (); @@ -535,6 +566,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan) hb_map_destroy (plan->reverse_glyph_map); hb_set_destroy (plan->_glyphset); hb_set_destroy (plan->_glyphset_gsub); + hb_set_destroy (plan->_glyphset_mathed); hb_map_destroy (plan->gsub_lookups); hb_map_destroy (plan->gpos_lookups); hb_map_destroy (plan->gsub_features); diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh index 92a4e27ccc..c30feeb42f 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.hh +++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh @@ -77,6 +77,7 @@ struct hb_subset_plan_t unsigned int _num_output_glyphs; hb_set_t *_glyphset; hb_set_t *_glyphset_gsub; + hb_set_t *_glyphset_mathed; //active lookups we'd like to retain hb_map_t *gsub_lookups; diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc index 34f92e0d81..048bdf1888 100644 --- a/thirdparty/harfbuzz/src/hb-subset.cc +++ b/thirdparty/harfbuzz/src/hb-subset.cc @@ -52,6 +52,7 @@ #include "hb-ot-layout-gpos-table.hh" #include "hb-ot-var-gvar-table.hh" #include "hb-ot-var-hvar-table.hh" +#include "hb-ot-math-table.hh" #include "hb-repacker.hh" /** @@ -109,7 +110,7 @@ _repack (hb_tag_t tag, const hb_serialize_context_t& c) return nullptr; hb_serialize_context_t repacked ((void *) buf, buf_size); - hb_resolve_overflows (c.object_graph (), &repacked); + hb_resolve_overflows (c.object_graph (), tag, &repacked); if (unlikely (repacked.in_error ())) // TODO(garretrieger): refactor so we can share the resize/retry logic with the subset @@ -305,6 +306,7 @@ _subset_table (hb_subset_plan_t *plan, hb_tag_t tag) case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan); case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan); case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */ + case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan); #ifndef HB_NO_SUBSET_CFF case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan); diff --git a/thirdparty/harfbuzz/src/hb-subset.hh b/thirdparty/harfbuzz/src/hb-subset.hh index c9b01c67f3..98c5f06fbf 100644 --- a/thirdparty/harfbuzz/src/hb-subset.hh +++ b/thirdparty/harfbuzz/src/hb-subset.hh @@ -45,14 +45,14 @@ struct hb_subset_context_t : private: template <typename T, typename ...Ts> auto _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN - ( obj.subset (this, hb_forward<Ts> (ds)...) ) + ( obj.subset (this, std::forward<Ts> (ds)...) ) template <typename T, typename ...Ts> auto _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN - ( obj.dispatch (this, hb_forward<Ts> (ds)...) ) + ( obj.dispatch (this, std::forward<Ts> (ds)...) ) public: template <typename T, typename ...Ts> auto dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN - ( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) ) + ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) ) hb_blob_t *source_blob; hb_subset_plan_t *plan; diff --git a/thirdparty/harfbuzz/src/hb-unicode.hh b/thirdparty/harfbuzz/src/hb-unicode.hh index 0a79944107..4c28bb0cdf 100644 --- a/thirdparty/harfbuzz/src/hb-unicode.hh +++ b/thirdparty/harfbuzz/src/hb-unicode.hh @@ -121,7 +121,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE static hb_bool_t is_variation_selector (hb_codepoint_t unicode) { - /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the + /* U+180B..180D, U+180F MONGOLIAN FREE VARIATION SELECTORs are handled in the * Arabic shaper. No need to match them here. */ return unlikely (hb_in_ranges<hb_codepoint_t> (unicode, 0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */ @@ -136,7 +136,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * As such, we make exceptions for those four. * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503 * - * Unicode 7.0: + * Unicode 14.0: * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/' * 00AD # Cf SOFT HYPHEN * 034F # Mn COMBINING GRAPHEME JOINER @@ -145,6 +145,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * 17B4..17B5 # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA * 180B..180D # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE * 180E # Cf MONGOLIAN VOWEL SEPARATOR + * 180F # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR * 200B..200F # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK * 202A..202E # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE * 2060..2064 # Cf [5] WORD JOINER..INVISIBLE PLUS diff --git a/thirdparty/harfbuzz/src/hb-vector.hh b/thirdparty/harfbuzz/src/hb-vector.hh index 110d457caf..b0a1e5e966 100644 --- a/thirdparty/harfbuzz/src/hb-vector.hh +++ b/thirdparty/harfbuzz/src/hb-vector.hh @@ -38,10 +38,23 @@ struct hb_vector_t typedef Type item_t; static constexpr unsigned item_size = hb_static_size (Type); - hb_vector_t () { init (); } - hb_vector_t (const hb_vector_t &o) + hb_vector_t () = default; + hb_vector_t (std::initializer_list<Type> lst) : hb_vector_t () + { + alloc (lst.size ()); + for (auto&& item : lst) + push (item); + } + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> + hb_vector_t (const Iterable &o) : hb_vector_t () + { + if (hb_iter (o).is_random_access_iterator) + alloc (hb_len (hb_iter (o))); + hb_copy (o, *this); + } + hb_vector_t (const hb_vector_t &o) : hb_vector_t () { - init (); alloc (o.length); hb_copy (o, *this); } @@ -55,11 +68,11 @@ struct hb_vector_t ~hb_vector_t () { fini (); } private: - int allocated; /* == -1 means allocation failed. */ + int allocated = 0; /* == -1 means allocation failed. */ public: - unsigned int length; + unsigned int length = 0; public: - Type *arrayZ; + Type *arrayZ = nullptr; void init () { @@ -87,6 +100,13 @@ struct hb_vector_t resize (0); } + friend void swap (hb_vector_t& a, hb_vector_t& b) + { + hb_swap (a.allocated, b.allocated); + hb_swap (a.length, b.length); + hb_swap (a.arrayZ, b.arrayZ); + } + hb_vector_t& operator = (const hb_vector_t &o) { reset (); @@ -96,11 +116,7 @@ struct hb_vector_t } hb_vector_t& operator = (hb_vector_t &&o) { - fini (); - allocated = o.allocated; - length = o.length; - arrayZ = o.arrayZ; - o.init (); + hb_swap (*this, o); return *this; } @@ -134,7 +150,7 @@ struct hb_vector_t /* Sink interface. */ template <typename T> - hb_vector_t& operator << (T&& v) { push (hb_forward<T> (v)); return *this; } + hb_vector_t& operator << (T&& v) { push (std::forward<T> (v)); return *this; } hb_array_t< Type> as_array () { return hb_array (arrayZ, length); } hb_array_t<const Type> as_array () const { return hb_array (arrayZ, length); } @@ -182,7 +198,7 @@ struct hb_vector_t // the created copy to leak memory since we won't have stored a // reference to it. return p; - *p = hb_forward<T> (v); + *p = std::forward<T> (v); return p; } @@ -239,7 +255,7 @@ struct hb_vector_t Type pop () { if (!length) return Null (Type); - return hb_move (arrayZ[--length]); /* Does this move actually work? */ + return std::move (arrayZ[--length]); /* Does this move actually work? */ } void remove (unsigned int i) @@ -295,6 +311,19 @@ struct hb_vector_t template <typename Type> struct hb_sorted_vector_t : hb_vector_t<Type> { + hb_sorted_vector_t () = default; + ~hb_sorted_vector_t () = default; + hb_sorted_vector_t (hb_sorted_vector_t& o) = default; + hb_sorted_vector_t (hb_sorted_vector_t &&o) = default; + hb_sorted_vector_t (std::initializer_list<Type> lst) : hb_vector_t<Type> (lst) {} + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> + hb_sorted_vector_t (const Iterable &o) : hb_vector_t<Type> (o) {} + hb_sorted_vector_t& operator = (const hb_sorted_vector_t &o) = default; + hb_sorted_vector_t& operator = (hb_sorted_vector_t &&o) = default; + friend void swap (hb_sorted_vector_t& a, hb_sorted_vector_t& b) + { hb_swap ((hb_vector_t<Type>&) (a), (hb_vector_t<Type>&) (b)); } + hb_sorted_array_t< Type> as_array () { return hb_sorted_array (this->arrayZ, this->length); } hb_sorted_array_t<const Type> as_array () const { return hb_sorted_array (this->arrayZ, this->length); } diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h index 70325f88eb..1a4f0bf62a 100644 --- a/thirdparty/harfbuzz/src/hb-version.h +++ b/thirdparty/harfbuzz/src/hb-version.h @@ -47,20 +47,20 @@ HB_BEGIN_DECLS * * The minor component of the library version available at compile-time. */ -#define HB_VERSION_MINOR 0 +#define HB_VERSION_MINOR 1 /** * HB_VERSION_MICRO: * * The micro component of the library version available at compile-time. */ -#define HB_VERSION_MICRO 0 +#define HB_VERSION_MICRO 1 /** * HB_VERSION_STRING: * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "3.0.0" +#define HB_VERSION_STRING "3.1.1" /** * HB_VERSION_ATLEAST: diff --git a/thirdparty/harfbuzz/src/hb.hh b/thirdparty/harfbuzz/src/hb.hh index 829b5a1ab7..1f14267525 100644 --- a/thirdparty/harfbuzz/src/hb.hh +++ b/thirdparty/harfbuzz/src/hb.hh @@ -62,6 +62,7 @@ /* Error. Should never happen. */ #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR +#pragma GCC diagnostic error "-Wbitwise-instead-of-logical" #pragma GCC diagnostic error "-Wcast-align" #pragma GCC diagnostic error "-Wcast-function-type" #pragma GCC diagnostic error "-Wdelete-non-virtual-dtor" |