#pragma once #include #include "tarray.h" #include "scancodes.h" #include "c_bind.h" #include "c_buttons.h" #include "d_event.h" #include "osd.h" #include "m_joy.h" #include "gamecvars.h" extern char appactive; typedef uint8_t kb_scancode; extern int GUICapture; // This encapsulates the entire game-readable input state which previously was spread out across several files. enum { MAXMOUSEBUTTONS = 10, }; extern bool g_mouseGrabbed; extern bool g_mouseEnabled; extern bool g_mouseInsideWindow; extern bool g_mouseLockedToWindow; enum EMouseBits { LEFT_MOUSE = 1, RIGHT_MOUSE = 2, MIDDLE_MOUSE = 4, THUMB_MOUSE = 8, WHEELUP_MOUSE = 16, WHEELDOWN_MOUSE= 32, THUMB2_MOUSE = 64, WHEELLEFT_MOUSE = 128, WHEELRIGHT_MOUSE = 256, }; enum { MOUSE_IDLE = 0, MOUSE_PRESSED, MOUSE_HELD, MOUSE_RELEASED, }; struct ControlInfo { int32_t dx; int32_t dy; int32_t dz; int32_t dyaw; int32_t dpitch; int32_t droll; int32_t mousex; int32_t mousey; }; class InputState { enum { KEYFIFOSIZ = 64, }; uint8_t KeyStatus[NUM_KEYS]; char g_keyFIFO[KEYFIFOSIZ]; char g_keyAsciiFIFO[KEYFIFOSIZ]; uint8_t g_keyFIFOpos; uint8_t g_keyFIFOend; uint8_t g_keyAsciiPos; uint8_t g_keyAsciiEnd; kb_scancode KB_LastScan; int g_mouseBits; uint8_t g_mouseClickState; vec2_t g_mousePos; vec2_t g_mouseAbs; public: uint8_t GetKeyStatus(int key) { return KeyStatus[key]; } void SetKeyStatus(int key, int state = 1) { KeyStatus[key] = (uint8_t)state; } void ClearKeyStatus(int key) { KeyStatus[key] = 0; } void ClearAllKeyStatus() { memset(KeyStatus, 0, sizeof(KeyStatus)); } bool AltPressed() { return KeyStatus[sc_LeftAlt] || KeyStatus[sc_RightAlt]; } bool CtrlPressed() { return KeyStatus[sc_LeftControl] || KeyStatus[sc_RightControl]; } bool WinPressed() { return KeyStatus[sc_LeftWin] || KeyStatus[sc_RightWin]; } bool ShiftPressed() { return KeyStatus[sc_LeftShift] || KeyStatus[sc_RightShift]; } bool EscapePressed() { return !!KeyStatus[sc_Escape]; } void SetBindsEnabled(bool on) { } bool keyBufferWaiting() { return (g_keyAsciiPos != g_keyAsciiEnd); } int keyBufferFull(void) { return ((g_keyAsciiEnd + 1) & (KEYFIFOSIZ - 1)) == g_keyAsciiPos; } void keyBufferInsert(char code) { g_keyAsciiFIFO[g_keyAsciiEnd] = code; g_keyAsciiEnd = ((g_keyAsciiEnd + 1) & (KEYFIFOSIZ - 1)); } void keySetState(int32_t key, int32_t state) { if (state && !GetKeyStatus(key)) { KB_LastScan = key; } SetKeyStatus(key, state); event_t ev = { (uint8_t)(state ? EV_KeyDown : EV_KeyUp), 0, (int16_t)key }; if (state) { g_keyFIFO[g_keyFIFOend] = key; g_keyFIFO[(g_keyFIFOend + 1) & (KEYFIFOSIZ - 1)] = state; g_keyFIFOend = ((g_keyFIFOend + 2) & (KEYFIFOSIZ - 1)); } } char keyGetScan(void) { if (g_keyFIFOpos == g_keyFIFOend) return 0; char const c = g_keyFIFO[g_keyFIFOpos]; g_keyFIFOpos = ((g_keyFIFOpos + 2) & (KEYFIFOSIZ - 1)); return c; } void keyFlushScans(void) { memset(&g_keyFIFO, 0, sizeof(g_keyFIFO)); g_keyFIFOpos = g_keyFIFOend = 0; } // // character-based input functions // char keyGetChar(void) { if (g_keyAsciiPos == g_keyAsciiEnd) return 0; char const c = g_keyAsciiFIFO[g_keyAsciiPos]; g_keyAsciiPos = ((g_keyAsciiPos + 1) & (KEYFIFOSIZ - 1)); return c; } void keySetChar(int key) { g_keyAsciiFIFO[g_keyAsciiEnd] = key; g_keyAsciiEnd = ((g_keyAsciiEnd + 1) & (KEYFIFOSIZ - 1)); } void keyFlushChars(void) { memset(&g_keyAsciiFIFO, 0, sizeof(g_keyAsciiFIFO)); g_keyAsciiPos = g_keyAsciiEnd = 0; } inline bool UnboundKeyPressed(int scan) { return (GetKeyStatus(scan) != 0 && Bindings.GetBind(scan) == nullptr); } kb_scancode GetLastScanCode() { return (KB_LastScan); } void SetLastScanCode(kb_scancode scancode) { KB_LastScan = (scancode); } void ClearLastScanCode() { KB_LastScan = sc_None; } void ClearKeysDown(void) { KB_LastScan = 0; ClearAllKeyStatus(); } void mouseSetBit(int val, int state) { if (state) g_mouseBits |= val; else g_mouseBits &=~val; } void handleevents_updatemousestate(uint8_t state) { g_mouseClickState = state == EV_KeyUp ? MOUSE_RELEASED : MOUSE_PRESSED; } void AddEvent(const event_t* ev); int32_t mouseReadButtons(void) { return (!g_mouseEnabled || !appactive || !g_mouseInsideWindow || GUICapture) ? 0 : g_mouseBits; } int mouseClickState() { return g_mouseClickState; } void clearMouseClickState() { g_mouseClickState = MOUSE_IDLE; } int32_t mouseAdvanceClickState(void) { switch (g_mouseClickState) { case MOUSE_PRESSED: g_mouseClickState = MOUSE_HELD; return 1; case MOUSE_RELEASED: g_mouseClickState = MOUSE_IDLE; return 1; case MOUSE_HELD: return 1; } return 0; } void MouseSetPos(int x, int y) { g_mousePos = { x, y }; } void MouseAddToPos(int x, int y) { g_mousePos.x += x; g_mousePos.y += y; } void MouseSetAbs(int x, int y) { g_mouseAbs = { x, y }; } bool gamePadActive() { // fixme: This needs to be tracked. return false; } int32_t MouseGetButtons(void) { return mouseReadButtons(); } inline void MouseClearButton(int32_t b) { g_mouseBits &= ~b; } inline void MouseClearAllButtonss(void) { g_mouseBits = 0; } int32_t mouseReadAbs(vec2_t* const pResult); void GetMouseDelta(ControlInfo* info); void ClearAllInput() { ClearKeysDown(); keyFlushChars(); keyFlushScans(); } }; extern InputState inputState; inline void CONTROL_GetInput(ControlInfo* info) { memset(info, 0, sizeof(ControlInfo)); if (in_mouse) inputState.GetMouseDelta(info); if (in_joystick) { // Handle joysticks/game controllers. float joyaxes[NUM_JOYAXIS]; I_GetAxes(joyaxes); info->dyaw += joyaxes[JOYAXIS_Yaw]; info->dx += joyaxes[JOYAXIS_Side]; info->dz += joyaxes[JOYAXIS_Forward]; info->dpitch += joyaxes[JOYAXIS_Pitch]; } }