|
@@ -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 <events_count>\n");
|
|
|
+ fprintf(repFile, "# e <frame> <event_type> <param0> <param1> <param2> // <event_type_name>\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
|