#ifdef USING_SDL3_PACKAGE
#define USING_SDL3_PROJECT
#endif
#ifndef SDL_ENABLE_OLD_NAMES
#define SDL_ENABLE_OLD_NAMES
#endif
#ifdef USING_SDL3_PROJECT
#include "SDL3/SDL.h"
#elif defined(USING_SDL2_PROJECT)
#include "SDL2/SDL.h"
#else
#include "SDL.h"
#endif
#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
#if defined(GRAPHICS_API_OPENGL_ES2)
#else
#ifdef USING_SDL3_PROJECT
#include "SDL3/SDL_opengl.h"
#elif defined(USING_SDL2_PROJECT)
#include "SDL2/SDL_opengl.h"
#else
#include "SDL_opengl.h"
#endif
#endif
#endif
#ifndef MAX_CLIPBOARD_BUFFER_LENGTH
#define MAX_CLIPBOARD_BUFFER_LENGTH 1024
#endif
#if ((defined(SDL_MAJOR_VERSION) && (SDL_MAJOR_VERSION == 3)) && (defined(SDL_MINOR_VERSION) && (SDL_MINOR_VERSION >= 1)))
#ifndef USING_VERSION_SDL3
#define USING_VERSION_SDL3
#endif
#endif
#define SCANCODE_MAPPED_NUM 232
typedef struct {
SDL_Window *window;
SDL_GLContext glContext;
SDL_GameController *gamepad[MAX_GAMEPADS];
SDL_JoystickID gamepadId[MAX_GAMEPADS]; SDL_Cursor *cursor;
} PlatformData;
extern CoreData CORE;
static PlatformData platform = { 0 };
static const KeyboardKey mapScancodeToKey[SCANCODE_MAPPED_NUM] = {
KEY_NULL, 0,
0,
0,
KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_ONE, KEY_TWO, KEY_THREE, KEY_FOUR, KEY_FIVE, KEY_SIX, KEY_SEVEN, KEY_EIGHT, KEY_NINE, KEY_ZERO, KEY_ENTER, KEY_ESCAPE, KEY_BACKSPACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFT_BRACKET, KEY_RIGHT_BRACKET, KEY_BACKSLASH, 0, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_PERIOD, KEY_SLASH, KEY_CAPS_LOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_PRINT_SCREEN, KEY_SCROLL_LOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGE_UP, KEY_DELETE, KEY_END, KEY_PAGE_DOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP, KEY_NUM_LOCK, KEY_KP_DIVIDE, KEY_KP_MULTIPLY, KEY_KP_SUBTRACT, KEY_KP_ADD, KEY_KP_ENTER, KEY_KP_1, KEY_KP_2, KEY_KP_3, KEY_KP_4, KEY_KP_5, KEY_KP_6, KEY_KP_7, KEY_KP_8, KEY_KP_9, KEY_KP_0, KEY_KP_DECIMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
KEY_LEFT_CONTROL, KEY_LEFT_SHIFT, KEY_LEFT_ALT, KEY_LEFT_SUPER, KEY_RIGHT_CONTROL, KEY_RIGHT_SHIFT, KEY_RIGHT_ALT, KEY_RIGHT_SUPER };
static const int CursorsLUT[] = {
SDL_SYSTEM_CURSOR_ARROW, SDL_SYSTEM_CURSOR_ARROW, SDL_SYSTEM_CURSOR_IBEAM, SDL_SYSTEM_CURSOR_CROSSHAIR, SDL_SYSTEM_CURSOR_HAND, SDL_SYSTEM_CURSOR_SIZEWE, SDL_SYSTEM_CURSOR_SIZENS, SDL_SYSTEM_CURSOR_SIZENWSE, SDL_SYSTEM_CURSOR_SIZENESW, SDL_SYSTEM_CURSOR_SIZEALL, SDL_SYSTEM_CURSOR_NO };
#if defined(USING_VERSION_SDL3)
#define SDL_WINDOW_FULLSCREEN_DESKTOP SDL_WINDOW_FULLSCREEN
#define SDL_IGNORE false
#define SDL_DISABLE false
#define SDL_ENABLE true
#define SDL_INIT_TIMER 0x0
#define SDL_WINDOW_SHOWN 0x0
#define SDL_DROPFILE SDL_EVENT_DROP_FILE
const char *SDL_GameControllerNameForIndex(int joystickIndex)
{
const char *name = NULL;
int numJoysticks = 0;
SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks);
if (joysticks)
{
if (joystickIndex < numJoysticks)
{
SDL_JoystickID instance_id = joysticks[joystickIndex];
name = SDL_GetGamepadNameForID(instance_id);
}
SDL_free(joysticks);
}
return name;
}
int SDL_GetNumVideoDisplays(void)
{
int monitorCount = 0;
SDL_DisplayID *displays = SDL_GetDisplays(&monitorCount);
SDL_free(displays);
return monitorCount;
}
Uint8 SDL_EventState(Uint32 type, int state)
{
Uint8 stateBefore = SDL_EventEnabled(type);
switch (state)
{
case SDL_DISABLE: SDL_SetEventEnabled(type, false); break;
case SDL_ENABLE: SDL_SetEventEnabled(type, true); break;
default: TRACELOG(LOG_WARNING, "SDL: Event state of unknow type");
}
return stateBefore;
}
void SDL_GetCurrentDisplayMode_Adapter(SDL_DisplayID displayID, SDL_DisplayMode *mode)
{
const SDL_DisplayMode *currentMode = SDL_GetCurrentDisplayMode(displayID);
if (currentMode == NULL) TRACELOG(LOG_WARNING, "SDL: No possible to get current display mode");
else *mode = *currentMode;
}
#define SDL_GetCurrentDisplayMode SDL_GetCurrentDisplayMode_Adapter
SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
{
return SDL_CreateSurface(width, height, SDL_GetPixelFormatForMasks(depth, Rmask, Gmask, Bmask, Amask));
}
int SDL_GetDisplayDPI(int displayIndex, float *ddpi, float *hdpi, float *vdpi)
{
float dpi = SDL_GetWindowDisplayScale(platform.window)*96.0;
if (ddpi != NULL) *ddpi = dpi;
if (hdpi != NULL) *hdpi = dpi;
if (vdpi != NULL) *vdpi = dpi;
return 0;
}
SDL_Surface *SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, Uint32 format)
{
return SDL_CreateSurface(width, height, format);
}
SDL_Surface *SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
{
return SDL_CreateSurfaceFrom(width, height, SDL_GetPixelFormatForMasks(depth, Rmask, Gmask, Bmask, Amask), pixels, pitch);
}
SDL_Surface *SDL_CreateRGBSurfaceWithFormatFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 format)
{
return SDL_CreateSurfaceFrom(width, height, format, pixels, pitch);
}
int SDL_NumJoysticks(void)
{
int numJoysticks;
SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks);
SDL_free(joysticks);
return numJoysticks;
}
int SDL_SetRelativeMouseMode_Adapter(SDL_bool enabled)
{
if (SDL_SetWindowRelativeMouseMode(platform.window, enabled))
{
return 0; }
else
{
return -1; }
}
#define SDL_SetRelativeMouseMode SDL_SetRelativeMouseMode_Adapter
bool SDL_GetRelativeMouseMode_Adapter(void)
{
return SDL_GetWindowRelativeMouseMode(platform.window);
}
#define SDL_GetRelativeMouseMode SDL_GetRelativeMouseMode_Adapter
int SDL_GetNumTouchFingers(SDL_TouchID touchID)
{
int count = 0;
SDL_Finger **fingers = SDL_GetTouchFingers(touchID, &count);
SDL_free(fingers);
return count;
}
#else
void *SDL_GetClipboardData(const char *mime_type, size_t *size)
{
TRACELOG(LOG_WARNING, "SDL: Getting clipboard data that is not text not available in SDL2");
return NULL;
}
#endif
int InitPlatform(void); void ClosePlatform(void);
static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode); static int GetCodepointNextSDL(const char *text, int *codepointSize); static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event);
bool WindowShouldClose(void)
{
if (CORE.Window.ready) return CORE.Window.shouldClose;
else return true;
}
void ToggleFullscreen(void)
{
const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))
{
SDL_SetWindowFullscreen(platform.window, 0);
FLAG_CLEAR(CORE.Window.flags, FLAG_FULLSCREEN_MODE);
}
else
{
SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN);
FLAG_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE);
}
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
}
void ToggleBorderlessWindowed(void)
{
const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
if (FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE))
{
SDL_SetWindowFullscreen(platform.window, 0);
FLAG_CLEAR(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE);
}
else
{
SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN_DESKTOP);
FLAG_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE);
}
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
}
void MaximizeWindow(void)
{
SDL_MaximizeWindow(platform.window);
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED)) FLAG_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED);
}
void MinimizeWindow(void)
{
SDL_MinimizeWindow(platform.window);
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED)) FLAG_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED);
}
void RestoreWindow(void)
{
SDL_RestoreWindow(platform.window);
}
void SetWindowState(unsigned int flags)
{
if (!CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetWindowState does nothing before window initialization, Use \"SetConfigFlags\" instead");
FLAG_SET(CORE.Window.flags, flags);
if (FLAG_IS_SET(flags, FLAG_VSYNC_HINT))
{
SDL_GL_SetSwapInterval(1);
}
if (FLAG_IS_SET(flags, FLAG_FULLSCREEN_MODE))
{
const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN);
FLAG_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE);
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_RESIZABLE))
{
SDL_SetWindowResizable(platform.window, SDL_TRUE);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_UNDECORATED))
{
SDL_SetWindowBordered(platform.window, SDL_FALSE);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_HIDDEN))
{
SDL_HideWindow(platform.window);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_MINIMIZED))
{
SDL_MinimizeWindow(platform.window);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_MAXIMIZED))
{
SDL_MaximizeWindow(platform.window);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_UNFOCUSED))
{
TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_SDL");
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_TOPMOST))
{
SDL_SetWindowAlwaysOnTop(platform.window, SDL_FALSE);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_ALWAYS_RUN))
{
FLAG_SET(CORE.Window.flags, FLAG_WINDOW_ALWAYS_RUN);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_TRANSPARENT))
{
TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_TRANSPARENT is not supported on PLATFORM_DESKTOP_SDL");
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_HIGHDPI))
{
TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_HIGHDPI is not supported on PLATFORM_DESKTOP_SDL");
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_MOUSE_PASSTHROUGH))
{
TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_MOUSE_PASSTHROUGH is not supported on PLATFORM_DESKTOP_SDL");
}
if (FLAG_IS_SET(flags, FLAG_BORDERLESS_WINDOWED_MODE))
{
const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN_DESKTOP);
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
}
if (FLAG_IS_SET(flags, FLAG_MSAA_4X_HINT))
{
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); }
if (FLAG_IS_SET(flags, FLAG_INTERLACED_HINT))
{
TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_INTERLACED_HINT is not supported on PLATFORM_DESKTOP_SDL");
}
}
void ClearWindowState(unsigned int flags)
{
FLAG_CLEAR(CORE.Window.flags, flags);
if (FLAG_IS_SET(flags, FLAG_VSYNC_HINT))
{
SDL_GL_SetSwapInterval(0);
}
if (FLAG_IS_SET(flags, FLAG_FULLSCREEN_MODE))
{
SDL_SetWindowFullscreen(platform.window, 0);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_RESIZABLE))
{
SDL_SetWindowResizable(platform.window, SDL_FALSE);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_UNDECORATED))
{
SDL_SetWindowBordered(platform.window, SDL_TRUE);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_HIDDEN))
{
SDL_ShowWindow(platform.window);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_MINIMIZED))
{
SDL_RestoreWindow(platform.window);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_MAXIMIZED))
{
SDL_RestoreWindow(platform.window);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_UNFOCUSED))
{
TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_SDL");
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_TOPMOST))
{
SDL_SetWindowAlwaysOnTop(platform.window, SDL_FALSE);
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_TRANSPARENT))
{
TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_TRANSPARENT is not supported on PLATFORM_DESKTOP_SDL");
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_HIGHDPI))
{
TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_HIGHDPI is not supported on PLATFORM_DESKTOP_SDL");
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_MOUSE_PASSTHROUGH))
{
TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_MOUSE_PASSTHROUGH is not supported on PLATFORM_DESKTOP_SDL");
}
if (FLAG_IS_SET(flags, FLAG_BORDERLESS_WINDOWED_MODE))
{
SDL_SetWindowFullscreen(platform.window, 0);
}
if (FLAG_IS_SET(flags, FLAG_MSAA_4X_HINT))
{
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); }
if (FLAG_IS_SET(flags, FLAG_INTERLACED_HINT))
{
TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_INTERLACED_HINT is not supported on PLATFORM_DESKTOP_SDL");
}
}
void SetWindowIcon(Image image)
{
SDL_Surface *iconSurface = NULL;
unsigned int rmask = 0, gmask = 0, bmask = 0, amask = 0;
int depth = 0; int pitch = 0;
switch (image.format)
{
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
{
rmask = 0xFF, gmask = 0;
bmask = 0, amask = 0;
depth = 8, pitch = image.width;
} break;
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
{
rmask = 0xFF, gmask = 0xFF00;
bmask = 0, amask = 0;
depth = 16, pitch = image.width*2;
} break;
case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
{
rmask = 0xF800, gmask = 0x07E0;
bmask = 0x001F, amask = 0;
depth = 16, pitch = image.width*2;
} break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8:
{
rmask = 0xFF0000, gmask = 0x00FF00;
bmask = 0x0000FF, amask = 0;
depth = 24, pitch = image.width*3;
} break;
case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
{
rmask = 0xF800, gmask = 0x07C0;
bmask = 0x003E, amask = 0x0001;
depth = 16, pitch = image.width*2;
} break;
case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
{
rmask = 0xF000, gmask = 0x0F00;
bmask = 0x00F0, amask = 0x000F;
depth = 16, pitch = image.width*2;
} break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
{
rmask = 0xFF000000, gmask = 0x00FF0000;
bmask = 0x0000FF00, amask = 0x000000FF;
depth = 32, pitch = image.width*4;
} break;
case PIXELFORMAT_UNCOMPRESSED_R32:
{
rmask = 0xFFFFFFFF, gmask = 0;
bmask = 0, amask = 0;
depth = 32, pitch = image.width*4;
} break;
case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
{
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
bmask = 0xFFFFFFFF, amask = 0;
depth = 96, pitch = image.width*12;
} break;
case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
{
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
bmask = 0xFFFFFFFF, amask = 0xFFFFFFFF;
depth = 128, pitch = image.width*16;
} break;
case PIXELFORMAT_UNCOMPRESSED_R16:
{
rmask = 0xFFFF, gmask = 0;
bmask = 0, amask = 0;
depth = 16, pitch = image.width*2;
} break;
case PIXELFORMAT_UNCOMPRESSED_R16G16B16:
{
rmask = 0xFFFF, gmask = 0xFFFF;
bmask = 0xFFFF, amask = 0;
depth = 48, pitch = image.width*6;
} break;
case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:
{
rmask = 0xFFFF, gmask = 0xFFFF;
bmask = 0xFFFF, amask = 0xFFFF;
depth = 64, pitch = image.width*8;
} break;
default: return; }
iconSurface = SDL_CreateRGBSurfaceFrom( image.data, image.width, image.height, depth, pitch, rmask, gmask, bmask, amask );
if (iconSurface)
{
SDL_SetWindowIcon(platform.window, iconSurface);
SDL_FreeSurface(iconSurface);
}
}
void SetWindowIcons(Image *images, int count)
{
TRACELOG(LOG_WARNING, "SetWindowIcons() not available on target platform");
}
void SetWindowTitle(const char *title)
{
SDL_SetWindowTitle(platform.window, title);
CORE.Window.title = title;
}
void SetWindowPosition(int x, int y)
{
SDL_SetWindowPosition(platform.window, x, y);
CORE.Window.position.x = x;
CORE.Window.position.y = y;
}
void SetWindowMonitor(int monitor)
{
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
const bool wasFullscreen = (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))? true : false;
const int screenWidth = CORE.Window.screen.width;
const int screenHeight = CORE.Window.screen.height;
SDL_Rect usableBounds;
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayUsableBounds(monitor, &usableBounds))
#else
if (SDL_GetDisplayUsableBounds(monitor, &usableBounds) == 0)
#endif
{
if (wasFullscreen == 1) ToggleFullscreen();
if ((screenWidth >= usableBounds.w) || (screenHeight >= usableBounds.h))
{
SDL_SetWindowPosition(platform.window, usableBounds.x, usableBounds.y);
CORE.Window.position.x = usableBounds.x;
CORE.Window.position.y = usableBounds.y;
}
else
{
const int x = usableBounds.x + (usableBounds.w/2) - (screenWidth/2);
const int y = usableBounds.y + (usableBounds.h/2) - (screenHeight/2);
SDL_SetWindowPosition(platform.window, x, y);
CORE.Window.position.x = x;
CORE.Window.position.y = y;
}
if (wasFullscreen == 1) ToggleFullscreen(); }
else TRACELOG(LOG_WARNING, "SDL: Failed to get selected display usable bounds");
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
}
void SetWindowMinSize(int width, int height)
{
SDL_SetWindowMinimumSize(platform.window, width, height);
CORE.Window.screenMin.width = width;
CORE.Window.screenMin.height = height;
}
void SetWindowMaxSize(int width, int height)
{
SDL_SetWindowMaximumSize(platform.window, width, height);
CORE.Window.screenMax.width = width;
CORE.Window.screenMax.height = height;
}
void SetWindowSize(int width, int height)
{
SDL_SetWindowSize(platform.window, width, height);
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
}
void SetWindowOpacity(float opacity)
{
if (opacity >= 1.0f) opacity = 1.0f;
else if (opacity <= 0.0f) opacity = 0.0f;
SDL_SetWindowOpacity(platform.window, opacity);
}
void SetWindowFocused(void)
{
SDL_RaiseWindow(platform.window);
}
void *GetWindowHandle(void)
{
return (void *)platform.window;
}
int GetMonitorCount(void)
{
int monitorCount = 0;
monitorCount = SDL_GetNumVideoDisplays();
return monitorCount;
}
int GetCurrentMonitor(void)
{
int currentMonitor = 0;
currentMonitor = SDL_GetWindowDisplayIndex(platform.window);
return currentMonitor;
}
Vector2 GetMonitorPosition(int monitor)
{
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
SDL_Rect displayBounds;
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayUsableBounds(monitor, &displayBounds))
#else
if (SDL_GetDisplayUsableBounds(monitor, &displayBounds) == 0)
#endif
{
return (Vector2){ (float)displayBounds.x, (float)displayBounds.y };
}
else TRACELOG(LOG_WARNING, "SDL: Failed to get selected display usable bounds");
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
return (Vector2){ 0.0f, 0.0f };
}
int GetMonitorWidth(int monitor)
{
int width = 0;
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
SDL_DisplayMode mode;
SDL_GetCurrentDisplayMode(monitor, &mode);
width = mode.w;
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
return width;
}
int GetMonitorHeight(int monitor)
{
int height = 0;
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
SDL_DisplayMode mode;
SDL_GetCurrentDisplayMode(monitor, &mode);
height = mode.h;
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
return height;
}
int GetMonitorPhysicalWidth(int monitor)
{
int width = 0;
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
float ddpi = 0.0f;
SDL_GetDisplayDPI(monitor, &ddpi, NULL, NULL);
SDL_DisplayMode mode;
SDL_GetCurrentDisplayMode(monitor, &mode);
if (ddpi > 0.0f) width = (int)((mode.w/ddpi)*25.4f);
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
return width;
}
int GetMonitorPhysicalHeight(int monitor)
{
int height = 0;
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
float ddpi = 0.0f;
SDL_GetDisplayDPI(monitor, &ddpi, NULL, NULL);
SDL_DisplayMode mode;
SDL_GetCurrentDisplayMode(monitor, &mode);
if (ddpi > 0.0f) height = (int)((mode.h/ddpi)*25.4f);
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
return height;
}
int GetMonitorRefreshRate(int monitor)
{
int refresh = 0;
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
SDL_DisplayMode mode;
SDL_GetCurrentDisplayMode(monitor, &mode);
refresh = mode.refresh_rate;
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
return refresh;
}
const char *GetMonitorName(int monitor)
{
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3)
if (SDL_GetDisplayProperties(monitor) != 0) #else
if ((monitor >= 0) && (monitor < monitorCount))
#endif
{
return SDL_GetDisplayName(monitor);
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
return "";
}
Vector2 GetWindowPosition(void)
{
int x = 0;
int y = 0;
SDL_GetWindowPosition(platform.window, &x, &y);
return (Vector2){ (float)x, (float)y };
}
Vector2 GetWindowScaleDPI(void)
{
Vector2 scale = { 1.0f, 1.0f };
#if defined(USING_VERSION_SDL3)
scale.x = SDL_GetWindowDisplayScale(platform.window);
scale.y = scale.x;
#else
TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform");
#endif
return scale;
}
void SetClipboardText(const char *text)
{
SDL_SetClipboardText(text);
}
const char *GetClipboardText(void)
{
static char buffer[MAX_CLIPBOARD_BUFFER_LENGTH] = { 0 };
char *clipboard = SDL_GetClipboardText();
int clipboardSize = snprintf(buffer, sizeof(buffer), "%s", clipboard);
if (clipboardSize >= MAX_CLIPBOARD_BUFFER_LENGTH)
{
char *truncate = buffer + MAX_CLIPBOARD_BUFFER_LENGTH - 4;
sprintf(truncate, "...");
}
SDL_free(clipboard);
return buffer;
}
Image GetClipboardImage(void)
{
Image image = { 0 };
#if SUPPORT_CLIPBOARD_IMAGE
#if !SUPPORT_MODULE_RTEXTURES
TRACELOG(LOG_WARNING, "Enabling SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly");
return image;
#endif
#if !SUPPORT_FILEFORMAT_BMP && defined(_WIN32)
TRACELOG(LOG_WARNING, "WARNING: Enabling SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_FILEFORMAT_BMP, specially on Windows");
return image;
#endif
#if (!SUPPORT_FILEFORMAT_PNG || !SUPPORT_FILEFORMAT_JPG) && !defined(_WIN32)
TRACELOG(LOG_WARNING, "WARNING: Getting image from the clipboard might not work without SUPPORT_FILEFORMAT_PNG or SUPPORT_FILEFORMAT_JPG");
#endif
const char *imageFormats[] = {
"image/bmp",
"image/png",
"image/jpg",
"image/tiff",
};
const char *imageExtensions[] = {
".bmp",
".png",
".jpg",
".tiff",
};
size_t dataSize = 0;
void *fileData = NULL;
for (int i = 0; i < SDL_arraysize(imageFormats); i++)
{
fileData = SDL_GetClipboardData(imageFormats[i], &dataSize);
if (fileData)
{
image = LoadImageFromMemory(imageExtensions[i], fileData, (int)dataSize);
if (IsImageValid(image))
{
TRACELOG(LOG_INFO, "Clipboard: Got image from clipboard successfully: %s", imageExtensions[i]);
return image;
}
}
}
if (!IsImageValid(image)) TRACELOG(LOG_WARNING, "Clipboard: Couldn't get clipboard data. ERROR: %s", SDL_GetError());
#endif
return image;
}
void ShowCursor(void)
{
#if defined(USING_VERSION_SDL3)
SDL_ShowCursor();
#else
SDL_ShowCursor(SDL_ENABLE);
#endif
CORE.Input.Mouse.cursorHidden = false;
}
void HideCursor(void)
{
#if defined(USING_VERSION_SDL3)
SDL_HideCursor();
#else
SDL_ShowCursor(SDL_DISABLE);
#endif
CORE.Input.Mouse.cursorHidden = true;
}
void EnableCursor(void)
{
SDL_SetRelativeMouseMode(SDL_FALSE);
ShowCursor();
CORE.Input.Mouse.cursorLocked = false;
}
void DisableCursor(void)
{
SDL_SetRelativeMouseMode(SDL_TRUE);
HideCursor();
CORE.Input.Mouse.cursorLocked = true;
}
void SwapScreenBuffer(void)
{
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
SDL_Surface *surface = SDL_GetWindowSurface(platform.window);
rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, surface->pixels);
SDL_UpdateWindowSurface(platform.window);
#else
SDL_GL_SwapWindow(platform.window);
#endif
}
double GetTime(void)
{
double time = ((double)SDL_GetPerformanceCounter()/(double)SDL_GetPerformanceFrequency()) - CORE.Time.base;
return time;
}
void OpenURL(const char *url)
{
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
else SDL_OpenURL(url);
}
int SetGamepadMappings(const char *mappings)
{
const int mappingsLength = strlen(mappings);
char *buffer = (char *)RL_CALLOC(mappingsLength + 1, sizeof(char));
memcpy(buffer, mappings, mappingsLength);
char *p = strtok(buffer, "\n");
bool succeed = true;
while (p != NULL)
{
if (SDL_GameControllerAddMapping(p) == -1)
{
succeed = false;
}
p = strtok(NULL, "\n");
}
RL_FREE(buffer);
return (succeed)? 1 : 0;
}
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (duration > 0.0f))
{
if (leftMotor < 0.0f) leftMotor = 0.0f;
if (leftMotor > 1.0f) leftMotor = 1.0f;
if (rightMotor < 0.0f) rightMotor = 0.0f;
if (rightMotor > 1.0f) rightMotor = 1.0f;
if (duration > MAX_GAMEPAD_VIBRATION_TIME) duration = MAX_GAMEPAD_VIBRATION_TIME;
SDL_GameControllerRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(duration*1000.0f));
}
}
void SetMousePosition(int x, int y)
{
SDL_WarpMouseInWindow(platform.window, x, y);
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
}
void SetMouseCursor(int cursor)
{
platform.cursor = SDL_CreateSystemCursor(CursorsLUT[cursor]);
SDL_SetCursor(platform.cursor);
CORE.Input.Mouse.cursor = cursor;
}
const char *GetKeyName(int key)
{
return SDL_GetKeyName(key);
}
void PollInputEvents(void)
{
#if SUPPORT_GESTURES_SYSTEM
UpdateGestures();
#endif
CORE.Input.Keyboard.keyPressedQueueCount = 0;
CORE.Input.Keyboard.charPressedQueueCount = 0;
CORE.Input.Mouse.currentWheelMove.x = 0;
CORE.Input.Mouse.currentWheelMove.y = 0;
if (CORE.Input.Mouse.cursorLocked) CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f };
else CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++)
{
if (CORE.Input.Gamepad.ready[i])
{
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++)
{
CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
}
}
}
for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
if (CORE.Input.Touch.pointCount == 0) CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
int touchAction = -1; bool realTouch = false;
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
{
CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
}
for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
CORE.Window.resizedLastFrame = false;
if ((CORE.Window.eventWaiting) || (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED) && !FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_ALWAYS_RUN)))
{
SDL_WaitEvent(NULL);
CORE.Time.previous = GetTime();
}
SDL_Event event = { 0 };
while (SDL_PollEvent(&event) != 0)
{
switch (event.type)
{
case SDL_QUIT: CORE.Window.shouldClose = true; break;
case SDL_DROPFILE: {
if (CORE.Window.dropFileCount == 0)
{
CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *));
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
#if defined(USING_VERSION_SDL3)
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data, MAX_FILEPATH_LENGTH - 1);
#else
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file, MAX_FILEPATH_LENGTH - 1);
SDL_free(event.drop.file);
#endif
CORE.Window.dropFileCount++;
}
else if (CORE.Window.dropFileCount < 1024)
{
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
#if defined(USING_VERSION_SDL3)
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data, MAX_FILEPATH_LENGTH - 1);
#else
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file, MAX_FILEPATH_LENGTH - 1);
SDL_free(event.drop.file);
#endif
CORE.Window.dropFileCount++;
}
else TRACELOG(LOG_WARNING, "FILE: Maximum drag and drop files at once is limited to 1024 files!");
} break;
#ifndef USING_VERSION_SDL3
case SDL_WINDOWEVENT:
{
switch (event.window.event)
{
#endif
case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_SIZE_CHANGED:
{
const int width = event.window.data1;
const int height = event.window.data2;
SetupViewport(width, height);
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
{
CORE.Window.screen.width = (int)(width/GetWindowScaleDPI().x);
CORE.Window.screen.height = (int)(height/GetWindowScaleDPI().y);
}
else
{
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
}
CORE.Window.currentFbo.width = width;
CORE.Window.currentFbo.height = height;
CORE.Window.resizedLastFrame = true;
#ifndef USING_VERSION_SDL3
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED))
{
int borderTop = 0;
int borderLeft = 0;
int borderBottom = 0;
int borderRight = 0;
SDL_GetWindowBordersSize(platform.window, &borderTop, &borderLeft, &borderBottom, &borderRight);
SDL_Rect usableBounds;
SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(platform.window), &usableBounds);
if ((width + borderLeft + borderRight != usableBounds.w) && (height + borderTop + borderBottom != usableBounds.h)) FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED);
}
#endif
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
swResize(width, height);
#endif
} break;
case SDL_WINDOWEVENT_ENTER: CORE.Input.Mouse.cursorOnScreen = true; break;
case SDL_WINDOWEVENT_LEAVE: CORE.Input.Mouse.cursorOnScreen = false; break;
case SDL_WINDOWEVENT_MINIMIZED:
{
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED)) FLAG_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED);
} break;
case SDL_WINDOWEVENT_MAXIMIZED:
{
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED)) FLAG_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED);
} break;
case SDL_WINDOWEVENT_RESTORED:
{
if (!FLAG_IS_SET(SDL_GetWindowFlags(platform.window), SDL_WINDOW_MINIMIZED))
{
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED)) FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_MINIMIZED);
}
#ifdef USING_VERSION_SDL3
if (!FLAG_IS_SET(SDL_GetWindowFlags(platform.window), SDL_WINDOW_MAXIMIZED))
{
if (FLAG_IS_SET(CORE.Window.flags, SDL_WINDOW_MAXIMIZED)) FLAG_CLEAR(CORE.Window.flags, SDL_WINDOW_MAXIMIZED);
}
#endif
} break;
case SDL_WINDOWEVENT_HIDDEN:
{
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIDDEN)) FLAG_SET(CORE.Window.flags, FLAG_WINDOW_HIDDEN);
} break;
case SDL_WINDOWEVENT_SHOWN:
{
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIDDEN)) FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_HIDDEN);
} break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
{
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED);
} break;
case SDL_WINDOWEVENT_FOCUS_LOST:
{
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) FLAG_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED);
} break;
#ifndef USING_VERSION_SDL3
default: break;
}
} break;
#endif
case SDL_KEYDOWN:
{
#if defined(USING_VERSION_SDL3)
KeyboardKey key = ConvertScancodeToKey(event.key.scancode);
#else
KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode);
#endif
if (key != KEY_NULL)
{
if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE))
{
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key;
CORE.Input.Keyboard.keyPressedQueueCount++;
}
CORE.Input.Keyboard.currentKeyState[key] = 1;
}
if (event.key.repeat) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;
if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) CORE.Window.shouldClose = true;
} break;
case SDL_KEYUP:
{
#if defined(USING_VERSION_SDL3)
KeyboardKey key = ConvertScancodeToKey(event.key.scancode);
#else
KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode);
#endif
if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0;
} break;
case SDL_TEXTINPUT:
{
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
{
#if defined(USING_VERSION_SDL3)
size_t textLen = strlen(event.text.text);
unsigned int codepoint = (unsigned int)SDL_StepUTF8(&event.text.text, &textLen);
#else
int codepointSize = 0;
int codepoint = GetCodepointNextSDL(event.text.text, &codepointSize);
#endif
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = codepoint;
CORE.Input.Keyboard.charPressedQueueCount++;
}
} break;
case SDL_MOUSEBUTTONDOWN:
{
int btn = event.button.button - 1;
if (btn == 2) btn = 1;
else if (btn == 1) btn = 2;
CORE.Input.Mouse.currentButtonState[btn] = 1;
CORE.Input.Touch.currentTouchState[btn] = 1;
touchAction = 1;
} break;
case SDL_MOUSEBUTTONUP:
{
int btn = event.button.button - 1;
if (btn == 2) btn = 1;
else if (btn == 1) btn = 2;
CORE.Input.Mouse.currentButtonState[btn] = 0;
CORE.Input.Touch.currentTouchState[btn] = 0;
touchAction = 0;
} break;
case SDL_MOUSEWHEEL:
{
CORE.Input.Mouse.currentWheelMove.x = (float)event.wheel.x;
CORE.Input.Mouse.currentWheelMove.y = (float)event.wheel.y;
} break;
case SDL_MOUSEMOTION:
{
if (CORE.Input.Mouse.cursorLocked)
{
CORE.Input.Mouse.currentPosition.x = (float)event.motion.xrel;
CORE.Input.Mouse.currentPosition.y = (float)event.motion.yrel;
CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f };
}
else
{
CORE.Input.Mouse.currentPosition.x = (float)event.motion.x;
CORE.Input.Mouse.currentPosition.y = (float)event.motion.y;
}
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
touchAction = 2;
} break;
case SDL_FINGERDOWN:
{
UpdateTouchPointsSDL(event.tfinger);
touchAction = 1;
realTouch = true;
} break;
case SDL_FINGERUP:
{
UpdateTouchPointsSDL(event.tfinger);
touchAction = 0;
realTouch = true;
} break;
case SDL_FINGERMOTION:
{
UpdateTouchPointsSDL(event.tfinger);
touchAction = 2;
realTouch = true;
} break;
case SDL_JOYDEVICEADDED:
{
int jid = event.jdevice.which;
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (jid == platform.gamepadId[i])
{
return;
}
}
int nextAvailableSlot = 0;
while (nextAvailableSlot < MAX_GAMEPADS && CORE.Input.Gamepad.ready[nextAvailableSlot])
{
++nextAvailableSlot;
}
if ((nextAvailableSlot < MAX_GAMEPADS) && !CORE.Input.Gamepad.ready[nextAvailableSlot])
{
platform.gamepad[nextAvailableSlot] = SDL_GameControllerOpen(jid);
platform.gamepadId[nextAvailableSlot] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[nextAvailableSlot]));
if (platform.gamepad[nextAvailableSlot])
{
CORE.Input.Gamepad.ready[nextAvailableSlot] = true;
CORE.Input.Gamepad.axisCount[nextAvailableSlot] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[nextAvailableSlot]));
CORE.Input.Gamepad.axisState[nextAvailableSlot][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
CORE.Input.Gamepad.axisState[nextAvailableSlot][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
memset(CORE.Input.Gamepad.name[nextAvailableSlot], 0, MAX_GAMEPAD_NAME_LENGTH);
const char *controllerName = SDL_GameControllerNameForIndex(nextAvailableSlot);
if (controllerName != NULL) strncpy(CORE.Input.Gamepad.name[nextAvailableSlot], controllerName, MAX_GAMEPAD_NAME_LENGTH - 1);
else strncpy(CORE.Input.Gamepad.name[nextAvailableSlot], "noname", 6);
}
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
}
} break;
case SDL_JOYDEVICEREMOVED:
{
int jid = event.jdevice.which;
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (platform.gamepadId[i] == jid)
{
SDL_GameControllerClose(platform.gamepad[i]);
CORE.Input.Gamepad.ready[i] = false;
memset(CORE.Input.Gamepad.name[i], 0, MAX_GAMEPAD_NAME_LENGTH);
platform.gamepadId[i] = -1;
break;
}
}
} break;
case SDL_CONTROLLERBUTTONDOWN:
{
int button = -1;
#if defined(USING_VERSION_SDL3)
switch (event.gbutton.button)
#else
switch (event.jbutton.button)
#endif
{
case SDL_CONTROLLER_BUTTON_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
case SDL_CONTROLLER_BUTTON_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;
case SDL_CONTROLLER_BUTTON_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break;
case SDL_CONTROLLER_BUTTON_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break;
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break;
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break;
case SDL_CONTROLLER_BUTTON_BACK: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break;
case SDL_CONTROLLER_BUTTON_GUIDE: button = GAMEPAD_BUTTON_MIDDLE; break;
case SDL_CONTROLLER_BUTTON_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break;
case SDL_CONTROLLER_BUTTON_DPAD_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break;
case SDL_CONTROLLER_BUTTON_LEFTSTICK: button = GAMEPAD_BUTTON_LEFT_THUMB; break;
case SDL_CONTROLLER_BUTTON_RIGHTSTICK: button = GAMEPAD_BUTTON_RIGHT_THUMB; break;
default: break;
}
if (button >= 0)
{
for (int i = 0; i < MAX_GAMEPADS; i++)
{
#if defined(USING_VERSION_SDL3)
if (platform.gamepadId[i] == event.gbutton.which)
#else
if (platform.gamepadId[i] == event.jbutton.which)
#endif
{
CORE.Input.Gamepad.currentButtonState[i][button] = 1;
CORE.Input.Gamepad.lastButtonPressed = button;
break;
}
}
}
} break;
case SDL_CONTROLLERBUTTONUP:
{
int button = -1;
#if defined(USING_VERSION_SDL3)
switch (event.gbutton.button)
#else
switch (event.jbutton.button)
#endif
{
case SDL_CONTROLLER_BUTTON_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
case SDL_CONTROLLER_BUTTON_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;
case SDL_CONTROLLER_BUTTON_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break;
case SDL_CONTROLLER_BUTTON_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break;
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break;
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break;
case SDL_CONTROLLER_BUTTON_BACK: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break;
case SDL_CONTROLLER_BUTTON_GUIDE: button = GAMEPAD_BUTTON_MIDDLE; break;
case SDL_CONTROLLER_BUTTON_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break;
case SDL_CONTROLLER_BUTTON_DPAD_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break;
case SDL_CONTROLLER_BUTTON_LEFTSTICK: button = GAMEPAD_BUTTON_LEFT_THUMB; break;
case SDL_CONTROLLER_BUTTON_RIGHTSTICK: button = GAMEPAD_BUTTON_RIGHT_THUMB; break;
default: break;
}
if (button >= 0)
{
for (int i = 0; i < MAX_GAMEPADS; i++)
{
#if defined(USING_VERSION_SDL3)
if (platform.gamepadId[i] == event.gbutton.which)
#else
if (platform.gamepadId[i] == event.jbutton.which)
#endif
{
CORE.Input.Gamepad.currentButtonState[i][button] = 0;
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
break;
}
}
}
} break;
case SDL_CONTROLLERAXISMOTION:
{
int axis = -1;
switch (event.jaxis.axis)
{
case SDL_CONTROLLER_AXIS_LEFTX: axis = GAMEPAD_AXIS_LEFT_X; break;
case SDL_CONTROLLER_AXIS_LEFTY: axis = GAMEPAD_AXIS_LEFT_Y; break;
case SDL_CONTROLLER_AXIS_RIGHTX: axis = GAMEPAD_AXIS_RIGHT_X; break;
case SDL_CONTROLLER_AXIS_RIGHTY: axis = GAMEPAD_AXIS_RIGHT_Y; break;
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: axis = GAMEPAD_AXIS_LEFT_TRIGGER; break;
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: axis = GAMEPAD_AXIS_RIGHT_TRIGGER; break;
default: break;
}
if (axis >= 0)
{
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (platform.gamepadId[i] == event.jaxis.which)
{
float value = event.jaxis.value/(float)32767;
CORE.Input.Gamepad.axisState[i][axis] = value;
if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))
{
int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
int pressed = (value > 0.1f);
CORE.Input.Gamepad.currentButtonState[i][button] = pressed;
if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
}
break;
}
}
}
} break;
default: break;
}
#if SUPPORT_GESTURES_SYSTEM
if (touchAction > -1)
{
GestureEvent gestureEvent = { 0 };
gestureEvent.touchAction = touchAction;
gestureEvent.pointId[0] = 0;
gestureEvent.pointCount = 1;
if (touchAction == 2 || realTouch) gestureEvent.position[0] = CORE.Input.Touch.position[0];
else gestureEvent.position[0] = GetMousePosition();
gestureEvent.position[0].x /= (float)GetScreenWidth();
gestureEvent.position[0].y /= (float)GetScreenHeight();
ProcessGestureEvent(gestureEvent);
touchAction = -1;
}
#endif
}
}
int InitPlatform(void)
{
int result = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER);
if (result < 0) { TRACELOG(LOG_WARNING, "SDL: Failed to initialize SDL"); return -1; }
unsigned int flags = 0;
FLAG_SET(flags, SDL_WINDOW_SHOWN);
FLAG_SET(flags, SDL_WINDOW_INPUT_FOCUS);
FLAG_SET(flags, SDL_WINDOW_MOUSE_FOCUS);
FLAG_SET(flags, SDL_WINDOW_MOUSE_CAPTURE);
if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE)) FLAG_SET(flags, SDL_WINDOW_FULLSCREEN);
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNDECORATED)) FLAG_SET(flags, SDL_WINDOW_BORDERLESS);
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_RESIZABLE)) FLAG_SET(flags, SDL_WINDOW_RESIZABLE);
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED)) FLAG_SET(flags, SDL_WINDOW_MINIMIZED);
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED)) FLAG_SET(flags, SDL_WINDOW_MAXIMIZED);
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED))
{
FLAG_CLEAR(flags, SDL_WINDOW_INPUT_FOCUS);
FLAG_CLEAR(flags, SDL_WINDOW_MOUSE_FOCUS);
}
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_TOPMOST)) FLAG_SET(flags, SDL_WINDOW_ALWAYS_ON_TOP);
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MOUSE_PASSTHROUGH)) FLAG_CLEAR(flags, SDL_WINDOW_MOUSE_CAPTURE);
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) FLAG_SET(flags, SDL_WINDOW_ALLOW_HIGHDPI);
if (rlGetVersion() != RL_OPENGL_SOFTWARE)
{
flags |= SDL_WINDOW_OPENGL;
if (rlGetVersion() == RL_OPENGL_21)
{
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
}
else if (rlGetVersion() == RL_OPENGL_33)
{
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
}
else if (rlGetVersion() == RL_OPENGL_43)
{
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#if RLGL_ENABLE_OPENGL_DEBUG_CONTEXT
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); #endif
}
else if (rlGetVersion() == RL_OPENGL_ES_20) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
}
else if (rlGetVersion() == RL_OPENGL_ES_30) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
}
if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT))
{
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
}
}
#if defined(USING_VERSION_SDL3)
platform.window = SDL_CreateWindow(CORE.Window.title, CORE.Window.screen.width, CORE.Window.screen.height, flags);
const char *enableOSK = SDL_GetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD);
if (enableOSK == NULL) SDL_SetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD, "0");
if (!SDL_StartTextInput(platform.window)) TRACELOG(LOG_WARNING, "SDL: Failed to start text input: %s", SDL_GetError());
if (enableOSK == NULL) SDL_SetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD, NULL);
#else
platform.window = SDL_CreateWindow(CORE.Window.title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, CORE.Window.screen.width, CORE.Window.screen.height, flags);
#endif
if (rlGetVersion() != RL_OPENGL_SOFTWARE)
{
platform.glContext = SDL_GL_CreateContext(platform.window);
}
if ((platform.window != NULL) && ((rlGetVersion() == RL_OPENGL_SOFTWARE) || (platform.glContext != NULL)))
{
CORE.Window.ready = true;
SDL_DisplayMode displayMode = { 0 };
SDL_GetCurrentDisplayMode(GetCurrentMonitor(), &displayMode);
CORE.Window.display.width = displayMode.w;
CORE.Window.display.height = displayMode.h;
CORE.Window.render.width = CORE.Window.screen.width;
CORE.Window.render.height = CORE.Window.screen.height;
CORE.Window.currentFbo.width = CORE.Window.render.width;
CORE.Window.currentFbo.height = CORE.Window.render.height;
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully %s",
FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)? "(HighDPI)" : "");
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
if (platform.glContext != NULL)
{
SDL_GL_SetSwapInterval((FLAG_IS_SET(CORE.Window.flags, FLAG_VSYNC_HINT))? 1: 0);
rlLoadExtensions(SDL_GL_GetProcAddress);
}
}
else
{
TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphics device");
return -1;
}
for (int i = 0; i < MAX_GAMEPADS; i++)
{
platform.gamepadId[i] = -1; }
int numJoysticks = SDL_NumJoysticks();
for (int i = 0; (i < numJoysticks) && (i < MAX_GAMEPADS); i++)
{
platform.gamepad[i] = SDL_GameControllerOpen(i);
platform.gamepadId[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[i]));
if (platform.gamepad[i])
{
CORE.Input.Gamepad.ready[i] = true;
CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[i]));
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), MAX_GAMEPAD_NAME_LENGTH - 1);
CORE.Input.Gamepad.name[i][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0';
}
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
}
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
CORE.Time.base = (double)SDL_GetPerformanceCounter()/(double)SDL_GetPerformanceFrequency();
#if defined(_WIN32) && SUPPORT_WINMM_HIGHRES_TIMER && !SUPPORT_BUSY_WAIT_LOOP
SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "1"); #endif
CORE.Storage.basePath = SDL_GetBasePath();
#if defined(USING_VERSION_SDL3)
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL3): Initialized successfully");
#else
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL2): Initialized successfully");
#endif
return 0;
}
void ClosePlatform(void)
{
SDL_FreeCursor(platform.cursor); if (platform.glContext != NULL) SDL_GL_DeleteContext(platform.glContext); SDL_DestroyWindow(platform.window);
SDL_Quit(); }
static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode)
{
if ((sdlScancode >= 0) && (sdlScancode < SCANCODE_MAPPED_NUM))
{
return mapScancodeToKey[sdlScancode];
}
return KEY_NULL; }
static int GetCodepointNextSDL(const char *text, int *codepointSize)
{
const char *ptr = text;
int codepoint = 0x3f; *codepointSize = 1;
if (0xf0 == (0xf8 & ptr[0]))
{
if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
*codepointSize = 4;
}
else if (0xe0 == (0xf0 & ptr[0]))
{
if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
*codepointSize = 3;
}
else if (0xc0 == (0xe0 & ptr[0]))
{
if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
*codepointSize = 2;
}
else if (0x00 == (0x80 & ptr[0]))
{
codepoint = ptr[0];
*codepointSize = 1;
}
return codepoint;
}
static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event)
{
#if defined(USING_VERSION_SDL3)
int count = 0;
SDL_Finger **fingers = SDL_GetTouchFingers(event.touchID, &count);
CORE.Input.Touch.pointCount = count;
for (int i = 0; i < CORE.Input.Touch.pointCount; i++)
{
SDL_Finger *finger = fingers[i];
CORE.Input.Touch.pointId[i] = finger->id;
CORE.Input.Touch.position[i].x = finger->x*CORE.Window.screen.width;
CORE.Input.Touch.position[i].y = finger->y*CORE.Window.screen.height;
CORE.Input.Touch.currentTouchState[i] = 1;
}
SDL_free(fingers);
#else
CORE.Input.Touch.pointCount = SDL_GetNumTouchFingers(event.touchId);
for (int i = 0; i < CORE.Input.Touch.pointCount; i++)
{
SDL_Finger *finger = SDL_GetTouchFinger(event.touchId, i);
CORE.Input.Touch.pointId[i] = (int)finger->id;
CORE.Input.Touch.position[i].x = finger->x*CORE.Window.screen.width;
CORE.Input.Touch.position[i].y = finger->y*CORE.Window.screen.height;
CORE.Input.Touch.currentTouchState[i] = 1;
}
#endif
for (int i = CORE.Input.Touch.pointCount; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.currentTouchState[i] = 0;
}