Virtual Keyboard: rewrite keyboard-gamepad switching

- Input handling is done straight in G_MapEventsToControls
- If a keyboard event is received, switch off virtual
  keyboard
  - Removed the input lock while virtual keyboard is
    sliding away
- If a gamepad event is received, and it is a change of at
  least half the full range, switch on virtual keyboard
This commit is contained in:
James R 2024-03-05 16:16:05 -08:00
parent e7fed5d7b5
commit bea1cccdde
6 changed files with 55 additions and 85 deletions

View file

@ -890,6 +890,7 @@ consvar_t cv_debugrender_freezebsp = PlayerCheat("debugrender_freezebsp", "Off")
consvar_t cv_debugrender_portal = PlayerCheat("debugrender_portal", "Off").on_off().description("Highlight visual portals in red"); consvar_t cv_debugrender_portal = PlayerCheat("debugrender_portal", "Off").on_off().description("Highlight visual portals in red");
consvar_t cv_debugrender_spriteclip = PlayerCheat("debugrender_spriteclip", "Off").on_off().description("Let sprites draw through walls"); consvar_t cv_debugrender_spriteclip = PlayerCheat("debugrender_spriteclip", "Off").on_off().description("Let sprites draw through walls");
consvar_t cv_debugrender_visplanes = PlayerCheat("debugrender_visplanes", "Off").on_off().description("Highlight the number of visplanes"); consvar_t cv_debugrender_visplanes = PlayerCheat("debugrender_visplanes", "Off").on_off().description("Highlight the number of visplanes");
consvar_t cv_debugvirtualkeyboard = PlayerCheat("debugvirtualkeyboard", "Off").on_off().description("Always show virtual keyboard instead of using real keyboard input.");
consvar_t cv_devmode_screen = PlayerCheat("devmode_screen", "1").min_max(1, 4).description("Choose which splitscreen player devmode applies to"); consvar_t cv_devmode_screen = PlayerCheat("devmode_screen", "1").min_max(1, 4).description("Choose which splitscreen player devmode applies to");
consvar_t cv_drawpickups = PlayerCheat("drawpickups", "Yes").yes_no().description("Hide rings, spheres, item capsules, prison capsules (visual only)"); consvar_t cv_drawpickups = PlayerCheat("drawpickups", "Yes").yes_no().description("Hide rings, spheres, item capsules, prison capsules (visual only)");

View file

@ -4131,7 +4131,6 @@ boolean G_CheckDemoTitleEntry(void)
demo.willsave = true; demo.willsave = true;
M_OpenVirtualKeyboard( M_OpenVirtualKeyboard(
false,
sizeof demo.titlename, sizeof demo.titlename,
[](const char* replace) -> const char* [](const char* replace) -> const char*
{ {

View file

@ -418,6 +418,12 @@ static INT32 AssignDeviceToFirstUnassignedPlayer(INT32 device)
return -1; return -1;
} }
static void update_vkb_axis(INT32 axis)
{
if (axis > JOYAXISRANGE/2)
M_SwitchVirtualKeyboard(true);
}
// //
// Remaps the inputs to game controls. // Remaps the inputs to game controls.
// //
@ -460,6 +466,8 @@ void G_MapEventsToControls(event_t *ev)
case ev_keydown: case ev_keydown:
if (ev->data1 < NUMINPUTS) if (ev->data1 < NUMINPUTS)
{ {
M_MenuTypingInput(ev->data1);
if (ev->data2) // OS repeat? We handle that ourselves if (ev->data2) // OS repeat? We handle that ourselves
{ {
break; break;
@ -556,11 +564,13 @@ void G_MapEventsToControls(event_t *ev)
if (ev->data2 != INT32_MAX) if (ev->data2 != INT32_MAX)
{ {
DeviceGameKeyDownArray[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2)] = max(0, ev->data2); DeviceGameKeyDownArray[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2)] = max(0, ev->data2);
update_vkb_axis(max(0, ev->data2));
} }
if (ev->data3 != INT32_MAX) if (ev->data3 != INT32_MAX)
{ {
DeviceGameKeyDownArray[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1] = max(0, ev->data3); DeviceGameKeyDownArray[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1] = max(0, ev->data3);
update_vkb_axis(max(0, ev->data3));
} }
} }
else else
@ -592,6 +602,7 @@ void G_MapEventsToControls(event_t *ev)
DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4)] = 0; DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4)] = 0;
DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 1] = abs(ev->data2); DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 1] = abs(ev->data2);
} }
update_vkb_axis(abs(ev->data2));
} }
if (ev->data3 != INT32_MAX) if (ev->data3 != INT32_MAX)
@ -608,6 +619,7 @@ void G_MapEventsToControls(event_t *ev)
DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 2] = 0; DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 2] = 0;
DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 3] = abs(ev->data3); DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 3] = abs(ev->data3);
} }
update_vkb_axis(abs(ev->data3));
} }
} }
break; break;

View file

@ -686,9 +686,10 @@ void M_PlayMenuJam(void);
boolean M_ConsiderSealedSwapAlert(void); boolean M_ConsiderSealedSwapAlert(void);
void M_OpenVirtualKeyboard(boolean gamepad, size_t cachelen, vkb_query_fn_t queryfn, menu_t *dummymenu); void M_OpenVirtualKeyboard(size_t cachelen, vkb_query_fn_t queryfn, menu_t *dummymenu);
void M_AbortVirtualKeyboard(void); void M_AbortVirtualKeyboard(void);
void M_MenuTypingInput(INT32 key); void M_MenuTypingInput(INT32 key);
void M_SwitchVirtualKeyboard(boolean gamepad);
void M_QuitResponse(INT32 ch); void M_QuitResponse(INT32 ch);
void M_QuitSRB2(INT32 choice); void M_QuitSRB2(INT32 choice);

View file

@ -275,8 +275,6 @@ static boolean M_GamestateCanOpenMenu(void)
// //
boolean M_Responder(event_t *ev) boolean M_Responder(event_t *ev)
{ {
boolean menuKeyJustChanged = false;
if (dedicated if (dedicated
|| (demo.playback && demo.attract) || (demo.playback && demo.attract)
|| M_GamestateCanOpenMenu() == false) || M_GamestateCanOpenMenu() == false)
@ -311,7 +309,6 @@ boolean M_Responder(event_t *ev)
{ {
// Record keyboard presses // Record keyboard presses
menuKey = ev->data1; menuKey = ev->data1;
menuKeyJustChanged = true;
} }
// Profiles: Control mapping. // Profiles: Control mapping.
@ -457,12 +454,6 @@ boolean M_Responder(event_t *ev)
return false; return false;
} }
// Typing for CV_IT_STRING
if (menuKeyJustChanged && menutyping.active && !menutyping.menutypingclose && menutyping.keyboardtyping)
{
M_ChangeStringCvar(menuKey);
}
// We're in the menu itself now. // We're in the menu itself now.
// M_Ticker will take care of the rest. // M_Ticker will take care of the rest.
return true; return true;
@ -1097,7 +1088,7 @@ static void M_HandleMenuInput(void)
// Typing for CV_IT_STRING // Typing for CV_IT_STRING
if (menutyping.active) if (menutyping.active)
{ {
M_MenuTypingInput(thisMenuKey); M_MenuTypingInput(-1);
return; return;
} }
@ -1136,7 +1127,7 @@ static void M_HandleMenuInput(void)
if (M_MenuConfirmPressed(pid)) if (M_MenuConfirmPressed(pid))
{ {
// If we entered this menu by pressing a menu Key, default to keyboard typing, otherwise use controller. // If we entered this menu by pressing a menu Key, default to keyboard typing, otherwise use controller.
M_OpenVirtualKeyboard(thisMenuKey == -1, MAXSTRINGLENGTH, M_QueryCvarAction, NULL); M_OpenVirtualKeyboard(MAXSTRINGLENGTH, M_QueryCvarAction, NULL);
return; return;
} }
else if (M_MenuExtraPressed(pid)) else if (M_MenuExtraPressed(pid))

View file

@ -196,18 +196,22 @@ void M_AbortVirtualKeyboard(void)
M_GoBack(0); M_GoBack(0);
} }
static boolean M_IsTypingKey(INT32 key)
{
return key == KEY_BACKSPACE || key == KEY_ENTER
|| key == KEY_ESCAPE || key == KEY_DEL
|| key == KEY_LCTRL || key == KEY_RCTRL
|| isprint(key);
}
void M_MenuTypingInput(INT32 key) void M_MenuTypingInput(INT32 key)
{ {
const UINT8 pid = 0; const UINT8 pid = 0;
// Determine when to check for keyboard inputs or controller inputs using menuKey, which is the key passed here as argument.
if (key > 0)
{
boolean gamepad = (key >= NUMKEYS);
M_SwitchVirtualKeyboard(gamepad);
if (gamepad)
return;
}
if (!menutyping.active)
return;
// Fade-in // Fade-in
if (menutyping.menutypingclose) if (menutyping.menutypingclose)
@ -233,6 +237,25 @@ void M_MenuTypingInput(INT32 key)
menutyping.menutypingfade++; menutyping.menutypingfade++;
} }
if (menutyping.menutypingfade >= 9) // either is visible
{
if (key == KEY_ENTER || key == KEY_ESCAPE)
{
M_CloseVirtualKeyboard();
M_SetMenuDelay(pid);
S_StartSound(NULL, sfx_s3k5b);
return;
}
if (menutyping.keyboardtyping)
{
M_ChangeStringCvar(key);
return;
}
}
if (menutyping.menutypingfade != destination) if (menutyping.menutypingfade != destination)
{ {
// Don't allow typing until it's fully opened. // Don't allow typing until it's fully opened.
@ -240,68 +263,6 @@ void M_MenuTypingInput(INT32 key)
} }
} }
// Determine when to check for keyboard inputs or controller inputs using menuKey, which is the key passed here as argument.
if (!menutyping.keyboardtyping) // controller inputs
{
// we pressed a keyboard input that's not any of our buttons
if (key >= 0 && M_IsTypingKey(key) && menucmd[pid].dpad_lr == 0 && menucmd[pid].dpad_ud == 0
&& !(menucmd[pid].buttons & MBT_A)
&& !(menucmd[pid].buttons & MBT_B)
&& !(menucmd[pid].buttons & MBT_C)
&& !(menucmd[pid].buttons & MBT_X)
&& !(menucmd[pid].buttons & MBT_Y)
&& !(menucmd[pid].buttons & MBT_Z)
&& !(menucmd[pid].buttons & MBT_START))
{
menutyping.keyboardtyping = true;
}
}
else // Keyboard inputs.
{
// On the flipside, if we're pressing any keyboard input, switch to controller inputs.
if (key >= 0 && !M_IsTypingKey(key) && (
M_MenuButtonPressed(pid, MBT_A)
|| M_MenuButtonPressed(pid, MBT_B)
|| M_MenuButtonPressed(pid, MBT_C)
|| M_MenuButtonPressed(pid, MBT_X)
|| M_MenuButtonPressed(pid, MBT_Y)
|| M_MenuButtonPressed(pid, MBT_Z)
|| M_MenuButtonPressed(pid, MBT_START)
|| (menucmd[pid].dpad_lr != 0 && menucmd[pid].prev_dpad_lr == 0)
|| (menucmd[pid].dpad_ud != 0 && menucmd[pid].prev_dpad_ud != 0)
))
{
/*CONS_Printf("key is %d, \
%c%c%c-%c%c%c-%c-%c%c%c%c\n",
key,
M_MenuButtonPressed(pid, MBT_A) ? 'A' : ' ',
M_MenuButtonPressed(pid, MBT_B) ? 'B' : ' ',
M_MenuButtonPressed(pid, MBT_C) ? 'C' : ' ',
M_MenuButtonPressed(pid, MBT_X) ? 'X' : ' ',
M_MenuButtonPressed(pid, MBT_Y) ? 'Y' : ' ',
M_MenuButtonPressed(pid, MBT_Z) ? 'Z' : ' ',
M_MenuButtonPressed(pid, MBT_START) ? '+' : ' ',
menucmd[pid].dpad_lr < 0 ? '<' : ' ',
menucmd[pid].dpad_ud > 0 ? '^' : ' ',
menucmd[pid].dpad_ud < 0 ? 'v' : ' ',
menucmd[pid].dpad_lr > 0 ? '>' : ' '
);*/
menutyping.keyboardtyping = false;
return;
}
// OTHERWISE, process keyboard inputs for typing!
if (key == KEY_ENTER || key == KEY_ESCAPE)
{
M_CloseVirtualKeyboard();
M_SetMenuDelay(pid);
S_StartSound(NULL, sfx_s3k5b);
return;
}
}
if (menucmd[pid].delay == 0 && !menutyping.keyboardtyping) // We must check for this here because we bypass the normal delay check to allow for normal keyboard inputs if (menucmd[pid].delay == 0 && !menutyping.keyboardtyping) // We must check for this here because we bypass the normal delay check to allow for normal keyboard inputs
{ {
if (menucmd[pid].dpad_ud > 0) // down if (menucmd[pid].dpad_ud > 0) // down
@ -418,9 +379,8 @@ void M_MenuTypingInput(INT32 key)
} }
} }
void M_OpenVirtualKeyboard(boolean gamepad, size_t cachelen, vkb_query_fn_t queryfn, menu_t *dummymenu) void M_OpenVirtualKeyboard(size_t cachelen, vkb_query_fn_t queryfn, menu_t *dummymenu)
{ {
menutyping.keyboardtyping = !gamepad;
menutyping.active = true; menutyping.active = true;
menutyping.menutypingclose = false; menutyping.menutypingclose = false;
@ -443,3 +403,9 @@ void M_OpenVirtualKeyboard(boolean gamepad, size_t cachelen, vkb_query_fn_t quer
M_SetupNextMenu(dummymenu, true); M_SetupNextMenu(dummymenu, true);
} }
} }
void M_SwitchVirtualKeyboard(boolean gamepad)
{
extern consvar_t cv_debugvirtualkeyboard;
menutyping.keyboardtyping = cv_debugvirtualkeyboard.value ? false : !gamepad;
}