Update C sources

This commit is contained in:
Milan Nikolic 2024-05-07 21:54:39 +02:00
parent 2a66186c7d
commit 1868520849
No known key found for this signature in database
GPG key ID: 9229D0EAA3AA4E75
27 changed files with 4582 additions and 2234 deletions

View file

@ -27,7 +27,7 @@
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2013-2023 Ramon Santamaria (@raysan5) and contributors
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -77,6 +77,175 @@ extern CoreData CORE; // Global CORE state context
static PlatformData platform = { 0 }; // Platform specific data
//----------------------------------------------------------------------------------
// Local Variables Definition
//----------------------------------------------------------------------------------
#define KEYCODE_MAP_SIZE 162
static const KeyboardKey KeycodeMap[KEYCODE_MAP_SIZE] = {
KEY_NULL, // AKEYCODE_UNKNOWN
0, // AKEYCODE_SOFT_LEFT
0, // AKEYCODE_SOFT_RIGHT
0, // AKEYCODE_HOME
KEY_BACK, // AKEYCODE_BACK
0, // AKEYCODE_CALL
0, // AKEYCODE_ENDCALL
KEY_ZERO, // AKEYCODE_0
KEY_ONE, // AKEYCODE_1
KEY_TWO, // AKEYCODE_2
KEY_THREE, // AKEYCODE_3
KEY_FOUR, // AKEYCODE_4
KEY_FIVE, // AKEYCODE_5
KEY_SIX, // AKEYCODE_6
KEY_SEVEN, // AKEYCODE_7
KEY_EIGHT, // AKEYCODE_8
KEY_NINE, // AKEYCODE_9
0, // AKEYCODE_STAR
0, // AKEYCODE_POUND
KEY_UP, // AKEYCODE_DPAD_UP
KEY_DOWN, // AKEYCODE_DPAD_DOWN
KEY_LEFT, // AKEYCODE_DPAD_LEFT
KEY_RIGHT, // AKEYCODE_DPAD_RIGHT
0, // AKEYCODE_DPAD_CENTER
KEY_VOLUME_UP, // AKEYCODE_VOLUME_UP
KEY_VOLUME_DOWN, // AKEYCODE_VOLUME_DOWN
0, // AKEYCODE_POWER
0, // AKEYCODE_CAMERA
0, // AKEYCODE_CLEAR
KEY_A, // AKEYCODE_A
KEY_B, // AKEYCODE_B
KEY_C, // AKEYCODE_C
KEY_D, // AKEYCODE_D
KEY_E, // AKEYCODE_E
KEY_F, // AKEYCODE_F
KEY_G, // AKEYCODE_G
KEY_H, // AKEYCODE_H
KEY_I, // AKEYCODE_I
KEY_J, // AKEYCODE_J
KEY_K, // AKEYCODE_K
KEY_L, // AKEYCODE_L
KEY_M, // AKEYCODE_M
KEY_N, // AKEYCODE_N
KEY_O, // AKEYCODE_O
KEY_P, // AKEYCODE_P
KEY_Q, // AKEYCODE_Q
KEY_R, // AKEYCODE_R
KEY_S, // AKEYCODE_S
KEY_T, // AKEYCODE_T
KEY_U, // AKEYCODE_U
KEY_V, // AKEYCODE_V
KEY_W, // AKEYCODE_W
KEY_X, // AKEYCODE_X
KEY_Y, // AKEYCODE_Y
KEY_Z, // AKEYCODE_Z
KEY_COMMA, // AKEYCODE_COMMA
KEY_PERIOD, // AKEYCODE_PERIOD
KEY_LEFT_ALT, // AKEYCODE_ALT_LEFT
KEY_RIGHT_ALT, // AKEYCODE_ALT_RIGHT
KEY_LEFT_SHIFT, // AKEYCODE_SHIFT_LEFT
KEY_RIGHT_SHIFT, // AKEYCODE_SHIFT_RIGHT
KEY_TAB, // AKEYCODE_TAB
KEY_SPACE, // AKEYCODE_SPACE
0, // AKEYCODE_SYM
0, // AKEYCODE_EXPLORER
0, // AKEYCODE_ENVELOPE
KEY_ENTER, // AKEYCODE_ENTER
KEY_BACKSPACE, // AKEYCODE_DEL
KEY_GRAVE, // AKEYCODE_GRAVE
KEY_MINUS, // AKEYCODE_MINUS
KEY_EQUAL, // AKEYCODE_EQUALS
KEY_LEFT_BRACKET, // AKEYCODE_LEFT_BRACKET
KEY_RIGHT_BRACKET, // AKEYCODE_RIGHT_BRACKET
KEY_BACKSLASH, // AKEYCODE_BACKSLASH
KEY_SEMICOLON, // AKEYCODE_SEMICOLON
KEY_APOSTROPHE, // AKEYCODE_APOSTROPHE
KEY_SLASH, // AKEYCODE_SLASH
0, // AKEYCODE_AT
0, // AKEYCODE_NUM
0, // AKEYCODE_HEADSETHOOK
0, // AKEYCODE_FOCUS
0, // AKEYCODE_PLUS
KEY_MENU, // AKEYCODE_MENU
0, // AKEYCODE_NOTIFICATION
0, // AKEYCODE_SEARCH
0, // AKEYCODE_MEDIA_PLAY_PAUSE
0, // AKEYCODE_MEDIA_STOP
0, // AKEYCODE_MEDIA_NEXT
0, // AKEYCODE_MEDIA_PREVIOUS
0, // AKEYCODE_MEDIA_REWIND
0, // AKEYCODE_MEDIA_FAST_FORWARD
0, // AKEYCODE_MUTE
KEY_PAGE_UP, // AKEYCODE_PAGE_UP
KEY_PAGE_DOWN, // AKEYCODE_PAGE_DOWN
0, // AKEYCODE_PICTSYMBOLS
0, // AKEYCODE_SWITCH_CHARSET
0, // AKEYCODE_BUTTON_A
0, // AKEYCODE_BUTTON_B
0, // AKEYCODE_BUTTON_C
0, // AKEYCODE_BUTTON_X
0, // AKEYCODE_BUTTON_Y
0, // AKEYCODE_BUTTON_Z
0, // AKEYCODE_BUTTON_L1
0, // AKEYCODE_BUTTON_R1
0, // AKEYCODE_BUTTON_L2
0, // AKEYCODE_BUTTON_R2
0, // AKEYCODE_BUTTON_THUMBL
0, // AKEYCODE_BUTTON_THUMBR
0, // AKEYCODE_BUTTON_START
0, // AKEYCODE_BUTTON_SELECT
0, // AKEYCODE_BUTTON_MODE
KEY_ESCAPE, // AKEYCODE_ESCAPE
KEY_DELETE, // AKEYCODE_FORWARD_DELL
KEY_LEFT_CONTROL, // AKEYCODE_CTRL_LEFT
KEY_RIGHT_CONTROL, // AKEYCODE_CTRL_RIGHT
KEY_CAPS_LOCK, // AKEYCODE_CAPS_LOCK
KEY_SCROLL_LOCK, // AKEYCODE_SCROLL_LOCK
KEY_LEFT_SUPER, // AKEYCODE_META_LEFT
KEY_RIGHT_SUPER, // AKEYCODE_META_RIGHT
0, // AKEYCODE_FUNCTION
KEY_PRINT_SCREEN, // AKEYCODE_SYSRQ
KEY_PAUSE, // AKEYCODE_BREAK
KEY_HOME, // AKEYCODE_MOVE_HOME
KEY_END, // AKEYCODE_MOVE_END
KEY_INSERT, // AKEYCODE_INSERT
0, // AKEYCODE_FORWARD
0, // AKEYCODE_MEDIA_PLAY
0, // AKEYCODE_MEDIA_PAUSE
0, // AKEYCODE_MEDIA_CLOSE
0, // AKEYCODE_MEDIA_EJECT
0, // AKEYCODE_MEDIA_RECORD
KEY_F1, // AKEYCODE_F1
KEY_F2, // AKEYCODE_F2
KEY_F3, // AKEYCODE_F3
KEY_F4, // AKEYCODE_F4
KEY_F5, // AKEYCODE_F5
KEY_F6, // AKEYCODE_F6
KEY_F7, // AKEYCODE_F7
KEY_F8, // AKEYCODE_F8
KEY_F9, // AKEYCODE_F9
KEY_F10, // AKEYCODE_F10
KEY_F11, // AKEYCODE_F11
KEY_F12, // AKEYCODE_F12
KEY_NUM_LOCK, // AKEYCODE_NUM_LOCK
KEY_KP_0, // AKEYCODE_NUMPAD_0
KEY_KP_1, // AKEYCODE_NUMPAD_1
KEY_KP_2, // AKEYCODE_NUMPAD_2
KEY_KP_3, // AKEYCODE_NUMPAD_3
KEY_KP_4, // AKEYCODE_NUMPAD_4
KEY_KP_5, // AKEYCODE_NUMPAD_5
KEY_KP_6, // AKEYCODE_NUMPAD_6
KEY_KP_7, // AKEYCODE_NUMPAD_7
KEY_KP_8, // AKEYCODE_NUMPAD_8
KEY_KP_9, // AKEYCODE_NUMPAD_9
KEY_KP_DIVIDE, // AKEYCODE_NUMPAD_DIVIDE
KEY_KP_MULTIPLY, // AKEYCODE_NUMPAD_MULTIPLY
KEY_KP_SUBTRACT, // AKEYCODE_NUMPAD_SUBTRACT
KEY_KP_ADD, // AKEYCODE_NUMPAD_ADD
KEY_KP_DECIMAL, // AKEYCODE_NUMPAD_DOT
0, // AKEYCODE_NUMPAD_COMMA
KEY_KP_ENTER, // AKEYCODE_NUMPAD_ENTER
KEY_KP_EQUAL // AKEYCODE_NUMPAD_EQUALS
};
//----------------------------------------------------------------------------------
// Module Internal Functions Declaration
//----------------------------------------------------------------------------------
@ -446,6 +615,12 @@ int SetGamepadMappings(const char *mappings)
return 0;
}
// Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor)
{
TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform");
}
// Set mouse position XY
void SetMousePosition(int x, int y)
{
@ -478,6 +653,16 @@ void PollInputEvents(void)
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
//CORE.Input.Gamepad.axisCount = 0;
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (CORE.Input.Gamepad.ready[i]) // Check if gamepad is available
{
// Register previous gamepad states
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++)
CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
}
}
// Register previous touch states
for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
@ -1018,17 +1203,21 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
return 1; // Handled gamepad button
}
// Save current button and its state
// NOTE: Android key action is 0 for down and 1 for up
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
KeyboardKey key = (keycode > 0 && keycode < KEYCODE_MAP_SIZE) ? KeycodeMap[keycode] : KEY_NULL;
if (key != KEY_NULL)
{
CORE.Input.Keyboard.currentKeyState[keycode] = 1; // Key down
// Save current key and its state
// NOTE: Android key action is 0 for down and 1 for up
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
{
CORE.Input.Keyboard.currentKeyState[key] = 1; // Key down
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode;
CORE.Input.Keyboard.keyPressedQueueCount++;
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key;
CORE.Input.Keyboard.keyPressedQueueCount++;
}
else if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_MULTIPLE) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;
else CORE.Input.Keyboard.currentKeyState[key] = 0; // Key up
}
else if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_MULTIPLE) CORE.Input.Keyboard.keyRepeatInFrame[keycode] = 1;
else CORE.Input.Keyboard.currentKeyState[keycode] = 0; // Key up
if (keycode == AKEYCODE_POWER)
{

View file

@ -30,7 +30,7 @@
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2013-2023 Ramon Santamaria (@raysan5) and contributors
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -74,7 +74,6 @@
//#define GLFW_EXPOSE_NATIVE_X11 // WARNING: Exposing Xlib.h > X.h results in dup symbols for Font type
//#define GLFW_EXPOSE_NATIVE_WAYLAND
//#define GLFW_EXPOSE_NATIVE_MIR
#include "GLFW/glfw3native.h" // Required for: glfwGetX11Window()
#endif
#if defined(__APPLE__)
@ -85,15 +84,6 @@
#include "GLFW/glfw3native.h" // Required for: glfwGetCocoaWindow()
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// TODO: HACK: Added flag if not provided by GLFW when using external library
// Latest GLFW release (GLFW 3.3.8) does not implement this flag, it was added for 3.4.0-dev
#if !defined(GLFW_MOUSE_PASSTHROUGH)
#define GLFW_MOUSE_PASSTHROUGH 0x0002000D
#endif
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
@ -123,13 +113,14 @@ static void WindowIconifyCallback(GLFWwindow *window, int iconified);
static void WindowMaximizeCallback(GLFWwindow* window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized
static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus
static void WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window
static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley); // GLFW3 Window Content Scale Callback, runs when window changes scale
// Input callbacks events
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
static void CharCallback(GLFWwindow *window, unsigned int key); // GLFW3 Char Key Callback, runs on key pressed (get char value)
static void CharCallback(GLFWwindow *window, unsigned int codepoint); // GLFW3 Char Callback, runs on key pressed (get codepoint value)
static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed
static void MouseCursorPosCallback(GLFWwindow *window, double x, double y); // GLFW3 Cursor Position Callback, runs on mouse move
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Scrolling Callback, runs on mouse wheel
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
static void JoystickCallback(int jid, int event); // GLFW3 Joystick Connected/Disconnected Callback
@ -941,31 +932,8 @@ Vector2 GetWindowPosition(void)
// Get window scale DPI factor for current monitor
Vector2 GetWindowScaleDPI(void)
{
float xdpi = 1.0;
float ydpi = 1.0;
Vector2 scale = { 1.0f, 1.0f };
Vector2 windowPos = GetWindowPosition();
int monitorCount = 0;
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
// Check window monitor
for (int i = 0; i < monitorCount; i++)
{
glfwGetMonitorContentScale(monitors[i], &xdpi, &ydpi);
int xpos, ypos, width, height;
glfwGetMonitorWorkarea(monitors[i], &xpos, &ypos, &width, &height);
if ((windowPos.x >= xpos) && (windowPos.x < xpos + width) &&
(windowPos.y >= ypos) && (windowPos.y < ypos + height))
{
scale.x = xdpi;
scale.y = ydpi;
break;
}
}
Vector2 scale = {0};
glfwGetWindowContentScale(platform.handle, &scale.x, &scale.y);
return scale;
}
@ -1004,6 +972,8 @@ void EnableCursor(void)
// Set cursor position in the middle
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
if (glfwRawMouseMotionSupported()) glfwSetInputMode(platform.handle, GLFW_RAW_MOUSE_MOTION, GLFW_FALSE);
CORE.Input.Mouse.cursorHidden = false;
}
@ -1015,6 +985,8 @@ void DisableCursor(void)
// Set cursor position in the middle
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
if (glfwRawMouseMotionSupported()) glfwSetInputMode(platform.handle, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
CORE.Input.Mouse.cursorHidden = true;
}
@ -1072,6 +1044,12 @@ int SetGamepadMappings(const char *mappings)
return glfwUpdateGamepadMappings(mappings);
}
// Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor)
{
TRACELOG(LOG_WARNING, "GamepadSetVibration() not available on target platform");
}
// Set mouse position XY
void SetMousePosition(int x, int y)
{
@ -1137,7 +1115,7 @@ void PollInputEvents(void)
//for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 };
// Map touch position to mouse position for convenience
// WARNING: If the target desktop device supports touch screen, this behavious should be reviewed!
// WARNING: If the target desktop device supports touch screen, this behaviour should be reviewed!
// TODO: GLFW does not support multi-touch input just yet
// https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch
// https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
@ -1240,6 +1218,19 @@ void PollInputEvents(void)
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
static void SetDimensionsFromMonitor(GLFWmonitor *monitor)
{
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
// Default display resolution to that of the current mode
CORE.Window.display.width = mode->width;
CORE.Window.display.height = mode->height;
// Set screen width/height to the display width/height if they are 0
if (CORE.Window.screen.width == 0) CORE.Window.screen.width = CORE.Window.display.width;
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;
}
// Initialize platform: graphics, inputs and more
int InitPlatform(void)
{
@ -1380,26 +1371,22 @@ int InitPlatform(void)
// REF: https://github.com/raysan5/raylib/issues/1554
glfwSetJoystickCallback(NULL);
// Find monitor resolution
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
if (!monitor)
{
TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor");
return -1;
}
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
CORE.Window.display.width = mode->width;
CORE.Window.display.height = mode->height;
// Set screen width/height to the display width/height if they are 0
if (CORE.Window.screen.width == 0) CORE.Window.screen.width = CORE.Window.display.width;
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;
GLFWmonitor *monitor = NULL;
if (CORE.Window.fullscreen)
{
// remember center for switchinging from fullscreen to window
// According to glfwCreateWindow(), if the user does not have a choice, fullscreen applications
// should default to the primary monitor.
monitor = glfwGetPrimaryMonitor();
if (!monitor)
{
TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor");
return -1;
}
SetDimensionsFromMonitor(monitor);
// Remember center for switching from fullscreen to window
if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))
{
// If screen width/height equal to the display, we can't calculate the window pos for toggling full-screened/windowed.
@ -1418,7 +1405,7 @@ int InitPlatform(void)
// Obtain recommended CORE.Window.display.width/CORE.Window.display.height from a valid videomode for the monitor
int count = 0;
const GLFWvidmode *modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count);
const GLFWvidmode *modes = glfwGetVideoModes(monitor, &count);
// Get closest video mode to desired CORE.Window.screen.width/CORE.Window.screen.height
for (int i = 0; i < count; i++)
@ -1448,21 +1435,55 @@ int InitPlatform(void)
// HighDPI monitors are properly considered in a following similar function: SetupViewport()
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
platform.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, (CORE.Window.title != 0)? CORE.Window.title : " ", glfwGetPrimaryMonitor(), NULL);
platform.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, (CORE.Window.title != 0)? CORE.Window.title : " ", monitor, NULL);
// NOTE: Full-screen change, not working properly...
//glfwSetWindowMonitor(platform.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
}
else
{
// If we are windowed fullscreen, ensures that window does not minimize when focus is lost
if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))
// No-fullscreen window creation
bool wantWindowedFullscreen = (CORE.Window.screen.height == 0) && (CORE.Window.screen.width == 0);
// If we are windowed fullscreen, ensures that window does not minimize when focus is lost.
// This hinting code will not work if the user already specified the correct monitor dimensions;
// at this point we don't know the monitor's dimensions. (Though, how did the user then?)
if (wantWindowedFullscreen)
{
glfwWindowHint(GLFW_AUTO_ICONIFY, 0);
}
// No-fullscreen window creation
platform.handle = glfwCreateWindow(CORE.Window.screen.width, CORE.Window.screen.height, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
// Default to at least one pixel in size, as creation with a zero dimension is not allowed.
int creationWidth = CORE.Window.screen.width != 0 ? CORE.Window.screen.width : 1;
int creationHeight = CORE.Window.screen.height != 0 ? CORE.Window.screen.height : 1;
platform.handle = glfwCreateWindow(creationWidth, creationHeight, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
// After the window was created, determine the monitor that the window manager assigned.
// Derive display sizes, and, if possible, window size in case it was zero at beginning.
int monitorCount = 0;
int monitorIndex = GetCurrentMonitor();
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
if (monitorIndex < monitorCount)
{
monitor = monitors[monitorIndex];
SetDimensionsFromMonitor(monitor);
TRACELOG(LOG_INFO, "wantWindowed: %d, size: %dx%d", wantWindowedFullscreen, CORE.Window.screen.width, CORE.Window.screen.height);
if (wantWindowedFullscreen)
{
glfwSetWindowSize(platform.handle, CORE.Window.screen.width, CORE.Window.screen.height);
}
}
else
{
// The monitor for the window-manager-created window can not be determined, so it can not be centered.
glfwTerminate();
TRACELOG(LOG_WARNING, "GLFW: Failed to determine Monitor to center Window");
return -1;
}
if (platform.handle)
{
@ -1537,7 +1558,21 @@ int InitPlatform(void)
// If graphic device is no properly initialized, we end program
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
else
{
// Try to center window on screen but avoiding window-bar outside of screen
int monitorX = 0;
int monitorY = 0;
int monitorWidth = 0;
int monitorHeight = 0;
glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight);
int posX = monitorX + (monitorWidth - (int)CORE.Window.screen.width)/2;
int posY = monitorY + (monitorHeight - (int)CORE.Window.screen.height)/2;
if (posX < monitorX) posX = monitorX;
if (posY < monitorY) posY = monitorY;
SetWindowPosition(posX, posY);
}
// Load OpenGL extensions
// NOTE: GL procedures address loader is required to load extensions
@ -1553,6 +1588,11 @@ int InitPlatform(void)
glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);
glfwSetDropCallback(platform.handle, WindowDropCallback);
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
{
glfwSetWindowContentScaleCallback(platform.handle, WindowContentScaleCallback);
}
// Set input callback events
glfwSetKeyCallback(platform.handle, KeyCallback);
glfwSetCharCallback(platform.handle, CharCallback);
@ -1581,6 +1621,17 @@ int InitPlatform(void)
CORE.Storage.basePath = GetWorkingDirectory();
//----------------------------------------------------------------------------
char* glfwPlatform = "";
switch (glfwGetPlatform())
{
case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break;
case GLFW_PLATFORM_COCOA: glfwPlatform = "Cocoa"; break;
case GLFW_PLATFORM_WAYLAND: glfwPlatform = "Wayland"; break;
case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break;
case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break;
}
TRACELOG(LOG_INFO, "GLFW platform: %s", glfwPlatform);
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW): Initialized successfully");
return 0;
@ -1638,6 +1689,11 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
// NOTE: Postprocessing texture is not scaled to new size
}
static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley)
{
CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f);
}
// GLFW3 WindowIconify Callback, runs when window is minimized/restored
static void WindowIconifyCallback(GLFWwindow *window, int iconified)
{
@ -1714,10 +1770,10 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
if ((key == CORE.Input.Keyboard.exitKey) && (action == GLFW_PRESS)) glfwSetWindowShouldClose(platform.handle, GLFW_TRUE);
}
// GLFW3 Char Key Callback, runs on key down (gets equivalent unicode char value)
static void CharCallback(GLFWwindow *window, unsigned int key)
// GLFW3 Char Callback, get unicode codepoint value
static void CharCallback(GLFWwindow *window, unsigned int codepoint)
{
//TRACELOG(LOG_DEBUG, "Char Callback: KEY:%i(%c)", key, key);
//TRACELOG(LOG_DEBUG, "Char Callback: Codepoint: %i", codepoint);
// NOTE: Registers any key down considering OS keyboard layout but
// does not detect action events, those should be managed by user...
@ -1728,7 +1784,7 @@ static void CharCallback(GLFWwindow *window, unsigned int key)
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
{
// Add character to the queue
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = key;
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = codepoint;
CORE.Input.Keyboard.charPressedQueueCount++;
}
}
@ -1739,6 +1795,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int
// WARNING: GLFW could only return GLFW_PRESS (1) or GLFW_RELEASE (0) for now,
// but future releases may add more actions (i.e. GLFW_REPEAT)
CORE.Input.Mouse.currentButtonState[button] = action;
CORE.Input.Touch.currentTouchState[button] = action;
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)
// Process mouse events as touches to be able to use mouse-gestures

