[Feature] Add GetKeyRepeat

This commit is contained in:
Nickolas McDonald 2023-08-17 17:05:33 -04:00
parent e4dcbd5180
commit 9a9535d9e5
3 changed files with 85 additions and 52 deletions

View File

@ -82,6 +82,7 @@
#define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad) #define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad) #define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported #define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
#define MAX_KEY_REPEAT 127 // Maximum number of key repeats per key
#define MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue #define MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue
#define MAX_CHAR_PRESSED_QUEUE 16 // Maximum number of characters in the char input queue #define MAX_CHAR_PRESSED_QUEUE 16 // Maximum number of characters in the char input queue

View File

@ -1119,6 +1119,7 @@ RLAPI bool IsKeyDown(int key); // Check if a key
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC) RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
RLAPI bool GetKeyRepeat(int key); // Get key's last repeat
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty

View File

@ -3750,7 +3750,7 @@ bool IsKeyPressed(int key)
{ {
bool pressed = false; bool pressed = false;
if ((CORE.Input.Keyboard.previousKeyState[key] == 0) && (CORE.Input.Keyboard.currentKeyState[key] == 1)) pressed = true; if ((CORE.Input.Keyboard.previousKeyState[key] == 0) && IsKeyDown(key)) pressed = true;
return pressed; return pressed;
} }
@ -3758,7 +3758,7 @@ bool IsKeyPressed(int key)
// Check if a key is being pressed (key held down) // Check if a key is being pressed (key held down)
bool IsKeyDown(int key) bool IsKeyDown(int key)
{ {
if (CORE.Input.Keyboard.currentKeyState[key] == 1) return true; if (CORE.Input.Keyboard.currentKeyState[key] >= 1) return true;
else return false; else return false;
} }
@ -3767,7 +3767,7 @@ bool IsKeyReleased(int key)
{ {
bool released = false; bool released = false;
if ((CORE.Input.Keyboard.previousKeyState[key] == 1) && (CORE.Input.Keyboard.currentKeyState[key] == 0)) released = true; if ((CORE.Input.Keyboard.previousKeyState[key] >= 1) && IsKeyUp(key)) released = true;
return released; return released;
} }
@ -3779,6 +3779,17 @@ bool IsKeyUp(int key)
else return false; else return false;
} }
// Get key's last repeat
bool GetKeyRepeat(int key)
{
if (CORE.Input.Keyboard.currentKeyState[key] > 1)
{
CORE.Input.Keyboard.currentKeyState[key]--;
return true;
}
return false;
}
// Get the last key pressed // Get the last key pressed
int GetKeyPressed(void) int GetKeyPressed(void)
{ {
@ -5158,6 +5169,25 @@ void SwapScreenBuffer(void)
#endif // PLATFORM_ANDROID || PLATFORM_RPI || PLATFORM_DRM #endif // PLATFORM_ANDROID || PLATFORM_RPI || PLATFORM_DRM
} }
static void RegisterCurrentKeyState(int key, bool state)
{
if (state && (CORE.Input.Keyboard.currentKeyState[key] < MAX_KEY_REPEAT)) CORE.Input.Keyboard.currentKeyState[key]++;
else CORE.Input.Keyboard.currentKeyState[key] = 0;
}
// Register previous keys states and remove unused key repeats
static void RegisterPreviousKeys(int count)
{
for (int i = 0; i < count; i++)
{
if (CORE.Input.Keyboard.currentKeyState[i] > 1)
{
CORE.Input.Keyboard.currentKeyState[i] = 1;
}
CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
}
}
// Register all input events // Register all input events
void PollInputEvents(void) void PollInputEvents(void)
{ {
@ -5178,9 +5208,7 @@ void PollInputEvents(void)
#endif #endif
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
// Register previous keys states RegisterPreviousKeys(MAX_KEYBOARD_KEYS);
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
PollKeyboardEvents(); PollKeyboardEvents();
// Register previous mouse states // Register previous mouse states
@ -5207,8 +5235,7 @@ void PollInputEvents(void)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
// Keyboard/Mouse input polling (automatically managed by GLFW3 through callback) // Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)
// Register previous keys states RegisterPreviousKeys(MAX_KEYBOARD_KEYS);
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
// Register previous mouse states // Register previous mouse states
for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i]; for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
@ -5390,7 +5417,7 @@ void PollInputEvents(void)
#if defined(PLATFORM_ANDROID) #if defined(PLATFORM_ANDROID)
// Register previous keys states // Register previous keys states
// NOTE: Android supports up to 260 keys // NOTE: Android supports up to 260 keys
for (int i = 0; i < 260; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i]; RegisterPreviousKeys(260);
// Android ALooper_pollAll() variables // Android ALooper_pollAll() variables
int pollResult = 0; int pollResult = 0;
@ -5583,16 +5610,18 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
{ {
if (key < 0) return; // Security check, macOS fn key generates -1 if (key < 0) return; // Security check, macOS fn key generates -1
// WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1 // WARNING: GLFW could return GLFW_REPEAT, we need to consider it as true
// to work properly with our implementation (IsKeyDown/IsKeyUp checks) // to work properly with our implementation (IsKeyDown/IsKeyUp checks)
if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0; if (action == GLFW_RELEASE)
else CORE.Input.Keyboard.currentKeyState[key] = 1; {
#if !defined(PLATFORM_WEB) #if !defined(PLATFORM_WEB)
// WARNING: Check if CAPS/NUM key modifiers are enabled and force down state for those keys // WARNING: Check if CAPS/NUM key modifiers are enabled and force down state for those keys
if (((key == KEY_CAPS_LOCK) && ((mods & GLFW_MOD_CAPS_LOCK) > 0)) || if (!((key == KEY_CAPS_LOCK) && ((mods & GLFW_MOD_CAPS_LOCK) > 0)) ||
((key == KEY_NUM_LOCK) && ((mods & GLFW_MOD_NUM_LOCK) > 0))) CORE.Input.Keyboard.currentKeyState[key] = 1; !((key == KEY_NUM_LOCK) && ((mods & GLFW_MOD_NUM_LOCK) > 0)))
#endif #endif
RegisterCurrentKeyState(key, false);
}
else RegisterCurrentKeyState(key, true);
// Check if there is space available in the key queue // Check if there is space available in the key queue
if ((CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE) && (action == GLFW_PRESS)) if ((CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE) && (action == GLFW_PRESS))
@ -6047,14 +6076,16 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
// Save current button and its state // Save current button and its state
// NOTE: Android key action is 0 for down and 1 for up // NOTE: Android key action is 0 for down and 1 for up
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_UP) RegisterCurrentKeyState(keycode, false);// Key up
else
{
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_PRESSED)
{ {
CORE.Input.Keyboard.currentKeyState[keycode] = 1; // Key down
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode; CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode;
CORE.Input.Keyboard.keyPressedQueueCount++; CORE.Input.Keyboard.keyPressedQueueCount++;
} }
else CORE.Input.Keyboard.currentKeyState[keycode] = 0; // Key up RegisterCurrentKeyState(keycode, true); // Key down
}
if (keycode == AKEYCODE_POWER) if (keycode == AKEYCODE_POWER)
{ {
@ -6367,7 +6398,7 @@ static void ProcessKeyboard(void)
if (keysBuffer[i] == 0x1b) if (keysBuffer[i] == 0x1b)
{ {
// Check if ESCAPE key has been pressed to stop program // Check if ESCAPE key has been pressed to stop program
if (bufferByteCount == 1) CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] = 1; if (bufferByteCount == 1) RegisterCurrentKeyState(CORE.Input.Keyboard.exitKey, true);
else else
{ {
if (keysBuffer[i + 1] == 0x5b) // Special function key if (keysBuffer[i + 1] == 0x5b) // Special function key
@ -6377,18 +6408,18 @@ static void ProcessKeyboard(void)
// Process special function keys (F1 - F12) // Process special function keys (F1 - F12)
switch (keysBuffer[i + 3]) switch (keysBuffer[i + 3])
{ {
case 0x41: CORE.Input.Keyboard.currentKeyState[290] = 1; break; // raylib KEY_F1 case 0x41: RegisterCurrentKeyState(290, true); break; // raylib KEY_F1
case 0x42: CORE.Input.Keyboard.currentKeyState[291] = 1; break; // raylib KEY_F2 case 0x42: RegisterCurrentKeyState(291, true); break; // raylib KEY_F2
case 0x43: CORE.Input.Keyboard.currentKeyState[292] = 1; break; // raylib KEY_F3 case 0x43: RegisterCurrentKeyState(292, true); break; // raylib KEY_F3
case 0x44: CORE.Input.Keyboard.currentKeyState[293] = 1; break; // raylib KEY_F4 case 0x44: RegisterCurrentKeyState(293, true); break; // raylib KEY_F4
case 0x45: CORE.Input.Keyboard.currentKeyState[294] = 1; break; // raylib KEY_F5 case 0x45: RegisterCurrentKeyState(294, true); break; // raylib KEY_F5
case 0x37: CORE.Input.Keyboard.currentKeyState[295] = 1; break; // raylib KEY_F6 case 0x37: RegisterCurrentKeyState(295, true); break; // raylib KEY_F6
case 0x38: CORE.Input.Keyboard.currentKeyState[296] = 1; break; // raylib KEY_F7 case 0x38: RegisterCurrentKeyState(296, true); break; // raylib KEY_F7
case 0x39: CORE.Input.Keyboard.currentKeyState[297] = 1; break; // raylib KEY_F8 case 0x39: RegisterCurrentKeyState(297, true); break; // raylib KEY_F8
case 0x30: CORE.Input.Keyboard.currentKeyState[298] = 1; break; // raylib KEY_F9 case 0x30: RegisterCurrentKeyState(298, true); break; // raylib KEY_F9
case 0x31: CORE.Input.Keyboard.currentKeyState[299] = 1; break; // raylib KEY_F10 case 0x31: RegisterCurrentKeyState(299, true); break; // raylib KEY_F10
case 0x33: CORE.Input.Keyboard.currentKeyState[300] = 1; break; // raylib KEY_F11 case 0x33: RegisterCurrentKeyState(300, true); break; // raylib KEY_F11
case 0x34: CORE.Input.Keyboard.currentKeyState[301] = 1; break; // raylib KEY_F12 case 0x34: RegisterCurrentKeyState(301, true); break; // raylib KEY_F12
default: break; default: break;
} }
@ -6399,10 +6430,10 @@ static void ProcessKeyboard(void)
{ {
switch (keysBuffer[i + 2]) switch (keysBuffer[i + 2])
{ {
case 0x41: CORE.Input.Keyboard.currentKeyState[265] = 1; break; // raylib KEY_UP case 0x41: RegisterCurrentKeyState(265, true); break; // raylib KEY_UP
case 0x42: CORE.Input.Keyboard.currentKeyState[264] = 1; break; // raylib KEY_DOWN case 0x42: RegisterCurrentKeyState(264, true); break; // raylib KEY_DOWN
case 0x43: CORE.Input.Keyboard.currentKeyState[262] = 1; break; // raylib KEY_RIGHT case 0x43: RegisterCurrentKeyState(262, true); break; // raylib KEY_RIGHT
case 0x44: CORE.Input.Keyboard.currentKeyState[263] = 1; break; // raylib KEY_LEFT case 0x44: RegisterCurrentKeyState(263, true); break; // raylib KEY_LEFT
default: break; default: break;
} }
@ -6415,14 +6446,14 @@ static void ProcessKeyboard(void)
} }
else if (keysBuffer[i] == 0x0a) // raylib KEY_ENTER (don't mix with <linux/input.h> KEY_*) else if (keysBuffer[i] == 0x0a) // raylib KEY_ENTER (don't mix with <linux/input.h> KEY_*)
{ {
CORE.Input.Keyboard.currentKeyState[257] = 1; RegisterCurrentKeyState(257, true);
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = 257; // Add keys pressed into queue CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = 257; // Add keys pressed into queue
CORE.Input.Keyboard.keyPressedQueueCount++; CORE.Input.Keyboard.keyPressedQueueCount++;
} }
else if (keysBuffer[i] == 0x7f) // raylib KEY_BACKSPACE else if (keysBuffer[i] == 0x7f) // raylib KEY_BACKSPACE
{ {
CORE.Input.Keyboard.currentKeyState[259] = 1; RegisterCurrentKeyState(259, true);
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = 257; // Add keys pressed into queue CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = 257; // Add keys pressed into queue
CORE.Input.Keyboard.keyPressedQueueCount++; CORE.Input.Keyboard.keyPressedQueueCount++;
@ -6432,9 +6463,9 @@ static void ProcessKeyboard(void)
// Translate lowercase a-z letters to A-Z // Translate lowercase a-z letters to A-Z
if ((keysBuffer[i] >= 97) && (keysBuffer[i] <= 122)) if ((keysBuffer[i] >= 97) && (keysBuffer[i] <= 122))
{ {
CORE.Input.Keyboard.currentKeyState[(int)keysBuffer[i] - 32] = 1; RegisterCurrentKeyState((int)keysBuffer[i] - 32, true);
} }
else CORE.Input.Keyboard.currentKeyState[(int)keysBuffer[i]] = 1; else RegisterCurrentKeyState((int)keysBuffer[i], true);
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keysBuffer[i]; // Add keys pressed into queue CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keysBuffer[i]; // Add keys pressed into queue
CORE.Input.Keyboard.keyPressedQueueCount++; CORE.Input.Keyboard.keyPressedQueueCount++;
@ -6442,11 +6473,11 @@ static void ProcessKeyboard(void)
} }
// Check exit key (same functionality as GLFW3 KeyCallback()) // Check exit key (same functionality as GLFW3 KeyCallback())
if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] == 1) CORE.Window.shouldClose = true; if (IsKeyDown(CORE.Input.Keyboard.exitKey)) CORE.Window.shouldClose = true;
#if defined(SUPPORT_SCREEN_CAPTURE) #if defined(SUPPORT_SCREEN_CAPTURE)
// Check screen capture key (raylib key: KEY_F12) // Check screen capture key (raylib key: KEY_F12)
if (CORE.Input.Keyboard.currentKeyState[301] == 1) if (IsKeyDown(301))
{ {
TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter)); TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter));
screenshotCounter++; screenshotCounter++;
@ -6748,7 +6779,7 @@ static void PollKeyboardEvents(void)
// WARNING: https://www.kernel.org/doc/Documentation/input/input.txt // WARNING: https://www.kernel.org/doc/Documentation/input/input.txt
// Event interface: 'value' is the value the event carries. Either a relative change for EV_REL, // Event interface: 'value' is the value the event carries. Either a relative change for EV_REL,
// absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for release, 1 for keypress and 2 for autorepeat // absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for release, 1 for keypress and 2 for autorepeat
CORE.Input.Keyboard.currentKeyState[keycode] = (event.value >= 1)? 1 : 0; RegisterCurrentKeyState(keycode, event.value >= 1);
if (event.value >= 1) if (event.value >= 1)
{ {
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode; // Register last key pressed CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode; // Register last key pressed
@ -6757,14 +6788,14 @@ static void PollKeyboardEvents(void)
#if defined(SUPPORT_SCREEN_CAPTURE) #if defined(SUPPORT_SCREEN_CAPTURE)
// Check screen capture key (raylib key: KEY_F12) // Check screen capture key (raylib key: KEY_F12)
if (CORE.Input.Keyboard.currentKeyState[301] == 1) if (IsKeyDown(301))
{ {
TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter)); TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter));
screenshotCounter++; screenshotCounter++;
} }
#endif #endif
if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] == 1) CORE.Window.shouldClose = true; if (IsKeyDown(CORE.Input.Keyboard.exitKey) CORE.Window.shouldClose = true;
TRACELOGD("RPI: KEY_%s ScanCode: %4i KeyCode: %4i", event.value == 0 ? "UP":"DOWN", event.code, keycode); TRACELOGD("RPI: KEY_%s ScanCode: %4i KeyCode: %4i", event.value == 0 ? "UP":"DOWN", event.code, keycode);
} }
@ -7446,10 +7477,10 @@ static void PlayAutomationEvent(unsigned int frame)
switch (events[i].type) switch (events[i].type)
{ {
// Input events // Input events
case INPUT_KEY_UP: CORE.Input.Keyboard.currentKeyState[events[i].params[0]] = false; break; // param[0]: key case INPUT_KEY_UP: RegisterCurrentKeyState(events[i].params[0]], false); break; // param[0]: key
case INPUT_KEY_DOWN: CORE.Input.Keyboard.currentKeyState[events[i].params[0]] = true; break; // param[0]: key case INPUT_KEY_DOWN: RegisterCurrentKeyState(events[i].params[0]], true); break; // param[0]: key
case INPUT_MOUSE_BUTTON_UP: CORE.Input.Mouse.currentButtonState[events[i].params[0]] = false; break; // param[0]: key case INPUT_MOUSE_BUTTON_UP: RegisterCurrentKeyState(events[i].params[0]], false); break; // param[0]: key
case INPUT_MOUSE_BUTTON_DOWN: CORE.Input.Mouse.currentButtonState[events[i].params[0]] = true; break; // param[0]: key case INPUT_MOUSE_BUTTON_DOWN: RegisterCurrentKeyState(events[i].params[0]], true); break; // param[0]: key
case INPUT_MOUSE_POSITION: // param[0]: x, param[1]: y case INPUT_MOUSE_POSITION: // param[0]: x, param[1]: y
{ {
CORE.Input.Mouse.currentPosition.x = (float)events[i].params[0]; CORE.Input.Mouse.currentPosition.x = (float)events[i].params[0];