diff --git a/src/config.h b/src/config.h index 6cec3446a..7c4777af6 100644 --- a/src/config.h +++ b/src/config.h @@ -55,6 +55,8 @@ #define SUPPORT_COMPRESSION_API 1 // Support saving binary data automatically to a generated storage.data file. This file is managed internally. #define SUPPORT_DATA_STORAGE 1 +// Support automatic generated events, loading and recording of those events when required +#define SUPPORT_EVENTS_AUTOMATION 1 // core: Configuration values //------------------------------------------------------------------------------------ diff --git a/src/core.c b/src/core.c index 6effe79f8..df6b642a0 100644 --- a/src/core.c +++ b/src/core.c @@ -82,6 +82,8 @@ * #define SUPPORT_DATA_STORAGE * Support saving binary data automatically to a generated storage.data file. This file is managed internally * +* #define SUPPORT_EVENTS_AUTOMATION +* Support automatic generated events, loading and recording of those events when required * * DEPENDENCIES: * rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD, OpenBSD, NetBSD, DragonFly) @@ -476,6 +478,7 @@ typedef struct CoreData { #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) || defined(PLATFORM_UWP) unsigned long long base; // Base time measure for hi-res timer #endif + unsigned int frameCounter; // Frame counter } Time; } CoreData; @@ -496,6 +499,93 @@ static int gifFramesCounter = 0; // GIF frames counter static bool gifRecording = false; // GIF recording state static MsfGifState gifState = { 0 }; // MSGIF context state #endif + +#if defined(SUPPORT_EVENTS_AUTOMATION) +#define MAX_CODE_AUTOMATION_EVENTS 16384 + +typedef enum AutomationEventType { + EVENT_NONE = 0, + // Input events + INPUT_KEY_UP, // param[0]: key + INPUT_KEY_DOWN, // param[0]: key + INPUT_KEY_PRESSED, // param[0]: key + INPUT_KEY_RELEASED, // param[0]: key + INPUT_MOUSE_BUTTON_UP, // param[0]: button + INPUT_MOUSE_BUTTON_DOWN, // param[0]: button + INPUT_MOUSE_POSITION, // param[0]: x, param[1]: y + INPUT_MOUSE_WHEEL_MOTION, // param[0]: delta + INPUT_GAMEPAD_CONNECT, // param[0]: gamepad + INPUT_GAMEPAD_DISCONNECT, // param[0]: gamepad + INPUT_GAMEPAD_BUTTON_UP, // param[0]: button + INPUT_GAMEPAD_BUTTON_DOWN, // param[0]: button + INPUT_GAMEPAD_AXIS_MOTION, // param[0]: axis, param[1]: delta + INPUT_TOUCH_UP, // param[0]: id + INPUT_TOUCH_DOWN, // param[0]: id + INPUT_TOUCH_POSITION, // param[0]: x, param[1]: y + INPUT_GESTURE, // param[0]: gesture + // Window events + WINDOW_CLOSE, // no params + WINDOW_MAXIMIZE, // no params + WINDOW_MINIMIZE, // no params + WINDOW_RESIZE, // param[0]: width, param[1]: height + // Custom events + ACTION_TAKE_SCREENSHOT, + ACTION_SETTARGETFPS +} AutomationEventType; + +// Event type +// Used to enable events flags +typedef enum { + EVENT_INPUT_KEYBOARD = 0, + EVENT_INPUT_MOUSE = 1, + EVENT_INPUT_GAMEPAD = 2, + EVENT_INPUT_TOUCH = 4, + EVENT_INPUT_GESTURE = 8, + EVENT_WINDOW = 16, + EVENT_CUSTOM = 32 +} EventType; + +static const char *autoEventTypeName[] = { + "EVENT_NONE", + "INPUT_KEY_UP", + "INPUT_KEY_DOWN", + "INPUT_KEY_PRESSED", + "INPUT_KEY_RELEASED", + "INPUT_MOUSE_BUTTON_UP", + "INPUT_MOUSE_BUTTON_DOWN", + "INPUT_MOUSE_POSITION", + "INPUT_MOUSE_WHEEL_MOTION", + "INPUT_GAMEPAD_CONNECT", + "INPUT_GAMEPAD_DISCONNECT", + "INPUT_GAMEPAD_BUTTON_UP", + "INPUT_GAMEPAD_BUTTON_DOWN", + "INPUT_GAMEPAD_AXIS_MOTION", + "INPUT_TOUCH_UP", + "INPUT_TOUCH_DOWN", + "INPUT_TOUCH_POSITION", + "INPUT_GESTURE", + "WINDOW_CLOSE", + "WINDOW_MAXIMIZE", + "WINDOW_MINIMIZE", + "WINDOW_RESIZE", + "ACTION_TAKE_SCREENSHOT", + "ACTION_SETTARGETFPS" +}; + +// Automation Event (20 bytes) +typedef struct AutomationEvent { + unsigned int frame; // Event frame + unsigned int type; // Event type (AutoEventType) + int params[3]; // Event parameters (if required) +} AutomationEvent; + +static AutomationEvent *events = NULL; // Events array +static unsigned int eventCount = 0; // Events count +static bool eventsPlaying = false; // Play events +static bool eventsRecording = false; // Record events + +//static short eventsEnabled = 0b0000001111111111; // Events enabled for checking +#endif //----------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- @@ -574,6 +664,13 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt #endif // PLATFORM_RPI || PLATFORM_DRM +#if defined(SUPPORT_EVENTS_AUTOMATION) +static void LoadAutomationEvents(const char *fileName); +static void ExportAutomationEvents(const char *fileName); +static void RecordAutomationEvent(unsigned int frame); +static void PlayAutomationEvent(unsigned int frame); +#endif + #if defined(_WIN32) // NOTE: We include Sleep() function signature here to avoid windows.h inclusion (kernel32 lib) void __stdcall Sleep(unsigned long msTimeout); // Required for Wait() @@ -799,7 +896,13 @@ void InitWindow(int width, int height, const char *title) CORE.Input.Mouse.currentPosition.x = (float)CORE.Window.screen.width/2.0f; CORE.Input.Mouse.currentPosition.y = (float)CORE.Window.screen.height/2.0f; -#endif // PLATFORM_ANDROID + +#if defined(SUPPORT_EVENTS_AUTOMATION) + events = (AutomationEvent *)malloc(MAX_CODE_AUTOMATION_EVENTS*sizeof(AutomationEvent)); + CORE.Time.frameCounter = 0; +#endif + +#endif // PLATFORM_DESKTOP || PLATFORM_WEB || PLATFORM_RPI || PLATFORM_DRM || PLATFORM_UWP } // Close window and unload OpenGL context @@ -925,6 +1028,10 @@ void CloseWindow(void) if (CORE.Input.Gamepad.threadId) pthread_join(CORE.Input.Gamepad.threadId, NULL); #endif +#if defined(SUPPORT_EVENTS_AUTOMATION) + free(events); +#endif + CORE.Window.ready = false; TRACELOG(LOG_INFO, "Window closed successfully"); } @@ -1876,8 +1983,35 @@ void EndDrawing(void) if (((gifFramesCounter/15)%2) == 1) { - DrawCircle(30, CORE.Window.screen.height - 20, 10, RED); - DrawText("RECORDING", 50, CORE.Window.screen.height - 25, 10, MAROON); + DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON); + DrawText("GIF RECORDING", 50, CORE.Window.screen.height - 25, 10, RED); + } + + rlDrawRenderBatchActive(); // Update and draw internal render batch + } +#endif + +#if defined(SUPPORT_EVENTS_AUTOMATION) + if (eventsRecording) + { + gifFramesCounter++; + + if (((gifFramesCounter/15)%2) == 1) + { + DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON); + DrawText("EVENTS RECORDING", 50, CORE.Window.screen.height - 25, 10, RED); + } + + rlDrawRenderBatchActive(); // Update and draw internal render batch + } + else if (eventsPlaying) + { + gifFramesCounter++; + + if (((gifFramesCounter/15)%2) == 1) + { + DrawCircle(30, CORE.Window.screen.height - 20, 10, LIME); + DrawText("EVENTS PLAYING", 50, CORE.Window.screen.height - 25, 10, GREEN); } rlDrawRenderBatchActive(); // Update and draw internal render batch @@ -1906,6 +2040,19 @@ void EndDrawing(void) } PollInputEvents(); // Poll user events + +#if defined(SUPPORT_EVENTS_AUTOMATION) + if (eventsRecording) RecordAutomationEvent(CORE.Time.frameCounter); + + // TODO: When should we play? After/before/replace PollInputEvents()? + if (eventsPlaying) + { + if (CORE.Time.frameCounter >= eventCount) eventsPlaying = false; + PlayAutomationEvent(CORE.Time.frameCounter); + } +#endif + + CORE.Time.frameCounter++; } // Initialize 2D mode with custom camera (2D) @@ -5039,6 +5186,22 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i } } #endif // SUPPORT_SCREEN_CAPTURE +#if defined(SUPPORT_EVENTS_AUTOMATION) + else if (key == GLFW_KEY_F11 && action == GLFW_PRESS) + { + eventsRecording = !eventsRecording; + + // On finish recording, we export events into a file + if (!eventsRecording) ExportAutomationEvents("eventsrec.rep"); + } + else if (key == GLFW_KEY_F9 && action == GLFW_PRESS) + { + LoadAutomationEvents("eventsrec.rep"); + eventsPlaying = true; + + TRACELOG(LOG_WARNING, "eventsPlaying enabled!"); + } +#endif else { // WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1 @@ -6627,3 +6790,363 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt return nearestIndex; } #endif + +#if defined(SUPPORT_EVENTS_AUTOMATION) +// NOTE: Loading happens over AutomationEvent *events +static void LoadAutomationEvents(const char *fileName) +{ + //unsigned char fileId[4] = { 0 }; + + // Load binary + /* + FILE *repFile = fopen(fileName, "rb"); + fread(fileId, 4, 1, repFile); + + if ((fileId[0] == 'r') && (fileId[1] == 'E') && (fileId[2] == 'P') && (fileId[1] == ' ')) + { + fread(&eventCount, sizeof(int), 1, repFile); + TraceLog(LOG_WARNING, "Events loaded: %i\n", eventCount); + fread(events, sizeof(AutomationEvent), eventCount, repFile); + } + + fclose(repFile); + */ + + // Load events (text file) + FILE *repFile = fopen(fileName, "rt"); + + if (repFile != NULL) + { + unsigned int count = 0; + char buffer[256] = { 0 }; + + fgets(buffer, 256, repFile); + + while (!feof(repFile)) + { + if (buffer[0] == 'c') sscanf(buffer, "c %i", &eventCount); + else if (buffer[0] == 'e') + { + sscanf(buffer, "e %d %d %d %d %d", &events[count].frame, &events[count].type, + &events[count].params[0], &events[count].params[1], &events[count].params[2]); + + count++; + } + + fgets(buffer, 256, repFile); + } + + if (count != eventCount) TRACELOG(LOG_WARNING, "Events count provided is different than count"); + + fclose(repFile); + } + + TRACELOG(LOG_WARNING, "Events loaded: %i", eventCount); +} + +// Export recorded events into a file +static void ExportAutomationEvents(const char *fileName) +{ + // TODO: eventCount is required -> header? -> rAEL + unsigned char fileId[4] = "rEP "; + + // Save as binary + /* + FILE *repFile = fopen(fileName, "wb"); + fwrite(fileId, 4, 1, repFile); + fwrite(&eventCount, sizeof(int), 1, repFile); + fwrite(events, sizeof(AutomationEvent), eventCount, repFile); + fclose(repFile); + */ + + // Export events as text + FILE *repFile = fopen(fileName, "wt"); + + if (repFile != NULL) + { + fprintf(repFile, "# Automation events list\n"); + fprintf(repFile, "# c \n"); + fprintf(repFile, "# e // \n"); + + fprintf(repFile, "c %i\n", eventCount); + for (int i = 0; i < eventCount; i++) + { + fprintf(repFile, "e %i %i %i %i %i // %s\n", events[i].frame, events[i].type, + events[i].params[0], events[i].params[1], events[i].params[2], autoEventTypeName[events[i].type]); + } + + fclose(repFile); + } +} + +// EndDrawing() -> After PollInputEvents() +// Check event in current frame and save into the events[i] array +static void RecordAutomationEvent(unsigned int frame) +{ + for (int key = 0; key < 512; key++) + { + // INPUT_KEY_UP (only saved once) + if (CORE.Input.Keyboard.previousKeyState[key] && !CORE.Input.Keyboard.currentKeyState[key]) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_KEY_UP; + events[eventCount].params[0] = key; + events[eventCount].params[1] = 0; + events[eventCount].params[2] = 0; + + TRACELOG(LOG_INFO, "[%i] INPUT_KEY_UP: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + + // INPUT_KEY_DOWN + if (CORE.Input.Keyboard.currentKeyState[key]) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_KEY_DOWN; + events[eventCount].params[0] = key; + events[eventCount].params[1] = 0; + events[eventCount].params[2] = 0; + + TRACELOG(LOG_INFO, "[%i] INPUT_KEY_DOWN: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + } + + for (int button = 0; button < MAX_MOUSE_BUTTONS; button++) + { + // INPUT_MOUSE_BUTTON_UP + if (CORE.Input.Mouse.previousButtonState[button] && !CORE.Input.Mouse.currentButtonState[button]) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_MOUSE_BUTTON_UP; + events[eventCount].params[0] = button; + events[eventCount].params[1] = 0; + events[eventCount].params[2] = 0; + + TRACELOG(LOG_INFO, "[%i] INPUT_MOUSE_BUTTON_UP: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + + // INPUT_MOUSE_BUTTON_DOWN + if (CORE.Input.Mouse.currentButtonState[button]) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_MOUSE_BUTTON_DOWN; + events[eventCount].params[0] = button; + events[eventCount].params[1] = 0; + events[eventCount].params[2] = 0; + + TRACELOG(LOG_INFO, "[%i] INPUT_MOUSE_BUTTON_DOWN: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + } + + // INPUT_MOUSE_POSITION (only saved if changed) + if (((int)CORE.Input.Mouse.currentPosition.x != (int)CORE.Input.Mouse.previousPosition.x) || + ((int)CORE.Input.Mouse.currentPosition.y != (int)CORE.Input.Mouse.previousPosition.y)) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_MOUSE_POSITION; + events[eventCount].params[0] = (int)CORE.Input.Mouse.currentPosition.x; + events[eventCount].params[1] = (int)CORE.Input.Mouse.currentPosition.y; + events[eventCount].params[2] = 0; + + TRACELOG(LOG_INFO, "[%i] INPUT_MOUSE_POSITION: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + + // INPUT_MOUSE_WHEEL_MOTION + if ((int)CORE.Input.Mouse.currentWheelMove != (int)CORE.Input.Mouse.previousWheelMove) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_MOUSE_WHEEL_MOTION; + events[eventCount].params[0] = (int)CORE.Input.Mouse.currentWheelMove; + events[eventCount].params[1] = 0; + events[eventCount].params[2] = 0; + + TRACELOG(LOG_INFO, "[%i] INPUT_MOUSE_WHEEL_MOTION: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + + for (int id = 0; id < MAX_TOUCH_POINTS; id++) + { + // INPUT_TOUCH_UP + if (CORE.Input.Touch.previousTouchState[id] && !CORE.Input.Touch.currentTouchState[id]) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_TOUCH_UP; + events[eventCount].params[0] = id; + events[eventCount].params[1] = 0; + events[eventCount].params[2] = 0; + + TRACELOG(LOG_INFO, "[%i] INPUT_TOUCH_UP: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + + // INPUT_TOUCH_DOWN + if (CORE.Input.Touch.currentTouchState[id]) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_TOUCH_DOWN; + events[eventCount].params[0] = id; + events[eventCount].params[1] = 0; + events[eventCount].params[2] = 0; + + TRACELOG(LOG_INFO, "[%i] INPUT_TOUCH_DOWN: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + + // INPUT_TOUCH_POSITION + // TODO: It requires the id! + /* + if (((int)CORE.Input.Touch.currentPosition[id].x != (int)CORE.Input.Touch.previousPosition[id].x) || + ((int)CORE.Input.Touch.currentPosition[id].y != (int)CORE.Input.Touch.previousPosition[id].y)) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_TOUCH_POSITION; + events[eventCount].params[0] = id; + events[eventCount].params[1] = (int)CORE.Input.Touch.currentPosition[id].x; + events[eventCount].params[2] = (int)CORE.Input.Touch.currentPosition[id].y; + + TRACELOG(LOG_INFO, "[%i] INPUT_TOUCH_POSITION: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + */ + } + + for (int gamepad = 0; gamepad < MAX_GAMEPADS; gamepad++) + { + // INPUT_GAMEPAD_CONNECT + /* + if ((CORE.Input.Gamepad.currentState[gamepad] != CORE.Input.Gamepad.previousState[gamepad]) && + (CORE.Input.Gamepad.currentState[gamepad] == true)) // Check if changed to ready + { + // TODO: Save gamepad connect event + } + */ + + // INPUT_GAMEPAD_DISCONNECT + /* + if ((CORE.Input.Gamepad.currentState[gamepad] != CORE.Input.Gamepad.previousState[gamepad]) && + (CORE.Input.Gamepad.currentState[gamepad] == false)) // Check if changed to not-ready + { + // TODO: Save gamepad disconnect event + } + */ + + for (int button = 0; button < MAX_GAMEPAD_BUTTONS; button++) + { + // INPUT_GAMEPAD_BUTTON_UP + if (CORE.Input.Gamepad.previousButtonState[gamepad][button] && !CORE.Input.Gamepad.currentButtonState[gamepad][button]) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_GAMEPAD_BUTTON_UP; + events[eventCount].params[0] = gamepad; + events[eventCount].params[1] = button; + events[eventCount].params[2] = 0; + + TRACELOG(LOG_INFO, "[%i] INPUT_GAMEPAD_BUTTON_UP: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + + // INPUT_GAMEPAD_BUTTON_DOWN + if (CORE.Input.Gamepad.currentButtonState[gamepad][button]) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_GAMEPAD_BUTTON_DOWN; + events[eventCount].params[0] = gamepad; + events[eventCount].params[1] = button; + events[eventCount].params[2] = 0; + + TRACELOG(LOG_INFO, "[%i] INPUT_GAMEPAD_BUTTON_DOWN: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + } + + for (int axis = 0; axis < MAX_GAMEPAD_AXIS; axis++) + { + // INPUT_GAMEPAD_AXIS_MOTION + if (CORE.Input.Gamepad.axisState[gamepad][axis] > 0.1f) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_GAMEPAD_AXIS_MOTION; + events[eventCount].params[0] = gamepad; + events[eventCount].params[1] = axis; + events[eventCount].params[2] = (int)(CORE.Input.Gamepad.axisState[gamepad][axis]*32768.0f); + + TRACELOG(LOG_INFO, "[%i] INPUT_GAMEPAD_AXIS_MOTION: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } + } + } + + // INPUT_GESTURE + if (GESTURES.current != GESTURE_NONE) + { + events[eventCount].frame = frame; + events[eventCount].type = INPUT_GESTURE; + events[eventCount].params[0] = GESTURES.current; + events[eventCount].params[1] = 0; + events[eventCount].params[2] = 0; + + TRACELOG(LOG_INFO, "[%i] INPUT_GESTURE: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); + eventCount++; + } +} + +// Play automation event +static void PlayAutomationEvent(unsigned int frame) +{ + for (unsigned int i = 0; i < eventCount; i++) + { + if (events[i].frame == frame) + { + switch (events[i].type) + { + // Input events + case INPUT_KEY_UP: CORE.Input.Keyboard.currentKeyState[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_MOUSE_BUTTON_UP: CORE.Input.Mouse.currentButtonState[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_POSITION: // param[0]: x, param[1]: y + { + CORE.Input.Mouse.currentPosition.x = (float)events[i].params[0]; + CORE.Input.Mouse.currentPosition.y = (float)events[i].params[1]; + } break; + case INPUT_MOUSE_WHEEL_MOTION: CORE.Input.Mouse.currentWheelMove = (float)events[i].params[0]; break; // param[0]: delta + case INPUT_TOUCH_UP: CORE.Input.Touch.currentTouchState[events[i].params[0]] = false; break; // param[0]: id + case INPUT_TOUCH_DOWN: CORE.Input.Touch.currentTouchState[events[i].params[0]] = true; break; // param[0]: id + case INPUT_TOUCH_POSITION: // param[0]: id, param[1]: x, param[2]: y + { + CORE.Input.Touch.position[events[i].params[0]].x = (float)events[i].params[1]; + CORE.Input.Touch.position[events[i].params[0]].y = (float)events[i].params[2]; + } break; + case INPUT_GAMEPAD_CONNECT: CORE.Input.Gamepad.ready[events[i].params[0]] = true; break; // param[0]: gamepad + case INPUT_GAMEPAD_DISCONNECT: CORE.Input.Gamepad.ready[events[i].params[0]] = false; break; // param[0]: gamepad + case INPUT_GAMEPAD_BUTTON_UP: CORE.Input.Gamepad.currentButtonState[events[i].params[0]][events[i].params[1]] = false; break; // param[0]: gamepad, param[1]: button + case INPUT_GAMEPAD_BUTTON_DOWN: CORE.Input.Gamepad.currentButtonState[events[i].params[0]][events[i].params[1]] = true; break; // param[0]: gamepad, param[1]: button + case INPUT_GAMEPAD_AXIS_MOTION: // param[0]: gamepad, param[1]: axis, param[2]: delta + { + CORE.Input.Gamepad.axisState[events[i].params[0]][events[i].params[1]] = ((float)events[i].params[2]/32768.0f); + } break; + case INPUT_GESTURE: GESTURES.current = events[i].params[0]; break; // param[0]: gesture (enum Gesture) -> gestures.h: GESTURES.current + + // Window events + case WINDOW_CLOSE: CORE.Window.shouldClose = true; break; + case WINDOW_MAXIMIZE: MaximizeWindow(); break; + case WINDOW_MINIMIZE: MinimizeWindow(); break; + case WINDOW_RESIZE: SetWindowSize(events[i].params[0], events[i].params[1]); break; + + // Custom events + case ACTION_TAKE_SCREENSHOT: + { + TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter)); + screenshotCounter++; + } break; + case ACTION_SETTARGETFPS: SetTargetFPS(events[i].params[0]); break; + default: break; + } + } + } +} +#endif