View file

@ -29,7 +29,7 @@
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2013-2023 Ramon Santamaria (@raysan5) and contributors
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -48,8 +48,14 @@
*
**********************************************************************************************/
#include "SDL.h" // SDL base library (window/rendered, input, timming... functionality)
#include "SDL_opengl.h" // SDL OpenGL functionality (if required, instead of internal renderer)
#include "SDL.h" // SDL base library (window/rendered, input, timing... functionality)
#if defined(GRAPHICS_API_OPENGL_ES2)
// It seems it does not need to be included to work
//#include "SDL_opengles2.h"
#else
#include "SDL_opengl.h" // SDL OpenGL functionality (if required, instead of internal renderer)
#endif
//----------------------------------------------------------------------------------
// Types and Structures Definition
@ -58,7 +64,7 @@ typedef struct {
SDL_Window *window;
SDL_GLContext glContext;
SDL_Joystick *gamepad;
SDL_Joystick *gamepad[MAX_GAMEPADS];
SDL_Cursor *cursor;
bool cursorRelative;
} PlatformData;
@ -493,9 +499,9 @@ void SetWindowIcon(Image image)
bmask = 0x001F, amask = 0;
depth = 16, pitch = image.width * 2;
break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8:
rmask = 0xFF0000, gmask = 0x00FF00;
bmask = 0x0000FF, amask = 0;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // Uses BGR for 24-bit
rmask = 0x0000FF, gmask = 0x00FF00;
bmask = 0xFF0000, amask = 0;
depth = 24, pitch = image.width * 3;
break;
case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
@ -592,7 +598,7 @@ void SetWindowMonitor(int monitor)
// NOTE:
// 1. SDL started supporting moving exclusive fullscreen windows between displays on SDL3,
// see commit https://github.com/libsdl-org/SDL/commit/3f5ef7dd422057edbcf3e736107e34be4b75d9ba
// 2. A workround for SDL2 is leaving fullscreen, moving the window, then entering full screen again.
// 2. A workaround for SDL2 is leaving fullscreen, moving the window, then entering full screen again.
const bool wasFullscreen = ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) ? true : false;
const int screenWidth = CORE.Window.screen.width;
@ -611,7 +617,7 @@ void SetWindowMonitor(int monitor)
// ending up positioned partly outside the target display.
// 2. The workaround for that is, previously to moving the window,
// setting the window size to the target display size, so they match.
// 3. It was't done here because we can't assume changing the window size automatically
// 3. It wasn't done here because we can't assume changing the window size automatically
// is acceptable behavior by the user.
SDL_SetWindowPosition(platform.window, usableBounds.x, usableBounds.y);
CORE.Window.position.x = usableBounds.x;
@ -932,9 +938,26 @@ int SetGamepadMappings(const char *mappings)
return SDL_GameControllerAddMapping(mappings);
}
// Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor)
{
//Limit input values to between 0.0f and 1.0f
leftMotor = (0.0f > leftMotor) ? 0.0f : leftMotor;
rightMotor = (0.0f > rightMotor) ? 0.0f : rightMotor;
leftMotor = (1.0f < leftMotor) ? 1.0f : leftMotor;
rightMotor = (1.0f < rightMotor) ? 1.0f : rightMotor;
if (IsGamepadAvailable(gamepad))
{
SDL_JoystickRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(MAX_GAMEPAD_VIBRATION_TIME*1000.0f));
}
}
// Set mouse position XY
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;
}
@ -948,6 +971,22 @@ void SetMouseCursor(int cursor)
CORE.Input.Mouse.cursor = cursor;
}
static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event)
{
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] = 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;
}
for (int i = CORE.Input.Touch.pointCount; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.currentTouchState[i] = 0;
}
// Register all input events
void PollInputEvents(void)
{
@ -961,9 +1000,6 @@ void PollInputEvents(void)
CORE.Input.Keyboard.keyPressedQueueCount = 0;
CORE.Input.Keyboard.charPressedQueueCount = 0;
// Reset key repeats
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
// Reset mouse wheel
CORE.Input.Mouse.currentWheelMove.x = 0;
CORE.Input.Mouse.currentWheelMove.y = 0;
@ -973,25 +1009,27 @@ void PollInputEvents(void)
else CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
// Reset last gamepad button/axis registered state
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
for (int i = 0; i < MAX_GAMEPADS; i++) CORE.Input.Gamepad.axisCount[i] = 0;
for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++)
{
// Check if gamepad is available
if (CORE.Input.Gamepad.ready[i])
{
// Register previous gamepad button states
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++)
{
CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
}
}
}
// Register previous touch states
for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
// Reset touch positions
// TODO: It resets on target platform the mouse position and not filled again until a move-event,
// so, if mouse is not moved it returns a (0, 0) position... this behaviour should be reviewed!
//for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 };
// Map touch position to mouse position for convenience
// WARNING: If the target desktop device supports touch screen, this behavious should be reviewed!
// https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch
// https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
bool gestureUpdate = false; // Flag to note gestures require to update
bool realTouch = false; // Flag to differentiate real touch gestures from mouse ones
// Register previous keys states
// NOTE: Android supports up to 260 keys
@ -1004,7 +1042,7 @@ void PollInputEvents(void)
// Register previous mouse states
for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
// Poll input events for current plaform
// Poll input events for current platform
//-----------------------------------------------------------------------------
/*
// WARNING: Indexes into this array are obtained by using SDL_Scancode values, not SDL_Keycode values
@ -1070,11 +1108,17 @@ void PollInputEvents(void)
CORE.Window.currentFbo.height = height;
CORE.Window.resizedLastFrame = true;
} break;
case SDL_WINDOWEVENT_ENTER:
{
CORE.Input.Mouse.cursorOnScreen = true;
} break;
case SDL_WINDOWEVENT_LEAVE:
{
CORE.Input.Mouse.cursorOnScreen = false;
} break;
case SDL_WINDOWEVENT_HIDDEN:
case SDL_WINDOWEVENT_MINIMIZED:
case SDL_WINDOWEVENT_FOCUS_LOST:
case SDL_WINDOWEVENT_ENTER:
case SDL_WINDOWEVENT_SHOWN:
case SDL_WINDOWEVENT_FOCUS_GAINED:
case SDL_WINDOWEVENT_MAXIMIZED:
@ -1087,7 +1131,19 @@ void PollInputEvents(void)
case SDL_KEYDOWN:
{
KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode);
if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 1;
if (key != KEY_NULL) {
// If key was up, add it to the key pressed queue
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;
// TODO: Put exitKey verification outside the switch?
if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey])
@ -1102,6 +1158,21 @@ void PollInputEvents(void)
if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0;
} break;
case SDL_TEXTINPUT:
{
// NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int)
int codepointSize = 0;
// Check if there is space available in the queue
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
{
// Add character (codepoint) to the queue
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = GetCodepointNext(event.text.text, &codepointSize);
CORE.Input.Keyboard.charPressedQueueCount++;
}
} break;
// Check mouse events
case SDL_MOUSEBUTTONDOWN:
{
@ -1112,9 +1183,9 @@ void PollInputEvents(void)
else if (btn == 1) btn = 2;
CORE.Input.Mouse.currentButtonState[btn] = 1;
CORE.Input.Touch.currentTouchState[btn] = 1;
touchAction = 1;
gestureUpdate = true;
} break;
case SDL_MOUSEBUTTONUP:
{
@ -1125,9 +1196,9 @@ void PollInputEvents(void)
else if (btn == 1) btn = 2;
CORE.Input.Mouse.currentButtonState[btn] = 0;
CORE.Input.Touch.currentTouchState[btn] = 0;
touchAction = 0;
gestureUpdate = true;
} break;
case SDL_MOUSEWHEEL:
{
@ -1150,24 +1221,160 @@ void PollInputEvents(void)
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
touchAction = 2;
gestureUpdate = true;
} 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;
// Check gamepad events
case SDL_JOYDEVICEADDED:
{
int jid = event.jdevice.which;
if (!CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS))
{
platform.gamepad[jid] = SDL_JoystickOpen(jid);
if (platform.gamepad[jid])
{
CORE.Input.Gamepad.ready[jid] = true;
CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(platform.gamepad[jid]);
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
strncpy(CORE.Input.Gamepad.name[jid], SDL_JoystickName(platform.gamepad[jid]), 63);
CORE.Input.Gamepad.name[jid][63] = '\0';
}
else
{
TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
}
}
} break;
case SDL_JOYDEVICEREMOVED:
{
int jid = event.jdevice.which;
if (jid == SDL_JoystickInstanceID(platform.gamepad[jid]))
{
SDL_JoystickClose(platform.gamepad[jid]);
platform.gamepad[jid] = SDL_JoystickOpen(0);
CORE.Input.Gamepad.ready[jid] = false;
memset(CORE.Input.Gamepad.name[jid], 0, 64);
}
} break;
case SDL_JOYBUTTONDOWN:
{
int button = -1;
switch (event.jbutton.button)
{
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)
{
CORE.Input.Gamepad.currentButtonState[event.jbutton.which][button] = 1;
CORE.Input.Gamepad.lastButtonPressed = button;
}
} break;
case SDL_JOYBUTTONUP:
{
int button = -1;
switch (event.jbutton.button)
{
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)
{
CORE.Input.Gamepad.currentButtonState[event.jbutton.which][button] = 0;
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
}
} break;
case SDL_JOYAXISMOTION:
{
// Motion on gamepad 0
if (event.jaxis.which == 0)
int axis = -1;
switch (event.jaxis.axis)
{
// X axis motion
if (event.jaxis.axis == 0)
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)
{
// SDL axis value range is -32768 to 32767, we normalize it to RayLib's -1.0 to 1.0f range
float value = event.jaxis.value / (float) 32767;
CORE.Input.Gamepad.axisState[event.jaxis.which][axis] = value;
// Register button state for triggers in addition to their axes
if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))
{
//...
}
// Y axis motion
else if (event.jaxis.axis == 1)
{
//...
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[event.jaxis.which][button] = pressed;
if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
}
}
} break;
@ -1175,7 +1382,7 @@ void PollInputEvents(void)
}
#if defined(SUPPORT_GESTURES_SYSTEM)
if (gestureUpdate)
if (touchAction > -1)
{
// Process mouse events as touches to be able to use mouse-gestures
GestureEvent gestureEvent = { 0 };
@ -1190,7 +1397,7 @@ void PollInputEvents(void)
gestureEvent.pointCount = 1;
// Register touch points position, only one point registered
if (touchAction == 2) gestureEvent.position[0] = CORE.Input.Touch.position[0];
if (touchAction == 2 || realTouch) gestureEvent.position[0] = CORE.Input.Touch.position[0];
else gestureEvent.position[0] = GetMousePosition();
// Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height
@ -1199,6 +1406,8 @@ void PollInputEvents(void)
// Gesture data is sent to gestures-system for processing
ProcessGestureEvent(gestureEvent);
touchAction = -1;
}
#endif
}
@ -1212,8 +1421,9 @@ void PollInputEvents(void)
// Initialize platform: graphics, inputs and more
int InitPlatform(void)
{
// Initialize SDL internal global state
int result = SDL_Init(SDL_INIT_EVERYTHING);
// Initialize SDL internal global state, only required systems
// NOTE: Not all systems need to be initialized, SDL_INIT_AUDIO is not required, managed by miniaudio
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; }
// Initialize graphic device: display/window and graphic context
@ -1265,11 +1475,7 @@ int InitPlatform(void)
{
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
#if defined(__APPLE__)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // OSX Requires forward compatibility
#else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#endif
}
else if (rlGetVersion() == RL_OPENGL_43)
{
@ -1310,7 +1516,7 @@ int InitPlatform(void)
// Init OpenGL context
platform.glContext = SDL_GL_CreateContext(platform.window);
// Check window and glContext have been initialized succesfully
// Check window and glContext have been initialized successfully
if ((platform.window != NULL) && (platform.glContext != NULL))
{
CORE.Window.ready = true;
@ -1345,19 +1551,38 @@ int InitPlatform(void)
// Initialize input events system
//----------------------------------------------------------------------------
if (SDL_NumJoysticks() >= 1)
// Initialize gamepads
for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++)
{
platform.gamepad = SDL_JoystickOpen(0);
//if (platform.gamepadgamepad == NULL) TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
platform.gamepad[i] = SDL_JoystickOpen(i);
if (platform.gamepad[i])
{
CORE.Input.Gamepad.ready[i] = true;
CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(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_JoystickName(platform.gamepad[i]), 63);
CORE.Input.Gamepad.name[i][63] = '\0';
}
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
}
// Disable mouse events being interpreted as touch events
// NOTE: This is wanted because there are SDL_FINGER* events available which provide unique data
// Due to the way PollInputEvents() and rgestures.h are currently implemented, setting this won't break SUPPORT_MOUSE_GESTURES
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
//----------------------------------------------------------------------------
// Initialize timming system
// Initialize timing system
//----------------------------------------------------------------------------
// NOTE: No need to call InitTimer(), let SDL manage it internally
CORE.Time.previous = GetTime(); // Get time as double
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "1"); // SDL equivalent of timeBeginPeriod() and timeEndPeriod()
#endif
//----------------------------------------------------------------------------
// Initialize storage system

File diff suppressed because it is too large Load diff