So apparently I implemented (d08c3d9) this way back and never tested it, then copied it to Linux where Josh later fixed it. Regardless, it doesn't work on master and it's also really slow because I didn't know how to write it and had it polling the keyboard state twice.
Anyway I made a little test to see if it was working and discovered that apparently the logical
vk_anykey were never supported by
keyboard_check_direct(), not in GM8.1 or GMSv1.4 afaict.
var text; text = string(keyboard_check_direct(vk_nokey)) + " " + string(keyboard_check_direct(vk_anykey)); draw_text(0,0,text);
Now when I benchmark this with the #2059 test I had, it's still slower (100,000~ microseconds) than our SDL (5000~ microseconds) and GMSv1.4 (50,000~ microseconds) even after the fix. There could be two reasons for this. either SDL & GMSv1.4 are caching the direct keyboard state once in a frame or
GetAsyncKeyState should be used here. The latter seems more likely since again GM never supported the
vk_anykey logical keys for this function, and there would be no way to tell their state if this function only polled a single key instead of the entire keyboard. Regardless, when I tested removing that and just using
GetAsyncKeyState the function then performed around 30,000~ microseconds suggesting it was closer to GM at that point and that SDL might be caching or not as low-level as it appears.
The documentation also seems to suggest that
GetKeyboardState is message based hardly distinguishing it from our existing high-level input that is based on messaging.
The status changes as a thread removes keyboard messages from its message queue.
GetKeyState also says the same & more, it seems like
GetAsyncKeyState really is the real candidate.
The status does not reflect the interrupt-level state associated with the hardware.
GetAsyncKeyState does mention that it checks at the time the function is called.
GetAsyncKeyStatecompletes in 33,000~ microseconds (closest to GMSv1.4), I decided to use it. I assume GMSv1.4's extra 20,000 microseconds are the fact I was using the Windows target and not the Windows YYC target.
Another clue that this is correct is that the
keyboard_check_direct() function is still only available on Windows, suggesting there was no SDL equivalent for YYG to port it easily.
NOTE: This function is only available for the standard Windows target and the result is independent of which application has focus.
Alright, I've devised the definitive test about this pull request's correctness. At first glance the test will tell you they always arrive at the same time in GM8.1, but it's not true. If we look a little closer and use spacebar (key we are testing) to dismiss the message, then another message will show with
0 0 1or saying that direct had arrived. GMSv1.4 is the same except you have to hold space down and click ok because it doesn't dismiss unless you release the space. Another way to test the two of them is to focus another window and press space like I am doing while typing this message and then be annoyed at the fact that it's telling you the direct message was received first.
var message, pressed, direct; message = keyboard_check(vk_space); pressed = keyboard_check_pressed(vk_space); direct = keyboard_check_direct(vk_space); if (message || pressed || direct) show_message(string(message) + " " + string(pressed) + " " + string(direct));
NOTE: Please remember to shut "Freeze on lose focus" setting off before testing in ENIGMA!
Now this is where it gets awesome, this pull request behaves like GMSv1.4 and GM8.1. It does this regardless of whether
GetKeyState is used, so it's not as definitive as I'd like. However,
GetKeyboardState when used is not able to get the direct input when the window is not focused. This definitely rules it out as the implementation for this function. Finally, it does indicate that
SDL_GetKeyboardState is wrong too because our SDL system is always reporting them all arriving at the same time, indicating its not as low-level as one would hope for. SDL also won't say anything if the window isn't focused, another indicator.
@@ Coverage Diff @@ ## master #2060 +/- ## ======================================= Coverage 30.93% 30.93% ======================================= Files 197 197 Lines 19102 19102 ======================================= Hits 5910 5910 Misses 13192 13192
Alright, now I have the real definitive test.
NOTE: Just to be sure UP is released between testing sessions, tap it a few times before you switch programs.
var message, pressed, direct; keyboard_key_release(vk_up); // for good measure keyboard_key_press(vk_up); message = keyboard_check(vk_up); pressed = keyboard_check_pressed(vk_up); direct = keyboard_check_direct(vk_up); keyboard_key_release(vk_up); show_message(string(message) + " " + string(pressed) + " " + string(direct));
As we can see ENIGMA is only the same as GM8.1 and GMSv1.4 when using
GetAsyncKeyState as we had predicted.
000 SDL 000 GetKeyState 000 GetKeyboardState 001 GetAsyncKeyState 001 GM8.1 001 GMSv1.4
Again, the reason why I would be so adamant about this is because if
keyboard_check_directdoesn't actually provide DIRECT keyboard state, there is no purpose to it. If it's in any way message based, then it's no different than
keyboard_checkand we would be wasting our time. Although implementing the function as message based on our platforms which do not yet have direct keyboard state functionality, like xlib/SDL, is sensible for people to easily port games and totally acceptable.