Update C sources
This commit is contained in:
parent
22ca1484d1
commit
781c207678
27 changed files with 13963 additions and 4637 deletions
412
raylib/rcore.c
412
raylib/rcore.c
|
@ -89,7 +89,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2022 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2023 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -151,10 +151,13 @@
|
|||
#include "external/sdefl.h" // Deflate (RFC 1951) compressor
|
||||
#endif
|
||||
|
||||
#if (defined(__linux__) || defined(PLATFORM_WEB)) && _POSIX_C_SOURCE < 199309L
|
||||
#if (defined(__linux__) || defined(PLATFORM_WEB)) && (_POSIX_C_SOURCE < 199309L)
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 199309L // Required for: CLOCK_MONOTONIC if compiled with c99 without gnu ext.
|
||||
#endif
|
||||
#if defined(__linux__) && !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
// Platform specific defines to handle GetApplicationDirectory()
|
||||
#if defined (PLATFORM_DESKTOP)
|
||||
|
@ -239,6 +242,7 @@
|
|||
#include <unistd.h> // Required for: usleep()
|
||||
|
||||
//#define GLFW_EXPOSE_NATIVE_COCOA // WARNING: Fails due to type redefinition
|
||||
void *glfwGetCocoaWindow(GLFWwindow* handle);
|
||||
#include "GLFW/glfw3native.h" // Required for: glfwGetCocoaWindow()
|
||||
#endif
|
||||
|
||||
|
@ -705,17 +709,15 @@ const char *TextFormat(const char *text, ...); // Formatting of text with
|
|||
#if defined(PLATFORM_ANDROID)
|
||||
// To allow easier porting to android, we allow the user to define a
|
||||
// main function which we call from android_main, defined by ourselves
|
||||
//extern int main(int argc, char *argv[]);
|
||||
extern void android_run();
|
||||
extern int main(int argc, char *argv[]);
|
||||
|
||||
void android_main(struct android_app *app)
|
||||
{
|
||||
char arg0[] = "raylib"; // NOTE: argv[] are mutable
|
||||
CORE.Android.app = app;
|
||||
|
||||
(void)android_run();
|
||||
// NOTE: Return codes != 0 are skipped
|
||||
//(void)main(1, (char *[]) { arg0, NULL });
|
||||
(void)main(1, (char *[]) { arg0, NULL });
|
||||
}
|
||||
|
||||
// NOTE: Add this to header (if apps really need it)
|
||||
|
@ -767,7 +769,7 @@ void InitWindow(int width, int height, const char *title)
|
|||
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
||||
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
||||
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
||||
CORE.Input.Gamepad.lastButtonPressed = -1;
|
||||
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
||||
#if defined(SUPPORT_EVENTS_WAITING)
|
||||
CORE.Window.eventWaiting = true;
|
||||
#endif
|
||||
|
@ -847,6 +849,7 @@ void InitWindow(int width, int height, const char *title)
|
|||
TRACELOG(LOG_FATAL, "Failed to initialize Graphic Device");
|
||||
return;
|
||||
}
|
||||
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
|
||||
|
||||
// Initialize hi-res timer
|
||||
InitTimer();
|
||||
|
@ -863,7 +866,7 @@ void InitWindow(int width, int height, const char *title)
|
|||
LoadFontDefault();
|
||||
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||
Rectangle rec = GetFontDefault().recs[95];
|
||||
// NOTE: We setup a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
|
||||
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
|
||||
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); // WARNING: Module required: rshapes
|
||||
#endif
|
||||
#else
|
||||
|
@ -921,9 +924,6 @@ void InitWindow(int width, int height, const char *title)
|
|||
emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
||||
#endif
|
||||
|
||||
CORE.Input.Mouse.currentPosition.x = (float)CORE.Window.screen.width/2.0f;
|
||||
CORE.Input.Mouse.currentPosition.y = (float)CORE.Window.screen.height/2.0f;
|
||||
|
||||
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
||||
events = (AutomationEvent *)malloc(MAX_CODE_AUTOMATION_EVENTS*sizeof(AutomationEvent));
|
||||
CORE.Time.frameCounter = 0;
|
||||
|
@ -1141,9 +1141,8 @@ bool IsWindowMinimized(void)
|
|||
{
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||
return ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if window has been maximized (only PLATFORM_DESKTOP)
|
||||
|
@ -1151,9 +1150,8 @@ bool IsWindowMaximized(void)
|
|||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
return ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if window has the focus
|
||||
|
@ -1161,9 +1159,11 @@ bool IsWindowFocused(void)
|
|||
{
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||
return ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
return CORE.Android.appEnabled;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if window has been resizedLastFrame
|
||||
|
@ -1316,7 +1316,7 @@ void MaximizeWindow(void)
|
|||
void MinimizeWindow(void)
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
// NOTE: Following function launches callback that sets appropiate flag!
|
||||
// NOTE: Following function launches callback that sets appropriate flag!
|
||||
glfwIconifyWindow(CORE.Window.handle);
|
||||
#endif
|
||||
}
|
||||
|
@ -1415,13 +1415,13 @@ void SetWindowState(unsigned int flags)
|
|||
// State change: FLAG_WINDOW_TRANSPARENT
|
||||
if (((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) != (flags & FLAG_WINDOW_TRANSPARENT)) && ((flags & FLAG_WINDOW_TRANSPARENT) > 0))
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only by configured before window initialization");
|
||||
TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization");
|
||||
}
|
||||
|
||||
// State change: FLAG_WINDOW_HIGHDPI
|
||||
if (((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) != (flags & FLAG_WINDOW_HIGHDPI)) && ((flags & FLAG_WINDOW_HIGHDPI) > 0))
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "WINDOW: High DPI can only by configured before window initialization");
|
||||
TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization");
|
||||
}
|
||||
|
||||
// State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
|
||||
|
@ -1434,13 +1434,13 @@ void SetWindowState(unsigned int flags)
|
|||
// State change: FLAG_MSAA_4X_HINT
|
||||
if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) != (flags & FLAG_MSAA_4X_HINT)) && ((flags & FLAG_MSAA_4X_HINT) > 0))
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "WINDOW: MSAA can only by configured before window initialization");
|
||||
TRACELOG(LOG_WARNING, "WINDOW: MSAA can only be configured before window initialization");
|
||||
}
|
||||
|
||||
// State change: FLAG_INTERLACED_HINT
|
||||
if (((CORE.Window.flags & FLAG_INTERLACED_HINT) != (flags & FLAG_INTERLACED_HINT)) && ((flags & FLAG_INTERLACED_HINT) > 0))
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only by configured before window initialization");
|
||||
TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1523,13 +1523,13 @@ void ClearWindowState(unsigned int flags)
|
|||
// State change: FLAG_WINDOW_TRANSPARENT
|
||||
if (((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) && ((flags & FLAG_WINDOW_TRANSPARENT) > 0))
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only by configured before window initialization");
|
||||
TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization");
|
||||
}
|
||||
|
||||
// State change: FLAG_WINDOW_HIGHDPI
|
||||
if (((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) && ((flags & FLAG_WINDOW_HIGHDPI) > 0))
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "WINDOW: High DPI can only by configured before window initialization");
|
||||
TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization");
|
||||
}
|
||||
|
||||
// State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
|
||||
|
@ -1542,35 +1542,81 @@ void ClearWindowState(unsigned int flags)
|
|||
// State change: FLAG_MSAA_4X_HINT
|
||||
if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) > 0) && ((flags & FLAG_MSAA_4X_HINT) > 0))
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "WINDOW: MSAA can only by configured before window initialization");
|
||||
TRACELOG(LOG_WARNING, "WINDOW: MSAA can only be configured before window initialization");
|
||||
}
|
||||
|
||||
// State change: FLAG_INTERLACED_HINT
|
||||
if (((CORE.Window.flags & FLAG_INTERLACED_HINT) > 0) && ((flags & FLAG_INTERLACED_HINT) > 0))
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only by configured before window initialization");
|
||||
TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set icon for window (only PLATFORM_DESKTOP)
|
||||
// NOTE: Image must be in RGBA format, 8bit per channel
|
||||
// NOTE 1: Image must be in RGBA format, 8bit per channel
|
||||
// NOTE 2: Image is scaled by the OS for all required sizes
|
||||
void SetWindowIcon(Image image)
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
if (image.format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
|
||||
if (image.data == NULL)
|
||||
{
|
||||
GLFWimage icon[1] = { 0 };
|
||||
|
||||
icon[0].width = image.width;
|
||||
icon[0].height = image.height;
|
||||
icon[0].pixels = (unsigned char *)image.data;
|
||||
|
||||
// NOTE 1: We only support one image icon
|
||||
// NOTE 2: The specified image data is copied before this function returns
|
||||
glfwSetWindowIcon(CORE.Window.handle, 1, icon);
|
||||
// Revert to the default window icon, pass in an empty image array
|
||||
glfwSetWindowIcon(CORE.Window.handle, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (image.format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
|
||||
{
|
||||
GLFWimage icon[1] = { 0 };
|
||||
|
||||
icon[0].width = image.width;
|
||||
icon[0].height = image.height;
|
||||
icon[0].pixels = (unsigned char *)image.data;
|
||||
|
||||
// NOTE 1: We only support one image icon
|
||||
// NOTE 2: The specified image data is copied before this function returns
|
||||
glfwSetWindowIcon(CORE.Window.handle, 1, icon);
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set icon for window (multiple images, only PLATFORM_DESKTOP)
|
||||
// NOTE 1: Images must be in RGBA format, 8bit per channel
|
||||
// NOTE 2: The multiple images are used depending on provided sizes
|
||||
// Standard Windows icon sizes: 256, 128, 96, 64, 48, 32, 24, 16
|
||||
void SetWindowIcons(Image *images, int count)
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
if ((images == NULL) || (count <= 0))
|
||||
{
|
||||
// Revert to the default window icon, pass in an empty image array
|
||||
glfwSetWindowIcon(CORE.Window.handle, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
int valid = 0;
|
||||
GLFWimage *icons = RL_CALLOC(count, sizeof(GLFWimage));
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (images[i].format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
|
||||
{
|
||||
icons[valid].width = images[i].width;
|
||||
icons[valid].height = images[i].height;
|
||||
icons[valid].pixels = (unsigned char *)images[i].data;
|
||||
|
||||
valid++;
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format");
|
||||
}
|
||||
// NOTE: Images data is copied internally before this function returns
|
||||
glfwSetWindowIcon(CORE.Window.handle, valid, icons);
|
||||
|
||||
RL_FREE(icons);
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1667,16 +1713,17 @@ void *GetWindowHandle(void)
|
|||
// NOTE: Returned handle is: void *HWND (windows.h)
|
||||
return glfwGetWin32Window(CORE.Window.handle);
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
#if defined(PLATFORM_DESKTOP) && defined(__linux__)
|
||||
// NOTE: Returned handle is: unsigned long Window (X.h)
|
||||
// typedef unsigned long XID;
|
||||
// typedef XID Window;
|
||||
//unsigned long id = (unsigned long)glfwGetX11Window(window);
|
||||
return NULL; // TODO: Find a way to return value... cast to void *?
|
||||
//unsigned long id = (unsigned long)glfwGetX11Window(CORE.Window.handle);
|
||||
//return NULL; // TODO: Find a way to return value... cast to void *?
|
||||
return (void *)CORE.Window.handle;
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
// NOTE: Returned handle is: (objc_object *)
|
||||
return NULL; // TODO: return (void *)glfwGetCocoaWindow(window);
|
||||
return (void *)glfwGetCocoaWindow(CORE.Window.handle);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
|
@ -1785,6 +1832,12 @@ int GetMonitorWidth(int monitor)
|
|||
else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");
|
||||
#endif
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
if (CORE.Android.app->window != NULL)
|
||||
{
|
||||
return ANativeWindow_getWidth(CORE.Android.app->window);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -1804,6 +1857,12 @@ int GetMonitorHeight(int monitor)
|
|||
else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");
|
||||
#endif
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
if (CORE.Android.app->window != NULL)
|
||||
{
|
||||
return ANativeWindow_getHeight(CORE.Android.app->window);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -1935,10 +1994,40 @@ void SetClipboardText(const char *text)
|
|||
glfwSetClipboardString(CORE.Window.handle, text);
|
||||
#endif
|
||||
#if defined(PLATFORM_WEB)
|
||||
emscripten_run_script(TextFormat("navigator.clipboard.writeText('%s')", text));
|
||||
// Security check to (partially) avoid malicious code
|
||||
if (strchr(text, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided Clipboard could be potentially malicious, avoid [\'] character");
|
||||
else emscripten_run_script(TextFormat("navigator.clipboard.writeText('%s')", text));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get clipboard text content
|
||||
// NOTE: returned string is allocated and freed by GLFW
|
||||
const char *GetClipboardText(void)
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
return glfwGetClipboardString(CORE.Window.handle);
|
||||
#endif
|
||||
#if defined(PLATFORM_WEB)
|
||||
/*
|
||||
// Accessing clipboard data from browser is tricky due to security reasons
|
||||
// The method to use is navigator.clipboard.readText() but this is an asynchronous method
|
||||
// that will return at some moment after the function is called with the required data
|
||||
emscripten_run_script_string("navigator.clipboard.readText() \
|
||||
.then(text => { document.getElementById('clipboard').innerText = text; console.log('Pasted content: ', text); }) \
|
||||
.catch(err => { console.error('Failed to read clipboard contents: ', err); });"
|
||||
);
|
||||
|
||||
// The main issue is getting that data, one approach could be using ASYNCIFY and wait
|
||||
// for the data but it requires adding Asyncify emscripten library on compilation
|
||||
|
||||
// Another approach could be just copy the data in a HTML text field and try to retrieve it
|
||||
// later on if available... and clean it for future accesses
|
||||
*/
|
||||
return NULL;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Enable waiting for events on EndDrawing(), no automatic event polling
|
||||
void EnableEventWaiting(void)
|
||||
{
|
||||
|
@ -1951,19 +2040,6 @@ void DisableEventWaiting(void)
|
|||
CORE.Window.eventWaiting = false;
|
||||
}
|
||||
|
||||
// Get clipboard text content
|
||||
// NOTE: returned string is allocated and freed by GLFW
|
||||
const char *GetClipboardText(void)
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
return glfwGetClipboardString(CORE.Window.handle);
|
||||
#endif
|
||||
#if defined(PLATFORM_WEB)
|
||||
return emscripten_run_script_string("navigator.clipboard.readText()");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Show mouse cursor
|
||||
void ShowCursor(void)
|
||||
{
|
||||
|
@ -1999,6 +2075,8 @@ void EnableCursor(void)
|
|||
#if defined(PLATFORM_WEB)
|
||||
emscripten_exit_pointerlock();
|
||||
#endif
|
||||
// Set cursor position in the middle
|
||||
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
|
||||
|
||||
CORE.Input.Mouse.cursorHidden = false;
|
||||
}
|
||||
|
@ -2012,6 +2090,8 @@ void DisableCursor(void)
|
|||
#if defined(PLATFORM_WEB)
|
||||
emscripten_request_pointerlock("#canvas", 1);
|
||||
#endif
|
||||
// Set cursor position in the middle
|
||||
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
|
||||
|
||||
CORE.Input.Mouse.cursorHidden = true;
|
||||
}
|
||||
|
@ -2173,7 +2253,7 @@ void EndMode2D(void)
|
|||
}
|
||||
|
||||
// Initializes 3D mode with custom camera (3D)
|
||||
void BeginMode3D(Camera3D camera)
|
||||
void BeginMode3D(Camera camera)
|
||||
{
|
||||
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
||||
|
||||
|
@ -2448,10 +2528,6 @@ Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
|||
Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
|
||||
{
|
||||
Shader shader = { 0 };
|
||||
shader.locs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int));
|
||||
|
||||
// NOTE: All locations must be reseted to -1 (no location)
|
||||
for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
|
||||
|
||||
shader.id = rlLoadShaderCode(vsCode, fsCode);
|
||||
|
||||
|
@ -2468,7 +2544,12 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
|
|||
|
||||
// NOTE: If any location is not found, loc point becomes -1
|
||||
|
||||
// Get handles to GLSL input attibute locations
|
||||
shader.locs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int));
|
||||
|
||||
// All locations reset to -1 (no location)
|
||||
for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
|
||||
|
||||
// Get handles to GLSL input attribute locations
|
||||
shader.locs[SHADER_LOC_VERTEX_POSITION] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION);
|
||||
shader.locs[SHADER_LOC_VERTEX_TEXCOORD01] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);
|
||||
shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
|
||||
|
@ -2493,12 +2574,46 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
|
|||
return shader;
|
||||
}
|
||||
|
||||
// Check if a shader is ready
|
||||
bool IsShaderReady(Shader shader)
|
||||
{
|
||||
return ((shader.id > 0) && // Validate shader id (loaded successfully)
|
||||
(shader.locs != NULL)); // Validate memory has been allocated for default shader locations
|
||||
|
||||
// The following locations are tried to be set automatically (locs[i] >= 0),
|
||||
// any of them can be checked for validation but the only mandatory one is, afaik, SHADER_LOC_VERTEX_POSITION
|
||||
// NOTE: Users can also setup manually their own attributes/uniforms and do not used the default raylib ones
|
||||
|
||||
// Vertex shader attribute locations (default)
|
||||
// shader.locs[SHADER_LOC_VERTEX_POSITION] // Set by default internal shader
|
||||
// shader.locs[SHADER_LOC_VERTEX_TEXCOORD01] // Set by default internal shader
|
||||
// shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]
|
||||
// shader.locs[SHADER_LOC_VERTEX_NORMAL]
|
||||
// shader.locs[SHADER_LOC_VERTEX_TANGENT]
|
||||
// shader.locs[SHADER_LOC_VERTEX_COLOR] // Set by default internal shader
|
||||
|
||||
// Vertex shader uniform locations (default)
|
||||
// shader.locs[SHADER_LOC_MATRIX_MVP] // Set by default internal shader
|
||||
// shader.locs[SHADER_LOC_MATRIX_VIEW]
|
||||
// shader.locs[SHADER_LOC_MATRIX_PROJECTION]
|
||||
// shader.locs[SHADER_LOC_MATRIX_MODEL]
|
||||
// shader.locs[SHADER_LOC_MATRIX_NORMAL]
|
||||
|
||||
// Fragment shader uniform locations (default)
|
||||
// shader.locs[SHADER_LOC_COLOR_DIFFUSE] // Set by default internal shader
|
||||
// shader.locs[SHADER_LOC_MAP_DIFFUSE] // Set by default internal shader
|
||||
// shader.locs[SHADER_LOC_MAP_SPECULAR]
|
||||
// shader.locs[SHADER_LOC_MAP_NORMAL]
|
||||
}
|
||||
|
||||
// Unload shader from GPU memory (VRAM)
|
||||
void UnloadShader(Shader shader)
|
||||
{
|
||||
if (shader.id != rlGetShaderIdDefault())
|
||||
{
|
||||
rlUnloadShaderProgram(shader.id);
|
||||
|
||||
// NOTE: If shader loading failed, it should be 0
|
||||
RL_FREE(shader.locs);
|
||||
}
|
||||
}
|
||||
|
@ -2524,25 +2639,34 @@ void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformT
|
|||
// Set shader uniform value vector
|
||||
void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count)
|
||||
{
|
||||
rlEnableShader(shader.id);
|
||||
rlSetUniform(locIndex, value, uniformType, count);
|
||||
//rlDisableShader(); // Avoid reseting current shader program, in case other uniforms are set
|
||||
if (locIndex > -1)
|
||||
{
|
||||
rlEnableShader(shader.id);
|
||||
rlSetUniform(locIndex, value, uniformType, count);
|
||||
//rlDisableShader(); // Avoid resetting current shader program, in case other uniforms are set
|
||||
}
|
||||
}
|
||||
|
||||
// Set shader uniform value (matrix 4x4)
|
||||
void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat)
|
||||
{
|
||||
rlEnableShader(shader.id);
|
||||
rlSetUniformMatrix(locIndex, mat);
|
||||
//rlDisableShader();
|
||||
if (locIndex > -1)
|
||||
{
|
||||
rlEnableShader(shader.id);
|
||||
rlSetUniformMatrix(locIndex, mat);
|
||||
//rlDisableShader();
|
||||
}
|
||||
}
|
||||
|
||||
// Set shader uniform value for texture
|
||||
void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture)
|
||||
{
|
||||
rlEnableShader(shader.id);
|
||||
rlSetUniformSampler(locIndex, texture.id);
|
||||
//rlDisableShader();
|
||||
if (locIndex > -1)
|
||||
{
|
||||
rlEnableShader(shader.id);
|
||||
rlSetUniformSampler(locIndex, texture.id);
|
||||
//rlDisableShader();
|
||||
}
|
||||
}
|
||||
|
||||
// Get a ray trace from mouse position
|
||||
|
@ -2584,7 +2708,7 @@ Ray GetMouseRay(Vector2 mouse, Camera camera)
|
|||
Vector3 farPoint = Vector3Unproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView);
|
||||
|
||||
// Unproject the mouse cursor in the near plane.
|
||||
// We need this as the source position because orthographic projects, compared to perspect doesn't have a
|
||||
// We need this as the source position because orthographic projects, compared to perspective doesn't have a
|
||||
// convergence point, meaning that the "eye" of the camera is more like a plane than a point.
|
||||
Vector3 cameraPlanePointerPos = Vector3Unproject((Vector3){ deviceCoords.x, deviceCoords.y, -1.0f }, matProj, matView);
|
||||
|
||||
|
@ -2757,22 +2881,24 @@ float GetFrameTime(void)
|
|||
// NOTE: On PLATFORM_DESKTOP, timer is initialized on glfwInit()
|
||||
double GetTime(void)
|
||||
{
|
||||
double time = 0.0;
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||
return glfwGetTime(); // Elapsed time since glfwInit()
|
||||
time = glfwGetTime(); // Elapsed time since glfwInit()
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
|
||||
struct timespec ts = { 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
unsigned long long int time = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
||||
|
||||
return (double)(time - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||
#endif
|
||||
return time;
|
||||
}
|
||||
|
||||
// Setup window configuration flags (view FLAGS)
|
||||
// NOTE: This function is expected to be called before window creation,
|
||||
// because it setups some flags for the window creation process.
|
||||
// because it sets up some flags for the window creation process.
|
||||
// To configure window states after creation, just use SetWindowState()
|
||||
void SetConfigFlags(unsigned int flags)
|
||||
{
|
||||
|
@ -2787,6 +2913,9 @@ void SetConfigFlags(unsigned int flags)
|
|||
void TakeScreenshot(const char *fileName)
|
||||
{
|
||||
#if defined(SUPPORT_MODULE_RTEXTURES)
|
||||
// Security check to (partially) avoid malicious code on PLATFORM_WEB
|
||||
if (strchr(fileName, '\'') != NULL) { TRACELOG(LOG_WARNING, "SYSTEM: Provided fileName could be potentially malicious, avoid [\'] character"); return; }
|
||||
|
||||
Vector2 scale = GetWindowScaleDPI();
|
||||
unsigned char *imgData = rlReadScreenPixels((int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y));
|
||||
Image image = { imgData, (int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y), 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
||||
|
@ -2810,6 +2939,9 @@ void TakeScreenshot(const char *fileName)
|
|||
}
|
||||
|
||||
// Get a random value between min and max (both included)
|
||||
// WARNING: Ranges higher than RAND_MAX will return invalid results
|
||||
// More specifically, if (max - min) > INT_MAX there will be an overflow,
|
||||
// and otherwise if (max - min) > RAND_MAX the random value will incorrectly never exceed a certain threshold
|
||||
int GetRandomValue(int min, int max)
|
||||
{
|
||||
if (min > max)
|
||||
|
@ -2819,6 +2951,11 @@ int GetRandomValue(int min, int max)
|
|||
min = tmp;
|
||||
}
|
||||
|
||||
if ((unsigned int)(max - min) > (unsigned int)RAND_MAX)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "Invalid GetRandomValue() arguments, range should not be higher than %i", RAND_MAX);
|
||||
}
|
||||
|
||||
return (rand()%(abs(max - min) + 1) + min);
|
||||
}
|
||||
|
||||
|
@ -2989,7 +3126,7 @@ const char *GetDirectoryPath(const char *filePath)
|
|||
if (filePath[1] != ':' && filePath[0] != '\\' && filePath[0] != '/')
|
||||
{
|
||||
// For security, we set starting path to current directory,
|
||||
// obtained path will be concated to this
|
||||
// obtained path will be concatenated to this
|
||||
dirPath[0] = '.';
|
||||
dirPath[1] = '/';
|
||||
}
|
||||
|
@ -3183,14 +3320,12 @@ FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool
|
|||
}
|
||||
|
||||
// Unload directory filepaths
|
||||
// WARNING: files.count is not reseted to 0 after unloading
|
||||
void UnloadDirectoryFiles(FilePathList files)
|
||||
{
|
||||
if (files.capacity > 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < files.capacity; i++) RL_FREE(files.paths[i]);
|
||||
for (unsigned int i = 0; i < files.capacity; i++) RL_FREE(files.paths[i]);
|
||||
|
||||
RL_FREE(files.paths);
|
||||
}
|
||||
RL_FREE(files.paths);
|
||||
}
|
||||
|
||||
// Change working directory, returns true on success
|
||||
|
@ -3275,7 +3410,7 @@ unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDa
|
|||
compData = (unsigned char *)RL_CALLOC(bounds, 1);
|
||||
*compDataSize = sdeflate(&sdefl, compData, data, dataSize, COMPRESSION_QUALITY_DEFLATE); // Compression level 8, same as stbwi
|
||||
|
||||
TraceLog(LOG_INFO, "SYSTEM: Compress data: Original size: %i -> Comp. size: %i", dataSize, *compDataSize);
|
||||
TRACELOG(LOG_INFO, "SYSTEM: Compress data: Original size: %i -> Comp. size: %i", dataSize, *compDataSize);
|
||||
#endif
|
||||
|
||||
return compData;
|
||||
|
@ -3288,16 +3423,19 @@ unsigned char *DecompressData(const unsigned char *compData, int compDataSize, i
|
|||
|
||||
#if defined(SUPPORT_COMPRESSION_API)
|
||||
// Decompress data from a valid DEFLATE stream
|
||||
data = RL_CALLOC(MAX_DECOMPRESSION_SIZE*1024*1024, 1);
|
||||
data = (unsigned char *)RL_CALLOC(MAX_DECOMPRESSION_SIZE*1024*1024, 1);
|
||||
int length = sinflate(data, MAX_DECOMPRESSION_SIZE*1024*1024, compData, compDataSize);
|
||||
unsigned char *temp = RL_REALLOC(data, length);
|
||||
|
||||
// WARNING: RL_REALLOC can make (and leave) data copies in memory, be careful with sensitive compressed data!
|
||||
// TODO: Use a different approach, create another buffer, copy data manually to it and wipe original buffer memory
|
||||
unsigned char *temp = (unsigned char *)RL_REALLOC(data, length);
|
||||
|
||||
if (temp != NULL) data = temp;
|
||||
else TRACELOG(LOG_WARNING, "SYSTEM: Failed to re-allocate required decompression memory");
|
||||
|
||||
*dataSize = length;
|
||||
|
||||
TraceLog(LOG_INFO, "SYSTEM: Decompress data: Comp. size: %i -> Original size: %i", compDataSize, *dataSize);
|
||||
TRACELOG(LOG_INFO, "SYSTEM: Decompress data: Comp. size: %i -> Original size: %i", compDataSize, *dataSize);
|
||||
#endif
|
||||
|
||||
return data;
|
||||
|
@ -3316,7 +3454,7 @@ char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize)
|
|||
|
||||
*outputSize = 4*((dataSize + 2)/3);
|
||||
|
||||
char *encodedData = RL_MALLOC(*outputSize);
|
||||
char *encodedData = (char *)RL_MALLOC(*outputSize);
|
||||
|
||||
if (encodedData == NULL) return NULL;
|
||||
|
||||
|
@ -3404,16 +3542,12 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
|
|||
// Ref: https://github.com/raysan5/raylib/issues/686
|
||||
void OpenURL(const char *url)
|
||||
{
|
||||
// Small security check trying to avoid (partially) malicious code...
|
||||
// sorry for the inconvenience when you hit this point...
|
||||
if (strchr(url, '\'') != NULL)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL is not valid");
|
||||
}
|
||||
// Security check to (aprtially) avoid malicious code on PLATFORM_WEB
|
||||
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
|
||||
else
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
char *cmd = (char *)RL_CALLOC(strlen(url) + 10, sizeof(char));
|
||||
char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char));
|
||||
#if defined(_WIN32)
|
||||
sprintf(cmd, "explorer \"%s\"", url);
|
||||
#endif
|
||||
|
@ -3508,7 +3642,7 @@ int GetKeyPressed(void)
|
|||
CORE.Input.Keyboard.keyPressedQueue[i] = CORE.Input.Keyboard.keyPressedQueue[i + 1];
|
||||
|
||||
// Reset last character in the queue
|
||||
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = 0;
|
||||
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount - 1] = 0;
|
||||
CORE.Input.Keyboard.keyPressedQueueCount--;
|
||||
}
|
||||
|
||||
|
@ -3530,7 +3664,7 @@ int GetCharPressed(void)
|
|||
CORE.Input.Keyboard.charPressedQueue[i] = CORE.Input.Keyboard.charPressedQueue[i + 1];
|
||||
|
||||
// Reset last character in the queue
|
||||
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = 0;
|
||||
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount - 1] = 0;
|
||||
CORE.Input.Keyboard.charPressedQueueCount--;
|
||||
}
|
||||
|
||||
|
@ -3743,7 +3877,7 @@ Vector2 GetMousePosition(void)
|
|||
// Get mouse delta between frames
|
||||
Vector2 GetMouseDelta(void)
|
||||
{
|
||||
Vector2 delta = {0};
|
||||
Vector2 delta = { 0 };
|
||||
|
||||
delta.x = CORE.Input.Mouse.currentPosition.x - CORE.Input.Mouse.previousPosition.x;
|
||||
delta.y = CORE.Input.Mouse.currentPosition.y - CORE.Input.Mouse.previousPosition.y;
|
||||
|
@ -3755,6 +3889,8 @@ Vector2 GetMouseDelta(void)
|
|||
void SetMousePosition(int x, int y)
|
||||
{
|
||||
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
|
||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||
// NOTE: emscripten not implemented
|
||||
glfwSetCursorPos(CORE.Window.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
|
||||
|
@ -3884,7 +4020,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|||
CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
|
||||
|
||||
// NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
|
||||
// ...in top-down or left-right to match display aspect ratio (no weird scalings)
|
||||
// ...in top-down or left-right to match display aspect ratio (no weird scaling)
|
||||
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||
glfwSetErrorCallback(ErrorCallback);
|
||||
|
@ -4005,7 +4141,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Enable OpenGL Debug Context
|
||||
#endif
|
||||
}
|
||||
else if (rlGetVersion() == RL_OPENGL_ES_20) // Request OpenGL ES 2.0 context
|
||||
else if (rlGetVersion() == RL_OPENGL_ES_20) // Request OpenGL ES 2.0 context
|
||||
{
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
|
@ -4053,8 +4189,18 @@ static bool InitGraphicsDevice(int width, int height)
|
|||
if (CORE.Window.fullscreen)
|
||||
{
|
||||
// remember center for switchinging from fullscreen to window
|
||||
CORE.Window.position.x = CORE.Window.display.width/2 - CORE.Window.screen.width/2;
|
||||
CORE.Window.position.y = CORE.Window.display.height/2 - CORE.Window.screen.height/2;
|
||||
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.
|
||||
// Toggling full-screened/windowed with pos(0, 0) can cause problems in some platforms, such as X11.
|
||||
CORE.Window.position.x = CORE.Window.display.width/4;
|
||||
CORE.Window.position.y = CORE.Window.display.height/4;
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE.Window.position.x = CORE.Window.display.width/2 - CORE.Window.screen.width/2;
|
||||
CORE.Window.position.y = CORE.Window.display.height/2 - CORE.Window.screen.height/2;
|
||||
}
|
||||
|
||||
if (CORE.Window.position.x < 0) CORE.Window.position.x = 0;
|
||||
if (CORE.Window.position.y < 0) CORE.Window.position.y = 0;
|
||||
|
@ -4083,7 +4229,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|||
// framebuffer is rendered correctly but once displayed on a 16:9 monitor, it gets stretched
|
||||
// by the sides to fit all monitor space...
|
||||
|
||||
// Try to setup the most appropiate fullscreen framebuffer for the requested screenWidth/screenHeight
|
||||
// Try to setup the most appropriate fullscreen framebuffer for the requested screenWidth/screenHeight
|
||||
// It considers device display resolution mode and setups a framebuffer with black bars if required (render size/offset)
|
||||
// Modified global variables: CORE.Window.screen.width/CORE.Window.screen.height - CORE.Window.render.width/CORE.Window.render.height - CORE.Window.renderOffset.x/CORE.Window.renderOffset.y - CORE.Window.screenScale
|
||||
// TODO: It is a quite cumbersome solution to display size vs requested size, it should be reviewed or removed...
|
||||
|
@ -4150,7 +4296,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|||
// NOTE: V-Sync can be enabled by graphic driver configuration
|
||||
if (CORE.Window.flags & FLAG_VSYNC_HINT)
|
||||
{
|
||||
// WARNING: It seems to hits a critical render path in Intel HD Graphics
|
||||
// WARNING: It seems to hit a critical render path in Intel HD Graphics
|
||||
glfwSwapInterval(1);
|
||||
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable VSYNC");
|
||||
}
|
||||
|
@ -4161,12 +4307,12 @@ static bool InitGraphicsDevice(int width, int height)
|
|||
#if defined(PLATFORM_DESKTOP)
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
|
||||
{
|
||||
// NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling
|
||||
// NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling.
|
||||
// Framebuffer scaling should be activated with: glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
|
||||
#if !defined(__APPLE__)
|
||||
glfwGetFramebufferSize(CORE.Window.handle, &fbWidth, &fbHeight);
|
||||
|
||||
// Screen scaling matrix is required in case desired screen area is different than display area
|
||||
// Screen scaling matrix is required in case desired screen area is different from display area
|
||||
CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f);
|
||||
|
||||
// Mouse input scaling for the new screen size
|
||||
|
@ -4764,7 +4910,7 @@ static void InitTimer(void)
|
|||
// NOTE: Sleep() granularity could be around 10 ms, it means, Sleep() could
|
||||
// take longer than expected... for that reason we use the busy wait loop
|
||||
// Ref: http://stackoverflow.com/questions/43057578/c-programming-win32-games-sleep-taking-longer-than-expected
|
||||
// Ref: http://www.geisswerks.com/ryan/FAQS/timing.html --> All about timming on Win32!
|
||||
// Ref: http://www.geisswerks.com/ryan/FAQS/timing.html --> All about timing on Win32!
|
||||
void WaitTime(double seconds)
|
||||
{
|
||||
#if defined(SUPPORT_BUSY_WAIT_LOOP) || defined(SUPPORT_PARTIALBUSY_WAIT_LOOP)
|
||||
|
@ -4859,7 +5005,7 @@ void PollInputEvents(void)
|
|||
|
||||
#if !(defined(PLATFORM_RPI) || defined(PLATFORM_DRM))
|
||||
// Reset last gamepad button/axis registered state
|
||||
CORE.Input.Gamepad.lastButtonPressed = -1;
|
||||
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
||||
CORE.Input.Gamepad.axisCount = 0;
|
||||
#endif
|
||||
|
||||
|
@ -5359,12 +5505,12 @@ static void CharCallback(GLFWwindow *window, unsigned int key)
|
|||
//TRACELOG(LOG_DEBUG, "Char Callback: KEY:%i(%c)", key, key);
|
||||
|
||||
// NOTE: Registers any key down considering OS keyboard layout but
|
||||
// do not detects action events, those should be managed by user...
|
||||
// does not detect action events, those should be managed by user...
|
||||
// Ref: https://github.com/glfw/glfw/issues/668#issuecomment-166794907
|
||||
// Ref: https://www.glfw.org/docs/latest/input_guide.html#input_char
|
||||
|
||||
// Check if there is space available in the queue
|
||||
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_KEY_PRESSED_QUEUE)
|
||||
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
|
||||
{
|
||||
// Add character to the queue
|
||||
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = key;
|
||||
|
@ -5402,7 +5548,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int
|
|||
gestureEvent.position[0].x /= (float)GetScreenWidth();
|
||||
gestureEvent.position[0].y /= (float)GetScreenHeight();
|
||||
|
||||
// Gesture data is sent to gestures system for processing
|
||||
// Gesture data is sent to gestures-system for processing
|
||||
ProcessGestureEvent(gestureEvent);
|
||||
#endif
|
||||
}
|
||||
|
@ -5433,7 +5579,7 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
|
|||
gestureEvent.position[0].x /= (float)GetScreenWidth();
|
||||
gestureEvent.position[0].y /= (float)GetScreenHeight();
|
||||
|
||||
// Gesture data is sent to gestures system for processing
|
||||
// Gesture data is sent to gestures-system for processing
|
||||
ProcessGestureEvent(gestureEvent);
|
||||
#endif
|
||||
}
|
||||
|
@ -5454,25 +5600,28 @@ static void CursorEnterCallback(GLFWwindow *window, int enter)
|
|||
// GLFW3 Window Drop Callback, runs when drop files into window
|
||||
static void WindowDropCallback(GLFWwindow *window, int count, const char **paths)
|
||||
{
|
||||
// In case previous dropped filepaths have not been freed, we free them
|
||||
if (CORE.Window.dropFileCount > 0)
|
||||
if (count > 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);
|
||||
// In case previous dropped filepaths have not been freed, we free them
|
||||
if (CORE.Window.dropFileCount > 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);
|
||||
|
||||
RL_FREE(CORE.Window.dropFilepaths);
|
||||
RL_FREE(CORE.Window.dropFilepaths);
|
||||
|
||||
CORE.Window.dropFileCount = 0;
|
||||
CORE.Window.dropFilepaths = NULL;
|
||||
}
|
||||
CORE.Window.dropFileCount = 0;
|
||||
CORE.Window.dropFilepaths = NULL;
|
||||
}
|
||||
|
||||
// WARNING: Paths are freed by GLFW when the callback returns, we must keep an internal copy
|
||||
CORE.Window.dropFileCount = count;
|
||||
CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *));
|
||||
// WARNING: Paths are freed by GLFW when the callback returns, we must keep an internal copy
|
||||
CORE.Window.dropFileCount = count;
|
||||
CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *));
|
||||
|
||||
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
|
||||
{
|
||||
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
||||
strcpy(CORE.Window.dropFilepaths[i], paths[i]);
|
||||
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
|
||||
{
|
||||
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
||||
strcpy(CORE.Window.dropFilepaths[i], paths[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -5702,14 +5851,15 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|||
CORE.Input.Gamepad.ready[0] = true;
|
||||
|
||||
GamepadButton button = AndroidTranslateGamepadButton(keycode);
|
||||
if (button == GAMEPAD_BUTTON_UNKNOWN)
|
||||
return 1;
|
||||
|
||||
if (button == GAMEPAD_BUTTON_UNKNOWN) return 1;
|
||||
|
||||
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
|
||||
{
|
||||
CORE.Input.Gamepad.currentButtonState[0][button] = 1;
|
||||
}
|
||||
else CORE.Input.Gamepad.currentButtonState[0][button] = 0; // Key up
|
||||
|
||||
return 1; // Handled gamepad button
|
||||
}
|
||||
|
||||
|
@ -6673,7 +6823,7 @@ static void *GamepadThread(void *arg)
|
|||
CORE.Input.Gamepad.currentButtonState[i][gamepadEvent.number] = (int)gamepadEvent.value;
|
||||
|
||||
if ((int)gamepadEvent.value == 1) CORE.Input.Gamepad.lastButtonPressed = gamepadEvent.number;
|
||||
else CORE.Input.Gamepad.lastButtonPressed = -1;
|
||||
else CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
||||
}
|
||||
}
|
||||
else if (gamepadEvent.type == JS_EVENT_AXIS)
|
||||
|
@ -6800,12 +6950,12 @@ static void LoadAutomationEvents(const char *fileName)
|
|||
// Load binary
|
||||
/*
|
||||
FILE *repFile = fopen(fileName, "rb");
|
||||
fread(fileId, 4, 1, repFile);
|
||||
fread(fileId, 1, 4, repFile);
|
||||
|
||||
if ((fileId[0] == 'r') && (fileId[1] == 'E') && (fileId[2] == 'P') && (fileId[1] == ' '))
|
||||
{
|
||||
fread(&eventCount, sizeof(int), 1, repFile);
|
||||
TraceLog(LOG_WARNING, "Events loaded: %i\n", eventCount);
|
||||
TRACELOG(LOG_WARNING, "Events loaded: %i\n", eventCount);
|
||||
fread(events, sizeof(AutomationEvent), eventCount, repFile);
|
||||
}
|
||||
|
||||
|
@ -6852,7 +7002,7 @@ static void ExportAutomationEvents(const char *fileName)
|
|||
// Save as binary
|
||||
/*
|
||||
FILE *repFile = fopen(fileName, "wb");
|
||||
fwrite(fileId, 4, 1, repFile);
|
||||
fwrite(fileId, sizeof(unsigned char), 4, repFile);
|
||||
fwrite(&eventCount, sizeof(int), 1, repFile);
|
||||
fwrite(events, sizeof(AutomationEvent), eventCount, repFile);
|
||||
fclose(repFile);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue