mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-10 23:02:03 +00:00
- major refactoring on the input code.
* moved the ASCII conversion hackery in SDLayer to a subfunction because this made things just messy. * integrated the keyboard callback's functionality directly into inputState for consolidation purposes. This was yet another independent layer in the keyboard management. * hook up D_PostEvent as the central place to dispatch keyboard input. This is now the only function that is getting called from the backend and a major prerequiside for swapping out the backend for GZDoom's. Todo: Route mouse input through that, too.
This commit is contained in:
parent
b747df60ee
commit
b4f91de7d3
5 changed files with 131 additions and 181 deletions
|
@ -26,12 +26,6 @@ int32_t g_borderless=2;
|
||||||
// input
|
// input
|
||||||
char inputdevices = 0;
|
char inputdevices = 0;
|
||||||
|
|
||||||
|
|
||||||
void (*keypresscallback)(int32_t, int32_t);
|
|
||||||
|
|
||||||
void keySetCallback(void (*callback)(int32_t, int32_t)) { keypresscallback = callback; }
|
|
||||||
|
|
||||||
|
|
||||||
vec2_t g_mousePos;
|
vec2_t g_mousePos;
|
||||||
vec2_t g_mouseAbs;
|
vec2_t g_mouseAbs;
|
||||||
int32_t g_mouseBits;
|
int32_t g_mouseBits;
|
||||||
|
|
|
@ -136,6 +136,7 @@ uint16_t joydead[9], joysatur[9];
|
||||||
|
|
||||||
#define MAX_ERRORTEXT 4096
|
#define MAX_ERRORTEXT 4096
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// I_Error
|
// I_Error
|
||||||
|
@ -1871,6 +1872,85 @@ int32_t handleevents_sdlcommon(SDL_Event *ev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// So this is how the engine handles text input?
|
||||||
|
// Argh. This is just gross.
|
||||||
|
int scancodetoasciihack(SDL_Event &ev)
|
||||||
|
{
|
||||||
|
SDL_Keycode keyvalue = ev.key.keysym.sym;
|
||||||
|
// Modifiers that have to be held down to be effective
|
||||||
|
// (excludes KMOD_NUM, for example).
|
||||||
|
static const int MODIFIERS =
|
||||||
|
KMOD_LSHIFT|KMOD_RSHIFT|KMOD_LCTRL|KMOD_RCTRL|
|
||||||
|
KMOD_LALT|KMOD_RALT|KMOD_LGUI|KMOD_RGUI;
|
||||||
|
|
||||||
|
// XXX: see osd.c, OSD_HandleChar(), there are more...
|
||||||
|
if (
|
||||||
|
(sc == SDL_SCANCODE_RETURN || sc == SDL_SCANCODE_KP_ENTER ||
|
||||||
|
sc == SDL_SCANCODE_ESCAPE ||
|
||||||
|
sc == SDL_SCANCODE_BACKSPACE ||
|
||||||
|
sc == SDL_SCANCODE_TAB ||
|
||||||
|
(((ev.key.keysym.mod) & MODIFIERS) == KMOD_LCTRL &&
|
||||||
|
(sc >= SDL_SCANCODE_A && sc <= SDL_SCANCODE_Z))))
|
||||||
|
{
|
||||||
|
char keyvalue;
|
||||||
|
switch (sc)
|
||||||
|
{
|
||||||
|
case SDL_SCANCODE_RETURN: case SDL_SCANCODE_KP_ENTER: keyvalue = '\r'; break;
|
||||||
|
case SDL_SCANCODE_ESCAPE: keyvalue = 27; break;
|
||||||
|
case SDL_SCANCODE_BACKSPACE: keyvalue = '\b'; break;
|
||||||
|
case SDL_SCANCODE_TAB: keyvalue = '\t'; break;
|
||||||
|
default: keyvalue = sc - SDL_SCANCODE_A + 1; break; // Ctrl+A --> 1, etc.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
ev.key.keysym.sym != g_keyAsciiTable[OSD_OSDKey()] && !SDL_IsTextInputActive()) // What is this? Preventing key repeat or what? :?
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Necessary for Duke 3D's method of entering cheats to work without showing IMEs.
|
||||||
|
SDL_TEXTINPUT is preferable overall, but with bitmap fonts it has no advantage.
|
||||||
|
*/
|
||||||
|
// Note that this is not how text input is supposed to be handled!
|
||||||
|
|
||||||
|
if ('a' <= keyvalue && keyvalue <= 'z')
|
||||||
|
{
|
||||||
|
if (!!(ev.key.keysym.mod & KMOD_SHIFT) ^ !!(ev.key.keysym.mod & KMOD_CAPS))
|
||||||
|
keyvalue -= 'a'-'A';
|
||||||
|
}
|
||||||
|
else if (ev.key.keysym.mod & KMOD_SHIFT)
|
||||||
|
{
|
||||||
|
keyvalue = g_keyAsciiTableShift[code];
|
||||||
|
}
|
||||||
|
else if (ev.key.keysym.mod & KMOD_NUM) // && !(ev.key.keysym.mod & KMOD_SHIFT)
|
||||||
|
{
|
||||||
|
switch (keyvalue)
|
||||||
|
{
|
||||||
|
case SDLK_KP_1: keyvalue = '1'; break;
|
||||||
|
case SDLK_KP_2: keyvalue = '2'; break;
|
||||||
|
case SDLK_KP_3: keyvalue = '3'; break;
|
||||||
|
case SDLK_KP_4: keyvalue = '4'; break;
|
||||||
|
case SDLK_KP_5: keyvalue = '5'; break;
|
||||||
|
case SDLK_KP_6: keyvalue = '6'; break;
|
||||||
|
case SDLK_KP_7: keyvalue = '7'; break;
|
||||||
|
case SDLK_KP_8: keyvalue = '8'; break;
|
||||||
|
case SDLK_KP_9: keyvalue = '9'; break;
|
||||||
|
case SDLK_KP_0: keyvalue = '0'; break;
|
||||||
|
case SDLK_KP_PERIOD: keyvalue = '.'; break;
|
||||||
|
case SDLK_KP_COMMA: keyvalue = ','; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (keyvalue)
|
||||||
|
{
|
||||||
|
case SDLK_KP_DIVIDE: keyvalue = '/'; break;
|
||||||
|
case SDLK_KP_MULTIPLY: keyvalue = '*'; break;
|
||||||
|
case SDLK_KP_MINUS: keyvalue = '-'; break;
|
||||||
|
case SDLK_KP_PLUS: keyvalue = '+'; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyvalue >= 0x80) keyvalue = 0; // Sadly ASCII only...
|
||||||
|
return keyvalue;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t handleevents_pollsdl(void);
|
int32_t handleevents_pollsdl(void);
|
||||||
#if SDL_MAJOR_VERSION != 1
|
#if SDL_MAJOR_VERSION != 1
|
||||||
// SDL 2.0 specific event handling
|
// SDL 2.0 specific event handling
|
||||||
|
@ -1901,158 +1981,33 @@ int32_t handleevents_pollsdl(void)
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
{
|
{
|
||||||
auto const &sc = ev.key.keysym.scancode;
|
auto const &sc = ev.key.keysym.scancode;
|
||||||
|
|
||||||
code = keytranslation[sc];
|
code = keytranslation[sc];
|
||||||
|
|
||||||
// Modifiers that have to be held down to be effective
|
// The pause key generates a release event right after
|
||||||
// (excludes KMOD_NUM, for example).
|
// the pressing one. As a result, it gets unseen
|
||||||
static const int MODIFIERS =
|
// by the game most of the time.
|
||||||
KMOD_LSHIFT|KMOD_RSHIFT|KMOD_LCTRL|KMOD_RCTRL|
|
if (code == 0x59 && ev.type == SDL_KEYUP) // pause
|
||||||
KMOD_LALT|KMOD_RALT|KMOD_LGUI|KMOD_RGUI;
|
break;
|
||||||
|
|
||||||
|
|
||||||
// XXX: see osd.c, OSD_HandleChar(), there are more...
|
int keyvalue = ev.type == SDL_KEYDOWN? scancodetoasciihack(ev) : 0;
|
||||||
if (ev.key.type == SDL_KEYDOWN && !inputState.keyBufferFull() &&
|
if (keyvalue > 0)
|
||||||
(sc == SDL_SCANCODE_RETURN || sc == SDL_SCANCODE_KP_ENTER ||
|
{
|
||||||
sc == SDL_SCANCODE_ESCAPE ||
|
keyvalue = OSD_HandleChar(keyvalue); // returns the char if it doesn't process it.
|
||||||
sc == SDL_SCANCODE_BACKSPACE ||
|
if (keyvalue == 0) break;
|
||||||
sc == SDL_SCANCODE_TAB ||
|
}
|
||||||
(((ev.key.keysym.mod) & MODIFIERS) == KMOD_LCTRL &&
|
j = OSD_HandleScanCode(code, (ev.type == SDL_KEYDOWN));
|
||||||
(sc >= SDL_SCANCODE_A && sc <= SDL_SCANCODE_Z))))
|
// returns are:
|
||||||
{
|
// j == -1: Console was opened
|
||||||
char keyvalue;
|
// j == 0: Console is active and used the key
|
||||||
switch (sc)
|
// j == 2: Console is inactive and did not use the key
|
||||||
{
|
|
||||||
case SDL_SCANCODE_RETURN: case SDL_SCANCODE_KP_ENTER: keyvalue = '\r'; break;
|
if (j == -1) inputState.ClearKeysDown(); // Flush the entire keyboard state for the game when the console opens.
|
||||||
case SDL_SCANCODE_ESCAPE: keyvalue = 27; break;
|
if (j <= 0) break; // Do not pass on to the game
|
||||||
case SDL_SCANCODE_BACKSPACE: keyvalue = '\b'; break;
|
|
||||||
case SDL_SCANCODE_TAB: keyvalue = '\t'; break;
|
|
||||||
default: keyvalue = sc - SDL_SCANCODE_A + 1; break; // Ctrl+A --> 1, etc.
|
|
||||||
}
|
|
||||||
if (OSD_HandleChar(keyvalue))
|
|
||||||
inputState.keyBufferInsert(keyvalue);
|
|
||||||
}
|
|
||||||
else if (ev.key.type == SDL_KEYDOWN &&
|
|
||||||
ev.key.keysym.sym != g_keyAsciiTable[OSD_OSDKey()] && !inputState.keyBufferFull() &&
|
|
||||||
!SDL_IsTextInputActive())
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Necessary for Duke 3D's method of entering cheats to work without showing IMEs.
|
|
||||||
SDL_TEXTINPUT is preferable overall, but with bitmap fonts it has no advantage.
|
|
||||||
*/
|
|
||||||
SDL_Keycode keyvalue = ev.key.keysym.sym;
|
|
||||||
|
|
||||||
if ('a' <= keyvalue && keyvalue <= 'z')
|
event_t ev = { (uint8_t)ev.type == SDL_KEYUP? EV_KeyUp : EV_KeyDown, 0, (int16_t)code, (int16_t)keyvalue };
|
||||||
{
|
D_PostEvent(&ev);
|
||||||
if (!!(ev.key.keysym.mod & KMOD_SHIFT) ^ !!(ev.key.keysym.mod & KMOD_CAPS))
|
|
||||||
keyvalue -= 'a'-'A';
|
|
||||||
}
|
|
||||||
else if (ev.key.keysym.mod & KMOD_SHIFT)
|
|
||||||
{
|
|
||||||
switch (keyvalue)
|
|
||||||
{
|
|
||||||
case '\'': keyvalue = '"'; break;
|
|
||||||
|
|
||||||
case ',': keyvalue = '<'; break;
|
|
||||||
case '-': keyvalue = '_'; break;
|
|
||||||
case '.': keyvalue = '>'; break;
|
|
||||||
case '/': keyvalue = '?'; break;
|
|
||||||
case '0': keyvalue = ')'; break;
|
|
||||||
case '1': keyvalue = '!'; break;
|
|
||||||
case '2': keyvalue = '@'; break;
|
|
||||||
case '3': keyvalue = '#'; break;
|
|
||||||
case '4': keyvalue = '$'; break;
|
|
||||||
case '5': keyvalue = '%'; break;
|
|
||||||
case '6': keyvalue = '^'; break;
|
|
||||||
case '7': keyvalue = '&'; break;
|
|
||||||
case '8': keyvalue = '*'; break;
|
|
||||||
case '9': keyvalue = '('; break;
|
|
||||||
|
|
||||||
case ';': keyvalue = ':'; break;
|
|
||||||
|
|
||||||
case '=': keyvalue = '+'; break;
|
|
||||||
|
|
||||||
case '[': keyvalue = '{'; break;
|
|
||||||
case '\\': keyvalue = '|'; break;
|
|
||||||
case ']': keyvalue = '}'; break;
|
|
||||||
|
|
||||||
case '`': keyvalue = '~'; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ev.key.keysym.mod & KMOD_NUM) // && !(ev.key.keysym.mod & KMOD_SHIFT)
|
|
||||||
{
|
|
||||||
switch (keyvalue)
|
|
||||||
{
|
|
||||||
case SDLK_KP_1: keyvalue = '1'; break;
|
|
||||||
case SDLK_KP_2: keyvalue = '2'; break;
|
|
||||||
case SDLK_KP_3: keyvalue = '3'; break;
|
|
||||||
case SDLK_KP_4: keyvalue = '4'; break;
|
|
||||||
case SDLK_KP_5: keyvalue = '5'; break;
|
|
||||||
case SDLK_KP_6: keyvalue = '6'; break;
|
|
||||||
case SDLK_KP_7: keyvalue = '7'; break;
|
|
||||||
case SDLK_KP_8: keyvalue = '8'; break;
|
|
||||||
case SDLK_KP_9: keyvalue = '9'; break;
|
|
||||||
case SDLK_KP_0: keyvalue = '0'; break;
|
|
||||||
case SDLK_KP_PERIOD: keyvalue = '.'; break;
|
|
||||||
case SDLK_KP_COMMA: keyvalue = ','; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (keyvalue)
|
|
||||||
{
|
|
||||||
case SDLK_KP_DIVIDE: keyvalue = '/'; break;
|
|
||||||
case SDLK_KP_MULTIPLY: keyvalue = '*'; break;
|
|
||||||
case SDLK_KP_MINUS: keyvalue = '-'; break;
|
|
||||||
case SDLK_KP_PLUS: keyvalue = '+'; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((unsigned)keyvalue <= 0x7Fu)
|
|
||||||
{
|
|
||||||
if (OSD_HandleChar(keyvalue))
|
|
||||||
inputState.keyBufferInsert(keyvalue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// initprintf("SDL2: got key %d, %d, %u\n", ev.key.keysym.scancode, code, ev.key.type);
|
|
||||||
|
|
||||||
// hook in the osd
|
|
||||||
if ((j = OSD_HandleScanCode(code, (ev.key.type == SDL_KEYDOWN))) <= 0)
|
|
||||||
{
|
|
||||||
if (j == -1) // osdkey
|
|
||||||
{
|
|
||||||
for (j = 0; j < NUMKEYS; ++j)
|
|
||||||
{
|
|
||||||
if (inputState.GetKeyStatus(j))
|
|
||||||
{
|
|
||||||
if (keypresscallback)
|
|
||||||
keypresscallback(j, 0);
|
|
||||||
}
|
|
||||||
inputState.keySetState(j, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ev.key.type == SDL_KEYDOWN)
|
|
||||||
{
|
|
||||||
if (!inputState.GetKeyStatus(code))
|
|
||||||
{
|
|
||||||
if (keypresscallback)
|
|
||||||
keypresscallback(code, 1);
|
|
||||||
}
|
|
||||||
inputState.keySetState(code, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
# if 1
|
|
||||||
// The pause key generates a release event right after
|
|
||||||
// the pressing one. As a result, it gets unseen
|
|
||||||
// by the game most of the time.
|
|
||||||
if (code == 0x59) // pause
|
|
||||||
break;
|
|
||||||
# endif
|
|
||||||
inputState.keySetState(code, 0);
|
|
||||||
if (keypresscallback)
|
|
||||||
keypresscallback(code, 0);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "c_bind.h"
|
#include "c_bind.h"
|
||||||
#include "d_event.h"
|
#include "d_event.h"
|
||||||
#include "d_gui.h"
|
#include "d_gui.h"
|
||||||
|
#include "inputstate.h"
|
||||||
|
|
||||||
int eventhead;
|
int eventhead;
|
||||||
int eventtail;
|
int eventtail;
|
||||||
|
@ -193,6 +194,15 @@ void D_PostEvent (const event_t *ev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Add the key to the global keyboard state.
|
||||||
|
// This is probably the biggest roadblock with the input system as it undermines a proper event driven approach.
|
||||||
|
// Too much code depends on just checking this instead of waiting for events to happen.
|
||||||
|
// Here's also definitely not the best place to maintain the keyboard state but right now it's unavoidable to do this outside the event processing because so much code depends on it.
|
||||||
|
// Once all those busy waiting loops can poll the event queue for a proper skip event, this will mostly go away.
|
||||||
|
inputState.AddEvent(ev);
|
||||||
|
|
||||||
|
// Also add it to the event queue - this is where everything should transition to eventually.
|
||||||
eventhead = (eventhead+1)&(NUM_EVENTS-1);
|
eventhead = (eventhead+1)&(NUM_EVENTS-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,4 +240,4 @@ void D_RemoveNextCharEvent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -247,11 +247,14 @@ public:
|
||||||
|
|
||||||
void keySetState(int32_t key, int32_t state)
|
void keySetState(int32_t key, int32_t state)
|
||||||
{
|
{
|
||||||
|
if (state && !GetKeyStatus(key))
|
||||||
|
{
|
||||||
|
KB_LastScan = key;
|
||||||
|
}
|
||||||
|
|
||||||
SetKeyStatus(key, state);
|
SetKeyStatus(key, state);
|
||||||
event_t ev = { (uint8_t)(state ? EV_KeyDown : EV_KeyUp), 0, (int16_t)key };
|
event_t ev = { (uint8_t)(state ? EV_KeyDown : EV_KeyUp), 0, (int16_t)key };
|
||||||
|
|
||||||
D_PostEvent(&ev);
|
|
||||||
|
|
||||||
if (state)
|
if (state)
|
||||||
{
|
{
|
||||||
g_keyFIFO[g_keyFIFOend] = key;
|
g_keyFIFO[g_keyFIFOend] = key;
|
||||||
|
@ -290,6 +293,12 @@ public:
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void keySetChar(int key)
|
||||||
|
{
|
||||||
|
g_keyAsciiFIFO[g_keyAsciiEnd] = key;
|
||||||
|
g_keyAsciiEnd = ((g_keyAsciiEnd + 1) & (KEYFIFOSIZ - 1));
|
||||||
|
}
|
||||||
|
|
||||||
void keyFlushChars(void)
|
void keyFlushChars(void)
|
||||||
{
|
{
|
||||||
|
@ -323,19 +332,15 @@ public:
|
||||||
KB_LastScan = 0;
|
KB_LastScan = 0;
|
||||||
ClearAllKeyStatus();
|
ClearAllKeyStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddEvent(const event_t *ev)
|
||||||
|
{
|
||||||
|
keySetState(ev->data1, ev->type == EV_KeyDown);
|
||||||
|
if (ev->data2) keySetChar(ev->data2);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern InputState inputState;
|
extern InputState inputState;
|
||||||
|
|
||||||
static inline void KB_KeyEvent(int32_t scancode, int32_t keypressed)
|
|
||||||
{
|
|
||||||
if (keypressed) inputState.SetLastScanCode(scancode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void keySetCallback(void (*callback)(int32_t, int32_t));
|
|
||||||
inline void KB_Startup(void) { keySetCallback(KB_KeyEvent); }
|
|
||||||
inline void KB_Shutdown(void) { keySetCallback((void (*)(int32_t, int32_t))NULL); }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,24 +48,10 @@ static FORCE_INLINE void Menu_StartTextInput()
|
||||||
{
|
{
|
||||||
inputState.keyFlushChars();
|
inputState.keyFlushChars();
|
||||||
inputState.ClearKeysDown();
|
inputState.ClearKeysDown();
|
||||||
#if defined EDUKE32_TOUCH_DEVICES && defined SDL_MAJOR_VERSION && SDL_MAJOR_VERSION > 1
|
|
||||||
# if defined __ANDROID__
|
|
||||||
AndroidShowKeyboard(1);
|
|
||||||
# else
|
|
||||||
SDL_StartTextInput();
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static FORCE_INLINE void Menu_StopTextInput()
|
static FORCE_INLINE void Menu_StopTextInput()
|
||||||
{
|
{
|
||||||
#if defined EDUKE32_TOUCH_DEVICES && defined SDL_MAJOR_VERSION && SDL_MAJOR_VERSION > 1
|
|
||||||
# if defined __ANDROID__
|
|
||||||
AndroidShowKeyboard(0);
|
|
||||||
# else
|
|
||||||
SDL_StopTextInput();
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static FORCE_INLINE void rotatesprite_ybounds(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t dapalnum, int32_t dastat, int32_t ydim_upper, int32_t ydim_lower)
|
static FORCE_INLINE void rotatesprite_ybounds(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t dapalnum, int32_t dastat, int32_t ydim_upper, int32_t ydim_lower)
|
||||||
|
|
Loading…
Reference in a new issue