Comprehensive cross-platform input for GameMaker 2022 LTS by Juju Adams, Alynne Keith, and Friends
-
Read the documentation
-
Talk about Input on the Discord server
-
You may also like Firehammer and Input Dog
Comprehensive cross-platform input for GameMaker
Home Page: https://www.jujuadams.com/Input/
License: MIT License
Comprehensive cross-platform input for GameMaker 2022 LTS by Juju Adams, Alynne Keith, and Friends
With that function you could check the very first input and then set the source of that input to the input source of player 1 instead of hardcoding it.
Or can you already do this and I just missed how?
Some functions to collect and return historical key presses (and holds and releases, with time data) is useful for combo systems and, in somewhat extreme cases, debug input replay
In 3.0.0pre001, direct gamepad access functions were added. These are: input_gamepad_button_check()
input_gamepad_button_check_pressed()
input_gamepad_button_check_released()
input_gamepad_axis_value()
. These were necessary to some extent to construct gamemap remapping for atypical devices as GameMaker's native remapping function(s) aren't reliable cross-platform.
Being able to access gamepads directly runs counter to Input's philosophy that everything should be handled through players. Input includes controller assignment, hotswapping, and rebinding as native functionality. These are typically the places where you'd want/need direct gamepad access but Input takes care of it for you.
Is there a justified use case for direct gamepad access at any point?
I'd like to be able to activate a mode that gives me more detailed states with "input_player_source_get()"
For now, enum INPUT_SOURCE has NONE, KEYBOARD_AND_MOUSE, GAMEPAD
After a call to a function like input_distinct_mouse_keyboard(true), i'd like to be able to get in the INPUT_SOURCE enum some more details, with NONE, KEYBOARD, MOUSE, GAMEPAD
In the following asset directories:
Line 177 needs to be changed to input_gamepad_value.
ps: sorry, I don't know how to add labels in github.
I know we've discussed this, wanting to consolidate thoughts on it in one place in case it's of interest.
Maps should be matched based on full GUID string and not just VID PID pair. The default GUID format shouldn't be assumed when extracting VID & PID.
The exception is on Windows, where VID & PID is adequate since GM's using the older format that omits other info. For type identification it's adequate (assuming the default GUID format was consumed properly), since that's all SDL's data uses.
Windows (old format):
********000000000000504944564944`
^ ^
VID PID
Non-Windows platforms GUIDs can take one of three formats:
Default:
****0000****0000****0000****0000
^ ^ ^ ^
Driver Vendor Product Revision
In this format all fields are important, for example a Bluetooth mode device (driver 0500
) may map different in USB mode (driver 0300
), and revision is heavily relied on for differentiating otherwise identically-reporting devices.
Fallback (Mac & Linux):
****0000************************
^ ^
Driver Devce name in UTF-8, right-padded
Fallback (Android):
********************************
^
Device name CRC as integer string
The most straightforward way to check for default format seems to me (at a glance) to check that the full GUID is not zeroed, but the expected padding after all 4 fields is.
If a full GUID comparison fails and VID & PID are found you can (but don't need to) fallback on VID & PID alone to find "nearest match".
Currently (iirc) you've got a platform-agnostic fallback if no same-platform match is made in the external or inbuilt db. The only (relatively) safe mapping fallback between platforms is between Windows and Linux.
Prior to most recent kernel these keycodes are fired by the default gamepad treatment in duplicate to button codes. Backspace on secondary face button (eg Xbox B, PS Circle) and Escape on meta button (eg Guide/Home). Prevent input source change on these keys when gamepad is enabled, and block them from binding, if appropriate.
increasingly PC users are presented options for combining gamepad and mouse/keyboard input, termed "mixed" or "simultaneous" input. limiting "player" slots to either/or means either thrashing between modes when hotswapping is enabled, or being locked out of one or the other input source altogether.
https://www.pcgamingwiki.com/wiki/List_of_games_that_support_simultaneous_input
common devices that leverage mixed input include gamepads (Steam Controller and thus by extension any gamepad leveraging Steam Input, and numerous Android gamepads that map selective buttons to keyboard), gameboards (Logitech G13, Wooting devices, CoolerMaster's Aimpad enabled MK850 and ControlPad, Belkin's N50 line, Saitek PZ31A, Razer's Orbweaver and Tartarus lines), gamemice (ROG Chakram, Swiftpoint Z, Lexip Pu94), and burgeoning hybrid ergo devices like the Azeron and 3dRudder
generally the consensus is "indicate device type as gamepad, but do not lock-out mouse or keyboard input". i know this is a pain especially for assigning devices per player, but if mouse/keyboard pairing is acceptable perhaps all three in tandem isn't entirely unreasonable ;-)
Just in case an overcompensator like me wants to have, for example, a separate menu for rebinding k+m and gamepads and you don't want to have to check the rebinding value for type .
Instead of:
var rebind = input_binding_scan_tick();
if (rebind && (rebind.type == "gamepad axis" || rebind.type == "gamepad button")) {
/* whatever */
}
One might instead do:
var rebind = input_binding_scan_tick(INPUT_SOURCE.GAMEPAD);
if (rebind) {
/* whatever */
}
It would be useful to have a way to put the player bindings into an external file so that players could have their control preferences set correctly the next time they open the game.
at some point i need to split off the blacklist and store that outside the code
issue as discussed. compatible pads: https://github.com/libsdl-org/SDL/blob/main/src/joystick/SDL_gamecontrollerdb.h#L839-L855
any compatible pad should be normalized and doesn't need mapping, through it may be possible to infer type by description.
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,
030000005e0400008e02000000007801,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,
03000000869800002400000000007801,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,
stick https://github.com/gabomdq/SDL_GameControllerDB/blob/master/LICENSE in datafiles
next to gamecontrollerdb.txt
Having the ability to check if an input has been pressed again within a certain timeframe would be extremely handy to have. For example, in Platformers, double pressing the down input would allow you to pass through a solid platform. Or double tapping a direction to give an extra boost. Just an idea that would come in handy in a future release.
SDL_GAMECONTROLLERCONFIG
// on windows target only, touchpad & touchscreen input fails to properly register taps as clicks
// pre-init mbl_count_press/release to 0
tap = false;
if os_type == os_windows {
mbl_count_press += mouse_check_button_pressed(mb_left);
mbl_count_release += mouse_check_button_released(mb_left);
if mbl_count_release > mbl_count_press {
tap = true;
}
if mbl_count_press == mbl_count_release || tap {
mbl_count_press = 0;
mbl_count_release = 0;
}
}
It would be great if upon success input_rebind_tick, if a swap between keybindings has happend, the function returns with what verb has the swap occured.
It's possible to scan the generated binding post-hoc but this is annoying. A feature should exist to prevent certain keys from being interpreted as valid inputs.
Additionally, these blocked keyboard keys should not trigger a switch to keyboard usage.
if os_type == os_android && // filter out non-gamepad devices on android
sc_string_has(string_lower(gamepad_get_description(gamepad_index)),
"mouse", "trackball", "keyboard", "button jack", "headphones", "jabra",
"transceiver", "surface type", "touchscreen", "multitouch", "headset",
"sennheiser", "corsair")
passed_filter = false;
The situation I'm thinking of is nested UI navigation. Imagine we have an in-game menu, and two verbs to go with that menu 'Select' and 'Back'. Now let's say I'm looking at the options menu and I've made some changes, and then I press the Back button. I want to confirm that the user doesn't want to save their changes, so I pop up a dialog over the options menu, asking if the want to save their changes. The dialog is checking the 'Select' verb for Yes and 'Back' verb for No.
The problem is, the options menu is also checking the 'Select' and 'Back' verbs for its own input logic! So what I want is something like:
input_redirect_verb(old_verb, new_verb)
Which, for the above example, I might call like so: input_redirect_verb("Select", "Select_Dialog").
After calling input_redirect_verb a subsequent call to input_check("Select") would no longer return true when whatever real input was mapped to "Select" is pressed. Instead, input_check("Select_Dialog") would return true.
The second part of this would ideally be an input_undo_redirect(current_verb), which would basically reverse whatever old_verb got mapped to current_verb. This is just a nice to have, as I could call input_redirect_verb("Select_Dialog", "Select") myself, but it would be nice for re-usability purposes to not have to keep track of how I got to the current verb mapping (so that a confirmation dialog box could be re-used from anywhere without me tracking the redirections myself).
case "7e050e20000000000000504944564944": // joycon charger windows
case "030000007e0500000e20000000020000": // joycon charger macos
case "030000007e0500000e20000011010000": // joycon charger linux
case "65366131663736363061313736656431": // joycon charger android
case "030000007e0500000920000000020000": // pro controller macos
case "030000007e0500000920000011010000": // pro controller linux
case "61393962646434393836356631636132": // pro controller android
case "61373939383333653939323337373730": // ps/2 usb adapter android
case "35623363656536396133623234666231": // elecom trackball android
case "32646532373735653736353036656333": // 8bd psc adapter android
case "64623037323132643231333433383536": // audio headset android
case "4c056802000000000000504944564944": // ps3 windows (bad format, sans sony driver)
// bad switch format on windows (wired), sans steam
case "7e050920000000000000504944564944": // pro controller
case "7e051720000000000000504944564944": // snes online
Windows Switch
a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b10,rightstick:b11,
Windows PS4
a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,leftstick:b10,rightstick:b11,
Windows Xbone (non-XInput)
a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,lefttriger:a2,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,leftstick:b8,rightstick:b9,
Windows PS3 with Sony VID "054c"
a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,leftstick:b10,rightstick:b11,
Windows PS3 with non-Sony VID
a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b10,rightstick:b11,
Winows X360 (non-XInput),
a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,lefttrigger:-a2,righttrigger:+a2,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,leftstick:b8,rightstick:b9,
Mac Switch
a:b0,b:b1,x:b2,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b10,rightstick:b11,
Mac Xbone
a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,leftstick:b8,rightstick:b9,
Mac PS3 with Sony VID "054c"
a:b14,b:b13,x:b15,y:b12,back:b0,start:b3,leftshoulder:b10,rightshoulder:b11,lefttrigger:b8,righttrigger:b9,dpup:b4,dpdown:b6,dpleft:b7,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b1,rightstick:b2,
Mac PS3 with non-Sony VID
a:b0,b:b1,x:b2,y:b3,back:b9,start:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:a2,righttrigger:a5,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,leftstick:b6,rightstick:b7,
Mac X360 (https://github.com/360Controller/360Controller)
a:b0,b:b1,x:b2,y:b3,back:b9,start:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:a2,righttrigger:a5,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,leftstick:b6,rightstick:b7,
Linux Switch
a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b10,rightstick:b11,
Linux PS4
a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,leftstick:b10,rightstick:b11,`
Linux Xbone
a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,leftstick:b9,rightstick:b10,
Linux PS3
a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b10,rightstick:b11,
Linux X360
a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b9,rightstick:b10,
Android Switch
a:b0,b:b1,x:b17,y:b2,back:b15,start:b16,leftshoulder:b3,rightshoulder:b18,lefttrigger:b9,righttrigger:b10,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b4,rightstick:b6,
Android PS4
if os_version > 22 AND gamepad_get_description contains any of "Wireless Controller", "Wireless Adaptor"
a:b0,b:b1,x:b2,y:b3,back:b15,start:b6,leftshoulder:b9,rightshoulder:b10,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b7,rightstick:b8,
Android PS4 else
a:b1,b:b17,x:b0,y:b2,back:b16,start:b5,leftshoulder:b3,rightshoulder:b3,lefttrigger:b9,righttrigger:a10,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,leftstick:b4,rightstick:b6,
Android Xbone
a:b0,b:b1,x:b2,y:b3,start:b6,leftshoulder:b9,rightshoulder:b10,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b7,rightstick:b8,
Android PS3 if os_version > 28 AND gamepad_get_description contains "(R)3"
a:b0,b:b1,x:b2,y:b3,back:b15,start:b6,leftshoulder:b9,rightshoulder:b10,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b7,rightstick:b8,
Android PS3 else
a:b0,b:b1,x:b2,y:b3,back:b4,start:b6,leftshoulder:b9,rightshoulder:b10,lefttrigger:a4,righttrigger:a5,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b7,rightstick:b8,
Android X360
a:b0,b:b1,x:b2,y:b3,back:b4,start:b6,leftshoulder:b9,rightshoulder:b10,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b7,rightstick:b8,
// assign a default map based on type
switch (os_type) {
#region windows maps
case os_windows:
switch (gp_type) {
case "wii":
type_map = "`wii`," + str_unknown_device + ",wii,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b10,rightstick:b11,";
break;
case "gc":
type_map = "`gc`," + str_unknown_device + ",gc,a:b1,b:b0,x:b2,y:b3,,start:b9,,rightshoulder:b7,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2";
break;
case "sat":
type_map = "`sat`," + str_unknown_device + ",sat,a:b0,b:b1,x:b3,y:b4,start:b8,leftshoulder:b5,rightshoulder:b2,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,";
break;
case "snes":
if vid == "2dc8" // 8bitdo vendor snes pad
type_map = "`snes`," + str_unknown_device + ",snes,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,";
else
type_map = "`snes`," + str_unknown_device + ",snes,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,";
break;
case "8bd":
type_map = "`8bd`," + str_unknown_device + ",8bd,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b13,rightstick:b14,";
break;
case "ps4":
if guid == "98860024" || guid == "0e6f0188" // c40 tr, nacon rev 3: xinput with ps4 labels
type_map = "`ps4`," + str_unknown_device + ",ps4,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,";
else
type_map = "`ps4`," + str_unknown_device + ",ps4,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,leftstick:b10,rightstick:b11,";
break;
case "xbone":
type_map = "`xbone`," + str_unknown_device + ",xbone,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,lefttriger:a2,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,leftstick:b8,rightstick:b9,";
break;
case "ps3":
if vid == "054c" // sony vendor ps3 pad
type_map = "`ps3`," + str_unknown_device + ",ps3,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,leftstick:b10,rightstick:b11,";
else
type_map = "`ps3`," + str_unknown_device + ",ps3,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b10,rightstick:b11,";
break;
case "xb360":
type_map = "`xb360`," + str_unknown_device + ",xb360,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,";
break;
}
break;
#endregion
#region macos maps
case os_macosx:
switch (gp_type) {
case "wii":
type_map = "`wii`," + str_unknown_device + ",wii,a:b0,b:b1,x:b2,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b10,rightstick:b11,";
break;
case "sat":
type_map = "`sat`," + str_unknown_device + ",sat,a:b0,b:b1,x:b3,y:b4,start:b11,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,leftx:a0,lefty:a1 dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,";
break;
case "8bd":
type_map = "`8bd`," + str_unknown_device + ",8bd,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b13,rightstick:b14,";
break;
case "ps4":
type_map = "`ps4`," + str_unknown_device + ",ps4,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,leftstick:b10,rightstick:b11,";
break;
case "xbone":
type_map = "`xbone`," + str_unknown_device + ",xbone,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,leftstick:b8,rightstick:b9,";
break;
case "ps3":
if vid == "054c"
type_map = "`ps3`," + str_unknown_device + ",ps3,a:b14,b:b13,x:b15,y:b12,back:b0,start:b3,leftshoulder:b10,rightshoulder:b11,lefttrigger:b8,righttrigger:b9,dpup:b4,dpdown:b6,dpleft:b7,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b1,rightstick:b2,";
else
type_map = "`ps3`," + str_unknown_device + ",ps3,a:b0,b:b1,x:b2,y:b3,back:b9,start:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:a2,righttrigger:a5,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,leftstick:b6,rightstick:b7,";
break;
case "x360":
type_map = "`xb360`," + str_unknown_device + ",xb360,a:b0,b:b1,x:b2,y:b3,back:b9,start:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:a2,righttrigger:a5,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,leftstick:b6,rightstick:b7,";
break;
}
break;
#endregion
#region linux maps
case os_linux:
switch (gp_type) {
case "wii":
type_map = "`wii`," + str_unknown_device + ",wii,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b10,rightstick:b11,";
break;
case "snes":
type_map = "`snes`," + str_unknown_device + ",snes,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,";
break;
case "8bd":
type_map = "`8bd`," + str_unknown_device + ",8bd,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b13,rightstick:b14,";
break;
case "ps4":
type_map = "`ps4`," + str_unknown_device + ",ps4,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,leftstick:b10,rightstick:b11,";
break;
case "xbone":
type_map = "`xbone`," + str_unknown_device + ",xbone,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,leftstick:b9,rightstick:b10,";
break;
case "ps3":
type_map = "`ps3`," + str_unknown_device + ",ps3,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b10,rightstick:b11,";
break;
case "xb360":
type_map = "`xb360`," + str_unknown_device + ",xb360,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b9,rightstick:b10,";
break;
}
break;
#endregion
#region android maps
case os_android:
switch (gp_type) {
case "8bd":
type_map = "`8bd`," + str_unknown_device + ",8bd,a:b1,b:b0,x:b3,y:b2,back:b15,start:b6,leftshoulder:b9,rightshoulder:b10,lefttrigger:b17,righttrigger:b18,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b7,rightstick:b8,";
break;
case "ps4":
if os_version > 22 &&
sc_string_has(gamepad_get_description(gamepad_index), "Wireless Controller", "Wireless Adaptor")
type_map = "`ps4`," + str_unknown_device + ",ps4,a:b0,b:b1,x:b2,y:b3,back:b15,start:b6,leftshoulder:b9,rightshoulder:b10,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b7,rightstick:b8,";
else
type_map = "`ps4`," + str_unknown_device + ",ps4,a:b1,b:b17,x:b0,y:b2,back:b16,start:b5,leftshoulder:b3,rightshoulder:b3,lefttrigger:b9,righttrigger:a10,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,leftstick:b4,rightstick:b6,";
break;
case "xbone":
type_map = "`xbone`," + str_unknown_device + ",xbone,a:b0,b:b1,x:b2,y:b3,start:b6,leftshoulder:b9,rightshoulder:b10,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b7,rightstick:b8,";
break;
case "ps3":
if os_version > 28 &&
sc_string_has(gamepad_get_description(gamepad_index), "(R)3")
type_map = "`ps3`," + str_unknown_device + ",ps3,a:b0,b:b1,x:b2,y:b3,back:b15,start:b6,leftshoulder:b9,rightshoulder:b10,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b7,rightstick:b8,";
else
type_map = "`ps3`," + str_unknown_device + ",ps3,a:b0,b:b1,x:b2,y:b3,back:b4,start:b6,leftshoulder:b9,rightshoulder:b10,lefttrigger:a4,righttrigger:a5,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b7,rightstick:b8,";
break;
case "xb360":
type_map = "`xb360`," + str_unknown_device + ",xb360,a:b0,b:b1,x:b2,y:b3,back:b4,start:b6,leftshoulder:b9,rightshoulder:b10,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,leftstick:b7,rightstick:b8,";
break;
}
break;
#endregion
}
Don't forget the documentation + quick start guide!
inc. list offalynne as co-creator
This would be useful to save on typing redundancy and who doesn't love that?
Would it be possible for this to use the same function? I think it's doable to detect an array in GMS?
Could be used like: if input_check([Verb.LEFT, Verb.RIGHT, Verb.UP, Verb.DOWN])
Otherwise they can be separate functions but I'll leave that for what you think is best.
mostly notes for me. as discussed i'm going to..
types juju asked to be included in the expanded list:
i would like to support type getting for the following on desktop as far as is possible:
Apple generic, Gamecube,PS3,PS4,PS5, SNES, Stadia (lol),Steam,Steam v2,Switch Pro,Switch joycon L,Switch joycon R,XB360,XB1
and possibly add
Userland Steam & Dual Joycon drivers, 8BitDo (DInput mode), official microconsole pads with PC USB compatibility (Ouya, Genesis/MD Mini, PS Classic, TG16/CGfx/PCE Mini, NeoGeo Mini, Capcom Home Arcade, Astro City Mini)
input_gamepad_default_axis_pair(axis, negativeVerb, positiveVerb, [alternate])
Ordinarily unbound verbs are just ignored, but if verbs are bound to the cursor but no keyboard keys or gamepad buttons it'll crash:
Variable <unknown_object>.consumed(100976, -2147483648) cannot be resolved.
at gml_Script_anon___input_class_cursor_gml_GlobalScript_input_tick_17524___input_class_cursor_gml_GlobalScript_input_tick (line 487) - var _dx = (_struct_d.consumed? 0.0 : clamp(_struct_d.raw, 0.0, 1.0)) - (_struct_u.consumed? 0.0 : clamp(_struct_u.raw, 0.0, 1.0));
############################################################################################
gml_Script_anon___input_class_cursor_gml_GlobalScript_input_tick_17524___input_class_cursor_gml_GlobalScript_input_tick (line 487)
gml_Script_anon___input_class_player_gml_GlobalScript_input_tick_6438___input_class_player_gml_GlobalScript_input_tick (line 255) - tick();
gml_Script_input_tick (line 20) - global.__input_players[_p].tick();
gml_Object_World_Step_0 (line 8) - input_tick();
Either commenting out the input_cursor_verbs
function or uncommenting the block at the bottom will make the crash go away.
enum InputVerbs {
LEFT, RIGHT, UP, DOWN,
LOOK_LEFT, LOOK_RIGHT, LOOK_UP, LOOK_DOWN,
...
}
input_cursor_verbs(InputVerbs.LOOK_LEFT, InputVerbs.LOOK_RIGHT, InputVerbs.LOOK_UP, InputVerbs.LOOK_DOWN, 5);
input_default_key(ord("A"), InputVerbs.LEFT);
input_default_key(ord("D"), InputVerbs.RIGHT);
input_default_key(ord("W"), InputVerbs.UP);
input_default_key(ord("S"), InputVerbs.DOWN);
/*
input_default_key(vk_left, InputVerbs.LOOK_LEFT);
input_default_key(vk_right, InputVerbs.LOOK_RIGHT);
input_default_key(vk_up, InputVerbs.LOOK_UP);
input_default_key(vk_down, InputVerbs.LOOK_DOWN);
*/
I often like to include a few variables to keep track of cursor movement between frames - drawing a cursor on the UI but having it disappear if the mouse hasn't moved in the last three seconds, for example.
mouse_x_previous = mouse_x_window;
mouse_y_previous = mouse_y_window;
mouse_x_window = window_mouse_get_x();
mouse_y_window = window_mouse_get_y();
mouse_x_delta = mouse_x_window - mouse_x_previous;
mouse_y_delta = mouse_y_window - mouse_y_previous;
if (mouse_x_previous != mouse_x_window || mouse_y_previous != mouse_y_window) {
mouse_last_moved = current_time;
}
It doesn't look like Input contains anything to do that yet. Would be useful on occasion!
It would be great to have a function to let you know what the last verb was that was activated. Maybe these could be multiple functions for stuff like last pressed and last released.
I was thinking it might also be beneficial to have these in stored in a stack as well? That way if you have two keys held and you let go, it'll give you the last last key held or pressed. This might be better as a separate function or implemented on the user's side though.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.