From 644e4adbe2026aa38bbf85e760d351806385d883 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 23 Mar 2026 11:51:37 +0100 Subject: [PATCH 001/185] Update rcore.c --- src/rcore.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index c83a1c4ae..894e00832 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -2278,10 +2278,8 @@ int FileMove(const char *srcPath, const char *dstPath) if (FileExists(srcPath)) { - if (FileCopy(srcPath, dstPath) == 0) - result = FileRemove(srcPath); - else - TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to copy file to [%s]", srcPath, dstPath); + if (FileCopy(srcPath, dstPath) == 0) result = FileRemove(srcPath); + else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to copy file to [%s]", srcPath, dstPath); } else TRACELOG(LOG_WARNING, "FILEIO: [%s] Source file does not exist", srcPath); From c1dbfc87f315e5525cb853afb87b301e9bf34743 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 23 Mar 2026 11:52:01 +0100 Subject: [PATCH 002/185] REVIEWED: PR #5679 --- src/platforms/rcore_desktop_rgfw.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 7817c7874..fb1fc6cf6 100755 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -1447,28 +1447,26 @@ void PollInputEvents(void) } break; case RGFW_mousePosChanged: { - float event_x = 0.0f, event_y = 0.0f; + float mouseX = 0.0f; + float mouseY = 0.0f; if (RGFW_window_isCaptured(platform.window)) { - event_x = (float)rgfw_event.mouse.vecX; - event_y = (float)rgfw_event.mouse.vecY; + mouseX = (float)rgfw_event.mouse.vecX; + mouseY = (float)rgfw_event.mouse.vecY; } else { - event_x = (float)rgfw_event.mouse.x; - event_y = (float)rgfw_event.mouse.y; + mouseX = (float)rgfw_event.mouse.x; + mouseY = (float)rgfw_event.mouse.y; } #if defined(__EMSCRIPTEN__) - { - double canvasWidth = 0.0; - double canvasHeight = 0.0; - emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight); - event_x *= ((float)GetScreenWidth() / (float)canvasWidth); - event_y *= ((float)GetScreenHeight() / (float)canvasHeight); - } + double canvasWidth = 0.0; + double canvasHeight = 0.0; + emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight); + mouseX *= ((float)GetScreenWidth()/(float)canvasWidth); + mouseY *= ((float)GetScreenHeight()/(float)canvasHeight); #endif - if (RGFW_window_isCaptured(platform.window)) { CORE.Input.Mouse.currentPosition.x += event_x; From 7e8aca00b69ce416e29dfd0de8b8204811473f00 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 23 Mar 2026 11:53:31 +0100 Subject: [PATCH 003/185] Update textures_raw_data.c --- examples/textures/textures_raw_data.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/examples/textures/textures_raw_data.c b/examples/textures/textures_raw_data.c index c38983b53..49efc890e 100644 --- a/examples/textures/textures_raw_data.c +++ b/examples/textures/textures_raw_data.c @@ -17,8 +17,6 @@ #include "raylib.h" -#include // Required for: malloc() and free() - //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ @@ -39,26 +37,31 @@ int main(void) UnloadImage(fudesumiRaw); // Unload CPU (RAM) image data // Generate a checked texture by code - int width = 960; - int height = 480; + int imWidth = 960; + int imHeight = 480; // Dynamic memory allocation to store pixels data (Color type) - Color *pixels = (Color *)malloc(width*height*sizeof(Color)); + // WARNING: Using raylib provided MemAlloc() that uses default raylib + // internal memory allocator, so this data can be freed using UnloadImage() + // that also uses raylib internal memory de-allocator + Color *pixels = (Color *)MemAlloc(imWidth*imHeight*sizeof(Color)); - for (int y = 0; y < height; y++) + for (int y = 0; y < imHeight; y++) { - for (int x = 0; x < width; x++) + for (int x = 0; x < imWidth; x++) { - if (((x/32+y/32)/1)%2 == 0) pixels[y*width + x] = ORANGE; - else pixels[y*width + x] = GOLD; + if (((x/32+y/32)/1)%2 == 0) pixels[y*imWidth + x] = ORANGE; + else pixels[y*imWidth + x] = GOLD; } } // Load pixels data into an image structure and create texture + // NOTE: We can assign pixels directly to data because Color is R8G8B8A8 + // data structure defining that pixelformat, format must be set properly Image checkedIm = { - .data = pixels, // We can assign pixels directly to data - .width = width, - .height = height, + .data = pixels, + .width = imWidth, + .height = imHeight, .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, .mipmaps = 1 }; From ca1baca7c2847e6f19fa774f02cf3fec6a0b4211 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 23 Mar 2026 11:53:57 +0100 Subject: [PATCH 004/185] REVIEWED: examples memory allocators, using raylib provided macros --- examples/core/core_random_sequence.c | 2 +- examples/shapes/shapes_ball_physics.c | 94 +++++++++++++------------ examples/text/text_codepoints_loading.c | 4 +- examples/textures/textures_bunnymark.c | 4 +- examples/textures/textures_fog_of_war.c | 8 +-- 5 files changed, 59 insertions(+), 53 deletions(-) diff --git a/examples/core/core_random_sequence.c b/examples/core/core_random_sequence.c index 19d44461e..32ec3001b 100644 --- a/examples/core/core_random_sequence.c +++ b/examples/core/core_random_sequence.c @@ -111,7 +111,7 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- - free(rectangles); + RL_FREE(rectangles); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shapes/shapes_ball_physics.c b/examples/shapes/shapes_ball_physics.c index 9aba0cf57..9c18ab66e 100644 --- a/examples/shapes/shapes_ball_physics.c +++ b/examples/shapes/shapes_ball_physics.c @@ -17,15 +17,19 @@ #include "raylib.h" -#include -#include +#include // Required for: malloc(), free() +#include // Required for: hypot() -#define MAX_BALLS 5000 // Maximum quantity of balls +#define MAX_BALLS 5000 // Maximum quantity of balls +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +// Ball data type typedef struct Ball { - Vector2 pos; // Position - Vector2 vel; // Velocity - Vector2 ppos; // Previous position + Vector2 position; + Vector2 speed; + Vector2 prevPosition; float radius; float friction; float elasticity; @@ -45,11 +49,13 @@ int main(void) InitWindow(screenWidth, screenHeight, "raylib [shapes] example - ball physics"); - Ball *balls = (Ball*)malloc(sizeof(Ball)*MAX_BALLS); + Ball *balls = (Ball*)RL_MALLOC(sizeof(Ball)*MAX_BALLS); + + // Init first ball in the array balls[0] = (Ball){ - .pos = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f }, - .vel = { 200, 200 }, - .ppos = { 0 }, + .position = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f }, + .speed = { 200, 200 }, + .prevPosition = { 0 }, .radius = 40, .friction = 0.99f, .elasticity = 0.9f, @@ -58,12 +64,12 @@ int main(void) }; int ballCount = 1; - Ball *grabbedBall = NULL; // A pointer to the current ball that is grabbed - Vector2 pressOffset = { 0 }; // Mouse press offset relative to the ball that grabbedd + Ball *grabbedBall = NULL; // A pointer to the current ball that is grabbed + Vector2 pressOffset = { 0 }; // Mouse press offset relative to the ball that grabbedd - float gravity = 100; // World gravity + float gravity = 100; // World gravity - SetTargetFPS(60); // Set our game to run at 60 frames-per-second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- // Main game loop @@ -80,8 +86,8 @@ int main(void) for (int i = ballCount - 1; i >= 0; i--) { Ball *ball = &balls[i]; - pressOffset.x = mousePos.x - ball->pos.x; - pressOffset.y = mousePos.y - ball->pos.y; + pressOffset.x = mousePos.x - ball->position.x; + pressOffset.y = mousePos.y - ball->position.y; // If the distance between the ball position and the mouse press position // is less than or equal to the ball radius, the event occurred inside the ball @@ -110,9 +116,9 @@ int main(void) if (ballCount < MAX_BALLS) { balls[ballCount++] = (Ball){ - .pos = mousePos, - .vel = { (float)GetRandomValue(-300, 300), (float)GetRandomValue(-300, 300) }, - .ppos = { 0 }, + .position = mousePos, + .speed = { (float)GetRandomValue(-300, 300), (float)GetRandomValue(-300, 300) }, + .prevPosition = { 0 }, .radius = 20.0f + (float)GetRandomValue(0, 30), .friction = 0.99f, .elasticity = 0.9f, @@ -127,7 +133,7 @@ int main(void) { for (int i = 0; i < ballCount; i++) { - if (!balls[i].grabbed) balls[i].vel = (Vector2){ (float)GetRandomValue(-2000, 2000), (float)GetRandomValue(-2000, 2000) }; + if (!balls[i].grabbed) balls[i].speed = (Vector2){ (float)GetRandomValue(-2000, 2000), (float)GetRandomValue(-2000, 2000) }; } } @@ -143,49 +149,49 @@ int main(void) if (!ball->grabbed) { // Ball repositioning using the velocity - ball->pos.x += ball->vel.x * delta; - ball->pos.y += ball->vel.y * delta; + ball->position.x += ball->speed.x * delta; + ball->position.y += ball->speed.y * delta; // Does the ball hit the screen right boundary? - if ((ball->pos.x + ball->radius) >= screenWidth) + if ((ball->position.x + ball->radius) >= screenWidth) { - ball->pos.x = screenWidth - ball->radius; // Ball repositioning - ball->vel.x = -ball->vel.x*ball->elasticity; // Elasticity makes the ball lose 10% of its velocity on hit + ball->position.x = screenWidth - ball->radius; // Ball repositioning + ball->speed.x = -ball->speed.x*ball->elasticity; // Elasticity makes the ball lose 10% of its velocity on hit } // Does the ball hit the screen left boundary? - else if ((ball->pos.x - ball->radius) <= 0) + else if ((ball->position.x - ball->radius) <= 0) { - ball->pos.x = ball->radius; - ball->vel.x = -ball->vel.x*ball->elasticity; + ball->position.x = ball->radius; + ball->speed.x = -ball->speed.x*ball->elasticity; } // The same for y axis - if ((ball->pos.y + ball->radius) >= screenHeight) + if ((ball->position.y + ball->radius) >= screenHeight) { - ball->pos.y = screenHeight - ball->radius; - ball->vel.y = -ball->vel.y*ball->elasticity; + ball->position.y = screenHeight - ball->radius; + ball->speed.y = -ball->speed.y*ball->elasticity; } - else if ((ball->pos.y - ball->radius) <= 0) + else if ((ball->position.y - ball->radius) <= 0) { - ball->pos.y = ball->radius; - ball->vel.y = -ball->vel.y*ball->elasticity; + ball->position.y = ball->radius; + ball->speed.y = -ball->speed.y*ball->elasticity; } // Friction makes the ball lose 1% of its velocity each frame - ball->vel.x = ball->vel.x*ball->friction; + ball->speed.x = ball->speed.x*ball->friction; // Gravity affects only the y axis - ball->vel.y = ball->vel.y*ball->friction + gravity; + ball->speed.y = ball->speed.y*ball->friction + gravity; } else { // Ball repositioning using the mouse position - ball->pos.x = mousePos.x - pressOffset.x; - ball->pos.y = mousePos.y - pressOffset.y; + ball->position.x = mousePos.x - pressOffset.x; + ball->position.y = mousePos.y - pressOffset.y; // While the ball is grabbed, recalculates its velocity - ball->vel.x = (ball->pos.x - ball->ppos.x)/delta; - ball->vel.y = (ball->pos.y - ball->ppos.y)/delta; - ball->ppos = ball->pos; + ball->speed.x = (ball->position.x - ball->prevPosition.x)/delta; + ball->speed.y = (ball->position.y - ball->prevPosition.y)/delta; + ball->prevPosition = ball->position; } } //---------------------------------------------------------------------------------- @@ -198,8 +204,8 @@ int main(void) for (int i = 0; i < ballCount; i++) { - DrawCircleV(balls[i].pos, balls[i].radius, balls[i].color); - DrawCircleLinesV(balls[i].pos, balls[i].radius, BLACK); + DrawCircleV(balls[i].position, balls[i].radius, balls[i].color); + DrawCircleLinesV(balls[i].position, balls[i].radius, BLACK); } DrawText("grab a ball by pressing with the mouse and throw it by releasing", 10, 10, 10, DARKGRAY); @@ -215,7 +221,7 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- - free(balls); + RL_FREE(balls); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/text/text_codepoints_loading.c b/examples/text/text_codepoints_loading.c index 1cd82d60e..1da8cf93f 100644 --- a/examples/text/text_codepoints_loading.c +++ b/examples/text/text_codepoints_loading.c @@ -61,7 +61,7 @@ int main(void) SetTextLineSpacing(20); // Set line spacing for multiline text (when line breaks are included '\n') // Free codepoints, atlas has already been generated - free(codepointsNoDups); + RL_FREE(codepointsNoDups); bool showFontAtlas = false; @@ -139,7 +139,7 @@ int main(void) static int *CodepointRemoveDuplicates(int *codepoints, int codepointCount, int *codepointsResultCount) { int codepointsNoDupsCount = codepointCount; - int *codepointsNoDups = (int *)calloc(codepointCount, sizeof(int)); + int *codepointsNoDups = (int *)RL_CALLOC(codepointCount, sizeof(int)); memcpy(codepointsNoDups, codepoints, codepointCount*sizeof(int)); // Remove duplicates diff --git a/examples/textures/textures_bunnymark.c b/examples/textures/textures_bunnymark.c index a04741227..64e55db43 100644 --- a/examples/textures/textures_bunnymark.c +++ b/examples/textures/textures_bunnymark.c @@ -47,7 +47,7 @@ int main(void) // Load bunny texture Texture2D texBunny = LoadTexture("resources/raybunny.png"); - Bunny *bunnies = (Bunny *)malloc(MAX_BUNNIES*sizeof(Bunny)); // Bunnies array + Bunny *bunnies = (Bunny *)RL_MALLOC(MAX_BUNNIES*sizeof(Bunny)); // Bunnies array int bunniesCount = 0; // Bunnies counter @@ -126,7 +126,7 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- - free(bunnies); // Unload bunnies data array + RL_FREE(bunnies); // Unload bunnies data array UnloadTexture(texBunny); // Unload bunny texture diff --git a/examples/textures/textures_fog_of_war.c b/examples/textures/textures_fog_of_war.c index 1354d7124..e4ed2b60a 100644 --- a/examples/textures/textures_fog_of_war.c +++ b/examples/textures/textures_fog_of_war.c @@ -51,8 +51,8 @@ int main(void) // NOTE: We can have up to 256 values for tile ids and for tile fog state, // probably we don't need that many values for fog state, it can be optimized // to use only 2 bits per fog state (reducing size by 4) but logic will be a bit more complex - map.tileIds = (unsigned char *)calloc(map.tilesX*map.tilesY, sizeof(unsigned char)); - map.tileFog = (unsigned char *)calloc(map.tilesX*map.tilesY, sizeof(unsigned char)); + map.tileIds = (unsigned char *)RL_CALLOC(map.tilesX*map.tilesY, sizeof(unsigned char)); + map.tileFog = (unsigned char *)RL_CALLOC(map.tilesX*map.tilesY, sizeof(unsigned char)); // Load map tiles (generating 2 random tile ids for testing) // NOTE: Map tile ids should be probably loaded from an external map file @@ -149,8 +149,8 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- - free(map.tileIds); // Free allocated map tile ids - free(map.tileFog); // Free allocated map tile fog state + RL_FREE(map.tileIds); // Free allocated map tile ids + RL_FREE(map.tileFog); // Free allocated map tile fog state UnloadRenderTexture(fogOfWar); // Unload render texture From e71633a0be295c91ff8a039e67deee6fef590237 Mon Sep 17 00:00:00 2001 From: Maicon Santana Date: Mon, 23 Mar 2026 13:05:23 +0000 Subject: [PATCH 005/185] Set textureWrapRepeat to avoid issue on web version (#5684) --- examples/models/models_yaw_pitch_roll.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c index c19aafdcd..af0f06daf 100644 --- a/examples/models/models_yaw_pitch_roll.c +++ b/examples/models/models_yaw_pitch_roll.c @@ -41,6 +41,9 @@ int main(void) Model model = LoadModel("resources/models/obj/plane.obj"); // Load model Texture2D texture = LoadTexture("resources/models/obj/plane_diffuse.png"); // Load model texture + + SetTextureWrap(texture, TEXTURE_WRAP_REPEAT); // Force Repeat to avoid issue on Web version + model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture float pitch = 0.0f; From 6cf71f565ca987ce465adfd7c01d3fa94250f3b3 Mon Sep 17 00:00:00 2001 From: Charlie Tonneslan Date: Mon, 23 Mar 2026 12:17:50 -0400 Subject: [PATCH 006/185] Fix typo: dependant -> dependent in rlgl.h and rexm.c (#5685) 5 instances in src/rlgl.h comments and 1 in tools/rexm/rexm.c. Skipped vendored raygui.h files in examples/. --- src/rlgl.h | 10 +++++----- tools/rexm/rexm.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 13c037132..ce10b2f64 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -880,7 +880,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #elif defined(GRAPHICS_API_OPENGL_ES2) // NOTE: OpenGL ES 2.0 can be enabled on Desktop platforms, // in that case, functions are loaded from a custom glad for OpenGL ES 2.0 - // TODO: OpenGL ES 2.0 support shouldn't be platform-dependant, neither require GLAD + // TODO: OpenGL ES 2.0 support shouldn't be platform-dependent, neither require GLAD #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL) #define GLAD_GLES2_IMPLEMENTATION #include "external/glad_gles2.h" @@ -893,7 +893,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad // It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi // provided headers (despite being defined in official Khronos GLES2 headers) - // TODO: Avoid raylib platform-dependant code on rlgl, it should be a completely portable library + // TODO: Avoid raylib platform-dependent code on rlgl, it should be a completely portable library #if defined(PLATFORM_DRM) typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); @@ -1392,7 +1392,7 @@ void rlFrustum(double left, double right, double bottom, double top, double znea void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar) { // NOTE: If left-right and top-botton values are equal it could create a division by zero, - // response to it is platform/compiler dependant + // response to it is platform/compiler dependent Matrix matOrtho = { 0 }; float rl = (float)(right - left); @@ -1509,7 +1509,7 @@ void rlBegin(int mode) // Finish vertex providing void rlEnd(void) { - // NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values, + // NOTE: Depth increment is dependent on rlOrtho(): z-near and z-far values, // as well as depth buffer bit-depth (16bit or 24bit or 32bit) // Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits) RLGL.currentBatch->currentDepth += (1.0f/20000.0f); @@ -1902,7 +1902,7 @@ void rlBindFramebuffer(unsigned int target, unsigned int framebuffer) void rlActiveDrawBuffers(int count) { #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3)) - // NOTE: Maximum number of draw buffers supported is implementation dependant, + // NOTE: Maximum number of draw buffers supported is implementation dependent, // it can be queried with glGet*() but it must be at least 8 //GLint maxDrawBuffers = 0; //glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index 49d4dce9a..e4881b633 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -1669,7 +1669,7 @@ int main(int argc, char *argv[]) FileRemove(TextFormat("%s/%s/%s.original.c", exBasePath, exCategory, exName)); // STEP 3: Run example with required arguments - // NOTE: Not easy to retrieve process return value from system(), it's platform dependant + // NOTE: Not easy to retrieve process return value from system(), it's platform dependent ChangeDirectory(TextFormat("%s/%s", exBasePath, exCategory)); #if defined(_WIN32) From 0f1e14a600df058d807ed5e26cddf2529674073d Mon Sep 17 00:00:00 2001 From: Charlie Tonneslan Date: Mon, 23 Mar 2026 12:58:45 -0400 Subject: [PATCH 007/185] Fix typo: dependant -> dependent in rlgl.h and rexm.c (#5685) 5 instances in src/rlgl.h comments and 1 in tools/rexm/rexm.c. Skipped vendored raygui.h files in examples/. From 52d2158f498dabee0f866a62bee88efd2d9fb77d Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 23 Mar 2026 18:28:09 +0100 Subject: [PATCH 008/185] Update ROADMAP.md --- ROADMAP.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ROADMAP.md b/ROADMAP.md index 10754e52b..91d2299c3 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -23,6 +23,7 @@ _Current version of raylib is complete and functional but there is always room f - [ ] `rlsw`: Software renderer optimizations: mipmaps, platform-specific SIMD - [ ] `rtextures`: Consider moving N-patch system to separate example - [ ] `rtextures`: Review blending modes system, provide more options or better samples + - [ ] `rtext`: Investigate the recently opened [`Slug`](https://sluglibrary.com/) font rendering algorithm - [ ] `raudio`: Support microphone input, basic API to read microphone - [ ] `rltexgpu`: Improve compressed textures support, loading and saving, improve KTX 2.0 - [ ] `rlobj`: Create OBJ loader, supporting material file separately (low priority) From cb05ef7f03673da0b54f0ef49b9ba4a0bbebf37b Mon Sep 17 00:00:00 2001 From: Krzysztof Szenk Date: Mon, 23 Mar 2026 22:22:21 +0100 Subject: [PATCH 009/185] [rcore_desktop_rgfw] [emscripten] fix typo (#5687) * RGFW also requires RGBA8 images as window icons, as raylib already reports in raylib.h * LibraryConfigurations.cmake: exchanged MATCHES -> STREQUAL in platform choosing if-statements * WebRGFW: remapping mouse/touch position to canvas pixel coordinates * fix 'typo' * has to be done like that because of += in case of captured mouse * [rcore_desktop_rgfw] [emscripten] fix typo --- src/platforms/rcore_desktop_rgfw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index fb1fc6cf6..51a73e1ad 100755 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -1469,13 +1469,13 @@ void PollInputEvents(void) #endif if (RGFW_window_isCaptured(platform.window)) { - CORE.Input.Mouse.currentPosition.x += event_x; - CORE.Input.Mouse.currentPosition.y += event_y; + CORE.Input.Mouse.currentPosition.x += mouseX; + CORE.Input.Mouse.currentPosition.y += mouseY; } else { - CORE.Input.Mouse.currentPosition.x = event_x; - CORE.Input.Mouse.currentPosition.y = event_y; + CORE.Input.Mouse.currentPosition.x = mouseX; + CORE.Input.Mouse.currentPosition.y = mouseY; } CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; From 5dd4036ed0065e8e89a1ee84d89d3a18bb7a3d59 Mon Sep 17 00:00:00 2001 From: Jordi Santonja <77529699+JordSant@users.noreply.github.com> Date: Tue, 24 Mar 2026 08:20:37 +0100 Subject: [PATCH 010/185] Fix UI Cellular Automata (#5688) --- examples/textures/textures_cellular_automata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/textures/textures_cellular_automata.c b/examples/textures/textures_cellular_automata.c index 802de3611..affeeda93 100644 --- a/examples/textures/textures_cellular_automata.c +++ b/examples/textures/textures_cellular_automata.c @@ -165,7 +165,7 @@ int main(void) // If the mouse is on this preset, highlight it if (mouseInCell == i + 8) - DrawRectangleLinesEx((Rectangle) { 2 + (presetsSizeX + 2.0f)*((float)i/2), + DrawRectangleLinesEx((Rectangle) { 2 + (presetsSizeX + 2.0f)*(i/2), (presetsSizeY + 2.0f)*(i%2), presetsSizeX + 4.0f, presetsSizeY + 4.0f }, 3, RED); } From 0f0983c06565b3a7ec7c2248a8361037cf3e4d24 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 25 Mar 2026 16:51:02 +0100 Subject: [PATCH 011/185] Remove trailing spaces --- examples/audio/audio_raw_stream.c | 6 +- examples/core/core_highdpi_testbed.c | 2 +- examples/core/core_keyboard_testbed.c | 34 +++++------ .../models/models_animation_blend_custom.c | 42 +++++++------- examples/models/models_animation_blending.c | 28 ++++----- examples/models/models_animation_timing.c | 10 ++-- examples/models/models_basic_voxel.c | 10 ++-- examples/models/models_skybox_rendering.c | 2 +- examples/models/models_yaw_pitch_roll.c | 2 +- examples/shaders/shaders_cel_shading.c | 16 ++--- examples/shaders/shaders_deferred_rendering.c | 4 +- examples/shaders/shaders_game_of_life.c | 18 +++--- examples/shapes/shapes_ball_physics.c | 12 ++-- examples/shapes/shapes_easings_testbed.c | 2 +- examples/shapes/shapes_hilbert_curve.c | 30 +++++----- examples/shapes/shapes_penrose_tile.c | 30 +++++----- examples/text/text_strings_management.c | 28 ++++----- examples/textures/textures_clipboard_image.c | 12 ++-- examples/textures/textures_magnifying_glass.c | 12 ++-- examples/textures/textures_screen_buffer.c | 8 +-- src/external/rlsw.h | 58 +++++++++---------- src/rcore.c | 2 +- src/rtext.c | 1 - 23 files changed, 184 insertions(+), 185 deletions(-) diff --git a/examples/audio/audio_raw_stream.c b/examples/audio/audio_raw_stream.c index 64c9b5a50..1978511ed 100644 --- a/examples/audio/audio_raw_stream.c +++ b/examples/audio/audio_raw_stream.c @@ -110,16 +110,16 @@ int main(void) //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); - + DrawText(TextFormat("sine frequency: %i", sineFrequency), screenWidth - 220, 10, 20, RED); DrawText(TextFormat("pan: %.2f", pan), screenWidth - 220, 30, 20, RED); DrawText("Up/down to change frequency", 10, 10, 20, DARKGRAY); DrawText("Left/right to pan", 10, 30, 20, DARKGRAY); - + int windowStart = (GetTime() - sineStartTime)*SAMPLE_RATE; int windowSize = 0.1f*SAMPLE_RATE; int wavelength = SAMPLE_RATE/sineFrequency; - + // Draw a sine wave with the same frequency as the one being sent to the audio stream for (int i = 0; i < screenWidth; i++) { diff --git a/examples/core/core_highdpi_testbed.c b/examples/core/core_highdpi_testbed.c index 601d12e8c..246ef4b42 100644 --- a/examples/core/core_highdpi_testbed.c +++ b/examples/core/core_highdpi_testbed.c @@ -73,7 +73,7 @@ int main(void) } // Draw UI info - DrawText(TextFormat("CURRENT MONITOR: %i/%i (%ix%i)", currentMonitor + 1, GetMonitorCount(), + DrawText(TextFormat("CURRENT MONITOR: %i/%i (%ix%i)", currentMonitor + 1, GetMonitorCount(), GetMonitorWidth(currentMonitor), GetMonitorHeight(currentMonitor)), 50, 50, 20, DARKGRAY); DrawText(TextFormat("WINDOW POSITION: %ix%i", (int)windowPos.x, (int)windowPos.y), 50, 90, 20, DARKGRAY); DrawText(TextFormat("SCREEN SIZE: %ix%i", GetScreenWidth(), GetScreenHeight()), 50, 130, 20, DARKGRAY); diff --git a/examples/core/core_keyboard_testbed.c b/examples/core/core_keyboard_testbed.c index 2ea5c361a..f65260b59 100644 --- a/examples/core/core_keyboard_testbed.c +++ b/examples/core/core_keyboard_testbed.c @@ -4,7 +4,7 @@ * * Example complexity rating: [★★☆☆] 2/4 * -* NOTE: raylib defined keys refer to ENG-US Keyboard layout, +* NOTE: raylib defined keys refer to ENG-US Keyboard layout, * mapping to other layouts is up to the user * * Example originally created with raylib 5.6, last time updated with raylib 5.6 @@ -43,20 +43,20 @@ int main(void) int line01KeyWidths[15] = { 0 }; for (int i = 0; i < 15; i++) line01KeyWidths[i] = 45; line01KeyWidths[13] = 62; // PRINTSCREEN - int line01Keys[15] = { - KEY_ESCAPE, 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_PAUSE + int line01Keys[15] = { + KEY_ESCAPE, 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_PAUSE }; - + // Keyboard line 02 int line02KeyWidths[15] = { 0 }; for (int i = 0; i < 15; i++) line02KeyWidths[i] = 45; line02KeyWidths[0] = 25; // GRAVE line02KeyWidths[13] = 82; // BACKSPACE - int line02Keys[15] = { - KEY_GRAVE, KEY_ONE, KEY_TWO, KEY_THREE, KEY_FOUR, - KEY_FIVE, KEY_SIX, KEY_SEVEN, KEY_EIGHT, KEY_NINE, + int line02Keys[15] = { + KEY_GRAVE, KEY_ONE, KEY_TWO, KEY_THREE, KEY_FOUR, + KEY_FIVE, KEY_SIX, KEY_SEVEN, KEY_EIGHT, KEY_NINE, KEY_ZERO, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_DELETE }; // Keyboard line 03 @@ -103,7 +103,7 @@ int main(void) KEY_SPACE, KEY_RIGHT_ALT, 162, KEY_NULL, KEY_RIGHT_CONTROL, KEY_LEFT, KEY_DOWN, KEY_RIGHT }; - + Vector2 keyboardOffset = { 26, 80 }; SetTargetFPS(60); @@ -128,23 +128,23 @@ int main(void) ClearBackground(RAYWHITE); DrawText("KEYBOARD LAYOUT: ENG-US", 26, 38, 20, LIGHTGRAY); - + // Keyboard line 01 - 15 keys // ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, IMP, CLOSE - for (int i = 0, recOffsetX = 0; i < 15; i++) + for (int i = 0, recOffsetX = 0; i < 15; i++) { GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y, (float)line01KeyWidths[i], 30.0f }, line01Keys[i]); recOffsetX += line01KeyWidths[i] + KEY_REC_SPACING; } - + // Keyboard line 02 - 15 keys // `, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, -, =, BACKSPACE, DEL - for (int i = 0, recOffsetX = 0; i < 15; i++) + for (int i = 0, recOffsetX = 0; i < 15; i++) { GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y + 30 + KEY_REC_SPACING, (float)line02KeyWidths[i], 38.0f }, line02Keys[i]); recOffsetX += line02KeyWidths[i] + KEY_REC_SPACING; } - + // Keyboard line 03 - 15 keys // TAB, Q, W, E, R, T, Y, U, I, O, P, [, ], \, INS for (int i = 0, recOffsetX = 0; i < 15; i++) @@ -324,8 +324,8 @@ static void GuiKeyboardKey(Rectangle bounds, int key) DrawText(GetKeyText(key), (int)(bounds.x + 4), (int)(bounds.y + 4), 10, DARKGRAY); } } - - if (CheckCollisionPointRec(GetMousePosition(), bounds)) + + if (CheckCollisionPointRec(GetMousePosition(), bounds)) { DrawRectangleRec(bounds, Fade(RED, 0.2f)); DrawRectangleLinesEx(bounds, 3.0f, RED); diff --git a/examples/models/models_animation_blend_custom.c b/examples/models/models_animation_blend_custom.c index 8262f6ac2..018012e9b 100644 --- a/examples/models/models_animation_blend_custom.c +++ b/examples/models/models_animation_blend_custom.c @@ -43,7 +43,7 @@ // Module Functions Declaration //------------------------------------------------------------------------------------ static bool IsUpperBodyBone(const char *boneName); -static void UpdateModelAnimationBones(Model *model, ModelAnimation *anim1, int frame1, +static void UpdateModelAnimationBones(Model *model, ModelAnimation *anim1, int frame1, ModelAnimation *anim2, int frame2, float blend, bool upperBodyBlend); //------------------------------------------------------------------------------------ @@ -86,7 +86,7 @@ int main(void) int animIndex1 = 3; // Attack animation (index 3) int animCurrentFrame0 = 0; int animCurrentFrame1 = 0; - + // Validate indices if (animIndex0 >= animCount) animIndex0 = 0; if (animIndex1 >= animCount) animIndex1 = (animCount > 1) ? 1 : 0; @@ -109,7 +109,7 @@ int main(void) // Update animation frames ModelAnimation anim0 = anims[animIndex0]; ModelAnimation anim1 = anims[animIndex1]; - + animCurrentFrame0 = (animCurrentFrame0 + 1)%anim0.keyframeCount; animCurrentFrame1 = (animCurrentFrame1 + 1)%anim1.keyframeCount; @@ -117,11 +117,11 @@ int main(void) // When upperBodyBlend is ON: upper body = attack (1.0), lower body = walk (0.0) // When upperBodyBlend is OFF: uniform blend at 0.5 (50% walk, 50% attack) float blendFactor = (upperBodyBlend? 1.0f : 0.5f); - UpdateModelAnimationBones(&model, &anim0, animCurrentFrame0, + UpdateModelAnimationBones(&model, &anim0, animCurrentFrame0, &anim1, animCurrentFrame1, blendFactor, upperBodyBlend); // raylib provided animation blending function - //UpdateModelAnimationEx(model, anim0, (float)animCurrentFrame0, + //UpdateModelAnimationEx(model, anim0, (float)animCurrentFrame0, // anim1, (float)animCurrentFrame1, blendFactor); //---------------------------------------------------------------------------------- @@ -142,8 +142,8 @@ int main(void) // Draw UI DrawText(TextFormat("ANIM 0: %s", anim0.name), 10, 10, 20, GRAY); DrawText(TextFormat("ANIM 1: %s", anim1.name), 10, 40, 20, GRAY); - DrawText(TextFormat("[SPACE] Toggle blending mode: %s", - upperBodyBlend? "Upper/Lower Body Blending" : "Uniform Blending"), + DrawText(TextFormat("[SPACE] Toggle blending mode: %s", + upperBodyBlend? "Upper/Lower Body Blending" : "Uniform Blending"), 10, GetScreenHeight() - 30, 20, DARKGRAY); EndDrawing(); @@ -180,7 +180,7 @@ static bool IsUpperBodyBone(const char *boneName) { return true; } - + // Check if bone name contains upper body keywords if (strstr(boneName, "spine") != NULL || strstr(boneName, "chest") != NULL || strstr(boneName, "neck") != NULL || strstr(boneName, "head") != NULL || @@ -189,12 +189,12 @@ static bool IsUpperBodyBone(const char *boneName) { return true; } - + return false; } // Blend two animations per-bone with selective upper/lower body blending -static void UpdateModelAnimationBones(Model *model, ModelAnimation *anim0, int frame0, +static void UpdateModelAnimationBones(Model *model, ModelAnimation *anim0, int frame0, ModelAnimation *anim1, int frame1, float blend, bool upperBodyBlend) { // Validate inputs @@ -204,59 +204,59 @@ static void UpdateModelAnimationBones(Model *model, ModelAnimation *anim0, int f { // Clamp blend factor to [0, 1] blend = fminf(1.0f, fmaxf(0.0f, blend)); - + // Ensure frame indices are valid if (frame0 >= anim0->keyframeCount) frame0 = anim0->keyframeCount - 1; if (frame1 >= anim1->keyframeCount) frame1 = anim1->keyframeCount - 1; if (frame0 < 0) frame0 = 0; if (frame1 < 0) frame1 = 0; - + // Get bone count (use minimum of all to be safe) int boneCount = model->skeleton.boneCount; if (anim0->boneCount < boneCount) boneCount = anim0->boneCount; if (anim1->boneCount < boneCount) boneCount = anim1->boneCount; - + // Blend each bone for (int boneIndex = 0; boneIndex < boneCount; boneIndex++) { // Determine blend factor for this bone float boneBlendFactor = blend; - + // If upper body blending is enabled, use different blend factors for upper vs lower body if (upperBodyBlend) { const char *boneName = model->skeleton.bones[boneIndex].name; bool isUpperBody = IsUpperBodyBone(boneName); - + // Upper body: use anim1 (attack), Lower body: use anim0 (walk) // blend = 0.0 means full anim0 (walk), 1.0 means full anim1 (attack) if (isUpperBody) boneBlendFactor = blend; // Upper body: blend towards anim1 (attack) else boneBlendFactor = 1.0f - blend; // Lower body: blend towards anim0 (walk) - invert the blend } - + // Get transforms from both animations Transform *bindTransform = &model->skeleton.bindPose[boneIndex]; Transform *animTransform0 = &anim0->keyframePoses[frame0][boneIndex]; Transform *animTransform1 = &anim1->keyframePoses[frame1][boneIndex]; - + // Blend the transforms Transform blended = { 0 }; blended.translation = Vector3Lerp(animTransform0->translation, animTransform1->translation, boneBlendFactor); blended.rotation = QuaternionSlerp(animTransform0->rotation, animTransform1->rotation, boneBlendFactor); blended.scale = Vector3Lerp(animTransform0->scale, animTransform1->scale, boneBlendFactor); - + // Convert bind pose to matrix Matrix bindMatrix = MatrixMultiply(MatrixMultiply( MatrixScale(bindTransform->scale.x, bindTransform->scale.y, bindTransform->scale.z), QuaternionToMatrix(bindTransform->rotation)), MatrixTranslate(bindTransform->translation.x, bindTransform->translation.y, bindTransform->translation.z)); - + // Convert blended transform to matrix Matrix blendedMatrix = MatrixMultiply(MatrixMultiply( MatrixScale(blended.scale.x, blended.scale.y, blended.scale.z), QuaternionToMatrix(blended.rotation)), MatrixTranslate(blended.translation.x, blended.translation.y, blended.translation.z)); - + // Calculate final bone matrix (similar to UpdateModelAnimationBones) model->boneMatrices[boneIndex] = MatrixMultiply(MatrixInvert(bindMatrix), blendedMatrix); } @@ -276,7 +276,7 @@ static void UpdateModelAnimationBones(Model *model, ModelAnimation *anim0, int f bool bufferUpdateRequired = false; // Flag to check when anim vertex information is updated // Skip if missing bone data or missing anim buffers initialization - if ((mesh.boneWeights == NULL) || (mesh.boneIndices == NULL) || + if ((mesh.boneWeights == NULL) || (mesh.boneIndices == NULL) || (mesh.animVertices == NULL) || (mesh.animNormals == NULL)) continue; for (int vCounter = 0; vCounter < vertexValuesCount; vCounter += 3) diff --git a/examples/models/models_animation_blending.c b/examples/models/models_animation_blending.c index e79067c3d..63eba61cd 100644 --- a/examples/models/models_animation_blending.c +++ b/examples/models/models_animation_blending.c @@ -3,7 +3,7 @@ * raylib [models] example - animation blending * * Example complexity rating: [★★★★] 4/4 -* +* * Example originally created with raylib 5.5, last time updated with raylib 6.0 * * Example contributed by Kirandeep (@Kirandeep-Singh-Khehra) and reviewed by Ramon Santamaria (@raysan5) @@ -57,7 +57,7 @@ int main(void) // WARNING: It requires SUPPORT_GPU_SKINNING enabled on raylib (disabled by default) Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION), TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION)); - + // Assign skinning shader to all materials shaders //for (int i = 0; i < model.materialCount; i++) model.materials[i].shader = skinningShader; @@ -105,7 +105,7 @@ int main(void) // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera, CAMERA_ORBITAL); - + if (IsKeyPressed(KEY_P)) animPause = !animPause; if (!animPause) @@ -127,7 +127,7 @@ int main(void) } // Set animation transition - animTransition = true; + animTransition = true; animBlendTimeCounter = 0.0f; animBlendFactor = 0.0f; } @@ -182,7 +182,7 @@ int main(void) animCurrentFrame0 += animFrameSpeed0; if (animCurrentFrame0 >= anims[animIndex0].keyframeCount) animCurrentFrame0 = 0.0f; UpdateModelAnimation(model, anims[animIndex0], animCurrentFrame0); - //UpdateModelAnimationEx(model, anims[animIndex0], animCurrentFrame0, + //UpdateModelAnimationEx(model, anims[animIndex0], animCurrentFrame0, // anims[animIndex1], animCurrentFrame1, 0.0f); // Same as above, first animation frame blend } else if (currentAnimPlaying == 1) @@ -191,7 +191,7 @@ int main(void) animCurrentFrame1 += animFrameSpeed1; if (animCurrentFrame1 >= anims[animIndex1].keyframeCount) animCurrentFrame1 = 0.0f; UpdateModelAnimation(model, anims[animIndex1], animCurrentFrame1); - //UpdateModelAnimationEx(model, anims[animIndex0], animCurrentFrame0, + //UpdateModelAnimationEx(model, anims[animIndex0], animCurrentFrame0, // anims[animIndex1], animCurrentFrame1, 1.0f); // Same as above, second animation frame blend } } @@ -213,7 +213,7 @@ int main(void) DrawModel(model, position, 1.0f, WHITE); // Draw animated model DrawGrid(10, 1.0f); - + EndMode3D(); if (animTransition) DrawText("ANIM TRANSITION BLENDING!", 170, 50, 30, BLUE); @@ -221,18 +221,18 @@ int main(void) // Draw UI elements //--------------------------------------------------------------------------------------------- if (dropdownEditMode0) GuiDisable(); - GuiSlider((Rectangle){ 10, 38, 160, 12 }, + GuiSlider((Rectangle){ 10, 38, 160, 12 }, NULL, TextFormat("x%.1f", animFrameSpeed0), &animFrameSpeed0, 0.1f, 2.0f); GuiEnable(); if (dropdownEditMode1) GuiDisable(); - GuiSlider((Rectangle){ GetScreenWidth() - 170.0f, 38, 160, 12 }, + GuiSlider((Rectangle){ GetScreenWidth() - 170.0f, 38, 160, 12 }, TextFormat("%.1fx", animFrameSpeed1), NULL, &animFrameSpeed1, 0.1f, 2.0f); GuiEnable(); // Draw animation selectors for blending transition - // NOTE: Transition does not start until requested + // NOTE: Transition does not start until requested GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 1); - if (GuiDropdownBox((Rectangle){ 10, 10, 160, 24 }, TextJoin(animNames, animCount, ";"), + if (GuiDropdownBox((Rectangle){ 10, 10, 160, 24 }, TextJoin(animNames, animCount, ";"), &animIndex0, dropdownEditMode0)) dropdownEditMode0 = !dropdownEditMode0; // Blending process progress bar @@ -249,7 +249,7 @@ int main(void) TextFormat("FRAME: %.2f / %i", animFrameProgress0, anims[animIndex0].keyframeCount), &animFrameProgress0, 0.0f, (float)anims[animIndex0].keyframeCount); for (int i = 0; i < anims[animIndex0].keyframeCount; i++) - DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex0].keyframeCount)*(float)i), + DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex0].keyframeCount)*(float)i), GetScreenHeight() - 60, 1, 20, BLUE); // Draw playing timeline with keyframes for anim1[] @@ -257,7 +257,7 @@ int main(void) TextFormat("FRAME: %.2f / %i", animFrameProgress1, anims[animIndex1].keyframeCount), &animFrameProgress1, 0.0f, (float)anims[animIndex1].keyframeCount); for (int i = 0; i < anims[animIndex1].keyframeCount; i++) - DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex1].keyframeCount)*(float)i), + DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex1].keyframeCount)*(float)i), GetScreenHeight() - 30, 1, 20, BLUE); //--------------------------------------------------------------------------------------------- @@ -270,7 +270,7 @@ int main(void) UnloadModelAnimations(anims, animCount); // Unload model animation UnloadModel(model); // Unload model and meshes/material UnloadShader(skinningShader); // Unload GPU skinning shader - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/models/models_animation_timing.c b/examples/models/models_animation_timing.c index a302322fe..b88deb49d 100644 --- a/examples/models/models_animation_timing.c +++ b/examples/models/models_animation_timing.c @@ -94,26 +94,26 @@ int main(void) BeginMode3D(camera); DrawModel(model, position, 1.0f, WHITE); - + DrawGrid(10, 1.0f); - + EndMode3D(); // Draw UI, select anim and playing speed GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 1); - if (GuiDropdownBox((Rectangle){ 10, 10, 140, 24 }, TextJoin(animNames, animCount, ";"), + if (GuiDropdownBox((Rectangle){ 10, 10, 140, 24 }, TextJoin(animNames, animCount, ";"), &animIndex, dropdownEditMode)) dropdownEditMode = !dropdownEditMode; GuiSlider((Rectangle){ 260, 10, 500, 24 }, "FRAME SPEED: ", TextFormat("x%.1f", animFrameSpeed), &animFrameSpeed, 0.1f, 2.0f); // Draw playing timeline with keyframes - GuiLabel((Rectangle){ 10, GetScreenHeight() - 64.0f, GetScreenWidth() - 20.0f, 24 }, + GuiLabel((Rectangle){ 10, GetScreenHeight() - 64.0f, GetScreenWidth() - 20.0f, 24 }, TextFormat("CURRENT FRAME: %.2f / %i", animFrameProgress, anims[animIndex].keyframeCount)); GuiProgressBar((Rectangle){ 10, GetScreenHeight() - 40.0f, GetScreenWidth() - 20.0f, 24 }, NULL, NULL, &animFrameProgress, 0.0f, (float)anims[animIndex].keyframeCount); for (int i = 0; i < anims[animIndex].keyframeCount; i++) - DrawRectangle(10 + (int)(((float)(GetScreenWidth() - 20)/(float)anims[animIndex].keyframeCount)*(float)i), + DrawRectangle(10 + (int)(((float)(GetScreenWidth() - 20)/(float)anims[animIndex].keyframeCount)*(float)i), GetScreenHeight() - 40, 1, 24, BLUE); EndDrawing(); diff --git a/examples/models/models_basic_voxel.c b/examples/models/models_basic_voxel.c index 2e2756f2b..127a7e989 100644 --- a/examples/models/models_basic_voxel.c +++ b/examples/models/models_basic_voxel.c @@ -60,7 +60,7 @@ int main(void) } } } - + SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -109,7 +109,7 @@ int main(void) } } } - + // Remove the closest voxel if one was hit if (voxelFound) { @@ -145,9 +145,9 @@ int main(void) } } } - + EndMode3D(); - + // Draw reference point for raycasting to delete blocks DrawCircle(GetScreenWidth()/2, GetScreenHeight()/2, 4, RED); @@ -161,7 +161,7 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- UnloadModel(cubeModel); - + CloseWindow(); //-------------------------------------------------------------------------------------- diff --git a/examples/models/models_skybox_rendering.c b/examples/models/models_skybox_rendering.c index 9359e03dc..c8d10dc25 100644 --- a/examples/models/models_skybox_rendering.c +++ b/examples/models/models_skybox_rendering.c @@ -92,7 +92,7 @@ int main(void) } else { - // TODO: WARNING: On PLATFORM_WEB it requires a big amount of memory to process input image + // TODO: WARNING: On PLATFORM_WEB it requires a big amount of memory to process input image // and generate the required cubemap image to be passed to rlLoadTextureCubemap() Image image = LoadImage("resources/skybox.png"); skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(image, CUBEMAP_LAYOUT_AUTO_DETECT); diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c index af0f06daf..76074cca4 100644 --- a/examples/models/models_yaw_pitch_roll.c +++ b/examples/models/models_yaw_pitch_roll.c @@ -41,7 +41,7 @@ int main(void) Model model = LoadModel("resources/models/obj/plane.obj"); // Load model Texture2D texture = LoadTexture("resources/models/obj/plane_diffuse.png"); // Load model texture - + SetTextureWrap(texture, TEXTURE_WRAP_REPEAT); // Force Repeat to avoid issue on Web version model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture diff --git a/examples/shaders/shaders_cel_shading.c b/examples/shaders/shaders_cel_shading.c index 133b8db9e..beda73bca 100644 --- a/examples/shaders/shaders_cel_shading.c +++ b/examples/shaders/shaders_cel_shading.c @@ -52,7 +52,7 @@ int main(void) camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; camera.fovy = 45.0f; camera.projection = CAMERA_PERSPECTIVE; - + // Load model Model model = LoadModel("resources/models/old_car_new.glb"); @@ -61,7 +61,7 @@ int main(void) TextFormat("resources/shaders/glsl%i/cel.vs", GLSL_VERSION), TextFormat("resources/shaders/glsl%i/cel.fs", GLSL_VERSION)); celShader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(celShader, "viewPos"); - + // Apply cel shader to model, keep copy of default shader Shader defaultShader = model.materials[0].shader; model.materials[0].shader = celShader; @@ -134,16 +134,16 @@ int main(void) // Outline pass: cull front faces, draw extruded back faces as silhouette float thickness = 0.005f; SetShaderValue(outlineShader, outlineThicknessLoc, &thickness, SHADER_UNIFORM_FLOAT); - + rlSetCullFace(RL_CULL_FACE_FRONT); - + model.materials[0].shader = outlineShader; - + DrawModel(model, Vector3Zero(), 0.75f, WHITE); - + if (celEnabled) model.materials[0].shader = celShader; // Apply cel shader to model else model.materials[0].shader = defaultShader; // Apply default shader to model - + rlSetCullFace(RL_CULL_FACE_BACK); } @@ -167,7 +167,7 @@ int main(void) UnloadModel(model); UnloadShader(celShader); UnloadShader(outlineShader); - + CloseWindow(); //-------------------------------------------------------------------------------------- diff --git a/examples/shaders/shaders_deferred_rendering.c b/examples/shaders/shaders_deferred_rendering.c index 4b03b69a4..ea27f9b8b 100644 --- a/examples/shaders/shaders_deferred_rendering.c +++ b/examples/shaders/shaders_deferred_rendering.c @@ -210,7 +210,7 @@ int main(void) rlClearColor(0, 0, 0, 0); rlClearScreenBuffers(); // Clear color and depth buffer rlDisableColorBlend(); - + BeginMode3D(camera); // NOTE: We have to use rlEnableShader here. `BeginShaderMode` or thus `rlSetShader` // will not work, as they won't immediately load the shader program @@ -226,7 +226,7 @@ int main(void) } rlDisableShader(); EndMode3D(); - + rlEnableColorBlend(); // Go back to the default framebufferId (0) and draw our deferred shading diff --git a/examples/shaders/shaders_game_of_life.c b/examples/shaders/shaders_game_of_life.c index 251095e2b..a09d889ac 100644 --- a/examples/shaders/shaders_game_of_life.c +++ b/examples/shaders/shaders_game_of_life.c @@ -59,7 +59,7 @@ int main(void) //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; - + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - game of life"); const int menuWidth = 100; @@ -81,7 +81,7 @@ int main(void) { "Puffer train", { 0.1f, 0.5f } }, { "Glider Gun", { 0.2f, 0.2f } }, { "Breeder", { 0.1f, 0.5f } }, { "Random", { 0.5f, 0.5f } } }; - + const int numberOfPresets = sizeof(presetPatterns)/sizeof(presetPatterns[0]); int zoom = 1; @@ -90,7 +90,7 @@ int main(void) int framesPerStep = 1; int frame = 0; - int preset = -1; // No button pressed for preset + int preset = -1; // No button pressed for preset int mode = MODE_RUN; // Starting mode: running bool buttonZoomIn = false; // Button states: false not pressed bool buttonZomOut = false; @@ -185,7 +185,7 @@ int main(void) EndTextureMode(); imageToDraw = (Image*)RL_MALLOC(sizeof(Image)); *imageToDraw = LoadImageFromTexture(worldOnScreen.texture); - + UnloadRenderTexture(worldOnScreen); } @@ -199,9 +199,9 @@ int main(void) if (mouseY >= sizeInWorldY) mouseY = sizeInWorldY - 1; if (firstColor == -1) firstColor = (GetImageColor(*imageToDraw, mouseX, mouseY).r < 5)? 0 : 1; const int prevColor = (GetImageColor(*imageToDraw, mouseX, mouseY).r < 5)? 0 : 1; - + ImageDrawPixel(imageToDraw, mouseX, mouseY, (firstColor) ? BLACK : RAYWHITE); - + if (prevColor != firstColor) UpdateTextureRec(currentWorld->texture, (Rectangle){ floorf(offsetX), floorf(offsetY), (float)(sizeInWorldX), (float)(sizeInWorldY) }, imageToDraw->data); } else firstColor = -1; @@ -228,7 +228,7 @@ int main(void) BeginTextureMode(*currentWorld); ClearBackground(RAYWHITE); EndTextureMode(); - + UpdateTextureRec(currentWorld->texture, (Rectangle){ worldWidth*presetPatterns[preset].position.x - pattern.width/2.0f, worldHeight*presetPatterns[preset].position.y - pattern.height/2.0f, (float)(pattern.width), (float)(pattern.height) }, pattern.data); @@ -256,7 +256,7 @@ int main(void) } UnloadImage(pattern); - + mode = MODE_PAUSE; offsetX = worldWidth*presetPatterns[preset].position.x - (float)windowWidth/zoom/2.0f; offsetY = worldHeight*presetPatterns[preset].position.y - (float)windowHeight/zoom/2.0f; @@ -293,7 +293,7 @@ int main(void) // Draw to screen //---------------------------------------------------------------------------------- BeginDrawing(); - + DrawTexturePro(currentWorld->texture, textureSourceToScreen, textureOnScreen, (Vector2){ 0, 0 }, 0.0f, WHITE); DrawLine(windowWidth, 0, windowWidth, screenHeight, (Color){ 218, 218, 218, 255 }); diff --git a/examples/shapes/shapes_ball_physics.c b/examples/shapes/shapes_ball_physics.c index 9c18ab66e..2a4cc8f18 100644 --- a/examples/shapes/shapes_ball_physics.c +++ b/examples/shapes/shapes_ball_physics.c @@ -31,7 +31,7 @@ typedef struct Ball { Vector2 speed; Vector2 prevPosition; float radius; - float friction; + float friction; float elasticity; Color color; bool grabbed; @@ -62,7 +62,7 @@ int main(void) .color = BLUE, .grabbed = false }; - + int ballCount = 1; Ball *grabbedBall = NULL; // A pointer to the current ball that is grabbed Vector2 pressOffset = { 0 }; // Mouse press offset relative to the ball that grabbedd @@ -157,10 +157,10 @@ int main(void) { ball->position.x = screenWidth - ball->radius; // Ball repositioning ball->speed.x = -ball->speed.x*ball->elasticity; // Elasticity makes the ball lose 10% of its velocity on hit - } + } // Does the ball hit the screen left boundary? else if ((ball->position.x - ball->radius) <= 0) - { + { ball->position.x = ball->radius; ball->speed.x = -ball->speed.x*ball->elasticity; } @@ -170,9 +170,9 @@ int main(void) { ball->position.y = screenHeight - ball->radius; ball->speed.y = -ball->speed.y*ball->elasticity; - } + } else if ((ball->position.y - ball->radius) <= 0) - { + { ball->position.y = ball->radius; ball->speed.y = -ball->speed.y*ball->elasticity; } diff --git a/examples/shapes/shapes_easings_testbed.c b/examples/shapes/shapes_easings_testbed.c index 1c9fcf741..6912422ea 100644 --- a/examples/shapes/shapes_easings_testbed.c +++ b/examples/shapes/shapes_easings_testbed.c @@ -72,7 +72,7 @@ typedef struct EasingFuncs { // Module Functions Declaration //------------------------------------------------------------------------------------ // Function used when "no easing" is selected for any axis -static float NoEase(float t, float b, float c, float d); +static float NoEase(float t, float b, float c, float d); //------------------------------------------------------------------------------------ // Global Variables Definition diff --git a/examples/shapes/shapes_hilbert_curve.c b/examples/shapes/shapes_hilbert_curve.c index 759fe93fd..64270fa24 100644 --- a/examples/shapes/shapes_hilbert_curve.c +++ b/examples/shapes/shapes_hilbert_curve.c @@ -46,13 +46,13 @@ int main(void) float size = (float)GetScreenHeight(); int strokeCount = 0; Vector2 *hilbertPath = LoadHilbertPath(order, size, &strokeCount); - + int prevOrder = order; int prevSize = (int)size; // NOTE: Size from slider is float but for comparison we use int int counter = 0; float thick = 2.0f; bool animate = true; - + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -68,19 +68,19 @@ int main(void) { UnloadHilbertPath(hilbertPath); hilbertPath = LoadHilbertPath(order, size, &strokeCount); - + if (animate) counter = 0; else counter = strokeCount; - + prevOrder = order; prevSize = (int)size; } //---------------------------------------------------------------------------------- - + // Draw //-------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); if (counter < strokeCount) @@ -90,7 +90,7 @@ int main(void) { DrawLineEx(hilbertPath[i], hilbertPath[i - 1], thick, ColorFromHSV(((float)i/strokeCount)*360.0f, 1.0f, 1.0f)); } - + counter += 1; } else @@ -101,13 +101,13 @@ int main(void) DrawLineEx(hilbertPath[i], hilbertPath[i - 1], thick, ColorFromHSV(((float)i/strokeCount)*360.0f, 1.0f, 1.0f)); } } - + // Draw UI using raygui GuiCheckBox((Rectangle){ 450, 50, 20, 20 }, "ANIMATE GENERATION ON CHANGE", &animate); GuiSpinner((Rectangle){ 585, 100, 180, 30 }, "HILBERT CURVE ORDER: ", &order, 2, 8, false); GuiSlider((Rectangle){ 524, 150, 240, 24 }, "THICKNESS: ", NULL, &thick, 1.0f, 10.0f); GuiSlider((Rectangle){ 524, 190, 240, 24 }, "TOTAL SIZE: ", NULL, &size, 10.0f, GetScreenHeight()*1.5f); - + EndDrawing(); //-------------------------------------------------------------------------- } @@ -116,7 +116,7 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- UnloadHilbertPath(hilbertPath); - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; @@ -133,14 +133,14 @@ static Vector2 *LoadHilbertPath(int order, float size, int *strokeCount) *strokeCount = N*N; Vector2 *hilbertPath = (Vector2 *)RL_CALLOC(*strokeCount, sizeof(Vector2)); - + for (int i = 0; i < *strokeCount; i++) { hilbertPath[i] = ComputeHilbertStep(order, i); hilbertPath[i].x = hilbertPath[i].x*len + len/2.0f; hilbertPath[i].y = hilbertPath[i].y*len + len/2.0f; } - + return hilbertPath; } @@ -160,7 +160,7 @@ static Vector2 ComputeHilbertStep(int order, int index) [2] = { .x = 1, .y = 1 }, [3] = { .x = 1, .y = 0 }, }; - + int hilbertIndex = index&3; Vector2 vect = hilbertPoints[hilbertIndex]; float temp = 0.0f; @@ -171,7 +171,7 @@ static Vector2 ComputeHilbertStep(int order, int index) index = index >> 2; hilbertIndex = index&3; len = 1 << j; - + switch (hilbertIndex) { case 0: @@ -191,6 +191,6 @@ static Vector2 ComputeHilbertStep(int order, int index) default: break; } } - + return vect; } diff --git a/examples/shapes/shapes_penrose_tile.c b/examples/shapes/shapes_penrose_tile.c index 0221a10b3..74d4bb717 100644 --- a/examples/shapes/shapes_penrose_tile.c +++ b/examples/shapes/shapes_penrose_tile.c @@ -106,7 +106,7 @@ int main(void) if (generations > 0) rebuild = true; } } - + if (rebuild) { RL_FREE(ls.production); // Free previous production for re-creation @@ -118,15 +118,15 @@ int main(void) // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground( RAYWHITE ); - + if (generations > 0) DrawPenroseLSystem(&ls); - + DrawText("penrose l-system", 10, 10, 20, DARKGRAY); DrawText("press up or down to change generations", 10, 30, 20, DARKGRAY); DrawText(TextFormat("generations: %d", generations), 10, 50, 20, DARKGRAY); - + EndDrawing(); //---------------------------------------------------------------------------------- } @@ -171,11 +171,11 @@ static PenroseLSystem CreatePenroseLSystem(float drawLength) .drawLength = drawLength, .theta = 36.0f // Degrees }; - + ls.production = (char *)RL_MALLOC(sizeof(char)*STR_MAX_SIZE); ls.production[0] = '\0'; strncpy(ls.production, "[X]++[X]++[X]++[X]++[X]", STR_MAX_SIZE); - + return ls; } @@ -211,7 +211,7 @@ static void BuildProductionStep(PenroseLSystem *ls) ls->drawLength *= 0.5f; strncpy(ls->production, newProduction, STR_MAX_SIZE); - + RL_FREE(newProduction); } @@ -228,9 +228,9 @@ static void DrawPenroseLSystem(PenroseLSystem *ls) int repeats = 1; int productionLength = (int)strnlen(ls->production, STR_MAX_SIZE); ls->steps += 12; - + if (ls->steps > productionLength) ls->steps = productionLength; - + for (int i = 0; i < ls->steps; i++) { char step = ls->production[i]; @@ -244,24 +244,24 @@ static void DrawPenroseLSystem(PenroseLSystem *ls) turtle.origin.y += ls->drawLength*sinf(radAngle); Vector2 startPosScreen = { startPosWorld.x + screenCenter.x, startPosWorld.y + screenCenter.y }; Vector2 endPosScreen = { turtle.origin.x + screenCenter.x, turtle.origin.y + screenCenter.y }; - + DrawLineEx(startPosScreen, endPosScreen, 2, Fade(BLACK, 0.2f)); } - + repeats = 1; - } + } else if (step == '+') { for (int j = 0; j < repeats; j++) turtle.angle += ls->theta; repeats = 1; - } + } else if (step == '-') { for (int j = 0; j < repeats; j++) turtle.angle += -ls->theta; repeats = 1; - } + } else if (step == '[') PushTurtleState(turtle); else if (step == ']') turtle = PopTurtleState(); else if ((step >= 48) && (step <= 57)) repeats = (int) step - 48; diff --git a/examples/text/text_strings_management.c b/examples/text/text_strings_management.c index 60f0941f3..449677eb6 100644 --- a/examples/text/text_strings_management.c +++ b/examples/text/text_strings_management.c @@ -33,7 +33,7 @@ typedef struct TextParticle { Vector2 ppos; // Previous position float padding; float borderWidth; - float friction; + float friction; float elasticity; Color color; bool grabbed; @@ -118,7 +118,7 @@ int main(void) if (IsKeyDown(KEY_LEFT_SHIFT)) { ShatterTextParticle(tp, i, textParticles, &particleCount); - } + } else { SliceTextParticle(tp, i, TextLength(tp->text)/2, textParticles, &particleCount); @@ -158,33 +158,33 @@ int main(void) TextParticle *tp = &textParticles[i]; // The text particle is not grabbed - if (!tp->grabbed) + if (!tp->grabbed) { // text particle repositioning using the velocity tp->rect.x += tp->vel.x * delta; tp->rect.y += tp->vel.y * delta; // Does the text particle hit the screen right boundary? - if ((tp->rect.x + tp->rect.width) >= screenWidth) + if ((tp->rect.x + tp->rect.width) >= screenWidth) { tp->rect.x = screenWidth - tp->rect.width; // Text particle repositioning tp->vel.x = -tp->vel.x*tp->elasticity; // Elasticity makes the text particle lose 10% of its velocity on hit - } + } // Does the text particle hit the screen left boundary? else if (tp->rect.x <= 0) - { + { tp->rect.x = 0.0f; tp->vel.x = -tp->vel.x*tp->elasticity; } // The same for y axis - if ((tp->rect.y + tp->rect.height) >= screenHeight) + if ((tp->rect.y + tp->rect.height) >= screenHeight) { tp->rect.y = screenHeight - tp->rect.height; tp->vel.y = -tp->vel.y*tp->elasticity; - } - else if (tp->rect.y <= 0) - { + } + else if (tp->rect.y <= 0) + { tp->rect.y = 0.0f; tp->vel.y = -tp->vel.y*tp->elasticity; } @@ -264,9 +264,9 @@ int main(void) void PrepareFirstTextParticle(const char* text, TextParticle *tps, int *particleCount) { tps[0] = CreateTextParticle( - text, - GetScreenWidth()/2.0f, - GetScreenHeight()/2.0f, + text, + GetScreenWidth()/2.0f, + GetScreenHeight()/2.0f, RAYWHITE ); *particleCount = 1; @@ -317,7 +317,7 @@ void SliceTextParticleByChar(TextParticle *tp, char charToSlice, TextParticle *t { int tokenCount = 0; char **tokens = TextSplit(tp->text, charToSlice, &tokenCount); - + if (tokenCount > 1) { int textLength = TextLength(tp->text); diff --git a/examples/textures/textures_clipboard_image.c b/examples/textures/textures_clipboard_image.c index 1e9ec0846..16501be31 100644 --- a/examples/textures/textures_clipboard_image.c +++ b/examples/textures/textures_clipboard_image.c @@ -51,7 +51,7 @@ int main(void) { // Unload textures to avoid memory leaks for (int i = 0; i < MAX_TEXTURE_COLLECTION; i++) UnloadTexture(collection[i].texture); - + currentCollectionIndex = 0; } @@ -59,7 +59,7 @@ int main(void) (currentCollectionIndex < MAX_TEXTURE_COLLECTION)) { Image image = GetClipboardImage(); - + if (IsImageValid(image)) { collection[currentCollectionIndex].texture = LoadTextureFromImage(image); @@ -76,15 +76,15 @@ int main(void) BeginDrawing(); ClearBackground(RAYWHITE); - + for (int i = 0; i < currentCollectionIndex; i++) { if (IsTextureValid(collection[i].texture)) { - DrawTexturePro(collection[i].texture, - (Rectangle){0,0,collection[i].texture.width, collection[i].texture.height}, + DrawTexturePro(collection[i].texture, + (Rectangle){0,0,collection[i].texture.width, collection[i].texture.height}, (Rectangle){collection[i].position.x,collection[i].position.y,collection[i].texture.width, collection[i].texture.height}, - (Vector2){collection[i].texture.width*0.5f, collection[i].texture.height*0.5f}, + (Vector2){collection[i].texture.width*0.5f, collection[i].texture.height*0.5f}, 0.0f, WHITE); } } diff --git a/examples/textures/textures_magnifying_glass.c b/examples/textures/textures_magnifying_glass.c index 12cd0cdee..e6d5d6316 100644 --- a/examples/textures/textures_magnifying_glass.c +++ b/examples/textures/textures_magnifying_glass.c @@ -3,7 +3,7 @@ * raylib textures example - magnifying glass * * Example complexity rating: [★★★☆] 3/4 -* +* * Example originally created with raylib 5.6, last time updated with raylib 5.6 * * Example contributed by Luke Vaughan (@badram) and reviewed by Ramon Santamaria (@raysan5) @@ -29,18 +29,18 @@ int main(void) const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - magnifying glass"); - + Texture2D bunny = LoadTexture("resources/raybunny.png"); Texture2D parrots = LoadTexture("resources/parrots.png"); - + // Use image draw to generate a mask texture instead of loading it from a file. Image circle = GenImageColor(256, 256, BLANK); ImageDrawCircle(&circle, 128, 128, 128, WHITE); Texture2D mask = LoadTextureFromImage(circle); // Copy the mask image from RAM to VRAM UnloadImage(circle); // Unload the image from RAM - + RenderTexture2D magnifiedWorld = LoadRenderTexture(256, 256); - + Camera2D camera = { 0 }; // Set magnifying glass zoom camera.zoom = 2; @@ -71,7 +71,7 @@ int main(void) DrawTexture(parrots, 144, 33, WHITE); DrawText("Use the magnifying glass to find hidden bunnies!", 154, 6, 20, BLACK); - // Render to a the magnifying glass + // Render to a the magnifying glass BeginTextureMode(magnifiedWorld); ClearBackground(RAYWHITE); diff --git a/examples/textures/textures_screen_buffer.c b/examples/textures/textures_screen_buffer.c index 9c0f25031..928b1a929 100644 --- a/examples/textures/textures_screen_buffer.c +++ b/examples/textures/textures_screen_buffer.c @@ -52,7 +52,7 @@ int main(void) float hue = t*t; float saturation = t; float value = t; - + palette[i] = ColorFromHSV(250.0f + 150.0f*hue, saturation, value); } @@ -92,14 +92,14 @@ int main(void) { unsigned int i = x + y*imageWidth; unsigned char colorIndex = indexBuffer[i]; - + if (colorIndex != 0) { // Move pixel a row above indexBuffer[i] = 0; int moveX = GetRandomValue(0, 2) - 1; int newX = x + moveX; - + if ((newX > 0) && (newX < imageWidth)) { unsigned int iabove = i - imageWidth + moveX; @@ -130,7 +130,7 @@ int main(void) // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); DrawTextureEx(screenTexture, (Vector2){ 0, 0 }, 0.0f, 2.0f, WHITE); diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 8472b03e9..0342211d2 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -2281,7 +2281,7 @@ static inline sw_pixel_write_color_f sw_pixel_get_write_color_func(sw_pixelforma { case SW_PIXELFORMAT_COLOR_GRAYSCALE: return sw_pixel_write_color_GRAYSCALE; case SW_PIXELFORMAT_COLOR_GRAYALPHA: return sw_pixel_write_color_GRAYALPHA; - case SW_PIXELFORMAT_COLOR_R3G3B2: return sw_pixel_write_color_R3G3B2; + case SW_PIXELFORMAT_COLOR_R3G3B2: return sw_pixel_write_color_R3G3B2; case SW_PIXELFORMAT_COLOR_R5G6B5: return sw_pixel_write_color_R5G6B5; case SW_PIXELFORMAT_COLOR_R8G8B8: return sw_pixel_write_color_R8G8B8; case SW_PIXELFORMAT_COLOR_R5G5B5A1: return sw_pixel_write_color_R5G5B5A1; @@ -2472,7 +2472,7 @@ static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_t static inline void sw_texture_sample(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex, float u, float v, float dUdx, float dUdy, float dVdx, float dVdy) { - // NOTE: Commented there is the previous method used + // NOTE: Commented there is the previous method used // There was no need to compute the square root because // using the squared value, the comparison remains (L2 > 1.0f*1.0f) //float du = sqrtf(dUdx*dUdx + dUdy*dUdy); @@ -2673,7 +2673,7 @@ static inline void sw_framebuffer_output_copy(void *dst, const sw_texture_t *buf } } -static inline void sw_framebuffer_output_blit(void *dst, const sw_texture_t *buffer, +static inline void sw_framebuffer_output_blit(void *dst, const sw_texture_t *buffer, int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, sw_pixelformat_t format) { const uint8_t *srcBase = buffer->pixels; @@ -3007,25 +3007,25 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #define RLSW_TEMPLATE_RASTER_TRIANGLE BASE #include __FILE__ // IWYU pragma: keep #undef RLSW_TEMPLATE_RASTER_TRIANGLE - + #define RLSW_TEMPLATE_RASTER_TRIANGLE TEX #define SW_ENABLE_TEXTURE #include __FILE__ #undef SW_ENABLE_TEXTURE #undef RLSW_TEMPLATE_RASTER_TRIANGLE - + #define RLSW_TEMPLATE_RASTER_TRIANGLE DEPTH #define SW_ENABLE_DEPTH_TEST #include __FILE__ #undef SW_ENABLE_DEPTH_TEST #undef RLSW_TEMPLATE_RASTER_TRIANGLE - + #define RLSW_TEMPLATE_RASTER_TRIANGLE BLEND #define SW_ENABLE_BLEND #include __FILE__ #undef SW_ENABLE_BLEND #undef RLSW_TEMPLATE_RASTER_TRIANGLE - + #define RLSW_TEMPLATE_RASTER_TRIANGLE TEX_DEPTH #define SW_ENABLE_TEXTURE #define SW_ENABLE_DEPTH_TEST @@ -3033,7 +3033,7 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #undef SW_ENABLE_DEPTH_TEST #undef SW_ENABLE_TEXTURE #undef RLSW_TEMPLATE_RASTER_TRIANGLE - + #define RLSW_TEMPLATE_RASTER_TRIANGLE TEX_BLEND #define SW_ENABLE_TEXTURE #define SW_ENABLE_BLEND @@ -3041,7 +3041,7 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #undef SW_ENABLE_BLEND #undef SW_ENABLE_TEXTURE #undef RLSW_TEMPLATE_RASTER_TRIANGLE - + #define RLSW_TEMPLATE_RASTER_TRIANGLE DEPTH_BLEND #define SW_ENABLE_DEPTH_TEST #define SW_ENABLE_BLEND @@ -3049,7 +3049,7 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #undef SW_ENABLE_BLEND #undef SW_ENABLE_DEPTH_TEST #undef RLSW_TEMPLATE_RASTER_TRIANGLE - + #define RLSW_TEMPLATE_RASTER_TRIANGLE TEX_DEPTH_BLEND #define SW_ENABLE_TEXTURE #define SW_ENABLE_DEPTH_TEST @@ -3059,7 +3059,7 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #undef SW_ENABLE_DEPTH_TEST #undef SW_ENABLE_TEXTURE #undef RLSW_TEMPLATE_RASTER_TRIANGLE - + // Dispatch table (auto-generated from SW_RASTER_VARIANTS) #define SW_TABLE_ENTRY(NAME, FLAGS) [FLAGS] = sw_raster_triangle_##NAME, static const sw_raster_triangle_f SW_RASTER_TRIANGLE_TABLE[] = { @@ -3106,25 +3106,25 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #define RLSW_TEMPLATE_RASTER_QUAD BASE #include __FILE__ // IWYU pragma: keep #undef RLSW_TEMPLATE_RASTER_QUAD - + #define RLSW_TEMPLATE_RASTER_QUAD TEX #define SW_ENABLE_TEXTURE #include __FILE__ #undef SW_ENABLE_TEXTURE #undef RLSW_TEMPLATE_RASTER_QUAD - + #define RLSW_TEMPLATE_RASTER_QUAD DEPTH #define SW_ENABLE_DEPTH_TEST #include __FILE__ #undef SW_ENABLE_DEPTH_TEST #undef RLSW_TEMPLATE_RASTER_QUAD - + #define RLSW_TEMPLATE_RASTER_QUAD BLEND #define SW_ENABLE_BLEND #include __FILE__ #undef SW_ENABLE_BLEND #undef RLSW_TEMPLATE_RASTER_QUAD - + #define RLSW_TEMPLATE_RASTER_QUAD TEX_DEPTH #define SW_ENABLE_TEXTURE #define SW_ENABLE_DEPTH_TEST @@ -3132,7 +3132,7 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #undef SW_ENABLE_DEPTH_TEST #undef SW_ENABLE_TEXTURE #undef RLSW_TEMPLATE_RASTER_QUAD - + #define RLSW_TEMPLATE_RASTER_QUAD TEX_BLEND #define SW_ENABLE_TEXTURE #define SW_ENABLE_BLEND @@ -3140,7 +3140,7 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #undef SW_ENABLE_BLEND #undef SW_ENABLE_TEXTURE #undef RLSW_TEMPLATE_RASTER_QUAD - + #define RLSW_TEMPLATE_RASTER_QUAD DEPTH_BLEND #define SW_ENABLE_DEPTH_TEST #define SW_ENABLE_BLEND @@ -3148,7 +3148,7 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #undef SW_ENABLE_BLEND #undef SW_ENABLE_DEPTH_TEST #undef RLSW_TEMPLATE_RASTER_QUAD - + #define RLSW_TEMPLATE_RASTER_QUAD TEX_DEPTH_BLEND #define SW_ENABLE_TEXTURE #define SW_ENABLE_DEPTH_TEST @@ -3158,7 +3158,7 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #undef SW_ENABLE_DEPTH_TEST #undef SW_ENABLE_TEXTURE #undef RLSW_TEMPLATE_RASTER_QUAD - + // Dispatch table (auto-generated from SW_RASTER_VARIANTS) #define SW_TABLE_ENTRY(NAME, FLAGS) [FLAGS] = sw_raster_quad_##NAME, static const sw_raster_quad_f SW_RASTER_QUAD_TABLE[] = { @@ -3202,19 +3202,19 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #define RLSW_TEMPLATE_RASTER_LINE BASE #include __FILE__ // IWYU pragma: keep #undef RLSW_TEMPLATE_RASTER_LINE - + #define RLSW_TEMPLATE_RASTER_LINE DEPTH #define SW_ENABLE_DEPTH_TEST #include __FILE__ #undef SW_ENABLE_DEPTH_TEST #undef RLSW_TEMPLATE_RASTER_LINE - + #define RLSW_TEMPLATE_RASTER_LINE BLEND #define SW_ENABLE_BLEND #include __FILE__ #undef SW_ENABLE_BLEND #undef RLSW_TEMPLATE_RASTER_LINE - + #define RLSW_TEMPLATE_RASTER_LINE DEPTH_BLEND #define SW_ENABLE_DEPTH_TEST #define SW_ENABLE_BLEND @@ -3222,7 +3222,7 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #undef SW_ENABLE_BLEND #undef SW_ENABLE_DEPTH_TEST #undef RLSW_TEMPLATE_RASTER_LINE - + // Dispatch table (auto-generated from SW_RASTER_VARIANTS) #define SW_TABLE_ENTRY0(NAME, FLAGS) [FLAGS] = sw_raster_line_##NAME, #define SW_TABLE_ENTRY1(NAME, FLAGS) [FLAGS] = sw_raster_line_thick_##NAME, @@ -3266,19 +3266,19 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #define RLSW_TEMPLATE_RASTER_POINT BASE #include __FILE__ // IWYU pragma: keep #undef RLSW_TEMPLATE_RASTER_POINT - + #define RLSW_TEMPLATE_RASTER_POINT DEPTH #define SW_ENABLE_DEPTH_TEST #include __FILE__ #undef SW_ENABLE_DEPTH_TEST #undef RLSW_TEMPLATE_RASTER_POINT - + #define RLSW_TEMPLATE_RASTER_POINT BLEND #define SW_ENABLE_BLEND #include __FILE__ #undef SW_ENABLE_BLEND #undef RLSW_TEMPLATE_RASTER_POINT - + #define RLSW_TEMPLATE_RASTER_POINT DEPTH_BLEND #define SW_ENABLE_DEPTH_TEST #define SW_ENABLE_BLEND @@ -3286,7 +3286,7 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES] #undef SW_ENABLE_BLEND #undef SW_ENABLE_DEPTH_TEST #undef RLSW_TEMPLATE_RASTER_POINT - + // Dispatch table (auto-generated from SW_RASTER_VARIANTS) #define SW_TABLE_ENTRY(NAME, FLAGS) [FLAGS] = sw_raster_point_##NAME, static const sw_raster_point_f SW_RASTER_POINT_TABLE[] = { @@ -5171,7 +5171,7 @@ void swFramebufferTexture2D(SWattachment attach, uint32_t texture) RLSW.colorBuffer = sw_pool_get(&RLSW.texturePool, texture); } break; case SW_DEPTH_ATTACHMENT: - { + { fb->depthAttachment = texture; RLSW.depthBuffer = sw_pool_get(&RLSW.texturePool, texture); } break; @@ -5262,7 +5262,7 @@ void swGetFramebufferAttachmentParameteriv(SWattachment attachment, SWattachget static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t *end, float dUdy, float dVdy) { - // Gets the start/end coordinates and skip empty lines + // Gets the start/end coordinates and skip empty lines int xStart = (int)start->position[0]; int xEnd = (int)end->position[0]; if (xStart == xEnd) return; diff --git a/src/rcore.c b/src/rcore.c index 894e00832..87df4d5d4 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -684,7 +684,7 @@ void InitWindow(int width, int height, const char *title) } // Initialize render dimensions for embedded platforms - // NOTE: On desktop platforms (GLFW, SDL, etc.), CORE.Window.render.width/height are set during window creation + // NOTE: On desktop platforms (GLFW, SDL, etc.), CORE.Window.render.width/height are set during window creation // On embedded platforms with no window manager, InitPlatform() doesn't set these values, so they should be initialized // here from screen dimensions (which are set from the InitWindow parameters) if ((CORE.Window.render.width == 0) || (CORE.Window.render.height == 0)) diff --git a/src/rtext.c b/src/rtext.c index 936ab9c16..16fe8e75f 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -2265,7 +2265,6 @@ int GetCodepoint(const char *text, int *codepointSize) 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - int codepoint = 0x3f; // Codepoint (defaults to '?') *codepointSize = 1; if (text == NULL) return codepoint; From bd3a35ca21a9f1181e8e67909e926902ed705270 Mon Sep 17 00:00:00 2001 From: Lewis Lee <105315997+LewisLee26@users.noreply.github.com> Date: Thu, 26 Mar 2026 08:20:44 +0000 Subject: [PATCH 012/185] [build.zig.zon] Fix: replace deleted hexops/xcode-frameworks with pkg.machengine.org mirror (#5693) --- build.zig.zon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index dbbde3aad..247386fb1 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -7,8 +7,8 @@ .dependencies = .{ .xcode_frameworks = .{ - .url = "git+https://github.com/hexops/xcode-frameworks#9a45f3ac977fd25dff77e58c6de1870b6808c4a7", - .hash = "N-V-__8AABHMqAWYuRdIlflwi8gksPnlUMQBiSxAqQAAZFms", + .url = "https://pkg.machengine.org/xcode-frameworks/9a45f3ac977fd25dff77e58c6de1870b6808c4a7.tar.gz", + .hash = "122098b9174895f9708bc824b0f9e550c401892c40a900006459acf2cbf78acd99bb", .lazy = true, }, .emsdk = .{ From a693365bf2597b081d64ec12a816fe32ad563aa6 Mon Sep 17 00:00:00 2001 From: Maicon Santana Date: Thu, 26 Mar 2026 17:29:05 +0000 Subject: [PATCH 013/185] Move DrawModelPoints methods to example - point rendering (#5697) --- examples/models/models_point_rendering.c | 33 ++- .../raylib_npp_parser/raylib_npp.xml | 20 +- .../raylib_npp_parser/raylib_to_parse.h | 2 - src/raylib.h | 2 - src/rmodels.c | 26 -- tools/rlparser/output/raylib_api.json | 54 ---- tools/rlparser/output/raylib_api.lua | 24 -- tools/rlparser/output/raylib_api.txt | 236 ++++++++---------- tools/rlparser/output/raylib_api.xml | 14 -- 9 files changed, 141 insertions(+), 270 deletions(-) diff --git a/examples/models/models_point_rendering.c b/examples/models/models_point_rendering.c index 71b907225..fd8d1b9b2 100644 --- a/examples/models/models_point_rendering.c +++ b/examples/models/models_point_rendering.c @@ -16,6 +16,7 @@ ********************************************************************************************/ #include "raylib.h" +#include "rlgl.h" #include // Required for: rand() #include // Required for: cosf(), sinf() @@ -26,8 +27,9 @@ //------------------------------------------------------------------------------------ // Module Functions Declaration //------------------------------------------------------------------------------------ -// Generate mesh using points -static Mesh GenMeshPoints(int numPoints); +static Mesh GenMeshPoints(int numPoints); // Generate mesh using points +void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points +void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters //------------------------------------------------------------------------------------ // Program main entry point @@ -184,3 +186,30 @@ static Mesh GenMeshPoints(int numPoints) return mesh; } + + +// Draw a model points +// WARNING: OpenGL ES 2.0 does not support point mode drawing +void DrawModelPoints(Model model, Vector3 position, float scale, Color tint) +{ + rlEnablePointMode(); + rlDisableBackfaceCulling(); + + DrawModel(model, position, scale, tint); + + rlEnableBackfaceCulling(); + rlDisablePointMode(); +} + +// Draw a model points +// WARNING: OpenGL ES 2.0 does not support point mode drawing +void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint) +{ + rlEnablePointMode(); + rlDisableBackfaceCulling(); + + DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint); + + rlEnableBackfaceCulling(); + rlDisablePointMode(); +} diff --git a/projects/Notepad++/raylib_npp_parser/raylib_npp.xml b/projects/Notepad++/raylib_npp_parser/raylib_npp.xml index 4c6362162..ee965bd76 100644 --- a/projects/Notepad++/raylib_npp_parser/raylib_npp.xml +++ b/projects/Notepad++/raylib_npp_parser/raylib_npp.xml @@ -2960,24 +2960,6 @@ - - - - - - - - - - - - - - - - - - @@ -3013,7 +2995,7 @@ - + diff --git a/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h b/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h index 27e9b79a2..1bd26fbc3 100644 --- a/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h +++ b/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h @@ -600,8 +600,6 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters -RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points -RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source diff --git a/src/raylib.h b/src/raylib.h index 2e849c917..0c2a0beda 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1596,8 +1596,6 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters -RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points -RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source diff --git a/src/rmodels.c b/src/rmodels.c index ba28eb839..0b31d224b 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -3961,32 +3961,6 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rlDisableWireMode(); } -// Draw a model points -// WARNING: OpenGL ES 2.0 does not support point mode drawing -void DrawModelPoints(Model model, Vector3 position, float scale, Color tint) -{ - rlEnablePointMode(); - rlDisableBackfaceCulling(); - - DrawModel(model, position, scale, tint); - - rlEnableBackfaceCulling(); - rlDisablePointMode(); -} - -// Draw a model points -// WARNING: OpenGL ES 2.0 does not support point mode drawing -void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint) -{ - rlEnablePointMode(); - rlDisableBackfaceCulling(); - - DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint); - - rlEnableBackfaceCulling(); - rlDisablePointMode(); -} - // Draw a billboard void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint) { diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index 082e349b7..d4ff5598b 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -10820,60 +10820,6 @@ } ] }, - { - "name": "DrawModelPoints", - "description": "Draw a model as points", - "returnType": "void", - "params": [ - { - "type": "Model", - "name": "model" - }, - { - "type": "Vector3", - "name": "position" - }, - { - "type": "float", - "name": "scale" - }, - { - "type": "Color", - "name": "tint" - } - ] - }, - { - "name": "DrawModelPointsEx", - "description": "Draw a model as points with extended parameters", - "returnType": "void", - "params": [ - { - "type": "Model", - "name": "model" - }, - { - "type": "Vector3", - "name": "position" - }, - { - "type": "Vector3", - "name": "rotationAxis" - }, - { - "type": "float", - "name": "rotationAngle" - }, - { - "type": "Vector3", - "name": "scale" - }, - { - "type": "Color", - "name": "tint" - } - ] - }, { "name": "DrawBoundingBox", "description": "Draw bounding box (wires)", diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index b68ab7563..5e22916b3 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -7493,30 +7493,6 @@ return { {type = "Color", name = "tint"} } }, - { - name = "DrawModelPoints", - description = "Draw a model as points", - returnType = "void", - params = { - {type = "Model", name = "model"}, - {type = "Vector3", name = "position"}, - {type = "float", name = "scale"}, - {type = "Color", name = "tint"} - } - }, - { - name = "DrawModelPointsEx", - description = "Draw a model as points with extended parameters", - returnType = "void", - params = { - {type = "Model", name = "model"}, - {type = "Vector3", name = "position"}, - {type = "Vector3", name = "rotationAxis"}, - {type = "float", name = "rotationAngle"}, - {type = "Vector3", name = "scale"}, - {type = "Color", name = "tint"} - } - }, { name = "DrawBoundingBox", description = "Draw bounding box (wires)", diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index 2213d3def..929a3a30e 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -4126,31 +4126,13 @@ Function 488: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 489: DrawModelPoints() (4 input parameters) - Name: DrawModelPoints - Return type: void - Description: Draw a model as points - Param[1]: model (type: Model) - Param[2]: position (type: Vector3) - Param[3]: scale (type: float) - Param[4]: tint (type: Color) -Function 490: DrawModelPointsEx() (6 input parameters) - Name: DrawModelPointsEx - Return type: void - Description: Draw a model as points with extended parameters - Param[1]: model (type: Model) - Param[2]: position (type: Vector3) - Param[3]: rotationAxis (type: Vector3) - Param[4]: rotationAngle (type: float) - Param[5]: scale (type: Vector3) - Param[6]: tint (type: Color) -Function 491: DrawBoundingBox() (2 input parameters) +Function 489: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 492: DrawBillboard() (5 input parameters) +Function 490: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -4159,7 +4141,7 @@ Function 492: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 493: DrawBillboardRec() (6 input parameters) +Function 491: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -4169,7 +4151,7 @@ Function 493: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 494: DrawBillboardPro() (9 input parameters) +Function 492: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -4182,13 +4164,13 @@ Function 494: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 495: UploadMesh() (2 input parameters) +Function 493: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 496: UpdateMeshBuffer() (5 input parameters) +Function 494: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4197,19 +4179,19 @@ Function 496: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 497: UnloadMesh() (1 input parameters) +Function 495: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 498: DrawMesh() (3 input parameters) +Function 496: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 499: DrawMeshInstanced() (4 input parameters) +Function 497: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4217,35 +4199,35 @@ Function 499: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 500: GetMeshBoundingBox() (1 input parameters) +Function 498: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 501: GenMeshTangents() (1 input parameters) +Function 499: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 502: ExportMesh() (2 input parameters) +Function 500: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 503: ExportMeshAsCode() (2 input parameters) +Function 501: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 504: GenMeshPoly() (2 input parameters) +Function 502: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 505: GenMeshPlane() (4 input parameters) +Function 503: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4253,42 +4235,42 @@ Function 505: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 506: GenMeshCube() (3 input parameters) +Function 504: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 507: GenMeshSphere() (3 input parameters) +Function 505: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 508: GenMeshHemiSphere() (3 input parameters) +Function 506: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 509: GenMeshCylinder() (3 input parameters) +Function 507: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 510: GenMeshCone() (3 input parameters) +Function 508: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 511: GenMeshTorus() (4 input parameters) +Function 509: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4296,7 +4278,7 @@ Function 511: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 512: GenMeshKnot() (4 input parameters) +Function 510: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4304,67 +4286,67 @@ Function 512: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 513: GenMeshHeightmap() (2 input parameters) +Function 511: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 514: GenMeshCubicmap() (2 input parameters) +Function 512: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 515: LoadMaterials() (2 input parameters) +Function 513: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 516: LoadMaterialDefault() (0 input parameters) +Function 514: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 517: IsMaterialValid() (1 input parameters) +Function 515: IsMaterialValid() (1 input parameters) Name: IsMaterialValid Return type: bool Description: Check if a material is valid (shader assigned, map textures loaded in GPU) Param[1]: material (type: Material) -Function 518: UnloadMaterial() (1 input parameters) +Function 516: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 519: SetMaterialTexture() (3 input parameters) +Function 517: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 520: SetModelMeshMaterial() (3 input parameters) +Function 518: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 521: LoadModelAnimations() (2 input parameters) +Function 519: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 522: UpdateModelAnimation() (3 input parameters) +Function 520: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose (vertex buffers and bone matrices) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: float) -Function 523: UpdateModelAnimationEx() (6 input parameters) +Function 521: UpdateModelAnimationEx() (6 input parameters) Name: UpdateModelAnimationEx Return type: void Description: Update model animation pose, blending two animations @@ -4374,19 +4356,19 @@ Function 523: UpdateModelAnimationEx() (6 input parameters) Param[4]: animB (type: ModelAnimation) Param[5]: frameB (type: float) Param[6]: blend (type: float) -Function 524: UnloadModelAnimations() (2 input parameters) +Function 522: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 525: IsModelAnimationValid() (2 input parameters) +Function 523: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 526: CheckCollisionSpheres() (4 input parameters) +Function 524: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4394,40 +4376,40 @@ Function 526: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 527: CheckCollisionBoxes() (2 input parameters) +Function 525: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 528: CheckCollisionBoxSphere() (3 input parameters) +Function 526: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 529: GetRayCollisionSphere() (3 input parameters) +Function 527: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 530: GetRayCollisionBox() (2 input parameters) +Function 528: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 531: GetRayCollisionMesh() (3 input parameters) +Function 529: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 532: GetRayCollisionTriangle() (4 input parameters) +Function 530: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4435,7 +4417,7 @@ Function 532: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 533: GetRayCollisionQuad() (5 input parameters) +Function 531: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4444,158 +4426,158 @@ Function 533: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 534: InitAudioDevice() (0 input parameters) +Function 532: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 535: CloseAudioDevice() (0 input parameters) +Function 533: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 536: IsAudioDeviceReady() (0 input parameters) +Function 534: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 537: SetMasterVolume() (1 input parameters) +Function 535: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 538: GetMasterVolume() (0 input parameters) +Function 536: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 539: LoadWave() (1 input parameters) +Function 537: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 540: LoadWaveFromMemory() (3 input parameters) +Function 538: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 541: IsWaveValid() (1 input parameters) +Function 539: IsWaveValid() (1 input parameters) Name: IsWaveValid Return type: bool Description: Checks if wave data is valid (data loaded and parameters) Param[1]: wave (type: Wave) -Function 542: LoadSound() (1 input parameters) +Function 540: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 543: LoadSoundFromWave() (1 input parameters) +Function 541: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 544: LoadSoundAlias() (1 input parameters) +Function 542: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 545: IsSoundValid() (1 input parameters) +Function 543: IsSoundValid() (1 input parameters) Name: IsSoundValid Return type: bool Description: Checks if a sound is valid (data loaded and buffers initialized) Param[1]: sound (type: Sound) -Function 546: UpdateSound() (3 input parameters) +Function 544: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data (default data format: 32 bit float, stereo) Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 547: UnloadWave() (1 input parameters) +Function 545: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 548: UnloadSound() (1 input parameters) +Function 546: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 549: UnloadSoundAlias() (1 input parameters) +Function 547: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload a sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 550: ExportWave() (2 input parameters) +Function 548: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 551: ExportWaveAsCode() (2 input parameters) +Function 549: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 552: PlaySound() (1 input parameters) +Function 550: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 553: StopSound() (1 input parameters) +Function 551: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 554: PauseSound() (1 input parameters) +Function 552: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 555: ResumeSound() (1 input parameters) +Function 553: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 556: IsSoundPlaying() (1 input parameters) +Function 554: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 557: SetSoundVolume() (2 input parameters) +Function 555: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 558: SetSoundPitch() (2 input parameters) +Function 556: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 559: SetSoundPan() (2 input parameters) +Function 557: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (-1.0 left, 0.0 center, 1.0 right) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 560: WaveCopy() (1 input parameters) +Function 558: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 561: WaveCrop() (3 input parameters) +Function 559: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 562: WaveFormat() (4 input parameters) +Function 560: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4603,203 +4585,203 @@ Function 562: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 563: LoadWaveSamples() (1 input parameters) +Function 561: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 564: UnloadWaveSamples() (1 input parameters) +Function 562: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 565: LoadMusicStream() (1 input parameters) +Function 563: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 566: LoadMusicStreamFromMemory() (3 input parameters) +Function 564: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 567: IsMusicValid() (1 input parameters) +Function 565: IsMusicValid() (1 input parameters) Name: IsMusicValid Return type: bool Description: Checks if a music stream is valid (context and buffers initialized) Param[1]: music (type: Music) -Function 568: UnloadMusicStream() (1 input parameters) +Function 566: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 569: PlayMusicStream() (1 input parameters) +Function 567: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 570: IsMusicStreamPlaying() (1 input parameters) +Function 568: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 571: UpdateMusicStream() (1 input parameters) +Function 569: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 572: StopMusicStream() (1 input parameters) +Function 570: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 573: PauseMusicStream() (1 input parameters) +Function 571: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 574: ResumeMusicStream() (1 input parameters) +Function 572: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 575: SeekMusicStream() (2 input parameters) +Function 573: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 576: SetMusicVolume() (2 input parameters) +Function 574: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 577: SetMusicPitch() (2 input parameters) +Function 575: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for a music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 578: SetMusicPan() (2 input parameters) +Function 576: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for a music (-1.0 left, 0.0 center, 1.0 right) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 579: GetMusicTimeLength() (1 input parameters) +Function 577: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 580: GetMusicTimePlayed() (1 input parameters) +Function 578: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 581: LoadAudioStream() (3 input parameters) +Function 579: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 582: IsAudioStreamValid() (1 input parameters) +Function 580: IsAudioStreamValid() (1 input parameters) Name: IsAudioStreamValid Return type: bool Description: Checks if an audio stream is valid (buffers initialized) Param[1]: stream (type: AudioStream) -Function 583: UnloadAudioStream() (1 input parameters) +Function 581: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 584: UpdateAudioStream() (3 input parameters) +Function 582: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 585: IsAudioStreamProcessed() (1 input parameters) +Function 583: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 586: PlayAudioStream() (1 input parameters) +Function 584: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 587: PauseAudioStream() (1 input parameters) +Function 585: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 588: ResumeAudioStream() (1 input parameters) +Function 586: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 589: IsAudioStreamPlaying() (1 input parameters) +Function 587: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 590: StopAudioStream() (1 input parameters) +Function 588: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 591: SetAudioStreamVolume() (2 input parameters) +Function 589: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 592: SetAudioStreamPitch() (2 input parameters) +Function 590: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 593: SetAudioStreamPan() (2 input parameters) +Function 591: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 594: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 592: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 595: SetAudioStreamCallback() (2 input parameters) +Function 593: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 596: AttachAudioStreamProcessor() (2 input parameters) +Function 594: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives frames x 2 samples as 'float' (stereo) Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 597: DetachAudioStreamProcessor() (2 input parameters) +Function 595: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 598: AttachAudioMixedProcessor() (1 input parameters) +Function 596: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives frames x 2 samples as 'float' (stereo) Param[1]: processor (type: AudioCallback) -Function 599: DetachAudioMixedProcessor() (1 input parameters) +Function 597: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 2ec474efd..3816c4dfc 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -2755,20 +2755,6 @@ - - - - - - - - - - - - - - From d7bd56ef1b97b10568a1272ed0aaf4f347d519f5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 17:29:18 +0000 Subject: [PATCH 014/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.txt | 2 +- tools/rlparser/output/raylib_api.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index 929a3a30e..7943b28f3 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -1000,7 +1000,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 599 +Functions found: 597 Function 001: InitWindow() (3 input parameters) Name: InitWindow diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 3816c4dfc..408ff18c7 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -682,7 +682,7 @@ - + From 51f4741912b25ddf9931c01aa594562a7b02b2de Mon Sep 17 00:00:00 2001 From: Antonio Jose Ramos Marquez Date: Fri, 27 Mar 2026 09:25:26 +0100 Subject: [PATCH 015/185] [rmodel] fix for devices without VAO support (#5692) --- src/rmodels.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/rmodels.c b/src/rmodels.c index 0b31d224b..c78930f03 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1281,7 +1281,6 @@ void UploadMesh(Mesh *mesh, bool dynamic) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) mesh->vaoId = rlLoadVertexArray(); - if (mesh->vaoId == 0) return; rlEnableVertexArray(mesh->vaoId); From 98d6e24c442e1c884d5f60590061aa0fa468778a Mon Sep 17 00:00:00 2001 From: mjt Date: Fri, 27 Mar 2026 10:26:01 +0200 Subject: [PATCH 016/185] remove comment (#5696) --- examples/shaders/resources/shaders/glsl100/normalmap.fs | 2 +- examples/shaders/resources/shaders/glsl120/normalmap.fs | 2 +- examples/shaders/resources/shaders/glsl330/normalmap.fs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/shaders/resources/shaders/glsl100/normalmap.fs b/examples/shaders/resources/shaders/glsl100/normalmap.fs index a1b992811..6628f2006 100644 --- a/examples/shaders/resources/shaders/glsl100/normalmap.fs +++ b/examples/shaders/resources/shaders/glsl100/normalmap.fs @@ -52,7 +52,7 @@ void main() float specCo = 0.0; - if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine + if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); specular += specCo; diff --git a/examples/shaders/resources/shaders/glsl120/normalmap.fs b/examples/shaders/resources/shaders/glsl120/normalmap.fs index 9e7ba5e19..8b12ca226 100644 --- a/examples/shaders/resources/shaders/glsl120/normalmap.fs +++ b/examples/shaders/resources/shaders/glsl120/normalmap.fs @@ -50,7 +50,7 @@ void main() float specCo = 0.0; - if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine + if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); specular += specCo; diff --git a/examples/shaders/resources/shaders/glsl330/normalmap.fs b/examples/shaders/resources/shaders/glsl330/normalmap.fs index 697423701..005446448 100644 --- a/examples/shaders/resources/shaders/glsl330/normalmap.fs +++ b/examples/shaders/resources/shaders/glsl330/normalmap.fs @@ -54,7 +54,7 @@ void main() float specCo = 0.0; - if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine + if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); specular += specCo; From ba83bd33f30513b3baa9c20a02d02969a62f446b Mon Sep 17 00:00:00 2001 From: Le Juez Victor <90587919+Bigfoot71@users.noreply.github.com> Date: Fri, 27 Mar 2026 09:26:53 +0100 Subject: [PATCH 017/185] simplify `CheckCollisionSpheres` using `Vector3DistanceSqr` (#5695) --- src/rmodels.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rmodels.c b/src/rmodels.c index c78930f03..a662a2dc2 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -4085,7 +4085,8 @@ bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, floa */ // Check for distances squared to avoid sqrtf() - if (Vector3DotProduct(Vector3Subtract(center2, center1), Vector3Subtract(center2, center1)) <= (radius1 + radius2)*(radius1 + radius2)) collision = true; + float radSum = radius1 + radius2; + if (Vector3DistanceSqr(center1, center2) <= radSum*radSum) collision = true; return collision; } From 8a7aff509dd13315930884bc8374a44b6b1ead28 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 27 Mar 2026 21:56:29 +0100 Subject: [PATCH 018/185] WARNING: BREAKING: REDESIGNED: `TextInsert()`, `TextReplace()`, `TextReplaceBetween()`, using static buffers Redesign has been conditioned by the usage of those functions on `rexm`, `rpc` and other tools; for many use cases a static buffer is enough and way more comfortable to use. ADDED: `TextInsertAlloc()`, `TextReplaceAlloc()`, `TextReplaceBetweenAlloc()`, alternatives with internal allocations --- CHANGELOG | 28 +++++++--- src/raylib.h | 13 +++-- src/rcore.c | 2 +- src/rtext.c | 139 ++++++++++++++++++++++++++++++++++++++++++++-- tools/rexm/rexm.c | 53 ++++++++---------- 5 files changed, 185 insertions(+), 50 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 053ff3018..cf9bf238d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -21,11 +21,17 @@ KEY CHANGES: Detailed changes: +[rcore] ADDED: `FileRename()`, by @raysan5 +[rcore] ADDED: `FileRemove()`, by @raysan5 +[rcore] ADDED: `FileCopy()`, by @raysan5 +[rcore] ADDED: `FileMove()`, by @raysan5 +[rcore] ADDED: `FileTextReplace()`, by @raysan5 +[rcore] ADDED: `FileTextFindIndex()`, by @raysan5 +[rcore] ADDED: `ComputeSHA256()` (#5264) by @iamahuman1395 +[rcore] ADDED: `GetKeyName()` (#4544) by @lecongsebastien [rcore] ADDED: Logging and file-system functionality from `utils` (#4551) by @raysan5 -WARNING- [rcore] ADDED: Flags set/clear macros: FLAG_SET, FLAG_CLEAR, FLAG_IS_SET (#5169) by @raysan5 [rcore] ADDED: Warnings in case of no platform backend defined by @raysan5 -[rcore] ADDED: `ComputeSHA256()` (#5264) by @iamahuman1395 -[rcore] ADDED: `GetKeyName()` (#4544) by @lecongsebastien [rcore] REMOVED: GIF recording option, added example by @raysan5 -WARNING- [rcore] REMOVED: `CORE.Window.fullscreen` variable, using available flag instead by @raysan5 [rcore] REMOVED: `SetupFramebuffer()`, most platforms do not need it any more by @raysan5 @@ -111,7 +117,7 @@ Detailed changes: [rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley [rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX [rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc -[rcore][RGFW] REVIEWED: Duplicate entries reemoved from `keyMappingRGFW` (#5242) by @iamahuman1395 +[rcore][RGFW] REVIEWED: Duplicate entries removed from `keyMappingRGFW` (#5242) by @iamahuman1395 [rcore][RGFW] REVIEWED: Fix Escape always closing the window by @M374LX [rcore][RGFW] REVIEWED: Forward declare the windows stuff, prevents failures in GCC (#5269) by @Jeffm2501 [rcore][RGFW] REVIEWED: Requires RGBA8 images as window icons (#5431) by @crisserpl2 @@ -198,7 +204,7 @@ Detailed changes: [rlgl] REVIEWED: `rlActiveDrawBuffers`, fix for OpenGL ES 3.0 (#4605) by @Bigfoot71 [rlgl] REVIEWED: `rlGetPixelDataSize()`, correct compressed data size calculation per blocks #5416 by @raysan5 [rlgl] REVIEWED: `instranceTransform` shader location index #4538 (#4579) by @meadiode -[rlgl] REVIEWED: `SetShaderValueTexture()`, updatee comments (#4703) by @pejorativefox +[rlgl] REVIEWED: `SetShaderValueTexture()`, update comments (#4703) by @pejorativefox [rlgl] REDESIGNED: Avoid program crash if GPU data is tried to be loaded before `InitWindow()` #4751 by @raysan5 -WARNING- [rlgl] REDESIGNED: Shader loading API function names for more consistency #5631 by @raysan5 -WARNING- [rlsw] ADDED: `swGetColorBuffer()` for convenience by @raysan5 @@ -239,6 +245,13 @@ Detailed changes: [rtextures] REVIEWED: `ImageDrawLineEx(), to be able to draw even numbered thicknesses (#5042) by @Sir-Irk [rtextures] REVIEWED: `ImageBlurGaussian()`, fix integer overflow in cast (#5037) by @garrisonhh [rtext] ADDED: `LoadTextLines()`/`UnloadTextLines()` by @raysan5 +[rtext] ADDED: `TextInsertAlloc()`, returns memory allocated string by @raysan5 +[rtext] ADDED: `TextReplace()`, using static buffer by @raysan5 +[rtext] ADDED: `TextReplaceAlloc()`, returns memory allocated string by @raysan5 +[rtext] ADDED: `TextReplaceBetween()`, using static buffer by @raysan5 +[rtext] ADDED: `TextReplaceBetweenAlloc()`, returns memory allocated string by @raysan5 +[rtext] ADDED: `GetTextBetween()`, using static buffer by @raysan5 +[rtext] ADDED: `TextRemoveSpaces()`, using static buffer by @raysan5 [rtext] ADDED: `MeasureTextCodepoints()` for direct measurement of codepoints (#5623) by @creeperblin [rtext] RENAMED: Variable names for consistency, `textLength` (length in bytes) vs `textSize` (measure in pixels) by @raysan5 [rtext] REVIEWED: Support default font loading with no GPU enabled, to be used with Image API @@ -263,11 +276,10 @@ Detailed changes: [rtext] REVIEWED: `GetCodepointCount()`, misuse of cast (#4741) by @sleeptightAnsiC [rtext] REVIEWED: `GenImageFontAtlas()`, memory corruption and invalid size calculation (#5602) by @konakona418 [rtext] REVIEWED: `TextInsert()`, fix bug on insertion (#5644) by @CrackedPixel +[rtext] REVIEWED: `TextInsert()`, use static buffer, easier to use by @raysan5 -WARNING- [rtext] REVIEWED: `TextJoin()`, convert `const char **` to `char**` by @raysan5 -[rtext] REVIEWED: `TextReplace()` and `TextLength()`, avoid using `strcpy()` by @raysan5 -[rtext] REVIEWED: `TextReplace()` by @raysan5 [rtext] REVIEWED: `TextReplace()`, improvements (#5511) by @belan2470 -[rtext] REVIEWED: `TextReplaceBetween()` by @raysan5 +[rtext] REVIEWED: `TextReplace()` and `TextLength()`, avoid using `strcpy()` by @raysan5 [rtext] REVIEWED: `TextSubtext(), fixes (#4759) by @veins1 [rtext] REVIEWED: `TextToPascal()`, fix issue by @raysan5 [rtext] REVIEWED: `TextToFloat()`, remove removed inaccurate comment (#4596) by @hexmaster111 @@ -735,7 +747,7 @@ Detailed changes: [rexm] REVIEWED: `ScanExampleResources()` avoid resources to be saved by the program by @raysan5 [rexm] REVIEWED: `UpdateSourceMetadata()` and `TextReplaceBetween()` by @raysan5 [rexm] REVIEWED: `examples.js` example addition working by @raysan5 -[rexm] REVIEWED: `add` command logic for existing examplee addition by @raysan5 +[rexm] REVIEWED: `add` command logic for existing example addition by @raysan5 [rexm] REVIEWED: Replace example name on project file by @raysan5 [rexm] REVIEWED: Report issues if logs can not be loaded by @raysan5 [rexm] REVIEWED: VS project adding to solution by @raysan5 diff --git a/src/raylib.h b/src/raylib.h index 0c2a0beda..ac5bc414e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1359,7 +1359,7 @@ RLAPI Image LoadImageFromScreen(void); RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters) RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM) RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success -RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer +RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer, memory must be MemFree() RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success // Image generation functions @@ -1528,7 +1528,7 @@ RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Text strings management functions (no UTF-8 strings, only byte chars) // WARNING 1: Most of these functions use internal static buffers[], it's recommended to store returned data on user-side for re-use -// WARNING 2: Some strings allocate memory internally for the returned strings, those strings must be free by user using MemFree() +// WARNING 2: Some functions allocate memory internally for the returned strings, those strings must be freed by user using MemFree() RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n') RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied @@ -1538,9 +1538,12 @@ RLAPI const char *TextFormat(const char *text, ...); RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string RLAPI const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words RLAPI char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings -RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string (WARNING: memory must be freed!) -RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings (WARNING: memory must be freed!) -RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!) +RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string with new string +RLAPI char *TextReplaceAlloc(const char *text, const char *search, const char *replacement); // Replace text string with new string, memory must be MemFree() +RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings +RLAPI char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings, memory must be MemFree() +RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a defined byte position +RLAPI char *TextInsertAlloc(const char *text, const char *insert, int position); // Insert text in a defined byte position, memory must be MemFree() RLAPI char *TextJoin(char **textList, int count, const char *delimiter); // Join text strings with delimiter RLAPI char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor diff --git a/src/rcore.c b/src/rcore.c index 87df4d5d4..3454b65ba 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -2298,7 +2298,7 @@ int FileTextReplace(const char *fileName, const char *search, const char *replac if (FileExists(fileName)) { fileText = LoadFileText(fileName); - fileTextUpdated = TextReplace(fileText, search, replacement); + fileTextUpdated = TextReplaceAlloc(fileText, search, replacement); result = SaveFileText(fileName, fileTextUpdated); MemFree(fileTextUpdated); UnloadFileText(fileText); diff --git a/src/rtext.c b/src/rtext.c index 16fe8e75f..a6ca65113 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -1736,8 +1736,6 @@ const char *TextRemoveSpaces(const char *text) // Get text between two strings char *GetTextBetween(const char *text, const char *begin, const char *end) { - #define MAX_TEXT_BETWEEN_SIZE 1024 - static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 }; memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH); @@ -1752,8 +1750,8 @@ char *GetTextBetween(const char *text, const char *begin, const char *end) { endIndex += (beginIndex + beginLen); int len = (endIndex - beginIndex - beginLen); - if (len < (MAX_TEXT_BETWEEN_SIZE - 1)) strncpy(buffer, text + beginIndex + beginLen, len); - else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BETWEEN_SIZE - 1); + if (len < (MAX_TEXT_BUFFER_LENGTH - 1)) strncpy(buffer, text + beginIndex + beginLen, len); + else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BUFFER_LENGTH - 1); } } @@ -1762,8 +1760,74 @@ char *GetTextBetween(const char *text, const char *begin, const char *end) // Replace text string // REQUIRES: strstr(), strncpy() -// WARNING: Allocated memory must be manually freed +// NOTE: Limited text replace functionality, using static string char *TextReplace(const char *text, const char *search, const char *replacement) +{ + static char result[MAX_TEXT_BUFFER_LENGTH] = { 0 }; + memset(result, 0, MAX_TEXT_BUFFER_LENGTH); + + if ((text != NULL) && (search != NULL) && (search[0] != '\0')) + { + if (replacement == NULL) replacement = ""; + + char *insertPoint = NULL; // Next insert point + char *tempPtr = NULL; // Temp pointer + int textLen = 0; // Text string length + int searchLen = 0; // Search string length of (the string to remove) + int replaceLen = 0; // Replacement length (the string to replace by) + int lastReplacePos = 0; // Distance between next search and end of last replace + int count = 0; // Number of replacements + + textLen = TextLength(text); + searchLen = TextLength(search); + replaceLen = TextLength(replacement); + + // Count the number of replacements needed + insertPoint = (char *)text; + for (count = 0; (tempPtr = strstr(insertPoint, search)); count++) insertPoint = tempPtr + searchLen; + + if ((textLen + count*(replaceLen - searchLen)) < (MAX_TEXT_BUFFER_LENGTH - 1)) + { + // TODO: Allow copying data replaced up to maximum buffer size and stop + + tempPtr = result; // Point to result start + + // First time through the loop, all the variable are set correctly from here on, + // - 'temp' points to the end of the result string + // - 'insertPoint' points to the next occurrence of replace in text + // - 'text' points to the remainder of text after "end of replace" + while (count > 0) + { + insertPoint = (char *)strstr(text, search); + lastReplacePos = (int)(insertPoint - text); + + memcpy(tempPtr, text, lastReplacePos); + tempPtr += lastReplacePos; + + if (replaceLen > 0) + { + memcpy(tempPtr, replacement, replaceLen); + tempPtr += replaceLen; + } + + text += (lastReplacePos + searchLen); // Move to next "end of replace" + count--; + } + + // Copy remaind text part after replacement to result (pointed by moving temp) + // NOTE: Text pointer internal copy has been updated along the process + strncpy(tempPtr, text, TextLength(text)); + } + else TRACELOG(LOG_WARNING, "Text with replacement is longer than internal buffer, use TextReplaceAlloc()"); + } + + return result; +} + +// Replace text string +// REQUIRES: strstr(), strncpy() +// WARNING: Allocated memory must be manually freed +char *TextReplaceAlloc(const char *text, const char *search, const char *replacement) { char *result = NULL; @@ -1825,11 +1889,46 @@ char *TextReplace(const char *text, const char *search, const char *replacement) return result; } +// Replace text between two specific strings +// REQUIRES: strncpy() +// NOTE: If (replacement == NULL) removes "begin"[ ]"end" text +char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement) +{ + static char result[MAX_TEXT_BUFFER_LENGTH] = { 0 }; + memset(result, 0, MAX_TEXT_BUFFER_LENGTH); + + if ((text != NULL) && (begin != NULL) && (end != NULL)) + { + int beginIndex = TextFindIndex(text, begin); + + if (beginIndex > -1) + { + int beginLen = TextLength(begin); + int endIndex = TextFindIndex(text + beginIndex + beginLen, end); + + if (endIndex > -1) + { + endIndex += (beginIndex + beginLen); + + int textLen = TextLength(text); + int replaceLen = (replacement == NULL)? 0 : TextLength(replacement); + int toreplaceLen = endIndex - beginIndex - beginLen; + + strncpy(result, text, beginIndex + beginLen); // Copy first text part + if (replacement != NULL) strncpy(result + beginIndex + beginLen, replacement, replaceLen); // Copy replacement (if provided) + strncpy(result + beginIndex + beginLen + replaceLen, text + endIndex, textLen - endIndex); // Copy end text part + } + } + } + + return result; +} + // Replace text between two specific strings // REQUIRES: strncpy() // NOTE: If (replacement == NULL) remove "begin"[ ]"end" text // WARNING: Returned string must be freed by user -char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement) +char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement) { char *result = NULL; @@ -1864,6 +1963,34 @@ char *TextReplaceBetween(const char *text, const char *begin, const char *end, c // Insert text in a specific position, moves all text forward // WARNING: Allocated memory must be manually freed char *TextInsert(const char *text, const char *insert, int position) +{ + static char result[MAX_TEXT_BUFFER_LENGTH] = { 0 }; + memset(result, 0, MAX_TEXT_BUFFER_LENGTH); + + if ((text != NULL) && (insert != NULL)) + { + int textLen = TextLength(text); + int insertLen = TextLength(insert); + + if ((textLen + insertLen) < (MAX_TEXT_BUFFER_LENGTH - 1)) + { + // TODO: Allow copying data inserted up to maximum buffer size and stop + + for (int i = 0; i < position; i++) result[i] = text[i]; + for (int i = position; i < insertLen + position; i++) result[i] = insert[i - position]; + for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i]; + + result[textLen + insertLen] = '\0'; // Add EOL + } + else TRACELOG(LOG_WARNING, "Text with inserted string is longer than internal buffer, use TextInserExt()"); + } + + return result; +} + +// Insert text in a specific position, moves all text forward +// WARNING: Allocated memory must be manually freed +char *TextInsertAlloc(const char *text, const char *insert, int position) { char *result = NULL; diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index e4881b633..48a621115 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -469,12 +469,12 @@ int main(int argc, char *argv[]) int exIndex = TextFindIndex(exText, "/****************"); // Update required info with some defaults - exTextUpdated[0] = TextReplace(exText + exIndex, "", exCategory); - exTextUpdated[1] = TextReplace(exTextUpdated[0], "", exName + strlen(exCategory) + 1); - //TextReplace(newExample, "", "Ray"); - //TextReplace(newExample, "@", "@raysan5"); - //TextReplace(newExample, "", 2025); - //TextReplace(newExample, "", 2025); + exTextUpdated[0] = TextReplaceAlloc(exText + exIndex, "", exCategory); + exTextUpdated[1] = TextReplaceAlloc(exTextUpdated[0], "", exName + strlen(exCategory) + 1); + //TextReplaceAlloc(newExample, "", "Ray"); + //TextReplaceAlloc(newExample, "@", "@raysan5"); + //TextReplaceAlloc(newExample, "", 2025); + //TextReplaceAlloc(newExample, "", 2025); SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), exTextUpdated[1]); for (int i = 0; i < 6; i++) { MemFree(exTextUpdated[i]); exTextUpdated[i] = NULL; } @@ -541,8 +541,6 @@ int main(int argc, char *argv[]) else LOG("WARNING: Example resource must be placed in 'resources' directory next to .c file\n"); } else LOG("WARNING: Example resource can not be found in: %s\n", TextFormat("%s/%s", GetDirectoryPath(inFileName), resPathUpdated)); - - RL_FREE(resPathUpdated); } } else @@ -863,9 +861,7 @@ int main(int argc, char *argv[]) for (int v = 0; v < 3; v++) { - char *resPathUpdated = TextReplace(resPaths[r], "glsl%i", TextFormat("glsl%i", glslVer[v])); - FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPathUpdated)); - RL_FREE(resPathUpdated); + FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, TextReplace(resPaths[r], "glsl%i", TextFormat("glsl%i", glslVer[v])))); } } else FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPaths[r])); @@ -1164,7 +1160,6 @@ int main(int argc, char *argv[]) // Logging missing resources for convenience LOG("WARNING: [%s] Missing resource: %s\n", exInfo->name, resPathUpdated); } - RL_FREE(resPathUpdated); } } else @@ -1577,13 +1572,13 @@ int main(int argc, char *argv[]) " SaveFileText(\"outputLogFileName\", logText);\n" " emscripten_run_script(\"saveFileFromMEMFSToDisk('outputLogFileName','outputLogFileName')\");\n\n" " return 0"; - char *returnReplaceTextUpdated = TextReplace(returnReplaceText, "outputLogFileName", TextFormat("%s.log", exName)); + char *returnReplaceTextUpdated = TextReplacEx(returnReplaceText, "outputLogFileName", TextFormat("%s.log", exName)); char *srcTextUpdated[4] = { 0 }; - srcTextUpdated[0] = TextReplace(srcText, "int main(void)\n{", mainReplaceText); - srcTextUpdated[1] = TextReplace(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)"); - srcTextUpdated[2] = TextReplace(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;"); - srcTextUpdated[3] = TextReplace(srcTextUpdated[2], " return 0", returnReplaceTextUpdated); + srcTextUpdated[0] = TextReplacEx(srcText, "int main(void)\n{", mainReplaceText); + srcTextUpdated[1] = TextReplacEx(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)"); + srcTextUpdated[2] = TextReplacEx(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;"); + srcTextUpdated[3] = TextReplacEx(srcTextUpdated[2], " return 0", returnReplaceTextUpdated); MemFree(returnReplaceTextUpdated); UnloadFileText(srcText); @@ -1633,9 +1628,9 @@ int main(int argc, char *argv[]) " if ((argc > 1) && (argc == 3) && (strcmp(argv[1], \"--frames\") != 0)) requestedTestFrames = atoi(argv[2]);\n"; char *srcTextUpdated[3] = { 0 }; - srcTextUpdated[0] = TextReplace(srcText, "int main(void)\n{", mainReplaceText); - srcTextUpdated[1] = TextReplace(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)"); - srcTextUpdated[2] = TextReplace(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;"); + srcTextUpdated[0] = TextReplacEx(srcText, "int main(void)\n{", mainReplaceText); + srcTextUpdated[1] = TextReplacEx(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)"); + srcTextUpdated[2] = TextReplacEx(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;"); UnloadFileText(srcText); SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), srcTextUpdated[2]); @@ -2042,10 +2037,8 @@ static int UpdateRequiredFiles(void) // In this case, we focus on web building for: glsl100 if (TextFindIndex(resPaths[r], "glsl%i") > -1) { - char *resPathUpdated = TextReplace(resPaths[r], "glsl%i", "glsl100"); memset(resPaths[r], 0, 256); - strcpy(resPaths[r], resPathUpdated); - RL_FREE(resPathUpdated); + strcpy(resPaths[r], TextReplace(resPaths[r], "glsl%i", "glsl100")); } if (r < (resPathCount - 1)) @@ -2815,7 +2808,7 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf // Update example header title (line #3 - ALWAYS) // String: "* raylib [shaders] example - texture drawing" - exTextUpdated[0] = TextReplaceBetween(exTextUpdatedPtr, "* raylib [", "\n", + exTextUpdated[0] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* raylib [", "\n", TextFormat("%s] example - %s", info->category, exNameFormated)); if (exTextUpdated[0] != NULL) exTextUpdatedPtr = exTextUpdated[0]; @@ -2829,13 +2822,13 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf if (i < info->stars) strcpy(starsText + 3*i, "★"); else strcpy(starsText + 3*i, "☆"); } - exTextUpdated[1] = TextReplaceBetween(exTextUpdatedPtr, "* Example complexity rating: [", "/4\n", + exTextUpdated[1] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example complexity rating: [", "/4\n", TextFormat("%s] %i", starsText, info->stars)); if (exTextUpdated[1] != NULL) exTextUpdatedPtr = exTextUpdated[1]; // Update example creation/update raylib versions // String: "* Example originally created with raylib 2.0, last time updated with raylib 3.7 - exTextUpdated[2] = TextReplaceBetween(exTextUpdatedPtr, "* Example originally created with raylib ", "\n", + exTextUpdated[2] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example originally created with raylib ", "\n", TextFormat("%s, last time updated with raylib %s", info->verCreated, info->verUpdated)); if (exTextUpdated[2] != NULL) exTextUpdatedPtr = exTextUpdated[2]; @@ -2843,27 +2836,27 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf // String: "* Copyright (c) 2019-2026 Contributor Name (@github_user) and Ramon Santamaria (@raysan5)" if (info->yearCreated == info->yearReviewed) { - exTextUpdated[3] = TextReplaceBetween(exTextUpdatedPtr, "Copyright (c) ", ")", + exTextUpdated[3] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "Copyright (c) ", ")", TextFormat("%i %s (@%s", info->yearCreated, info->author, info->authorGitHub)); if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3]; } else { - exTextUpdated[3] = TextReplaceBetween(exTextUpdatedPtr, "Copyright (c) ", ")", + exTextUpdated[3] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "Copyright (c) ", ")", TextFormat("%i-%i %s (@%s", info->yearCreated, info->yearReviewed, info->author, info->authorGitHub)); if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3]; } // Update window title // String: "InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture drawing");" - exTextUpdated[4] = TextReplaceBetween(exTextUpdated[3], "InitWindow(screenWidth, screenHeight, \"", "\");", + exTextUpdated[4] = TextReplaceBetweenAlloc(exTextUpdated[3], "InitWindow(screenWidth, screenHeight, \"", "\");", TextFormat("raylib [%s] example - %s", info->category, exNameFormated)); if (exTextUpdated[4] != NULL) exTextUpdatedPtr = exTextUpdated[4]; // Update contributors names // String: "* Example contributed by Contributor Name (@github_user) and reviewed by Ramon Santamaria (@raysan5)" // WARNING: Not all examples are contributed by someone, so the result of this replace can be NULL (string not found) - exTextUpdated[5] = TextReplaceBetween(exTextUpdatedPtr, "* Example contributed by ", ")", + exTextUpdated[5] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example contributed by ", ")", TextFormat("%s (@%s", info->author, info->authorGitHub)); if (exTextUpdated[5] != NULL) exTextUpdatedPtr = exTextUpdated[5]; From 990a5e0cb47c3fd5f89cc3b33cffec68326a66f3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 20:56:45 +0000 Subject: [PATCH 019/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 69 +++++- tools/rlparser/output/raylib_api.lua | 39 ++- tools/rlparser/output/raylib_api.txt | 336 ++++++++++++++------------ tools/rlparser/output/raylib_api.xml | 26 +- 4 files changed, 300 insertions(+), 170 deletions(-) diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index d4ff5598b..1fbc87a9d 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -7231,7 +7231,7 @@ }, { "name": "ExportImageToMemory", - "description": "Export image to memory buffer", + "description": "Export image to memory buffer, memory must be MemFree()", "returnType": "unsigned char *", "params": [ { @@ -9946,7 +9946,26 @@ }, { "name": "TextReplace", - "description": "Replace text string (WARNING: memory must be freed!)", + "description": "Replace text string with new string", + "returnType": "char *", + "params": [ + { + "type": "const char *", + "name": "text" + }, + { + "type": "const char *", + "name": "search" + }, + { + "type": "const char *", + "name": "replacement" + } + ] + }, + { + "name": "TextReplaceAlloc", + "description": "Replace text string with new string, memory must be MemFree()", "returnType": "char *", "params": [ { @@ -9965,7 +9984,30 @@ }, { "name": "TextReplaceBetween", - "description": "Replace text between two specific strings (WARNING: memory must be freed!)", + "description": "Replace text between two specific strings", + "returnType": "char *", + "params": [ + { + "type": "const char *", + "name": "text" + }, + { + "type": "const char *", + "name": "begin" + }, + { + "type": "const char *", + "name": "end" + }, + { + "type": "const char *", + "name": "replacement" + } + ] + }, + { + "name": "TextReplaceBetweenAlloc", + "description": "Replace text between two specific strings, memory must be MemFree()", "returnType": "char *", "params": [ { @@ -9988,7 +10030,26 @@ }, { "name": "TextInsert", - "description": "Insert text in a position (WARNING: memory must be freed!)", + "description": "Insert text in a defined byte position", + "returnType": "char *", + "params": [ + { + "type": "const char *", + "name": "text" + }, + { + "type": "const char *", + "name": "insert" + }, + { + "type": "int", + "name": "position" + } + ] + }, + { + "name": "TextInsertAlloc", + "description": "Insert text in a defined byte position, memory must be MemFree()", "returnType": "char *", "params": [ { diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index 5e22916b3..398e1b177 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -5596,7 +5596,7 @@ return { }, { name = "ExportImageToMemory", - description = "Export image to memory buffer", + description = "Export image to memory buffer, memory must be MemFree()", returnType = "unsigned char *", params = { {type = "Image", name = "image"}, @@ -7045,7 +7045,17 @@ return { }, { name = "TextReplace", - description = "Replace text string (WARNING: memory must be freed!)", + description = "Replace text string with new string", + returnType = "char *", + params = { + {type = "const char *", name = "text"}, + {type = "const char *", name = "search"}, + {type = "const char *", name = "replacement"} + } + }, + { + name = "TextReplaceAlloc", + description = "Replace text string with new string, memory must be MemFree()", returnType = "char *", params = { {type = "const char *", name = "text"}, @@ -7055,7 +7065,18 @@ return { }, { name = "TextReplaceBetween", - description = "Replace text between two specific strings (WARNING: memory must be freed!)", + description = "Replace text between two specific strings", + returnType = "char *", + params = { + {type = "const char *", name = "text"}, + {type = "const char *", name = "begin"}, + {type = "const char *", name = "end"}, + {type = "const char *", name = "replacement"} + } + }, + { + name = "TextReplaceBetweenAlloc", + description = "Replace text between two specific strings, memory must be MemFree()", returnType = "char *", params = { {type = "const char *", name = "text"}, @@ -7066,7 +7087,17 @@ return { }, { name = "TextInsert", - description = "Insert text in a position (WARNING: memory must be freed!)", + description = "Insert text in a defined byte position", + returnType = "char *", + params = { + {type = "const char *", name = "text"}, + {type = "const char *", name = "insert"}, + {type = "int", name = "position"} + } + }, + { + name = "TextInsertAlloc", + description = "Insert text in a defined byte position, memory must be MemFree()", returnType = "char *", params = { {type = "const char *", name = "text"}, diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index 7943b28f3..d3cd7bcdc 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -1000,7 +1000,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 597 +Functions found: 600 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -2800,7 +2800,7 @@ Function 297: ExportImage() (2 input parameters) Function 298: ExportImageToMemory() (3 input parameters) Name: ExportImageToMemory Return type: unsigned char * - Description: Export image to memory buffer + Description: Export image to memory buffer, memory must be MemFree() Param[1]: image (type: Image) Param[2]: fileType (type: const char *) Param[3]: fileSize (type: int *) @@ -3811,101 +3811,123 @@ Function 444: GetTextBetween() (3 input parameters) Function 445: TextReplace() (3 input parameters) Name: TextReplace Return type: char * - Description: Replace text string (WARNING: memory must be freed!) + Description: Replace text string with new string Param[1]: text (type: const char *) Param[2]: search (type: const char *) Param[3]: replacement (type: const char *) -Function 446: TextReplaceBetween() (4 input parameters) +Function 446: TextReplaceAlloc() (3 input parameters) + Name: TextReplaceAlloc + Return type: char * + Description: Replace text string with new string, memory must be MemFree() + Param[1]: text (type: const char *) + Param[2]: search (type: const char *) + Param[3]: replacement (type: const char *) +Function 447: TextReplaceBetween() (4 input parameters) Name: TextReplaceBetween Return type: char * - Description: Replace text between two specific strings (WARNING: memory must be freed!) + Description: Replace text between two specific strings Param[1]: text (type: const char *) Param[2]: begin (type: const char *) Param[3]: end (type: const char *) Param[4]: replacement (type: const char *) -Function 447: TextInsert() (3 input parameters) +Function 448: TextReplaceBetweenAlloc() (4 input parameters) + Name: TextReplaceBetweenAlloc + Return type: char * + Description: Replace text between two specific strings, memory must be MemFree() + Param[1]: text (type: const char *) + Param[2]: begin (type: const char *) + Param[3]: end (type: const char *) + Param[4]: replacement (type: const char *) +Function 449: TextInsert() (3 input parameters) Name: TextInsert Return type: char * - Description: Insert text in a position (WARNING: memory must be freed!) + Description: Insert text in a defined byte position Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 448: TextJoin() (3 input parameters) +Function 450: TextInsertAlloc() (3 input parameters) + Name: TextInsertAlloc + Return type: char * + Description: Insert text in a defined byte position, memory must be MemFree() + Param[1]: text (type: const char *) + Param[2]: insert (type: const char *) + Param[3]: position (type: int) +Function 451: TextJoin() (3 input parameters) Name: TextJoin Return type: char * Description: Join text strings with delimiter Param[1]: textList (type: char **) Param[2]: count (type: int) Param[3]: delimiter (type: const char *) -Function 449: TextSplit() (3 input parameters) +Function 452: TextSplit() (3 input parameters) Name: TextSplit Return type: char ** Description: Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings Param[1]: text (type: const char *) Param[2]: delimiter (type: char) Param[3]: count (type: int *) -Function 450: TextAppend() (3 input parameters) +Function 453: TextAppend() (3 input parameters) Name: TextAppend Return type: void Description: Append text at specific position and move cursor Param[1]: text (type: char *) Param[2]: append (type: const char *) Param[3]: position (type: int *) -Function 451: TextFindIndex() (2 input parameters) +Function 454: TextFindIndex() (2 input parameters) Name: TextFindIndex Return type: int Description: Find first text occurrence within a string, -1 if not found Param[1]: text (type: const char *) Param[2]: search (type: const char *) -Function 452: TextToUpper() (1 input parameters) +Function 455: TextToUpper() (1 input parameters) Name: TextToUpper Return type: char * Description: Get upper case version of provided string Param[1]: text (type: const char *) -Function 453: TextToLower() (1 input parameters) +Function 456: TextToLower() (1 input parameters) Name: TextToLower Return type: char * Description: Get lower case version of provided string Param[1]: text (type: const char *) -Function 454: TextToPascal() (1 input parameters) +Function 457: TextToPascal() (1 input parameters) Name: TextToPascal Return type: char * Description: Get Pascal case notation version of provided string Param[1]: text (type: const char *) -Function 455: TextToSnake() (1 input parameters) +Function 458: TextToSnake() (1 input parameters) Name: TextToSnake Return type: char * Description: Get Snake case notation version of provided string Param[1]: text (type: const char *) -Function 456: TextToCamel() (1 input parameters) +Function 459: TextToCamel() (1 input parameters) Name: TextToCamel Return type: char * Description: Get Camel case notation version of provided string Param[1]: text (type: const char *) -Function 457: TextToInteger() (1 input parameters) +Function 460: TextToInteger() (1 input parameters) Name: TextToInteger Return type: int Description: Get integer value from text Param[1]: text (type: const char *) -Function 458: TextToFloat() (1 input parameters) +Function 461: TextToFloat() (1 input parameters) Name: TextToFloat Return type: float Description: Get float value from text Param[1]: text (type: const char *) -Function 459: DrawLine3D() (3 input parameters) +Function 462: DrawLine3D() (3 input parameters) Name: DrawLine3D Return type: void Description: Draw a line in 3D world space Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: color (type: Color) -Function 460: DrawPoint3D() (2 input parameters) +Function 463: DrawPoint3D() (2 input parameters) Name: DrawPoint3D Return type: void Description: Draw a point in 3D space, actually a small line Param[1]: position (type: Vector3) Param[2]: color (type: Color) -Function 461: DrawCircle3D() (5 input parameters) +Function 464: DrawCircle3D() (5 input parameters) Name: DrawCircle3D Return type: void Description: Draw a circle in 3D world space @@ -3914,7 +3936,7 @@ Function 461: DrawCircle3D() (5 input parameters) Param[3]: rotationAxis (type: Vector3) Param[4]: rotationAngle (type: float) Param[5]: color (type: Color) -Function 462: DrawTriangle3D() (4 input parameters) +Function 465: DrawTriangle3D() (4 input parameters) Name: DrawTriangle3D Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -3922,14 +3944,14 @@ Function 462: DrawTriangle3D() (4 input parameters) Param[2]: v2 (type: Vector3) Param[3]: v3 (type: Vector3) Param[4]: color (type: Color) -Function 463: DrawTriangleStrip3D() (3 input parameters) +Function 466: DrawTriangleStrip3D() (3 input parameters) Name: DrawTriangleStrip3D Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector3 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 464: DrawCube() (5 input parameters) +Function 467: DrawCube() (5 input parameters) Name: DrawCube Return type: void Description: Draw cube @@ -3938,14 +3960,14 @@ Function 464: DrawCube() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 465: DrawCubeV() (3 input parameters) +Function 468: DrawCubeV() (3 input parameters) Name: DrawCubeV Return type: void Description: Draw cube (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 466: DrawCubeWires() (5 input parameters) +Function 469: DrawCubeWires() (5 input parameters) Name: DrawCubeWires Return type: void Description: Draw cube wires @@ -3954,21 +3976,21 @@ Function 466: DrawCubeWires() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 467: DrawCubeWiresV() (3 input parameters) +Function 470: DrawCubeWiresV() (3 input parameters) Name: DrawCubeWiresV Return type: void Description: Draw cube wires (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 468: DrawSphere() (3 input parameters) +Function 471: DrawSphere() (3 input parameters) Name: DrawSphere Return type: void Description: Draw sphere Param[1]: centerPos (type: Vector3) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 469: DrawSphereEx() (5 input parameters) +Function 472: DrawSphereEx() (5 input parameters) Name: DrawSphereEx Return type: void Description: Draw sphere with extended parameters @@ -3977,7 +3999,7 @@ Function 469: DrawSphereEx() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 470: DrawSphereWires() (5 input parameters) +Function 473: DrawSphereWires() (5 input parameters) Name: DrawSphereWires Return type: void Description: Draw sphere wires @@ -3986,7 +4008,7 @@ Function 470: DrawSphereWires() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 471: DrawCylinder() (6 input parameters) +Function 474: DrawCylinder() (6 input parameters) Name: DrawCylinder Return type: void Description: Draw a cylinder/cone @@ -3996,7 +4018,7 @@ Function 471: DrawCylinder() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 472: DrawCylinderEx() (6 input parameters) +Function 475: DrawCylinderEx() (6 input parameters) Name: DrawCylinderEx Return type: void Description: Draw a cylinder with base at startPos and top at endPos @@ -4006,7 +4028,7 @@ Function 472: DrawCylinderEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 473: DrawCylinderWires() (6 input parameters) +Function 476: DrawCylinderWires() (6 input parameters) Name: DrawCylinderWires Return type: void Description: Draw a cylinder/cone wires @@ -4016,7 +4038,7 @@ Function 473: DrawCylinderWires() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 474: DrawCylinderWiresEx() (6 input parameters) +Function 477: DrawCylinderWiresEx() (6 input parameters) Name: DrawCylinderWiresEx Return type: void Description: Draw a cylinder wires with base at startPos and top at endPos @@ -4026,7 +4048,7 @@ Function 474: DrawCylinderWiresEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 475: DrawCapsule() (6 input parameters) +Function 478: DrawCapsule() (6 input parameters) Name: DrawCapsule Return type: void Description: Draw a capsule with the center of its sphere caps at startPos and endPos @@ -4036,7 +4058,7 @@ Function 475: DrawCapsule() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 476: DrawCapsuleWires() (6 input parameters) +Function 479: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires Return type: void Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos @@ -4046,51 +4068,51 @@ Function 476: DrawCapsuleWires() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 477: DrawPlane() (3 input parameters) +Function 480: DrawPlane() (3 input parameters) Name: DrawPlane Return type: void Description: Draw a plane XZ Param[1]: centerPos (type: Vector3) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 478: DrawRay() (2 input parameters) +Function 481: DrawRay() (2 input parameters) Name: DrawRay Return type: void Description: Draw a ray line Param[1]: ray (type: Ray) Param[2]: color (type: Color) -Function 479: DrawGrid() (2 input parameters) +Function 482: DrawGrid() (2 input parameters) Name: DrawGrid Return type: void Description: Draw a grid (centered at (0, 0, 0)) Param[1]: slices (type: int) Param[2]: spacing (type: float) -Function 480: LoadModel() (1 input parameters) +Function 483: LoadModel() (1 input parameters) Name: LoadModel Return type: Model Description: Load model from files (meshes and materials) Param[1]: fileName (type: const char *) -Function 481: LoadModelFromMesh() (1 input parameters) +Function 484: LoadModelFromMesh() (1 input parameters) Name: LoadModelFromMesh Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 482: IsModelValid() (1 input parameters) +Function 485: IsModelValid() (1 input parameters) Name: IsModelValid Return type: bool Description: Check if a model is valid (loaded in GPU, VAO/VBOs) Param[1]: model (type: Model) -Function 483: UnloadModel() (1 input parameters) +Function 486: UnloadModel() (1 input parameters) Name: UnloadModel Return type: void Description: Unload model (including meshes) from memory (RAM and/or VRAM) Param[1]: model (type: Model) -Function 484: GetModelBoundingBox() (1 input parameters) +Function 487: GetModelBoundingBox() (1 input parameters) Name: GetModelBoundingBox Return type: BoundingBox Description: Compute model bounding box limits (considers all meshes) Param[1]: model (type: Model) -Function 485: DrawModel() (4 input parameters) +Function 488: DrawModel() (4 input parameters) Name: DrawModel Return type: void Description: Draw a model (with texture if set) @@ -4098,7 +4120,7 @@ Function 485: DrawModel() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 486: DrawModelEx() (6 input parameters) +Function 489: DrawModelEx() (6 input parameters) Name: DrawModelEx Return type: void Description: Draw a model with extended parameters @@ -4108,7 +4130,7 @@ Function 486: DrawModelEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 487: DrawModelWires() (4 input parameters) +Function 490: DrawModelWires() (4 input parameters) Name: DrawModelWires Return type: void Description: Draw a model wires (with texture if set) @@ -4116,7 +4138,7 @@ Function 487: DrawModelWires() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 488: DrawModelWiresEx() (6 input parameters) +Function 491: DrawModelWiresEx() (6 input parameters) Name: DrawModelWiresEx Return type: void Description: Draw a model wires (with texture if set) with extended parameters @@ -4126,13 +4148,13 @@ Function 488: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 489: DrawBoundingBox() (2 input parameters) +Function 492: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 490: DrawBillboard() (5 input parameters) +Function 493: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -4141,7 +4163,7 @@ Function 490: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 491: DrawBillboardRec() (6 input parameters) +Function 494: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -4151,7 +4173,7 @@ Function 491: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 492: DrawBillboardPro() (9 input parameters) +Function 495: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -4164,13 +4186,13 @@ Function 492: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 493: UploadMesh() (2 input parameters) +Function 496: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 494: UpdateMeshBuffer() (5 input parameters) +Function 497: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4179,19 +4201,19 @@ Function 494: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 495: UnloadMesh() (1 input parameters) +Function 498: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 496: DrawMesh() (3 input parameters) +Function 499: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 497: DrawMeshInstanced() (4 input parameters) +Function 500: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4199,35 +4221,35 @@ Function 497: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 498: GetMeshBoundingBox() (1 input parameters) +Function 501: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 499: GenMeshTangents() (1 input parameters) +Function 502: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 500: ExportMesh() (2 input parameters) +Function 503: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 501: ExportMeshAsCode() (2 input parameters) +Function 504: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 502: GenMeshPoly() (2 input parameters) +Function 505: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 503: GenMeshPlane() (4 input parameters) +Function 506: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4235,42 +4257,42 @@ Function 503: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 504: GenMeshCube() (3 input parameters) +Function 507: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 505: GenMeshSphere() (3 input parameters) +Function 508: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 506: GenMeshHemiSphere() (3 input parameters) +Function 509: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 507: GenMeshCylinder() (3 input parameters) +Function 510: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 508: GenMeshCone() (3 input parameters) +Function 511: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 509: GenMeshTorus() (4 input parameters) +Function 512: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4278,7 +4300,7 @@ Function 509: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 510: GenMeshKnot() (4 input parameters) +Function 513: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4286,67 +4308,67 @@ Function 510: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 511: GenMeshHeightmap() (2 input parameters) +Function 514: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 512: GenMeshCubicmap() (2 input parameters) +Function 515: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 513: LoadMaterials() (2 input parameters) +Function 516: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 514: LoadMaterialDefault() (0 input parameters) +Function 517: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 515: IsMaterialValid() (1 input parameters) +Function 518: IsMaterialValid() (1 input parameters) Name: IsMaterialValid Return type: bool Description: Check if a material is valid (shader assigned, map textures loaded in GPU) Param[1]: material (type: Material) -Function 516: UnloadMaterial() (1 input parameters) +Function 519: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 517: SetMaterialTexture() (3 input parameters) +Function 520: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 518: SetModelMeshMaterial() (3 input parameters) +Function 521: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 519: LoadModelAnimations() (2 input parameters) +Function 522: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 520: UpdateModelAnimation() (3 input parameters) +Function 523: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose (vertex buffers and bone matrices) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: float) -Function 521: UpdateModelAnimationEx() (6 input parameters) +Function 524: UpdateModelAnimationEx() (6 input parameters) Name: UpdateModelAnimationEx Return type: void Description: Update model animation pose, blending two animations @@ -4356,19 +4378,19 @@ Function 521: UpdateModelAnimationEx() (6 input parameters) Param[4]: animB (type: ModelAnimation) Param[5]: frameB (type: float) Param[6]: blend (type: float) -Function 522: UnloadModelAnimations() (2 input parameters) +Function 525: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 523: IsModelAnimationValid() (2 input parameters) +Function 526: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 524: CheckCollisionSpheres() (4 input parameters) +Function 527: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4376,40 +4398,40 @@ Function 524: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 525: CheckCollisionBoxes() (2 input parameters) +Function 528: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 526: CheckCollisionBoxSphere() (3 input parameters) +Function 529: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 527: GetRayCollisionSphere() (3 input parameters) +Function 530: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 528: GetRayCollisionBox() (2 input parameters) +Function 531: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 529: GetRayCollisionMesh() (3 input parameters) +Function 532: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 530: GetRayCollisionTriangle() (4 input parameters) +Function 533: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4417,7 +4439,7 @@ Function 530: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 531: GetRayCollisionQuad() (5 input parameters) +Function 534: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4426,158 +4448,158 @@ Function 531: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 532: InitAudioDevice() (0 input parameters) +Function 535: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 533: CloseAudioDevice() (0 input parameters) +Function 536: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 534: IsAudioDeviceReady() (0 input parameters) +Function 537: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 535: SetMasterVolume() (1 input parameters) +Function 538: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 536: GetMasterVolume() (0 input parameters) +Function 539: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 537: LoadWave() (1 input parameters) +Function 540: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 538: LoadWaveFromMemory() (3 input parameters) +Function 541: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 539: IsWaveValid() (1 input parameters) +Function 542: IsWaveValid() (1 input parameters) Name: IsWaveValid Return type: bool Description: Checks if wave data is valid (data loaded and parameters) Param[1]: wave (type: Wave) -Function 540: LoadSound() (1 input parameters) +Function 543: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 541: LoadSoundFromWave() (1 input parameters) +Function 544: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 542: LoadSoundAlias() (1 input parameters) +Function 545: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 543: IsSoundValid() (1 input parameters) +Function 546: IsSoundValid() (1 input parameters) Name: IsSoundValid Return type: bool Description: Checks if a sound is valid (data loaded and buffers initialized) Param[1]: sound (type: Sound) -Function 544: UpdateSound() (3 input parameters) +Function 547: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data (default data format: 32 bit float, stereo) Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 545: UnloadWave() (1 input parameters) +Function 548: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 546: UnloadSound() (1 input parameters) +Function 549: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 547: UnloadSoundAlias() (1 input parameters) +Function 550: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload a sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 548: ExportWave() (2 input parameters) +Function 551: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 549: ExportWaveAsCode() (2 input parameters) +Function 552: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 550: PlaySound() (1 input parameters) +Function 553: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 551: StopSound() (1 input parameters) +Function 554: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 552: PauseSound() (1 input parameters) +Function 555: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 553: ResumeSound() (1 input parameters) +Function 556: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 554: IsSoundPlaying() (1 input parameters) +Function 557: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 555: SetSoundVolume() (2 input parameters) +Function 558: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 556: SetSoundPitch() (2 input parameters) +Function 559: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 557: SetSoundPan() (2 input parameters) +Function 560: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (-1.0 left, 0.0 center, 1.0 right) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 558: WaveCopy() (1 input parameters) +Function 561: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 559: WaveCrop() (3 input parameters) +Function 562: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 560: WaveFormat() (4 input parameters) +Function 563: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4585,203 +4607,203 @@ Function 560: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 561: LoadWaveSamples() (1 input parameters) +Function 564: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 562: UnloadWaveSamples() (1 input parameters) +Function 565: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 563: LoadMusicStream() (1 input parameters) +Function 566: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 564: LoadMusicStreamFromMemory() (3 input parameters) +Function 567: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 565: IsMusicValid() (1 input parameters) +Function 568: IsMusicValid() (1 input parameters) Name: IsMusicValid Return type: bool Description: Checks if a music stream is valid (context and buffers initialized) Param[1]: music (type: Music) -Function 566: UnloadMusicStream() (1 input parameters) +Function 569: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 567: PlayMusicStream() (1 input parameters) +Function 570: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 568: IsMusicStreamPlaying() (1 input parameters) +Function 571: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 569: UpdateMusicStream() (1 input parameters) +Function 572: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 570: StopMusicStream() (1 input parameters) +Function 573: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 571: PauseMusicStream() (1 input parameters) +Function 574: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 572: ResumeMusicStream() (1 input parameters) +Function 575: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 573: SeekMusicStream() (2 input parameters) +Function 576: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 574: SetMusicVolume() (2 input parameters) +Function 577: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 575: SetMusicPitch() (2 input parameters) +Function 578: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for a music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 576: SetMusicPan() (2 input parameters) +Function 579: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for a music (-1.0 left, 0.0 center, 1.0 right) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 577: GetMusicTimeLength() (1 input parameters) +Function 580: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 578: GetMusicTimePlayed() (1 input parameters) +Function 581: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 579: LoadAudioStream() (3 input parameters) +Function 582: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 580: IsAudioStreamValid() (1 input parameters) +Function 583: IsAudioStreamValid() (1 input parameters) Name: IsAudioStreamValid Return type: bool Description: Checks if an audio stream is valid (buffers initialized) Param[1]: stream (type: AudioStream) -Function 581: UnloadAudioStream() (1 input parameters) +Function 584: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 582: UpdateAudioStream() (3 input parameters) +Function 585: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 583: IsAudioStreamProcessed() (1 input parameters) +Function 586: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 584: PlayAudioStream() (1 input parameters) +Function 587: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 585: PauseAudioStream() (1 input parameters) +Function 588: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 586: ResumeAudioStream() (1 input parameters) +Function 589: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 587: IsAudioStreamPlaying() (1 input parameters) +Function 590: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 588: StopAudioStream() (1 input parameters) +Function 591: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 589: SetAudioStreamVolume() (2 input parameters) +Function 592: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 590: SetAudioStreamPitch() (2 input parameters) +Function 593: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 591: SetAudioStreamPan() (2 input parameters) +Function 594: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 592: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 595: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 593: SetAudioStreamCallback() (2 input parameters) +Function 596: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 594: AttachAudioStreamProcessor() (2 input parameters) +Function 597: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives frames x 2 samples as 'float' (stereo) Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 595: DetachAudioStreamProcessor() (2 input parameters) +Function 598: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 596: AttachAudioMixedProcessor() (1 input parameters) +Function 599: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives frames x 2 samples as 'float' (stereo) Param[1]: processor (type: AudioCallback) -Function 597: DetachAudioMixedProcessor() (1 input parameters) +Function 600: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 408ff18c7..62d8bdfaf 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -682,7 +682,7 @@ - + @@ -1809,7 +1809,7 @@ - + @@ -2525,18 +2525,34 @@ - + - + + + + + + - + + + + + + + + + + + + From 4142c89baab4639cfcf9a51a37a37d14f0dbefba Mon Sep 17 00:00:00 2001 From: mjt Date: Fri, 27 Mar 2026 22:58:28 +0200 Subject: [PATCH 020/185] Update rcore.c comment (#5700) --- src/rcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rcore.c b/src/rcore.c index 3454b65ba..dc31a103b 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -1227,7 +1227,7 @@ void UnloadVrStereoConfig(VrStereoConfig config) //---------------------------------------------------------------------------------- // Load shader from files and bind default locations -// NOTE: If shader string is NULL, using default vertex/fragment shaders +// NOTE: If shader filename is NULL, using default vertex/fragment shaders Shader LoadShader(const char *vsFileName, const char *fsFileName) { Shader shader = { 0 }; From 5fad835ff1e8d473ee3a41ab365a93e548f2b5a3 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 28 Mar 2026 23:54:51 +0100 Subject: [PATCH 021/185] Update rcore.c --- src/rcore.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index dc31a103b..c7ff22951 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -821,7 +821,7 @@ int GetRenderWidth(void) { int width = 0; - if (CORE.Window.usingFbo) return CORE.Window.currentFbo.width; + if (CORE.Window.usingFbo) width = CORE.Window.currentFbo.width; else width = CORE.Window.render.width; return width; @@ -832,7 +832,7 @@ int GetRenderHeight(void) { int height = 0; - if (CORE.Window.usingFbo) return CORE.Window.currentFbo.height; + if (CORE.Window.usingFbo) height = CORE.Window.currentFbo.height; else height = CORE.Window.render.height; return height; From 8c44ea503281a4a3e90a1c13522ee0a94b8107a1 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 00:37:01 +0100 Subject: [PATCH 022/185] Code gardening REVIEWED: Some early returns, avoid if possible REVIEWED: Some return variable names, for consistency, rename `success` to `result` --- src/raudio.c | 107 +++++++++++++++++++++++++----------------------- src/rcore.c | 54 ++++++++++++------------ src/rlgl.h | 6 +-- src/rmodels.c | 14 +++---- src/rshapes.c | 50 ++++++++++++---------- src/rtext.c | 66 ++++++++++++++--------------- src/rtextures.c | 70 +++++++++++++++---------------- 7 files changed, 188 insertions(+), 179 deletions(-) diff --git a/src/raudio.c b/src/raudio.c index 937c33ac3..00e819466 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -963,20 +963,18 @@ Sound LoadSoundFromWave(Wave wave) if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed to get frame count for format conversion"); AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, frameCount, AUDIO_BUFFER_USAGE_STATIC); - if (audioBuffer == NULL) + if (audioBuffer != NULL) { - TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer"); - return sound; // early return to avoid dereferencing the audioBuffer null pointer + frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, frameCount, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, wave.data, frameCountIn, formatIn, wave.channels, wave.sampleRate); + if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed format conversion"); + + sound.frameCount = frameCount; + sound.stream.sampleRate = AUDIO.System.device.sampleRate; + sound.stream.sampleSize = 32; + sound.stream.channels = AUDIO_DEVICE_CHANNELS; + sound.stream.buffer = audioBuffer; } - - frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, frameCount, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, wave.data, frameCountIn, formatIn, wave.channels, wave.sampleRate); - if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed format conversion"); - - sound.frameCount = frameCount; - sound.stream.sampleRate = AUDIO.System.device.sampleRate; - sound.stream.sampleSize = 32; - sound.stream.channels = AUDIO_DEVICE_CHANNELS; - sound.stream.buffer = audioBuffer; + else TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer"); } return sound; @@ -992,25 +990,23 @@ Sound LoadSoundAlias(Sound source) { AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, 0, AUDIO_BUFFER_USAGE_STATIC); - if (audioBuffer == NULL) + if (audioBuffer != NULL) { - TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer"); - return sound; // Early return to avoid dereferencing the audioBuffer null pointer + audioBuffer->sizeInFrames = source.stream.buffer->sizeInFrames; + audioBuffer->data = source.stream.buffer->data; + + // Initalize the buffer as if it was new + audioBuffer->volume = 1.0f; + audioBuffer->pitch = 1.0f; + audioBuffer->pan = 0.0f; // Center + + sound.frameCount = source.frameCount; + sound.stream.sampleRate = AUDIO.System.device.sampleRate; + sound.stream.sampleSize = 32; + sound.stream.channels = AUDIO_DEVICE_CHANNELS; + sound.stream.buffer = audioBuffer; } - - audioBuffer->sizeInFrames = source.stream.buffer->sizeInFrames; - audioBuffer->data = source.stream.buffer->data; - - // Initalize the buffer as if it was new - audioBuffer->volume = 1.0f; - audioBuffer->pitch = 1.0f; - audioBuffer->pan = 0.0f; // Center - - sound.frameCount = source.frameCount; - sound.stream.sampleRate = AUDIO.System.device.sampleRate; - sound.stream.sampleSize = 32; - sound.stream.channels = AUDIO_DEVICE_CHANNELS; - sound.stream.buffer = audioBuffer; + else TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer"); } return sound; @@ -1071,7 +1067,7 @@ void UpdateSound(Sound sound, const void *data, int frameCount) // Export wave data to file bool ExportWave(Wave wave, const char *fileName) { - bool success = false; + bool result = false; if (false) { } #if SUPPORT_FILEFORMAT_WAV @@ -1088,11 +1084,11 @@ bool ExportWave(Wave wave, const char *fileName) void *fileData = NULL; size_t fileDataSize = 0; - success = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL); - if (success) success = (int)drwav_write_pcm_frames(&wav, wave.frameCount, wave.data); + result = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL); + if (result) result = (int)drwav_write_pcm_frames(&wav, wave.frameCount, wave.data); drwav_result result = drwav_uninit(&wav); - if (result == DRWAV_SUCCESS) success = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize); + if (result == DRWAV_SUCCESS) result = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize); drwav_free(fileData, NULL); } @@ -1108,7 +1104,7 @@ bool ExportWave(Wave wave, const char *fileName) qoa.samples = wave.frameCount; int bytesWritten = qoa_write(fileName, (const short *)wave.data, &qoa); - if (bytesWritten > 0) success = true; + if (bytesWritten > 0) result = true; } else TRACELOG(LOG_WARNING, "AUDIO: Wave data must be 16 bit per sample for QOA format export"); } @@ -1117,19 +1113,19 @@ bool ExportWave(Wave wave, const char *fileName) { // Export raw sample data (without header) // NOTE: It's up to the user to track wave parameters - success = SaveFileData(fileName, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8); + result = SaveFileData(fileName, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8); } - if (success) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName); + if (result) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName); else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave data", fileName); - return success; + return result; } // Export wave sample data to code (.h) bool ExportWaveAsCode(Wave wave, const char *fileName) { - bool success = false; + bool result = false; #ifndef TEXT_BYTES_PER_LINE #define TEXT_BYTES_PER_LINE 20 @@ -1183,14 +1179,14 @@ bool ExportWaveAsCode(Wave wave, const char *fileName) } // NOTE: Text data length exported is determined by '\0' (NULL) character - success = SaveFileText(fileName, txtData); + result = SaveFileText(fileName, txtData); RL_FREE(txtData); - if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave as code exported successfully", fileName); + if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave as code exported successfully", fileName); else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave as code", fileName); - return success; + return result; } // Play a sound @@ -2187,12 +2183,15 @@ void UpdateAudioStream(AudioStream stream, const void *data, int frameCount) // Check if any audio stream buffers requires refill bool IsAudioStreamProcessed(AudioStream stream) { - if (stream.buffer == NULL) return false; - bool result = false; - ma_mutex_lock(&AUDIO.System.lock); - result = stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1]; - ma_mutex_unlock(&AUDIO.System.lock); + + if (stream.buffer != NULL) + { + ma_mutex_lock(&AUDIO.System.lock); + result = stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1]; + ma_mutex_unlock(&AUDIO.System.lock); + } + return result; } @@ -2885,6 +2884,8 @@ static unsigned char *LoadFileData(const char *fileName, int *dataSize) // Save data to file from buffer static bool SaveFileData(const char *fileName, void *data, int dataSize) { + bool result = true; + if (fileName != NULL) { FILE *file = fopen(fileName, "wb"); @@ -2902,21 +2903,23 @@ static bool SaveFileData(const char *fileName, void *data, int dataSize) else { TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName); - return false; + result = false; } } else { TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid"); - return false; + result = false; } - return true; + return result; } // Save text data to file (write), string must be '\0' terminated static bool SaveFileText(const char *fileName, char *text) { + bool result = true; + if (fileName != NULL) { FILE *file = fopen(fileName, "wt"); @@ -2934,16 +2937,16 @@ static bool SaveFileText(const char *fileName, char *text) else { TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName); - return false; + result = false; } } else { TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid"); - return false; + result = false; } - return true; + return result; } #endif diff --git a/src/rcore.c b/src/rcore.c index c7ff22951..1f6699af9 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -1621,18 +1621,20 @@ int GetFPS(void) for (int i = 0; i < FPS_CAPTURE_FRAMES_COUNT; i++) history[i] = 0; } - if (fpsFrame == 0) return 0; - - if ((GetTime() - last) > FPS_STEP) + if (fpsFrame != 0) { - last = (float)GetTime(); - index = (index + 1)%FPS_CAPTURE_FRAMES_COUNT; - average -= history[index]; - history[index] = fpsFrame/FPS_CAPTURE_FRAMES_COUNT; - average += history[index]; - } + if ((GetTime() - last) > FPS_STEP) + { + last = (float)GetTime(); + index = (index + 1)%FPS_CAPTURE_FRAMES_COUNT; + average -= history[index]; + history[index] = fpsFrame/FPS_CAPTURE_FRAMES_COUNT; + average += history[index]; + } - fps = (int)roundf(1.0f/average); + fps = (int)roundf(1.0f/average); + } + else fps = 0; #endif return fps; @@ -2025,7 +2027,7 @@ void UnloadFileData(unsigned char *data) // Save data to file from buffer bool SaveFileData(const char *fileName, void *data, int dataSize) { - bool success = false; + bool result = false; if (fileName != NULL) { @@ -2043,20 +2045,20 @@ bool SaveFileData(const char *fileName, void *data, int dataSize) else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName); else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName); - int result = fclose(file); - if (result == 0) success = true; + int closed = fclose(file); + if (closed == 0) result = true; } else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName); } else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid"); - return success; + return result; } // Export data to code (.h), returns true on success bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName) { - bool success = false; + bool result = false; #ifndef TEXT_BYTES_PER_LINE #define TEXT_BYTES_PER_LINE 20 @@ -2096,14 +2098,14 @@ bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileN byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[dataSize - 1]); // NOTE: Text data size exported is determined by '\0' (NULL) character - success = SaveFileText(fileName, txtData); + result = SaveFileText(fileName, txtData); RL_FREE(txtData); - if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName); + if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName); else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export data as code", fileName); - return success; + return result; } // Load text data from file, returns a '\0' terminated string @@ -2166,7 +2168,7 @@ void UnloadFileText(char *text) // Save text data to file (write), string must be '\0' terminated bool SaveFileText(const char *fileName, const char *text) { - bool success = false; + bool result = false; if (fileName != NULL) { @@ -2181,14 +2183,14 @@ bool SaveFileText(const char *fileName, const char *text) if (count < 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write text file", fileName); else TRACELOG(LOG_INFO, "FILEIO: [%s] Text file saved successfully", fileName); - int result = fclose(file); - if (result == 0) success = true; + int closed = fclose(file); + if (closed == 0) result = true; } else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName); } else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid"); - return success; + return result; } // File access custom callbacks @@ -3628,7 +3630,7 @@ void UnloadAutomationEventList(AutomationEventList list) // Export automation events list as text file bool ExportAutomationEventList(AutomationEventList list, const char *fileName) { - bool success = false; + bool result = false; #if SUPPORT_AUTOMATION_EVENTS // Export events as binary file @@ -3646,7 +3648,7 @@ bool ExportAutomationEventList(AutomationEventList list, const char *fileName) memcpy(binBuffer + offset, list.events, sizeof(AutomationEvent)*list.count); offset += sizeof(AutomationEvent)*list.count; - success = SaveFileData(TextFormat("%s.rae",fileName), binBuffer, binarySize); + result = SaveFileData(TextFormat("%s.rae",fileName), binBuffer, binarySize); RL_FREE(binBuffer); } */ @@ -3677,12 +3679,12 @@ bool ExportAutomationEventList(AutomationEventList list, const char *fileName) } // NOTE: Text data size exported is determined by '\0' (NULL) character - success = SaveFileText(fileName, txtData); + result = SaveFileText(fileName, txtData); RL_FREE(txtData); #endif - return success; + return result; } // Setup automation event list to record to diff --git a/src/rlgl.h b/src/rlgl.h index ce10b2f64..845f75d26 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4647,14 +4647,14 @@ void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSi // Get SSBO buffer size unsigned int rlGetShaderBufferSize(unsigned int id) { + unsigned int result = 0; #if defined(GRAPHICS_API_OPENGL_43) GLint64 size = 0; glBindBuffer(GL_SHADER_STORAGE_BUFFER, id); glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size); - return (size > 0)? (unsigned int)size : 0; -#else - return 0; + if (size > 0) result = (unsigned int)size; #endif + return result; } // Read SSBO buffer data (GPU->CPU) diff --git a/src/rmodels.c b/src/rmodels.c index a662a2dc2..6c1e0482e 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1949,7 +1949,7 @@ void UnloadMesh(Mesh mesh) // Export mesh data to file bool ExportMesh(Mesh mesh, const char *fileName) { - bool success = false; + bool result = false; if (IsFileExtension(fileName, ".obj")) { @@ -2013,7 +2013,7 @@ bool ExportMesh(Mesh mesh, const char *fileName) } // NOTE: Text data length exported is determined by '\0' (NULL) character - success = SaveFileText(fileName, txtData); + result = SaveFileText(fileName, txtData); RL_FREE(txtData); } @@ -2022,13 +2022,13 @@ bool ExportMesh(Mesh mesh, const char *fileName) // TODO: Support additional file formats to export mesh vertex data } - return success; + return result; } // Export mesh as code file (.h) defining multiple arrays of vertex attributes bool ExportMeshAsCode(Mesh mesh, const char *fileName) { - bool success = false; + bool result = false; #ifndef TEXT_BYTES_PER_LINE #define TEXT_BYTES_PER_LINE 20 @@ -2112,14 +2112,14 @@ bool ExportMeshAsCode(Mesh mesh, const char *fileName) //----------------------------------------------------------------------------------------- // NOTE: Text data size exported is determined by '\0' (NULL) character - success = SaveFileText(fileName, txtData); + result = SaveFileText(fileName, txtData); RL_FREE(txtData); - //if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName); + //if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName); //else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName); - return success; + return result; } #if SUPPORT_FILEFORMAT_OBJ || SUPPORT_FILEFORMAT_MTL diff --git a/src/rshapes.c b/src/rshapes.c index e24689040..268da45f1 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -2348,16 +2348,18 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec) float dx = fabsf(center.x - recCenterX); float dy = fabsf(center.y - recCenterY); - if (dx > (rec.width/2.0f + radius)) { return false; } - if (dy > (rec.height/2.0f + radius)) { return false; } + if ((dx <= (rec.width/2.0f + radius)) && (dy <= (rec.height/2.0f + radius))) + { + if (dx <= (rec.width/2.0f)) collision = true; + else if (dy <= (rec.height/2.0f)) collision = true; + else + { + float cornerDistanceSq = (dx - rec.width/2.0f)*(dx - rec.width/2.0f) + + (dy - rec.height/2.0f)*(dy - rec.height/2.0f); - if (dx <= (rec.width/2.0f)) { return true; } - if (dy <= (rec.height/2.0f)) { return true; } - - float cornerDistanceSq = (dx - rec.width/2.0f)*(dx - rec.width/2.0f) + - (dy - rec.height/2.0f)*(dy - rec.height/2.0f); - - collision = (cornerDistanceSq <= (radius*radius)); + collision = (cornerDistanceSq <= (radius*radius)); + } + } return collision; } @@ -2418,25 +2420,31 @@ bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshol // Check if circle collides with a line created between two points [p1] and [p2] bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2) { + bool collision = false; + float dx = p1.x - p2.x; float dy = p1.y - p2.y; if ((fabsf(dx) + fabsf(dy)) <= FLT_EPSILON) { - return CheckCollisionCircles(p1, 0, center, radius); + collision = CheckCollisionCircles(p1, 0, center, radius); + } + else + { + float lengthSQ = ((dx*dx) + (dy*dy)); + float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ); + + if (dotProduct > 1.0f) dotProduct = 1.0f; + else if (dotProduct < 0.0f) dotProduct = 0.0f; + + float dx2 = (p1.x - (dotProduct*(dx))) - center.x; + float dy2 = (p1.y - (dotProduct*(dy))) - center.y; + float distanceSQ = ((dx2*dx2) + (dy2*dy2)); + + if (distanceSQ <= radius*radius) collision = true; } - float lengthSQ = ((dx*dx) + (dy*dy)); - float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ); - - if (dotProduct > 1.0f) dotProduct = 1.0f; - else if (dotProduct < 0.0f) dotProduct = 0.0f; - - float dx2 = (p1.x - (dotProduct*(dx))) - center.x; - float dy2 = (p1.y - (dotProduct*(dy))) - center.y; - float distanceSQ = ((dx2*dx2) + (dy2*dy2)); - - return (distanceSQ <= radius*radius); + return collision; } // Get collision rectangle for two rectangles collision diff --git a/src/rtext.c b/src/rtext.c index a6ca65113..3f4c993c3 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -447,7 +447,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar) int j = 0; while (((lineSpacing + j) < image.height) && - !COLOR_EQUAL(pixels[(lineSpacing + j)*image.width + charSpacing], key)) j++; + !COLOR_EQUAL(pixels[(lineSpacing + j)*image.width + charSpacing], key)) j++; charHeight = j; @@ -1017,7 +1017,7 @@ void UnloadFont(Font font) // Export font as code file, returns true on success bool ExportFontAsCode(Font font, const char *fileName) { - bool success = false; + bool result = false; #ifndef TEXT_BYTES_PER_LINE #define TEXT_BYTES_PER_LINE 20 @@ -1159,14 +1159,14 @@ bool ExportFontAsCode(Font font, const char *fileName) UnloadImage(image); // NOTE: Text data size exported is determined by '\0' (NULL) character - success = SaveFileText(fileName, txtData); + result = SaveFileText(fileName, txtData); RL_FREE(txtData); - if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Font as code exported successfully", fileName); + if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Font as code exported successfully", fileName); else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export font as code", fileName); - return success; + return result; } // Draw current FPS @@ -1395,8 +1395,7 @@ Vector2 MeasureTextCodepoints(Font font, const int *codepoints, int length, floa { Vector2 textSize = { 0 }; - // Security check - if ((font.texture.id == 0) || (codepoints == NULL) || (length == 0)) return textSize; + if ((font.texture.id == 0) || (codepoints == NULL) || (length == 0)) return textSize; // Security check float textWidth = 0.0f; // Used to count longer text line width @@ -1699,17 +1698,18 @@ const char *TextSubtext(const char *text, int position, int length) { int textLength = TextLength(text); - if (position >= textLength) return buffer; // First char is already '\0' by memset + if (position < textLength) + { + int maxLength = textLength - position; + if (length > maxLength) length = maxLength; + if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1; - int maxLength = textLength - position; - if (length > maxLength) length = maxLength; - if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1; + // NOTE: Alternative: memcpy(buffer, text + position, length) - // NOTE: Alternative: memcpy(buffer, text + position, length) + for (int c = 0; c < length; c++) buffer[c] = text[position + c]; - for (int c = 0; c < length; c++) buffer[c] = text[position + c]; - - buffer[length] = '\0'; + buffer[length] = '\0'; + } } return buffer; @@ -1763,8 +1763,8 @@ char *GetTextBetween(const char *text, const char *begin, const char *end) // NOTE: Limited text replace functionality, using static string char *TextReplace(const char *text, const char *search, const char *replacement) { - static char result[MAX_TEXT_BUFFER_LENGTH] = { 0 }; - memset(result, 0, MAX_TEXT_BUFFER_LENGTH); + static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 }; + memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH); if ((text != NULL) && (search != NULL) && (search[0] != '\0')) { @@ -1790,7 +1790,7 @@ char *TextReplace(const char *text, const char *search, const char *replacement) { // TODO: Allow copying data replaced up to maximum buffer size and stop - tempPtr = result; // Point to result start + tempPtr = buffer; // Point to result start // First time through the loop, all the variable are set correctly from here on, // - 'temp' points to the end of the result string @@ -1821,7 +1821,7 @@ char *TextReplace(const char *text, const char *search, const char *replacement) else TRACELOG(LOG_WARNING, "Text with replacement is longer than internal buffer, use TextReplaceAlloc()"); } - return result; + return buffer; } // Replace text string @@ -1894,8 +1894,8 @@ char *TextReplaceAlloc(const char *text, const char *search, const char *replace // NOTE: If (replacement == NULL) removes "begin"[ ]"end" text char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement) { - static char result[MAX_TEXT_BUFFER_LENGTH] = { 0 }; - memset(result, 0, MAX_TEXT_BUFFER_LENGTH); + static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 }; + memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH); if ((text != NULL) && (begin != NULL) && (end != NULL)) { @@ -1912,16 +1912,16 @@ char *TextReplaceBetween(const char *text, const char *begin, const char *end, c int textLen = TextLength(text); int replaceLen = (replacement == NULL)? 0 : TextLength(replacement); - int toreplaceLen = endIndex - beginIndex - beginLen; + //int toreplaceLen = endIndex - beginIndex - beginLen; - strncpy(result, text, beginIndex + beginLen); // Copy first text part - if (replacement != NULL) strncpy(result + beginIndex + beginLen, replacement, replaceLen); // Copy replacement (if provided) - strncpy(result + beginIndex + beginLen + replaceLen, text + endIndex, textLen - endIndex); // Copy end text part + strncpy(buffer, text, beginIndex + beginLen); // Copy first text part + if (replacement != NULL) strncpy(buffer + beginIndex + beginLen, replacement, replaceLen); // Copy replacement (if provided) + strncpy(buffer + beginIndex + beginLen + replaceLen, text + endIndex, textLen - endIndex); // Copy end text part } } } - return result; + return buffer; } // Replace text between two specific strings @@ -1964,8 +1964,8 @@ char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *e // WARNING: Allocated memory must be manually freed char *TextInsert(const char *text, const char *insert, int position) { - static char result[MAX_TEXT_BUFFER_LENGTH] = { 0 }; - memset(result, 0, MAX_TEXT_BUFFER_LENGTH); + static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 }; + memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH); if ((text != NULL) && (insert != NULL)) { @@ -1976,16 +1976,16 @@ char *TextInsert(const char *text, const char *insert, int position) { // TODO: Allow copying data inserted up to maximum buffer size and stop - for (int i = 0; i < position; i++) result[i] = text[i]; - for (int i = position; i < insertLen + position; i++) result[i] = insert[i - position]; - for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i]; + for (int i = 0; i < position; i++) buffer[i] = text[i]; + for (int i = position; i < insertLen + position; i++) buffer[i] = insert[i - position]; + for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i]; - result[textLen + insertLen] = '\0'; // Add EOL + buffer[textLen + insertLen] = '\0'; // Add EOL } else TRACELOG(LOG_WARNING, "Text with inserted string is longer than internal buffer, use TextInserExt()"); } - return result; + return buffer; } // Insert text in a specific position, moves all text forward diff --git a/src/rtextures.c b/src/rtextures.c index 45b615cf7..b13f697d1 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -376,8 +376,7 @@ Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileDat Image image = { 0 }; int frameCount = 0; - // Security check for input data - if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image; + if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image; // Security check #if SUPPORT_FILEFORMAT_GIF if ((strcmp(fileType, ".gif") == 0) || (strcmp(fileType, ".GIF") == 0)) @@ -621,8 +620,7 @@ bool ExportImage(Image image, const char *fileName) { int result = 0; - // Security check for input data - if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return result; + if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return result; // Security check #if SUPPORT_IMAGE_EXPORT int channels = 4; @@ -709,8 +707,7 @@ unsigned char *ExportImageToMemory(Image image, const char *fileType, int *dataS unsigned char *fileData = NULL; *dataSize = 0; - // Security check for input data - if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return NULL; + if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return fileData; // Security check int channels = 4; @@ -734,7 +731,7 @@ unsigned char *ExportImageToMemory(Image image, const char *fileType, int *dataS // Export image as code file (.h) defining an array of bytes bool ExportImageAsCode(Image image, const char *fileName) { - bool success = false; + bool result = false; #ifndef TEXT_BYTES_PER_LINE #define TEXT_BYTES_PER_LINE 20 @@ -774,14 +771,14 @@ bool ExportImageAsCode(Image image, const char *fileName) byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]); // NOTE: Text data size exported is determined by '\0' (NULL) character - success = SaveFileText(fileName, txtData); + result = SaveFileText(fileName, txtData); RL_FREE(txtData); - if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName); + if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName); else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName); - return success; + return result; } //------------------------------------------------------------------------------------ @@ -1536,8 +1533,7 @@ Image ImageFromChannel(Image image, int selectedChannel) { Image result = { 0 }; - // Security check to avoid program crash - if ((image.data == NULL) || (image.width == 0) || (image.height == 0)) return result; + if ((image.data == NULL) || (image.width == 0) || (image.height == 0)) return result; // Security check // Check selected channel is valid if (selectedChannel < 0) @@ -2937,7 +2933,7 @@ void ImageColorReplace(Image *image, Color color, Color replace) // NOTE: Memory allocated should be freed using UnloadImageColors(); Color *LoadImageColors(Image image) { - if ((image.width == 0) || (image.height == 0)) return NULL; + if ((image.width == 0) || (image.height == 0)) return NULL; // Security check Color *pixels = (Color *)RL_MALLOC(image.width*image.height*sizeof(Color)); @@ -4903,44 +4899,44 @@ Vector3 ColorToHSV(Color color) float max = 0.0f; float delta = 0.0f; - min = rgb.x < rgb.y? rgb.x : rgb.y; - min = min < rgb.z? min : rgb.z; + min = (rgb.x < rgb.y)? rgb.x : rgb.y; + min = (min < rgb.z)? min : rgb.z; - max = rgb.x > rgb.y? rgb.x : rgb.y; - max = max > rgb.z? max : rgb.z; + max = (rgb.x > rgb.y)? rgb.x : rgb.y; + max = (max > rgb.z)? max : rgb.z; - hsv.z = max; // Value + hsv.z = max; // Value delta = max - min; if (delta < 0.00001f) { hsv.y = 0.0f; - hsv.x = 0.0f; // Undefined, maybe NAN? + hsv.x = 0.0f; // Undefined, maybe NAN? return hsv; } if (max > 0.0f) { // NOTE: If max is 0, this divide would cause a crash - hsv.y = (delta/max); // Saturation + hsv.y = (delta/max); // Saturation } else { // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined hsv.y = 0.0f; - hsv.x = NAN; // Undefined + hsv.x = NAN; // Undefined return hsv; } // NOTE: Comparing float values could not work properly - if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta + if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta else { - if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow - else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan + if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow + else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan } - hsv.x *= 60.0f; // Convert to degrees + hsv.x *= 60.0f; // Convert to degrees if (hsv.x < 0.0f) hsv.x += 360.0f; @@ -5093,7 +5089,7 @@ Color ColorAlpha(Color color, float alpha) // Get src alpha-blended into dst color with tint Color ColorAlphaBlend(Color dst, Color src, Color tint) { - Color out = WHITE; + Color result = WHITE; // Apply color tint to source color src.r = (unsigned char)(((unsigned int)src.r*((unsigned int)tint.r+1)) >> 8); @@ -5104,24 +5100,24 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint) //#define COLORALPHABLEND_FLOAT #define COLORALPHABLEND_INTEGERS #if defined(COLORALPHABLEND_INTEGERS) - if (src.a == 0) out = dst; - else if (src.a == 255) out = src; + if (src.a == 0) result = dst; + else if (src.a == 255) result = src; else { unsigned int alpha = (unsigned int)src.a + 1; // Shifting by 8 (dividing by 256), so need to take that excess into account - out.a = (unsigned char)(((unsigned int)alpha*256 + (unsigned int)dst.a*(256 - alpha)) >> 8); + result.a = (unsigned char)(((unsigned int)alpha*256 + (unsigned int)dst.a*(256 - alpha)) >> 8); - if (out.a > 0) + if (result.a > 0) { - out.r = (unsigned char)((((unsigned int)src.r*alpha*256 + (unsigned int)dst.r*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8); - out.g = (unsigned char)((((unsigned int)src.g*alpha*256 + (unsigned int)dst.g*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8); - out.b = (unsigned char)((((unsigned int)src.b*alpha*256 + (unsigned int)dst.b*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8); + result.r = (unsigned char)((((unsigned int)src.r*alpha*256 + (unsigned int)dst.r*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8); + result.g = (unsigned char)((((unsigned int)src.g*alpha*256 + (unsigned int)dst.g*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8); + result.b = (unsigned char)((((unsigned int)src.b*alpha*256 + (unsigned int)dst.b*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8); } } #endif #if defined(COLORALPHABLEND_FLOAT) - if (src.a == 0) out = dst; - else if (src.a == 255) out = src; + if (src.a == 0) result = dst; + else if (src.a == 255) result = src; else { Vector4 fdst = ColorNormalize(dst); @@ -5138,11 +5134,11 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint) fout.z = (fsrc.z*fsrc.w + fdst.z*fdst.w*(1 - fsrc.w))/fout.w; } - out = (Color){ (unsigned char)(fout.x*255.0f), (unsigned char)(fout.y*255.0f), (unsigned char)(fout.z*255.0f), (unsigned char)(fout.w*255.0f) }; + result = (Color){ (unsigned char)(fout.x*255.0f), (unsigned char)(fout.y*255.0f), (unsigned char)(fout.z*255.0f), (unsigned char)(fout.w*255.0f) }; } #endif - return out; + return result; } // Get color lerp interpolation between two colors, factor [0.0f..1.0f] From 5915584cd6cd8120429b70e224d6e80c8c1abadf Mon Sep 17 00:00:00 2001 From: Mr Josh Date: Sun, 29 Mar 2026 10:38:45 +1100 Subject: [PATCH 023/185] Fix zig build and minor improvements (#5702) - Added zig-pkg directory to gitignore - Brought min zig version to recent nightly release these improvements were completed on - For linux build, only add rglfw.c if the platform is glfw - Add a None option to the LinuxDisplayBackend - Fixed xcode-frameworks dependency and update to using most recent commit hash --- .gitignore | 1 + build.zig | 8 ++++++-- build.zig.zon | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 00a751a73..a0fa8db1c 100644 --- a/.gitignore +++ b/.gitignore @@ -118,6 +118,7 @@ GTAGS # Zig programming language .zig-cache/ zig-cache/ +zig-pkg/ zig-out/ build/ build-*/ diff --git a/build.zig b/build.zig index 3dc95bc83..ec254debf 100644 --- a/build.zig +++ b/build.zig @@ -2,7 +2,7 @@ const std = @import("std"); const builtin = @import("builtin"); /// Minimum supported version of Zig -const min_ver = "0.16.0-dev.2349+204fa8959"; +const min_ver = "0.16.0-dev.3013+abd131e33"; const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str; const emccOutputFile = "index.html"; @@ -264,7 +264,10 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. setDesktopPlatform(raylib, .android); } else { - try c_source_files.append(b.allocator, "src/rglfw.c"); + switch (options.platform) { + .glfw => try c_source_files.append(b.allocator, "src/rglfw.c"), + .rgfw, .sdl, .drm, .android => {}, + } if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { raylib.root_module.addCMacro("_GLFW_X11", ""); @@ -434,6 +437,7 @@ pub const OpenglVersion = enum { }; pub const LinuxDisplayBackend = enum { + None, X11, Wayland, Both, diff --git a/build.zig.zon b/build.zig.zon index 247386fb1..ee5a84c68 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -7,8 +7,8 @@ .dependencies = .{ .xcode_frameworks = .{ - .url = "https://pkg.machengine.org/xcode-frameworks/9a45f3ac977fd25dff77e58c6de1870b6808c4a7.tar.gz", - .hash = "122098b9174895f9708bc824b0f9e550c401892c40a900006459acf2cbf78acd99bb", + .url = "https://pkg.machengine.org/xcode-frameworks/8a1cfb373587ea4c9bb1468b7c986462d8d4e10e.tar.gz", + .hash = "N-V-__8AALShqgXkvqYU6f__FrA22SMWmi2TXCJjNTO1m8XJ", .lazy = true, }, .emsdk = .{ From bb78e98a7158c54177921e436a0f82c228c830b9 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Sat, 28 Mar 2026 16:39:23 -0700 Subject: [PATCH 024/185] Remove forced normalization of normal vectors in rlNormal3f, assume the user has set the correct input for the shader. (#5703) --- src/rlgl.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rlgl.h b/src/rlgl.h index 845f75d26..21899e6f6 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -1613,7 +1613,9 @@ void rlNormal3f(float x, float y, float z) normaly = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z; normalz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z; } - float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz); + +/* Normalize the vector if required. Default behavior assumes the normal vector is in the correct space for what the shader expects. + float length = sqrtf(normalx * normalx + normaly * normaly + normalz * normalz); if (length != 0.0f) { float ilength = 1.0f/length; @@ -1621,6 +1623,7 @@ void rlNormal3f(float x, float y, float z) normaly *= ilength; normalz *= ilength; } +*/ RLGL.State.normalx = normalx; RLGL.State.normaly = normaly; RLGL.State.normalz = normalz; From 29ded51ea437fe0639fd3b6408066ed3a5b931e6 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 00:43:50 +0100 Subject: [PATCH 025/185] Update rlgl.h --- src/rlgl.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 21899e6f6..e97bad36a 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -1614,8 +1614,11 @@ void rlNormal3f(float x, float y, float z) normalz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z; } -/* Normalize the vector if required. Default behavior assumes the normal vector is in the correct space for what the shader expects. - float length = sqrtf(normalx * normalx + normaly * normaly + normalz * normalz); + // NOTE: Default behavior assumes the normal vector is in the correct space for what the shader expects, + // it could be not normalized to 0.0f..1.0f, magnitud can be useed for some effects + /* + // WARNING: Vector normalization if required + float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz); if (length != 0.0f) { float ilength = 1.0f/length; @@ -1623,7 +1626,7 @@ void rlNormal3f(float x, float y, float z) normaly *= ilength; normalz *= ilength; } -*/ + */ RLGL.State.normalx = normalx; RLGL.State.normaly = normaly; RLGL.State.normalz = normalz; From fb0f83bc9169f9e36c23440b0623b97c71d6a13c Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 01:10:29 +0100 Subject: [PATCH 026/185] Remove trailing spaces on shaders --- .../audio/resources/shaders/glsl100/fft.fs | 6 +-- .../audio/resources/shaders/glsl120/fft.fs | 6 +-- .../audio/resources/shaders/glsl330/fft.fs | 6 +-- .../resources/shaders/glsl100/skinning.fs | 2 +- .../resources/shaders/glsl100/skinning.vs | 10 ++--- .../resources/shaders/glsl120/skinning.fs | 2 +- .../resources/shaders/glsl120/skinning.vs | 10 ++--- .../resources/shaders/glsl330/skinning.vs | 10 ++--- .../resources/shaders/glsl100/ascii.fs | 4 +- .../shaders/glsl100/deferred_shading.vs | 2 +- .../resources/shaders/glsl100/depth_write.fs | 4 +- .../resources/shaders/glsl100/gbuffer.fs | 6 +-- .../resources/shaders/glsl100/gbuffer.vs | 2 +- .../shaders/glsl100/hybrid_raster.fs | 2 +- .../shaders/glsl100/hybrid_raymarch.fs | 36 ++++++++--------- .../shaders/glsl100/mandelbrot_set.fs | 2 +- .../shaders/glsl100/palette_switch.fs | 4 +- .../shaders/resources/shaders/glsl100/pbr.fs | 14 +++---- .../resources/shaders/glsl100/shadowmap.fs | 4 +- .../resources/shaders/glsl120/ascii.fs | 4 +- .../shaders/glsl120/deferred_shading.vs | 2 +- .../resources/shaders/glsl120/depth_write.fs | 4 +- .../resources/shaders/glsl120/gbuffer.fs | 6 +-- .../resources/shaders/glsl120/gbuffer.vs | 2 +- .../shaders/glsl120/hybrid_raster.fs | 2 +- .../shaders/glsl120/hybrid_raymarch.fs | 34 ++++++++-------- .../shaders/resources/shaders/glsl120/pbr.fs | 14 +++---- .../resources/shaders/glsl120/shadowmap.fs | 4 +- .../resources/shaders/glsl330/ascii.fs | 4 +- .../shaders/resources/shaders/glsl330/base.fs | 2 +- .../resources/shaders/glsl330/depth_write.fs | 2 +- .../resources/shaders/glsl330/gbuffer.vs | 2 +- .../shaders/glsl330/hybrid_raster.fs | 2 +- .../shaders/glsl330/hybrid_raymarch.fs | 40 +++++++++---------- .../shaders/glsl330/palette_switch.fs | 2 +- .../shaders/resources/shaders/glsl330/pbr.fs | 14 +++---- .../shaders/glsl330/vertex_displacement.vs | 2 +- 37 files changed, 137 insertions(+), 137 deletions(-) diff --git a/examples/audio/resources/shaders/glsl100/fft.fs b/examples/audio/resources/shaders/glsl100/fft.fs index a97bf336b..15f6fef0f 100644 --- a/examples/audio/resources/shaders/glsl100/fft.fs +++ b/examples/audio/resources/shaders/glsl100/fft.fs @@ -23,15 +23,15 @@ void main() float localX = mod(fragCoord.x, cellWidth); float barWidth = cellWidth - 1.0; vec4 color = WHITE; - + if (localX <= barWidth) { float sampleX = (binIndex + 0.5)/NUM_OF_BINS; vec2 sampleCoord = vec2(sampleX, FFT_ROW); float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use - + if (fragTexCoord.y < amplitude) color = BLACK; } - + gl_FragColor = color; } diff --git a/examples/audio/resources/shaders/glsl120/fft.fs b/examples/audio/resources/shaders/glsl120/fft.fs index bab5d533b..3048d6c1f 100644 --- a/examples/audio/resources/shaders/glsl120/fft.fs +++ b/examples/audio/resources/shaders/glsl120/fft.fs @@ -21,15 +21,15 @@ void main() float localX = mod(fragCoord.x, cellWidth); float barWidth = cellWidth - 1.0; vec4 color = WHITE; - + if (localX <= barWidth) { float sampleX = (binIndex + 0.5)/NUM_OF_BINS; vec2 sampleCoord = vec2(sampleX, FFT_ROW); float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use - + if (fragTexCoord.y < amplitude) color = BLACK; } - + gl_FragColor = color; } diff --git a/examples/audio/resources/shaders/glsl330/fft.fs b/examples/audio/resources/shaders/glsl330/fft.fs index 20b2e9dfa..f355ced65 100644 --- a/examples/audio/resources/shaders/glsl330/fft.fs +++ b/examples/audio/resources/shaders/glsl330/fft.fs @@ -21,15 +21,15 @@ void main() float localX = mod(fragCoord.x, cellWidth); float barWidth = cellWidth - 1.0; vec4 color = WHITE; - + if (localX <= barWidth) { float sampleX = (binIndex + 0.5)/NUM_OF_BINS; vec2 sampleCoord = vec2(sampleX, FFT_ROW); float amplitude = texture(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use - + if (fragTexCoord.y < amplitude) color = BLACK; } - + finalColor = color; } diff --git a/examples/models/resources/shaders/glsl100/skinning.fs b/examples/models/resources/shaders/glsl100/skinning.fs index 96bcabe01..7feb097dd 100644 --- a/examples/models/resources/shaders/glsl100/skinning.fs +++ b/examples/models/resources/shaders/glsl100/skinning.fs @@ -14,7 +14,7 @@ void main() { // Fetch color from texture sampler vec4 texelColor = texture2D(texture0, fragTexCoord); - + // Calculate final fragment color gl_FragColor = texelColor*colDiffuse*fragColor; } diff --git a/examples/models/resources/shaders/glsl100/skinning.vs b/examples/models/resources/shaders/glsl100/skinning.vs index 344ad3f95..cb726eb5a 100644 --- a/examples/models/resources/shaders/glsl100/skinning.vs +++ b/examples/models/resources/shaders/glsl100/skinning.vs @@ -23,7 +23,7 @@ void main() int boneIndex1 = int(vertexBoneIndices.y); int boneIndex2 = int(vertexBoneIndices.z); int boneIndex3 = int(vertexBoneIndices.w); - + // WARNING: OpenGL ES 2.0 does not support automatic matrix transposing, neither transpose() function mat4 boneMatrixTransposed0 = mat4( vec4(boneMatrices[boneIndex0][0].x, boneMatrices[boneIndex0][1].x, boneMatrices[boneIndex0][2].x, boneMatrices[boneIndex0][3].x), @@ -45,13 +45,13 @@ void main() vec4(boneMatrices[boneIndex3][0].y, boneMatrices[boneIndex3][1].y, boneMatrices[boneIndex3][2].y, boneMatrices[boneIndex3][3].y), vec4(boneMatrices[boneIndex3][0].z, boneMatrices[boneIndex3][1].z, boneMatrices[boneIndex3][2].z, boneMatrices[boneIndex3][3].z), vec4(boneMatrices[boneIndex3][0].w, boneMatrices[boneIndex3][1].w, boneMatrices[boneIndex3][2].w, boneMatrices[boneIndex3][3].w)); - + vec4 skinnedPosition = vertexBoneWeights.x*(boneMatrixTransposed0*vec4(vertexPosition, 1.0)) + - vertexBoneWeights.y*(boneMatrixTransposed1*vec4(vertexPosition, 1.0)) + - vertexBoneWeights.z*(boneMatrixTransposed2*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.y*(boneMatrixTransposed1*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.z*(boneMatrixTransposed2*vec4(vertexPosition, 1.0)) + vertexBoneWeights.w*(boneMatrixTransposed3*vec4(vertexPosition, 1.0)); - + fragTexCoord = vertexTexCoord; fragColor = vertexColor; diff --git a/examples/models/resources/shaders/glsl120/skinning.fs b/examples/models/resources/shaders/glsl120/skinning.fs index 44c6314d1..5ea45cbac 100644 --- a/examples/models/resources/shaders/glsl120/skinning.fs +++ b/examples/models/resources/shaders/glsl120/skinning.fs @@ -12,7 +12,7 @@ void main() { // Fetch color from texture sampler vec4 texelColor = texture2D(texture0, fragTexCoord); - + // Calculate final fragment color gl_FragColor = texelColor*colDiffuse*fragColor; } diff --git a/examples/models/resources/shaders/glsl120/skinning.vs b/examples/models/resources/shaders/glsl120/skinning.vs index 1d9855074..02815f515 100644 --- a/examples/models/resources/shaders/glsl120/skinning.vs +++ b/examples/models/resources/shaders/glsl120/skinning.vs @@ -23,7 +23,7 @@ void main() int boneIndex1 = int(vertexBoneIndices.y); int boneIndex2 = int(vertexBoneIndices.z); int boneIndex3 = int(vertexBoneIndices.w); - + // WARNING: OpenGL ES 2.0 does not support automatic matrix transposing, neither transpose() function mat4 boneMatrixTransposed0 = mat4( vec4(boneMatrices[boneIndex0][0].x, boneMatrices[boneIndex0][1].x, boneMatrices[boneIndex0][2].x, boneMatrices[boneIndex0][3].x), @@ -45,13 +45,13 @@ void main() vec4(boneMatrices[boneIndex3][0].y, boneMatrices[boneIndex3][1].y, boneMatrices[boneIndex3][2].y, boneMatrices[boneIndex3][3].y), vec4(boneMatrices[boneIndex3][0].z, boneMatrices[boneIndex3][1].z, boneMatrices[boneIndex3][2].z, boneMatrices[boneIndex3][3].z), vec4(boneMatrices[boneIndex3][0].w, boneMatrices[boneIndex3][1].w, boneMatrices[boneIndex3][2].w, boneMatrices[boneIndex3][3].w)); - + vec4 skinnedPosition = vertexBoneWeights.x*(boneMatrixTransposed0*vec4(vertexPosition, 1.0)) + - vertexBoneWeights.y*(boneMatrixTransposed1*vec4(vertexPosition, 1.0)) + - vertexBoneWeights.z*(boneMatrixTransposed2*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.y*(boneMatrixTransposed1*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.z*(boneMatrixTransposed2*vec4(vertexPosition, 1.0)) + vertexBoneWeights.w*(boneMatrixTransposed3*vec4(vertexPosition, 1.0)); - + fragTexCoord = vertexTexCoord; fragColor = vertexColor; diff --git a/examples/models/resources/shaders/glsl330/skinning.vs b/examples/models/resources/shaders/glsl330/skinning.vs index 9b4ffbbfa..406d16f56 100644 --- a/examples/models/resources/shaders/glsl330/skinning.vs +++ b/examples/models/resources/shaders/glsl330/skinning.vs @@ -26,17 +26,17 @@ void main() int boneIndex1 = int(vertexBoneIndices.y); int boneIndex2 = int(vertexBoneIndices.z); int boneIndex3 = int(vertexBoneIndices.w); - + vec4 skinnedPosition = vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexPosition, 1.0)) + - vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0)) + - vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0)) + vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexPosition, 1.0)); vec4 skinnedNormal = vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexNormal, 0.0)) + - vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexNormal, 0.0)) + - vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexNormal, 0.0)) + + vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexNormal, 0.0)) + + vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexNormal, 0.0)) + vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexNormal, 0.0)); skinnedNormal.w = 0.0; diff --git a/examples/shaders/resources/shaders/glsl100/ascii.fs b/examples/shaders/resources/shaders/glsl100/ascii.fs index 11b46e471..2e325c0ed 100644 --- a/examples/shaders/resources/shaders/glsl100/ascii.fs +++ b/examples/shaders/resources/shaders/glsl100/ascii.fs @@ -58,12 +58,12 @@ void main() float gray = GreyScale(cellColor); float n = 4096.0; - + // Character set from https://www.shadertoy.com/view/lssGDj // Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/ if (gray > 0.2) n = 65600.0; // : if (gray > 0.3) n = 18725316.0; // v - if (gray > 0.4) n = 15255086.0; // o + if (gray > 0.4) n = 15255086.0; // o if (gray > 0.5) n = 13121101.0; // & if (gray > 0.6) n = 15252014.0; // 8 if (gray > 0.7) n = 13195790.0; // @ diff --git a/examples/shaders/resources/shaders/glsl100/deferred_shading.vs b/examples/shaders/resources/shaders/glsl100/deferred_shading.vs index bb108ce09..bd5bed5b1 100644 --- a/examples/shaders/resources/shaders/glsl100/deferred_shading.vs +++ b/examples/shaders/resources/shaders/glsl100/deferred_shading.vs @@ -12,5 +12,5 @@ void main() fragTexCoord = vertexTexCoord; // Calculate final vertex position - gl_Position = vec4(vertexPosition, 1.0); + gl_Position = vec4(vertexPosition, 1.0); } diff --git a/examples/shaders/resources/shaders/glsl100/depth_write.fs b/examples/shaders/resources/shaders/glsl100/depth_write.fs index 15095db11..55d3a2d87 100644 --- a/examples/shaders/resources/shaders/glsl100/depth_write.fs +++ b/examples/shaders/resources/shaders/glsl100/depth_write.fs @@ -1,5 +1,5 @@ #version 100 -#extension GL_EXT_frag_depth : enable +#extension GL_EXT_frag_depth : enable precision mediump float; @@ -14,7 +14,7 @@ uniform vec4 colDiffuse; void main() { vec4 texelColor = texture2D(texture0, fragTexCoord); - + gl_FragColor = texelColor*colDiffuse*fragColor; gl_FragDepthEXT = 1.0 - gl_FragCoord.z; } diff --git a/examples/shaders/resources/shaders/glsl100/gbuffer.fs b/examples/shaders/resources/shaders/glsl100/gbuffer.fs index 2945c5ddd..deb3d9ff3 100644 --- a/examples/shaders/resources/shaders/glsl100/gbuffer.fs +++ b/examples/shaders/resources/shaders/glsl100/gbuffer.fs @@ -24,13 +24,13 @@ void main() { // Store the fragment position vector in the first gbuffer texture //gPosition = fragPosition; - + // Store the per-fragment normals into the gbuffer //gNormal = normalize(fragNormal); - + // Store the diffuse per-fragment color gl_FragColor.rgb = texture2D(texture0, fragTexCoord).rgb; - + // Store specular intensity in gAlbedoSpec's alpha component gl_FragColor.a = texture2D(specularTexture, fragTexCoord).r; } diff --git a/examples/shaders/resources/shaders/glsl100/gbuffer.vs b/examples/shaders/resources/shaders/glsl100/gbuffer.vs index 2791ce5ee..0df010b8c 100644 --- a/examples/shaders/resources/shaders/glsl100/gbuffer.vs +++ b/examples/shaders/resources/shaders/glsl100/gbuffer.vs @@ -48,7 +48,7 @@ void main() { // Calculate vertex attributes for fragment shader vec4 worldPos = matModel*vec4(vertexPosition, 1.0); - fragPosition = worldPos.xyz; + fragPosition = worldPos.xyz; fragTexCoord = vertexTexCoord; fragColor = vertexColor; diff --git a/examples/shaders/resources/shaders/glsl100/hybrid_raster.fs b/examples/shaders/resources/shaders/glsl100/hybrid_raster.fs index 9658b3819..4f4f4a675 100644 --- a/examples/shaders/resources/shaders/glsl100/hybrid_raster.fs +++ b/examples/shaders/resources/shaders/glsl100/hybrid_raster.fs @@ -1,7 +1,7 @@ #version 100 #extension GL_EXT_frag_depth : enable // Extension required for writing depth - + precision mediump float; // Precision required for OpenGL ES2 (WebGL) varying vec2 fragTexCoord; diff --git a/examples/shaders/resources/shaders/glsl100/hybrid_raymarch.fs b/examples/shaders/resources/shaders/glsl100/hybrid_raymarch.fs index e3287fc04..f13902d12 100644 --- a/examples/shaders/resources/shaders/glsl100/hybrid_raymarch.fs +++ b/examples/shaders/resources/shaders/glsl100/hybrid_raymarch.fs @@ -32,12 +32,12 @@ float sdHorseshoe(in vec3 p, in vec2 c, in float r, in float le, vec2 w) { p.x = abs(p.x); float l = length(p.xy); - p.xy = mat2(-c.x, c.y, + p.xy = mat2(-c.x, c.y, c.y, c.x)*p.xy; p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x), (p.x>0.0)?p.y:l); p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0); - + vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z); vec2 d = abs(q) - w; return min(max(d.x,d.y),0.0) + length(max(d,0.0)); @@ -56,9 +56,9 @@ float sdSixWayCutHollowSphere(vec3 p, float r, float h, float t) } vec2 q = vec2(length(ap.yz), ap.x); - + float w = sqrt(r*r-h*h); - + return ((h*q.xtmax) break; vec2 h = map(ro+rd*t); if (abs(h.x) < (0.0001*t)) - { - res = vec2(t,h.y); + { + res = vec2(t,h.y); break; } t += h.x; @@ -146,9 +146,9 @@ float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax) vec3 calcNormal(in vec3 pos) { vec2 e = vec2(1.0,-1.0)*0.5773*0.0005; - return normalize(e.xyy*map(pos + e.xyy).x + - e.yyx*map(pos + e.yyx).x + - e.yxy*map(pos + e.yxy).x + + return normalize(e.xyy*map(pos + e.xyy).x + + e.yyx*map(pos + e.yyx).x + + e.yxy*map(pos + e.yxy).x + e.xxx*map(pos + e.xxx).x); } @@ -176,15 +176,15 @@ float checkersGradBox(in vec2 p) // analytical integral (box filter) vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w; // xor pattern - return 0.5 - 0.5*i.x*i.y; + return 0.5 - 0.5*i.x*i.y; } // https://www.shadertoy.com/view/tdS3DG vec4 render(in vec3 ro, in vec3 rd) -{ +{ // background vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3; - + // raycast scene vec2 res = raycast(ro,rd); float t = res.x; @@ -194,11 +194,11 @@ vec4 render(in vec3 ro, in vec3 rd) vec3 pos = ro + t*rd; vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos); vec3 ref = reflect(rd, nor); - - // material + + // material col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0)); float ks = 1.0; - + if (m<1.5) { float f = checkersGradBox(3.0*pos.xz); @@ -208,7 +208,7 @@ vec4 render(in vec3 ro, in vec3 rd) // lighting float occ = calcAO(pos, nor); - + vec3 lin = vec3(0.0); // sun @@ -249,7 +249,7 @@ vec4 render(in vec3 ro, in vec3 rd) dif *= occ; lin += col*0.25*dif*vec3(1.00,1.00,1.00); } - + col = lin; col = mix(col, vec3(0.7,0.7,0.9), 1.0-exp(-0.0001*t*t*t)); @@ -289,7 +289,7 @@ void main() color = res.xyz; depth = CalcDepth(rd,res.w); } - + gl_FragColor = vec4(color , 1.0); gl_FragDepthEXT = depth; } \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs b/examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs index 7a89e86b0..b0125a5f6 100644 --- a/examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs +++ b/examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs @@ -48,7 +48,7 @@ void main() float normR = float(iter - (iter/55)*55)/55.0; float normG = float(iter - (iter/69)*69)/69.0; float normB = float(iter - (iter/40)*40)/40.0; - + gl_FragColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0); return; } diff --git a/examples/shaders/resources/shaders/glsl100/palette_switch.fs b/examples/shaders/resources/shaders/glsl100/palette_switch.fs index d8d696d4f..a2dcdb912 100644 --- a/examples/shaders/resources/shaders/glsl100/palette_switch.fs +++ b/examples/shaders/resources/shaders/glsl100/palette_switch.fs @@ -21,7 +21,7 @@ void main() // Convert the (normalized) texel color RED component (GB would work, too) // to the palette index by scaling up from [0..1] to [0..255] int index = int(texelColor.r*255.0); - + ivec3 color = ivec3(0); // NOTE: On GLSL 100 we are not allowed to index a uniform array by a variable value, @@ -34,7 +34,7 @@ void main() else if (index == 5) color = palette[5]; else if (index == 6) color = palette[6]; else if (index == 7) color = palette[7]; - + //gl_FragColor = texture2D(palette, texelColor.xy); // Alternative to ivec3 // Calculate final fragment color. Note that the palette color components diff --git a/examples/shaders/resources/shaders/glsl100/pbr.fs b/examples/shaders/resources/shaders/glsl100/pbr.fs index 48688ebe9..28212bf63 100644 --- a/examples/shaders/resources/shaders/glsl100/pbr.fs +++ b/examples/shaders/resources/shaders/glsl100/pbr.fs @@ -83,11 +83,11 @@ vec3 ComputePBR() { vec3 albedo = texture2D(albedoMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb; albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z); - + float metallic = clamp(metallicValue, 0.0, 1.0); float roughness = clamp(roughnessValue, 0.0, 1.0); float ao = clamp(aoValue, 0.0, 1.0); - + if (useTexMRA == 1) { vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)); @@ -132,18 +132,18 @@ vec3 ComputePBR() vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance vec3 spec = (D*G*F)/(4.0*nDotV*nDotL); - + // Difuse and spec light can't be above 1.0 // kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent vec3 kD = vec3(1.0) - F; - + // Mult kD by the inverse of metallnes, only non-metals should have diffuse light kD *= 1.0 - metallic; lightAccum += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*float(lights[i].enabled); // Angle of light has impact on result } - + vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5; - + return (ambientFinal + lightAccum*ao + emissive); } @@ -153,7 +153,7 @@ void main() // HDR tonemapping color = pow(color, color + vec3(1.0)); - + // Gamma correction color = pow(color, vec3(1.0/2.2)); diff --git a/examples/shaders/resources/shaders/glsl100/shadowmap.fs b/examples/shaders/resources/shaders/glsl100/shadowmap.fs index 7a0e806a5..c65d20e44 100644 --- a/examples/shaders/resources/shaders/glsl100/shadowmap.fs +++ b/examples/shaders/resources/shaders/glsl100/shadowmap.fs @@ -60,7 +60,7 @@ void main() float bias = max(0.0008*(1.0 - dot(normal, l)), 0.00008); int shadowCounter = 0; const int numSamples = 9; - + // PCF (percentage-closer filtering) algorithm: // Instead of testing if just one point is closer to the current point, // we test the surrounding points as well @@ -74,7 +74,7 @@ void main() if (curDepth - bias > sampleDepth) shadowCounter++; } } - + finalColor = mix(finalColor, vec4(0, 0, 0, 1), float(shadowCounter)/float(numSamples)); // Add ambient lighting whether in shadow or not diff --git a/examples/shaders/resources/shaders/glsl120/ascii.fs b/examples/shaders/resources/shaders/glsl120/ascii.fs index e4e9927b9..44ff399ae 100644 --- a/examples/shaders/resources/shaders/glsl120/ascii.fs +++ b/examples/shaders/resources/shaders/glsl120/ascii.fs @@ -56,12 +56,12 @@ void main() float gray = GreyScale(cellColor); float n = 4096.0; - + // Character set from https://www.shadertoy.com/view/lssGDj // Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/ if (gray > 0.2) n = 65600.0; // : if (gray > 0.3) n = 18725316.0; // v - if (gray > 0.4) n = 15255086.0; // o + if (gray > 0.4) n = 15255086.0; // o if (gray > 0.5) n = 13121101.0; // & if (gray > 0.6) n = 15252014.0; // 8 if (gray > 0.7) n = 13195790.0; // @ diff --git a/examples/shaders/resources/shaders/glsl120/deferred_shading.vs b/examples/shaders/resources/shaders/glsl120/deferred_shading.vs index daece19e5..d08e909a9 100644 --- a/examples/shaders/resources/shaders/glsl120/deferred_shading.vs +++ b/examples/shaders/resources/shaders/glsl120/deferred_shading.vs @@ -12,5 +12,5 @@ void main() fragTexCoord = vertexTexCoord; // Calculate final vertex position - gl_Position = vec4(vertexPosition, 1.0); + gl_Position = vec4(vertexPosition, 1.0); } diff --git a/examples/shaders/resources/shaders/glsl120/depth_write.fs b/examples/shaders/resources/shaders/glsl120/depth_write.fs index a2bc38516..897b5ccd0 100644 --- a/examples/shaders/resources/shaders/glsl120/depth_write.fs +++ b/examples/shaders/resources/shaders/glsl120/depth_write.fs @@ -1,6 +1,6 @@ #version 120 -#extension GL_EXT_frag_depth : enable +#extension GL_EXT_frag_depth : enable varying vec2 fragTexCoord; varying vec4 fragColor; @@ -11,7 +11,7 @@ uniform vec4 colDiffuse; void main() { vec4 texelColor = texture2D(texture0, fragTexCoord); - + gl_FragColor = texelColor*colDiffuse*fragColor; gl_FragDepthEXT = 1.0 - gl_FragCoord.z; } \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl120/gbuffer.fs b/examples/shaders/resources/shaders/glsl120/gbuffer.fs index a826d7916..509558e24 100644 --- a/examples/shaders/resources/shaders/glsl120/gbuffer.fs +++ b/examples/shaders/resources/shaders/glsl120/gbuffer.fs @@ -22,13 +22,13 @@ void main() { // Store the fragment position vector in the first gbuffer texture //gPosition = fragPosition; - + // Store the per-fragment normals into the gbuffer //gNormal = normalize(fragNormal); - + // Store the diffuse per-fragment color gl_FragColor.rgb = texture2D(texture0, fragTexCoord).rgb; - + // Store specular intensity in gAlbedoSpec's alpha component gl_FragColor.a = texture2D(specularTexture, fragTexCoord).r; } diff --git a/examples/shaders/resources/shaders/glsl120/gbuffer.vs b/examples/shaders/resources/shaders/glsl120/gbuffer.vs index adc1dcd1a..502dc6792 100644 --- a/examples/shaders/resources/shaders/glsl120/gbuffer.vs +++ b/examples/shaders/resources/shaders/glsl120/gbuffer.vs @@ -48,7 +48,7 @@ void main() { // Calculate vertex attributes for fragment shader vec4 worldPos = matModel*vec4(vertexPosition, 1.0); - fragPosition = worldPos.xyz; + fragPosition = worldPos.xyz; fragTexCoord = vertexTexCoord; fragColor = vertexColor; diff --git a/examples/shaders/resources/shaders/glsl120/hybrid_raster.fs b/examples/shaders/resources/shaders/glsl120/hybrid_raster.fs index e4c7e2eca..74e17eee9 100644 --- a/examples/shaders/resources/shaders/glsl120/hybrid_raster.fs +++ b/examples/shaders/resources/shaders/glsl120/hybrid_raster.fs @@ -1,6 +1,6 @@ #version 120 -#extension GL_EXT_frag_depth : enable // Extension required for writing depth +#extension GL_EXT_frag_depth : enable // Extension required for writing depth varying vec2 fragTexCoord; varying vec4 fragColor; diff --git a/examples/shaders/resources/shaders/glsl120/hybrid_raymarch.fs b/examples/shaders/resources/shaders/glsl120/hybrid_raymarch.fs index 6090df6b1..7a097feff 100644 --- a/examples/shaders/resources/shaders/glsl120/hybrid_raymarch.fs +++ b/examples/shaders/resources/shaders/glsl120/hybrid_raymarch.fs @@ -30,12 +30,12 @@ float sdHorseshoe(in vec3 p, in vec2 c, in float r, in float le, vec2 w) { p.x = abs(p.x); float l = length(p.xy); - p.xy = mat2(-c.x, c.y, + p.xy = mat2(-c.x, c.y, c.y, c.x)*p.xy; p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x), (p.x>0.0)?p.y:l); p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0); - + vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z); vec2 d = abs(q) - w; return min(max(d.x,d.y),0.0) + length(max(d,0.0)); @@ -54,9 +54,9 @@ float sdSixWayCutHollowSphere(vec3 p, float r, float h, float t) } vec2 q = vec2(length(ap.yz), ap.x); - + float w = sqrt(r*r-h*h); - + return ((h*q.xtmax) break; vec2 h = map(ro+rd*t); if (abs(h.x) < (0.0001*t)) - { - res = vec2(t,h.y); + { + res = vec2(t,h.y); break; } t += h.x; @@ -144,9 +144,9 @@ float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax) vec3 calcNormal(in vec3 pos) { vec2 e = vec2(1.0, -1.0)*0.5773*0.0005; - return normalize(e.xyy*map(pos + e.xyy).x + - e.yyx*map(pos + e.yyx).x + - e.yxy*map(pos + e.yxy).x + + return normalize(e.xyy*map(pos + e.xyy).x + + e.yyx*map(pos + e.yyx).x + + e.yxy*map(pos + e.yxy).x + e.xxx*map(pos + e.xxx).x); } @@ -174,15 +174,15 @@ float checkersGradBox(in vec2 p) // analytical integral (box filter) vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w; // xor pattern - return 0.5 - 0.5*i.x*i.y; + return 0.5 - 0.5*i.x*i.y; } // https://www.shadertoy.com/view/tdS3DG vec4 render(in vec3 ro, in vec3 rd) -{ +{ // background vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3; - + // raycast scene vec2 res = raycast(ro,rd); float t = res.x; @@ -192,11 +192,11 @@ vec4 render(in vec3 ro, in vec3 rd) vec3 pos = ro + t*rd; vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos); vec3 ref = reflect(rd, nor); - - // material + + // material col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0)); float ks = 1.0; - + if (m<1.5) { float f = checkersGradBox(3.0*pos.xz); @@ -206,7 +206,7 @@ vec4 render(in vec3 ro, in vec3 rd) // lighting float occ = calcAO(pos, nor); - + vec3 lin = vec3(0.0); // sun @@ -247,7 +247,7 @@ vec4 render(in vec3 ro, in vec3 rd) dif *= occ; lin += col*0.25*dif*vec3(1.00,1.00,1.00); } - + col = lin; col = mix(col, vec3(0.7,0.7,0.9), 1.0-exp(-0.0001*t*t*t)); diff --git a/examples/shaders/resources/shaders/glsl120/pbr.fs b/examples/shaders/resources/shaders/glsl120/pbr.fs index 63241709b..b36b76bee 100644 --- a/examples/shaders/resources/shaders/glsl120/pbr.fs +++ b/examples/shaders/resources/shaders/glsl120/pbr.fs @@ -81,11 +81,11 @@ vec3 ComputePBR() { vec3 albedo = texture2D(albedoMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb; albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z); - + float metallic = clamp(metallicValue, 0.0, 1.0); float roughness = clamp(roughnessValue, 0.0, 1.0); float ao = clamp(aoValue, 0.0, 1.0); - + if (useTexMRA == 1) { vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)); @@ -130,18 +130,18 @@ vec3 ComputePBR() vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance vec3 spec = (D*G*F)/(4.0*nDotV*nDotL); - + // Difuse and spec light can't be above 1.0 // kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent vec3 kD = vec3(1.0) - F; - + // Mult kD by the inverse of metallnes, only non-metals should have diffuse light kD *= 1.0 - metallic; lightAccum += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*float(lights[i].enabled); // Angle of light has impact on result } - + vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5; - + return (ambientFinal + lightAccum*ao + emissive); } @@ -151,7 +151,7 @@ void main() // HDR tonemapping color = pow(color, color + vec3(1.0)); - + // Gamma correction color = pow(color, vec3(1.0/2.2)); diff --git a/examples/shaders/resources/shaders/glsl120/shadowmap.fs b/examples/shaders/resources/shaders/glsl120/shadowmap.fs index 354c4a2c5..a0f8e9425 100644 --- a/examples/shaders/resources/shaders/glsl120/shadowmap.fs +++ b/examples/shaders/resources/shaders/glsl120/shadowmap.fs @@ -58,7 +58,7 @@ void main() float bias = max(0.0008*(1.0 - dot(normal, l)), 0.00008); int shadowCounter = 0; const int numSamples = 9; - + // PCF (percentage-closer filtering) algorithm: // Instead of testing if just one point is closer to the current point, // we test the surrounding points as well @@ -72,7 +72,7 @@ void main() if (curDepth - bias > sampleDepth) shadowCounter++; } } - + finalColor = mix(finalColor, vec4(0, 0, 0, 1), float(shadowCounter)/float(numSamples)); // Add ambient lighting whether in shadow or not diff --git a/examples/shaders/resources/shaders/glsl330/ascii.fs b/examples/shaders/resources/shaders/glsl330/ascii.fs index 3934c5dc1..8a6cc01d9 100644 --- a/examples/shaders/resources/shaders/glsl330/ascii.fs +++ b/examples/shaders/resources/shaders/glsl330/ascii.fs @@ -52,12 +52,12 @@ void main() float gray = GreyScale(cellColor); int n = 4096; - + // Character set from https://www.shadertoy.com/view/lssGDj // Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/ if (gray > 0.2) n = 65600; // : if (gray > 0.3) n = 18725316; // v - if (gray > 0.4) n = 15255086; // o + if (gray > 0.4) n = 15255086; // o if (gray > 0.5) n = 13121101; // & if (gray > 0.6) n = 15252014; // 8 if (gray > 0.7) n = 13195790; // @ diff --git a/examples/shaders/resources/shaders/glsl330/base.fs b/examples/shaders/resources/shaders/glsl330/base.fs index e8bf9e2d2..abf5dec6b 100644 --- a/examples/shaders/resources/shaders/glsl330/base.fs +++ b/examples/shaders/resources/shaders/glsl330/base.fs @@ -20,7 +20,7 @@ void main() // NOTE: Implement here your fragment shader code - // final color is the color from the texture + // final color is the color from the texture // times the tint color (colDiffuse) // times the fragment color (interpolated vertex color) finalColor = texelColor*colDiffuse*fragColor; diff --git a/examples/shaders/resources/shaders/glsl330/depth_write.fs b/examples/shaders/resources/shaders/glsl330/depth_write.fs index f0e07beec..31f716784 100644 --- a/examples/shaders/resources/shaders/glsl330/depth_write.fs +++ b/examples/shaders/resources/shaders/glsl330/depth_write.fs @@ -14,7 +14,7 @@ out vec4 finalColor; void main() { vec4 texelColor = texture(texture0, fragTexCoord); - + finalColor = texelColor*colDiffuse*fragColor; gl_FragDepth = 1.0 - finalColor.z; } diff --git a/examples/shaders/resources/shaders/glsl330/gbuffer.vs b/examples/shaders/resources/shaders/glsl330/gbuffer.vs index 5af4448e6..e39779e27 100644 --- a/examples/shaders/resources/shaders/glsl330/gbuffer.vs +++ b/examples/shaders/resources/shaders/glsl330/gbuffer.vs @@ -14,7 +14,7 @@ uniform mat4 matProjection; void main() { vec4 worldPos = matModel*vec4(vertexPosition, 1.0); - fragPosition = worldPos.xyz; + fragPosition = worldPos.xyz; fragTexCoord = vertexTexCoord; mat3 normalMatrix = transpose(inverse(mat3(matModel))); diff --git a/examples/shaders/resources/shaders/glsl330/hybrid_raster.fs b/examples/shaders/resources/shaders/glsl330/hybrid_raster.fs index 0b94dbdef..a31920bbf 100644 --- a/examples/shaders/resources/shaders/glsl330/hybrid_raster.fs +++ b/examples/shaders/resources/shaders/glsl330/hybrid_raster.fs @@ -16,7 +16,7 @@ out vec4 finalColor; void main() { vec4 texelColor = texture(texture0, fragTexCoord); - + finalColor = texelColor*colDiffuse*fragColor; gl_FragDepth = finalColor.z; } \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/hybrid_raymarch.fs b/examples/shaders/resources/shaders/glsl330/hybrid_raymarch.fs index 073fef4f1..48fba9af8 100644 --- a/examples/shaders/resources/shaders/glsl330/hybrid_raymarch.fs +++ b/examples/shaders/resources/shaders/glsl330/hybrid_raymarch.fs @@ -33,7 +33,7 @@ float sdHorseshoe(in vec3 p, in vec2 c, in float r, in float le, vec2 w) p.xy = mat2(-c.x, c.y, c.y, c.x)*p.xy; p.xy = vec2(((p.y > 0.0) || (p.x > 0.0))? p.x : l*sign(-c.x), (p.x>0.0)? p.y : l); p.xy = vec2(p.x, abs(p.y - r)) - vec2(le, 0.0); - + vec2 q = vec2(length(max(p.xy, 0.0)) + min(0.0, max(p.x, p.y)), p.z); vec2 d = abs(q) - w; return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)); @@ -54,7 +54,7 @@ float sdSixWayCutHollowSphere(vec3 p, float r, float h, float t) vec2 q = vec2(length(ap.yz), ap.x); float w = sqrt(r*r-h*h); - + return ((h*q.x < w*q.y)? length(q - vec2(w, h)) : abs(length(q) - r)) - t; } @@ -79,7 +79,7 @@ vec2 map(in vec3 pos) { vec2 res = vec2(sdHorseshoe(pos - vec3(-1.0, 0.08, 1.0), vec2(cos(1.3), sin(1.3)), 0.2, 0.3, vec2(0.03,0.5)), 11.5); res = opU(res, vec2(sdSixWayCutHollowSphere(pos-vec3(0.0, 1.0, 0.0), 4.0, 3.5, 0.5), 4.5)); - + return res; } @@ -105,8 +105,8 @@ vec2 raycast(in vec3 ro, in vec3 rd) if (t > tmax) break; vec2 h = map(ro + rd*t); if (abs(h.x )< (0.0001*t)) - { - res = vec2(t, h.y); + { + res = vec2(t, h.y); break; } t += h.x; @@ -131,9 +131,9 @@ float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax) t += clamp(h, 0.01, 0.2); if ((res < 0.004) || (t > tmax)) break; } - + res = clamp(res, 0.0, 1.0); - + return res*res*(3.0-2.0*res); } @@ -141,9 +141,9 @@ float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax) vec3 calcNormal(in vec3 pos) { vec2 e = vec2(1.0, -1.0)*0.5773*0.0005; - return normalize(e.xyy*map(pos + e.xyy).x + - e.yyx*map(pos + e.yyx).x + - e.yxy*map(pos + e.yxy).x + + return normalize(e.xyy*map(pos + e.xyy).x + + e.yyx*map(pos + e.yyx).x + + e.yxy*map(pos + e.yxy).x + e.xxx*map(pos + e.xxx).x); } @@ -160,7 +160,7 @@ float calcAO(in vec3 pos, in vec3 nor) sca *= 0.95; if (occ>0.35) break; } - + return clamp(1.0 - 3.0*occ, 0.0, 1.0)*(0.5+0.5*nor.y); } @@ -172,15 +172,15 @@ float checkersGradBox(in vec2 p) // analytical integral (box filter) vec2 i = 2.0*(abs(fract((p - 0.5*w)*0.5)-0.5) - abs(fract((p + 0.5*w)*0.5) - 0.5))/w; // xor pattern - return (0.5 - 0.5*i.x*i.y); + return (0.5 - 0.5*i.x*i.y); } // https://www.shadertoy.com/view/tdS3DG vec4 render(in vec3 ro, in vec3 rd) -{ +{ // background vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3; - + // raycast scene vec2 res = raycast(ro,rd); float t = res.x; @@ -190,11 +190,11 @@ vec4 render(in vec3 ro, in vec3 rd) vec3 pos = ro + t*rd; vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos); vec3 ref = reflect(rd, nor); - - // material + + // material col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0)); float ks = 1.0; - + if (m < 1.5) { float f = checkersGradBox(3.0*pos.xz); @@ -204,7 +204,7 @@ vec4 render(in vec3 ro, in vec3 rd) // lighting float occ = calcAO(pos, nor); - + vec3 lin = vec3(0.0); // sun @@ -245,7 +245,7 @@ vec4 render(in vec3 ro, in vec3 rd) dif *= occ; lin += col*0.25*dif*vec3(1.00,1.00,1.00); } - + col = lin; col = mix(col, vec3(0.7,0.7,0.9), 1.0-exp(-0.0001*t*t*t)); @@ -285,7 +285,7 @@ void main() color = res.xyz; depth = CalcDepth(rd,res.w); } - + finalColor = vec4(color , 1.0); gl_FragDepth = depth; } \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/palette_switch.fs b/examples/shaders/resources/shaders/glsl330/palette_switch.fs index 2db8880d1..9bd77e863 100644 --- a/examples/shaders/resources/shaders/glsl330/palette_switch.fs +++ b/examples/shaders/resources/shaders/glsl330/palette_switch.fs @@ -24,7 +24,7 @@ void main() // to the palette index by scaling up from [0..1] to [0..255] int index = int(texelColor.r*255.0); ivec3 color = palette[index]; - + //finalColor = texture(palette, texelColor.xy); // Alternative to ivec3 // Calculate final fragment color. Note that the palette color components diff --git a/examples/shaders/resources/shaders/glsl330/pbr.fs b/examples/shaders/resources/shaders/glsl330/pbr.fs index d439841df..ceaead308 100644 --- a/examples/shaders/resources/shaders/glsl330/pbr.fs +++ b/examples/shaders/resources/shaders/glsl330/pbr.fs @@ -84,11 +84,11 @@ vec3 ComputePBR() { vec3 albedo = texture(albedoMap,vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb; albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z); - + float metallic = clamp(metallicValue, 0.0, 1.0); float roughness = clamp(roughnessValue, 0.0, 1.0); float ao = clamp(aoValue, 0.0, 1.0); - + if (useTexMRA == 1) { vec4 mra = texture(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)); @@ -133,18 +133,18 @@ vec3 ComputePBR() vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance vec3 spec = (D*G*F)/(4.0*nDotV*nDotL); - + // Difuse and spec light can't be above 1.0 // kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent vec3 kD = vec3(1.0) - F; - + // Mult kD by the inverse of metallnes, only non-metals should have diffuse light kD *= 1.0 - metallic; lightAccum += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*lights[i].enabled; // Angle of light has impact on result } - + vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5; - + return (ambientFinal + lightAccum*ao + emissive); } @@ -154,7 +154,7 @@ void main() // HDR tonemapping color = pow(color, color + vec3(1.0)); - + // Gamma correction color = pow(color, vec3(1.0/2.2)); diff --git a/examples/shaders/resources/shaders/glsl330/vertex_displacement.vs b/examples/shaders/resources/shaders/glsl330/vertex_displacement.vs index 080ad473a..b324cbd57 100644 --- a/examples/shaders/resources/shaders/glsl330/vertex_displacement.vs +++ b/examples/shaders/resources/shaders/glsl330/vertex_displacement.vs @@ -11,7 +11,7 @@ uniform mat4 mvp; uniform mat4 matModel; uniform mat4 matNormal; -uniform float time; +uniform float time; uniform sampler2D perlinNoiseMap; From da93ec4a2145f2ae6ac9319923c8a8820df24a7d Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 01:17:25 +0100 Subject: [PATCH 027/185] Remove trailing spaces --- .github/workflows/build_android.yml | 18 ++++---- .github/workflows/build_examples_linux.yml | 8 ++-- .github/workflows/build_examples_windows.yml | 2 +- .github/workflows/build_linux.yml | 20 ++++---- .github/workflows/build_macos.yml | 30 ++++++------ .github/workflows/update_examples.yml | 4 +- projects/4coder/main.c | 2 +- projects/Geany/core_basic_window.c | 4 +- .../raylib_npp_parser/raylib_npp_parser.c | 46 +++++++++---------- src/raudio.c | 8 ++-- src/rshapes.c | 2 +- src/rtext.c | 4 +- tools/rlparser/rlparser.c | 4 +- 13 files changed, 76 insertions(+), 76 deletions(-) diff --git a/.github/workflows/build_android.yml b/.github/workflows/build_android.yml index 6993eb292..c87807847 100644 --- a/.github/workflows/build_android.yml +++ b/.github/workflows/build_android.yml @@ -28,20 +28,20 @@ jobs: max-parallel: 1 matrix: ARCH: ["arm64", "x86_64"] - + env: RELEASE_NAME: raylib-dev_android_api29_${{ matrix.ARCH }} - + steps: - name: Checkout uses: actions/checkout@master - + - name: Setup Release Version run: | echo "RELEASE_NAME=raylib-${{ github.event.release.tag_name }}_android_api29_${{ matrix.ARCH }}" >> $GITHUB_ENV shell: bash if: github.event_name == 'release' && github.event.action == 'published' - + - name: Setup Android NDK id: setup-ndk uses: nttld/setup-ndk@v1 @@ -52,7 +52,7 @@ jobs: ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} - name: Setup Environment - run: | + run: | mkdir build cd build mkdir ${{ env.RELEASE_NAME }} @@ -60,7 +60,7 @@ jobs: mkdir include mkdir lib cd ../.. - + # Generating static + shared library for 64bit arquitectures and API version 29 - name: Build Library run: | @@ -69,7 +69,7 @@ jobs: make PLATFORM=PLATFORM_ANDROID ANDROID_ARCH=${{ matrix.ARCH }} ANDROID_API_VERSION=29 ANDROID_NDK=${{ env.ANDROID_NDK_HOME }} RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B cd .. shell: cmd - + - name: Generate Artifacts run: | cp -v ./src/raylib.h ./build/${{ env.RELEASE_NAME }}/include @@ -80,7 +80,7 @@ jobs: cp -v ./LICENSE ./build/${{ env.RELEASE_NAME }}/LICENSE cd build tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }} - + - name: Upload Artifacts uses: actions/upload-artifact@v4 with: @@ -88,7 +88,7 @@ jobs: path: | ./build/${{ env.RELEASE_NAME }} !./build/${{ env.RELEASE_NAME }}.tar.gz - + - name: Upload Artifact to Release uses: softprops/action-gh-release@v1 with: diff --git a/.github/workflows/build_examples_linux.yml b/.github/workflows/build_examples_linux.yml index 5f029e73f..c293efd1d 100644 --- a/.github/workflows/build_examples_linux.yml +++ b/.github/workflows/build_examples_linux.yml @@ -23,18 +23,18 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 - + - name: Setup Environment - run: | + run: | sudo apt-get update -qq sudo apt-get install -y --no-install-recommends libglfw3 libglfw3-dev libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libxext-dev libxfixes-dev libwayland-dev libxkbcommon-dev - + - name: Build Library run: | cd src make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=STATIC cd .. - + - name: Build Examples run: | cd examples diff --git a/.github/workflows/build_examples_windows.yml b/.github/workflows/build_examples_windows.yml index 6530931e6..4cc2e84b9 100644 --- a/.github/workflows/build_examples_windows.yml +++ b/.github/workflows/build_examples_windows.yml @@ -13,7 +13,7 @@ on: - 'src/**' - 'examples/**' - '.github/workflows/windows_examples.yml' - + permissions: contents: read diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index b101750bc..0fc32d374 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -42,23 +42,23 @@ jobs: ARCH_NAME: "arm64" COMPILER_PATH: "/usr/bin" runner: "ubuntu-24.04-arm" - + runs-on: ${{ matrix.runner }} env: RELEASE_NAME: raylib-dev_linux_${{ matrix.ARCH_NAME }} - + steps: - name: Checkout code uses: actions/checkout@master - + - name: Setup Release Version run: | echo "RELEASE_NAME=raylib-${{ github.event.release.tag_name }}_linux_${{ matrix.ARCH_NAME }}" >> $GITHUB_ENV shell: bash if: github.event_name == 'release' && github.event.action == 'published' - + - name: Setup Environment - run: | + run: | sudo apt-get update -qq sudo apt-get install -y --no-install-recommends libglfw3 libglfw3-dev libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libxext-dev libxfixes-dev libwayland-dev libxkbcommon-dev mkdir build @@ -74,7 +74,7 @@ jobs: run : | sudo apt-get install gcc-multilib if: matrix.bits == 32 && matrix.ARCH == 'i386' - + # TODO: Support 32bit (i386) static/shared library building - name: Build Library (32-bit) run: | @@ -91,7 +91,7 @@ jobs: make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B cd .. if: matrix.bits == 64 && matrix.ARCH == 'x86_64' - + - name: Build Library (64-bit ARM) run: | cd src @@ -99,7 +99,7 @@ jobs: make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B cd .. if: matrix.bits == 64 && matrix.ARCH == 'aarch64' - + - name: Generate Artifacts run: | cp -v ./src/raylib.h ./build/${{ env.RELEASE_NAME }}/include @@ -110,7 +110,7 @@ jobs: cp -v ./LICENSE ./build/${{ env.RELEASE_NAME }}/LICENSE cd build tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }} - + - name: Upload Artifacts uses: actions/upload-artifact@v4 with: @@ -118,7 +118,7 @@ jobs: path: | ./build/${{ env.RELEASE_NAME }} !./build/${{ env.RELEASE_NAME }}.tar.gz - + - name: Upload Artifact to Release uses: softprops/action-gh-release@v1 with: diff --git a/.github/workflows/build_macos.yml b/.github/workflows/build_macos.yml index f27140107..08ea0188a 100644 --- a/.github/workflows/build_macos.yml +++ b/.github/workflows/build_macos.yml @@ -23,14 +23,14 @@ jobs: permissions: contents: write # for actions/upload-release-asset to upload release asset runs-on: macos-latest - + env: RELEASE_NAME: raylib-dev_macos - + steps: - name: Checkout uses: actions/checkout@master - + - name: Setup Release Version run: | echo "RELEASE_NAME=raylib-${{ github.event.release.tag_name }}_macos" >> $GITHUB_ENV @@ -38,7 +38,7 @@ jobs: if: github.event_name == 'release' && github.event.action == 'published' - name: Setup Environment - run: | + run: | mkdir build cd build mkdir ${{ env.RELEASE_NAME }} @@ -46,47 +46,47 @@ jobs: mkdir include mkdir lib cd ../.. - + # Generating static + shared library, note that i386 architecture is deprecated # Defining GL_SILENCE_DEPRECATION because OpenGL is deprecated on macOS - name: Build Library run: | cd src clang --version - + # Extract version numbers from Makefile brew install grep RAYLIB_API_VERSION=`ggrep -Po 'RAYLIB_API_VERSION\s*=\s\K(.*)' Makefile` RAYLIB_VERSION=`ggrep -Po 'RAYLIB_VERSION\s*=\s\K(.*)' Makefile` - + # Build raylib x86_64 static make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC CUSTOM_CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION" mv libraylib.a /tmp/libraylib_x86_64.a make clean - + # Build raylib arm64 static make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC CUSTOM_CFLAGS="-target arm64-apple-macos11 -DGL_SILENCE_DEPRECATION" -B mv libraylib.a /tmp/libraylib_arm64.a make clean - + # Join x86_64 and arm64 static lipo -create -output ../build/${{ env.RELEASE_NAME }}/lib/libraylib.a /tmp/libraylib_x86_64.a /tmp/libraylib_arm64.a - + # Build raylib x86_64 dynamic make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED CUSTOM_CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION" CUSTOM_LDFLAGS="-target x86_64-apple-macos10.12" -B mv libraylib.${RAYLIB_VERSION}.dylib /tmp/libraylib_x86_64.${RAYLIB_VERSION}.dylib make clean - + # Build raylib arm64 dynamic make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED CUSTOM_CFLAGS="-target arm64-apple-macos11 -DGL_SILENCE_DEPRECATION" CUSTOM_LDFLAGS="-target arm64-apple-macos11" -B mv libraylib.${RAYLIB_VERSION}.dylib /tmp/libraylib_arm64.${RAYLIB_VERSION}.dylib - + # Join x86_64 and arm64 dynamic lipo -create -output ../build/${{ env.RELEASE_NAME }}/lib/libraylib.${RAYLIB_VERSION}.dylib /tmp/libraylib_x86_64.${RAYLIB_VERSION}.dylib /tmp/libraylib_arm64.${RAYLIB_VERSION}.dylib ln -sv libraylib.${RAYLIB_VERSION}.dylib ../build/${{ env.RELEASE_NAME }}/lib/libraylib.dylib ln -sv libraylib.${RAYLIB_VERSION}.dylib ../build/${{ env.RELEASE_NAME }}/lib/libraylib.${RAYLIB_API_VERSION}.dylib cd .. - + - name: Generate Artifacts run: | cp -v ./src/raylib.h ./build/${{ env.RELEASE_NAME }}/include @@ -97,7 +97,7 @@ jobs: cp -v ./LICENSE ./build/${{ env.RELEASE_NAME }}/LICENSE cd build tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }} - + - name: Upload Artifacts uses: actions/upload-artifact@v4 with: @@ -105,7 +105,7 @@ jobs: path: | ./build/${{ env.RELEASE_NAME }} !./build/${{ env.RELEASE_NAME }}.tar.gz - + - name: Upload Artifact to Release uses: softprops/action-gh-release@v1 with: diff --git a/.github/workflows/update_examples.yml b/.github/workflows/update_examples.yml index c4ada2bd1..fe8e4c48f 100644 --- a/.github/workflows/update_examples.yml +++ b/.github/workflows/update_examples.yml @@ -12,11 +12,11 @@ on: jobs: build: runs-on: ubuntu-latest - + steps: - name: Checkout uses: actions/checkout@v4 - + - name: Setup emsdk uses: mymindstorm/setup-emsdk@v14 with: diff --git a/projects/4coder/main.c b/projects/4coder/main.c index e33f9a1db..78e1519cb 100644 --- a/projects/4coder/main.c +++ b/projects/4coder/main.c @@ -34,7 +34,7 @@ int main() DrawFPS(10, 10); EndDrawing(); } - + CloseWindow(); return 0; } diff --git a/projects/Geany/core_basic_window.c b/projects/Geany/core_basic_window.c index 486f899cb..8ec817532 100644 --- a/projects/Geany/core_basic_window.c +++ b/projects/Geany/core_basic_window.c @@ -19,7 +19,7 @@ int main() int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); - + SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -44,7 +44,7 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/projects/Notepad++/raylib_npp_parser/raylib_npp_parser.c b/projects/Notepad++/raylib_npp_parser/raylib_npp_parser.c index e2e256c98..a7a6663c0 100644 --- a/projects/Notepad++/raylib_npp_parser/raylib_npp_parser.c +++ b/projects/Notepad++/raylib_npp_parser/raylib_npp_parser.c @@ -15,9 +15,9 @@ - + NOTE: Generated XML text should be copied inside raylib\Notepad++\plugins\APIs\c.xml - + WARNING: Be careful with functions that split parameters into several lines, it breaks the process! LICENSE: zlib/libpng @@ -42,13 +42,13 @@ int main(int argc, char *argv[]) { FILE *rFile = fopen(argv[1], "rt"); FILE *rxmlFile = fopen("raylib_npp.xml", "wt"); - + if ((rFile == NULL) || (rxmlFile == NULL)) { printf("File could not be opened.\n"); return 0; } - + char *buffer = (char *)calloc(MAX_BUFFER_SIZE, 1); int count = 0; @@ -56,7 +56,7 @@ int main(int argc, char *argv[]) { // Read one full line fgets(buffer, MAX_BUFFER_SIZE, rFile); - + if (buffer[0] == '/') fprintf(rxmlFile, " \n", strlen(buffer) - 3, buffer + 2); else if (buffer[0] == '\n') fprintf(rxmlFile, "%s", buffer); // Direct copy of code comments else if (strncmp(buffer, "RLAPI", 5) == 0) // raylib function declaration @@ -65,33 +65,33 @@ int main(int argc, char *argv[]) char funcTypeAux[64]; char funcName[64]; char funcDesc[256]; - + char params[128]; char paramType[16][16]; char paramName[16][32]; - + int index = 0; char *ptr = NULL; - + sscanf(buffer, "RLAPI %s %[^(]s", funcType, funcName); - + if (strcmp(funcType, "const") == 0) - { + { sscanf(buffer, "RLAPI %s %s %[^(]s", funcType, funcTypeAux, funcName); strcat(funcType, " "); strcat(funcType, funcTypeAux); } - + ptr = strchr(buffer, '/'); index = (int)(ptr - buffer); - + sscanf(buffer + index, "%[^\n]s", funcDesc); // Read function comment after declaration - + ptr = strchr(buffer, '('); - + if (ptr != NULL) index = (int)(ptr - buffer); else printf("Character not found!\n"); - + sscanf(buffer + (index + 1), "%[^)]s", params); // Read what's inside '(' and ')' // Scan params string for number of func params, type and name @@ -102,23 +102,23 @@ int main(int argc, char *argv[]) if ((funcName[0] == '*') && (funcName[1] == '*')) fprintf(rxmlFile, " \n", funcName + 2); else if (funcName[0] == '*') fprintf(rxmlFile, " \n", funcName + 1); else fprintf(rxmlFile, " \n", funcName); - + fprintf(rxmlFile, " ", funcType, funcDesc + 3); - + bool paramsVoid = false; - + char paramConst[8][16]; while (paramPtr[paramsCount] != NULL) { sscanf(paramPtr[paramsCount], "%s %s\n", paramType[paramsCount], paramName[paramsCount]); - + if (strcmp(paramType[paramsCount], "void") == 0) { paramsVoid = true; break; } - + if ((strcmp(paramType[paramsCount], "const") == 0) || (strcmp(paramType[paramsCount], "unsigned") == 0)) { sscanf(paramPtr[paramsCount], "%s %s %s\n", paramConst[paramsCount], paramType[paramsCount], paramName[paramsCount]); @@ -130,17 +130,17 @@ int main(int argc, char *argv[]) paramsCount++; paramPtr[paramsCount] = strtok(NULL, ","); } - + fprintf(rxmlFile, "%s\n", paramsVoid ? "" : "\n "); fprintf(rxmlFile, " \n"); count++; printf("Function processed %02i: %s\n", count, funcName); - + memset(buffer, 0, MAX_BUFFER_SIZE); } } - + free(buffer); fclose(rFile); fclose(rxmlFile); diff --git a/src/raudio.c b/src/raudio.c index 00e819466..cd37ca305 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -2184,14 +2184,14 @@ void UpdateAudioStream(AudioStream stream, const void *data, int frameCount) bool IsAudioStreamProcessed(AudioStream stream) { bool result = false; - + if (stream.buffer != NULL) { ma_mutex_lock(&AUDIO.System.lock); result = stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1]; ma_mutex_unlock(&AUDIO.System.lock); } - + return result; } @@ -2885,7 +2885,7 @@ static unsigned char *LoadFileData(const char *fileName, int *dataSize) static bool SaveFileData(const char *fileName, void *data, int dataSize) { bool result = true; - + if (fileName != NULL) { FILE *file = fopen(fileName, "wb"); @@ -2919,7 +2919,7 @@ static bool SaveFileData(const char *fileName, void *data, int dataSize) static bool SaveFileText(const char *fileName, char *text) { bool result = true; - + if (fileName != NULL) { FILE *file = fopen(fileName, "wt"); diff --git a/src/rshapes.c b/src/rshapes.c index 268da45f1..0a927a1d7 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -2440,7 +2440,7 @@ bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 float dx2 = (p1.x - (dotProduct*(dx))) - center.x; float dy2 = (p1.y - (dotProduct*(dy))) - center.y; float distanceSQ = ((dx2*dx2) + (dy2*dy2)); - + if (distanceSQ <= radius*radius) collision = true; } diff --git a/src/rtext.c b/src/rtext.c index 3f4c993c3..f71991e33 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -1785,7 +1785,7 @@ char *TextReplace(const char *text, const char *search, const char *replacement) // Count the number of replacements needed insertPoint = (char *)text; for (count = 0; (tempPtr = strstr(insertPoint, search)); count++) insertPoint = tempPtr + searchLen; - + if ((textLen + count*(replaceLen - searchLen)) < (MAX_TEXT_BUFFER_LENGTH - 1)) { // TODO: Allow copying data replaced up to maximum buffer size and stop @@ -1971,7 +1971,7 @@ char *TextInsert(const char *text, const char *insert, int position) { int textLen = TextLength(text); int insertLen = TextLength(insert); - + if ((textLen + insertLen) < (MAX_TEXT_BUFFER_LENGTH - 1)) { // TODO: Allow copying data inserted up to maximum buffer size and stop diff --git a/tools/rlparser/rlparser.c b/tools/rlparser/rlparser.c index e69f7ad56..c2aad0794 100644 --- a/tools/rlparser/rlparser.c +++ b/tools/rlparser/rlparser.c @@ -9,10 +9,10 @@ - struct AliasInfo - struct EnumInfo - struct FunctionInfo - + WARNING: This parser is specifically designed to work with raylib.h, and has some contraints in that regards. Still, it can also work with other header files that follow same file structure - conventions as raylib.h: rlgl.h, raymath.h, raygui.h, reasings.h + conventions as raylib.h: rlgl.h, raymath.h, raygui.h, reasings.h CONSTRAINTS: This parser is specifically designed to work with raylib.h, so, it has some constraints: From e3dcb144bc30e7e039bc36cafd499eb3ed68c39d Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 01:33:27 +0100 Subject: [PATCH 028/185] Update rexm.c --- tools/rexm/rexm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index 48a621115..d54760023 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -1572,13 +1572,13 @@ int main(int argc, char *argv[]) " SaveFileText(\"outputLogFileName\", logText);\n" " emscripten_run_script(\"saveFileFromMEMFSToDisk('outputLogFileName','outputLogFileName')\");\n\n" " return 0"; - char *returnReplaceTextUpdated = TextReplacEx(returnReplaceText, "outputLogFileName", TextFormat("%s.log", exName)); + char *returnReplaceTextUpdated = TextReplaceAlloc(returnReplaceText, "outputLogFileName", TextFormat("%s.log", exName)); char *srcTextUpdated[4] = { 0 }; - srcTextUpdated[0] = TextReplacEx(srcText, "int main(void)\n{", mainReplaceText); - srcTextUpdated[1] = TextReplacEx(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)"); - srcTextUpdated[2] = TextReplacEx(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;"); - srcTextUpdated[3] = TextReplacEx(srcTextUpdated[2], " return 0", returnReplaceTextUpdated); + srcTextUpdated[0] = TextReplaceAlloc(srcText, "int main(void)\n{", mainReplaceText); + srcTextUpdated[1] = TextReplaceAlloc(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)"); + srcTextUpdated[2] = TextReplaceAlloc(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;"); + srcTextUpdated[3] = TextReplaceAlloc(srcTextUpdated[2], " return 0", returnReplaceTextUpdated); MemFree(returnReplaceTextUpdated); UnloadFileText(srcText); @@ -1628,9 +1628,9 @@ int main(int argc, char *argv[]) " if ((argc > 1) && (argc == 3) && (strcmp(argv[1], \"--frames\") != 0)) requestedTestFrames = atoi(argv[2]);\n"; char *srcTextUpdated[3] = { 0 }; - srcTextUpdated[0] = TextReplacEx(srcText, "int main(void)\n{", mainReplaceText); - srcTextUpdated[1] = TextReplacEx(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)"); - srcTextUpdated[2] = TextReplacEx(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;"); + srcTextUpdated[0] = TextReplaceAlloc(srcText, "int main(void)\n{", mainReplaceText); + srcTextUpdated[1] = TextReplaceAlloc(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)"); + srcTextUpdated[2] = TextReplaceAlloc(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;"); UnloadFileText(srcText); SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), srcTextUpdated[2]); From d3cc78d9d79b3a786e0815fc19b94702cade6b44 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 01:44:33 +0100 Subject: [PATCH 029/185] Update rexm.c --- tools/rexm/rexm.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index d54760023..b160a9be1 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -2037,8 +2037,10 @@ static int UpdateRequiredFiles(void) // In this case, we focus on web building for: glsl100 if (TextFindIndex(resPaths[r], "glsl%i") > -1) { + char *resPathUpdated = TextReplaceAlloc(resPaths[r], "glsl%i", "glsl100"); memset(resPaths[r], 0, 256); - strcpy(resPaths[r], TextReplace(resPaths[r], "glsl%i", "glsl100")); + strcpy(resPaths[r], resPathUpdated); + RL_FREE(resPathUpdated); } if (r < (resPathCount - 1)) @@ -2140,7 +2142,7 @@ static int UpdateRequiredFiles(void) { mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex, TextFormat("\n### category: shaders [%i]\n\n", exCollectionCount)); mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex, - "Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.c) module.\n\n"); + "Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.h) module.\n\n"); } else if (i == 6) // "audio" { @@ -2903,14 +2905,14 @@ static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath) UnloadFileText(exText); // Update example.html required text - exHtmlTextUpdated[0] = TextReplace(exHtmlText, "raylib web game", exTitle); - exHtmlTextUpdated[1] = TextReplace(exHtmlTextUpdated[0], "New raylib web videogame, developed using raylib videogames library", exDescription); - exHtmlTextUpdated[2] = TextReplace(exHtmlTextUpdated[1], "https://www.raylib.com/common/raylib_logo.png", + exHtmlTextUpdated[0] = TextReplaceAlloc(exHtmlText, "raylib web game", exTitle); + exHtmlTextUpdated[1] = TextReplaceAlloc(exHtmlTextUpdated[0], "New raylib web videogame, developed using raylib videogames library", exDescription); + exHtmlTextUpdated[2] = TextReplaceAlloc(exHtmlTextUpdated[1], "https://www.raylib.com/common/raylib_logo.png", TextFormat("https://raw.githubusercontent.com/raysan5/raylib/master/examples/%s/%s.png", exCategory, exName)); - exHtmlTextUpdated[3] = TextReplace(exHtmlTextUpdated[2], "https://www.raylib.com/games.html", + exHtmlTextUpdated[3] = TextReplaceAlloc(exHtmlTextUpdated[2], "https://www.raylib.com/games.html", TextFormat("https://www.raylib.com/examples/%s/%s.html", exCategory, exName)); - exHtmlTextUpdated[4] = TextReplace(exHtmlTextUpdated[3], "raylib - example", TextFormat("raylib - %s", exName)); // og:site_name - exHtmlTextUpdated[5] = TextReplace(exHtmlTextUpdated[4], "https://github.com/raysan5/raylib", + exHtmlTextUpdated[4] = TextReplaceAlloc(exHtmlTextUpdated[3], "raylib - example", TextFormat("raylib - %s", exName)); // og:site_name + exHtmlTextUpdated[5] = TextReplaceAlloc(exHtmlTextUpdated[4], "https://github.com/raysan5/raylib", TextFormat("https://github.com/raysan5/raylib/blob/master/examples/%s/%s.c", exCategory, exName)); SaveFileText(exHtmlPathCopy, exHtmlTextUpdated[5]); From a1bf8d9c752041423a245a21bce73274a9215c9e Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:17:51 +0200 Subject: [PATCH 030/185] Update cgltf.h --- src/external/cgltf.h | 211 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 185 insertions(+), 26 deletions(-) diff --git a/src/external/cgltf.h b/src/external/cgltf.h index 36fd644e1..316a11dfd 100644 --- a/src/external/cgltf.h +++ b/src/external/cgltf.h @@ -1,7 +1,7 @@ /** * cgltf - a single-file glTF 2.0 parser written in C99. * - * Version: 1.14 + * Version: 1.15 * * Website: https://github.com/jkuhlmann/cgltf * @@ -141,7 +141,7 @@ typedef struct cgltf_memory_options typedef struct cgltf_file_options { cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data); - void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data); + void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size); void* user_data; } cgltf_file_options; @@ -296,6 +296,7 @@ typedef enum cgltf_meshopt_compression_filter { cgltf_meshopt_compression_filter_octahedral, cgltf_meshopt_compression_filter_quaternion, cgltf_meshopt_compression_filter_exponential, + cgltf_meshopt_compression_filter_color, cgltf_meshopt_compression_filter_max_enum } cgltf_meshopt_compression_filter; @@ -308,6 +309,7 @@ typedef struct cgltf_meshopt_compression cgltf_size count; cgltf_meshopt_compression_mode mode; cgltf_meshopt_compression_filter filter; + cgltf_bool is_khr; } cgltf_meshopt_compression; typedef struct cgltf_buffer_view @@ -376,13 +378,29 @@ typedef struct cgltf_image cgltf_extension* extensions; } cgltf_image; +typedef enum cgltf_filter_type { + cgltf_filter_type_undefined = 0, + cgltf_filter_type_nearest = 9728, + cgltf_filter_type_linear = 9729, + cgltf_filter_type_nearest_mipmap_nearest = 9984, + cgltf_filter_type_linear_mipmap_nearest = 9985, + cgltf_filter_type_nearest_mipmap_linear = 9986, + cgltf_filter_type_linear_mipmap_linear = 9987 +} cgltf_filter_type; + +typedef enum cgltf_wrap_mode { + cgltf_wrap_mode_clamp_to_edge = 33071, + cgltf_wrap_mode_mirrored_repeat = 33648, + cgltf_wrap_mode_repeat = 10497 +} cgltf_wrap_mode; + typedef struct cgltf_sampler { char* name; - cgltf_int mag_filter; - cgltf_int min_filter; - cgltf_int wrap_s; - cgltf_int wrap_t; + cgltf_filter_type mag_filter; + cgltf_filter_type min_filter; + cgltf_wrap_mode wrap_s; + cgltf_wrap_mode wrap_t; cgltf_extras extras; cgltf_size extensions_count; cgltf_extension* extensions; @@ -500,6 +518,14 @@ typedef struct cgltf_iridescence cgltf_texture_view iridescence_thickness_texture; } cgltf_iridescence; +typedef struct cgltf_diffuse_transmission +{ + cgltf_texture_view diffuse_transmission_texture; + cgltf_float diffuse_transmission_factor; + cgltf_float diffuse_transmission_color_factor[3]; + cgltf_texture_view diffuse_transmission_color_texture; +} cgltf_diffuse_transmission; + typedef struct cgltf_anisotropy { cgltf_float anisotropy_strength; @@ -525,6 +551,7 @@ typedef struct cgltf_material cgltf_bool has_sheen; cgltf_bool has_emissive_strength; cgltf_bool has_iridescence; + cgltf_bool has_diffuse_transmission; cgltf_bool has_anisotropy; cgltf_bool has_dispersion; cgltf_pbr_metallic_roughness pbr_metallic_roughness; @@ -537,6 +564,7 @@ typedef struct cgltf_material cgltf_volume volume; cgltf_emissive_strength emissive_strength; cgltf_iridescence iridescence; + cgltf_diffuse_transmission diffuse_transmission; cgltf_anisotropy anisotropy; cgltf_dispersion dispersion; cgltf_texture_view normal_texture; @@ -743,6 +771,7 @@ typedef struct cgltf_data { cgltf_file_type file_type; void* file_data; + cgltf_size file_size; cgltf_asset asset; @@ -844,6 +873,8 @@ void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix) const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view); +const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index); + cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size); cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size); cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index); @@ -1071,9 +1102,10 @@ static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* m return cgltf_result_success; } -static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data) +static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size) { (void)file_options; + (void)size; void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free; memfree(memory_options->user_data, data); } @@ -1220,7 +1252,7 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg } cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read; - void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = options->file.release ? options->file.release : cgltf_default_file_release; + void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = options->file.release ? options->file.release : cgltf_default_file_release; void* file_data = NULL; cgltf_size file_size = 0; @@ -1234,11 +1266,12 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg if (result != cgltf_result_success) { - file_release(&options->memory, &options->file, file_data); + file_release(&options->memory, &options->file, file_data, file_size); return result; } (*out_data)->file_data = file_data; + (*out_data)->file_size = file_size; return cgltf_result_success; } @@ -1630,8 +1663,8 @@ cgltf_result cgltf_validate(cgltf_data* data) CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->filter != cgltf_meshopt_compression_filter_none, cgltf_result_invalid_gltf); CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf); - CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf); + CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_color && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf); } } @@ -1822,7 +1855,7 @@ void cgltf_free(cgltf_data* data) return; } - void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = data->file.release ? data->file.release : cgltf_default_file_release; + void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = data->file.release ? data->file.release : cgltf_default_file_release; data->memory.free_func(data->memory.user_data, data->asset.copyright); data->memory.free_func(data->memory.user_data, data->asset.generator); @@ -1857,7 +1890,7 @@ void cgltf_free(cgltf_data* data) if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release) { - file_release(&data->memory, &data->file, data->buffers[i].data); + file_release(&data->memory, &data->file, data->buffers[i].data, data->buffers[i].size); } else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free) { @@ -2096,7 +2129,7 @@ void cgltf_free(cgltf_data* data) data->memory.free_func(data->memory.user_data, data->extensions_required); - file_release(&data->memory, &data->file, data->file_data); + file_release(&data->memory, &data->file, data->file_data, data->file_size); data->memory.free_func(data->memory.user_data, data); } @@ -2312,11 +2345,58 @@ const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view) return result; } +const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index) +{ + for (cgltf_size i = 0; i < prim->attributes_count; ++i) + { + const cgltf_attribute* attr = &prim->attributes[i]; + if (attr->type == type && attr->index == index) + return attr->data; + } + + return NULL; +} + +static const uint8_t* cgltf_find_sparse_index(const cgltf_accessor* accessor, cgltf_size needle) +{ + const cgltf_accessor_sparse* sparse = &accessor->sparse; + const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view); + const uint8_t* value_data = cgltf_buffer_view_data(sparse->values_buffer_view); + + if (index_data == NULL || value_data == NULL) + return NULL; + + index_data += sparse->indices_byte_offset; + value_data += sparse->values_byte_offset; + + cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type); + + cgltf_size offset = 0; + cgltf_size length = sparse->count; + + while (length) + { + cgltf_size rem = length % 2; + length /= 2; + + cgltf_size index = cgltf_component_read_index(index_data + (offset + length) * index_stride, sparse->indices_component_type); + offset += index < needle ? length + rem : 0; + } + + if (offset == sparse->count) + return NULL; + + cgltf_size index = cgltf_component_read_index(index_data + offset * index_stride, sparse->indices_component_type); + return index == needle ? value_data + offset * accessor->stride : NULL; +} + cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size) { if (accessor->is_sparse) { - return 0; + const uint8_t* element = cgltf_find_sparse_index(accessor, index); + if (element) + return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size); } if (accessor->buffer_view == NULL) { @@ -2460,11 +2540,13 @@ cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size i { if (accessor->is_sparse) { - return 0; + const uint8_t* element = cgltf_find_sparse_index(accessor, index); + if (element) + return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size); } if (accessor->buffer_view == NULL) { - memset(out, 0, element_size * sizeof( cgltf_uint )); + memset(out, 0, element_size * sizeof(cgltf_uint)); return 1; } const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view); @@ -2480,7 +2562,9 @@ cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size { if (accessor->is_sparse) { - return 0; // This is an error case, but we can't communicate the error with existing interface. + const uint8_t* element = cgltf_find_sparse_index(accessor, index); + if (element) + return cgltf_component_read_index(element, accessor->component_type); } if (accessor->buffer_view == NULL) { @@ -2598,7 +2682,10 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o return accessor->count; } - index_count = accessor->count < index_count ? accessor->count : index_count; + cgltf_size numbers_per_element = cgltf_num_components(accessor->type); + cgltf_size available_numbers = accessor->count * numbers_per_element; + + index_count = available_numbers < index_count ? available_numbers : index_count; cgltf_size index_component_size = cgltf_component_size(accessor->component_type); if (accessor->is_sparse) @@ -2620,15 +2707,23 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o } element += accessor->offset; - if (index_component_size == out_component_size && accessor->stride == out_component_size) + if (index_component_size == out_component_size && accessor->stride == out_component_size * numbers_per_element) { memcpy(out, element, index_count * index_component_size); return index_count; } + // Data couldn't be copied with memcpy due to stride being larger than the component size. + // OR // The component size of the output array is larger than the component size of the index data, so index data will be padded. switch (out_component_size) { + case 1: + for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride) + { + ((uint8_t*)out)[index] = (uint8_t)cgltf_component_read_index(element, accessor->component_type); + } + break; case 2: for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride) { @@ -2642,7 +2737,7 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o } break; default: - break; + return 0; } return index_count; @@ -4278,6 +4373,52 @@ static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const* return i; } +static int cgltf_parse_json_diffuse_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_diffuse_transmission* out_diff_transmission) +{ + CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); + int size = tokens[i].size; + ++i; + + // Defaults + cgltf_fill_float_array(out_diff_transmission->diffuse_transmission_color_factor, 3, 1.0f); + out_diff_transmission->diffuse_transmission_factor = 0.f; + + for (int j = 0; j < size; ++j) + { + CGLTF_CHECK_KEY(tokens[i]); + + if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionFactor") == 0) + { + ++i; + out_diff_transmission->diffuse_transmission_factor = cgltf_json_to_float(tokens + i, json_chunk); + ++i; + } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionTexture") == 0) + { + i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_texture); + } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorFactor") == 0) + { + i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_diff_transmission->diffuse_transmission_color_factor, 3); + } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorTexture") == 0) + { + i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_color_texture); + } + else + { + i = cgltf_skip_json(tokens, i + 1); + } + + if (i < 0) + { + return i; + } + } + + return i; +} + static int cgltf_parse_json_anisotropy(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_anisotropy* out_anisotropy) { CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); @@ -4406,8 +4547,8 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok (void)options; CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); - out_sampler->wrap_s = 10497; - out_sampler->wrap_t = 10497; + out_sampler->wrap_s = cgltf_wrap_mode_repeat; + out_sampler->wrap_t = cgltf_wrap_mode_repeat; int size = tokens[i].size; ++i; @@ -4424,28 +4565,28 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok { ++i; out_sampler->mag_filter - = cgltf_json_to_int(tokens + i, json_chunk); + = (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0) { ++i; out_sampler->min_filter - = cgltf_json_to_int(tokens + i, json_chunk); + = (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0) { ++i; out_sampler->wrap_s - = cgltf_json_to_int(tokens + i, json_chunk); + = (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0) { ++i; out_sampler->wrap_t - = cgltf_json_to_int(tokens + i, json_chunk); + = (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) @@ -4766,6 +4907,11 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to out_material->has_iridescence = 1; i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence); } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_diffuse_transmission") == 0) + { + out_material->has_diffuse_transmission = 1; + i = cgltf_parse_json_diffuse_transmission(options, tokens, i + 1, json_chunk, &out_material->diffuse_transmission); + } else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_anisotropy") == 0) { out_material->has_anisotropy = 1; @@ -4974,6 +5120,10 @@ static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_ { out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential; } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "COLOR") == 0) + { + out_meshopt_compression->filter = cgltf_meshopt_compression_filter_color; + } ++i; } else @@ -5084,6 +5234,12 @@ static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const* out_buffer_view->has_meshopt_compression = 1; i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression); } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_meshopt_compression") == 0) + { + out_buffer_view->has_meshopt_compression = 1; + out_buffer_view->meshopt_compression.is_khr = 1; + i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression); + } else { i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++])); @@ -6629,6 +6785,9 @@ static int cgltf_fixup_pointers(cgltf_data* data) CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count); CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_color_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count); } From 0b87a35e5a6ba6a663daeba7cc2e73dd2cbc1c4d Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:18:28 +0200 Subject: [PATCH 031/185] Update dr_flac.h --- src/external/dr_flac.h | 306 +++++++++++++++++++++++++++-------------- 1 file changed, 205 insertions(+), 101 deletions(-) diff --git a/src/external/dr_flac.h b/src/external/dr_flac.h index 497fcddd5..2891194c7 100644 --- a/src/external/dr_flac.h +++ b/src/external/dr_flac.h @@ -1,6 +1,6 @@ /* FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file. -dr_flac - v0.13.0 - TBD +dr_flac - v0.13.3 - 2026-01-17 David Reid - mackron@gmail.com @@ -126,7 +126,7 @@ extern "C" { #define DRFLAC_VERSION_MAJOR 0 #define DRFLAC_VERSION_MINOR 13 -#define DRFLAC_VERSION_REVISION 0 +#define DRFLAC_VERSION_REVISION 3 #define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION) #include /* For size_t. */ @@ -331,6 +331,12 @@ typedef struct */ drflac_uint32 type; + /* The size in bytes of the block and the buffer pointed to by pRawData if it's non-NULL. */ + drflac_uint32 rawDataSize; + + /* The offset in the stream of the raw data. */ + drflac_uint64 rawDataOffset; + /* A pointer to the raw data. This points to a temporary buffer so don't hold on to it. It's best to not modify the contents of this buffer. Use the structures below for more meaningful and structured @@ -338,9 +344,6 @@ typedef struct */ const void* pRawData; - /* The size in bytes of the block and the buffer pointed to by pRawData if it's non-NULL. */ - drflac_uint32 rawDataSize; - union { drflac_streaminfo streaminfo; @@ -392,6 +395,7 @@ typedef struct drflac_uint32 colorDepth; drflac_uint32 indexColorCount; drflac_uint32 pictureDataSize; + drflac_uint64 pictureDataOffset; /* Offset from the start of the stream. */ const drflac_uint8* pPictureData; } picture; } data; @@ -2712,9 +2716,17 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x) #if defined(__GNUC__) || defined(__clang__) #if defined(DRFLAC_X64) { + /* + A note on lzcnt. + + We check for the presence of the lzcnt instruction at runtime before calling this function, but we still generate this code. I have had + a report where the assembler does not recognize the lzcnt instruction. To work around this we are going to use `rep; bsr` instead which + has an identical byte encoding as lzcnt, and should hopefully improve compatibility with older assemblers. + */ drflac_uint64 r; __asm__ __volatile__ ( - "lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc" + "rep; bsr{q %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc" + /*"lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"*/ ); return (drflac_uint32)r; @@ -2723,12 +2735,13 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x) { drflac_uint32 r; __asm__ __volatile__ ( - "lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc" + "rep; bsr{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc" + /*"lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"*/ ); return r; } - #elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !defined(DRFLAC_64BIT) /* <-- I haven't tested 64-bit inline assembly, so only enabling this for the 32-bit build for now. */ + #elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !(defined(__thumb__) && !defined(__thumb2__)) && !defined(DRFLAC_64BIT) /* <-- I haven't tested 64-bit inline assembly, so only enabling this for the 32-bit build for now. */ { unsigned int r; __asm__ __volatile__ ( @@ -6434,8 +6447,9 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d runningFilePos += 4; metadata.type = blockType; - metadata.pRawData = NULL; metadata.rawDataSize = 0; + metadata.rawDataOffset = runningFilePos; + metadata.pRawData = NULL; switch (blockType) { @@ -6712,59 +6726,151 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d } if (onMeta) { - void* pRawData; - const char* pRunningData; - const char* pRunningDataEnd; + drflac_bool32 result = DRFLAC_TRUE; + drflac_uint32 blockSizeRemaining = blockSize; + char* pMime = NULL; + char* pDescription = NULL; + void* pPictureData = NULL; - pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks); - if (pRawData == NULL) { - return DRFLAC_FALSE; + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.type, 4) != 4) { + result = DRFLAC_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.type = drflac__be2host_32(metadata.data.picture.type); + + + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.mimeLength, 4) != 4) { + result = DRFLAC_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.mimeLength = drflac__be2host_32(metadata.data.picture.mimeLength); + + pMime = (char*)drflac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); /* +1 for null terminator. */ + if (pMime == NULL) { + result = DRFLAC_FALSE; + goto done_flac; } - if (onRead(pUserData, pRawData, blockSize) != blockSize) { - drflac__free_from_callbacks(pRawData, pAllocationCallbacks); - return DRFLAC_FALSE; + if (blockSizeRemaining < metadata.data.picture.mimeLength || onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) { + result = DRFLAC_FALSE; + goto done_flac; + } + blockSizeRemaining -= metadata.data.picture.mimeLength; + pMime[metadata.data.picture.mimeLength] = '\0'; /* Null terminate for safety. */ + metadata.data.picture.mime = (const char*)pMime; + + + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.descriptionLength, 4) != 4) { + result = DRFLAC_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.descriptionLength = drflac__be2host_32(metadata.data.picture.descriptionLength); + + pDescription = (char*)drflac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); /* +1 for null terminator. */ + if (pDescription == NULL) { + result = DRFLAC_FALSE; + goto done_flac; } - metadata.pRawData = pRawData; - metadata.rawDataSize = blockSize; - - pRunningData = (const char*)pRawData; - pRunningDataEnd = (const char*)pRawData + blockSize; - - metadata.data.picture.type = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.mimeLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - - /* Need space for the rest of the block */ - if ((pRunningDataEnd - pRunningData) - 24 < (drflac_int64)metadata.data.picture.mimeLength) { /* <-- Note the order of operations to avoid overflow to a valid value */ - drflac__free_from_callbacks(pRawData, pAllocationCallbacks); - return DRFLAC_FALSE; + if (blockSizeRemaining < metadata.data.picture.descriptionLength || onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) { + result = DRFLAC_FALSE; + goto done_flac; } - metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength; - metadata.data.picture.descriptionLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; + blockSizeRemaining -= metadata.data.picture.descriptionLength; + pDescription[metadata.data.picture.descriptionLength] = '\0'; /* Null terminate for safety. */ + metadata.data.picture.description = (const char*)pDescription; - /* Need space for the rest of the block */ - if ((pRunningDataEnd - pRunningData) - 20 < (drflac_int64)metadata.data.picture.descriptionLength) { /* <-- Note the order of operations to avoid overflow to a valid value */ - drflac__free_from_callbacks(pRawData, pAllocationCallbacks); - return DRFLAC_FALSE; + + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.width, 4) != 4) { + result = DRFLAC_FALSE; + goto done_flac; } - metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength; - metadata.data.picture.width = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.height = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.colorDepth = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.indexColorCount = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.pictureDataSize = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData; + blockSizeRemaining -= 4; + metadata.data.picture.width = drflac__be2host_32(metadata.data.picture.width); - /* Need space for the picture after the block */ - if (pRunningDataEnd - pRunningData < (drflac_int64)metadata.data.picture.pictureDataSize) { /* <-- Note the order of operations to avoid overflow to a valid value */ - drflac__free_from_callbacks(pRawData, pAllocationCallbacks); - return DRFLAC_FALSE; + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.height, 4) != 4) { + result = DRFLAC_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.height = drflac__be2host_32(metadata.data.picture.height); + + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.colorDepth, 4) != 4) { + result = DRFLAC_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.colorDepth = drflac__be2host_32(metadata.data.picture.colorDepth); + + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.indexColorCount, 4) != 4) { + result = DRFLAC_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.indexColorCount = drflac__be2host_32(metadata.data.picture.indexColorCount); + + + /* Picture data. */ + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.pictureDataSize, 4) != 4) { + result = DRFLAC_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.pictureDataSize = drflac__be2host_32(metadata.data.picture.pictureDataSize); + + if (blockSizeRemaining < metadata.data.picture.pictureDataSize) { + result = DRFLAC_FALSE; + goto done_flac; } - onMeta(pUserDataMD, &metadata); + /* For the actual image data we want to store the offset to the start of the stream. */ + metadata.data.picture.pictureDataOffset = runningFilePos + (blockSize - blockSizeRemaining); - drflac__free_from_callbacks(pRawData, pAllocationCallbacks); + /* + For the allocation of image data, we can allow memory allocation to fail, in which case we just leave + the pointer as null. If it fails, we need to fall back to seeking past the image data. + */ + #ifndef DR_FLAC_NO_PICTURE_METADATA_MALLOC + pPictureData = drflac__malloc_from_callbacks(metadata.data.picture.pictureDataSize, pAllocationCallbacks); + if (pPictureData != NULL) { + if (onRead(pUserData, pPictureData, metadata.data.picture.pictureDataSize) != metadata.data.picture.pictureDataSize) { + result = DRFLAC_FALSE; + goto done_flac; + } + } else + #endif + { + /* Allocation failed. We need to seek past the picture data. */ + if (!onSeek(pUserData, metadata.data.picture.pictureDataSize, DRFLAC_SEEK_CUR)) { + result = DRFLAC_FALSE; + goto done_flac; + } + } + + blockSizeRemaining -= metadata.data.picture.pictureDataSize; + (void)blockSizeRemaining; + + metadata.data.picture.pPictureData = (const drflac_uint8*)pPictureData; + + + /* Only fire the callback if we actually have a way to read the image data. We must have either a valid offset, or a valid data pointer. */ + if (metadata.data.picture.pictureDataOffset != 0 || metadata.data.picture.pPictureData != NULL) { + onMeta(pUserDataMD, &metadata); + } else { + /* Don't have a valid offset or data pointer, so just pretend we don't have a picture metadata. */ + } + + done_flac: + drflac__free_from_callbacks(pMime, pAllocationCallbacks); + drflac__free_from_callbacks(pDescription, pAllocationCallbacks); + drflac__free_from_callbacks(pPictureData, pAllocationCallbacks); + + if (result != DRFLAC_TRUE) { + return DRFLAC_FALSE; + } } } break; @@ -6800,13 +6906,16 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d */ if (onMeta) { void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks); - if (pRawData == NULL) { - return DRFLAC_FALSE; - } - - if (onRead(pUserData, pRawData, blockSize) != blockSize) { - drflac__free_from_callbacks(pRawData, pAllocationCallbacks); - return DRFLAC_FALSE; + if (pRawData != NULL) { + if (onRead(pUserData, pRawData, blockSize) != blockSize) { + drflac__free_from_callbacks(pRawData, pAllocationCallbacks); + return DRFLAC_FALSE; + } + } else { + /* Allocation failed. We need to seek past the block. */ + if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) { + return DRFLAC_FALSE; + } } metadata.pRawData = pRawData; @@ -8699,7 +8808,7 @@ static drflac_bool32 drflac__on_tell_stdio(void* pUserData, drflac_int64* pCurso DRFLAC_ASSERT(pFileStdio != NULL); DRFLAC_ASSERT(pCursor != NULL); -#if defined(_WIN32) +#if defined(_WIN32) && !defined(NXDK) #if defined(_MSC_VER) && _MSC_VER > 1200 result = _ftelli64(pFileStdio); #else @@ -8821,8 +8930,6 @@ static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_ DRFLAC_ASSERT(memoryStream != NULL); - newCursor = memoryStream->currentReadPos; - if (origin == DRFLAC_SEEK_SET) { newCursor = 0; } else if (origin == DRFLAC_SEEK_CUR) { @@ -11702,58 +11809,43 @@ static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned { \ type* pSampleData = NULL; \ drflac_uint64 totalPCMFrameCount; \ + type buffer[4096]; \ + drflac_uint64 pcmFramesRead; \ + size_t sampleDataBufferSize = sizeof(buffer); \ \ DRFLAC_ASSERT(pFlac != NULL); \ \ - totalPCMFrameCount = pFlac->totalPCMFrameCount; \ + totalPCMFrameCount = 0; \ \ - if (totalPCMFrameCount == 0) { \ - type buffer[4096]; \ - drflac_uint64 pcmFramesRead; \ - size_t sampleDataBufferSize = sizeof(buffer); \ + pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \ + if (pSampleData == NULL) { \ + goto on_error; \ + } \ \ - pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \ - if (pSampleData == NULL) { \ - goto on_error; \ - } \ + while ((pcmFramesRead = (drflac_uint64)drflac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \ + if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \ + type* pNewSampleData; \ + size_t newSampleDataBufferSize; \ \ - while ((pcmFramesRead = (drflac_uint64)drflac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \ - if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \ - type* pNewSampleData; \ - size_t newSampleDataBufferSize; \ - \ - newSampleDataBufferSize = sampleDataBufferSize * 2; \ - pNewSampleData = (type*)drflac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \ - if (pNewSampleData == NULL) { \ - drflac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \ - goto on_error; \ - } \ - \ - sampleDataBufferSize = newSampleDataBufferSize; \ - pSampleData = pNewSampleData; \ + newSampleDataBufferSize = sampleDataBufferSize * 2; \ + pNewSampleData = (type*)drflac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \ + if (pNewSampleData == NULL) { \ + drflac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \ + goto on_error; \ } \ \ - DRFLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \ - totalPCMFrameCount += pcmFramesRead; \ + sampleDataBufferSize = newSampleDataBufferSize; \ + pSampleData = pNewSampleData; \ } \ \ - /* At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to \ - protect those ears from random noise! */ \ - DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \ - } else { \ - drflac_uint64 dataSize = totalPCMFrameCount*pFlac->channels*sizeof(type); \ - if (dataSize > (drflac_uint64)DRFLAC_SIZE_MAX) { \ - goto on_error; /* The decoded data is too big. */ \ - } \ - \ - pSampleData = (type*)drflac__malloc_from_callbacks((size_t)dataSize, &pFlac->allocationCallbacks); /* <-- Safe cast as per the check above. */ \ - if (pSampleData == NULL) { \ - goto on_error; \ - } \ - \ - totalPCMFrameCount = drflac_read_pcm_frames_##extension(pFlac, pFlac->totalPCMFrameCount, pSampleData); \ + DRFLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \ + totalPCMFrameCount += pcmFramesRead; \ } \ \ + /* At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to \ + protect those ears from random noise! */ \ + DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \ + \ if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \ if (channelsOut) *channelsOut = pFlac->channels; \ if (totalPCMFrameCountOut) *totalPCMFrameCountOut = totalPCMFrameCount; \ @@ -12077,7 +12169,19 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat /* REVISION HISTORY ================ -v0.13.0 - TBD +v0.13.3 - 2026-01-17 + - Fix a compiler compatibility issue with some inlined assembly. + - Fix a compilation warning. + +v0.13.2 - 2025-12-02 + - Improve robustness of the parsing of picture metadata to improve support for memory constrained embedded devices. + - Fix a warning about an assigned by unused variable. + - Improvements to drflac_open_and_read_pcm_frames_*() and family to avoid excessively large memory allocations from malformed files. + +v0.13.1 - 2025-09-10 + - Fix an error with the NXDK build. + +v0.13.0 - 2025-07-23 - API CHANGE: Seek origin enums have been renamed to match the naming convention used by other dr_libs libraries: - drflac_seek_origin_start -> DRFLAC_SEEK_SET - drflac_seek_origin_current -> DRFLAC_SEEK_CUR From b09da8fce8e2f31cdd0b5a98c9187d2fec49aca3 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:18:56 +0200 Subject: [PATCH 032/185] Update dr_mp3.h --- src/external/dr_mp3.h | 171 ++++++++++++++++++++++++++---------------- 1 file changed, 108 insertions(+), 63 deletions(-) diff --git a/src/external/dr_mp3.h b/src/external/dr_mp3.h index cc033ce87..c0969c476 100644 --- a/src/external/dr_mp3.h +++ b/src/external/dr_mp3.h @@ -1,6 +1,6 @@ /* MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file. -dr_mp3 - v0.7.0 - TBD +dr_mp3 - v0.7.4 - TBD David Reid - mackron@gmail.com @@ -72,7 +72,7 @@ extern "C" { #define DRMP3_VERSION_MAJOR 0 #define DRMP3_VERSION_MINOR 7 -#define DRMP3_VERSION_REVISION 0 +#define DRMP3_VERSION_REVISION 4 #define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION) #include /* For size_t. */ @@ -257,16 +257,45 @@ typedef struct Low Level Push API ================== */ +#define DRMP3_MAX_BITRESERVOIR_BYTES 511 +#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */ +#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */ + typedef struct { int frame_bytes, channels, sample_rate, layer, bitrate_kbps; } drmp3dec_frame_info; +typedef struct +{ + const drmp3_uint8 *buf; + int pos, limit; +} drmp3_bs; + +typedef struct +{ + const drmp3_uint8 *sfbtab; + drmp3_uint16 part_23_length, big_values, scalefac_compress; + drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb; + drmp3_uint8 table_select[3], region_count[3], subblock_gain[3]; + drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi; +} drmp3_L3_gr_info; + +typedef struct +{ + drmp3_bs bs; + drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES]; + drmp3_L3_gr_info gr_info[4]; + float grbuf[2][576], scf[40], syn[18 + 15][2*32]; + drmp3_uint8 ist_pos[2][39]; +} drmp3dec_scratch; + typedef struct { float mdct_overlap[2][9*32], qmf_state[15*2*32]; int reserv, free_format_bytes; drmp3_uint8 header[4], reserv_buf[511]; + drmp3dec_scratch scratch; } drmp3dec; /* Initializes a low level decoder. */ @@ -592,14 +621,10 @@ DRMP3_API const char* drmp3_version_string(void) #define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset))) -#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */ #ifndef DRMP3_MAX_FRAME_SYNC_MATCHES #define DRMP3_MAX_FRAME_SYNC_MATCHES 10 #endif -#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */ - -#define DRMP3_MAX_BITRESERVOIR_BYTES 511 #define DRMP3_SHORT_BLOCK_TYPE 2 #define DRMP3_STOP_BLOCK_TYPE 3 #define DRMP3_MODE_MONO 3 @@ -632,8 +657,10 @@ DRMP3_API const char* drmp3_version_string(void) #if !defined(DR_MP3_NO_SIMD) -#if !defined(DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) -/* x64 always have SSE2, arm64 always have neon, no need for generic code */ +#if !defined(DR_MP3_ONLY_SIMD) && ((defined(_MSC_VER) && _MSC_VER >= 1400) && defined(_M_X64)) || ((defined(__i386) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && ((defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__))) +#define DR_MP3_ONLY_SIMD +#endif +#if !defined(DR_MP3_ONLY_SIMD) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) #define DR_MP3_ONLY_SIMD #endif @@ -655,7 +682,7 @@ DRMP3_API const char* drmp3_version_string(void) #define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s)) #define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3)) typedef __m128 drmp3_f4; -#if defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD) +#if (defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)) && !defined(__clang__) #define drmp3_cpuid __cpuid #else static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType) @@ -779,11 +806,7 @@ static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_ar #define DRMP3_FREE(p) free((p)) #endif -typedef struct -{ - const drmp3_uint8 *buf; - int pos, limit; -} drmp3_bs; + typedef struct { @@ -796,24 +819,6 @@ typedef struct drmp3_uint8 tab_offset, code_tab_width, band_count; } drmp3_L12_subband_alloc; -typedef struct -{ - const drmp3_uint8 *sfbtab; - drmp3_uint16 part_23_length, big_values, scalefac_compress; - drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb; - drmp3_uint8 table_select[3], region_count[3], subblock_gain[3]; - drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi; -} drmp3_L3_gr_info; - -typedef struct -{ - drmp3_bs bs; - drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES]; - drmp3_L3_gr_info gr_info[4]; - float grbuf[2][576], scf[40], syn[18 + 15][2*32]; - drmp3_uint8 ist_pos[2][39]; -} drmp3dec_scratch; - static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes) { bs->buf = data; @@ -1227,6 +1232,14 @@ static float drmp3_L3_ldexp_q2(float y, int exp_q2) return y; } +/* +I've had reports of GCC 14 throwing an incorrect -Wstringop-overflow warning here. This is an attempt +to silence this warning. +*/ +#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch) { static const drmp3_uint8 g_scf_partitions[3][28] = { @@ -1288,6 +1301,9 @@ static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *is scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift); } } +#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__) + #pragma GCC diagnostic pop +#endif static const float g_drmp3_pow43[129 + 16] = { 0,-1,-2.519842f,-4.326749f,-6.349604f,-8.549880f,-10.902724f,-13.390518f,-16.000000f,-18.720754f,-21.544347f,-24.463781f,-27.473142f,-30.567351f,-33.741992f,-36.993181f, @@ -2299,7 +2315,6 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m int i = 0, igr, frame_size = 0, success = 1; const drmp3_uint8 *hdr; drmp3_bs bs_frame[1]; - drmp3dec_scratch scratch; if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3)) { @@ -2336,23 +2351,23 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m if (info->layer == 3) { - int main_data_begin = drmp3_L3_read_side_info(bs_frame, scratch.gr_info, hdr); + int main_data_begin = drmp3_L3_read_side_info(bs_frame, dec->scratch.gr_info, hdr); if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit) { drmp3dec_init(dec); return 0; } - success = drmp3_L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin); + success = drmp3_L3_restore_reservoir(dec, bs_frame, &dec->scratch, main_data_begin); if (success && pcm != NULL) { for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*576*info->channels)) { - DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float)); - drmp3_L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels); - drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]); + DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float)); + drmp3_L3_decode(dec, &dec->scratch, dec->scratch.gr_info + igr*info->channels, info->channels); + drmp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, dec->scratch.syn[0]); } } - drmp3_L3_save_reservoir(dec, &scratch); + drmp3_L3_save_reservoir(dec, &dec->scratch); } else { #ifdef DR_MP3_ONLY_MP3 @@ -2366,15 +2381,15 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m drmp3_L12_read_scale_info(hdr, bs_frame, sci); - DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float)); + DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float)); for (i = 0, igr = 0; igr < 3; igr++) { - if (12 == (i += drmp3_L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1))) + if (12 == (i += drmp3_L12_dequantize_granule(dec->scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1))) { i = 0; - drmp3_L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]); - drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]); - DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float)); + drmp3_L12_apply_scf_384(sci, sci->scf + igr, dec->scratch.grbuf[0]); + drmp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, dec->scratch.syn[0]); + DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float)); pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels); } if (bs_frame->pos > bs_frame->limit) @@ -3005,23 +3020,27 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm ((drmp3_uint32)ape[26] << 16) | ((drmp3_uint32)ape[27] << 24); - streamEndOffset -= 32 + tagSize; - streamLen -= 32 + tagSize; - - /* Fire a metadata callback for the APE data. Must include both the main content and footer. */ - if (onMeta != NULL) { - /* We first need to seek to the start of the APE tag. */ - if (onSeek(pUserData, streamEndOffset, DRMP3_SEEK_END)) { - size_t apeTagSize = (size_t)tagSize + 32; - drmp3_uint8* pTagData = (drmp3_uint8*)drmp3_malloc(apeTagSize, pAllocationCallbacks); - if (pTagData != NULL) { - if (onRead(pUserData, pTagData, apeTagSize) == apeTagSize) { - drmp3__on_meta(pMP3, DRMP3_METADATA_TYPE_APE, pTagData, apeTagSize); - } + if (32 + tagSize < streamLen) { + streamEndOffset -= 32 + tagSize; + streamLen -= 32 + tagSize; + + /* Fire a metadata callback for the APE data. Must include both the main content and footer. */ + if (onMeta != NULL) { + /* We first need to seek to the start of the APE tag. */ + if (onSeek(pUserData, streamEndOffset, DRMP3_SEEK_END)) { + size_t apeTagSize = (size_t)tagSize + 32; + drmp3_uint8* pTagData = (drmp3_uint8*)drmp3_malloc(apeTagSize, pAllocationCallbacks); + if (pTagData != NULL) { + if (onRead(pUserData, pTagData, apeTagSize) == apeTagSize) { + drmp3__on_meta(pMP3, DRMP3_METADATA_TYPE_APE, pTagData, apeTagSize); + } - drmp3_free(pTagData, pAllocationCallbacks); + drmp3_free(pTagData, pAllocationCallbacks); + } } } + } else { + /* The tag size is larger than the stream. Invalid APE tag. */ } } } @@ -3153,7 +3172,6 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm { drmp3_bs bs; drmp3_L3_gr_info grInfo[4]; - const drmp3_uint8* pTagData = pFirstFrameData; drmp3_bs_init(&bs, pFirstFrameData + DRMP3_HDR_SIZE, firstFrameInfo.frame_bytes - DRMP3_HDR_SIZE); @@ -3164,6 +3182,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm if (drmp3_L3_read_side_info(&bs, grInfo, pFirstFrameData) >= 0) { drmp3_bool32 isXing = DRMP3_FALSE; drmp3_bool32 isInfo = DRMP3_FALSE; + const drmp3_uint8* pTagData; const drmp3_uint8* pTagDataBeg; pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8); @@ -3246,6 +3265,13 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm /* The start offset needs to be moved to the end of this frame so it's not included in any audio processing after seeking. */ pMP3->streamStartOffset += (drmp3_uint32)(firstFrameInfo.frame_bytes); pMP3->streamCursor = pMP3->streamStartOffset; + + /* + The internal decoder needs to be reset to clear out any state. If we don't reset this state, it's possible for + there to be inconsistencies in the number of samples read when reading to the end of the stream depending on + whether or not the caller seeks to the start of the stream. + */ + drmp3dec_init(&pMP3->decoder); } } else { /* Failed to read the side info. */ @@ -3307,8 +3333,6 @@ static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3 DRMP3_ASSERT(pMP3 != NULL); - newCursor = pMP3->memory.currentReadPos; - if (origin == DRMP3_SEEK_SET) { newCursor = 0; } else if (origin == DRMP3_SEEK_CUR) { @@ -3981,7 +4005,7 @@ static drmp3_bool32 drmp3__on_tell_stdio(void* pUserData, drmp3_int64* pCursor) DRMP3_ASSERT(pFileStdio != NULL); DRMP3_ASSERT(pCursor != NULL); -#if defined(_WIN32) +#if defined(_WIN32) && !defined(NXDK) #if defined(_MSC_VER) && _MSC_VER > 1200 result = _ftelli64(pFileStdio); #else @@ -4780,6 +4804,8 @@ static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig, pNewFrames = (float*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks); if (pNewFrames == NULL) { drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks); + pFrames = NULL; + totalFramesRead = 0; break; } @@ -4847,6 +4873,8 @@ static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pC pNewFrames = (drmp3_int16*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks); if (pNewFrames == NULL) { drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks); + pFrames = NULL; + totalFramesRead = 0; break; } @@ -4981,7 +5009,24 @@ DIFFERENCES BETWEEN minimp3 AND dr_mp3 /* REVISION HISTORY ================ -v0.7.0 - TBD +v0.7.4 - TBD + - Improvements to SIMD detection. + +v0.7.3 - 2026-01-17 + - Fix an error in drmp3_open_and_read_pcm_frames_s16() and family when memory allocation fails. + - Fix some compilation warnings. + +v0.7.2 - 2025-12-02 + - Reduce stack space to improve robustness on embedded systems. + - Fix a compilation error with MSVC Clang toolset relating to cpuid. + - Fix an error with APE tag parsing. + +v0.7.1 - 2025-09-10 + - Silence a warning with GCC. + - Fix an error with the NXDK build. + - Fix a decoding inconsistency when seeking. Prior to this change, reading to the end of the stream immediately after initializing will result in a different number of samples read than if the stream is seeked to the start and read to the end. + +v0.7.0 - 2025-07-23 - The old `DRMP3_IMPLEMENTATION` has been removed. Use `DR_MP3_IMPLEMENTATION` instead. The reason for this change is that in the future everything will eventually be using the underscored naming convention in the future, so `drmp3` will become `dr_mp3`. - API CHANGE: Seek origins have been renamed to match the naming convention used by dr_wav and my other libraries. - drmp3_seek_origin_start -> DRMP3_SEEK_SET From adc4c9b875de3179c02494967ae92ccc10b246f0 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:19:31 +0200 Subject: [PATCH 033/185] Update dr_wav.h --- src/external/dr_wav.h | 133 ++++++++++++++++++++++++++++++------------ 1 file changed, 95 insertions(+), 38 deletions(-) diff --git a/src/external/dr_wav.h b/src/external/dr_wav.h index 7a7e02246..c7bd89fa3 100644 --- a/src/external/dr_wav.h +++ b/src/external/dr_wav.h @@ -1,6 +1,6 @@ /* WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file. -dr_wav - v0.14.0 - TBD +dr_wav - v0.14.5 - 2026-03-03 David Reid - mackron@gmail.com @@ -147,7 +147,7 @@ extern "C" { #define DRWAV_VERSION_MAJOR 0 #define DRWAV_VERSION_MINOR 14 -#define DRWAV_VERSION_REVISION 0 +#define DRWAV_VERSION_REVISION 5 #define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION) #include /* For size_t. */ @@ -2189,6 +2189,22 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) { drwav_uint32 iSampleLoop; + drwav_uint32 loopCount; + drwav_uint32 calculatedLoopCount; + + /* + When we calcualted the amount of memory required for the "smpl" chunk we excluded the chunk entirely + if the loop count in the header did not match with the calculated count based on the size of the + chunk. When this happens, the second stage will still hit this path but the `pMetadata` will be + non-null, but will either be pointing at the very end of the allocation or at the start of another + chunk. We need to check the loop counts for consistency *before* dereferencing the pMetadata object + so it's consistent with how we do it in the first stage. + */ + loopCount = drwav_bytes_to_u32(smplHeaderData + 28); + calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES; + if (loopCount != calculatedLoopCount) { + return totalBytesRead; + } pMetadata->type = drwav_metadata_type_smpl; pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0); @@ -2205,7 +2221,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars The loop count needs to be validated against the size of the chunk for safety so we don't attempt to read over the boundary of the chunk. */ - if (pMetadata->data.smpl.sampleLoopCount == (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES) { + if (pMetadata->data.smpl.sampleLoopCount == calculatedLoopCount) { pMetadata->data.smpl.pLoops = (drwav_smpl_loop*)drwav__metadata_get_memory(pParser, sizeof(drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT); for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) { @@ -2230,6 +2246,15 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead); } + } else { + /* + Getting here means the loop count in the header does not match up with the size of the + chunk. Clear out the data to zero just to be safe. + + This should never actually get hit because we check for it above, but keeping this here + for added safety. + */ + DRWAV_ZERO_OBJECT(&pMetadata->data.smpl); } } @@ -3605,7 +3630,7 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on we'll need to abort because we can't be doing a backwards seek back to the SSND chunk in order to read the data. For this reason, this configuration of AIFF files are not supported with sequential mode. */ - return DRWAV_FALSE; + return DRWAV_FALSE; } } else { chunkSize += header.paddingSize; /* <-- Make sure we seek past the padding. */ @@ -5285,7 +5310,7 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_tell_stdio(void* pUserData, drwav_int64* pC DRWAV_ASSERT(pFileStdio != NULL); DRWAV_ASSERT(pCursor != NULL); -#if defined(_WIN32) +#if defined(_WIN32) && !defined(NXDK) #if defined(_MSC_VER) && _MSC_VER > 1200 result = _ftelli64(pFileStdio); #else @@ -5492,8 +5517,6 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, dr DRWAV_ASSERT(pWav != NULL); - newCursor = pWav->memoryStream.currentReadPos; - if (origin == DRWAV_SEEK_SET) { newCursor = 0; } else if (origin == DRWAV_SEEK_CUR) { @@ -5566,8 +5589,6 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offs DRWAV_ASSERT(pWav != NULL); - newCursor = pWav->memoryStreamWrite.currentWritePos; - if (origin == DRWAV_SEEK_SET) { newCursor = 0; } else if (origin == DRWAV_SEEK_CUR) { @@ -5576,7 +5597,7 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offs newCursor = (drwav_int64)pWav->memoryStreamWrite.dataSize; } else { DRWAV_ASSERT(!"Invalid seek origin"); - return DRWAV_INVALID_ARGS; + return DRWAV_FALSE; } newCursor += offset; @@ -6258,12 +6279,12 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav { drwav_uint64 totalFramesRead = 0; - static drwav_int32 adaptationTable[] = { + static const drwav_int32 adaptationTable[] = { 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307, 230, 230, 230 }; - static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 }; - static drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 }; + static const drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 }; + static const drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 }; DRWAV_ASSERT(pWav != NULL); DRWAV_ASSERT(framesToRead > 0); @@ -6292,7 +6313,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav pWav->msadpcm.cachedFrameCount = 2; /* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */ - if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table)) { + if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) { return totalFramesRead; /* Invalid file. */ } } else { @@ -6319,7 +6340,8 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav pWav->msadpcm.cachedFrameCount = 2; /* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */ - if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) { + if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table) || + pWav->msadpcm.predictor[1] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) { return totalFramesRead; /* Invalid file. */ } } @@ -6373,15 +6395,17 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav drwav_int32 newSample0; drwav_int32 newSample1; + /* The predictor is read from the file and then indexed into a table. Check that it's in bounds. */ + if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) { + return totalFramesRead; + } + newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8; newSample0 += nibble0 * pWav->msadpcm.delta[0]; newSample0 = drwav_clamp(newSample0, -32768, 32767); - pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8; - if (pWav->msadpcm.delta[0] < 16) { - pWav->msadpcm.delta[0] = 16; - } - + pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF); + pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1]; pWav->msadpcm.prevFrames[0][1] = newSample0; @@ -6390,15 +6414,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav newSample1 += nibble1 * pWav->msadpcm.delta[0]; newSample1 = drwav_clamp(newSample1, -32768, 32767); - pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8; - if (pWav->msadpcm.delta[0] < 16) { - pWav->msadpcm.delta[0] = 16; - } + pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF); pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1]; pWav->msadpcm.prevFrames[0][1] = newSample1; - pWav->msadpcm.cachedFrames[2] = newSample0; pWav->msadpcm.cachedFrames[3] = newSample1; pWav->msadpcm.cachedFrameCount = 2; @@ -6408,28 +6428,30 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav drwav_int32 newSample1; /* Left. */ + if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) { + return totalFramesRead; /* Out of bounds. Invalid file. */ + } + newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8; newSample0 += nibble0 * pWav->msadpcm.delta[0]; newSample0 = drwav_clamp(newSample0, -32768, 32767); - pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8; - if (pWav->msadpcm.delta[0] < 16) { - pWav->msadpcm.delta[0] = 16; - } + pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF); pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1]; pWav->msadpcm.prevFrames[0][1] = newSample0; /* Right. */ + if (pWav->msadpcm.predictor[1] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) { + return totalFramesRead; /* Out of bounds. Invalid file. */ + } + newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8; newSample1 += nibble1 * pWav->msadpcm.delta[1]; newSample1 = drwav_clamp(newSample1, -32768, 32767); - pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8; - if (pWav->msadpcm.delta[1] < 16) { - pWav->msadpcm.delta[1] = 16; - } + pWav->msadpcm.delta[1] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8, 16, 0x7FFFFFFF); pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1]; pWav->msadpcm.prevFrames[1][1] = newSample1; @@ -6451,12 +6473,12 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin drwav_uint64 totalFramesRead = 0; drwav_uint32 iChannel; - static drwav_int32 indexTable[16] = { + static const drwav_int32 indexTable[16] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 }; - static drwav_int32 stepTable[89] = { + static const drwav_int32 stepTable[89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, @@ -6606,7 +6628,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin #ifndef DR_WAV_NO_CONVERSION_API -static unsigned short g_drwavAlawTable[256] = { +static const unsigned short g_drwavAlawTable[256] = { 0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580, 0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0, 0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600, @@ -6625,7 +6647,7 @@ static unsigned short g_drwavAlawTable[256] = { 0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350 }; -static unsigned short g_drwavMulawTable[256] = { +static const unsigned short g_drwavMulawTable[256] = { 0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84, 0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84, 0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004, @@ -8053,6 +8075,12 @@ DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, uns DRWAV_ASSERT(pWav != NULL); + /* Check for overflow before multiplication. */ + if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(drwav_int16)) { + drwav_uninit(pWav); + return NULL; /* Overflow or invalid channels. */ + } + sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16); if (sampleDataSize > DRWAV_SIZE_MAX) { drwav_uninit(pWav); @@ -8095,6 +8123,12 @@ DRWAV_PRIVATE float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned DRWAV_ASSERT(pWav != NULL); + /* Check for overflow before multiplication. */ + if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(float)) { + drwav_uninit(pWav); + return NULL; /* Overflow or invalid channels. */ + } + sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float); if (sampleDataSize > DRWAV_SIZE_MAX) { drwav_uninit(pWav); @@ -8137,6 +8171,12 @@ DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, uns DRWAV_ASSERT(pWav != NULL); + /* Check for overflow before multiplication. */ + if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(drwav_int32)) { + drwav_uninit(pWav); + return NULL; /* Overflow or invalid channels. */ + } + sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32); if (sampleDataSize > DRWAV_SIZE_MAX) { drwav_uninit(pWav); @@ -8517,7 +8557,24 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b) /* REVISION HISTORY ================ -v0.14.0 - TBD +v0.14.5 - 2026-03-03 + - Fix a crash when loading files with a malformed "smpl" chunk. + - Fix a signed overflow bug with the MS-ADPCM decoder. + +v0.14.4 - 2026-01-17 + - Fix some compilation warnings. + +v0.14.3 - 2025-12-14 + - Fix a possible out-of-bounds read when reading from MS-ADPCM encoded files. + - Fix a possible integer overflow error. + +v0.14.2 - 2025-12-02 + - Fix a compilation warning. + +v0.14.1 - 2025-09-10 + - Fix an error with the NXDK build. + +v0.14.0 - 2025-07-23 - API CHANGE: Seek origin enums have been renamed to the following: - drwav_seek_origin_start -> DRWAV_SEEK_SET - drwav_seek_origin_current -> DRWAV_SEEK_CUR From d5326fe880b26c941f967aedf9ece48c99554cad Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:20:23 +0200 Subject: [PATCH 034/185] Update m3d.h --- src/external/m3d.h | 53 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/src/external/m3d.h b/src/external/m3d.h index 6abaad142..8bba18325 100644 --- a/src/external/m3d.h +++ b/src/external/m3d.h @@ -236,7 +236,8 @@ typedef struct { #ifdef M3D_ASCII #define M3D_PROPERTYDEF(f,i,n) { (f), (i), (char*)(n) } char *key; -#else +#endif +#ifndef M3D_ASCII #define M3D_PROPERTYDEF(f,i,n) { (f), (i) } #endif } m3dpd_t; @@ -414,7 +415,8 @@ typedef struct { #ifdef M3D_ASCII #define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (char*)(n), (p), { (a), (b), (c), (d), (e), (f), (g), (h) } } char *key; -#else +#endif +#ifndef M3D_ASCII #define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (p), { (a), (b), (c), (d), (e), (f), (g), (h) } } #endif uint8_t p; @@ -674,6 +676,10 @@ static m3dcd_t m3d_commandtypes[] = { #include #include +/* we'll need this with M3D_NOTEXTURE */ +char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); + +#ifndef M3D_NOTEXTURE #if !defined(M3D_NOIMPORTER) && !defined(STBI_INCLUDE_STB_IMAGE_H) /* PNG decompressor from @@ -1868,6 +1874,11 @@ static void *_m3dstbi__png_load(_m3dstbi__context *s, int *x, int *y, int *comp, #if !defined(M3D_NOIMPORTER) && defined(STBI_INCLUDE_STB_IMAGE_H) && !defined(STB_IMAGE_IMPLEMENTATION) #error "stb_image.h included without STB_IMAGE_IMPLEMENTATION. Sorry, we need some stuff defined inside the ifguard for proper integration" #endif +#else +#if !defined(STBI_INCLUDE_STB_IMAGE_H) || defined(STBI_NO_ZLIB) +#error "stb_image.h not included or STBI_NO_ZLIB defined. Sorry, we need its zlib implementation for proper integration" +#endif +#endif /* M3D_NOTEXTURE */ #if defined(M3D_EXPORTER) && !defined(INCLUDE_STB_IMAGE_WRITE_H) /* zlib_compressor from @@ -2168,9 +2179,11 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char unsigned int i, len = 0; unsigned char *buff = NULL; char *fn2; +#ifndef M3D_NOTEXTURE unsigned int w, h; stbi__context s; stbi__result_info ri; +#endif /* failsafe */ if(!fn || !*fn) return M3D_UNDEF; @@ -2209,13 +2222,17 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char if(!model->texture) { if(buff && freecb) (*freecb)(buff); model->errcode = M3D_ERR_ALLOC; + model->numtexture = 0; return M3D_UNDEF; } + memset(&model->texture[i], 0, sizeof(m3dtx_t)); model->texture[i].name = fn; - model->texture[i].w = model->texture[i].h = 0; model->texture[i].d = NULL; if(buff) { if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') { - s.read_from_callbacks = 0; +#ifndef M3D_NOTEXTURE + /* return pixel buffer of the decoded texture */ + memset(&s, 0, sizeof(s)); + memset(&ri, 0, sizeof(ri)); s.img_buffer = s.img_buffer_original = (unsigned char *) buff; s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len; /* don't use model->texture[i].w directly, it's a uint16_t */ @@ -2225,6 +2242,16 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char model->texture[i].w = w; model->texture[i].h = h; model->texture[i].f = (uint8_t)len; +#else + /* return only the raw undecoded texture */ + if((model->texture[i].d = (uint8_t*)M3D_MALLOC(len))) { + memcpy(model->texture[i].d, buff, len); + model->texture[i].w = len & 0xffff; + model->texture[i].h = (len >> 16) & 0xffff; + model->texture[i].f = 0; + } else + model->errcode = M3D_ERR_ALLOC; +#endif } else { #ifdef M3D_TX_INTERP if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) { @@ -4280,7 +4307,7 @@ m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec) if(l != msec) { model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, (model->numvertex + 2 * model->numbone) * sizeof(m3dv_t)); if(!model->vertex) { - free(ret); + M3D_FREE(ret); model->errcode = M3D_ERR_ALLOC; return NULL; } @@ -4492,7 +4519,7 @@ void m3d_free(m3d_t *model) if(model->label) M3D_FREE(model->label); if(model->inlined) M3D_FREE(model->inlined); if(model->extra) M3D_FREE(model->extra); - free(model); + M3D_FREE(model); } #endif @@ -4568,15 +4595,15 @@ static uint32_t _m3d_stridx(m3dstr_t *str, uint32_t numstr, char *s) safe = _m3d_safestr(s, 0); if(!safe) return 0; if(!*safe) { - free(safe); + M3D_FREE(safe); return 0; } for(i = 0; i < numstr; i++) if(!strcmp(str[i].str, s)) { - free(safe); + M3D_FREE(safe); return str[i].offs; } - free(safe); + M3D_FREE(safe); } return 0; } @@ -4889,7 +4916,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size if(cmd->type == m3dc_mesh) { if(numgrp + 2 < maxgrp) { maxgrp += 1024; - grpidx = (uint32_t*)realloc(grpidx, maxgrp * sizeof(uint32_t)); + grpidx = (uint32_t*)M3D_REALLOC(grpidx, maxgrp * sizeof(uint32_t)); if(!grpidx) goto memerr; if(!numgrp) { grpidx[0] = 0; @@ -5194,7 +5221,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(sa) M3D_FREE(sa); if(sd) M3D_FREE(sd); if(out) M3D_FREE(out); - if(opa) free(opa); + if(opa) M3D_FREE(opa); if(h) M3D_FREE(h); M3D_LOG("Out of memory"); model->errcode = M3D_ERR_ALLOC; @@ -6285,7 +6312,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(skin) M3D_FREE(skin); if(str) M3D_FREE(str); if(vrtx) M3D_FREE(vrtx); - if(opa) free(opa); + if(opa) M3D_FREE(opa); if(h) M3D_FREE(h); return out; } @@ -6310,7 +6337,7 @@ namespace M3D { public: Model() { - this->model = (m3d_t*)malloc(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t)); + this->model = (m3d_t*)M3D_MALLOC(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t)); } Model(_unused const std::string &data, _unused m3dread_t ReadFileCB, _unused m3dfree_t FreeCB, _unused M3D::Model mtllib) { From e5f0c9f8b1dce384534ad802c343c40ba4956b67 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:21:11 +0200 Subject: [PATCH 035/185] Update qoa.h --- src/external/qoa.h | 60 +++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/external/qoa.h b/src/external/qoa.h index 57b85d131..e11c84269 100644 --- a/src/external/qoa.h +++ b/src/external/qoa.h @@ -31,7 +31,7 @@ struct { struct { char magic[4]; // magic bytes "qoaf" uint32_t samples; // samples per channel in this file - } file_header; + } file_header; struct { struct { @@ -39,12 +39,12 @@ struct { uint24_t samplerate; // samplerate in hz uint16_t fsamples; // samples per channel in this frame uint16_t fsize; // frame size (includes this header) - } frame_header; + } frame_header; struct { int16_t history[4]; // most recent last int16_t weights[4]; // most recent last - } lms_state[num_channels]; + } lms_state[num_channels]; qoa_slice_t slices[256][num_channels]; @@ -66,7 +66,7 @@ frame may contain between 1 .. 256 (inclusive) slices per channel. The last slice (for each channel) in the last frame may contain less than 20 samples; the slice still must be 8 bytes wide, with the unused samples zeroed out. -Channels are interleaved per slice. E.g. for 2 channel stereo: +Channels are interleaved per slice. E.g. for 2 channel stereo: slice[0] = L, slice[1] = R, slice[2] = L, slice[3] = R ... A valid QOA file or stream must have at least one frame. Each frame must contain @@ -74,7 +74,7 @@ at least one channel and one sample with a samplerate between 1 .. 16777215 (inclusive). If the total number of samples is not known by the encoder, the samples in the -file header may be set to 0x00000000 to indicate that the encoder is +file header may be set to 0x00000000 to indicate that the encoder is "streaming". In a streaming context, the samplerate and number of channels may differ from frame to frame. For static files (those with samples set to a non-zero value), each frame must have the same number of channels and same @@ -88,15 +88,15 @@ counts 1 .. 8 is: 1. Mono 2. L, R - 3. L, R, C - 4. FL, FR, B/SL, B/SR - 5. FL, FR, C, B/SL, B/SR + 3. L, R, C + 4. FL, FR, B/SL, B/SR + 5. FL, FR, C, B/SL, B/SR 6. FL, FR, C, LFE, B/SL, B/SR - 7. FL, FR, C, LFE, B, SL, SR + 7. FL, FR, C, LFE, B, SL, SR 8. FL, FR, C, LFE, BL, BR, SL, SR QOA predicts each audio sample based on the previously decoded ones using a -"Sign-Sign Least Mean Squares Filter" (LMS). This prediction plus the +"Sign-Sign Least Mean Squares Filter" (LMS). This prediction plus the dequantized residual forms the final output sample. */ @@ -178,9 +178,9 @@ typedef unsigned long long qoa_uint64_t; /* The quant_tab provides an index into the dequant_tab for residuals in the -range of -8 .. 8. It maps this range to just 3bits and becomes less accurate at -the higher end. Note that the residual zero is identical to the lowest positive -value. This is mostly fine, since the qoa_div() function always rounds away +range of -8 .. 8. It maps this range to just 3bits and becomes less accurate at +the higher end. Note that the residual zero is identical to the lowest positive +value. This is mostly fine, since the qoa_div() function always rounds away from zero. */ static const int qoa_quant_tab[17] = { @@ -193,8 +193,8 @@ static const int qoa_quant_tab[17] = { /* We have 16 different scalefactors. Like the quantized residuals these become less accurate at the higher end. In theory, the highest scalefactor that we would need to encode the highest 16bit residual is (2**16)/8 = 8192. However we -rely on the LMS filter to predict samples accurately enough that a maximum -residual of one quarter of the 16 bit range is sufficient. I.e. with the +rely on the LMS filter to predict samples accurately enough that a maximum +residual of one quarter of the 16 bit range is sufficient. I.e. with the scalefactor 2048 times the quant range of 8 we can encode residuals up to 2**14. The scalefactor values are computed as: @@ -205,9 +205,9 @@ static const int qoa_scalefactor_tab[16] = { }; -/* The reciprocal_tab maps each of the 16 scalefactors to their rounded -reciprocals 1/scalefactor. This allows us to calculate the scaled residuals in -the encoder with just one multiplication instead of an expensive division. We +/* The reciprocal_tab maps each of the 16 scalefactors to their rounded +reciprocals 1/scalefactor. This allows us to calculate the scaled residuals in +the encoder with just one multiplication instead of an expensive division. We do this in .16 fixed point with integers, instead of floats. The reciprocal_tab is computed as: @@ -218,11 +218,11 @@ static const int qoa_reciprocal_tab[16] = { }; -/* The dequant_tab maps each of the scalefactors and quantized residuals to +/* The dequant_tab maps each of the scalefactors and quantized residuals to their unscaled & dequantized version. Since qoa_div rounds away from the zero, the smallest entries are mapped to 3/4 -instead of 1. The dequant_tab assumes the following dequantized values for each +instead of 1. The dequant_tab assumes the following dequantized values for each of the quant_tab indices and is computed as: float dqt[8] = {0.75, -0.75, 2.5, -2.5, 4.5, -4.5, 7, -7}; dequant_tab[s][q] <- round_ties_away_from_zero(scalefactor_tab[s] * dqt[q]) @@ -258,7 +258,7 @@ adjusting 4 weights based on the residual of the previous prediction. The next sample is predicted as the sum of (weight[i] * history[i]). The adjustment of the weights is done with a "Sign-Sign-LMS" that adds or -subtracts the residual to each weight, based on the corresponding sample from +subtracts the residual to each weight, based on the corresponding sample from the history. This, surprisingly, is sufficient to get worthwhile predictions. This is all done with fixed point integers. Hence the right-shifts when updating @@ -285,8 +285,8 @@ static void qoa_lms_update(qoa_lms_t *lms, int sample, int residual) { } -/* qoa_div() implements a rounding division, but avoids rounding to zero for -small numbers. E.g. 0.1 will be rounded to 1. Note that 0 itself still +/* qoa_div() implements a rounding division, but avoids rounding to zero for +small numbers. E.g. 0.1 will be rounded to 1. Note that 0 itself still returns as 0, which is handled in the qoa_quant_tab[]. qoa_div() takes an index into the .16 fixed point qoa_reciprocal_tab as an argument, so it can do the division with a cheaper integer multiplication. */ @@ -385,10 +385,10 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned for (unsigned int c = 0; c < channels; c++) { int slice_len = qoa_clamp(QOA_SLICE_LEN, 0, frame_len - sample_index); int slice_start = sample_index * channels + c; - int slice_end = (sample_index + slice_len) * channels + c; + int slice_end = (sample_index + slice_len) * channels + c; - /* Brute for search for the best scalefactor. Just go through all - 16 scalefactors, encode all samples for the current slice and + /* Brute force search for the best scalefactor. Just go through all + 16 scalefactors, encode all samples for the current slice and meassure the total squared error. */ qoa_uint64_t best_rank = -1; #ifdef QOA_RECORD_TOTAL_ERROR @@ -402,7 +402,7 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned /* There is a strong correlation between the scalefactors of neighboring slices. As an optimization, start testing the best scalefactor of the previous slice first. */ - int scalefactor = (sfi + prev_scalefactor[c]) % 16; + int scalefactor = (sfi + prev_scalefactor[c]) & (16 - 1); /* We have to reset the LMS state to the last known good one before trying each scalefactor, as each pass updates the LMS @@ -500,7 +500,7 @@ void *qoa_encode(const short *sample_data, qoa_desc *qoa, unsigned int *out_len) num_frames * QOA_LMS_LEN * 4 * qoa->channels + /* 4 * 4 bytes lms state per channel */ num_slices * 8 * qoa->channels; /* 8 byte slices */ - unsigned char *bytes = (unsigned char *)QOA_MALLOC(encoded_size); + unsigned char *bytes = QOA_MALLOC(encoded_size); for (unsigned int c = 0; c < qoa->channels; c++) { /* Set the initial LMS weights to {0, 0, -1, 2}. This helps with the @@ -657,7 +657,7 @@ short *qoa_decode(const unsigned char *bytes, int size, qoa_desc *qoa) { /* Calculate the required size of the sample buffer and allocate */ int total_samples = qoa->samples * qoa->channels; - short *sample_data = (short *)QOA_MALLOC(total_samples * sizeof(short)); + short *sample_data = QOA_MALLOC(total_samples * sizeof(short)); unsigned int sample_index = 0; unsigned int frame_len; @@ -733,7 +733,7 @@ void *qoa_read(const char *filename, qoa_desc *qoa) { bytes_read = fread(data, 1, size, f); fclose(f); - sample_data = qoa_decode((const unsigned char *)data, bytes_read, qoa); + sample_data = qoa_decode(data, bytes_read, qoa); QOA_FREE(data); return sample_data; } From 4c79c6837bd479fa938fc81eb61c6574fac078f1 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:21:16 +0200 Subject: [PATCH 036/185] Update qoi.h --- src/external/qoi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/external/qoi.h b/src/external/qoi.h index f2800b0cc..e09d3a43d 100644 --- a/src/external/qoi.h +++ b/src/external/qoi.h @@ -427,7 +427,7 @@ void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) { run = 0; } - index_pos = QOI_COLOR_HASH(px) % 64; + index_pos = QOI_COLOR_HASH(px) & (64 - 1); if (index[index_pos].v == px.v) { bytes[p++] = QOI_OP_INDEX | index_pos; @@ -574,7 +574,7 @@ void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) { run = (b1 & 0x3f); } - index[QOI_COLOR_HASH(px) % 64] = px; + index[QOI_COLOR_HASH(px) & (64 - 1)] = px; } pixels[px_pos + 0] = px.rgba.r; From e9231bc4f1b3df2c1eec24cb535130d2e6aabd6a Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:24:20 +0200 Subject: [PATCH 037/185] Update stb_image_resize2.h --- src/external/stb_image_resize2.h | 662 +++++++++++++++++-------------- 1 file changed, 370 insertions(+), 292 deletions(-) diff --git a/src/external/stb_image_resize2.h b/src/external/stb_image_resize2.h index 2f2627463..079897658 100644 --- a/src/external/stb_image_resize2.h +++ b/src/external/stb_image_resize2.h @@ -1,4 +1,4 @@ -/* stb_image_resize2 - v2.12 - public domain image resizing +/* stb_image_resize2 - v2.18 - public domain image resizing by Jeff Roberts (v2) and Jorge L Rodriguez http://github.com/nothings/stb @@ -141,13 +141,13 @@ COLOR+ALPHA buffer types tell the resizer to do. When you use the pixel layouts STBIR_RGBA, STBIR_BGRA, STBIR_ARGB, - STBIR_ABGR, STBIR_RX, or STBIR_XR you are telling us that the pixels are + STBIR_ABGR, STBIR_RA, or STBIR_AR you are telling us that the pixels are non-premultiplied. In these cases, the resizer will alpha weight the colors (effectively creating the premultiplied image), do the filtering, and then convert back to non-premult on exit. - When you use the pixel layouts STBIR_RGBA_PM, STBIR_RGBA_PM, STBIR_RGBA_PM, - STBIR_RGBA_PM, STBIR_RX_PM or STBIR_XR_PM, you are telling that the pixels + When you use the pixel layouts STBIR_RGBA_PM, STBIR_BGRA_PM, STBIR_ARGB_PM, + STBIR_ABGR_PM, STBIR_RA_PM or STBIR_AR_PM, you are telling that the pixels ARE premultiplied. In this case, the resizer doesn't have to do the premultipling - it can filter directly on the input. This about twice as fast as the non-premultiplied case, so it's the right option if your data is @@ -254,7 +254,7 @@ using the stbir_set_filter_callbacks function. PROGRESS - For interactive use with slow resize operations, you can use the the + For interactive use with slow resize operations, you can use the scanline callbacks in the extended API. It would have to be a *very* large image resample to need progress though - we're very fast. @@ -307,6 +307,8 @@ some pixel reconversion, but probably dwarfed by things falling out of cache. Probably also something possible with alternating between scattering and gathering at high resize scales? + * Should we have a multiple MIPs at the same time function (could keep + more memory in cache during multiple resizes)? * Rewrite the coefficient generator to do many at once. * AVX-512 vertical kernels - worried about downclocking here. * Convert the reincludes to macros when we know they aren't changing. @@ -327,6 +329,24 @@ Nathan Reed: warning fixes for 1.0 REVISIONS + 2.18 (2026-03-25) fixed coefficient calculation when skipping a coefficient off + the left side of the window, added non-aligned access safe + memcpy mode for scalar path, fixed various typos, and fixed + define error in the float clamp output mode. + 2.17 (2025-10-25) silly format bug in easy-to-use APIs. + 2.16 (2025-10-21) fixed the easy-to-use APIs to allow inverted bitmaps (negative + strides), fix vertical filter kernel callback, fix threaded + gather buffer priming (and assert). + (thanks adipose, TainZerL, and Harrison Green) + 2.15 (2025-07-17) fixed an assert in debug mode when using floats with input + callbacks, work around GCC warning when adding to null ptr + (thanks Johannes Spohr and Pyry Kovanen). + 2.14 (2025-05-09) fixed a bug using downsampling gather horizontal first, and + scatter with vertical first. + 2.13 (2025-02-27) fixed a bug when using input callbacks, turned off simd for + tiny-c, fixed some variables that should have been static, + fixes a bug when calculating temp memory with resizes that + exceed 2GB of temp memory (very large resizes). 2.12 (2024-10-18) fix incorrect use of user_data with STBIR_FREE 2.11 (2024-09-08) fix harmless asan warnings in 2-channel and 3-channel mode with AVX-2, fix some weird scaling edge conditions with @@ -382,62 +402,6 @@ typedef uint32_t stbir_uint32; typedef uint64_t stbir_uint64; #endif -#ifdef _M_IX86_FP -#if ( _M_IX86_FP >= 1 ) -#ifndef STBIR_SSE -#define STBIR_SSE -#endif -#endif -#endif - -#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(_M_AMD64) || defined(__SSE2__) || defined(STBIR_SSE) || defined(STBIR_SSE2) - #ifndef STBIR_SSE2 - #define STBIR_SSE2 - #endif - #if defined(__AVX__) || defined(STBIR_AVX2) - #ifndef STBIR_AVX - #ifndef STBIR_NO_AVX - #define STBIR_AVX - #endif - #endif - #endif - #if defined(__AVX2__) || defined(STBIR_AVX2) - #ifndef STBIR_NO_AVX2 - #ifndef STBIR_AVX2 - #define STBIR_AVX2 - #endif - #if defined( _MSC_VER ) && !defined(__clang__) - #ifndef STBIR_FP16C // FP16C instructions are on all AVX2 cpus, so we can autoselect it here on microsoft - clang needs -m16c - #define STBIR_FP16C - #endif - #endif - #endif - #endif - #ifdef __F16C__ - #ifndef STBIR_FP16C // turn on FP16C instructions if the define is set (for clang and gcc) - #define STBIR_FP16C - #endif - #endif -#endif - -#if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || ((__ARM_NEON_FP & 4) != 0) || defined(__ARM_NEON__) -#ifndef STBIR_NEON -#define STBIR_NEON -#endif -#endif - -#if defined(_M_ARM) || defined(__arm__) -#ifdef STBIR_USE_FMA -#undef STBIR_USE_FMA // no FMA for 32-bit arm on MSVC -#endif -#endif - -#if defined(__wasm__) && defined(__wasm_simd128__) -#ifndef STBIR_WASM -#define STBIR_WASM -#endif -#endif - #ifndef STBIRDEF #ifdef STB_IMAGE_RESIZE_STATIC #define STBIRDEF static @@ -1036,7 +1000,7 @@ typedef struct char no_cache_straddle[64]; } stbir__per_split_info; -typedef void stbir__decode_pixels_func( float * decode, int width_times_channels, void const * input ); +typedef float * stbir__decode_pixels_func( float * decode, int width_times_channels, void const * input ); typedef void stbir__alpha_weight_func( float * decode_buffer, int width_times_channels ); typedef void stbir__horizontal_gather_channels_func( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ); @@ -1099,8 +1063,8 @@ struct stbir__info #define stbir__max_uint8_as_float 255.0f #define stbir__max_uint16_as_float 65535.0f -#define stbir__max_uint8_as_float_inverted (1.0f/255.0f) -#define stbir__max_uint16_as_float_inverted (1.0f/65535.0f) +#define stbir__max_uint8_as_float_inverted 3.9215689e-03f // (1.0f/255.0f) +#define stbir__max_uint16_as_float_inverted 1.5259022e-05f // (1.0f/65535.0f) #define stbir__small_float ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) // min/max friendly @@ -1205,6 +1169,69 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #define STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS 4 // when threading, what is the minimum number of scanlines for a split? #endif +#define STBIR_INPUT_CALLBACK_PADDING 3 + +#ifdef _M_IX86_FP +#if ( _M_IX86_FP >= 1 ) +#ifndef STBIR_SSE +#define STBIR_SSE +#endif +#endif +#endif + +#ifdef __TINYC__ + // tiny c has no intrinsics yet - this can become a version check if they add them + #define STBIR_NO_SIMD +#endif + +#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(_M_AMD64) || defined(__SSE2__) || defined(STBIR_SSE) || defined(STBIR_SSE2) + #ifndef STBIR_SSE2 + #define STBIR_SSE2 + #endif + #if defined(__AVX__) || defined(STBIR_AVX2) + #ifndef STBIR_AVX + #ifndef STBIR_NO_AVX + #define STBIR_AVX + #endif + #endif + #endif + #if defined(__AVX2__) || defined(STBIR_AVX2) + #ifndef STBIR_NO_AVX2 + #ifndef STBIR_AVX2 + #define STBIR_AVX2 + #endif + #if defined( _MSC_VER ) && !defined(__clang__) + #ifndef STBIR_FP16C // FP16C instructions are on all AVX2 cpus, so we can autoselect it here on microsoft - clang needs -mf16c + #define STBIR_FP16C + #endif + #endif + #endif + #endif + #ifdef __F16C__ + #ifndef STBIR_FP16C // turn on FP16C instructions if the define is set (for clang and gcc) + #define STBIR_FP16C + #endif + #endif +#endif + +#if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || ((__ARM_NEON_FP & 4) != 0) || defined(__ARM_NEON__) +#ifndef STBIR_NEON +#define STBIR_NEON +#endif +#endif + +#if defined(_M_ARM) || defined(__arm__) +#ifdef STBIR_USE_FMA +#undef STBIR_USE_FMA // no FMA for 32-bit arm on MSVC +#endif +#endif + +#if defined(__wasm__) && defined(__wasm_simd128__) +#ifndef STBIR_WASM +#define STBIR_WASM +#endif +#endif + // restrict pointers for the output pointers, other loop and unroll control #if defined( _MSC_VER ) && !defined(__clang__) #define STBIR_STREAMOUT_PTR( star ) star __restrict @@ -1451,8 +1478,8 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #include #define stbir__simdf_pack_to_8words(out,reg0,reg1) out = _mm_packus_epi32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg0,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())), _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg1,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps()))) #else - STBIR__SIMDI_CONST(stbir__s32_32768, 32768); - STBIR__SIMDI_CONST(stbir__s16_32768, ((32768<<16)|32768)); + static STBIR__SIMDI_CONST(stbir__s32_32768, 32768); + static STBIR__SIMDI_CONST(stbir__s16_32768, ((32768<<16)|32768)); #define stbir__simdf_pack_to_8words(out,reg0,reg1) \ { \ @@ -2545,7 +2572,7 @@ static const STBIR__SIMDF_CONST(STBIR_simd_point5, 0.5f); static const STBIR__SIMDF_CONST(STBIR_ones, 1.0f); static const STBIR__SIMDI_CONST(STBIR_almost_zero, (127 - 13) << 23); static const STBIR__SIMDI_CONST(STBIR_almost_one, 0x3f7fffff); -static const STBIR__SIMDI_CONST(STBIR_mastissa_mask, 0xff); +static const STBIR__SIMDI_CONST(STBIR_mantissa_mask, 0xff); static const STBIR__SIMDI_CONST(STBIR_topscale, 0x02000000); // Basically, in simd mode, we unroll the proper amount, and we don't want @@ -2816,16 +2843,34 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes; ptrdiff_t ofs_to_dest = (char*)dest - (char*)src; - if ( ofs_to_dest >= 8 ) // is the overlap more than 8 away? + if ( ofs_to_dest >= 8 ) // is the overlap more than 8 away { char STBIR_SIMD_STREAMOUT_PTR( * ) s_end8 = ((char*) src) + (bytes&~7); - STBIR_NO_UNROLL_LOOP_START - do + + if ( ( ( ((ptrdiff_t)dest)|((ptrdiff_t)src) ) & 7 ) == 0 ) // is it 8byte aligned? { - STBIR_NO_UNROLL(sd); - *(stbir_uint64*)( sd + ofs_to_dest ) = *(stbir_uint64*) sd; - sd += 8; - } while ( sd < s_end8 ); + STBIR_NO_UNROLL_LOOP_START + do + { + STBIR_NO_UNROLL(sd); + *(stbir_uint64*)( sd + ofs_to_dest ) = *(stbir_uint64*) sd; + sd += 8; + } while ( sd < s_end8 ); + } + else + { + STBIR_NO_UNROLL_LOOP_START + do + { + int a,b; + STBIR_NO_UNROLL(sd); + a = ((int*)sd)[0]; + b = ((int*)sd)[1]; + ((int*)( sd + ofs_to_dest ))[0] = a; + ((int*)( sd + ofs_to_dest ))[1] = b; + sd += 8; + } while ( sd < s_end8 ); + } if ( sd == s_end ) return; @@ -3217,10 +3262,9 @@ static void stbir__get_extents( stbir__sampler * samp, stbir__extents * scanline newspan->n0 = -left_margin; newspan->n1 = ( max_left - min_left ) - left_margin; scanline_extents->edge_sizes[0] = 0; // don't need to copy the left margin, since we are directly decoding into the margin - return; } - - // if we can't merge the min_left range, add it as a second range + // if we can't merge the min_right range, add it as a second range + else if ( ( right_margin ) && ( min_right != 0x7fffffff ) ) { stbir__span * newspan = scanline_extents->spans + 1; @@ -3235,7 +3279,14 @@ static void stbir__get_extents( stbir__sampler * samp, stbir__extents * scanline newspan->n0 = scanline_extents->spans[1].n1 + 1; newspan->n1 = scanline_extents->spans[1].n1 + 1 + ( max_right - min_right ); scanline_extents->edge_sizes[1] = 0; // don't need to copy the right margin, since we are directly decoding into the margin - return; + } + + // sort the spans into write output order + if ( ( scanline_extents->spans[1].n1 > scanline_extents->spans[1].n0 ) && ( scanline_extents->spans[0].n0 > scanline_extents->spans[1].n0 ) ) + { + stbir__span tspan = scanline_extents->spans[0]; + scanline_extents->spans[0] = scanline_extents->spans[1]; + scanline_extents->spans[1] = tspan; } } @@ -3328,23 +3379,29 @@ static void stbir__calculate_coefficients_for_gather_upsample( float out_filter_ static void stbir__insert_coeff( stbir__contributors * contribs, float * coeffs, int new_pixel, float new_coeff, int max_width ) { - if ( new_pixel <= contribs->n1 ) // before the end + if ( contribs->n1 < contribs->n0 ) // this first clause should never happen, but handle in case + { + contribs->n0 = contribs->n1 = new_pixel; + coeffs[0] = new_coeff; + } + else if ( new_pixel <= contribs->n1 ) // before the end { if ( new_pixel < contribs->n0 ) // before the front? { if ( ( contribs->n1 - new_pixel + 1 ) <= max_width ) { int j, o = contribs->n0 - new_pixel; - for ( j = contribs->n1 - contribs->n0 ; j <= 0 ; j-- ) + for ( j = contribs->n1 - contribs->n0 ; j >= 0 ; j-- ) coeffs[ j + o ] = coeffs[ j ]; - for ( j = 1 ; j < o ; j-- ) - coeffs[ j ] = coeffs[ 0 ]; + for ( j = 1 ; j < o ; j++ ) + coeffs[ j ] = 0; coeffs[ 0 ] = new_coeff; contribs->n0 = new_pixel; } } else { + // add new weight to existing coeff if already there coeffs[ new_pixel - contribs->n0 ] += new_coeff; } } @@ -3791,7 +3848,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } } - // some horizontal routines read one float off the end (which is then masked off), so put in a sentinal so we don't read an snan or denormal + // some horizontal routines read one float off the end (which is then masked off), so put in a sentinel so we don't read an snan or denormal coefficents[ widest * num_contributors ] = 8888.0f; // the minimum we might read for unrolled filters widths is 12. So, we need to @@ -4560,7 +4617,8 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float int row = stbir__edge_wrap(edge_vertical, n, stbir_info->vertical.scale_info.input_full_size); const void* input_plane_data = ( (char *) stbir_info->input_data ) + (size_t)row * (size_t) stbir_info->input_stride_bytes; stbir__span const * spans = stbir_info->scanline_extents.spans; - float* full_decode_buffer = output_buffer - stbir_info->scanline_extents.conservative.n0 * effective_channels; + float * full_decode_buffer = output_buffer - stbir_info->scanline_extents.conservative.n0 * effective_channels; + float * last_decoded = 0; // if we are on edge_zero, and we get in here with an out of bounds n, then the calculate filters has failed STBIR_ASSERT( !(edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->vertical.scale_info.input_full_size)) ); @@ -4588,12 +4646,12 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float if ( stbir_info->in_pixels_cb ) { // call the callback with a temp buffer (that they can choose to use or not). the temp is just right aligned memory in the decode_buffer itself - input_data = stbir_info->in_pixels_cb( ( (char*) end_decode ) - ( width * input_sample_in_bytes ), input_plane_data, width, spans->pixel_offset_for_input, row, stbir_info->user_data ); + input_data = stbir_info->in_pixels_cb( ( (char*) end_decode ) - ( width * input_sample_in_bytes ) + ( ( stbir_info->input_type != STBIR_TYPE_FLOAT ) ? ( sizeof(float)*STBIR_INPUT_CALLBACK_PADDING ) : 0 ), input_plane_data, width, spans->pixel_offset_for_input, row, stbir_info->user_data ); } STBIR_PROFILE_START( decode ); // convert the pixels info the float decode_buffer, (we index from end_decode, so that when channelsdecode_pixels( (float*)end_decode - width_times_channels, width_times_channels, input_data ); + last_decoded = stbir_info->decode_pixels( (float*)end_decode - width_times_channels, width_times_channels, input_data ); STBIR_PROFILE_END( decode ); if (stbir_info->alpha_weight) @@ -4628,9 +4686,19 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float float * marg = full_decode_buffer + x * effective_channels; float const * src = full_decode_buffer + stbir__edge_wrap(edge_horizontal, x, input_full_size) * effective_channels; STBIR_MEMCPY( marg, src, margin * effective_channels * sizeof(float) ); + if ( e == 1 ) last_decoded = marg + margin * effective_channels; } } } + + // some of the horizontal gathers read one float off the edge (which is masked out), but we force a zero here to make sure no NaNs leak in + // (we can't pre-zero it, because the input callback can use that area as padding) + last_decoded[0] = 0.0f; + + // we clear this extra float, because the final output pixel filter kernel might have used one less coeff than the max filter width + // when this happens, we do read that pixel from the input, so it too could be Nan, so just zero an extra one. + // this fits because each scanline is padded by three floats (STBIR_INPUT_CALLBACK_PADDING) + last_decoded[1] = 0.0f; } @@ -6209,6 +6277,8 @@ static void stbir__resample_vertical_gather(stbir__info const * stbir_info, stbi if ( vertical_first ) { // Now resample the gathered vertical data in the horizontal axis into the encode buffer + decode_buffer[ width_times_channels ] = 0.0f; // clear two over for horizontals with a remnant of 3 + decode_buffer[ width_times_channels+1 ] = 0.0f; stbir__resample_horizontal_gather(stbir_info, encode_buffer, decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); } @@ -6380,6 +6450,8 @@ static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir_ void * scanline_scatter_buffer; void * scanline_scatter_buffer_end; int on_first_input_y, last_input_y; + int width = (stbir_info->vertical_first) ? ( stbir_info->scanline_extents.conservative.n1-stbir_info->scanline_extents.conservative.n0+1 ) : stbir_info->horizontal.scale_info.output_sub_size; + int width_times_channels = stbir_info->effective_channels * width; STBIR_ASSERT( !stbir_info->vertical.is_gather ); @@ -6414,7 +6486,12 @@ static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir_ // mark all the buffers as empty to start for( y = 0 ; y < stbir_info->ring_buffer_num_entries ; y++ ) - stbir__get_ring_buffer_entry( stbir_info, split_info, y )[0] = STBIR__FLOAT_EMPTY_MARKER; // only used on scatter + { + float * decode_buffer = stbir__get_ring_buffer_entry( stbir_info, split_info, y ); + decode_buffer[ width_times_channels ] = 0.0f; // clear two over for horizontals with a remnant of 3 + decode_buffer[ width_times_channels+1 ] = 0.0f; + decode_buffer[0] = STBIR__FLOAT_EMPTY_MARKER; // only used on scatter + } // do the loop in input space on_first_input_y = 1; last_input_y = start_input_y; @@ -6562,7 +6639,7 @@ static void stbir__set_sampler(stbir__sampler * samp, stbir_filter filter, stbir samp->num_contributors = stbir__get_contributors(samp, samp->is_gather); samp->contributors_size = samp->num_contributors * sizeof(stbir__contributors); - samp->coefficients_size = samp->num_contributors * samp->coefficient_width * sizeof(float) + sizeof(float); // extra sizeof(float) is padding + samp->coefficients_size = samp->num_contributors * samp->coefficient_width * sizeof(float) + sizeof(float)*STBIR_INPUT_CALLBACK_PADDING; // extra sizeof(float) is padding samp->gather_prescatter_contributors = 0; samp->gather_prescatter_coefficients = 0; @@ -6667,7 +6744,7 @@ static void stbir__get_conservative_extents( stbir__sampler * samp, stbir__contr } } -static void stbir__get_split_info( stbir__per_split_info* split_info, int splits, int output_height, int vertical_pixel_margin, int input_full_height ) +static void stbir__get_split_info( stbir__per_split_info* split_info, int splits, int output_height, int vertical_pixel_margin, int input_full_height, int is_gather, stbir__contributors * contribs ) { int i, cur; int left = output_height; @@ -6676,9 +6753,58 @@ static void stbir__get_split_info( stbir__per_split_info* split_info, int splits for( i = 0 ; i < splits ; i++ ) { int each; + split_info[i].start_output_y = cur; each = left / ( splits - i ); split_info[i].end_output_y = cur + each; + + // ok, when we are gathering, we need to make sure we are starting on a y offset that doesn't have + // a "special" set of coefficients. Basically, with exactly the right filter at exactly the right + // resize at exactly the right phase, some of the coefficents can be zero. When they are zero, we + // don't process them at all. But this leads to a tricky thing with the thread splits, where we + // might have a set of two coeffs like this for example: (4,4) and (3,6). The 4,4 means there was + // just one single coeff because things worked out perfectly (normally, they all have 4 coeffs + // like the range 3,6. The problem is that if we start right on the (4,4) on a brand new thread, + // then when we get to (3,6), we don't have the "3" sample in memory (because we didn't load + // it on the initial (4,4) range because it didn't have a 3 (we only add new samples that are + // larger than our existing samples - it's just how the eviction works). So, our solution here + // is pretty simple, if we start right on a range that has samples that start earlier, then we + // simply bump up our previous thread split range to include it, and then start this threads + // range with the smaller sample. It just moves one scanline from one thread split to another, + // so that we end with the unusual one, instead of start with it. To do this, we check 2-4 + // sample at each thread split start and then occassionally move them. + + if ( ( is_gather ) && ( i ) ) + { + stbir__contributors * small_contribs; + int j, smallest, stop, start_n0; + stbir__contributors * split_contribs = contribs + cur; + + // scan for a max of 3x the filter width or until the next thread split + stop = vertical_pixel_margin * 3; + if ( each < stop ) + stop = each; + + // loops a few times before early out + smallest = 0; + small_contribs = split_contribs; + start_n0 = small_contribs->n0; + for( j = 1 ; j <= stop ; j++ ) + { + ++split_contribs; + if ( split_contribs->n0 > start_n0 ) + break; + if ( split_contribs->n0 < small_contribs->n0 ) + { + small_contribs = split_contribs; + smallest = j; + } + } + + split_info[i-1].end_output_y += smallest; + split_info[i].start_output_y += smallest; + } + cur += each; left -= each; @@ -6774,45 +6900,45 @@ static float stbir__compute_weights[5][STBIR_RESIZE_CLASSIFICATIONS][4]= // 5 = { 0.56250f, 0.59375f, 0.00000f, 0.96875f }, { 1.00000f, 0.06250f, 0.00000f, 1.00000f }, { 0.00000f, 0.09375f, 1.00000f, 1.00000f }, - { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 0.31250f, 1.00000f }, { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, - { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 0.06250f, 1.00000f }, { 0.00000f, 1.00000f, 0.00000f, 0.03125f }, }, { { 0.00000f, 0.84375f, 0.00000f, 0.03125f }, { 0.09375f, 0.93750f, 0.00000f, 0.78125f }, { 0.87500f, 0.21875f, 0.00000f, 0.96875f }, { 0.09375f, 0.09375f, 1.00000f, 1.00000f }, - { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.00000f, 0.84375f, 0.00000f, 0.03125f }, { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, - { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 0.06250f, 1.00000f }, { 0.00000f, 1.00000f, 0.00000f, 0.53125f }, }, { { 0.00000f, 0.53125f, 0.00000f, 0.03125f }, { 0.06250f, 0.96875f, 0.00000f, 0.53125f }, { 0.87500f, 0.18750f, 0.00000f, 0.93750f }, { 0.00000f, 0.09375f, 1.00000f, 1.00000f }, - { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.00000f, 0.53125f, 0.00000f, 0.03125f }, { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, - { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 0.06250f, 1.00000f }, { 0.00000f, 1.00000f, 0.00000f, 0.56250f }, }, { { 0.00000f, 0.50000f, 0.00000f, 0.71875f }, { 0.06250f, 0.84375f, 0.00000f, 0.87500f }, { 1.00000f, 0.50000f, 0.50000f, 0.96875f }, { 1.00000f, 0.09375f, 0.31250f, 0.50000f }, - { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.00000f, 0.50000f, 0.00000f, 0.71875f }, { 1.00000f, 0.03125f, 0.03125f, 0.53125f }, - { 0.18750f, 0.12500f, 0.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 0.06250f, 1.00000f }, { 0.00000f, 1.00000f, 0.03125f, 0.18750f }, }, { { 0.00000f, 0.59375f, 0.00000f, 0.96875f }, { 0.06250f, 0.81250f, 0.06250f, 0.59375f }, { 0.75000f, 0.43750f, 0.12500f, 0.96875f }, { 0.87500f, 0.06250f, 0.18750f, 0.43750f }, - { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.00000f, 0.59375f, 0.00000f, 0.96875f }, { 0.15625f, 0.12500f, 1.00000f, 1.00000f }, - { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 0.06250f, 1.00000f }, { 0.00000f, 1.00000f, 0.03125f, 0.34375f }, } }; @@ -6866,16 +6992,16 @@ static int stbir__should_do_vertical_first( float weights_table[STBIR_RESIZE_CLA // categorize the resize into buckets if ( ( vertical_output_size <= 4 ) || ( horizontal_output_size <= 4 ) ) v_classification = ( vertical_output_size < horizontal_output_size ) ? 6 : 7; + else if ( ( !is_gather ) && ( ( vertical_output_size <= 16 ) || ( horizontal_output_size <= 16 ) ) ) + v_classification = 4; else if ( vertical_scale <= 1.0f ) v_classification = ( is_gather ) ? 1 : 0; else if ( vertical_scale <= 2.0f) v_classification = 2; else if ( vertical_scale <= 3.0f) v_classification = 3; - else if ( vertical_scale <= 4.0f) - v_classification = 5; - else - v_classification = 6; + else + v_classification = 5; // everything bigger than 3x // use the right weights weights = weights_table[ v_classification ]; @@ -6927,7 +7053,8 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample void * alloced = 0; size_t alloced_total = 0; int vertical_first; - int decode_buffer_size, ring_buffer_length_bytes, ring_buffer_size, vertical_buffer_size, alloc_ring_buffer_num_entries; + size_t decode_buffer_size, ring_buffer_length_bytes, ring_buffer_size, vertical_buffer_size; + int alloc_ring_buffer_num_entries; int alpha_weighting_type = 0; // 0=none, 1=simple, 2=fancy int conservative_split_output_size = stbir__get_max_split( splits, vertical->scale_info.output_sub_size ); @@ -6972,14 +7099,16 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample vertical_first = stbir__should_do_vertical_first( stbir__compute_weights[ (int)stbir_channel_count_index[ effective_channels ] ], horizontal->filter_pixel_width, horizontal->scale_info.scale, horizontal->scale_info.output_sub_size, vertical->filter_pixel_width, vertical->scale_info.scale, vertical->scale_info.output_sub_size, vertical->is_gather, STBIR__V_FIRST_INFO_POINTER ); // sometimes read one float off in some of the unrolled loops (with a weight of zero coeff, so it doesn't have an effect) - decode_buffer_size = ( conservative->n1 - conservative->n0 + 1 ) * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + // we use a few extra floats instead of just 1, so that input callback buffer can overlap with the decode buffer without + // the conversion routines overwriting the callback input data. + decode_buffer_size = ( conservative->n1 - conservative->n0 + 1 ) * effective_channels * sizeof(float) + sizeof(float)*STBIR_INPUT_CALLBACK_PADDING; // extra floats for input callback stagger #if defined( STBIR__SEPARATE_ALLOCATIONS ) && defined(STBIR_SIMD8) if ( effective_channels == 3 ) decode_buffer_size += sizeof(float); // avx in 3 channel mode needs one float at the start of the buffer (only with separate allocations) #endif - ring_buffer_length_bytes = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + ring_buffer_length_bytes = (size_t)horizontal->scale_info.output_sub_size * (size_t)effective_channels * sizeof(float) + sizeof(float)*STBIR_INPUT_CALLBACK_PADDING; // extra floats for padding // if we do vertical first, the ring buffer holds a whole decoded line if ( vertical_first ) @@ -6994,13 +7123,13 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample if ( ( !vertical->is_gather ) && ( alloc_ring_buffer_num_entries > conservative_split_output_size ) ) alloc_ring_buffer_num_entries = conservative_split_output_size; - ring_buffer_size = alloc_ring_buffer_num_entries * ring_buffer_length_bytes; + ring_buffer_size = (size_t)alloc_ring_buffer_num_entries * (size_t)ring_buffer_length_bytes; // The vertical buffer is used differently, depending on whether we are scattering // the vertical scanlines, or gathering them. // If scattering, it's used at the temp buffer to accumulate each output. // If gathering, it's just the output buffer. - vertical_buffer_size = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + vertical_buffer_size = (size_t)horizontal->scale_info.output_sub_size * (size_t)effective_channels * sizeof(float) + sizeof(float); // extra float for padding // we make two passes through this loop, 1st to add everything up, 2nd to allocate and init for(;;) @@ -7013,7 +7142,7 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample #ifdef STBIR__SEPARATE_ALLOCATIONS #define STBIR__NEXT_PTR( ptr, size, ntype ) if ( alloced ) { void * p = STBIR_MALLOC( size, user_data); if ( p == 0 ) { stbir__free_internal_mem( info ); return 0; } (ptr) = (ntype*)p; } #else - #define STBIR__NEXT_PTR( ptr, size, ntype ) advance_mem = (void*) ( ( ((size_t)advance_mem) + 15 ) & ~15 ); if ( alloced ) ptr = (ntype*)advance_mem; advance_mem = ((char*)advance_mem) + (size); + #define STBIR__NEXT_PTR( ptr, size, ntype ) advance_mem = (void*) ( ( ((size_t)advance_mem) + 15 ) & ~15 ); if ( alloced ) ptr = (ntype*)advance_mem; advance_mem = (char*)(((size_t)advance_mem) + (size)); #endif STBIR__NEXT_PTR( info, sizeof( stbir__info ), stbir__info ); @@ -7036,9 +7165,9 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample info->offset_x = new_x; info->offset_y = new_y; - info->alloc_ring_buffer_num_entries = alloc_ring_buffer_num_entries; + info->alloc_ring_buffer_num_entries = (int)alloc_ring_buffer_num_entries; info->ring_buffer_num_entries = 0; - info->ring_buffer_length_bytes = ring_buffer_length_bytes; + info->ring_buffer_length_bytes = (int)ring_buffer_length_bytes; info->splits = splits; info->vertical_first = vertical_first; @@ -7119,14 +7248,14 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample // alloc memory for to-be-pivoted coeffs (if necessary) if ( vertical->is_gather == 0 ) { - int both; - int temp_mem_amt; + size_t both; + size_t temp_mem_amt; // when in vertical scatter mode, we first build the coefficients in gather mode, and then pivot after, // that means we need two buffers, so we try to use the decode buffer and ring buffer for this. if that // is too small, we just allocate extra memory to use as this temp. - both = vertical->gather_prescatter_contributors_size + vertical->gather_prescatter_coefficients_size; + both = (size_t)vertical->gather_prescatter_contributors_size + (size_t)vertical->gather_prescatter_coefficients_size; #ifdef STBIR__SEPARATE_ALLOCATIONS temp_mem_amt = decode_buffer_size; @@ -7136,7 +7265,7 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample --temp_mem_amt; // avx in 3 channel mode needs one float at the start of the buffer #endif #else - temp_mem_amt = ( decode_buffer_size + ring_buffer_size + vertical_buffer_size ) * splits; + temp_mem_amt = (size_t)( decode_buffer_size + ring_buffer_size + vertical_buffer_size ) * (size_t)splits; #endif if ( temp_mem_amt >= both ) { @@ -7222,7 +7351,7 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample } // setup the vertical split ranges - stbir__get_split_info( info->split_info, info->splits, info->vertical.scale_info.output_sub_size, info->vertical.filter_pixel_margin, info->vertical.scale_info.input_full_size ); + stbir__get_split_info( info->split_info, info->splits, info->vertical.scale_info.output_sub_size, info->vertical.filter_pixel_margin, info->vertical.scale_info.input_full_size, info->vertical.is_gather, info->vertical.contributors ); // now we know precisely how many entries we need info->ring_buffer_num_entries = info->vertical.extent_info.widest; @@ -7231,39 +7360,7 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample if ( ( !info->vertical.is_gather ) && ( info->ring_buffer_num_entries > conservative_split_output_size ) ) info->ring_buffer_num_entries = conservative_split_output_size; STBIR_ASSERT( info->ring_buffer_num_entries <= info->alloc_ring_buffer_num_entries ); - - // a few of the horizontal gather functions read past the end of the decode (but mask it out), - // so put in normal values so no snans or denormals accidentally sneak in (also, in the ring - // buffer for vertical first) - for( i = 0 ; i < splits ; i++ ) - { - int t, ofs, start; - - ofs = decode_buffer_size / 4; - - #if defined( STBIR__SEPARATE_ALLOCATIONS ) && defined(STBIR_SIMD8) - if ( effective_channels == 3 ) - --ofs; // avx in 3 channel mode needs one float at the start of the buffer, so we snap back for clearing - #endif - - start = ofs - 4; - if ( start < 0 ) start = 0; - - for( t = start ; t < ofs; t++ ) - info->split_info[i].decode_buffer[ t ] = 9999.0f; - - if ( vertical_first ) - { - int j; - for( j = 0; j < info->ring_buffer_num_entries ; j++ ) - { - for( t = start ; t < ofs; t++ ) - stbir__get_ring_buffer_entry( info, info->split_info + i, j )[ t ] = 9999.0f; - } - } - } } - #undef STBIR__NEXT_PTR @@ -7528,7 +7625,7 @@ static int stbir__double_to_rational(double f, stbir_uint32 limit, stbir_uint32 numer_estimate = temp; } - // we didn't fine anything good enough for float, use a full range estimate + // we didn't find anything good enough for float, use a full range estimate if ( limit_denom ) { numer_estimate= (stbir_uint64)( f * (double)limit + 0.5 ); @@ -7818,7 +7915,7 @@ static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) stbir__set_sampler(&horizontal, resize->horizontal_filter, resize->horizontal_filter_kernel, resize->horizontal_filter_support, resize->horizontal_edge, &horizontal.scale_info, 1, resize->user_data ); stbir__get_conservative_extents( &horizontal, &conservative, resize->user_data ); - stbir__set_sampler(&vertical, resize->vertical_filter, resize->horizontal_filter_kernel, resize->vertical_filter_support, resize->vertical_edge, &vertical.scale_info, 0, resize->user_data ); + stbir__set_sampler(&vertical, resize->vertical_filter, resize->vertical_filter_kernel, resize->vertical_filter_support, resize->vertical_edge, &vertical.scale_info, 0, resize->user_data ); if ( ( vertical.scale_info.output_sub_size / splits ) < STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS ) // each split should be a minimum of 4 scanlines (handwavey choice) { @@ -7849,7 +7946,7 @@ static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) return 0; } -void stbir_free_samplers( STBIR_RESIZE * resize ) +STBIRDEF void stbir_free_samplers( STBIR_RESIZE * resize ) { if ( resize->samplers ) { @@ -7943,138 +8040,64 @@ STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start return stbir__perform_resize( resize->samplers, split_start, split_count ); } -static int stbir__check_output_stuff( void ** ret_ptr, int * ret_pitch, void * output_pixels, int type_size, int output_w, int output_h, int output_stride_in_bytes, stbir_internal_pixel_layout pixel_layout ) + +static void * stbir_quick_resize_helper( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout, stbir_datatype data_type, stbir_edge edge, stbir_filter filter ) { - size_t size; - int pitch; - void * ptr; + STBIR_RESIZE resize; + int scanline_output_in_bytes; + int positive_output_stride_in_bytes; + void * start_ptr; + void * free_ptr; - pitch = output_w * type_size * stbir__pixel_channels[ pixel_layout ]; - if ( pitch == 0 ) + scanline_output_in_bytes = output_w * stbir__type_size[ data_type ] * stbir__pixel_channels[ stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ]; + if ( scanline_output_in_bytes == 0 ) return 0; + // if zero stride, use scanline output if ( output_stride_in_bytes == 0 ) - output_stride_in_bytes = pitch; + output_stride_in_bytes = scanline_output_in_bytes; - if ( output_stride_in_bytes < pitch ) + // abs value for inverted images (negative pitches) + positive_output_stride_in_bytes = output_stride_in_bytes; + if ( positive_output_stride_in_bytes < 0 ) + positive_output_stride_in_bytes = -positive_output_stride_in_bytes; + + // is the requested stride smaller than the scanline output? if so, just fail + if ( positive_output_stride_in_bytes < scanline_output_in_bytes ) return 0; - size = (size_t)output_stride_in_bytes * (size_t)output_h; - if ( size == 0 ) - return 0; - - *ret_ptr = 0; - *ret_pitch = output_stride_in_bytes; + start_ptr = output_pixels; + free_ptr = 0; // no free pointer, since they passed buffer to use + // did they pass a zero for the dest? if so, allocate the buffer if ( output_pixels == 0 ) { - ptr = STBIR_MALLOC( size, 0 ); + size_t size; + char * ptr; + + size = (size_t)positive_output_stride_in_bytes * (size_t)output_h; + if ( size == 0 ) + return 0; + + ptr = (char*) STBIR_MALLOC( size, 0 ); if ( ptr == 0 ) return 0; - *ret_ptr = ptr; - *ret_pitch = pitch; + free_ptr = ptr; + + // point at the last scanline, if they requested a flipped image + if ( output_stride_in_bytes < 0 ) + start_ptr = ptr + ( (size_t)positive_output_stride_in_bytes * (size_t)( output_h - 1 ) ); + else + start_ptr = ptr; } - return 1; -} - - -STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, - unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, - stbir_pixel_layout pixel_layout ) -{ - STBIR_RESIZE resize; - unsigned char * optr; - int opitch; - - if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) - return 0; - + // ok, now do the resize stbir_resize_init( &resize, input_pixels, input_w, input_h, input_stride_in_bytes, - (optr) ? optr : output_pixels, output_w, output_h, opitch, - pixel_layout, STBIR_TYPE_UINT8 ); - - if ( !stbir_resize_extended( &resize ) ) - { - if ( optr ) - STBIR_FREE( optr, 0 ); - return 0; - } - - return (optr) ? optr : output_pixels; -} - -STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, - unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, - stbir_pixel_layout pixel_layout ) -{ - STBIR_RESIZE resize; - unsigned char * optr; - int opitch; - - if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) - return 0; - - stbir_resize_init( &resize, - input_pixels, input_w, input_h, input_stride_in_bytes, - (optr) ? optr : output_pixels, output_w, output_h, opitch, - pixel_layout, STBIR_TYPE_UINT8_SRGB ); - - if ( !stbir_resize_extended( &resize ) ) - { - if ( optr ) - STBIR_FREE( optr, 0 ); - return 0; - } - - return (optr) ? optr : output_pixels; -} - - -STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes, - float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, - stbir_pixel_layout pixel_layout ) -{ - STBIR_RESIZE resize; - float * optr; - int opitch; - - if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( float ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) - return 0; - - stbir_resize_init( &resize, - input_pixels, input_w, input_h, input_stride_in_bytes, - (optr) ? optr : output_pixels, output_w, output_h, opitch, - pixel_layout, STBIR_TYPE_FLOAT ); - - if ( !stbir_resize_extended( &resize ) ) - { - if ( optr ) - STBIR_FREE( optr, 0 ); - return 0; - } - - return (optr) ? optr : output_pixels; -} - - -STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes, - void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, - stbir_pixel_layout pixel_layout, stbir_datatype data_type, - stbir_edge edge, stbir_filter filter ) -{ - STBIR_RESIZE resize; - float * optr; - int opitch; - - if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, stbir__type_size[data_type], output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) - return 0; - - stbir_resize_init( &resize, - input_pixels, input_w, input_h, input_stride_in_bytes, - (optr) ? optr : output_pixels, output_w, output_h, output_stride_in_bytes, + start_ptr, output_w, output_h, output_stride_in_bytes, pixel_layout, data_type ); resize.horizontal_edge = edge; @@ -8084,19 +8107,60 @@ STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input if ( !stbir_resize_extended( &resize ) ) { - if ( optr ) - STBIR_FREE( optr, 0 ); + if ( free_ptr ) + STBIR_FREE( free_ptr, 0 ); return 0; } - return (optr) ? optr : output_pixels; + return (free_ptr) ? free_ptr : start_ptr; +} + + + +STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + return (unsigned char *) stbir_quick_resize_helper( input_pixels , input_w , input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout, STBIR_TYPE_UINT8, STBIR_EDGE_CLAMP, STBIR_FILTER_DEFAULT ); +} + +STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + return (unsigned char *) stbir_quick_resize_helper( input_pixels , input_w , input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout, STBIR_TYPE_UINT8_SRGB, STBIR_EDGE_CLAMP, STBIR_FILTER_DEFAULT ); +} + + +STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + return (float *) stbir_quick_resize_helper( input_pixels , input_w , input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout, STBIR_TYPE_FLOAT, STBIR_EDGE_CLAMP, STBIR_FILTER_DEFAULT ); +} + + +STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout, stbir_datatype data_type, + stbir_edge edge, stbir_filter filter ) +{ + return (void *) stbir_quick_resize_helper( input_pixels , input_w , input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout, data_type, edge, filter ); } #ifdef STBIR_PROFILE STBIRDEF void stbir_resize_build_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize ) { - static char const * bdescriptions[6] = { "Building", "Allocating", "Horizontal sampler", "Vertical sampler", "Coefficient cleanup", "Coefficient piovot" } ; + static char const * bdescriptions[6] = { "Building", "Allocating", "Horizontal sampler", "Vertical sampler", "Coefficient cleanup", "Coefficient pivot" } ; stbir__info* samp = resize->samplers; int i; @@ -8147,7 +8211,7 @@ STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * info, STBIR_ info->clocks[i] = sum; } - info->total_clocks = split_info->profile.named.total; + info->total_clocks = split_info->profile.named.total; info->descriptions = descriptions; info->count = STBIR__ARRAY_SIZE( descriptions ); } @@ -8226,7 +8290,7 @@ STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * info, STB #define stbir__encode_simdfX_unflip stbir__encode_simdf4_unflip #endif -static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * decodep, int width_times_channels, void const * inputp ) +static float * STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * decodep, int width_times_channels, void const * inputp ) { float STBIR_STREAMOUT_PTR( * ) decode = decodep; float * decode_end = (float*) decode + width_times_channels; @@ -8286,7 +8350,7 @@ static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * deco decode = decode_end; // backup and do last couple input = end_input_m16; } - return; + return decode_end + 16; } #endif @@ -8324,6 +8388,8 @@ static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * deco input += stbir__coder_min_num; } #endif + + return decode_end; } static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outputp, int width_times_channels, float const * encode ) @@ -8443,7 +8509,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outpu #endif } -static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int width_times_channels, void const * inputp ) +static float * STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int width_times_channels, void const * inputp ) { float STBIR_STREAMOUT_PTR( * ) decode = decodep; float * decode_end = (float*) decode + width_times_channels; @@ -8497,7 +8563,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int decode = decode_end; // backup and do last couple input = end_input_m16; } - return; + return decode_end + 16; } #endif @@ -8535,6 +8601,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int input += stbir__coder_min_num; } #endif + return decode_end; } static void STBIR__CODER_NAME( stbir__encode_uint8_linear )( void * outputp, int width_times_channels, float const * encode ) @@ -8636,10 +8703,10 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear )( void * outputp, int #endif } -static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int width_times_channels, void const * inputp ) +static float * STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int width_times_channels, void const * inputp ) { float STBIR_STREAMOUT_PTR( * ) decode = decodep; - float const * decode_end = (float*) decode + width_times_channels; + float * decode_end = (float*) decode + width_times_channels; unsigned char const * input = (unsigned char const *)inputp; // try to do blocks of 4 when you can @@ -8674,6 +8741,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int wi input += stbir__coder_min_num; } #endif + return decode_end; } #define stbir__min_max_shift20( i, f ) \ @@ -8691,7 +8759,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int wi { \ stbir__simdi temp; \ stbir__simdi_32shr( temp, stbir_simdi_castf( f ), 12 ) ; \ - stbir__simdi_and( temp, temp, STBIR__CONSTI(STBIR_mastissa_mask) ); \ + stbir__simdi_and( temp, temp, STBIR__CONSTI(STBIR_mantissa_mask) ); \ stbir__simdi_or( temp, temp, STBIR__CONSTI(STBIR_topscale) ); \ stbir__simdi_16madd( i, i, temp ); \ stbir__simdi_32shr( i, i, 16 ); \ @@ -8826,11 +8894,12 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int w #if ( stbir__coder_min_num == 4 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) ) -static void STBIR__CODER_NAME(stbir__decode_uint8_srgb4_linearalpha)( float * decodep, int width_times_channels, void const * inputp ) +static float * STBIR__CODER_NAME(stbir__decode_uint8_srgb4_linearalpha)( float * decodep, int width_times_channels, void const * inputp ) { float STBIR_STREAMOUT_PTR( * ) decode = decodep; - float const * decode_end = (float*) decode + width_times_channels; + float * decode_end = (float*) decode + width_times_channels; unsigned char const * input = (unsigned char const *)inputp; + do { decode[0] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ]; decode[1] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order1] ]; @@ -8839,6 +8908,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_srgb4_linearalpha)( float * de input += 4; decode += 4; } while( decode < decode_end ); + return decode_end; } @@ -8911,11 +8981,12 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb4_linearalpha )( void * o #if ( stbir__coder_min_num == 2 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) ) -static void STBIR__CODER_NAME(stbir__decode_uint8_srgb2_linearalpha)( float * decodep, int width_times_channels, void const * inputp ) +static float * STBIR__CODER_NAME(stbir__decode_uint8_srgb2_linearalpha)( float * decodep, int width_times_channels, void const * inputp ) { float STBIR_STREAMOUT_PTR( * ) decode = decodep; - float const * decode_end = (float*) decode + width_times_channels; + float * decode_end = (float*) decode + width_times_channels; unsigned char const * input = (unsigned char const *)inputp; + decode += 4; while( decode <= decode_end ) { @@ -8929,9 +9000,10 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_srgb2_linearalpha)( float * de decode -= 4; if( decode < decode_end ) { - decode[0] = stbir__srgb_uchar_to_linear_float[ stbir__decode_order0 ]; + decode[0] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ]; decode[1] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted; } + return decode_end; } static void STBIR__CODER_NAME( stbir__encode_uint8_srgb2_linearalpha )( void * outputp, int width_times_channels, float const * encode ) @@ -8997,7 +9069,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb2_linearalpha )( void * o #endif -static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decodep, int width_times_channels, void const * inputp ) +static float * STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decodep, int width_times_channels, void const * inputp ) { float STBIR_STREAMOUT_PTR( * ) decode = decodep; float * decode_end = (float*) decode + width_times_channels; @@ -9045,7 +9117,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decod decode = decode_end; // backup and do last couple input = end_input_m8; } - return; + return decode_end + 8; } #endif @@ -9083,6 +9155,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decod input += stbir__coder_min_num; } #endif + return decode_end; } @@ -9202,7 +9275,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * output #endif } -static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int width_times_channels, void const * inputp ) +static float * STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int width_times_channels, void const * inputp ) { float STBIR_STREAMOUT_PTR( * ) decode = decodep; float * decode_end = (float*) decode + width_times_channels; @@ -9247,7 +9320,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int decode = decode_end; // backup and do last couple input = end_input_m8; } - return; + return decode_end + 8; } #endif @@ -9285,6 +9358,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int input += stbir__coder_min_num; } #endif + return decode_end; } static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int width_times_channels, float const * encode ) @@ -9385,7 +9459,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int #endif } -static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, int width_times_channels, void const * inputp ) +static float * STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, int width_times_channels, void const * inputp ) { float STBIR_STREAMOUT_PTR( * ) decode = decodep; float * decode_end = (float*) decode + width_times_channels; @@ -9431,7 +9505,7 @@ static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, decode = decode_end; // backup and do last couple input = end_input_m8; } - return; + return decode_end + 8; } #endif @@ -9469,6 +9543,7 @@ static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, input += stbir__coder_min_num; } #endif + return decode_end; } static void STBIR__CODER_NAME( stbir__encode_half_float_linear )( void * outputp, int width_times_channels, float const * encode ) @@ -9555,7 +9630,7 @@ static void STBIR__CODER_NAME( stbir__encode_half_float_linear )( void * outputp #endif } -static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int width_times_channels, void const * inputp ) +static float * STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int width_times_channels, void const * inputp ) { #ifdef stbir__decode_swizzle float STBIR_STREAMOUT_PTR( * ) decode = decodep; @@ -9609,7 +9684,7 @@ static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int decode = decode_end; // backup and do last couple input = end_input_m16; } - return; + return decode_end + 16; } #endif @@ -9647,18 +9722,21 @@ static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int input += stbir__coder_min_num; } #endif + return decode_end; #else if ( (void*)decodep != inputp ) STBIR_MEMCPY( decodep, inputp, width_times_channels * sizeof( float ) ); + return decodep + width_times_channels; + #endif } static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int width_times_channels, float const * encode ) { - #if !defined( STBIR_FLOAT_HIGH_CLAMP ) && !defined(STBIR_FLOAT_LO_CLAMP) && !defined(stbir__decode_swizzle) + #if !defined( STBIR_FLOAT_HIGH_CLAMP ) && !defined(STBIR_FLOAT_LOW_CLAMP) && !defined(stbir__decode_swizzle) if ( (void*)outputp != (void*) encode ) STBIR_MEMCPY( outputp, encode, width_times_channels * sizeof( float ) ); @@ -9713,7 +9791,7 @@ static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int stbir__simdfX_store( output+stbir__simdfX_float_count, e1 ); encode += stbir__simdfX_float_count * 2; output += stbir__simdfX_float_count * 2; - if ( output < end_output ) + if ( output <= end_output ) continue; if ( output == ( end_output + ( stbir__simdfX_float_count * 2 ) ) ) break; From 6c0134bb5c4309713cccacf06ad03a4c06bcc2af Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:24:24 +0200 Subject: [PATCH 038/185] Create cgltf_write.h --- src/external/cgltf_write.h | 1565 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1565 insertions(+) create mode 100644 src/external/cgltf_write.h diff --git a/src/external/cgltf_write.h b/src/external/cgltf_write.h new file mode 100644 index 000000000..4c060da79 --- /dev/null +++ b/src/external/cgltf_write.h @@ -0,0 +1,1565 @@ +/** + * cgltf_write - a single-file glTF 2.0 writer written in C99. + * + * Version: 1.15 + * + * Website: https://github.com/jkuhlmann/cgltf + * + * Distributed under the MIT License, see notice at the end of this file. + * + * Building: + * Include this file where you need the struct and function + * declarations. Have exactly one source file where you define + * `CGLTF_WRITE_IMPLEMENTATION` before including this file to get the + * function definitions. + * + * Reference: + * `cgltf_result cgltf_write_file(const cgltf_options* options, const char* + * path, const cgltf_data* data)` writes a glTF data to the given file path. + * If `options->type` is `cgltf_file_type_glb`, both JSON content and binary + * buffer of the given glTF data will be written in a GLB format. + * Otherwise, only the JSON part will be written. + * External buffers and images are not written out. `data` is not deallocated. + * + * `cgltf_size cgltf_write(const cgltf_options* options, char* buffer, + * cgltf_size size, const cgltf_data* data)` writes JSON into the given memory + * buffer. Returns the number of bytes written to `buffer`, including a null + * terminator. If buffer is null, returns the number of bytes that would have + * been written. `data` is not deallocated. + */ +#ifndef CGLTF_WRITE_H_INCLUDED__ +#define CGLTF_WRITE_H_INCLUDED__ + +#include "cgltf.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +cgltf_result cgltf_write_file(const cgltf_options* options, const char* path, const cgltf_data* data); +cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size size, const cgltf_data* data); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef CGLTF_WRITE_H_INCLUDED__ */ + +/* + * + * Stop now, if you are only interested in the API. + * Below, you find the implementation. + * + */ + +#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__) +/* This makes MSVC/CLion intellisense work. */ +#define CGLTF_WRITE_IMPLEMENTATION +#endif + +#ifdef CGLTF_WRITE_IMPLEMENTATION + +#include +#include +#include +#include +#include +#include + +#define CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM (1 << 0) +#define CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT (1 << 1) +#define CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS (1 << 2) +#define CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL (1 << 3) +#define CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION (1 << 4) +#define CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT (1 << 5) +#define CGLTF_EXTENSION_FLAG_MATERIALS_IOR (1 << 6) +#define CGLTF_EXTENSION_FLAG_MATERIALS_SPECULAR (1 << 7) +#define CGLTF_EXTENSION_FLAG_MATERIALS_TRANSMISSION (1 << 8) +#define CGLTF_EXTENSION_FLAG_MATERIALS_SHEEN (1 << 9) +#define CGLTF_EXTENSION_FLAG_MATERIALS_VARIANTS (1 << 10) +#define CGLTF_EXTENSION_FLAG_MATERIALS_VOLUME (1 << 11) +#define CGLTF_EXTENSION_FLAG_TEXTURE_BASISU (1 << 12) +#define CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH (1 << 13) +#define CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING (1 << 14) +#define CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE (1 << 15) +#define CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY (1 << 16) +#define CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION (1 << 17) +#define CGLTF_EXTENSION_FLAG_TEXTURE_WEBP (1 << 18) +#define CGLTF_EXTENSION_FLAG_MATERIALS_DIFFUSE_TRANSMISSION (1 << 19) + +typedef struct { + char* buffer; + cgltf_size buffer_size; + cgltf_size remaining; + char* cursor; + cgltf_size tmp; + cgltf_size chars_written; + const cgltf_data* data; + int depth; + const char* indent; + int needs_comma; + uint32_t extension_flags; + uint32_t required_extension_flags; +} cgltf_write_context; + +#define CGLTF_MIN(a, b) (a < b ? a : b) + +#ifdef FLT_DECIMAL_DIG + // FLT_DECIMAL_DIG is C11 + #define CGLTF_DECIMAL_DIG (FLT_DECIMAL_DIG) +#else + #define CGLTF_DECIMAL_DIG 9 +#endif + +#define CGLTF_SPRINTF(...) { \ + assert(context->cursor || (!context->cursor && context->remaining == 0)); \ + context->tmp = snprintf ( context->cursor, context->remaining, __VA_ARGS__ ); \ + context->chars_written += context->tmp; \ + if (context->cursor) { \ + context->cursor += context->tmp; \ + context->remaining -= context->tmp; \ + } } + +#define CGLTF_SNPRINTF(length, ...) { \ + assert(context->cursor || (!context->cursor && context->remaining == 0)); \ + context->tmp = snprintf ( context->cursor, CGLTF_MIN(length + 1, context->remaining), __VA_ARGS__ ); \ + context->chars_written += length; \ + if (context->cursor) { \ + context->cursor += length; \ + context->remaining -= length; \ + } } + +#define CGLTF_WRITE_IDXPROP(label, val, start) if (val) { \ + cgltf_write_indent(context); \ + CGLTF_SPRINTF("\"%s\": %d", label, (int) (val - start)); \ + context->needs_comma = 1; } + +#define CGLTF_WRITE_IDXARRPROP(label, dim, vals, start) if (vals) { \ + cgltf_write_indent(context); \ + CGLTF_SPRINTF("\"%s\": [", label); \ + for (int i = 0; i < (int)(dim); ++i) { \ + int idx = (int) (vals[i] - start); \ + if (i != 0) CGLTF_SPRINTF(","); \ + CGLTF_SPRINTF(" %d", idx); \ + } \ + CGLTF_SPRINTF(" ]"); \ + context->needs_comma = 1; } + +#define CGLTF_WRITE_TEXTURE_INFO(label, info) if (info.texture) { \ + cgltf_write_line(context, "\"" label "\": {"); \ + CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \ + cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \ + if (info.has_transform) { \ + context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \ + cgltf_write_texture_transform(context, &info.transform); \ + } \ + cgltf_write_line(context, "}"); } + +#define CGLTF_WRITE_NORMAL_TEXTURE_INFO(label, info) if (info.texture) { \ + cgltf_write_line(context, "\"" label "\": {"); \ + CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \ + cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \ + cgltf_write_floatprop(context, "scale", info.scale, 1.0f); \ + if (info.has_transform) { \ + context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \ + cgltf_write_texture_transform(context, &info.transform); \ + } \ + cgltf_write_line(context, "}"); } + +#define CGLTF_WRITE_OCCLUSION_TEXTURE_INFO(label, info) if (info.texture) { \ + cgltf_write_line(context, "\"" label "\": {"); \ + CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \ + cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \ + cgltf_write_floatprop(context, "strength", info.scale, 1.0f); \ + if (info.has_transform) { \ + context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \ + cgltf_write_texture_transform(context, &info.transform); \ + } \ + cgltf_write_line(context, "}"); } + +#ifndef CGLTF_CONSTS +#define GlbHeaderSize 12 +#define GlbChunkHeaderSize 8 +static const uint32_t GlbVersion = 2; +static const uint32_t GlbMagic = 0x46546C67; +static const uint32_t GlbMagicJsonChunk = 0x4E4F534A; +static const uint32_t GlbMagicBinChunk = 0x004E4942; +#define CGLTF_CONSTS +#endif + +static void cgltf_write_indent(cgltf_write_context* context) +{ + if (context->needs_comma) + { + CGLTF_SPRINTF(",\n"); + context->needs_comma = 0; + } + else + { + CGLTF_SPRINTF("\n"); + } + for (int i = 0; i < context->depth; ++i) + { + CGLTF_SPRINTF("%s", context->indent); + } +} + +static void cgltf_write_line(cgltf_write_context* context, const char* line) +{ + if (line[0] == ']' || line[0] == '}') + { + --context->depth; + context->needs_comma = 0; + } + cgltf_write_indent(context); + CGLTF_SPRINTF("%s", line); + cgltf_size last = (cgltf_size)(strlen(line) - 1); + if (line[0] == ']' || line[0] == '}') + { + context->needs_comma = 1; + } + if (line[last] == '[' || line[last] == '{') + { + ++context->depth; + context->needs_comma = 0; + } +} + +static void cgltf_write_strprop(cgltf_write_context* context, const char* label, const char* val) +{ + if (val) + { + cgltf_write_indent(context); + CGLTF_SPRINTF("\"%s\": \"%s\"", label, val); + context->needs_comma = 1; + } +} + +static void cgltf_write_extras(cgltf_write_context* context, const cgltf_extras* extras) +{ + if (extras->data) + { + cgltf_write_indent(context); + CGLTF_SPRINTF("\"extras\": %s", extras->data); + context->needs_comma = 1; + } + else + { + cgltf_size length = extras->end_offset - extras->start_offset; + if (length > 0 && context->data->json) + { + char* json_string = ((char*) context->data->json) + extras->start_offset; + cgltf_write_indent(context); + CGLTF_SPRINTF("%s", "\"extras\": "); + CGLTF_SNPRINTF(length, "%.*s", (int)(extras->end_offset - extras->start_offset), json_string); + context->needs_comma = 1; + } + } +} + +static void cgltf_write_stritem(cgltf_write_context* context, const char* item) +{ + cgltf_write_indent(context); + CGLTF_SPRINTF("\"%s\"", item); + context->needs_comma = 1; +} + +static void cgltf_write_intprop(cgltf_write_context* context, const char* label, int val, int def) +{ + if (val != def) + { + cgltf_write_indent(context); + CGLTF_SPRINTF("\"%s\": %d", label, val); + context->needs_comma = 1; + } +} + +static void cgltf_write_sizeprop(cgltf_write_context* context, const char* label, cgltf_size val, cgltf_size def) +{ + if (val != def) + { + cgltf_write_indent(context); + CGLTF_SPRINTF("\"%s\": %zu", label, val); + context->needs_comma = 1; + } +} + +static void cgltf_write_floatprop(cgltf_write_context* context, const char* label, float val, float def) +{ + if (val != def) + { + cgltf_write_indent(context); + CGLTF_SPRINTF("\"%s\": ", label); + CGLTF_SPRINTF("%.*g", CGLTF_DECIMAL_DIG, val); + context->needs_comma = 1; + + if (context->cursor) + { + char *decimal_comma = strchr(context->cursor - context->tmp, ','); + if (decimal_comma) + { + *decimal_comma = '.'; + } + } + } +} + +static void cgltf_write_boolprop_optional(cgltf_write_context* context, const char* label, bool val, bool def) +{ + if (val != def) + { + cgltf_write_indent(context); + CGLTF_SPRINTF("\"%s\": %s", label, val ? "true" : "false"); + context->needs_comma = 1; + } +} + +static void cgltf_write_floatarrayprop(cgltf_write_context* context, const char* label, const cgltf_float* vals, cgltf_size dim) +{ + cgltf_write_indent(context); + CGLTF_SPRINTF("\"%s\": [", label); + for (cgltf_size i = 0; i < dim; ++i) + { + if (i != 0) + { + CGLTF_SPRINTF(", %.*g", CGLTF_DECIMAL_DIG, vals[i]); + } + else + { + CGLTF_SPRINTF("%.*g", CGLTF_DECIMAL_DIG, vals[i]); + } + } + CGLTF_SPRINTF("]"); + context->needs_comma = 1; +} + +static bool cgltf_check_floatarray(const float* vals, int dim, float val) { + while (dim--) + { + if (vals[dim] != val) + { + return true; + } + } + return false; +} + +static int cgltf_int_from_component_type(cgltf_component_type ctype) +{ + switch (ctype) + { + case cgltf_component_type_r_8: return 5120; + case cgltf_component_type_r_8u: return 5121; + case cgltf_component_type_r_16: return 5122; + case cgltf_component_type_r_16u: return 5123; + case cgltf_component_type_r_32u: return 5125; + case cgltf_component_type_r_32f: return 5126; + default: return 0; + } +} + +static int cgltf_int_from_primitive_type(cgltf_primitive_type ctype) +{ + switch (ctype) + { + case cgltf_primitive_type_points: return 0; + case cgltf_primitive_type_lines: return 1; + case cgltf_primitive_type_line_loop: return 2; + case cgltf_primitive_type_line_strip: return 3; + case cgltf_primitive_type_triangles: return 4; + case cgltf_primitive_type_triangle_strip: return 5; + case cgltf_primitive_type_triangle_fan: return 6; + default: return -1; + } +} + +static const char* cgltf_str_from_alpha_mode(cgltf_alpha_mode alpha_mode) +{ + switch (alpha_mode) + { + case cgltf_alpha_mode_mask: return "MASK"; + case cgltf_alpha_mode_blend: return "BLEND"; + default: return NULL; + } +} + +static const char* cgltf_str_from_type(cgltf_type type) +{ + switch (type) + { + case cgltf_type_scalar: return "SCALAR"; + case cgltf_type_vec2: return "VEC2"; + case cgltf_type_vec3: return "VEC3"; + case cgltf_type_vec4: return "VEC4"; + case cgltf_type_mat2: return "MAT2"; + case cgltf_type_mat3: return "MAT3"; + case cgltf_type_mat4: return "MAT4"; + default: return NULL; + } +} + +static cgltf_size cgltf_dim_from_type(cgltf_type type) +{ + switch (type) + { + case cgltf_type_scalar: return 1; + case cgltf_type_vec2: return 2; + case cgltf_type_vec3: return 3; + case cgltf_type_vec4: return 4; + case cgltf_type_mat2: return 4; + case cgltf_type_mat3: return 9; + case cgltf_type_mat4: return 16; + default: return 0; + } +} + +static const char* cgltf_str_from_camera_type(cgltf_camera_type camera_type) +{ + switch (camera_type) + { + case cgltf_camera_type_perspective: return "perspective"; + case cgltf_camera_type_orthographic: return "orthographic"; + default: return NULL; + } +} + +static const char* cgltf_str_from_light_type(cgltf_light_type light_type) +{ + switch (light_type) + { + case cgltf_light_type_directional: return "directional"; + case cgltf_light_type_point: return "point"; + case cgltf_light_type_spot: return "spot"; + default: return NULL; + } +} + +static void cgltf_write_texture_transform(cgltf_write_context* context, const cgltf_texture_transform* transform) +{ + cgltf_write_line(context, "\"extensions\": {"); + cgltf_write_line(context, "\"KHR_texture_transform\": {"); + if (cgltf_check_floatarray(transform->offset, 2, 0.0f)) + { + cgltf_write_floatarrayprop(context, "offset", transform->offset, 2); + } + cgltf_write_floatprop(context, "rotation", transform->rotation, 0.0f); + if (cgltf_check_floatarray(transform->scale, 2, 1.0f)) + { + cgltf_write_floatarrayprop(context, "scale", transform->scale, 2); + } + if (transform->has_texcoord) + { + cgltf_write_intprop(context, "texCoord", transform->texcoord, -1); + } + cgltf_write_line(context, "}"); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_asset(cgltf_write_context* context, const cgltf_asset* asset) +{ + cgltf_write_line(context, "\"asset\": {"); + cgltf_write_strprop(context, "copyright", asset->copyright); + cgltf_write_strprop(context, "generator", asset->generator); + cgltf_write_strprop(context, "version", asset->version); + cgltf_write_strprop(context, "min_version", asset->min_version); + cgltf_write_extras(context, &asset->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_primitive(cgltf_write_context* context, const cgltf_primitive* prim) +{ + cgltf_write_intprop(context, "mode", cgltf_int_from_primitive_type(prim->type), 4); + CGLTF_WRITE_IDXPROP("indices", prim->indices, context->data->accessors); + CGLTF_WRITE_IDXPROP("material", prim->material, context->data->materials); + cgltf_write_line(context, "\"attributes\": {"); + for (cgltf_size i = 0; i < prim->attributes_count; ++i) + { + const cgltf_attribute* attr = prim->attributes + i; + CGLTF_WRITE_IDXPROP(attr->name, attr->data, context->data->accessors); + } + cgltf_write_line(context, "}"); + + if (prim->targets_count) + { + cgltf_write_line(context, "\"targets\": ["); + for (cgltf_size i = 0; i < prim->targets_count; ++i) + { + cgltf_write_line(context, "{"); + for (cgltf_size j = 0; j < prim->targets[i].attributes_count; ++j) + { + const cgltf_attribute* attr = prim->targets[i].attributes + j; + CGLTF_WRITE_IDXPROP(attr->name, attr->data, context->data->accessors); + } + cgltf_write_line(context, "}"); + } + cgltf_write_line(context, "]"); + } + cgltf_write_extras(context, &prim->extras); + + if (prim->has_draco_mesh_compression || prim->mappings_count > 0) + { + cgltf_write_line(context, "\"extensions\": {"); + + if (prim->has_draco_mesh_compression) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION; + if (prim->attributes_count == 0 || prim->indices == 0) + { + context->required_extension_flags |= CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION; + } + + cgltf_write_line(context, "\"KHR_draco_mesh_compression\": {"); + CGLTF_WRITE_IDXPROP("bufferView", prim->draco_mesh_compression.buffer_view, context->data->buffer_views); + cgltf_write_line(context, "\"attributes\": {"); + for (cgltf_size i = 0; i < prim->draco_mesh_compression.attributes_count; ++i) + { + const cgltf_attribute* attr = prim->draco_mesh_compression.attributes + i; + CGLTF_WRITE_IDXPROP(attr->name, attr->data, context->data->accessors); + } + cgltf_write_line(context, "}"); + cgltf_write_line(context, "}"); + } + + if (prim->mappings_count > 0) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_VARIANTS; + cgltf_write_line(context, "\"KHR_materials_variants\": {"); + cgltf_write_line(context, "\"mappings\": ["); + for (cgltf_size i = 0; i < prim->mappings_count; ++i) + { + const cgltf_material_mapping* map = prim->mappings + i; + cgltf_write_line(context, "{"); + CGLTF_WRITE_IDXPROP("material", map->material, context->data->materials); + + cgltf_write_indent(context); + CGLTF_SPRINTF("\"variants\": [%d]", (int)map->variant); + context->needs_comma = 1; + + cgltf_write_extras(context, &map->extras); + cgltf_write_line(context, "}"); + } + cgltf_write_line(context, "]"); + cgltf_write_line(context, "}"); + } + + cgltf_write_line(context, "}"); + } +} + +static void cgltf_write_mesh(cgltf_write_context* context, const cgltf_mesh* mesh) +{ + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "name", mesh->name); + + cgltf_write_line(context, "\"primitives\": ["); + for (cgltf_size i = 0; i < mesh->primitives_count; ++i) + { + cgltf_write_line(context, "{"); + cgltf_write_primitive(context, mesh->primitives + i); + cgltf_write_line(context, "}"); + } + cgltf_write_line(context, "]"); + + if (mesh->weights_count > 0) + { + cgltf_write_floatarrayprop(context, "weights", mesh->weights, mesh->weights_count); + } + + cgltf_write_extras(context, &mesh->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_buffer_view(cgltf_write_context* context, const cgltf_buffer_view* view) +{ + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "name", view->name); + CGLTF_WRITE_IDXPROP("buffer", view->buffer, context->data->buffers); + cgltf_write_sizeprop(context, "byteLength", view->size, (cgltf_size)-1); + cgltf_write_sizeprop(context, "byteOffset", view->offset, 0); + cgltf_write_sizeprop(context, "byteStride", view->stride, 0); + // NOTE: We skip writing "target" because the spec says its usage can be inferred. + cgltf_write_extras(context, &view->extras); + cgltf_write_line(context, "}"); +} + + +static void cgltf_write_buffer(cgltf_write_context* context, const cgltf_buffer* buffer) +{ + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "name", buffer->name); + cgltf_write_strprop(context, "uri", buffer->uri); + cgltf_write_sizeprop(context, "byteLength", buffer->size, (cgltf_size)-1); + cgltf_write_extras(context, &buffer->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_material(cgltf_write_context* context, const cgltf_material* material) +{ + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "name", material->name); + if (material->alpha_mode == cgltf_alpha_mode_mask) + { + cgltf_write_floatprop(context, "alphaCutoff", material->alpha_cutoff, 0.5f); + } + cgltf_write_boolprop_optional(context, "doubleSided", (bool)material->double_sided, false); + // cgltf_write_boolprop_optional(context, "unlit", material->unlit, false); + + if (material->unlit) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT; + } + + if (material->has_pbr_specular_glossiness) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS; + } + + if (material->has_clearcoat) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT; + } + + if (material->has_transmission) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_TRANSMISSION; + } + + if (material->has_volume) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_VOLUME; + } + + if (material->has_ior) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_IOR; + } + + if (material->has_specular) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_SPECULAR; + } + + if (material->has_sheen) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_SHEEN; + } + + if (material->has_emissive_strength) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH; + } + + if (material->has_iridescence) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE; + } + + if (material->has_diffuse_transmission) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_DIFFUSE_TRANSMISSION; + } + + if (material->has_anisotropy) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY; + } + + if (material->has_dispersion) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION; + } + + if (material->has_pbr_metallic_roughness) + { + const cgltf_pbr_metallic_roughness* params = &material->pbr_metallic_roughness; + cgltf_write_line(context, "\"pbrMetallicRoughness\": {"); + CGLTF_WRITE_TEXTURE_INFO("baseColorTexture", params->base_color_texture); + CGLTF_WRITE_TEXTURE_INFO("metallicRoughnessTexture", params->metallic_roughness_texture); + cgltf_write_floatprop(context, "metallicFactor", params->metallic_factor, 1.0f); + cgltf_write_floatprop(context, "roughnessFactor", params->roughness_factor, 1.0f); + if (cgltf_check_floatarray(params->base_color_factor, 4, 1.0f)) + { + cgltf_write_floatarrayprop(context, "baseColorFactor", params->base_color_factor, 4); + } + cgltf_write_line(context, "}"); + } + + if (material->unlit || material->has_pbr_specular_glossiness || material->has_clearcoat || material->has_ior || material->has_specular || material->has_transmission || material->has_sheen || material->has_volume || material->has_emissive_strength || material->has_iridescence || material->has_anisotropy || material->has_dispersion || material->has_diffuse_transmission) + { + cgltf_write_line(context, "\"extensions\": {"); + if (material->has_clearcoat) + { + const cgltf_clearcoat* params = &material->clearcoat; + cgltf_write_line(context, "\"KHR_materials_clearcoat\": {"); + CGLTF_WRITE_TEXTURE_INFO("clearcoatTexture", params->clearcoat_texture); + CGLTF_WRITE_TEXTURE_INFO("clearcoatRoughnessTexture", params->clearcoat_roughness_texture); + CGLTF_WRITE_NORMAL_TEXTURE_INFO("clearcoatNormalTexture", params->clearcoat_normal_texture); + cgltf_write_floatprop(context, "clearcoatFactor", params->clearcoat_factor, 0.0f); + cgltf_write_floatprop(context, "clearcoatRoughnessFactor", params->clearcoat_roughness_factor, 0.0f); + cgltf_write_line(context, "}"); + } + if (material->has_ior) + { + const cgltf_ior* params = &material->ior; + cgltf_write_line(context, "\"KHR_materials_ior\": {"); + cgltf_write_floatprop(context, "ior", params->ior, 1.5f); + cgltf_write_line(context, "}"); + } + if (material->has_specular) + { + const cgltf_specular* params = &material->specular; + cgltf_write_line(context, "\"KHR_materials_specular\": {"); + CGLTF_WRITE_TEXTURE_INFO("specularTexture", params->specular_texture); + CGLTF_WRITE_TEXTURE_INFO("specularColorTexture", params->specular_color_texture); + cgltf_write_floatprop(context, "specularFactor", params->specular_factor, 1.0f); + if (cgltf_check_floatarray(params->specular_color_factor, 3, 1.0f)) + { + cgltf_write_floatarrayprop(context, "specularColorFactor", params->specular_color_factor, 3); + } + cgltf_write_line(context, "}"); + } + if (material->has_transmission) + { + const cgltf_transmission* params = &material->transmission; + cgltf_write_line(context, "\"KHR_materials_transmission\": {"); + CGLTF_WRITE_TEXTURE_INFO("transmissionTexture", params->transmission_texture); + cgltf_write_floatprop(context, "transmissionFactor", params->transmission_factor, 0.0f); + cgltf_write_line(context, "}"); + } + if (material->has_volume) + { + const cgltf_volume* params = &material->volume; + cgltf_write_line(context, "\"KHR_materials_volume\": {"); + CGLTF_WRITE_TEXTURE_INFO("thicknessTexture", params->thickness_texture); + cgltf_write_floatprop(context, "thicknessFactor", params->thickness_factor, 0.0f); + if (cgltf_check_floatarray(params->attenuation_color, 3, 1.0f)) + { + cgltf_write_floatarrayprop(context, "attenuationColor", params->attenuation_color, 3); + } + if (params->attenuation_distance < FLT_MAX) + { + cgltf_write_floatprop(context, "attenuationDistance", params->attenuation_distance, FLT_MAX); + } + cgltf_write_line(context, "}"); + } + if (material->has_sheen) + { + const cgltf_sheen* params = &material->sheen; + cgltf_write_line(context, "\"KHR_materials_sheen\": {"); + CGLTF_WRITE_TEXTURE_INFO("sheenColorTexture", params->sheen_color_texture); + CGLTF_WRITE_TEXTURE_INFO("sheenRoughnessTexture", params->sheen_roughness_texture); + if (cgltf_check_floatarray(params->sheen_color_factor, 3, 0.0f)) + { + cgltf_write_floatarrayprop(context, "sheenColorFactor", params->sheen_color_factor, 3); + } + cgltf_write_floatprop(context, "sheenRoughnessFactor", params->sheen_roughness_factor, 0.0f); + cgltf_write_line(context, "}"); + } + if (material->has_pbr_specular_glossiness) + { + const cgltf_pbr_specular_glossiness* params = &material->pbr_specular_glossiness; + cgltf_write_line(context, "\"KHR_materials_pbrSpecularGlossiness\": {"); + CGLTF_WRITE_TEXTURE_INFO("diffuseTexture", params->diffuse_texture); + CGLTF_WRITE_TEXTURE_INFO("specularGlossinessTexture", params->specular_glossiness_texture); + if (cgltf_check_floatarray(params->diffuse_factor, 4, 1.0f)) + { + cgltf_write_floatarrayprop(context, "diffuseFactor", params->diffuse_factor, 4); + } + if (cgltf_check_floatarray(params->specular_factor, 3, 1.0f)) + { + cgltf_write_floatarrayprop(context, "specularFactor", params->specular_factor, 3); + } + cgltf_write_floatprop(context, "glossinessFactor", params->glossiness_factor, 1.0f); + cgltf_write_line(context, "}"); + } + if (material->unlit) + { + cgltf_write_line(context, "\"KHR_materials_unlit\": {}"); + } + if (material->has_emissive_strength) + { + cgltf_write_line(context, "\"KHR_materials_emissive_strength\": {"); + const cgltf_emissive_strength* params = &material->emissive_strength; + cgltf_write_floatprop(context, "emissiveStrength", params->emissive_strength, 1.f); + cgltf_write_line(context, "}"); + } + if (material->has_iridescence) + { + cgltf_write_line(context, "\"KHR_materials_iridescence\": {"); + const cgltf_iridescence* params = &material->iridescence; + cgltf_write_floatprop(context, "iridescenceFactor", params->iridescence_factor, 0.f); + CGLTF_WRITE_TEXTURE_INFO("iridescenceTexture", params->iridescence_texture); + cgltf_write_floatprop(context, "iridescenceIor", params->iridescence_ior, 1.3f); + cgltf_write_floatprop(context, "iridescenceThicknessMinimum", params->iridescence_thickness_min, 100.f); + cgltf_write_floatprop(context, "iridescenceThicknessMaximum", params->iridescence_thickness_max, 400.f); + CGLTF_WRITE_TEXTURE_INFO("iridescenceThicknessTexture", params->iridescence_thickness_texture); + cgltf_write_line(context, "}"); + } + if (material->has_diffuse_transmission) + { + const cgltf_diffuse_transmission* params = &material->diffuse_transmission; + cgltf_write_line(context, "\"KHR_materials_diffuse_transmission\": {"); + CGLTF_WRITE_TEXTURE_INFO("diffuseTransmissionTexture", params->diffuse_transmission_texture); + cgltf_write_floatprop(context, "diffuseTransmissionFactor", params->diffuse_transmission_factor, 0.f); + if (cgltf_check_floatarray(params->diffuse_transmission_color_factor, 3, 1.f)) + { + cgltf_write_floatarrayprop(context, "diffuseTransmissionColorFactor", params->diffuse_transmission_color_factor, 3); + } + CGLTF_WRITE_TEXTURE_INFO("diffuseTransmissionColorTexture", params->diffuse_transmission_color_texture); + cgltf_write_line(context, "}"); + } + if (material->has_anisotropy) + { + cgltf_write_line(context, "\"KHR_materials_anisotropy\": {"); + const cgltf_anisotropy* params = &material->anisotropy; + cgltf_write_floatprop(context, "anisotropyStrength", params->anisotropy_strength, 0.f); + cgltf_write_floatprop(context, "anisotropyRotation", params->anisotropy_rotation, 0.f); + CGLTF_WRITE_TEXTURE_INFO("anisotropyTexture", params->anisotropy_texture); + cgltf_write_line(context, "}"); + } + if (material->has_dispersion) + { + cgltf_write_line(context, "\"KHR_materials_dispersion\": {"); + const cgltf_dispersion* params = &material->dispersion; + cgltf_write_floatprop(context, "dispersion", params->dispersion, 0.f); + cgltf_write_line(context, "}"); + } + cgltf_write_line(context, "}"); + } + + CGLTF_WRITE_NORMAL_TEXTURE_INFO("normalTexture", material->normal_texture); + CGLTF_WRITE_OCCLUSION_TEXTURE_INFO("occlusionTexture", material->occlusion_texture); + CGLTF_WRITE_TEXTURE_INFO("emissiveTexture", material->emissive_texture); + if (cgltf_check_floatarray(material->emissive_factor, 3, 0.0f)) + { + cgltf_write_floatarrayprop(context, "emissiveFactor", material->emissive_factor, 3); + } + cgltf_write_strprop(context, "alphaMode", cgltf_str_from_alpha_mode(material->alpha_mode)); + cgltf_write_extras(context, &material->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_image(cgltf_write_context* context, const cgltf_image* image) +{ + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "name", image->name); + cgltf_write_strprop(context, "uri", image->uri); + CGLTF_WRITE_IDXPROP("bufferView", image->buffer_view, context->data->buffer_views); + cgltf_write_strprop(context, "mimeType", image->mime_type); + cgltf_write_extras(context, &image->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_texture(cgltf_write_context* context, const cgltf_texture* texture) +{ + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "name", texture->name); + CGLTF_WRITE_IDXPROP("source", texture->image, context->data->images); + CGLTF_WRITE_IDXPROP("sampler", texture->sampler, context->data->samplers); + + if (texture->has_basisu || texture->has_webp) + { + cgltf_write_line(context, "\"extensions\": {"); + if (texture->has_basisu) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_BASISU; + cgltf_write_line(context, "\"KHR_texture_basisu\": {"); + CGLTF_WRITE_IDXPROP("source", texture->basisu_image, context->data->images); + cgltf_write_line(context, "}"); + } + if (texture->has_webp) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_WEBP; + cgltf_write_line(context, "\"EXT_texture_webp\": {"); + CGLTF_WRITE_IDXPROP("source", texture->webp_image, context->data->images); + cgltf_write_line(context, "}"); + } + cgltf_write_line(context, "}"); + } + cgltf_write_extras(context, &texture->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_skin(cgltf_write_context* context, const cgltf_skin* skin) +{ + cgltf_write_line(context, "{"); + CGLTF_WRITE_IDXPROP("skeleton", skin->skeleton, context->data->nodes); + CGLTF_WRITE_IDXPROP("inverseBindMatrices", skin->inverse_bind_matrices, context->data->accessors); + CGLTF_WRITE_IDXARRPROP("joints", skin->joints_count, skin->joints, context->data->nodes); + cgltf_write_strprop(context, "name", skin->name); + cgltf_write_extras(context, &skin->extras); + cgltf_write_line(context, "}"); +} + +static const char* cgltf_write_str_path_type(cgltf_animation_path_type path_type) +{ + switch (path_type) + { + case cgltf_animation_path_type_translation: + return "translation"; + case cgltf_animation_path_type_rotation: + return "rotation"; + case cgltf_animation_path_type_scale: + return "scale"; + case cgltf_animation_path_type_weights: + return "weights"; + default: + break; + } + return "invalid"; +} + +static const char* cgltf_write_str_interpolation_type(cgltf_interpolation_type interpolation_type) +{ + switch (interpolation_type) + { + case cgltf_interpolation_type_linear: + return "LINEAR"; + case cgltf_interpolation_type_step: + return "STEP"; + case cgltf_interpolation_type_cubic_spline: + return "CUBICSPLINE"; + default: + break; + } + return "invalid"; +} + +static void cgltf_write_path_type(cgltf_write_context* context, const char *label, cgltf_animation_path_type path_type) +{ + cgltf_write_strprop(context, label, cgltf_write_str_path_type(path_type)); +} + +static void cgltf_write_interpolation_type(cgltf_write_context* context, const char *label, cgltf_interpolation_type interpolation_type) +{ + cgltf_write_strprop(context, label, cgltf_write_str_interpolation_type(interpolation_type)); +} + +static void cgltf_write_animation_sampler(cgltf_write_context* context, const cgltf_animation_sampler* animation_sampler) +{ + cgltf_write_line(context, "{"); + cgltf_write_interpolation_type(context, "interpolation", animation_sampler->interpolation); + CGLTF_WRITE_IDXPROP("input", animation_sampler->input, context->data->accessors); + CGLTF_WRITE_IDXPROP("output", animation_sampler->output, context->data->accessors); + cgltf_write_extras(context, &animation_sampler->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_animation_channel(cgltf_write_context* context, const cgltf_animation* animation, const cgltf_animation_channel* animation_channel) +{ + cgltf_write_line(context, "{"); + CGLTF_WRITE_IDXPROP("sampler", animation_channel->sampler, animation->samplers); + cgltf_write_line(context, "\"target\": {"); + CGLTF_WRITE_IDXPROP("node", animation_channel->target_node, context->data->nodes); + cgltf_write_path_type(context, "path", animation_channel->target_path); + cgltf_write_line(context, "}"); + cgltf_write_extras(context, &animation_channel->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_animation(cgltf_write_context* context, const cgltf_animation* animation) +{ + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "name", animation->name); + + if (animation->samplers_count > 0) + { + cgltf_write_line(context, "\"samplers\": ["); + for (cgltf_size i = 0; i < animation->samplers_count; ++i) + { + cgltf_write_animation_sampler(context, animation->samplers + i); + } + cgltf_write_line(context, "]"); + } + if (animation->channels_count > 0) + { + cgltf_write_line(context, "\"channels\": ["); + for (cgltf_size i = 0; i < animation->channels_count; ++i) + { + cgltf_write_animation_channel(context, animation, animation->channels + i); + } + cgltf_write_line(context, "]"); + } + cgltf_write_extras(context, &animation->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_sampler(cgltf_write_context* context, const cgltf_sampler* sampler) +{ + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "name", sampler->name); + cgltf_write_intprop(context, "magFilter", sampler->mag_filter, 0); + cgltf_write_intprop(context, "minFilter", sampler->min_filter, 0); + cgltf_write_intprop(context, "wrapS", sampler->wrap_s, 10497); + cgltf_write_intprop(context, "wrapT", sampler->wrap_t, 10497); + cgltf_write_extras(context, &sampler->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_node(cgltf_write_context* context, const cgltf_node* node) +{ + cgltf_write_line(context, "{"); + CGLTF_WRITE_IDXARRPROP("children", node->children_count, node->children, context->data->nodes); + CGLTF_WRITE_IDXPROP("mesh", node->mesh, context->data->meshes); + cgltf_write_strprop(context, "name", node->name); + if (node->has_matrix) + { + cgltf_write_floatarrayprop(context, "matrix", node->matrix, 16); + } + if (node->has_translation) + { + cgltf_write_floatarrayprop(context, "translation", node->translation, 3); + } + if (node->has_rotation) + { + cgltf_write_floatarrayprop(context, "rotation", node->rotation, 4); + } + if (node->has_scale) + { + cgltf_write_floatarrayprop(context, "scale", node->scale, 3); + } + if (node->skin) + { + CGLTF_WRITE_IDXPROP("skin", node->skin, context->data->skins); + } + + bool has_extension = node->light || (node->has_mesh_gpu_instancing && node->mesh_gpu_instancing.attributes_count > 0); + if(has_extension) + cgltf_write_line(context, "\"extensions\": {"); + + if (node->light) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL; + cgltf_write_line(context, "\"KHR_lights_punctual\": {"); + CGLTF_WRITE_IDXPROP("light", node->light, context->data->lights); + cgltf_write_line(context, "}"); + } + + if (node->has_mesh_gpu_instancing && node->mesh_gpu_instancing.attributes_count > 0) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING; + context->required_extension_flags |= CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING; + + cgltf_write_line(context, "\"EXT_mesh_gpu_instancing\": {"); + { + cgltf_write_line(context, "\"attributes\": {"); + { + for (cgltf_size i = 0; i < node->mesh_gpu_instancing.attributes_count; ++i) + { + const cgltf_attribute* attr = node->mesh_gpu_instancing.attributes + i; + CGLTF_WRITE_IDXPROP(attr->name, attr->data, context->data->accessors); + } + } + cgltf_write_line(context, "}"); + } + cgltf_write_line(context, "}"); + } + + if (has_extension) + cgltf_write_line(context, "}"); + + if (node->weights_count > 0) + { + cgltf_write_floatarrayprop(context, "weights", node->weights, node->weights_count); + } + + if (node->camera) + { + CGLTF_WRITE_IDXPROP("camera", node->camera, context->data->cameras); + } + + cgltf_write_extras(context, &node->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_scene(cgltf_write_context* context, const cgltf_scene* scene) +{ + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "name", scene->name); + CGLTF_WRITE_IDXARRPROP("nodes", scene->nodes_count, scene->nodes, context->data->nodes); + cgltf_write_extras(context, &scene->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_accessor(cgltf_write_context* context, const cgltf_accessor* accessor) +{ + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "name", accessor->name); + CGLTF_WRITE_IDXPROP("bufferView", accessor->buffer_view, context->data->buffer_views); + cgltf_write_intprop(context, "componentType", cgltf_int_from_component_type(accessor->component_type), 0); + cgltf_write_strprop(context, "type", cgltf_str_from_type(accessor->type)); + cgltf_size dim = cgltf_dim_from_type(accessor->type); + cgltf_write_boolprop_optional(context, "normalized", (bool)accessor->normalized, false); + cgltf_write_sizeprop(context, "byteOffset", (int)accessor->offset, 0); + cgltf_write_intprop(context, "count", (int)accessor->count, -1); + if (accessor->has_min) + { + cgltf_write_floatarrayprop(context, "min", accessor->min, dim); + } + if (accessor->has_max) + { + cgltf_write_floatarrayprop(context, "max", accessor->max, dim); + } + if (accessor->is_sparse) + { + cgltf_write_line(context, "\"sparse\": {"); + cgltf_write_intprop(context, "count", (int)accessor->sparse.count, 0); + cgltf_write_line(context, "\"indices\": {"); + cgltf_write_sizeprop(context, "byteOffset", (int)accessor->sparse.indices_byte_offset, 0); + CGLTF_WRITE_IDXPROP("bufferView", accessor->sparse.indices_buffer_view, context->data->buffer_views); + cgltf_write_intprop(context, "componentType", cgltf_int_from_component_type(accessor->sparse.indices_component_type), 0); + cgltf_write_line(context, "}"); + cgltf_write_line(context, "\"values\": {"); + cgltf_write_sizeprop(context, "byteOffset", (int)accessor->sparse.values_byte_offset, 0); + CGLTF_WRITE_IDXPROP("bufferView", accessor->sparse.values_buffer_view, context->data->buffer_views); + cgltf_write_line(context, "}"); + cgltf_write_line(context, "}"); + } + cgltf_write_extras(context, &accessor->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_camera(cgltf_write_context* context, const cgltf_camera* camera) +{ + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "type", cgltf_str_from_camera_type(camera->type)); + if (camera->name) + { + cgltf_write_strprop(context, "name", camera->name); + } + + if (camera->type == cgltf_camera_type_orthographic) + { + cgltf_write_line(context, "\"orthographic\": {"); + cgltf_write_floatprop(context, "xmag", camera->data.orthographic.xmag, -1.0f); + cgltf_write_floatprop(context, "ymag", camera->data.orthographic.ymag, -1.0f); + cgltf_write_floatprop(context, "zfar", camera->data.orthographic.zfar, -1.0f); + cgltf_write_floatprop(context, "znear", camera->data.orthographic.znear, -1.0f); + cgltf_write_extras(context, &camera->data.orthographic.extras); + cgltf_write_line(context, "}"); + } + else if (camera->type == cgltf_camera_type_perspective) + { + cgltf_write_line(context, "\"perspective\": {"); + + if (camera->data.perspective.has_aspect_ratio) { + cgltf_write_floatprop(context, "aspectRatio", camera->data.perspective.aspect_ratio, -1.0f); + } + + cgltf_write_floatprop(context, "yfov", camera->data.perspective.yfov, -1.0f); + + if (camera->data.perspective.has_zfar) { + cgltf_write_floatprop(context, "zfar", camera->data.perspective.zfar, -1.0f); + } + + cgltf_write_floatprop(context, "znear", camera->data.perspective.znear, -1.0f); + cgltf_write_extras(context, &camera->data.perspective.extras); + cgltf_write_line(context, "}"); + } + cgltf_write_extras(context, &camera->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_light(cgltf_write_context* context, const cgltf_light* light) +{ + context->extension_flags |= CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL; + + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "type", cgltf_str_from_light_type(light->type)); + if (light->name) + { + cgltf_write_strprop(context, "name", light->name); + } + if (cgltf_check_floatarray(light->color, 3, 1.0f)) + { + cgltf_write_floatarrayprop(context, "color", light->color, 3); + } + cgltf_write_floatprop(context, "intensity", light->intensity, 1.0f); + cgltf_write_floatprop(context, "range", light->range, 0.0f); + + if (light->type == cgltf_light_type_spot) + { + cgltf_write_line(context, "\"spot\": {"); + cgltf_write_floatprop(context, "innerConeAngle", light->spot_inner_cone_angle, 0.0f); + cgltf_write_floatprop(context, "outerConeAngle", light->spot_outer_cone_angle, 3.14159265358979323846f/4.0f); + cgltf_write_line(context, "}"); + } + cgltf_write_extras( context, &light->extras ); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_variant(cgltf_write_context* context, const cgltf_material_variant* variant) +{ + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_VARIANTS; + + cgltf_write_line(context, "{"); + cgltf_write_strprop(context, "name", variant->name); + cgltf_write_extras(context, &variant->extras); + cgltf_write_line(context, "}"); +} + +static void cgltf_write_glb(FILE* file, const void* json_buf, const cgltf_size json_size, const void* bin_buf, const cgltf_size bin_size) +{ + char header[GlbHeaderSize]; + char chunk_header[GlbChunkHeaderSize]; + char json_pad[3] = { 0x20, 0x20, 0x20 }; + char bin_pad[3] = { 0, 0, 0 }; + + cgltf_size json_padsize = (json_size % 4 != 0) ? 4 - json_size % 4 : 0; + cgltf_size bin_padsize = (bin_size % 4 != 0) ? 4 - bin_size % 4 : 0; + cgltf_size total_size = GlbHeaderSize + GlbChunkHeaderSize + json_size + json_padsize; + if (bin_buf != NULL && bin_size > 0) { + total_size += GlbChunkHeaderSize + bin_size + bin_padsize; + } + + // Write a GLB header + memcpy(header, &GlbMagic, 4); + memcpy(header + 4, &GlbVersion, 4); + memcpy(header + 8, &total_size, 4); + fwrite(header, 1, GlbHeaderSize, file); + + // Write a JSON chunk (header & data) + uint32_t json_chunk_size = (uint32_t)(json_size + json_padsize); + memcpy(chunk_header, &json_chunk_size, 4); + memcpy(chunk_header + 4, &GlbMagicJsonChunk, 4); + fwrite(chunk_header, 1, GlbChunkHeaderSize, file); + + fwrite(json_buf, 1, json_size, file); + fwrite(json_pad, 1, json_padsize, file); + + if (bin_buf != NULL && bin_size > 0) { + // Write a binary chunk (header & data) + uint32_t bin_chunk_size = (uint32_t)(bin_size + bin_padsize); + memcpy(chunk_header, &bin_chunk_size, 4); + memcpy(chunk_header + 4, &GlbMagicBinChunk, 4); + fwrite(chunk_header, 1, GlbChunkHeaderSize, file); + + fwrite(bin_buf, 1, bin_size, file); + fwrite(bin_pad, 1, bin_padsize, file); + } +} + +cgltf_result cgltf_write_file(const cgltf_options* options, const char* path, const cgltf_data* data) +{ + cgltf_size expected = cgltf_write(options, NULL, 0, data); + char* buffer = (char*) malloc(expected); + cgltf_size actual = cgltf_write(options, buffer, expected, data); + if (expected != actual) { + fprintf(stderr, "Error: expected %zu bytes but wrote %zu bytes.\n", expected, actual); + } + FILE* file = fopen(path, "wb"); + if (!file) + { + return cgltf_result_file_not_found; + } + // Note that cgltf_write() includes a null terminator, which we omit from the file content. + if (options->type == cgltf_file_type_glb) { + cgltf_write_glb(file, buffer, actual - 1, data->bin, data->bin_size); + } else { + // Write a plain JSON file. + fwrite(buffer, actual - 1, 1, file); + } + fclose(file); + free(buffer); + return cgltf_result_success; +} + +static void cgltf_write_extensions(cgltf_write_context* context, uint32_t extension_flags) +{ + if (extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM) { + cgltf_write_stritem(context, "KHR_texture_transform"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT) { + cgltf_write_stritem(context, "KHR_materials_unlit"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS) { + cgltf_write_stritem(context, "KHR_materials_pbrSpecularGlossiness"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL) { + cgltf_write_stritem(context, "KHR_lights_punctual"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION) { + cgltf_write_stritem(context, "KHR_draco_mesh_compression"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT) { + cgltf_write_stritem(context, "KHR_materials_clearcoat"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_IOR) { + cgltf_write_stritem(context, "KHR_materials_ior"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_SPECULAR) { + cgltf_write_stritem(context, "KHR_materials_specular"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_TRANSMISSION) { + cgltf_write_stritem(context, "KHR_materials_transmission"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_SHEEN) { + cgltf_write_stritem(context, "KHR_materials_sheen"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_VARIANTS) { + cgltf_write_stritem(context, "KHR_materials_variants"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_VOLUME) { + cgltf_write_stritem(context, "KHR_materials_volume"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_BASISU) { + cgltf_write_stritem(context, "KHR_texture_basisu"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_WEBP) { + cgltf_write_stritem(context, "EXT_texture_webp"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH) { + cgltf_write_stritem(context, "KHR_materials_emissive_strength"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE) { + cgltf_write_stritem(context, "KHR_materials_iridescence"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_DIFFUSE_TRANSMISSION) { + cgltf_write_stritem(context, "KHR_materials_diffuse_transmission"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY) { + cgltf_write_stritem(context, "KHR_materials_anisotropy"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING) { + cgltf_write_stritem(context, "EXT_mesh_gpu_instancing"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION) { + cgltf_write_stritem(context, "KHR_materials_dispersion"); + } +} + +cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size size, const cgltf_data* data) +{ + (void)options; + cgltf_write_context ctx; + ctx.buffer = buffer; + ctx.buffer_size = size; + ctx.remaining = size; + ctx.cursor = buffer; + ctx.chars_written = 0; + ctx.data = data; + ctx.depth = 1; + ctx.indent = " "; + ctx.needs_comma = 0; + ctx.extension_flags = 0; + ctx.required_extension_flags = 0; + + cgltf_write_context* context = &ctx; + + CGLTF_SPRINTF("{"); + + if (data->accessors_count > 0) + { + cgltf_write_line(context, "\"accessors\": ["); + for (cgltf_size i = 0; i < data->accessors_count; ++i) + { + cgltf_write_accessor(context, data->accessors + i); + } + cgltf_write_line(context, "]"); + } + + cgltf_write_asset(context, &data->asset); + + if (data->buffer_views_count > 0) + { + cgltf_write_line(context, "\"bufferViews\": ["); + for (cgltf_size i = 0; i < data->buffer_views_count; ++i) + { + cgltf_write_buffer_view(context, data->buffer_views + i); + } + cgltf_write_line(context, "]"); + } + + if (data->buffers_count > 0) + { + cgltf_write_line(context, "\"buffers\": ["); + for (cgltf_size i = 0; i < data->buffers_count; ++i) + { + cgltf_write_buffer(context, data->buffers + i); + } + cgltf_write_line(context, "]"); + } + + if (data->images_count > 0) + { + cgltf_write_line(context, "\"images\": ["); + for (cgltf_size i = 0; i < data->images_count; ++i) + { + cgltf_write_image(context, data->images + i); + } + cgltf_write_line(context, "]"); + } + + if (data->meshes_count > 0) + { + cgltf_write_line(context, "\"meshes\": ["); + for (cgltf_size i = 0; i < data->meshes_count; ++i) + { + cgltf_write_mesh(context, data->meshes + i); + } + cgltf_write_line(context, "]"); + } + + if (data->materials_count > 0) + { + cgltf_write_line(context, "\"materials\": ["); + for (cgltf_size i = 0; i < data->materials_count; ++i) + { + cgltf_write_material(context, data->materials + i); + } + cgltf_write_line(context, "]"); + } + + if (data->nodes_count > 0) + { + cgltf_write_line(context, "\"nodes\": ["); + for (cgltf_size i = 0; i < data->nodes_count; ++i) + { + cgltf_write_node(context, data->nodes + i); + } + cgltf_write_line(context, "]"); + } + + if (data->samplers_count > 0) + { + cgltf_write_line(context, "\"samplers\": ["); + for (cgltf_size i = 0; i < data->samplers_count; ++i) + { + cgltf_write_sampler(context, data->samplers + i); + } + cgltf_write_line(context, "]"); + } + + CGLTF_WRITE_IDXPROP("scene", data->scene, data->scenes); + + if (data->scenes_count > 0) + { + cgltf_write_line(context, "\"scenes\": ["); + for (cgltf_size i = 0; i < data->scenes_count; ++i) + { + cgltf_write_scene(context, data->scenes + i); + } + cgltf_write_line(context, "]"); + } + + if (data->textures_count > 0) + { + cgltf_write_line(context, "\"textures\": ["); + for (cgltf_size i = 0; i < data->textures_count; ++i) + { + cgltf_write_texture(context, data->textures + i); + } + cgltf_write_line(context, "]"); + } + + if (data->skins_count > 0) + { + cgltf_write_line(context, "\"skins\": ["); + for (cgltf_size i = 0; i < data->skins_count; ++i) + { + cgltf_write_skin(context, data->skins + i); + } + cgltf_write_line(context, "]"); + } + + if (data->animations_count > 0) + { + cgltf_write_line(context, "\"animations\": ["); + for (cgltf_size i = 0; i < data->animations_count; ++i) + { + cgltf_write_animation(context, data->animations + i); + } + cgltf_write_line(context, "]"); + } + + if (data->cameras_count > 0) + { + cgltf_write_line(context, "\"cameras\": ["); + for (cgltf_size i = 0; i < data->cameras_count; ++i) + { + cgltf_write_camera(context, data->cameras + i); + } + cgltf_write_line(context, "]"); + } + + if (data->lights_count > 0 || data->variants_count > 0) + { + cgltf_write_line(context, "\"extensions\": {"); + + if (data->lights_count > 0) + { + cgltf_write_line(context, "\"KHR_lights_punctual\": {"); + cgltf_write_line(context, "\"lights\": ["); + for (cgltf_size i = 0; i < data->lights_count; ++i) + { + cgltf_write_light(context, data->lights + i); + } + cgltf_write_line(context, "]"); + cgltf_write_line(context, "}"); + } + + if (data->variants_count) + { + cgltf_write_line(context, "\"KHR_materials_variants\": {"); + cgltf_write_line(context, "\"variants\": ["); + for (cgltf_size i = 0; i < data->variants_count; ++i) + { + cgltf_write_variant(context, data->variants + i); + } + cgltf_write_line(context, "]"); + cgltf_write_line(context, "}"); + } + + cgltf_write_line(context, "}"); + } + + if (context->extension_flags != 0) + { + cgltf_write_line(context, "\"extensionsUsed\": ["); + cgltf_write_extensions(context, context->extension_flags); + cgltf_write_line(context, "]"); + } + + if (context->required_extension_flags != 0) + { + cgltf_write_line(context, "\"extensionsRequired\": ["); + cgltf_write_extensions(context, context->required_extension_flags); + cgltf_write_line(context, "]"); + } + + cgltf_write_extras(context, &data->extras); + + CGLTF_SPRINTF("\n}\n"); + + // snprintf does not include the null terminator in its return value, so be sure to include it + // in the returned byte count. + return 1 + ctx.chars_written; +} + +#endif /* #ifdef CGLTF_WRITE_IMPLEMENTATION */ + +/* cgltf is distributed under MIT license: + * + * Copyright (c) 2019-2021 Philip Rideout + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ From 8d70f1007b5c34be0967ff091067c52962861f1c Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:24:33 +0200 Subject: [PATCH 039/185] Update CHANGELOG --- CHANGELOG | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index cf9bf238d..cc44aac2c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -759,6 +759,7 @@ Detailed changes: [rexm] REVIEWED: `Makefile.Web` before trying to rebuild new example for web by @raysan5 [rexm] REVIEWED: Using `Makefile.Web` for specific web versions generation by @raysan5 +[external] ADDED: `cgltf_write` 1.15, to support glTF models export in the future, by @raysan5 [external] RENAMED: `rl_gputex.h` to `rltexgpu.h`, compressed textures loading [external] REVIEWED: `rltexgpu.h`, make it usable standalone by @raysan5 [external] REVIEWED: `rltexgpu.h, fix the swizzling in `rl_load_dds_from_memory()` (#5422) by @msmith-codes @@ -767,16 +768,23 @@ Detailed changes: [external] REVIEWED: `sdefl` and `sinfl` issues (#5367) by @raysan5 [external] REVIEWED: `sinfl_bsr()`, improvements by @RicoP [external] REVIEWED: `stb_truetype`, fix composite glyph scaling logic (#4811) by @ashishbhattarai +[external] UPDATED: `raygui` to 5.0-dev for examples by @raysan5 [external] UPDATED: dr_libs (#5020) by @Emil2010 -[external] UPDATED: miniaudio to v0.11.22 (#4983) by @M374LX -[external] UPDATED: miniaudio to v0.11.23 (#5234) by @pyrokn8 -[external] UPDATED: miniaudio to v0.11.24 (#5506) by @vdemcak -[external] UPDATED: raygui to 5.0-dev for examples by @raysan5 -[external] UPDATED: RGFW to 1.5 (#4688) by @ColleagueRiley -[external] UPDATED: RGFW to 1.6 (#4795) by @colleagueRiley -[external] UPDATED: RGFW to 1.7 (#4965) by @M374LX -[external] UPDATED: RGFW to 1.7.5-dev (#4976) by @M374LX -[external] UPDATED: RGFW to 2.0.0 (#5582) by @CrackedPixel +[external] UPDATED: `miniaudio` to v0.11.22 (#4983) by @M374LX +[external] UPDATED: `miniaudio` to v0.11.23 (#5234) by @pyrokn8 +[external] UPDATED: `miniaudio` to v0.11.24 (#5506) by @vdemcak +[external] UPDATED: `RGFW` to 1.5 (#4688) by @ColleagueRiley +[external] UPDATED: `RGFW` to 1.6 (#4795) by @colleagueRiley +[external] UPDATED: `RGFW` to 1.7 (#4965) by @M374LX +[external] UPDATED: `RGFW` to 1.7.5-dev (#4976) by @M374LX +[external] UPDATED: `RGFW` to 2.0.0 (#5582) by @CrackedPixel +[external] UPDATED: `cgltf` 1.14 to 1.15 by @raysan5 +[external] UPDATED: `dr_flac` v0.13.0 to v0.13.3 by @raysan5 +[external] UPDATED: `dr_mp3` v0.7.0 to v0.7.4 by @raysan5 +[external] UPDATED: `m3d` to latest master by @raysan5 +[external] UPDATED: `qoi` to latest master by @raysan5 +[external] UPDATED: `qoa` to latest master by @raysan5 +[external] UPDATED: `stb_image_resize2` v2.12 to v2.18 by @raysan5 [misc] ADDED: SECURITY.md for security reporting policies by @raysan5 [misc] ADDED: `examples/examples_list`, to be used by `rexm` or other tools by @raysan5 From 04f81538b7d458569d280dc1e10e517494df9fa4 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:37:01 +0200 Subject: [PATCH 040/185] ADDED: Some sample code to export gltf/glb meshes -WIP- --- src/rmodels.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/rmodels.c b/src/rmodels.c index 6c1e0482e..3fff05eaa 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -10,6 +10,7 @@ * #define SUPPORT_FILEFORMAT_MTL * #define SUPPORT_FILEFORMAT_IQM * #define SUPPORT_FILEFORMAT_GLTF +* #define SUPPORT_FILEFORMAT_GLTF_WRITE * #define SUPPORT_FILEFORMAT_VOX * #define SUPPORT_FILEFORMAT_M3D * Selected desired fileformats to be supported for model data loading @@ -71,6 +72,11 @@ #define CGLTF_IMPLEMENTATION #include "external/cgltf.h" // glTF file format loading #endif +#if SUPPORT_FILEFORMAT_GLTF_WRITE + // NOTE: No need for custom allocators, memory buffer provided + #define CGLTF_WRITE_IMPLEMENTATION + #include "external/cgltf_write.h" // glTF file format writing +#endif #if SUPPORT_FILEFORMAT_VOX #define VOX_MALLOC RL_MALLOC @@ -2017,6 +2023,19 @@ bool ExportMesh(Mesh mesh, const char *fileName) RL_FREE(txtData); } + else if (IsFileExtension(fileName, ".gltf")) // Or .glb + { + // TODO: Implement gltf/glb support + /* + cgltf_size expected = cgltf_write(options, NULL, 0, data); + char *buffer = (char *)RL_CALLOC(expected, 0); + cgltf_size actual = cgltf_write(options, buffer, expected, data); + + // NOTE: cgltf_write() includes a NULL terminator that should be ommited in case of a .glb + if (options->type == cgltf_file_type_glb) cgltf_write_glb(file, buffer, actual - 1, data->bin, data->bin_size); + else SaveFileText(fileName, buffer); // Write a plain JSON file + */ + } else if (IsFileExtension(fileName, ".raw")) { // TODO: Support additional file formats to export mesh vertex data From 8743e11285c5d1dae3f64d36f799deac01898977 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:40:41 +0200 Subject: [PATCH 041/185] Update rmodels.c --- src/rmodels.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rmodels.c b/src/rmodels.c index 3fff05eaa..3dd28c6c1 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -5284,7 +5284,7 @@ static cgltf_result LoadFileGLTFCallback(const struct cgltf_memory_options *memo } // Release file data callback for cgltf -static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data) +static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data, cgltf_size size) { UnloadFileData((unsigned char *)data); } From b3bf537fab25f9395f42281e8e935b77b820f735 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 30 Mar 2026 11:00:26 +0200 Subject: [PATCH 042/185] Update rexm.c --- tools/rexm/rexm.c | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index b160a9be1..d47a207e3 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -68,6 +68,7 @@ #define REXM_MAX_BUFFER_SIZE (2*1024*1024) // 2MB #define REXM_MAX_RESOURCE_PATHS 256 +#define REXM_MAX_RESOURCE_PATH_LENGTH 256 // Create local commit with changes on example renaming //#define RENAME_AUTO_COMMIT_CREATION @@ -2493,25 +2494,21 @@ static void SortExampleByName(rlExampleInfo *items, int count) qsort(items, count, sizeof(rlExampleInfo), rlExampleInfoCompare); } -// Scan resource paths in example file -// WARNING: Supported resource file extensions is hardcoded by used file types -// but new examples could require other file extensions to be added, -// maybe it should look for '.xxx")' patterns instead -// TODO: WARNING: Some resources could require linked resources: .fnt --> .png, .mtl --> .png, .gltf --> .png, ... -static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount) +// Scan asset paths from a source code file (raylib) +// WARNING: Supported asset file extensions are hardcoded by used file types +// but new examples could require other file extensions to be added +static char **LoadExampleResourcePaths(const char *srcFilePath, int *resPathCount) { - #define REXM_MAX_RESOURCE_PATH_LEN 256 - char **paths = (char **)RL_CALLOC(REXM_MAX_RESOURCE_PATHS, sizeof(char **)); - for (int i = 0; i < REXM_MAX_RESOURCE_PATHS; i++) paths[i] = (char *)RL_CALLOC(REXM_MAX_RESOURCE_PATH_LEN, sizeof(char)); + for (int i = 0; i < REXM_MAX_RESOURCE_PATHS; i++) paths[i] = (char *)RL_CALLOC(REXM_MAX_RESOURCE_PATH_LENGTH, sizeof(char)); int resCounter = 0; - char *code = LoadFileText(filePath); + char *code = LoadFileText(srcFilePath); if (code != NULL) { // Resources extensions to check - const char *exts[] = { ".png", ".bmp", ".jpg", ".qoi", ".gif", ".raw", ".hdr", ".ttf", ".fnt", ".wav", ".ogg", ".mp3", ".flac", ".mod", ".qoa", ".obj", ".iqm", ".glb", ".m3d", ".vox", ".vs", ".fs", ".txt" }; + const char *exts[] = { ".png", ".bmp", ".jpg", ".qoi", ".gif", ".raw", ".hdr", ".ttf", ".fnt", ".wav", ".ogg", ".mp3", ".flac", ".mod", ".xm", ".qoa", ".obj", ".iqm", ".glb", ".m3d", ".vox", ".vs", ".fs", ".txt" }; const int extCount = sizeof(exts)/sizeof(char *); char *ptr = code; @@ -2537,9 +2534,9 @@ static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount) !((functionIndex05 != -1) && (functionIndex05 < 40))) // Not found SaveFileText() before "" { int len = (int)(end - start); - if ((len > 0) && (len < REXM_MAX_RESOURCE_PATH_LEN)) + if ((len > 0) && (len < REXM_MAX_RESOURCE_PATH_LENGTH)) { - char buffer[REXM_MAX_RESOURCE_PATH_LEN] = { 0 }; + char buffer[REXM_MAX_RESOURCE_PATH_LENGTH] = { 0 }; strncpy(buffer, start, len); buffer[len] = '\0'; @@ -2575,6 +2572,29 @@ static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount) UnloadFileText(code); } + /* + // Some resources could require linked resources: .fnt --> .png, .mtl --> .png, .gltf --> .png + // So doing a recursive pass to scan possible files with second resources + int currentAssetCounter = resCounter; + for (int i = 0; i < currentAssetCounter; i++) + { + if (IsFileExtension(paths[i], ".fnt;.gltf")) + { + int assetCount2 = 0; + // ERROR: srcFilePath changes on rcursive call and TextFormat() static arrays are oveerride + char **assetPaths2 = LoadExampleResourcePaths(TextFormat("%s/%s", GetDirectoryPath(srcFilePath), paths[i]), &assetCount2); + + for (int j = 0; j < assetCount2; j++) + { + strcpy(paths[resCounter], TextFormat("%s/%s", GetDirectoryPath(paths[i]) + 2, assetPaths2[j])); + resCounter++; + } + + UnloadExampleResourcePaths(assetPaths2); + } + } + */ + *resPathCount = resCounter; return paths; } From 63beefd0de4ac59fdd1d20a0314166a0173a7389 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 30 Mar 2026 11:00:29 +0200 Subject: [PATCH 043/185] Update Makefile.Web --- examples/Makefile.Web | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 68c34f31b..709072be1 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -1153,7 +1153,10 @@ text/text_font_filters: text/text_font_filters.c --preload-file text/resources/KAISG.ttf@resources/KAISG.ttf text/text_font_loading: text/text_font_loading.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file text/resources/pixantiqua.fnt@resources/pixantiqua.fnt \ + --preload-file text/resources/pixantiqua.png@resources/pixantiqua.png \ + --preload-file text/resources/pixantiqua.ttf@resources/pixantiqua.ttf text/text_font_sdf: text/text_font_sdf.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ From c7df641aa25d40b1998d28cd38876e09f738b656 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 30 Mar 2026 11:00:39 +0200 Subject: [PATCH 044/185] Update text_font_loading.c --- examples/text/text_font_loading.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/text/text_font_loading.c b/examples/text/text_font_loading.c index 151b63d45..1bd3d26a2 100644 --- a/examples/text/text_font_loading.c +++ b/examples/text/text_font_loading.c @@ -38,12 +38,12 @@ int main(void) // Define characters to draw // NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally - const char msg[256] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ"; + const char msg[256] = "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ"; // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) // BMFont (AngelCode) : Font data and image atlas have been generated using external program - Font fontBm = LoadFont("resources/pixantiqua.fnt"); + Font fontBm = LoadFont("resources/pixantiqua.fnt"); // Requires "resources/pixantiqua.png" // TTF font : Font data and atlas are generated directly from TTF // NOTE: We define a font base size of 32 pixels tall and up-to 250 characters From a6dc9f9e9251818bc15c556986e2f2e8d6a7cb20 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 30 Mar 2026 20:16:40 +0200 Subject: [PATCH 045/185] Update LICENSE.md --- examples/models/resources/LICENSE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/models/resources/LICENSE.md b/examples/models/resources/LICENSE.md index d7f85c0f4..1feb770ab 100644 --- a/examples/models/resources/LICENSE.md +++ b/examples/models/resources/LICENSE.md @@ -13,9 +13,9 @@ | models/vox/chr_knight.vox | ❔ | ❔ | - | | models/vox/chr_sword.vox | ❔ | ❔ | - | | models/vox/monu9.vox | ❔ | ❔ | - | -| billboard.png | [@emegeme](https://github.com/emegeme) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - | +| billboard.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - | | cubicmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - | -| cubicmap_atlas.png | [@emegeme](https://github.com/emegeme) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - | +| cubicmap_atlas.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - | | heightmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - | | dresden_square_1k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - | | dresden_square_2k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - | From 78797757f04f6b76f7a340ecbbd75cfa63ab5762 Mon Sep 17 00:00:00 2001 From: Green3492 <57958064+r3g492@users.noreply.github.com> Date: Tue, 31 Mar 2026 23:45:54 +0900 Subject: [PATCH 046/185] store bytes at global data seg (#5708) --- examples/models/models_decals.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/models/models_decals.c b/examples/models/models_decals.c index 6e80283f2..2956d3c7a 100644 --- a/examples/models/models_decals.c +++ b/examples/models/models_decals.c @@ -108,7 +108,7 @@ int main(void) decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE; bool showModel = true; - Model decalModels[MAX_DECALS] = { 0 }; + static Model decalModels[MAX_DECALS] = { 0 }; int decalCount = 0; SetTargetFPS(60); // Set our game to run at 60 frames-per-second From 4ca9170f5b03f6fddd1f40494ddbcd8d27646795 Mon Sep 17 00:00:00 2001 From: Krzysztof Szenk Date: Wed, 1 Apr 2026 09:46:14 +0200 Subject: [PATCH 047/185] [rcore_rgfw] Updating render resolution as well on SetWindowSize (#5709) * [rcore_rgfw] Updating render resolution as well on SetWindowSize * Actually, maybe even better call SetupViewport() --- src/platforms/rcore_desktop_rgfw.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 51a73e1ad..11f268d9f 100755 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -821,6 +821,11 @@ void SetWindowSize(int width, int height) CORE.Window.screen.height = height; } + if (!CORE.Window.usingFbo) + { + SetupViewport(CORE.Window.screen.width, CORE.Window.screen.height); + } + RGFW_window_resize(platform.window, CORE.Window.screen.width, CORE.Window.screen.height); } From 449182bb517b7d62e9b726f650cb281df0e4a7c5 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 1 Apr 2026 10:17:34 +0200 Subject: [PATCH 048/185] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bc503cd6..00929215c 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ features - Written in plain C code (C99) using PascalCase/camelCase notation - Hardware accelerated with OpenGL: **1.1, 2.1, 3.3, 4.3, ES 2.0, ES 3.0** - **Unique OpenGL abstraction layer** (usable as standalone module): [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) + - **Software Renderer** backend (no OpenGL required!): [rlsw](https://github.com/raysan5/raylib/blob/master/src/external/rlsw.h) - Multiple **Fonts** formats supported (TTF, OTF, FNT, BDF, sprite fonts) - Multiple texture formats supported, including **compressed formats** (DXT, ETC, ASTC) - **Full 3D support**, including 3D Shapes, Models, Billboards, Heightmaps and more! @@ -61,7 +62,7 @@ This is a basic raylib example, it creates a window and draws the text `"Congrat int main(void) { - InitWindow(800, 450, "raylib [core] example - basic window"); + InitWindow(800, 450, "raylib example - basic window"); while (!WindowShouldClose()) { From eb4f1a6da0b443db9eb2e2cead3befbbbf762264 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 1 Apr 2026 10:17:37 +0200 Subject: [PATCH 049/185] Update ROADMAP.md --- ROADMAP.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index 91d2299c3..87cbb3fc8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -6,6 +6,7 @@ Here is a wishlist with features and ideas to improve the library. Note that fea - [GitHub PRs](https://github.com/raysan5/raylib/pulls) open with improvements to be reviewed. - [raylib source code](https://github.com/raysan5/raylib/tree/master/src) has multiple *TODO* comments around code with pending things to review or improve. - raylib wishlists discussions are open to everyone to ask for improvements, feel free to check and comment: + - [raylib 7.0 wishlist](https://github.com/raysan5/raylib/discussions/5710) - [raylib 6.0 wishlist](https://github.com/raysan5/raylib/discussions/4660) - [raylib 5.0 wishlist](https://github.com/raysan5/raylib/discussions/2952) - [raylib wishlist 2022](https://github.com/raysan5/raylib/discussions/2272) @@ -21,7 +22,7 @@ _Current version of raylib is complete and functional but there is always room f - [ ] `rcore_desktop_wayland`: Create additional platform backend: Linux/Wayland - [ ] `rcore`: Investigate alternative embedded platforms and realtime OSs - [ ] `rlsw`: Software renderer optimizations: mipmaps, platform-specific SIMD - - [ ] `rtextures`: Consider moving N-patch system to separate example + - [ ] `rtextures`: Consider removing N-patch system, provide as separate example - [ ] `rtextures`: Review blending modes system, provide more options or better samples - [ ] `rtext`: Investigate the recently opened [`Slug`](https://sluglibrary.com/) font rendering algorithm - [ ] `raudio`: Support microphone input, basic API to read microphone From 4799cab7727cd95796ebc77730d1fb65e52f90bc Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 1 Apr 2026 10:17:41 +0200 Subject: [PATCH 050/185] Update rexm.c --- tools/rexm/rexm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index d47a207e3..841ccbce8 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -2573,7 +2573,7 @@ static char **LoadExampleResourcePaths(const char *srcFilePath, int *resPathCoun } /* - // Some resources could require linked resources: .fnt --> .png, .mtl --> .png, .gltf --> .png + // WARNING: Some resources could require linked resources: .fnt --> .png, .mtl --> .png, .gltf --> .png // So doing a recursive pass to scan possible files with second resources int currentAssetCounter = resCounter; for (int i = 0; i < currentAssetCounter; i++) @@ -2581,7 +2581,7 @@ static char **LoadExampleResourcePaths(const char *srcFilePath, int *resPathCoun if (IsFileExtension(paths[i], ".fnt;.gltf")) { int assetCount2 = 0; - // ERROR: srcFilePath changes on rcursive call and TextFormat() static arrays are oveerride + // ERROR: srcFilePath changes on rcursive call and TextFormat() static arrays are override char **assetPaths2 = LoadExampleResourcePaths(TextFormat("%s/%s", GetDirectoryPath(srcFilePath), paths[i]), &assetCount2); for (int j = 0; j < assetCount2; j++) From 12140cd444d03591c36b0fdd6dec3a7173e5edb3 Mon Sep 17 00:00:00 2001 From: Green3492 <57958064+r3g492@users.noreply.github.com> Date: Wed, 1 Apr 2026 21:48:49 +0900 Subject: [PATCH 051/185] explicitly state TEXTURE_WRAP_REPEAT for web build (#5711) --- examples/shaders/shaders_texture_tiling.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/shaders/shaders_texture_tiling.c b/examples/shaders/shaders_texture_tiling.c index 14e15b8b2..4f6b26d71 100644 --- a/examples/shaders/shaders_texture_tiling.c +++ b/examples/shaders/shaders_texture_tiling.c @@ -56,6 +56,7 @@ int main(void) // Set the texture tiling using a shader float tiling[2] = { 3.0f, 3.0f }; Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/tiling.fs", GLSL_VERSION)); + SetTextureWrap(texture, TEXTURE_WRAP_REPEAT); SetShaderValue(shader, GetShaderLocation(shader, "tiling"), tiling, SHADER_UNIFORM_VEC2); model.materials[0].shader = shader; From 5c2dee086282397ecaea9cbe46b1077704f946d2 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 1 Apr 2026 23:23:25 +0200 Subject: [PATCH 052/185] REVIEWED: `LoadDirectoryFiles*()` comments --- src/raylib.h | 4 ++-- src/rcore.c | 26 +++++++++++++++----------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index ac5bc414e..c6aad860a 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1161,8 +1161,8 @@ RLAPI int MakeDirectory(const char *dirPath); // Create di RLAPI bool ChangeDirectory(const char *dirPath); // Change working directory, return true on success RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS -RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths -RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result +RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths, files and directories, no subdirs scan +RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*" RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths diff --git a/src/rcore.c b/src/rcore.c index 1f6699af9..f93e25573 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -267,15 +267,18 @@ #define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record #endif +// File and directory scan filters +// NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx() +// WARNING: Custom file filters can be specified but following raylib IsFileExtension() convention: ".png;.wav;.glb" #ifndef FILE_FILTER_TAG_ALL - #define FILE_FILTER_TAG_ALL "*.*" // Filter to include all file types and directories on directory scan -#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx() + #define FILE_FILTER_TAG_ALL "*.*" // Filter to include all file types and directories on scan +#endif #ifndef FILE_FILTER_TAG_FILE_ONLY - #define FILE_FILTER_TAG_FILE_ONLY "FILES*" // Filter to include all file types on directory scan -#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx() + #define FILE_FILTER_TAG_FILE_ONLY "FILES*" // Filter to include all file types on scan (no directories) +#endif #ifndef FILE_FILTER_TAG_DIR_ONLY - #define FILE_FILTER_TAG_DIR_ONLY "DIR*" // Filter to include directories on directory scan -#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx() + #define FILE_FILTER_TAG_DIR_ONLY "DIRS*" // Filter to include only directories on scan +#endif // Flags bitwise operation macros #define FLAG_SET(n, f) ((n) |= (f)) @@ -2720,17 +2723,18 @@ const char *GetApplicationDirectory(void) // Load directory filepaths // NOTE: Base path is prepended to the scanned filepaths -// WARNING: Directory is scanned twice, first time to get files count -// No recursive scanning is done! +// WARNING: Directory is scanned twice, first time to get paths count +// Scanneed files and directories, no recursive/subdirs scanning FilePathList LoadDirectoryFiles(const char *dirPath) { return LoadDirectoryFilesEx(dirPath, FILE_FILTER_TAG_ALL, false); } // Load directory filepaths with extension filtering and recursive directory scan -// Use 'DIR*' to include directories on directory scan -// Use '*.*' to include all file types and directories on directory scan -// WARNING: Directory is scanned twice, first time to get files count +// Use "*.*" to include all files and directories on scan +// Use "FILES*" to include only files on scan +// Use "DIRS*" to include only directories on scan +// WARNING: Directory is scanned twice, first time to get paths count FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs) { FilePathList files = { 0 }; From f36533cbd8feead845a2e0b4568ec0484a15cd10 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 21:23:44 +0000 Subject: [PATCH 053/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 4 ++-- tools/rlparser/output/raylib_api.lua | 4 ++-- tools/rlparser/output/raylib_api.txt | 4 ++-- tools/rlparser/output/raylib_api.xml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index 1fbc87a9d..ed0e220d7 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -4685,7 +4685,7 @@ }, { "name": "LoadDirectoryFiles", - "description": "Load directory filepaths", + "description": "Load directory filepaths, files and directories, no subdirs scan", "returnType": "FilePathList", "params": [ { @@ -4696,7 +4696,7 @@ }, { "name": "LoadDirectoryFilesEx", - "description": "Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result", + "description": "Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"", "returnType": "FilePathList", "params": [ { diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index 398e1b177..a412e513f 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -4199,7 +4199,7 @@ return { }, { name = "LoadDirectoryFiles", - description = "Load directory filepaths", + description = "Load directory filepaths, files and directories, no subdirs scan", returnType = "FilePathList", params = { {type = "const char *", name = "dirPath"} @@ -4207,7 +4207,7 @@ return { }, { name = "LoadDirectoryFilesEx", - description = "Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result", + description = "Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"", returnType = "FilePathList", params = { {type = "const char *", name = "basePath"}, diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index d3cd7bcdc..bdad7db98 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -1784,12 +1784,12 @@ Function 145: IsFileNameValid() (1 input parameters) Function 146: LoadDirectoryFiles() (1 input parameters) Name: LoadDirectoryFiles Return type: FilePathList - Description: Load directory filepaths + Description: Load directory filepaths, files and directories, no subdirs scan Param[1]: dirPath (type: const char *) Function 147: LoadDirectoryFilesEx() (3 input parameters) Name: LoadDirectoryFilesEx Return type: FilePathList - Description: Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result + Description: Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*" Param[1]: basePath (type: const char *) Param[2]: filter (type: const char *) Param[3]: scanSubdirs (type: bool) diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 62d8bdfaf..83e2bd548 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -1122,10 +1122,10 @@ - + - + From bb7b8d70e90f4d8303817cc0701f2f283ffdf0a9 Mon Sep 17 00:00:00 2001 From: Arbinda Rizki Muhammad <156565433+arbipink@users.noreply.github.com> Date: Sat, 4 Apr 2026 16:04:24 +0700 Subject: [PATCH 054/185] Example/audio adsr (#5713) * add audio_amp_envelope example * Change 1.0f to env->sustainLevel in case the user release the spacebar before attack state done --- examples/audio/audio_amp_envelope.c | 235 + examples/audio/audio_amp_envelope.png | Bin 0 -> 11047 bytes examples/audio/raygui.h | 6051 +++++++++++++++++++++++++ 3 files changed, 6286 insertions(+) create mode 100644 examples/audio/audio_amp_envelope.c create mode 100644 examples/audio/audio_amp_envelope.png create mode 100644 examples/audio/raygui.h diff --git a/examples/audio/audio_amp_envelope.c b/examples/audio/audio_amp_envelope.c new file mode 100644 index 000000000..9d6939e35 --- /dev/null +++ b/examples/audio/audio_amp_envelope.c @@ -0,0 +1,235 @@ +/******************************************************************************************* +* +* raylib [audio] example - amp envelope +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 6.0, last time updated with raylib 6.0 +* +* Example contributed by Arbinda Rizki Muhammad (@arbipink) and reviewed by Ramon Santamaria (@raysan5) +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2026 Arbinda Rizki Muhammad (@arbipink) +* +********************************************************************************************/ + +#include "raylib.h" + +#define RAYGUI_IMPLEMENTATION +#include "raygui.h" + +#include + +#define BUFFER_SIZE 4096 +#define SAMPLE_RATE 44100 + +// Wave state +typedef enum { + IDLE, + ATTACK, + DECAY, + SUSTAIN, + RELEASE +} ADSRState; + +// Grouping all ADSR parameters and state into a struct +typedef struct { + float attackTime; + float decayTime; + float sustainLevel; + float releaseTime; + float currentValue; + ADSRState state; +} Envelope; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration +//------------------------------------------------------------------------------------ +static void FillAudioBuffer(int i, float* buffer, float envelopeValue, float* audioTime); +static void UpdateEnvelope(Envelope* env); +static void DrawADSRGraph(const Envelope *env, Rectangle bounds); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [audio] example - amp envelope"); + + InitAudioDevice(); + + // Set the number of samples the stream will keep in memory at a time to BUFFER_SIZE + SetAudioStreamBufferSizeDefault(BUFFER_SIZE); + float buffer[BUFFER_SIZE] = { 0 }; + + // Init raw audio stream (sample rate: 44100, sample size: 32bit-float, channels: 1-mono) + AudioStream stream = LoadAudioStream(SAMPLE_RATE, 32, 1); + + // Init Phase + float audioTime = 0.0f; + + // Initialize the struct + Envelope env = { + .attackTime = 1.0f, + .decayTime = 1.0f, + .sustainLevel = 0.5f, + .releaseTime = 1.0f, + .currentValue = 0.0f, + .state = IDLE + }; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) + { + // Update + //---------------------------------------------------------------------------------- + + if (IsKeyPressed(KEY_SPACE)) { + env.state = ATTACK; + } + + if (IsKeyReleased(KEY_SPACE)) { + if (env.state != IDLE) env.state = RELEASE; + } + + if (IsAudioStreamProcessed(stream)) { + + if (env.state != IDLE || env.currentValue > 0.0f) { + for (int i = 0; i < BUFFER_SIZE; i++) + { + UpdateEnvelope(&env); + FillAudioBuffer(i, buffer, env.currentValue, &audioTime); + } + } else { + // Clear buffer if silent to avoid looping noise + for (int i = 0; i < BUFFER_SIZE; i++) buffer[i] = 0; + audioTime = 0.0f; + } + + UpdateAudioStream(stream, buffer, BUFFER_SIZE); + } + + if (!IsAudioStreamPlaying(stream)) PlayAudioStream(stream); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + GuiSliderBar((Rectangle){ 100, 60, 400, 30 }, "Attack (s)", TextFormat("%2.2fs", env.attackTime), &env.attackTime, 0.1f, 3.0f); + GuiSliderBar((Rectangle){ 100, 100, 400, 30 }, "Decay (s)", TextFormat("%2.2fs", env.decayTime), &env.decayTime, 0.1f, 3.0f); + GuiSliderBar((Rectangle){ 100, 140, 400, 30 }, "Sustain", TextFormat("%2.2f", env.sustainLevel), &env.sustainLevel, 0.0f, 1.0f); + GuiSliderBar((Rectangle){ 100, 180, 400, 30 }, "Release (s)", TextFormat("%2.2fs", env.releaseTime), &env.releaseTime, 0.1f, 3.0f); + + DrawADSRGraph(&env, (Rectangle){ 100, 250, 400, 100 }); + + DrawCircleV((Vector2){ 520, 350 - (env.currentValue * 100) }, 5, MAROON); + DrawText(TextFormat("Current Gain: %2.2f", env.currentValue), 535, 345 - (env.currentValue * 100), 10, MAROON); + + DrawText("Press SPACE to PLAY the sound!", 200, 400, 20, LIGHTGRAY); + EndDrawing(); + //---------------------------------------------------------------------------------- + } + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadAudioStream(stream); + CloseAudioDevice(); + + CloseWindow(); + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definition +//------------------------------------------------------------------------------------ +static void FillAudioBuffer(int i, float* buffer, float envelopeValue, float* audioTime) +{ + + int frequency = 440; + buffer[i] = envelopeValue * sinf(2.0f * PI * frequency * (*audioTime)); + *audioTime += 1.0f / SAMPLE_RATE; +} + +static void UpdateEnvelope(Envelope *env) +{ + // Calculate the time delta for ONE sample (1/44100) + float sampleTime = 1.0f / SAMPLE_RATE; + + switch(env->state) + { + case ATTACK: + env->currentValue += (1.0f / env->attackTime) * sampleTime; + if (env->currentValue >= 1.0f) + { + env->currentValue = 1.0f; + env->state = DECAY; + } + break; + + case DECAY: + env->currentValue -= ((1.0f - env->sustainLevel) / env->decayTime) * sampleTime; + if (env->currentValue <= env->sustainLevel) + { + env->currentValue = env->sustainLevel; + env->state = SUSTAIN; + } + break; + + case SUSTAIN: + env->currentValue = env->sustainLevel; + break; + + case RELEASE: + env->currentValue -= (env->sustainLevel / env->releaseTime) * sampleTime; + if (env->currentValue <= 0.001f) // Use a small threshold to avoid infinite tail + { + env->currentValue = 0.0f; + env->state = IDLE; + } + break; + + default: break; + } +} + +static void DrawADSRGraph(const Envelope *env, Rectangle bounds) +{ + DrawRectangleRec(bounds, Fade(LIGHTGRAY, 0.3f)); + DrawRectangleLinesEx(bounds, 1, GRAY); + + // Fixed visual width for sustain stage since it's an amplitude not a time value + float sustainWidth = 1.0f; + + // Total time to visualize (sum of A, D, R + a padding for Sustain) + float totalTime = env->attackTime + env->decayTime + sustainWidth + env->releaseTime; + + float scaleX = bounds.width / totalTime; + float scaleY = bounds.height; + + Vector2 start = { bounds.x, bounds.y + bounds.height }; + Vector2 peak = { start.x + (env->attackTime * scaleX), bounds.y }; + Vector2 sustain = { peak.x + (env->decayTime * scaleX), bounds.y + (1.0f - env->sustainLevel) * scaleY }; + Vector2 rel = { sustain.x + (sustainWidth * scaleX), sustain.y }; + Vector2 end = { rel.x + (env->releaseTime * scaleX), bounds.y + bounds.height }; + + DrawLineV(start, peak, SKYBLUE); + DrawLineV(peak, sustain, BLUE); + DrawLineV(sustain, rel, DARKBLUE); + DrawLineV(rel, end, ORANGE); + + DrawText("ADSR Visualizer", bounds.x, bounds.y - 20, 10, DARKGRAY); +} \ No newline at end of file diff --git a/examples/audio/audio_amp_envelope.png b/examples/audio/audio_amp_envelope.png new file mode 100644 index 0000000000000000000000000000000000000000..b09dcc9d016d19ad80a92e2ca482ce22b35a67c8 GIT binary patch literal 11047 zcmeG?dpuNW|Ic8Xu9H%`YDZ0zNE9hGQcURLnx$P*p}dOPm=JQwQEgEqDG4$CHbp7y zrgER%E@QVsWwA-7*xW)QQ^dUA=b0FL`RrfsXLsNC*ZF78Ip6#Jd7d*7HrA`gjh;Fh zAvDfxwW%#aBlHoH-#u~!ym3@nw-|or`mS*BHSu=a9xacu8*s?o13SP zyO(c=e6b-ybB>ysE?*mv^rCjYmsZto;nUm$pNi!&zNfaye|F>9xroF`cMsak%^4AQ zsloU{Zdk&kme(`Bp*=_&Jw|V|;#pOZv8Q~-=ekA5HDWZ|+wZw+tiGnE#xv4ZNSY7dN!D{_ zzu@f^C7mC&?|gr$6|=k6b6cwOs^)r?Y3JiIKSfAj6Qcf8Uvl)ca4WlC`}9~Eav0X$<}B!Ox+tvVbGBXx%C^qgBGhl6JO&}1agA<>8zt+9 z^JB8b^V))L-N|jceR-63^W?>;>KsNcdn7_G>q_q+Dj|HRA-b|%)iumd^}Z1%Z*9>G zEG^Wwp9CgZ-q}3`*(k~S<-+#r$qQ4}mNBA@eoA0ktho((W}NQQ{gnY}ce6E}k62ko z)_OK|O*a_GE<2gr#9N^VR$B;5^UYJ}j9LbAu^u$J`QD!5&?f%GgZ3k$PAlYgb86ap zIy(!ajoPTI8*1xzA*5H`<`*5Ec<-D%a$&{}X}#~lamO29SL`G?kaqGPkQ79d;j>7z z|6*T08Bx@dVe`it43dttT|@KAt4B8QZma%R3@@kbT2BL*wfbK!N@O5vr!4ts>KmM$ z{lOh}QcF)xkd5V}mu++}1O8llu|M&_4n-M^I8gDgA5Y6a_w@913Jwkms)_ong+tV+ zu#l}B78oSyaJKA-rLS>5Y1`5Fl9L)e9%}AnQEZDz+2YeFa%is13ZZf7#!;@XfC=Sq zZso+Rkv#Z85mB>b2{7|!h4>4V{Qg|cJ?2*bcimnKYU7)vlQg6^ln(4w@wR}Iw{fm` z^Da_6QUsYJSH-8R&DnOUg46i8)px}NU~z@8_!UNG_>{co!VR{S&_$5@iQkl}LrHZ| zJfk+VyT`oUnsn{fJ>+u5xsJC_vb(-M)92h9jF8W;;&QF@o)x8e07^7RLoa=PRTmB2 zT`r5GroZQo!#B#J3yqt2#Xc!U{*P@lVaNjd2AOZ%?`}{Um)iczBXQTsB5iTxM+jB6 zKi(blgFj-$$hUWxa7@GeZLvxvm^@t>&W`*w`sf{-;?zmB(@wyex zEE-x3(w~S6UVBK+)X1ZX)v~ISKb^nVt?4FS`y|F*Vk%(Jh+yfDx0mY{A{u6T)-+4PBECG+kGf8x1+Y@5DRM8O+b z-0_BMMy{G0XdCd`HSp|)$EL#SoO$LdjY+wcFO~01UJhv5QOmrR`X$-I7U=GfO@%*q zh{vm}-Q46j!%k&ueyyQlk+}1`N_iYvIr2y3*S2@=lx~+?j}0Av*qpH49&mh#bjZFQ z)=EGOoR|!8m-%IglwkY?yTAYGY5G?=k;wUvhx6s3Xv1Fj@*d~V{@48e+zdgP1`5z)(G8&A=GAN%gz?|#s*k)~RGNO)+BjZ>5h*R% zTttTquC5g7hg5Z6?|vgZ9$0I)0~X5&6%0GI<7{fr(Yo#Qvyr%!x&1=K{`5-KW&<-_ z-{KbsmbljO+l*bBx{`v5Tw_&S)fH}Ej@nt8n^{#|Wl*JRQ72B+T}Nn|2Ztdj zJ+8$dVtx+I8sk+qz8i zf{mPTp_B^~c(TG=1BrZYKfrY4gauMqAe7{Cg(L6jUV|HqM>2OQ5_v5kPeGB>B9)-E zrU9iT2|im)6m`)DrneN1Fr`Ml1E%Jqn5U#n--6ncCvsj%7J60;5#wsZtQRMUAJkU&<$`gr+kyY+triJ7;j!7B076E{(Nm>D zfK7t}`Do(g)j$`i$}49} zpMWkBU`wP=KsQ#Em!(F;+h8kD*uI>JIC2zTIV~H-lq$LloEoUe5lJ&FEv$sbJ0PG5 ziM@hj5I7|TM$;;yOdK#}&fp1ngsBefmqnB1=o_S(KF2^s4xdTn$3s7U87ZJWB)LLq zK*&SYd4g`@V?KP2;VW@mJf+I*Eum#33ut$wzOe{r3NDOd+RzCfWs?T(bwM4w(oed?zP9M(bNoFs6-MK+JCMhF9F|S2t2Na z6Nme8jC{B%5807WvEbPI<^&FvOU$=f3@|niSrDh>6qb zsQp@j!T;i5_Sb!Nk|wGuMB*i>fVw#j)_$(Up%jePc)yu7kJ(id8Y=1R)Rw#ofd*s) z4SubK2vL4ZZ;iu_oDIv$3!o1-5u1!7mv%%zLv6T8Qxn1BIdXKAaTuGt!5C0y@Sum` zV*h2zv ziQp^-63QzuPShZhCqRn!2R6Z3OsS5&EU@mT$t^x$ER01wife<{MLts?~5eP*{eTQ{x zy9p+zLDa`WoY6Z=@CW49&LgG5UB+UxF}GZ`yfX!$!vPGe z2jEOBWH+{CEW`&exo#MfIYRK$7YG6!SkDCx7Xi2^2uZJXuIosBVbv8EL(8z`bq6MT)$Fo|H=&_Hpt2UiDP@r=P?6z#&m#&Bj93j<4WopZpdudwDikyzImG4dZ{ zT?GLcb&V+_{uF2j83YapXTm52x*suJr9}gEiqOr4pt^(rW*Elo!jY;pX`mu-s%DJ^ zAU}jnhgk|a^9%N48^oWD{aAsQ1@6%$G$rgSz7t5~8kjO>TVm9)_{lIvel&If3$F@} zf<$9%aS1l6VS+v%M^Tz$4T}0AW6bl48SqSlh1Dm7X9(s}Xv$DF!#sDbvwQI-GxSZP zy+jiFu0sN-aC#sZi3v08?_}3IJm$PB08tgj4OAEwB|06qS(tl$=a+pNuEO%FE0r&8 zTY~0SRRy)%REk4Xf|i+xi@V<<<#v0O@1-z6cmS&FsK{cYZ|?LbKu< zsAR%!(wO6G>K{+;Ft%7{7g~5S!DY5y`h9%sJ6oV($o9m{sa*c9W9|{28@P4qSTO`5^;6scPZ1ROCHrqKlTbV2VS>1=eJ){ z8V6~)HCUvf+ugtJ zqJoPd!F5SBw{(erhEUwlmQFBdW8ke^IIq?EfqZt$sGb#LECP%zI>9Trt0{X@u~{BISmc(}bzHTfNsmAK2X){BxOqdQR=Wkmi(w>BXU`R{eXP5A;?H z1a30lvxi1C{t*Yvo7nY5Bj|82UYDBe%}nud}F zKa0ZVi*RGX5}aK4g_C#hG{v%n~r?=@VAOSrFW*}UvArknaU=>ep@C#Aw!=AJ8$r@e<-W7%vOSb$dZ)Y7; z{AQqFQQcO=(|+Icjt-vVnGJg(P|qx_9x#*-4BR4aUhv&Lt(2U;-phthy6<*xEfZhs z%1$nJ>@RwJX^)Y8W{1c5ODB8#e8i1w)`txAB*{@hu<`tzHsr-wNwl!OZ90K+BSYUO n)^N!L^x*|@!yks`|AB)#w)36rZB5=T!nT^Nur|GH?6UXY(i;B6 literal 0 HcmV?d00001 diff --git a/examples/audio/raygui.h b/examples/audio/raygui.h new file mode 100644 index 000000000..03e487912 --- /dev/null +++ b/examples/audio/raygui.h @@ -0,0 +1,6051 @@ +/******************************************************************************************* +* +* raygui v5.0-dev - A simple and easy-to-use immediate-mode gui library +* +* DESCRIPTION: +* raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also +* available as a standalone library, as long as input and drawing functions are provided +* +* FEATURES: +* - Immediate-mode gui, minimal retained data +* - +25 controls provided (basic and advanced) +* - Styling system for colors, font and metrics +* - Icons supported, embedded as a 1-bit icons pack +* - Standalone mode option (custom input/graphics backend) +* - Multiple support tools provided for raygui development +* +* POSSIBLE IMPROVEMENTS: +* - Better standalone mode API for easy plug of custom backends +* - Externalize required inputs, allow user easier customization +* +* LIMITATIONS: +* - No editable multi-line word-wraped text box supported +* - No auto-layout mechanism, up to the user to define controls position and size +* - Standalone mode requires library modification and some user work to plug another backend +* +* NOTES: +* - WARNING: GuiLoadStyle() and GuiLoadStyle{Custom}() functions, allocate memory for +* font atlas recs and glyphs, freeing that memory is (usually) up to the user, +* no unload function is explicitly provided... but note that GuiLoadStyleDefault() unloads +* by default any previously loaded font (texture, recs, glyphs) +* - Global UI alpha (guiAlpha) is applied inside GuiDrawRectangle() and GuiDrawText() functions +* +* CONTROLS PROVIDED: +* # Container/separators Controls +* - WindowBox --> StatusBar, Panel +* - GroupBox --> Line +* - Line +* - Panel --> StatusBar +* - ScrollPanel --> StatusBar +* - TabBar --> Button +* +* # Basic Controls +* - Label +* - LabelButton --> Label +* - Button +* - Toggle +* - ToggleGroup --> Toggle +* - ToggleSlider +* - CheckBox +* - ComboBox +* - DropdownBox +* - TextBox +* - ValueBox --> TextBox +* - Spinner --> Button, ValueBox +* - Slider +* - SliderBar --> Slider +* - ProgressBar +* - StatusBar +* - DummyRec +* - Grid +* +* # Advance Controls +* - ListView +* - ColorPicker --> ColorPanel, ColorBarHue +* - MessageBox --> Window, Label, Button +* - TextInputBox --> Window, Label, TextBox, Button +* +* It also provides a set of functions for styling the controls based on its properties (size, color) +* +* +* RAYGUI STYLE (guiStyle): +* raygui uses a global data array for all gui style properties (allocated on data segment by default), +* when a new style is loaded, it is loaded over the global style... but a default gui style could always be +* recovered with GuiLoadStyleDefault() function, that overwrites the current style to the default one +* +* The global style array size is fixed and depends on the number of controls and properties: +* +* static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)]; +* +* guiStyle size is by default: 16*(16 + 8) = 384 int = 384*4 bytes = 1536 bytes = 1.5 KB +* +* Note that the first set of BASE properties (by default guiStyle[0..15]) belong to the generic style +* used for all controls, when any of those base values is set, it is automatically populated to all +* controls, so, specific control values overwriting generic style should be set after base values +* +* After the first BASE properties set, the EXTENDED properties set is defined (by default guiStyle[16..23]), +* those properties are actually common to all controls and can not be overwritten individually (like BASE ones) +* Some of those properties are: TEXT_SIZE, TEXT_SPACING, LINE_COLOR, BACKGROUND_COLOR +* +* Custom control properties can be defined using the EXTENDED properties for each independent control. +* +* TOOL: rGuiStyler is a visual tool to customize raygui style: github.com/raysan5/rguistyler +* +* +* RAYGUI ICONS (guiIcons): +* raygui could use a global array containing icons data (allocated on data segment by default), +* a custom icons set could be loaded over this array using GuiLoadIcons(), but loaded icons set +* must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS will be loaded +* +* Every icon is codified in binary form, using 1 bit per pixel, so, every 16x16 icon +* requires 8 integers (16*16/32) to be stored in memory. +* +* When the icon is draw, actually one quad per pixel is drawn if the bit for that pixel is set +* +* The global icons array size is fixed and depends on the number of icons and size: +* +* static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS]; +* +* guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB +* +* TOOL: rGuiIcons is a visual tool to customize/create raygui icons: github.com/raysan5/rguiicons +* +* RAYGUI LAYOUT: +* raygui currently does not provide an auto-layout mechanism like other libraries, +* layouts must be defined manually on controls drawing, providing the right bounds Rectangle for it +* +* TOOL: rGuiLayout is a visual tool to create raygui layouts: github.com/raysan5/rguilayout +* +* CONFIGURATION: +* #define RAYGUI_IMPLEMENTATION +* Generates the implementation of the library into the included file +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation +* +* #define RAYGUI_STANDALONE +* Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined +* internally in the library and input management and drawing functions must be provided by +* the user (check library implementation for further details) +* +* #define RAYGUI_NO_ICONS +* Avoid including embedded ricons data (256 icons, 16x16 pixels, 1-bit per pixel, 2KB) +* +* #define RAYGUI_CUSTOM_ICONS +* Includes custom ricons.h header defining a set of custom icons, +* this file can be generated using rGuiIcons tool +* +* #define RAYGUI_DEBUG_RECS_BOUNDS +* Draw control bounds rectangles for debug +* +* #define RAYGUI_DEBUG_TEXT_BOUNDS +* Draw text bounds rectangles for debug +* +* VERSIONS HISTORY: +* 5.0 (xx-Mar-2026) ADDED: Support up to 32 controls (v500) +* ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes +* ADDED: GuiValueBoxFloat() +* ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP +* ADDED: GuiListView() property: LIST_ITEMS_BORDER_WIDTH +* ADDED: GuiLoadIconsFromMemory() +* ADDED: Multiple new icons +* ADDED: Macros for inputs customization, raylib decoupling +* REMOVED: GuiSpinner() from controls list, using BUTTON + VALUEBOX properties +* REMOVED: GuiSliderPro(), functionality was redundant +* REVIEWED: Controls using text labels to use LABEL properties +* REVIEWED: Replaced sprintf() by snprintf() for more safety +* REVIEWED: GuiTabBar(), close tab with mouse middle button +* REVIEWED: GuiScrollPanel(), scroll speed proportional to content +* REVIEWED: GuiDropdownBox(), support roll up and hidden arrow +* REVIEWED: GuiTextBox(), cursor position initialization +* REVIEWED: GuiSliderPro(), control value change check +* REVIEWED: GuiGrid(), simplified implementation +* REVIEWED: GuiIconText(), increase buffer size and reviewed padding +* REVIEWED: GuiDrawText(), improved wrap mode drawing +* REVIEWED: GuiScrollBar(), minor tweaks +* REVIEWED: GuiProgressBar(), improved borders computing +* REVIEWED: GuiTextBox(), multiple improvements: autocursor and more +* REVIEWED: Functions descriptions, removed wrong return value reference +* REDESIGNED: GuiColorPanel(), improved HSV <-> RGBA convertion +* REDESIGNED: WARNING: TEXT_LINE_SPACING does not consider text height, only lines spacing +* +* 4.0 (12-Sep-2023) ADDED: GuiToggleSlider() +* ADDED: GuiColorPickerHSV() and GuiColorPanelHSV() +* ADDED: Multiple new icons, mostly compiler related +* ADDED: New DEFAULT properties: TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE +* ADDED: New enum values: GuiTextAlignment, GuiTextAlignmentVertical, GuiTextWrapMode +* ADDED: Support loading styles with custom font charset from external file +* REDESIGNED: GuiTextBox(), support mouse cursor positioning +* REDESIGNED: GuiDrawText(), support multiline and word-wrap modes (read only) +* REDESIGNED: GuiProgressBar() to be more visual, progress affects border color +* REDESIGNED: Global alpha consideration moved to GuiDrawRectangle() and GuiDrawText() +* REDESIGNED: GuiScrollPanel(), get parameters by reference and return result value +* REDESIGNED: GuiToggleGroup(), get parameters by reference and return result value +* REDESIGNED: GuiComboBox(), get parameters by reference and return result value +* REDESIGNED: GuiCheckBox(), get parameters by reference and return result value +* REDESIGNED: GuiSlider(), get parameters by reference and return result value +* REDESIGNED: GuiSliderBar(), get parameters by reference and return result value +* REDESIGNED: GuiProgressBar(), get parameters by reference and return result value +* REDESIGNED: GuiListView(), get parameters by reference and return result value +* REDESIGNED: GuiColorPicker(), get parameters by reference and return result value +* REDESIGNED: GuiColorPanel(), get parameters by reference and return result value +* REDESIGNED: GuiColorBarAlpha(), get parameters by reference and return result value +* REDESIGNED: GuiColorBarHue(), get parameters by reference and return result value +* REDESIGNED: GuiGrid(), get parameters by reference and return result value +* REDESIGNED: GuiGrid(), added extra parameter +* REDESIGNED: GuiListViewEx(), change parameters order +* REDESIGNED: All controls return result as int value +* REVIEWED: GuiScrollPanel() to avoid smallish scroll-bars +* REVIEWED: All examples and specially controls_test_suite +* RENAMED: gui_file_dialog module to gui_window_file_dialog +* UPDATED: All styles to include ISO-8859-15 charset (as much as possible) +* +* 3.6 (10-May-2023) ADDED: New icon: SAND_TIMER +* ADDED: GuiLoadStyleFromMemory() (binary only) +* REVIEWED: GuiScrollBar() horizontal movement key +* REVIEWED: GuiTextBox() crash on cursor movement +* REVIEWED: GuiTextBox(), additional inputs support +* REVIEWED: GuiLabelButton(), avoid text cut +* REVIEWED: GuiTextInputBox(), password input +* REVIEWED: Local GetCodepointNext(), aligned with raylib +* REDESIGNED: GuiSlider*()/GuiScrollBar() to support out-of-bounds +* +* 3.5 (20-Apr-2023) ADDED: GuiTabBar(), based on GuiToggle() +* ADDED: Helper functions to split text in separate lines +* ADDED: Multiple new icons, useful for code editing tools +* REMOVED: Unneeded icon editing functions +* REMOVED: GuiTextBoxMulti(), very limited and broken +* REMOVED: MeasureTextEx() dependency, logic directly implemented +* REMOVED: DrawTextEx() dependency, logic directly implemented +* REVIEWED: GuiScrollBar(), improve mouse-click behaviour +* REVIEWED: Library header info, more info, better organized +* REDESIGNED: GuiTextBox() to support cursor movement +* REDESIGNED: GuiDrawText() to divide drawing by lines +* +* 3.2 (22-May-2022) RENAMED: Some enum values, for unification, avoiding prefixes +* REMOVED: GuiScrollBar(), only internal +* REDESIGNED: GuiPanel() to support text parameter +* REDESIGNED: GuiScrollPanel() to support text parameter +* REDESIGNED: GuiColorPicker() to support text parameter +* REDESIGNED: GuiColorPanel() to support text parameter +* REDESIGNED: GuiColorBarAlpha() to support text parameter +* REDESIGNED: GuiColorBarHue() to support text parameter +* REDESIGNED: GuiTextInputBox() to support password +* +* 3.1 (12-Jan-2022) REVIEWED: Default style for consistency (aligned with rGuiLayout v2.5 tool) +* REVIEWED: GuiLoadStyle() to support compressed font atlas image data and unload previous textures +* REVIEWED: External icons usage logic +* REVIEWED: GuiLine() for centered alignment when including text +* RENAMED: Multiple controls properties definitions to prepend RAYGUI_ +* RENAMED: RICON_ references to RAYGUI_ICON_ for library consistency +* Projects updated and multiple tweaks +* +* 3.0 (04-Nov-2021) Integrated ricons data to avoid external file +* REDESIGNED: GuiTextBoxMulti() +* REMOVED: GuiImageButton*() +* Multiple minor tweaks and bugs corrected +* +* 2.9 (17-Mar-2021) REMOVED: Tooltip API +* 2.8 (03-May-2020) Centralized rectangles drawing to GuiDrawRectangle() +* 2.7 (20-Feb-2020) ADDED: Possible tooltips API +* 2.6 (09-Sep-2019) ADDED: GuiTextInputBox() +* REDESIGNED: GuiListView*(), GuiDropdownBox(), GuiSlider*(), GuiProgressBar(), GuiMessageBox() +* REVIEWED: GuiTextBox(), GuiSpinner(), GuiValueBox(), GuiLoadStyle() +* Replaced property INNER_PADDING by TEXT_PADDING, renamed some properties +* ADDED: 8 new custom styles ready to use +* Multiple minor tweaks and bugs corrected +* +* 2.5 (28-May-2019) Implemented extended GuiTextBox(), GuiValueBox(), GuiSpinner() +* 2.3 (29-Apr-2019) ADDED: rIcons auxiliar library and support for it, multiple controls reviewed +* Refactor all controls drawing mechanism to use control state +* 2.2 (05-Feb-2019) ADDED: GuiScrollBar(), GuiScrollPanel(), reviewed GuiListView(), removed Gui*Ex() controls +* 2.1 (26-Dec-2018) REDESIGNED: GuiCheckBox(), GuiComboBox(), GuiDropdownBox(), GuiToggleGroup() > Use combined text string +* REDESIGNED: Style system (breaking change) +* 2.0 (08-Nov-2018) ADDED: Support controls guiLock and custom fonts +* REVIEWED: GuiComboBox(), GuiListView()... +* 1.9 (09-Oct-2018) REVIEWED: GuiGrid(), GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()... +* 1.8 (01-May-2018) Lot of rework and redesign to align with rGuiStyler and rGuiLayout +* 1.5 (21-Jun-2017) Working in an improved styles system +* 1.4 (15-Jun-2017) Rewritten all GUI functions (removed useless ones) +* 1.3 (12-Jun-2017) Complete redesign of style system +* 1.1 (01-Jun-2017) Complete review of the library +* 1.0 (07-Jun-2016) Converted to header-only by Ramon Santamaria +* 0.9 (07-Mar-2016) Reviewed and tested by Albert Martos, Ian Eito, Sergio Martinez and Ramon Santamaria +* 0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria +* +* DEPENDENCIES: +* raylib 5.6-dev - Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing +* +* STANDALONE MODE: +* By default raygui depends on raylib mostly for the inputs and the drawing functionality but that dependency can be disabled +* with the config flag RAYGUI_STANDALONE. In that case is up to the user to provide another backend to cover library needs +* +* The following functions should be redefined for a custom backend: +* +* - Vector2 GetMousePosition(void); +* - float GetMouseWheelMove(void); +* - bool IsMouseButtonDown(int button); +* - bool IsMouseButtonPressed(int button); +* - bool IsMouseButtonReleased(int button); +* - bool IsKeyDown(int key); +* - bool IsKeyPressed(int key); +* - int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox() +* +* - void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle() +* - void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() +* +* - Font GetFontDefault(void); // -- GuiLoadStyleDefault() +* - Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle() +* - Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image +* - void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization) +* - char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data +* - void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data +* - const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs +* - int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list +* - void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list +* - unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle() +* +* CONTRIBUTORS: +* Ramon Santamaria: Supervision, review, redesign, update and maintenance +* Vlad Adrian: Complete rewrite of GuiTextBox() to support extended features (2019) +* Sergio Martinez: Review, testing (2015) and redesign of multiple controls (2018) +* Adria Arranz: Testing and implementation of additional controls (2018) +* Jordi Jorba: Testing and implementation of additional controls (2018) +* Albert Martos: Review and testing of the library (2015) +* Ian Eito: Review and testing of the library (2015) +* Kevin Gato: Initial implementation of basic components (2014) +* Daniel Nicolas: Initial implementation of basic components (2014) +* +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2014-2026 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. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef RAYGUI_H +#define RAYGUI_H + +#define RAYGUI_VERSION_MAJOR 4 +#define RAYGUI_VERSION_MINOR 5 +#define RAYGUI_VERSION_PATCH 0 +#define RAYGUI_VERSION "5.0-dev" + +#if !defined(RAYGUI_STANDALONE) + #include "raylib.h" +#endif + +// Function specifiers in case library is build/used as a shared library (Windows) +// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll +#if defined(_WIN32) + #if defined(BUILD_LIBTYPE_SHARED) + #define RAYGUIAPI __declspec(dllexport) // Building the library as a Win32 shared library (.dll) + #elif defined(USE_LIBTYPE_SHARED) + #define RAYGUIAPI __declspec(dllimport) // Using the library as a Win32 shared library (.dll) + #endif + #define _CRT_SECURE_NO_WARNINGS // Disable unsafe warnings on scanf() functions in MSVC +#endif + +// Function specifiers definition +#ifndef RAYGUIAPI + #define RAYGUIAPI // Functions defined as 'extern' by default (implicit specifiers) +#endif + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// Simple log system to avoid printf() calls if required +// NOTE: Avoiding those calls, also avoids const strings memory usage +#define RAYGUI_SUPPORT_LOG_INFO +#if defined(RAYGUI_SUPPORT_LOG_INFO) + #define RAYGUI_LOG(...) printf(__VA_ARGS__) +#else + #define RAYGUI_LOG(...) +#endif + +// Macros to define required UI inputs, including mapping to gamepad controls +// TODO: Define additionally required macros for missing inputs +#if !defined(GUI_BUTTON_DOWN) + #define GUI_BUTTON_DOWN (IsMouseButtonDown(MOUSE_LEFT_BUTTON) || IsGamepadButtonDown(0, GAMEPAD_BUTTON_RIGHT_FACE_DOWN)) +#endif +#if !defined(GUI_BUTTON_DOWN_ALT) + // Mapping to alternative button down pressed + #define GUI_BUTTON_DOWN_ALT (IsMouseButtonDown(MOUSE_RIGHT_BUTTON) || IsGamepadButtonDown(0, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT)) +#endif +#if !defined(GUI_BUTTON_PRESSED) + #define GUI_BUTTON_PRESSED (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsGamepadButtonPressed(0, GAMEPAD_BUTTON_RIGHT_FACE_DOWN)) +#endif +// TODO: WARNING: GuiTabBar() still requires IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON) +#if !defined(GUI_BUTTON_RELEASED) + #define GUI_BUTTON_RELEASED (IsMouseButtonReleased(MOUSE_LEFT_BUTTON) || IsGamepadButtonReleased(0, GAMEPAD_BUTTON_RIGHT_FACE_DOWN)) +#endif +#if !defined(GUI_SCROLL_DELTA) + // Mapping to scroll delta changes + // TODO: Review inconsistencies between platforms + #if defined(PLATFORM_WEB) + // NOTE: Gamepad axis triggers not detected on web platform + #define GUI_SCROLL_DELTA ((float)IsGamepadButtonDown(0, GAMEPAD_BUTTON_RIGHT_TRIGGER_2) - (float)IsGamepadButtonDown(0, GAMEPAD_BUTTON_LEFT_TRIGGER_2)) + #else + #define GUI_SCROLL_DELTA (GetMouseWheelMove() + (GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_TRIGGER) + 1) - (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_TRIGGER) + 1)) + #endif +#endif +#if !defined(GUI_POINTER_POSITION) + #define GUI_POINTER_POSITION GetMousePosition() +#endif +#if !defined(GUI_KEY_DOWN) + #define GUI_KEY_DOWN(key) IsKeyDown(key) +#endif +#if !defined(GUI_KEY_PRESSED) + #define GUI_KEY_PRESSED(key) IsKeyPressed(key) +#endif +#if !defined(GUI_INPUT_KEY) + #define GUI_INPUT_KEY GetCharPressed() +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +// NOTE: Some types are required for RAYGUI_STANDALONE usage +//---------------------------------------------------------------------------------- +#if defined(RAYGUI_STANDALONE) + #ifndef __cplusplus + // Boolean type + #ifndef true + typedef enum { false, true } bool; + #endif + #endif + + // Vector2 type + typedef struct Vector2 { + float x; + float y; + } Vector2; + + // Vector3 type // -- ConvertHSVtoRGB(), ConvertRGBtoHSV() + typedef struct Vector3 { + float x; + float y; + float z; + } Vector3; + + // Color type, RGBA (32bit) + typedef struct Color { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + } Color; + + // Rectangle type + typedef struct Rectangle { + float x; + float y; + float width; + float height; + } Rectangle; + + // TODO: Texture2D type is very coupled to raylib, required by Font type + // It should be redesigned to be provided by user + typedef struct Texture { + unsigned int id; // OpenGL texture id + int width; // Texture base width + int height; // Texture base height + int mipmaps; // Mipmap levels, 1 by default + int format; // Data format (PixelFormat type) + } Texture; + + // Texture2D, same as Texture + typedef Texture Texture2D; + + // Image, pixel data stored in CPU memory (RAM) + typedef struct Image { + void *data; // Image raw data + int width; // Image base width + int height; // Image base height + int mipmaps; // Mipmap levels, 1 by default + int format; // Data format (PixelFormat type) + } Image; + + // GlyphInfo, font characters glyphs info + typedef struct GlyphInfo { + int value; // Character value (Unicode) + int offsetX; // Character offset X when drawing + int offsetY; // Character offset Y when drawing + int advanceX; // Character advance position X + Image image; // Character image data + } GlyphInfo; + + // TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle() + // It should be redesigned to be provided by user + typedef struct Font { + int baseSize; // Base size (default chars height) + int glyphCount; // Number of glyph characters + int glyphPadding; // Padding around the glyph characters + Texture2D texture; // Texture atlas containing the glyphs + Rectangle *recs; // Rectangles in texture for the glyphs + GlyphInfo *glyphs; // Glyphs info data + } Font; +#endif + +// Style property +// NOTE: Used when exporting style as code for convenience +typedef struct GuiStyleProp { + unsigned short controlId; // Control identifier + unsigned short propertyId; // Property identifier + int propertyValue; // Property value +} GuiStyleProp; + +/* +// Controls text style -NOT USED- +// NOTE: Text style is defined by control +typedef struct GuiTextStyle { + unsigned int size; + int charSpacing; + int lineSpacing; + int alignmentH; + int alignmentV; + int padding; +} GuiTextStyle; +*/ + +// Gui control state +typedef enum { + STATE_NORMAL = 0, + STATE_FOCUSED, + STATE_PRESSED, + STATE_DISABLED +} GuiState; + +// Gui control text alignment +typedef enum { + TEXT_ALIGN_LEFT = 0, + TEXT_ALIGN_CENTER, + TEXT_ALIGN_RIGHT +} GuiTextAlignment; + +// Gui control text alignment vertical +// NOTE: Text vertical position inside the text bounds +typedef enum { + TEXT_ALIGN_TOP = 0, + TEXT_ALIGN_MIDDLE, + TEXT_ALIGN_BOTTOM +} GuiTextAlignmentVertical; + +// Gui control text wrap mode +// NOTE: Useful for multiline text +typedef enum { + TEXT_WRAP_NONE = 0, + TEXT_WRAP_CHAR, + TEXT_WRAP_WORD +} GuiTextWrapMode; + +// Gui controls +typedef enum { + // Default -> populates to all controls when set + DEFAULT = 0, + + // Basic controls + LABEL, // Used also for: LABELBUTTON + BUTTON, + TOGGLE, // Used also for: TOGGLEGROUP + SLIDER, // Used also for: SLIDERBAR, TOGGLESLIDER + PROGRESSBAR, + CHECKBOX, + COMBOBOX, + DROPDOWNBOX, + TEXTBOX, // Used also for: TEXTBOXMULTI + VALUEBOX, + CONTROL11, + LISTVIEW, + COLORPICKER, + SCROLLBAR, + STATUSBAR +} GuiControl; + +// Gui base properties for every control +// NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties) +typedef enum { + BORDER_COLOR_NORMAL = 0, // Control border color in STATE_NORMAL + BASE_COLOR_NORMAL, // Control base color in STATE_NORMAL + TEXT_COLOR_NORMAL, // Control text color in STATE_NORMAL + BORDER_COLOR_FOCUSED, // Control border color in STATE_FOCUSED + BASE_COLOR_FOCUSED, // Control base color in STATE_FOCUSED + TEXT_COLOR_FOCUSED, // Control text color in STATE_FOCUSED + BORDER_COLOR_PRESSED, // Control border color in STATE_PRESSED + BASE_COLOR_PRESSED, // Control base color in STATE_PRESSED + TEXT_COLOR_PRESSED, // Control text color in STATE_PRESSED + BORDER_COLOR_DISABLED, // Control border color in STATE_DISABLED + BASE_COLOR_DISABLED, // Control base color in STATE_DISABLED + TEXT_COLOR_DISABLED, // Control text color in STATE_DISABLED + BORDER_WIDTH = 12, // Control border size, 0 for no border + //TEXT_SIZE, // Control text size (glyphs max height) -> GLOBAL for all controls + //TEXT_SPACING, // Control text spacing between glyphs -> GLOBAL for all controls + //TEXT_LINE_SPACING, // Control text spacing between lines -> GLOBAL for all controls + TEXT_PADDING = 13, // Control text padding, not considering border + TEXT_ALIGNMENT = 14, // Control text horizontal alignment inside control text bound (after border and padding) + //TEXT_WRAP_MODE // Control text wrap-mode inside text bounds -> GLOBAL for all controls +} GuiControlProperty; + +// TODO: Which text styling properties should be global or per-control? +// At this moment TEXT_PADDING and TEXT_ALIGNMENT is configured and saved per control while +// TEXT_SIZE, TEXT_SPACING, TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE are global and +// should be configured by user as needed while defining the UI layout + +// Gui extended properties depend on control +// NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default, max 8 properties) +//---------------------------------------------------------------------------------- +// DEFAULT extended properties +// NOTE: Those properties are common to all controls or global +// WARNING: Only 8 slots vailable for those properties by default +typedef enum { + TEXT_SIZE = 16, // Text size (glyphs max height) + TEXT_SPACING, // Text spacing between glyphs + LINE_COLOR, // Line control color + BACKGROUND_COLOR, // Background color + TEXT_LINE_SPACING, // Text spacing between lines + TEXT_ALIGNMENT_VERTICAL, // Text vertical alignment inside text bounds (after border and padding) + TEXT_WRAP_MODE // Text wrap-mode inside text bounds + //TEXT_DECORATION // Text decoration: 0-None, 1-Underline, 2-Line-through, 3-Overline + //TEXT_DECORATION_THICK // Text decoration line thickness +} GuiDefaultProperty; + +// Other possible text properties: +// TEXT_WEIGHT // Normal, Italic, Bold -> Requires specific font change +// TEXT_INDENT // Text indentation -> Now using TEXT_PADDING... + +// Label +//typedef enum { } GuiLabelProperty; + +// Button/Spinner +//typedef enum { } GuiButtonProperty; + +// Toggle/ToggleGroup +typedef enum { + GROUP_PADDING = 16, // ToggleGroup separation between toggles +} GuiToggleProperty; + +// Slider/SliderBar +typedef enum { + SLIDER_WIDTH = 16, // Slider size of internal bar + SLIDER_PADDING // Slider/SliderBar internal bar padding +} GuiSliderProperty; + +// ProgressBar +typedef enum { + PROGRESS_PADDING = 16, // ProgressBar internal padding + PROGRESS_SIDE, // ProgressBar increment side: 0-left->right, 1-right-left +} GuiProgressBarProperty; + +// ScrollBar +typedef enum { + ARROWS_SIZE = 16, // ScrollBar arrows size + ARROWS_VISIBLE, // ScrollBar arrows visible + SCROLL_SLIDER_PADDING, // ScrollBar slider internal padding + SCROLL_SLIDER_SIZE, // ScrollBar slider size + SCROLL_PADDING, // ScrollBar scroll padding from arrows + SCROLL_SPEED, // ScrollBar scrolling speed +} GuiScrollBarProperty; + +// CheckBox +typedef enum { + CHECK_PADDING = 16 // CheckBox internal check padding +} GuiCheckBoxProperty; + +// ComboBox +typedef enum { + COMBO_BUTTON_WIDTH = 16, // ComboBox right button width + COMBO_BUTTON_SPACING // ComboBox button separation +} GuiComboBoxProperty; + +// DropdownBox +typedef enum { + ARROW_PADDING = 16, // DropdownBox arrow separation from border and items + DROPDOWN_ITEMS_SPACING, // DropdownBox items separation + DROPDOWN_ARROW_HIDDEN, // DropdownBox arrow hidden + DROPDOWN_ROLL_UP // DropdownBox roll up flag (default rolls down) +} GuiDropdownBoxProperty; + +// TextBox/TextBoxMulti/ValueBox/Spinner +typedef enum { + TEXT_READONLY = 16, // TextBox in read-only mode: 0-text editable, 1-text no-editable +} GuiTextBoxProperty; + +// ValueBox/Spinner +typedef enum { + SPINNER_BUTTON_WIDTH = 16, // Spinner left/right buttons width + SPINNER_BUTTON_SPACING, // Spinner buttons separation +} GuiValueBoxProperty; + +// Control11 +//typedef enum { } GuiControl11Property; + +// ListView +typedef enum { + LIST_ITEMS_HEIGHT = 16, // ListView items height + LIST_ITEMS_SPACING, // ListView items separation + SCROLLBAR_WIDTH, // ListView scrollbar size (usually width) + SCROLLBAR_SIDE, // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE) + LIST_ITEMS_BORDER_NORMAL, // ListView items border enabled in normal state + LIST_ITEMS_BORDER_WIDTH // ListView items border width +} GuiListViewProperty; + +// ColorPicker +typedef enum { + COLOR_SELECTOR_SIZE = 16, + HUEBAR_WIDTH, // ColorPicker right hue bar width + HUEBAR_PADDING, // ColorPicker right hue bar separation from panel + HUEBAR_SELECTOR_HEIGHT, // ColorPicker right hue bar selector height + HUEBAR_SELECTOR_OVERFLOW // ColorPicker right hue bar selector overflow +} GuiColorPickerProperty; + +#define SCROLLBAR_LEFT_SIDE 0 +#define SCROLLBAR_RIGHT_SIDE 1 + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- + +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif + +// Global gui state control functions +RAYGUIAPI void GuiEnable(void); // Enable gui controls (global state) +RAYGUIAPI void GuiDisable(void); // Disable gui controls (global state) +RAYGUIAPI void GuiLock(void); // Lock gui controls (global state) +RAYGUIAPI void GuiUnlock(void); // Unlock gui controls (global state) +RAYGUIAPI bool GuiIsLocked(void); // Check if gui is locked (global state) +RAYGUIAPI void GuiSetAlpha(float alpha); // Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f +RAYGUIAPI void GuiSetState(int state); // Set gui state (global state) +RAYGUIAPI int GuiGetState(void); // Get gui state (global state) + +// Font set/get functions +RAYGUIAPI void GuiSetFont(Font font); // Set gui custom font (global state) +RAYGUIAPI Font GuiGetFont(void); // Get gui custom font (global state) + +// Style set/get functions +RAYGUIAPI void GuiSetStyle(int control, int property, int value); // Set one style property +RAYGUIAPI int GuiGetStyle(int control, int property); // Get one style property + +// Styles loading functions +RAYGUIAPI void GuiLoadStyle(const char *fileName); // Load style file over global style variable (.rgs) +RAYGUIAPI void GuiLoadStyleDefault(void); // Load style default over global style + +// Tooltips management functions +RAYGUIAPI void GuiEnableTooltip(void); // Enable gui tooltips (global state) +RAYGUIAPI void GuiDisableTooltip(void); // Disable gui tooltips (global state) +RAYGUIAPI void GuiSetTooltip(const char *tooltip); // Set tooltip string + +// Icons functionality +RAYGUIAPI const char *GuiIconText(int iconId, const char *text); // Get text with icon id prepended (if supported) +#if !defined(RAYGUI_NO_ICONS) +RAYGUIAPI void GuiSetIconScale(int scale); // Set default icon drawing size +RAYGUIAPI unsigned int *GuiGetIcons(void); // Get raygui icons data pointer +RAYGUIAPI char **GuiLoadIcons(const char *fileName, bool loadIconsName); // Load raygui icons file (.rgi) into internal icons data +RAYGUIAPI void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color); // Draw icon using pixel size at specified position +#endif + +// Utility functions +RAYGUIAPI int GuiGetTextWidth(const char *text); // Get text width considering gui style and icon size (if required) + +// Controls +//---------------------------------------------------------------------------------------------------------- +// Container/separator controls, useful for controls organization +RAYGUIAPI int GuiWindowBox(Rectangle bounds, const char *title); // Window Box control, shows a window that can be closed +RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name +RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text +RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls +RAYGUIAPI int GuiTabBar(Rectangle bounds, char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1 +RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control + +// Basic controls set +RAYGUIAPI int GuiLabel(Rectangle bounds, const char *text); // Label control +RAYGUIAPI int GuiButton(Rectangle bounds, const char *text); // Button control, returns true when clicked +RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text); // Label button control, returns true when clicked +RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active); // Toggle Button control +RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active); // Toggle Group control +RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active); // Toggle Slider control +RAYGUIAPI int GuiCheckBox(Rectangle bounds, const char *text, bool *checked); // Check Box control, returns true when active +RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); // Combo Box control + +RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode); // Dropdown Box control +RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control +RAYGUIAPI int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Value Box control, updates input text with numbers +RAYGUIAPI int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode); // Value box control for float values +RAYGUIAPI int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode); // Text Box control, updates input text + +RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control +RAYGUIAPI int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider Bar control +RAYGUIAPI int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Progress Bar control +RAYGUIAPI int GuiStatusBar(Rectangle bounds, const char *text); // Status Bar control, shows info text +RAYGUIAPI int GuiDummyRec(Rectangle bounds, const char *text); // Dummy control for placeholders +RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell); // Grid control + +// Advance controls set +RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control +RAYGUIAPI int GuiListViewEx(Rectangle bounds, char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters +RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message +RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret +RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls) +RAYGUIAPI int GuiColorPanel(Rectangle bounds, const char *text, Color *color); // Color Panel control +RAYGUIAPI int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha); // Color Bar Alpha control +RAYGUIAPI int GuiColorBarHue(Rectangle bounds, const char *text, float *value); // Color Bar Hue control +RAYGUIAPI int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Picker control that avoids conversion to RGB on each call (multiple color controls) +RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Panel control that updates Hue-Saturation-Value color value, used by GuiColorPickerHSV() +//---------------------------------------------------------------------------------------------------------- + +#if !defined(RAYGUI_NO_ICONS) + +#if !defined(RAYGUI_CUSTOM_ICONS) +//---------------------------------------------------------------------------------- +// Icons enumeration +//---------------------------------------------------------------------------------- +typedef enum { + ICON_NONE = 0, + ICON_FOLDER_FILE_OPEN = 1, + ICON_FILE_SAVE_CLASSIC = 2, + ICON_FOLDER_OPEN = 3, + ICON_FOLDER_SAVE = 4, + ICON_FILE_OPEN = 5, + ICON_FILE_SAVE = 6, + ICON_FILE_EXPORT = 7, + ICON_FILE_ADD = 8, + ICON_FILE_DELETE = 9, + ICON_FILETYPE_TEXT = 10, + ICON_FILETYPE_AUDIO = 11, + ICON_FILETYPE_IMAGE = 12, + ICON_FILETYPE_PLAY = 13, + ICON_FILETYPE_VIDEO = 14, + ICON_FILETYPE_INFO = 15, + ICON_FILE_COPY = 16, + ICON_FILE_CUT = 17, + ICON_FILE_PASTE = 18, + ICON_CURSOR_HAND = 19, + ICON_CURSOR_POINTER = 20, + ICON_CURSOR_CLASSIC = 21, + ICON_PENCIL = 22, + ICON_PENCIL_BIG = 23, + ICON_BRUSH_CLASSIC = 24, + ICON_BRUSH_PAINTER = 25, + ICON_WATER_DROP = 26, + ICON_COLOR_PICKER = 27, + ICON_RUBBER = 28, + ICON_COLOR_BUCKET = 29, + ICON_TEXT_T = 30, + ICON_TEXT_A = 31, + ICON_SCALE = 32, + ICON_RESIZE = 33, + ICON_FILTER_POINT = 34, + ICON_FILTER_BILINEAR = 35, + ICON_CROP = 36, + ICON_CROP_ALPHA = 37, + ICON_SQUARE_TOGGLE = 38, + ICON_SYMMETRY = 39, + ICON_SYMMETRY_HORIZONTAL = 40, + ICON_SYMMETRY_VERTICAL = 41, + ICON_LENS = 42, + ICON_LENS_BIG = 43, + ICON_EYE_ON = 44, + ICON_EYE_OFF = 45, + ICON_FILTER_TOP = 46, + ICON_FILTER = 47, + ICON_TARGET_POINT = 48, + ICON_TARGET_SMALL = 49, + ICON_TARGET_BIG = 50, + ICON_TARGET_MOVE = 51, + ICON_CURSOR_MOVE = 52, + ICON_CURSOR_SCALE = 53, + ICON_CURSOR_SCALE_RIGHT = 54, + ICON_CURSOR_SCALE_LEFT = 55, + ICON_UNDO = 56, + ICON_REDO = 57, + ICON_REREDO = 58, + ICON_MUTATE = 59, + ICON_ROTATE = 60, + ICON_REPEAT = 61, + ICON_SHUFFLE = 62, + ICON_EMPTYBOX = 63, + ICON_TARGET = 64, + ICON_TARGET_SMALL_FILL = 65, + ICON_TARGET_BIG_FILL = 66, + ICON_TARGET_MOVE_FILL = 67, + ICON_CURSOR_MOVE_FILL = 68, + ICON_CURSOR_SCALE_FILL = 69, + ICON_CURSOR_SCALE_RIGHT_FILL = 70, + ICON_CURSOR_SCALE_LEFT_FILL = 71, + ICON_UNDO_FILL = 72, + ICON_REDO_FILL = 73, + ICON_REREDO_FILL = 74, + ICON_MUTATE_FILL = 75, + ICON_ROTATE_FILL = 76, + ICON_REPEAT_FILL = 77, + ICON_SHUFFLE_FILL = 78, + ICON_EMPTYBOX_SMALL = 79, + ICON_BOX = 80, + ICON_BOX_TOP = 81, + ICON_BOX_TOP_RIGHT = 82, + ICON_BOX_RIGHT = 83, + ICON_BOX_BOTTOM_RIGHT = 84, + ICON_BOX_BOTTOM = 85, + ICON_BOX_BOTTOM_LEFT = 86, + ICON_BOX_LEFT = 87, + ICON_BOX_TOP_LEFT = 88, + ICON_BOX_CENTER = 89, + ICON_BOX_CIRCLE_MASK = 90, + ICON_POT = 91, + ICON_ALPHA_MULTIPLY = 92, + ICON_ALPHA_CLEAR = 93, + ICON_DITHERING = 94, + ICON_MIPMAPS = 95, + ICON_BOX_GRID = 96, + ICON_GRID = 97, + ICON_BOX_CORNERS_SMALL = 98, + ICON_BOX_CORNERS_BIG = 99, + ICON_FOUR_BOXES = 100, + ICON_GRID_FILL = 101, + ICON_BOX_MULTISIZE = 102, + ICON_ZOOM_SMALL = 103, + ICON_ZOOM_MEDIUM = 104, + ICON_ZOOM_BIG = 105, + ICON_ZOOM_ALL = 106, + ICON_ZOOM_CENTER = 107, + ICON_BOX_DOTS_SMALL = 108, + ICON_BOX_DOTS_BIG = 109, + ICON_BOX_CONCENTRIC = 110, + ICON_BOX_GRID_BIG = 111, + ICON_OK_TICK = 112, + ICON_CROSS = 113, + ICON_ARROW_LEFT = 114, + ICON_ARROW_RIGHT = 115, + ICON_ARROW_DOWN = 116, + ICON_ARROW_UP = 117, + ICON_ARROW_LEFT_FILL = 118, + ICON_ARROW_RIGHT_FILL = 119, + ICON_ARROW_DOWN_FILL = 120, + ICON_ARROW_UP_FILL = 121, + ICON_AUDIO = 122, + ICON_FX = 123, + ICON_WAVE = 124, + ICON_WAVE_SINUS = 125, + ICON_WAVE_SQUARE = 126, + ICON_WAVE_TRIANGULAR = 127, + ICON_CROSS_SMALL = 128, + ICON_PLAYER_PREVIOUS = 129, + ICON_PLAYER_PLAY_BACK = 130, + ICON_PLAYER_PLAY = 131, + ICON_PLAYER_PAUSE = 132, + ICON_PLAYER_STOP = 133, + ICON_PLAYER_NEXT = 134, + ICON_PLAYER_RECORD = 135, + ICON_MAGNET = 136, + ICON_LOCK_CLOSE = 137, + ICON_LOCK_OPEN = 138, + ICON_CLOCK = 139, + ICON_TOOLS = 140, + ICON_GEAR = 141, + ICON_GEAR_BIG = 142, + ICON_BIN = 143, + ICON_HAND_POINTER = 144, + ICON_LASER = 145, + ICON_COIN = 146, + ICON_EXPLOSION = 147, + ICON_1UP = 148, + ICON_PLAYER = 149, + ICON_PLAYER_JUMP = 150, + ICON_KEY = 151, + ICON_DEMON = 152, + ICON_TEXT_POPUP = 153, + ICON_GEAR_EX = 154, + ICON_CRACK = 155, + ICON_CRACK_POINTS = 156, + ICON_STAR = 157, + ICON_DOOR = 158, + ICON_EXIT = 159, + ICON_MODE_2D = 160, + ICON_MODE_3D = 161, + ICON_CUBE = 162, + ICON_CUBE_FACE_TOP = 163, + ICON_CUBE_FACE_LEFT = 164, + ICON_CUBE_FACE_FRONT = 165, + ICON_CUBE_FACE_BOTTOM = 166, + ICON_CUBE_FACE_RIGHT = 167, + ICON_CUBE_FACE_BACK = 168, + ICON_CAMERA = 169, + ICON_SPECIAL = 170, + ICON_LINK_NET = 171, + ICON_LINK_BOXES = 172, + ICON_LINK_MULTI = 173, + ICON_LINK = 174, + ICON_LINK_BROKE = 175, + ICON_TEXT_NOTES = 176, + ICON_NOTEBOOK = 177, + ICON_SUITCASE = 178, + ICON_SUITCASE_ZIP = 179, + ICON_MAILBOX = 180, + ICON_MONITOR = 181, + ICON_PRINTER = 182, + ICON_PHOTO_CAMERA = 183, + ICON_PHOTO_CAMERA_FLASH = 184, + ICON_HOUSE = 185, + ICON_HEART = 186, + ICON_CORNER = 187, + ICON_VERTICAL_BARS = 188, + ICON_VERTICAL_BARS_FILL = 189, + ICON_LIFE_BARS = 190, + ICON_INFO = 191, + ICON_CROSSLINE = 192, + ICON_HELP = 193, + ICON_FILETYPE_ALPHA = 194, + ICON_FILETYPE_HOME = 195, + ICON_LAYERS_VISIBLE = 196, + ICON_LAYERS = 197, + ICON_WINDOW = 198, + ICON_HIDPI = 199, + ICON_FILETYPE_BINARY = 200, + ICON_HEX = 201, + ICON_SHIELD = 202, + ICON_FILE_NEW = 203, + ICON_FOLDER_ADD = 204, + ICON_ALARM = 205, + ICON_CPU = 206, + ICON_ROM = 207, + ICON_STEP_OVER = 208, + ICON_STEP_INTO = 209, + ICON_STEP_OUT = 210, + ICON_RESTART = 211, + ICON_BREAKPOINT_ON = 212, + ICON_BREAKPOINT_OFF = 213, + ICON_BURGER_MENU = 214, + ICON_CASE_SENSITIVE = 215, + ICON_REG_EXP = 216, + ICON_FOLDER = 217, + ICON_FILE = 218, + ICON_SAND_TIMER = 219, + ICON_WARNING = 220, + ICON_HELP_BOX = 221, + ICON_INFO_BOX = 222, + ICON_PRIORITY = 223, + ICON_LAYERS_ISO = 224, + ICON_LAYERS2 = 225, + ICON_MLAYERS = 226, + ICON_MAPS = 227, + ICON_HOT = 228, + ICON_LABEL = 229, + ICON_NAME_ID = 230, + ICON_SLICING = 231, + ICON_MANUAL_CONTROL = 232, + ICON_COLLISION = 233, + ICON_CIRCLE_ADD = 234, + ICON_CIRCLE_ADD_FILL = 235, + ICON_CIRCLE_WARNING = 236, + ICON_CIRCLE_WARNING_FILL = 237, + ICON_BOX_MORE = 238, + ICON_BOX_MORE_FILL = 239, + ICON_BOX_MINUS = 240, + ICON_BOX_MINUS_FILL = 241, + ICON_UNION = 242, + ICON_INTERSECTION = 243, + ICON_DIFFERENCE = 244, + ICON_SPHERE = 245, + ICON_CYLINDER = 246, + ICON_CONE = 247, + ICON_ELLIPSOID = 248, + ICON_CAPSULE = 249, + ICON_250 = 250, + ICON_251 = 251, + ICON_252 = 252, + ICON_253 = 253, + ICON_254 = 254, + ICON_255 = 255 +} GuiIconName; +#endif + +#endif + +#if defined(__cplusplus) +} // Prevents name mangling of functions +#endif + +#endif // RAYGUI_H + +/*********************************************************************************** +* +* RAYGUI IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RAYGUI_IMPLEMENTATION) + +#include // required for: isspace() [GuiTextBox()] +#include // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), snprintf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()] +#include // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy() +#include // Required for: va_list, va_start(), vfprintf(), va_end() [TextFormat()] +#include // Required for: roundf() [GuiColorPicker()] + +// Allow custom memory allocators +#if defined(RAYGUI_MALLOC) || defined(RAYGUI_CALLOC) || defined(RAYGUI_FREE) + #if !defined(RAYGUI_MALLOC) || !defined(RAYGUI_CALLOC) || !defined(RAYGUI_FREE) + #error "RAYGUI: if RAYGUI_MALLOC, RAYGUI_CALLOC, or RAYGUI_FREE is customized, all three must be customized" + #endif +#else + #include // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()] + + #define RAYGUI_MALLOC(sz) malloc(sz) + #define RAYGUI_CALLOC(n,sz) calloc(n,sz) + #define RAYGUI_FREE(p) free(p) +#endif + +#ifdef __cplusplus + #define RAYGUI_CLITERAL(name) name +#else + #define RAYGUI_CLITERAL(name) (name) +#endif + +// Check if two rectangles are equal, used to validate a slider bounds as an id +#ifndef CHECK_BOUNDS_ID + #define CHECK_BOUNDS_ID(src, dst) (((int)src.x == (int)dst.x) && ((int)src.y == (int)dst.y) && ((int)src.width == (int)dst.width) && ((int)src.height == (int)dst.height)) +#endif + +#if !defined(RAYGUI_NO_ICONS) && !defined(RAYGUI_CUSTOM_ICONS) + +// Embedded icons, no external file provided +#define RAYGUI_ICON_SIZE 16 // Size of icons in pixels (squared) +#define RAYGUI_ICON_MAX_ICONS 256 // Maximum number of icons +#define RAYGUI_ICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id + +// Icons data is defined by bit array (every bit represents one pixel) +// Those arrays are stored as unsigned int data arrays, so, +// every array element defines 32 pixels (bits) of information +// One icon is defined by 8 int, (8 int*32 bit = 256 bit = 16*16 pixels) +// NOTE: Number of elemens depend on RAYGUI_ICON_SIZE (by default 16x16 pixels) +#define RAYGUI_ICON_DATA_ELEMENTS (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32) + +//---------------------------------------------------------------------------------- +// Icons data for all gui possible icons (allocated on data segment by default) +// +// NOTE 1: Every icon is codified in binary form, using 1 bit per pixel, so, +// every 16x16 icon requires 8 integers (16*16/32) to be stored +// +// NOTE 2: A different icon set could be loaded over this array using GuiLoadIcons(), +// but loaded icons set must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS +// +// guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB +//---------------------------------------------------------------------------------- +static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_NONE + 0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe, // ICON_FOLDER_FILE_OPEN + 0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe, // ICON_FILE_SAVE_CLASSIC + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024002, 0x44424282, 0x793e4102, 0x00000100, // ICON_FOLDER_OPEN + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024102, 0x44424102, 0x793e4282, 0x00000000, // ICON_FOLDER_SAVE + 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x24442284, 0x21042104, 0x20042104, 0x00003ffc, // ICON_FILE_OPEN + 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x21042104, 0x22842444, 0x20042104, 0x00003ffc, // ICON_FILE_SAVE + 0x3ff00000, 0x201c2010, 0x00042004, 0x20041004, 0x20844784, 0x00841384, 0x20042784, 0x00003ffc, // ICON_FILE_EXPORT + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x22042204, 0x22042f84, 0x20042204, 0x00003ffc, // ICON_FILE_ADD + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x25042884, 0x25042204, 0x20042884, 0x00003ffc, // ICON_FILE_DELETE + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_FILETYPE_TEXT + 0x3ff00000, 0x201c2010, 0x27042004, 0x244424c4, 0x26442444, 0x20642664, 0x20042004, 0x00003ffc, // ICON_FILETYPE_AUDIO + 0x3ff00000, 0x201c2010, 0x26042604, 0x20042004, 0x35442884, 0x2414222c, 0x20042004, 0x00003ffc, // ICON_FILETYPE_IMAGE + 0x3ff00000, 0x201c2010, 0x20c42004, 0x22442144, 0x22442444, 0x20c42144, 0x20042004, 0x00003ffc, // ICON_FILETYPE_PLAY + 0x3ff00000, 0x3ffc2ff0, 0x3f3c2ff4, 0x3dbc2eb4, 0x3dbc2bb4, 0x3f3c2eb4, 0x3ffc2ff4, 0x00002ff4, // ICON_FILETYPE_VIDEO + 0x3ff00000, 0x201c2010, 0x21842184, 0x21842004, 0x21842184, 0x21842184, 0x20042184, 0x00003ffc, // ICON_FILETYPE_INFO + 0x0ff00000, 0x381c0810, 0x28042804, 0x28042804, 0x28042804, 0x28042804, 0x20102ffc, 0x00003ff0, // ICON_FILE_COPY + 0x00000000, 0x701c0000, 0x079c1e14, 0x55a000f0, 0x079c00f0, 0x701c1e14, 0x00000000, 0x00000000, // ICON_FILE_CUT + 0x01c00000, 0x13e41bec, 0x3f841004, 0x204420c4, 0x20442044, 0x20442044, 0x207c2044, 0x00003fc0, // ICON_FILE_PASTE + 0x00000000, 0x3aa00fe0, 0x2abc2aa0, 0x2aa42aa4, 0x20042aa4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_CURSOR_HAND + 0x00000000, 0x003c000c, 0x030800c8, 0x30100c10, 0x10202020, 0x04400840, 0x01800280, 0x00000000, // ICON_CURSOR_POINTER + 0x00000000, 0x00180000, 0x01f00078, 0x03e007f0, 0x07c003e0, 0x04000e40, 0x00000000, 0x00000000, // ICON_CURSOR_CLASSIC + 0x00000000, 0x04000000, 0x11000a00, 0x04400a80, 0x01100220, 0x00580088, 0x00000038, 0x00000000, // ICON_PENCIL + 0x04000000, 0x15000a00, 0x50402880, 0x14102820, 0x05040a08, 0x015c028c, 0x007c00bc, 0x00000000, // ICON_PENCIL_BIG + 0x01c00000, 0x01400140, 0x01400140, 0x0ff80140, 0x0ff80808, 0x0aa80808, 0x0aa80aa8, 0x00000ff8, // ICON_BRUSH_CLASSIC + 0x1ffc0000, 0x5ffc7ffe, 0x40004000, 0x00807f80, 0x01c001c0, 0x01c001c0, 0x01c001c0, 0x00000080, // ICON_BRUSH_PAINTER + 0x00000000, 0x00800000, 0x01c00080, 0x03e001c0, 0x07f003e0, 0x036006f0, 0x000001c0, 0x00000000, // ICON_WATER_DROP + 0x00000000, 0x3e003800, 0x1f803f80, 0x0c201e40, 0x02080c10, 0x00840104, 0x00380044, 0x00000000, // ICON_COLOR_PICKER + 0x00000000, 0x07800300, 0x1fe00fc0, 0x3f883fd0, 0x0e021f04, 0x02040402, 0x00f00108, 0x00000000, // ICON_RUBBER + 0x00c00000, 0x02800140, 0x08200440, 0x20081010, 0x2ffe3004, 0x03f807fc, 0x00e001f0, 0x00000040, // ICON_COLOR_BUCKET + 0x00000000, 0x21843ffc, 0x01800180, 0x01800180, 0x01800180, 0x01800180, 0x03c00180, 0x00000000, // ICON_TEXT_T + 0x00800000, 0x01400180, 0x06200340, 0x0c100620, 0x1ff80c10, 0x380c1808, 0x70067004, 0x0000f80f, // ICON_TEXT_A + 0x78000000, 0x50004000, 0x00004800, 0x03c003c0, 0x03c003c0, 0x00100000, 0x0002000a, 0x0000000e, // ICON_SCALE + 0x75560000, 0x5e004002, 0x54001002, 0x41001202, 0x408200fe, 0x40820082, 0x40820082, 0x00006afe, // ICON_RESIZE + 0x00000000, 0x3f003f00, 0x3f003f00, 0x3f003f00, 0x00400080, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_POINT + 0x6d800000, 0x00004080, 0x40804080, 0x40800000, 0x00406d80, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_BILINEAR + 0x40080000, 0x1ffe2008, 0x14081008, 0x11081208, 0x10481088, 0x10081028, 0x10047ff8, 0x00001002, // ICON_CROP + 0x00100000, 0x3ffc0010, 0x2ab03550, 0x22b02550, 0x20b02150, 0x20302050, 0x2000fff0, 0x00002000, // ICON_CROP_ALPHA + 0x40000000, 0x1ff82000, 0x04082808, 0x01082208, 0x00482088, 0x00182028, 0x35542008, 0x00000002, // ICON_SQUARE_TOGGLE + 0x00000000, 0x02800280, 0x06c006c0, 0x0ea00ee0, 0x1e901eb0, 0x3e883e98, 0x7efc7e8c, 0x00000000, // ICON_SYMMETRY + 0x01000000, 0x05600100, 0x1d480d50, 0x7d423d44, 0x3d447d42, 0x0d501d48, 0x01000560, 0x00000100, // ICON_SYMMETRY_HORIZONTAL + 0x01800000, 0x04200240, 0x10080810, 0x00001ff8, 0x00007ffe, 0x0ff01ff8, 0x03c007e0, 0x00000180, // ICON_SYMMETRY_VERTICAL + 0x00000000, 0x010800f0, 0x02040204, 0x02040204, 0x07f00308, 0x1c000e00, 0x30003800, 0x00000000, // ICON_LENS + 0x00000000, 0x061803f0, 0x08240c0c, 0x08040814, 0x0c0c0804, 0x23f01618, 0x18002400, 0x00000000, // ICON_LENS_BIG + 0x00000000, 0x00000000, 0x1c7007c0, 0x638e3398, 0x1c703398, 0x000007c0, 0x00000000, 0x00000000, // ICON_EYE_ON + 0x00000000, 0x10002000, 0x04700fc0, 0x610e3218, 0x1c703098, 0x001007a0, 0x00000008, 0x00000000, // ICON_EYE_OFF + 0x00000000, 0x00007ffc, 0x40047ffc, 0x10102008, 0x04400820, 0x02800280, 0x02800280, 0x00000100, // ICON_FILTER_TOP + 0x00000000, 0x40027ffe, 0x10082004, 0x04200810, 0x02400240, 0x02400240, 0x01400240, 0x000000c0, // ICON_FILTER + 0x00800000, 0x00800080, 0x00000080, 0x3c9e0000, 0x00000000, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_POINT + 0x00800000, 0x00800080, 0x00800080, 0x3f7e01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL + 0x00800000, 0x00800080, 0x03e00080, 0x3e3e0220, 0x03e00220, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG + 0x01000000, 0x04400280, 0x01000100, 0x43842008, 0x43849ab2, 0x01002008, 0x04400100, 0x01000280, // ICON_TARGET_MOVE + 0x01000000, 0x04400280, 0x01000100, 0x41042108, 0x41049ff2, 0x01002108, 0x04400100, 0x01000280, // ICON_CURSOR_MOVE + 0x781e0000, 0x500a4002, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x4002500a, 0x0000781e, // ICON_CURSOR_SCALE + 0x00000000, 0x20003c00, 0x24002800, 0x01000200, 0x00400080, 0x00140024, 0x003c0004, 0x00000000, // ICON_CURSOR_SCALE_RIGHT + 0x00000000, 0x0004003c, 0x00240014, 0x00800040, 0x02000100, 0x28002400, 0x3c002000, 0x00000000, // ICON_CURSOR_SCALE_LEFT + 0x00000000, 0x00100020, 0x10101fc8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO + 0x00000000, 0x08000400, 0x080813f8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO + 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3f902020, 0x00400020, 0x00000000, // ICON_REREDO + 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3fc82010, 0x00200010, 0x00000000, // ICON_MUTATE + 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18101020, 0x00100fc8, 0x00000020, // ICON_ROTATE + 0x00000000, 0x04000200, 0x240429fc, 0x20042204, 0x20442004, 0x3f942024, 0x00400020, 0x00000000, // ICON_REPEAT + 0x00000000, 0x20001000, 0x22104c0e, 0x00801120, 0x11200040, 0x4c0e2210, 0x10002000, 0x00000000, // ICON_SHUFFLE + 0x7ffe0000, 0x50024002, 0x44024802, 0x41024202, 0x40424082, 0x40124022, 0x4002400a, 0x00007ffe, // ICON_EMPTYBOX + 0x00800000, 0x03e00080, 0x08080490, 0x3c9e0808, 0x08080808, 0x03e00490, 0x00800080, 0x00000000, // ICON_TARGET + 0x00800000, 0x00800080, 0x00800080, 0x3ffe01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL_FILL + 0x00800000, 0x00800080, 0x03e00080, 0x3ffe03e0, 0x03e003e0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG_FILL + 0x01000000, 0x07c00380, 0x01000100, 0x638c2008, 0x638cfbbe, 0x01002008, 0x07c00100, 0x01000380, // ICON_TARGET_MOVE_FILL + 0x01000000, 0x07c00380, 0x01000100, 0x610c2108, 0x610cfffe, 0x01002108, 0x07c00100, 0x01000380, // ICON_CURSOR_MOVE_FILL + 0x781e0000, 0x6006700e, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x700e6006, 0x0000781e, // ICON_CURSOR_SCALE_FILL + 0x00000000, 0x38003c00, 0x24003000, 0x01000200, 0x00400080, 0x000c0024, 0x003c001c, 0x00000000, // ICON_CURSOR_SCALE_RIGHT_FILL + 0x00000000, 0x001c003c, 0x0024000c, 0x00800040, 0x02000100, 0x30002400, 0x3c003800, 0x00000000, // ICON_CURSOR_SCALE_LEFT_FILL + 0x00000000, 0x00300020, 0x10301ff8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO_FILL + 0x00000000, 0x0c000400, 0x0c081ff8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO_FILL + 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3ff02060, 0x00400060, 0x00000000, // ICON_REREDO_FILL + 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3ff82030, 0x00200030, 0x00000000, // ICON_MUTATE_FILL + 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18301020, 0x00300ff8, 0x00000020, // ICON_ROTATE_FILL + 0x00000000, 0x06000200, 0x26042ffc, 0x20042204, 0x20442004, 0x3ff42064, 0x00400060, 0x00000000, // ICON_REPEAT_FILL + 0x00000000, 0x30001000, 0x32107c0e, 0x00801120, 0x11200040, 0x7c0e3210, 0x10003000, 0x00000000, // ICON_SHUFFLE_FILL + 0x00000000, 0x30043ffc, 0x24042804, 0x21042204, 0x20442084, 0x20142024, 0x3ffc200c, 0x00000000, // ICON_EMPTYBOX_SMALL + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX + 0x00000000, 0x23c43ffc, 0x23c423c4, 0x200423c4, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP + 0x00000000, 0x3e043ffc, 0x3e043e04, 0x20043e04, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x3e043e04, 0x3e043e04, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x3e042004, 0x3e043e04, 0x3ffc3e04, 0x00000000, // ICON_BOX_BOTTOM_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x23c42004, 0x23c423c4, 0x3ffc23c4, 0x00000000, // ICON_BOX_BOTTOM + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x207c2004, 0x207c207c, 0x3ffc207c, 0x00000000, // ICON_BOX_BOTTOM_LEFT + 0x00000000, 0x20043ffc, 0x20042004, 0x207c207c, 0x207c207c, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_LEFT + 0x00000000, 0x207c3ffc, 0x207c207c, 0x2004207c, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_LEFT + 0x00000000, 0x20043ffc, 0x20042004, 0x23c423c4, 0x23c423c4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_CENTER + 0x7ffe0000, 0x40024002, 0x47e24182, 0x4ff247e2, 0x47e24ff2, 0x418247e2, 0x40024002, 0x00007ffe, // ICON_BOX_CIRCLE_MASK + 0x7fff0000, 0x40014001, 0x40014001, 0x49555ddd, 0x4945495d, 0x400149c5, 0x40014001, 0x00007fff, // ICON_POT + 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x404e40ce, 0x48125432, 0x4006540e, 0x00007ffe, // ICON_ALPHA_MULTIPLY + 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x5c4e40ce, 0x44124432, 0x40065c0e, 0x00007ffe, // ICON_ALPHA_CLEAR + 0x7ffe0000, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x00007ffe, // ICON_DITHERING + 0x07fe0000, 0x1ffa0002, 0x7fea000a, 0x402a402a, 0x5b2a512a, 0x5128552a, 0x40205128, 0x00007fe0, // ICON_MIPMAPS + 0x00000000, 0x1ff80000, 0x12481248, 0x12481ff8, 0x1ff81248, 0x12481248, 0x00001ff8, 0x00000000, // ICON_BOX_GRID + 0x12480000, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x00001248, // ICON_GRID + 0x00000000, 0x1c380000, 0x1c3817e8, 0x08100810, 0x08100810, 0x17e81c38, 0x00001c38, 0x00000000, // ICON_BOX_CORNERS_SMALL + 0x700e0000, 0x700e5ffa, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x5ffa700e, 0x0000700e, // ICON_BOX_CORNERS_BIG + 0x3f7e0000, 0x21422142, 0x21422142, 0x00003f7e, 0x21423f7e, 0x21422142, 0x3f7e2142, 0x00000000, // ICON_FOUR_BOXES + 0x00000000, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x00000000, // ICON_GRID_FILL + 0x7ffe0000, 0x7ffe7ffe, 0x77fe7000, 0x77fe77fe, 0x777e7700, 0x777e777e, 0x777e777e, 0x0000777e, // ICON_BOX_MULTISIZE + 0x781e0000, 0x40024002, 0x00004002, 0x01800000, 0x00000180, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_SMALL + 0x781e0000, 0x40024002, 0x00004002, 0x03c003c0, 0x03c003c0, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_MEDIUM + 0x781e0000, 0x40024002, 0x07e04002, 0x07e007e0, 0x07e007e0, 0x400207e0, 0x40024002, 0x0000781e, // ICON_ZOOM_BIG + 0x781e0000, 0x5ffa4002, 0x1ff85ffa, 0x1ff81ff8, 0x1ff81ff8, 0x5ffa1ff8, 0x40025ffa, 0x0000781e, // ICON_ZOOM_ALL + 0x00000000, 0x2004381c, 0x00002004, 0x00000000, 0x00000000, 0x20040000, 0x381c2004, 0x00000000, // ICON_ZOOM_CENTER + 0x00000000, 0x1db80000, 0x10081008, 0x10080000, 0x00001008, 0x10081008, 0x00001db8, 0x00000000, // ICON_BOX_DOTS_SMALL + 0x35560000, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x35562002, 0x00000000, // ICON_BOX_DOTS_BIG + 0x7ffe0000, 0x40024002, 0x48124ff2, 0x49924812, 0x48124992, 0x4ff24812, 0x40024002, 0x00007ffe, // ICON_BOX_CONCENTRIC + 0x00000000, 0x10841ffc, 0x10841084, 0x1ffc1084, 0x10841084, 0x10841084, 0x00001ffc, 0x00000000, // ICON_BOX_GRID_BIG + 0x00000000, 0x00000000, 0x10000000, 0x04000800, 0x01040200, 0x00500088, 0x00000020, 0x00000000, // ICON_OK_TICK + 0x00000000, 0x10080000, 0x04200810, 0x01800240, 0x02400180, 0x08100420, 0x00001008, 0x00000000, // ICON_CROSS + 0x00000000, 0x02000000, 0x00800100, 0x00200040, 0x00200010, 0x00800040, 0x02000100, 0x00000000, // ICON_ARROW_LEFT + 0x00000000, 0x00400000, 0x01000080, 0x04000200, 0x04000800, 0x01000200, 0x00400080, 0x00000000, // ICON_ARROW_RIGHT + 0x00000000, 0x00000000, 0x00000000, 0x08081004, 0x02200410, 0x00800140, 0x00000000, 0x00000000, // ICON_ARROW_DOWN + 0x00000000, 0x00000000, 0x01400080, 0x04100220, 0x10040808, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP + 0x00000000, 0x02000000, 0x03800300, 0x03e003c0, 0x03e003f0, 0x038003c0, 0x02000300, 0x00000000, // ICON_ARROW_LEFT_FILL + 0x00000000, 0x00400000, 0x01c000c0, 0x07c003c0, 0x07c00fc0, 0x01c003c0, 0x004000c0, 0x00000000, // ICON_ARROW_RIGHT_FILL + 0x00000000, 0x00000000, 0x00000000, 0x0ff81ffc, 0x03e007f0, 0x008001c0, 0x00000000, 0x00000000, // ICON_ARROW_DOWN_FILL + 0x00000000, 0x00000000, 0x01c00080, 0x07f003e0, 0x1ffc0ff8, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP_FILL + 0x00000000, 0x18a008c0, 0x32881290, 0x24822686, 0x26862482, 0x12903288, 0x08c018a0, 0x00000000, // ICON_AUDIO + 0x00000000, 0x04800780, 0x004000c0, 0x662000f0, 0x08103c30, 0x130a0e18, 0x0000318e, 0x00000000, // ICON_FX + 0x00000000, 0x00800000, 0x08880888, 0x2aaa0a8a, 0x0a8a2aaa, 0x08880888, 0x00000080, 0x00000000, // ICON_WAVE + 0x00000000, 0x00600000, 0x01080090, 0x02040108, 0x42044204, 0x24022402, 0x00001800, 0x00000000, // ICON_WAVE_SINUS + 0x00000000, 0x07f80000, 0x04080408, 0x04080408, 0x04080408, 0x7c0e0408, 0x00000000, 0x00000000, // ICON_WAVE_SQUARE + 0x00000000, 0x00000000, 0x00a00040, 0x22084110, 0x08021404, 0x00000000, 0x00000000, 0x00000000, // ICON_WAVE_TRIANGULAR + 0x00000000, 0x00000000, 0x04200000, 0x01800240, 0x02400180, 0x00000420, 0x00000000, 0x00000000, // ICON_CROSS_SMALL + 0x00000000, 0x18380000, 0x12281428, 0x10a81128, 0x112810a8, 0x14281228, 0x00001838, 0x00000000, // ICON_PLAYER_PREVIOUS + 0x00000000, 0x18000000, 0x11801600, 0x10181060, 0x10601018, 0x16001180, 0x00001800, 0x00000000, // ICON_PLAYER_PLAY_BACK + 0x00000000, 0x00180000, 0x01880068, 0x18080608, 0x06081808, 0x00680188, 0x00000018, 0x00000000, // ICON_PLAYER_PLAY + 0x00000000, 0x1e780000, 0x12481248, 0x12481248, 0x12481248, 0x12481248, 0x00001e78, 0x00000000, // ICON_PLAYER_PAUSE + 0x00000000, 0x1ff80000, 0x10081008, 0x10081008, 0x10081008, 0x10081008, 0x00001ff8, 0x00000000, // ICON_PLAYER_STOP + 0x00000000, 0x1c180000, 0x14481428, 0x15081488, 0x14881508, 0x14281448, 0x00001c18, 0x00000000, // ICON_PLAYER_NEXT + 0x00000000, 0x03c00000, 0x08100420, 0x10081008, 0x10081008, 0x04200810, 0x000003c0, 0x00000000, // ICON_PLAYER_RECORD + 0x00000000, 0x0c3007e0, 0x13c81818, 0x14281668, 0x14281428, 0x1c381c38, 0x08102244, 0x00000000, // ICON_MAGNET + 0x07c00000, 0x08200820, 0x3ff80820, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_CLOSE + 0x07c00000, 0x08000800, 0x3ff80800, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_OPEN + 0x01c00000, 0x0c180770, 0x3086188c, 0x60832082, 0x60034781, 0x30062002, 0x0c18180c, 0x01c00770, // ICON_CLOCK + 0x0a200000, 0x1b201b20, 0x04200e20, 0x04200420, 0x04700420, 0x0e700e70, 0x0e700e70, 0x04200e70, // ICON_TOOLS + 0x01800000, 0x3bdc318c, 0x0ff01ff8, 0x7c3e1e78, 0x1e787c3e, 0x1ff80ff0, 0x318c3bdc, 0x00000180, // ICON_GEAR + 0x01800000, 0x3ffc318c, 0x1c381ff8, 0x781e1818, 0x1818781e, 0x1ff81c38, 0x318c3ffc, 0x00000180, // ICON_GEAR_BIG + 0x00000000, 0x08080ff8, 0x08081ffc, 0x0aa80aa8, 0x0aa80aa8, 0x0aa80aa8, 0x08080aa8, 0x00000ff8, // ICON_BIN + 0x00000000, 0x00000000, 0x20043ffc, 0x08043f84, 0x04040f84, 0x04040784, 0x000007fc, 0x00000000, // ICON_HAND_POINTER + 0x00000000, 0x24400400, 0x00001480, 0x6efe0e00, 0x00000e00, 0x24401480, 0x00000400, 0x00000000, // ICON_LASER + 0x00000000, 0x03c00000, 0x08300460, 0x11181118, 0x11181118, 0x04600830, 0x000003c0, 0x00000000, // ICON_COIN + 0x00000000, 0x10880080, 0x06c00810, 0x366c07e0, 0x07e00240, 0x00001768, 0x04200240, 0x00000000, // ICON_EXPLOSION + 0x00000000, 0x3d280000, 0x2528252c, 0x3d282528, 0x05280528, 0x05e80528, 0x00000000, 0x00000000, // ICON_1UP + 0x01800000, 0x03c003c0, 0x018003c0, 0x0ff007e0, 0x0bd00bd0, 0x0a500bd0, 0x02400240, 0x02400240, // ICON_PLAYER + 0x01800000, 0x03c003c0, 0x118013c0, 0x03c81ff8, 0x07c003c8, 0x04400440, 0x0c080478, 0x00000000, // ICON_PLAYER_JUMP + 0x3ff80000, 0x30183ff8, 0x30183018, 0x3ff83ff8, 0x03000300, 0x03c003c0, 0x03e00300, 0x000003e0, // ICON_KEY + 0x3ff80000, 0x3ff83ff8, 0x33983ff8, 0x3ff83398, 0x3ff83ff8, 0x00000540, 0x0fe00aa0, 0x00000fe0, // ICON_DEMON + 0x00000000, 0x0ff00000, 0x20041008, 0x25442004, 0x10082004, 0x06000bf0, 0x00000300, 0x00000000, // ICON_TEXT_POPUP + 0x00000000, 0x11440000, 0x07f00be8, 0x1c1c0e38, 0x1c1c0c18, 0x07f00e38, 0x11440be8, 0x00000000, // ICON_GEAR_EX + 0x00000000, 0x20080000, 0x0c601010, 0x07c00fe0, 0x07c007c0, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK + 0x00000000, 0x20080000, 0x0c601010, 0x04400fe0, 0x04405554, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK_POINTS + 0x00000000, 0x00800080, 0x01c001c0, 0x1ffc3ffe, 0x03e007f0, 0x07f003e0, 0x0c180770, 0x00000808, // ICON_STAR + 0x0ff00000, 0x08180810, 0x08100818, 0x0a100810, 0x08180810, 0x08100818, 0x08100810, 0x00001ff8, // ICON_DOOR + 0x0ff00000, 0x08100810, 0x08100810, 0x10100010, 0x4f902010, 0x10102010, 0x08100010, 0x00000ff0, // ICON_EXIT + 0x00040000, 0x001f000e, 0x0ef40004, 0x12f41284, 0x0ef41214, 0x10040004, 0x7ffc3004, 0x10003000, // ICON_MODE_2D + 0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000, // ICON_MODE_3D + 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE + 0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_TOP + 0x7fe00000, 0x50386030, 0x47c2483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe, // ICON_CUBE_FACE_LEFT + 0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe, // ICON_CUBE_FACE_FRONT + 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3bf27be2, 0x0bfe1bfa, 0x000007fe, // ICON_CUBE_FACE_BOTTOM + 0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe, // ICON_CUBE_FACE_RIGHT + 0x7fe00000, 0x6fe85ff0, 0x781e77e4, 0x7be27be2, 0x7be27be2, 0x24127be2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_BACK + 0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000, // ICON_CAMERA + 0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000, // ICON_SPECIAL + 0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800, // ICON_LINK_NET + 0x00000000, 0x44007c00, 0x45004600, 0x00627cbe, 0x00620022, 0x45007cbe, 0x44004600, 0x00007c00, // ICON_LINK_BOXES + 0x00000000, 0x0044007c, 0x0010007c, 0x3f100010, 0x3f1021f0, 0x3f100010, 0x3f0021f0, 0x00000000, // ICON_LINK_MULTI + 0x00000000, 0x0044007c, 0x00440044, 0x0010007c, 0x00100010, 0x44107c10, 0x440047f0, 0x00007c00, // ICON_LINK + 0x00000000, 0x0044007c, 0x00440044, 0x0000007c, 0x00000010, 0x44007c10, 0x44004550, 0x00007c00, // ICON_LINK_BROKE + 0x02a00000, 0x22a43ffc, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_TEXT_NOTES + 0x3ffc0000, 0x20042004, 0x245e27c4, 0x27c42444, 0x2004201e, 0x201e2004, 0x20042004, 0x00003ffc, // ICON_NOTEBOOK + 0x00000000, 0x07e00000, 0x04200420, 0x24243ffc, 0x24242424, 0x24242424, 0x3ffc2424, 0x00000000, // ICON_SUITCASE + 0x00000000, 0x0fe00000, 0x08200820, 0x40047ffc, 0x7ffc5554, 0x40045554, 0x7ffc4004, 0x00000000, // ICON_SUITCASE_ZIP + 0x00000000, 0x20043ffc, 0x3ffc2004, 0x13c81008, 0x100813c8, 0x10081008, 0x1ff81008, 0x00000000, // ICON_MAILBOX + 0x00000000, 0x40027ffe, 0x5ffa5ffa, 0x5ffa5ffa, 0x40025ffa, 0x03c07ffe, 0x1ff81ff8, 0x00000000, // ICON_MONITOR + 0x0ff00000, 0x6bfe7ffe, 0x7ffe7ffe, 0x68167ffe, 0x08106816, 0x08100810, 0x0ff00810, 0x00000000, // ICON_PRINTER + 0x3ff80000, 0xfffe2008, 0x870a8002, 0x904a888a, 0x904a904a, 0x870a888a, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA + 0x0fc00000, 0xfcfe0cd8, 0x8002fffe, 0x84428382, 0x84428442, 0x80028382, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA_FLASH + 0x00000000, 0x02400180, 0x08100420, 0x20041008, 0x23c42004, 0x22442244, 0x3ffc2244, 0x00000000, // ICON_HOUSE + 0x00000000, 0x1c700000, 0x3ff83ef8, 0x3ff83ff8, 0x0fe01ff0, 0x038007c0, 0x00000100, 0x00000000, // ICON_HEART + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe000c000, // ICON_CORNER + 0x00000000, 0x14001c00, 0x15c01400, 0x15401540, 0x155c1540, 0x15541554, 0x1ddc1554, 0x00000000, // ICON_VERTICAL_BARS + 0x00000000, 0x03000300, 0x1b001b00, 0x1b601b60, 0x1b6c1b60, 0x1b6c1b6c, 0x1b6c1b6c, 0x00000000, // ICON_VERTICAL_BARS_FILL + 0x00000000, 0x00000000, 0x403e7ffe, 0x7ffe403e, 0x7ffe0000, 0x43fe43fe, 0x00007ffe, 0x00000000, // ICON_LIFE_BARS + 0x7ffc0000, 0x43844004, 0x43844284, 0x43844004, 0x42844284, 0x42844284, 0x40044384, 0x00007ffc, // ICON_INFO + 0x40008000, 0x10002000, 0x04000800, 0x01000200, 0x00400080, 0x00100020, 0x00040008, 0x00010002, // ICON_CROSSLINE + 0x00000000, 0x1ff01ff0, 0x18301830, 0x1f001830, 0x03001f00, 0x00000300, 0x03000300, 0x00000000, // ICON_HELP + 0x3ff00000, 0x2abc3550, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x00003ffc, // ICON_FILETYPE_ALPHA + 0x3ff00000, 0x201c2010, 0x22442184, 0x28142424, 0x29942814, 0x2ff42994, 0x20042004, 0x00003ffc, // ICON_FILETYPE_HOME + 0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS_VISIBLE + 0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS + 0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_WINDOW + 0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000, // ICON_HIDPI + 0x3ff00000, 0x201c2010, 0x2a842e84, 0x2e842a84, 0x2ba42004, 0x2aa42aa4, 0x20042ba4, 0x00003ffc, // ICON_FILETYPE_BINARY + 0x00000000, 0x00000000, 0x00120012, 0x4a5e4bd2, 0x485233d2, 0x00004bd2, 0x00000000, 0x00000000, // ICON_HEX + 0x01800000, 0x381c0660, 0x23c42004, 0x23c42044, 0x13c82204, 0x08101008, 0x02400420, 0x00000180, // ICON_SHIELD + 0x007e0000, 0x20023fc2, 0x40227fe2, 0x400a403a, 0x400a400a, 0x400a400a, 0x4008400e, 0x00007ff8, // ICON_FILE_NEW + 0x00000000, 0x0042007e, 0x40027fc2, 0x44024002, 0x5f024402, 0x44024402, 0x7ffe4002, 0x00000000, // ICON_FOLDER_ADD + 0x44220000, 0x12482244, 0xf3cf0000, 0x14280420, 0x48122424, 0x08100810, 0x1ff81008, 0x03c00420, // ICON_ALARM + 0x0aa00000, 0x1ff80aa0, 0x1068700e, 0x1008706e, 0x1008700e, 0x1008700e, 0x0aa01ff8, 0x00000aa0, // ICON_CPU + 0x07e00000, 0x04201db8, 0x04a01c38, 0x04a01d38, 0x04a01d38, 0x04a01d38, 0x04201d38, 0x000007e0, // ICON_ROM + 0x00000000, 0x03c00000, 0x3c382ff0, 0x3c04380c, 0x01800000, 0x03c003c0, 0x00000180, 0x00000000, // ICON_STEP_OVER + 0x01800000, 0x01800180, 0x01800180, 0x03c007e0, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_INTO + 0x01800000, 0x07e003c0, 0x01800180, 0x01800180, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_OUT + 0x00000000, 0x0ff003c0, 0x181c1c34, 0x303c301c, 0x30003000, 0x1c301800, 0x03c00ff0, 0x00000000, // ICON_RESTART + 0x00000000, 0x00000000, 0x07e003c0, 0x0ff00ff0, 0x0ff00ff0, 0x03c007e0, 0x00000000, 0x00000000, // ICON_BREAKPOINT_ON + 0x00000000, 0x00000000, 0x042003c0, 0x08100810, 0x08100810, 0x03c00420, 0x00000000, 0x00000000, // ICON_BREAKPOINT_OFF + 0x00000000, 0x00000000, 0x1ff81ff8, 0x1ff80000, 0x00001ff8, 0x1ff81ff8, 0x00000000, 0x00000000, // ICON_BURGER_MENU + 0x00000000, 0x00000000, 0x00880070, 0x0c880088, 0x1e8810f8, 0x3e881288, 0x00000000, 0x00000000, // ICON_CASE_SENSITIVE + 0x00000000, 0x02000000, 0x07000a80, 0x07001fc0, 0x02000a80, 0x00300030, 0x00000000, 0x00000000, // ICON_REG_EXP + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_FOLDER + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x00003ffc, // ICON_FILE + 0x1ff00000, 0x20082008, 0x17d02fe8, 0x05400ba0, 0x09200540, 0x23881010, 0x2fe827c8, 0x00001ff0, // ICON_SAND_TIMER + 0x01800000, 0x02400240, 0x05a00420, 0x09900990, 0x11881188, 0x21842004, 0x40024182, 0x00003ffc, // ICON_WARNING + 0x7ffe0000, 0x4ff24002, 0x4c324ff2, 0x4f824c02, 0x41824f82, 0x41824002, 0x40024182, 0x00007ffe, // ICON_HELP_BOX + 0x7ffe0000, 0x41824002, 0x40024182, 0x41824182, 0x41824182, 0x41824182, 0x40024182, 0x00007ffe, // ICON_INFO_BOX + 0x01800000, 0x04200240, 0x10080810, 0x7bde2004, 0x0a500a50, 0x08500bd0, 0x08100850, 0x00000ff0, // ICON_PRIORITY + 0x01800000, 0x18180660, 0x80016006, 0x98196006, 0x99996666, 0x19986666, 0x01800660, 0x00000000, // ICON_LAYERS_ISO + 0x07fe0000, 0x1c020402, 0x74021402, 0x54025402, 0x54025402, 0x500857fe, 0x40205ff8, 0x00007fe0, // ICON_LAYERS2 + 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x422a422a, 0x422e422a, 0x40384e28, 0x00007fe0, // ICON_MLAYERS + 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x5b2a512a, 0x512e552a, 0x40385128, 0x00007fe0, // ICON_MAPS + 0x04200000, 0x1cf00c60, 0x11f019f0, 0x0f3807b8, 0x1e3c0f3c, 0x1c1c1e1c, 0x1e3c1c1c, 0x00000f70, // ICON_HOT + 0x00000000, 0x20803f00, 0x2a202e40, 0x20082e10, 0x08021004, 0x02040402, 0x00900108, 0x00000060, // ICON_LABEL + 0x00000000, 0x042007e0, 0x47e27c3e, 0x4ffa4002, 0x47fa4002, 0x4ffa4002, 0x7ffe4002, 0x00000000, // ICON_NAME_ID + 0x7fe00000, 0x402e4020, 0x43ce5e0a, 0x40504078, 0x438e4078, 0x402e5e0a, 0x7fe04020, 0x00000000, // ICON_SLICING + 0x00000000, 0x40027ffe, 0x47c24002, 0x55425d42, 0x55725542, 0x50125552, 0x10105016, 0x00001ff0, // ICON_MANUAL_CONTROL + 0x7ffe0000, 0x43c24002, 0x48124422, 0x500a500a, 0x500a500a, 0x44224812, 0x400243c2, 0x00007ffe, // ICON_COLLISION + 0x03c00000, 0x10080c30, 0x21842184, 0x4ff24182, 0x41824ff2, 0x21842184, 0x0c301008, 0x000003c0, // ICON_CIRCLE_ADD + 0x03c00000, 0x1ff80ff0, 0x3e7c3e7c, 0x700e7e7e, 0x7e7e700e, 0x3e7c3e7c, 0x0ff01ff8, 0x000003c0, // ICON_CIRCLE_ADD_FILL + 0x03c00000, 0x10080c30, 0x21842184, 0x41824182, 0x40024182, 0x21842184, 0x0c301008, 0x000003c0, // ICON_CIRCLE_WARNING + 0x03c00000, 0x1ff80ff0, 0x3e7c3e7c, 0x7e7e7e7e, 0x7ffe7e7e, 0x3e7c3e7c, 0x0ff01ff8, 0x000003c0, // ICON_CIRCLE_WARNING_FILL + 0x00000000, 0x10041ffc, 0x10841004, 0x13e41084, 0x10841084, 0x10041004, 0x00001ffc, 0x00000000, // ICON_BOX_MORE + 0x00000000, 0x1ffc1ffc, 0x1f7c1ffc, 0x1c1c1f7c, 0x1f7c1f7c, 0x1ffc1ffc, 0x00001ffc, 0x00000000, // ICON_BOX_MORE_FILL + 0x00000000, 0x1ffc1ffc, 0x1ffc1ffc, 0x1c1c1ffc, 0x1ffc1ffc, 0x1ffc1ffc, 0x00001ffc, 0x00000000, // ICON_BOX_MINUS + 0x00000000, 0x10041ffc, 0x10041004, 0x13e41004, 0x10041004, 0x10041004, 0x00001ffc, 0x00000000, // ICON_BOX_MINUS_FILL + 0x07fe0000, 0x055606aa, 0x7ff606aa, 0x55766eba, 0x55766eaa, 0x55606ffe, 0x55606aa0, 0x00007fe0, // ICON_UNION + 0x07fe0000, 0x04020402, 0x7fe20402, 0x456246a2, 0x456246a2, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_INTERSECTION + 0x07fe0000, 0x055606aa, 0x7ff606aa, 0x4436442a, 0x4436442a, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_DIFFERENCE + 0x03c00000, 0x10080c30, 0x20042004, 0x60064002, 0x47e2581a, 0x20042004, 0x0c301008, 0x000003c0, // ICON_SPHERE + 0x03e00000, 0x08080410, 0x0c180808, 0x08080be8, 0x08080808, 0x08080808, 0x04100808, 0x000003e0, // ICON_CYLINDER + 0x00800000, 0x01400140, 0x02200220, 0x04100410, 0x08080808, 0x1c1c13e4, 0x08081004, 0x000007f0, // ICON_CONE + 0x00000000, 0x07e00000, 0x20841918, 0x40824082, 0x40824082, 0x19182084, 0x000007e0, 0x00000000, // ICON_ELLIPSOID + 0x00000000, 0x00000000, 0x20041ff8, 0x40024002, 0x40024002, 0x1ff82004, 0x00000000, 0x00000000, // ICON_CAPSULE + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_250 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_251 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_252 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_253 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_254 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_255 +}; + +// NOTE: A pointer to current icons array should be defined +static unsigned int *guiIconsPtr = guiIcons; + +#endif // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS + +#ifndef RAYGUI_ICON_SIZE + #define RAYGUI_ICON_SIZE 0 +#endif + +// WARNING: Those values define the total size of the style data array, +// if changed, previous saved styles could become incompatible +#define RAYGUI_MAX_CONTROLS 16 // Maximum number of controls +#define RAYGUI_MAX_PROPS_BASE 16 // Maximum number of base properties +#define RAYGUI_MAX_PROPS_EXTENDED 8 // Maximum number of extended properties + +//---------------------------------------------------------------------------------- +// Module Types and Structures Definition +//---------------------------------------------------------------------------------- +// Gui control property style color element +typedef enum { BORDER = 0, BASE, TEXT, OTHER } GuiPropertyElement; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +static GuiState guiState = STATE_NORMAL; // Gui global state, if !STATE_NORMAL, forces defined state + +static Font guiFont = { 0 }; // Gui current font (WARNING: highly coupled to raylib) +static bool guiLocked = false; // Gui lock state (no inputs processed) +static float guiAlpha = 1.0f; // Gui controls transparency + +static unsigned int guiIconScale = 1; // Gui icon default scale (if icons enabled) + +static bool guiTooltip = false; // Tooltip enabled/disabled +static const char *guiTooltipPtr = NULL; // Tooltip string pointer (string provided by user) + +static bool guiControlExclusiveMode = false; // Gui control exclusive mode (no inputs processed except current control) +static Rectangle guiControlExclusiveRec = { 0 }; // Gui control exclusive bounds rectangle, used as an unique identifier + +static int textBoxCursorIndex = 0; // Cursor index, shared by all GuiTextBox*() +//static int blinkCursorFrameCounter = 0; // Frame counter for cursor blinking +static int autoCursorCounter = 0; // Frame counter for automatic repeated cursor movement on key-down (cooldown and delay) + +//---------------------------------------------------------------------------------- +// Style data array for all gui style properties (allocated on data segment by default) +// +// NOTE 1: First set of BASE properties are generic to all controls but could be individually +// overwritten per control, first set of EXTENDED properties are generic to all controls and +// can not be overwritten individually but custom EXTENDED properties can be used by control +// +// NOTE 2: A new style set could be loaded over this array using GuiLoadStyle(), +// but default gui style could always be recovered with GuiLoadStyleDefault() +// +// guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB +//---------------------------------------------------------------------------------- +static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)] = { 0 }; + +static bool guiStyleLoaded = false; // Style loaded flag for lazy style initialization + +//---------------------------------------------------------------------------------- +// Standalone Mode Functions Declaration +// +// NOTE: raygui depend on some raylib input and drawing functions +// To use raygui as standalone library, below functions must be defined by the user +//---------------------------------------------------------------------------------- +#if defined(RAYGUI_STANDALONE) + +#define KEY_RIGHT 262 +#define KEY_LEFT 263 +#define KEY_DOWN 264 +#define KEY_UP 265 +#define KEY_BACKSPACE 259 +#define KEY_ENTER 257 + +#define MOUSE_LEFT_BUTTON 0 + +// Input required functions +//------------------------------------------------------------------------------- +static Vector2 GetMousePosition(void); +static float GetMouseWheelMove(void); +static bool IsMouseButtonDown(int button); +static bool IsMouseButtonPressed(int button); +static bool IsMouseButtonReleased(int button); + +static bool IsKeyDown(int key); +static bool IsKeyPressed(int key); +static int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox() +//------------------------------------------------------------------------------- + +// Drawing required functions +//------------------------------------------------------------------------------- +static void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle() +static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() +//------------------------------------------------------------------------------- + +// Text required functions +//------------------------------------------------------------------------------- +static Font GetFontDefault(void); // -- GuiLoadStyleDefault() +static Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle(), load font + +static Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image +static void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization) + +static char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data +static void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data + +static const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs + +static int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list +static void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list + +static unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle() +//------------------------------------------------------------------------------- + +// raylib functions already implemented in raygui +//------------------------------------------------------------------------------- +static Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value +static int ColorToInt(Color color); // Returns hexadecimal value for a Color +static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle +static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' +static char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings +static int TextToInteger(const char *text); // Get integer value from text +static float TextToFloat(const char *text); // Get float value from text + +static int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded text +static const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode codepoint into UTF-8 text (char array size returned as parameter) + +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2); // Draw rectangle vertical gradient +//------------------------------------------------------------------------------- + +#endif // RAYGUI_STANDALONE + +//---------------------------------------------------------------------------------- +// Module Internal Functions Declaration +//---------------------------------------------------------------------------------- +static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize); // Load style from memory (binary only) + +static Rectangle GetTextBounds(int control, Rectangle bounds); // Get text bounds considering control bounds +static const char *GetTextIcon(const char *text, int *iconId); // Get text icon if provided and move text cursor + +static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font +static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style + +static char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings +static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB +static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV + +static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue); // Scroll bar control, used by GuiScrollPanel() +static void GuiTooltip(Rectangle controlRec); // Draw tooltip using control rec position + +static Color GuiFade(Color color, float alpha); // Fade color by an alpha factor + +//---------------------------------------------------------------------------------- +// Gui Setup Functions Definition +//---------------------------------------------------------------------------------- +// Enable gui global state +// NOTE: Checking for STATE_DISABLED to avoid messing custom global state setups +void GuiEnable(void) { if (guiState == STATE_DISABLED) guiState = STATE_NORMAL; } + +// Disable gui global state +// NOTE: Checking for STATE_NORMAL to avoid messing custom global state setups +void GuiDisable(void) { if (guiState == STATE_NORMAL) guiState = STATE_DISABLED; } + +// Lock gui global state +void GuiLock(void) { guiLocked = true; } + +// Unlock gui global state +void GuiUnlock(void) { guiLocked = false; } + +// Check if gui is locked (global state) +bool GuiIsLocked(void) { return guiLocked; } + +// Set gui controls alpha global state +void GuiSetAlpha(float alpha) +{ + if (alpha < 0.0f) alpha = 0.0f; + else if (alpha > 1.0f) alpha = 1.0f; + + guiAlpha = alpha; +} + +// Set gui state (global state) +void GuiSetState(int state) { guiState = (GuiState)state; } + +// Get gui state (global state) +int GuiGetState(void) { return guiState; } + +// Set custom gui font +// NOTE: Font loading/unloading is external to raygui +void GuiSetFont(Font font) +{ + if (font.texture.id > 0) + { + // NOTE: If a font is tried to be set but default style has not been lazily loaded first, + // it will be overwritten, so default style loading needs to be forced first + if (!guiStyleLoaded) GuiLoadStyleDefault(); + + guiFont = font; + } +} + +// Get custom gui font +Font GuiGetFont(void) +{ + return guiFont; +} + +// Set control style property value +void GuiSetStyle(int control, int property, int value) +{ + if (!guiStyleLoaded) GuiLoadStyleDefault(); + guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value; + + // Default properties are propagated to all controls + if ((control == 0) && (property < RAYGUI_MAX_PROPS_BASE)) + { + for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) guiStyle[i*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value; + } +} + +// Get control style property value +int GuiGetStyle(int control, int property) +{ + if (!guiStyleLoaded) GuiLoadStyleDefault(); + return guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property]; +} + +//---------------------------------------------------------------------------------- +// Gui Controls Functions Definition +//---------------------------------------------------------------------------------- + +// Window Box control +int GuiWindowBox(Rectangle bounds, const char *title) +{ + // Window title bar height (including borders) + // NOTE: This define is also used by GuiMessageBox() and GuiTextInputBox() + #if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT) + #define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24 + #endif + + #if !defined(RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT) + #define RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT 18 + #endif + + int result = 0; + //GuiState state = guiState; + + int statusBarHeight = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT; + int statusBorderWidth = GuiGetStyle(STATUSBAR, BORDER_WIDTH); + + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)statusBarHeight }; + if (bounds.height < statusBarHeight*2.0f) bounds.height = statusBarHeight*2.0f; + + const float vPadding = statusBarHeight/2.0f - RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT/2.0f; + Rectangle windowPanel = { bounds.x, bounds.y + (float)statusBarHeight - (float)statusBorderWidth, bounds.width, bounds.height - (float)statusBarHeight + (float)statusBorderWidth }; + Rectangle closeButtonRec = { statusBar.x + statusBar.width - (float)statusBorderWidth - RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT - vPadding, + statusBar.y + vPadding, RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT, RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT }; + + // Update control + //-------------------------------------------------------------------- + // NOTE: Logic is directly managed by button + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiPanel(windowPanel, NULL); // Draw window base + GuiStatusBar(statusBar, title); // Draw window header as status bar + + // Draw window close button + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); +#if defined(RAYGUI_NO_ICONS) + result = GuiButton(closeButtonRec, "x"); +#else + result = GuiButton(closeButtonRec, GuiIconText(ICON_CROSS_SMALL, NULL)); +#endif + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment); + //-------------------------------------------------------------------- + + return result; // Window close button clicked: result = 1 +} + +// Group Box control with text name +int GuiGroupBox(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_GROUPBOX_LINE_THICK) + #define RAYGUI_GROUPBOX_LINE_THICK 1 + #endif + + int result = 0; + GuiState state = guiState; + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + + GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text); + //-------------------------------------------------------------------- + + return result; +} + +// Line control +int GuiLine(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_LINE_MARGIN_TEXT) + #define RAYGUI_LINE_MARGIN_TEXT 12 + #endif + #if !defined(RAYGUI_LINE_TEXT_PADDING) + #define RAYGUI_LINE_TEXT_PADDING 4 + #endif + + int result = 0; + GuiState state = guiState; + + Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)); + + // Draw control + //-------------------------------------------------------------------- + if (text == NULL) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, bounds.width, 1 }, 0, BLANK, color); + else + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(text) + 2; + textBounds.height = bounds.height; + textBounds.x = bounds.x + RAYGUI_LINE_MARGIN_TEXT; + textBounds.y = bounds.y; + + // Draw line with embedded text label: "--- text --------------" + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color); + GuiDrawText(text, textBounds, TEXT_ALIGN_LEFT, color); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + 12 + textBounds.width + 4, bounds.y + bounds.height/2, bounds.width - textBounds.width - RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color); + } + //-------------------------------------------------------------------- + + return result; +} + +// Panel control +int GuiPanel(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_PANEL_BORDER_WIDTH) + #define RAYGUI_PANEL_BORDER_WIDTH 1 + #endif + + int result = 0; + GuiState state = guiState; + + // Text will be drawn as a header bar (if provided) + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }; + if ((text != NULL) && (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f)) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f; + + if (text != NULL) + { + // Move panel bounds after the header bar + bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + } + + // Draw control + //-------------------------------------------------------------------- + if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar + + GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)), + GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BASE_COLOR_DISABLED : (int)BACKGROUND_COLOR))); + //-------------------------------------------------------------------- + + return result; +} + +// Tab Bar control +// NOTE: Using GuiToggle() for the TABS +int GuiTabBar(Rectangle bounds, char **text, int count, int *active) +{ + #define RAYGUI_TABBAR_ITEM_WIDTH 148 + + int result = -1; + //GuiState state = guiState; + + Rectangle tabBounds = { bounds.x, bounds.y, RAYGUI_TABBAR_ITEM_WIDTH, bounds.height }; + + if (*active < 0) *active = 0; + else if (*active > count - 1) *active = count - 1; + + int offsetX = 0; // Required in case tabs go out of screen + offsetX = (*active + 2)*RAYGUI_TABBAR_ITEM_WIDTH - GetScreenWidth(); + if (offsetX < 0) offsetX = 0; + + bool toggle = false; // Required for individual toggles + + // Draw control + //-------------------------------------------------------------------- + for (int i = 0; i < count; i++) + { + tabBounds.x = bounds.x + (RAYGUI_TABBAR_ITEM_WIDTH + 4)*i - offsetX; + + if (tabBounds.x < GetScreenWidth()) + { + // Draw tabs as toggle controls + int textAlignment = GuiGetStyle(TOGGLE, TEXT_ALIGNMENT); + int textPadding = GuiGetStyle(TOGGLE, TEXT_PADDING); + GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(TOGGLE, TEXT_PADDING, 8); + + if (i == (*active)) + { + toggle = true; + GuiToggle(tabBounds, text[i], &toggle); + } + else + { + toggle = false; + GuiToggle(tabBounds, text[i], &toggle); + if (toggle) *active = i; + } + + // Close tab with middle mouse button pressed + if (CheckCollisionPointRec(GUI_POINTER_POSITION, tabBounds) && IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) result = i; + + GuiSetStyle(TOGGLE, TEXT_PADDING, textPadding); + GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment); + + // Draw tab close button + // NOTE: Only draw close button for current tab: if (CheckCollisionPointRec(mousePosition, tabBounds)) + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); +#if defined(RAYGUI_NO_ICONS) + if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, "x")) result = i; +#else + if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, GuiIconText(ICON_CROSS_SMALL, NULL))) result = i; +#endif + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment); + } + } + + // Draw tab-bar bottom line + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, 1 }, 0, BLANK, GetColor(GuiGetStyle(TOGGLE, BORDER_COLOR_NORMAL))); + //-------------------------------------------------------------------- + + return result; // Return as result the current TAB closing requested +} + +// Scroll Panel control +int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view) +{ + #define RAYGUI_MIN_SCROLLBAR_WIDTH 40 + #define RAYGUI_MIN_SCROLLBAR_HEIGHT 40 + #define RAYGUI_MIN_MOUSE_WHEEL_SPEED 20 + + int result = 0; + GuiState state = guiState; + + Rectangle temp = { 0 }; + if (view == NULL) view = &temp; + + Vector2 scrollPos = { 0.0f, 0.0f }; + if (scroll != NULL) scrollPos = *scroll; + + // Text will be drawn as a header bar (if provided) + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }; + if (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f; + + if (text != NULL) + { + // Move panel bounds after the header bar + bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + 1; + } + + bool hasHorizontalScrollBar = (content.width > bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false; + bool hasVerticalScrollBar = (content.height > bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false; + + // Recheck to account for the other scrollbar being visible + if (!hasHorizontalScrollBar) hasHorizontalScrollBar = (hasVerticalScrollBar && (content.width > (bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false; + if (!hasVerticalScrollBar) hasVerticalScrollBar = (hasHorizontalScrollBar && (content.height > (bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false; + + int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; + int verticalScrollBarWidth = hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; + Rectangle horizontalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)horizontalScrollBarWidth + }; + Rectangle verticalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)), + (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)verticalScrollBarWidth, + (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) + }; + + // Make sure scroll bars have a minimum width/height + if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH) horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH; + if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT) verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT; + + // Calculate view area (area without the scrollbars) + *view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? + RAYGUI_CLITERAL(Rectangle){ bounds.x + verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth } : + RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth }; + + // Clip view area to the actual content size + if (view->width > content.width) view->width = content.width; + if (view->height > content.height) view->height = content.height; + + float horizontalMin = hasHorizontalScrollBar? ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH); + float horizontalMax = hasHorizontalScrollBar? content.width - bounds.width + (float)verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH) - (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)verticalScrollBarWidth : 0) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH); + float verticalMin = hasVerticalScrollBar? 0.0f : -1.0f; + float verticalMax = hasVerticalScrollBar? content.height - bounds.height + (float)horizontalScrollBarWidth + (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH); + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (GUI_BUTTON_DOWN) state = STATE_PRESSED; + else state = STATE_FOCUSED; + +#if defined(SUPPORT_SCROLLBAR_KEY_INPUT) + if (hasHorizontalScrollBar) + { + if (GUI_KEY_DOWN(KEY_RIGHT)) scrollPos.x -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + if (GUI_KEY_DOWN(KEY_LEFT)) scrollPos.x += GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + } + + if (hasVerticalScrollBar) + { + if (GUI_KEY_DOWN(KEY_DOWN)) scrollPos.y -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + if (GUI_KEY_DOWN(KEY_UP)) scrollPos.y += GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + } +#endif + float scrollDelta = GUI_SCROLL_DELTA; + + // Set scrolling speed with mouse wheel based on ratio between bounds and content + Vector2 scrollSpeed = { content.width/bounds.width, content.height/bounds.height }; + if (scrollSpeed.x < RAYGUI_MIN_MOUSE_WHEEL_SPEED) scrollSpeed.x = RAYGUI_MIN_MOUSE_WHEEL_SPEED; + if (scrollSpeed.y < RAYGUI_MIN_MOUSE_WHEEL_SPEED) scrollSpeed.y = RAYGUI_MIN_MOUSE_WHEEL_SPEED; + + // Horizontal and vertical scrolling with mouse wheel + if (hasHorizontalScrollBar && (GUI_KEY_DOWN(KEY_LEFT_CONTROL) || GUI_KEY_DOWN(KEY_LEFT_SHIFT))) scrollPos.x += scrollDelta*scrollSpeed.x; + else scrollPos.y += scrollDelta*scrollSpeed.y; // Vertical scroll + } + } + + // Normalize scroll values + if (scrollPos.x > -horizontalMin) scrollPos.x = -horizontalMin; + if (scrollPos.x < -horizontalMax) scrollPos.x = -horizontalMax; + if (scrollPos.y > -verticalMin) scrollPos.y = -verticalMin; + if (scrollPos.y < -verticalMax) scrollPos.y = -verticalMax; + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar + + GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + + // Save size of the scrollbar slider + const int slider = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); + + // Draw horizontal scrollbar if visible + if (hasHorizontalScrollBar) + { + // Change scrollbar slider size to show the diff in size between the content width and the widget width + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth)/(int)content.width)*((int)bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth))); + scrollPos.x = (float)-GuiScrollBar(horizontalScrollBar, (int)-scrollPos.x, (int)horizontalMin, (int)horizontalMax); + } + else scrollPos.x = 0.0f; + + // Draw vertical scrollbar if visible + if (hasVerticalScrollBar) + { + // Change scrollbar slider size to show the diff in size between the content height and the widget height + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)/(int)content.height)*((int)bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth))); + scrollPos.y = (float)-GuiScrollBar(verticalScrollBar, (int)-scrollPos.y, (int)verticalMin, (int)verticalMax); + } + else scrollPos.y = 0.0f; + + // Draw detail corner rectangle if both scroll bars are visible + if (hasHorizontalScrollBar && hasVerticalScrollBar) + { + Rectangle corner = { (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) + 2) : (horizontalScrollBar.x + horizontalScrollBar.width + 2), verticalScrollBar.y + verticalScrollBar.height + 2, (float)horizontalScrollBarWidth - 4, (float)verticalScrollBarWidth - 4 }; + GuiDrawRectangle(corner, 0, BLANK, GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3)))); + } + + // Draw scrollbar lines depending on current state + GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK); + + // Set scrollbar slider size back to the way it was before + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, slider); + //-------------------------------------------------------------------- + + if (scroll != NULL) *scroll = scrollPos; + + return result; +} + +// Label control +int GuiLabel(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + //... + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Button control, returns true when clicked +int GuiButton(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (GUI_BUTTON_DOWN) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (GUI_BUTTON_RELEASED) result = 1; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), GetColor(GuiGetStyle(BUTTON, BASE + (state*3)))); + GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), GetColor(GuiGetStyle(BUTTON, TEXT + (state*3)))); + + if (state == STATE_FOCUSED) GuiTooltip(bounds); + //------------------------------------------------------------------ + + return result; // Button pressed: result = 1 +} + +// Label button control +int GuiLabelButton(Rectangle bounds, const char *text) +{ + GuiState state = guiState; + bool pressed = false; + + // NOTE: Force bounds.width to be all text + float textWidth = (float)GuiGetTextWidth(text); + if ((bounds.width - 2*GuiGetStyle(LABEL, BORDER_WIDTH) - 2*GuiGetStyle(LABEL, TEXT_PADDING)) < textWidth) bounds.width = textWidth + 2*GuiGetStyle(LABEL, BORDER_WIDTH) + 2*GuiGetStyle(LABEL, TEXT_PADDING) + 2; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + // Check checkbox state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (GUI_BUTTON_DOWN) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (GUI_BUTTON_RELEASED) pressed = true; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return pressed; +} + +// Toggle Button control +int GuiToggle(Rectangle bounds, const char *text, bool *active) +{ + int result = 0; + GuiState state = guiState; + + bool temp = false; + if (active == NULL) active = &temp; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + // Check toggle button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (GUI_BUTTON_DOWN) state = STATE_PRESSED; + else if (GUI_BUTTON_RELEASED) + { + state = STATE_NORMAL; + *active = !(*active); + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_NORMAL) + { + GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, ((*active)? BORDER_COLOR_PRESSED : (BORDER + state*3)))), GetColor(GuiGetStyle(TOGGLE, ((*active)? BASE_COLOR_PRESSED : (BASE + state*3))))); + GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, ((*active)? TEXT_COLOR_PRESSED : (TEXT + state*3))))); + } + else + { + GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + state*3)), GetColor(GuiGetStyle(TOGGLE, BASE + state*3))); + GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, TEXT + state*3))); + } + + if (state == STATE_FOCUSED) GuiTooltip(bounds); + //-------------------------------------------------------------------- + + return result; +} + +// Toggle Group control +int GuiToggleGroup(Rectangle bounds, const char *text, int *active) +{ + #if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS) + #define RAYGUI_TOGGLEGROUP_MAX_ITEMS 32 + #endif + + int result = 0; + float initBoundsX = bounds.x; + + int temp = 0; + if (active == NULL) active = &temp; + + bool toggle = false; // Required for individual toggles + + // Get substrings items from text (items pointers) + int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 }; + int itemCount = 0; + char **items = GuiTextSplit(text, ';', &itemCount, rows); + + int prevRow = rows[0]; + + for (int i = 0; i < itemCount; i++) + { + if (prevRow != rows[i]) + { + bounds.x = initBoundsX; + bounds.y += (bounds.height + GuiGetStyle(TOGGLE, GROUP_PADDING)); + prevRow = rows[i]; + } + + if (i == (*active)) + { + toggle = true; + GuiToggle(bounds, items[i], &toggle); + } + else + { + toggle = false; + GuiToggle(bounds, items[i], &toggle); + if (toggle) *active = i; + } + + bounds.x += (bounds.width + GuiGetStyle(TOGGLE, GROUP_PADDING)); + } + + return result; +} + +// Toggle Slider control extended +int GuiToggleSlider(Rectangle bounds, const char *text, int *active) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + //bool toggle = false; // Required for individual toggles + + // Get substrings items from text (items pointers) + int itemCount = 0; + char **items = NULL; + + if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); + + Rectangle slider = { + 0, // Calculated later depending on the active toggle + bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING), + (bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - (itemCount + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING))/itemCount, + bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (GUI_BUTTON_DOWN) state = STATE_PRESSED; + else if (GUI_BUTTON_RELEASED) + { + state = STATE_PRESSED; + (*active)++; + result = 1; + } + else state = STATE_FOCUSED; + } + + if ((*active) && (state != STATE_FOCUSED)) state = STATE_PRESSED; + } + + if (*active >= itemCount) *active = 0; + slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH) + (*active + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING) + (*active)*slider.width; + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + (state*3))), + GetColor(GuiGetStyle(TOGGLE, BASE_COLOR_NORMAL))); + + // Draw internal slider + if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_FOCUSED))); + else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + + // Draw text in slider + if (text != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(text); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = slider.x + slider.width/2 - textBounds.width/2; + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(items[*active], textBounds, GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, TEXT + (state*3))), guiAlpha)); + } + //-------------------------------------------------------------------- + + return result; +} + +// Check Box control, returns 1 when state changed +int GuiCheckBox(Rectangle bounds, const char *text, bool *checked) +{ + int result = 0; + GuiState state = guiState; + + bool temp = false; + if (checked == NULL) checked = &temp; + + Rectangle textBounds = { 0 }; + + if (text != NULL) + { + textBounds.width = (float)GuiGetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(CHECKBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + Rectangle totalBounds = { + (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT)? textBounds.x : bounds.x, + bounds.y, + bounds.width + textBounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING), + bounds.height, + }; + + // Check checkbox state + if (CheckCollisionPointRec(mousePoint, totalBounds)) + { + if (GUI_BUTTON_DOWN) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (GUI_BUTTON_RELEASED) + { + *checked = !(*checked); + result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(CHECKBOX, BORDER_WIDTH), GetColor(GuiGetStyle(CHECKBOX, BORDER + (state*3))), BLANK); + + if (*checked) + { + Rectangle check = { bounds.x + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING), + bounds.y + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING), + bounds.width - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)), + bounds.height - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)) }; + GuiDrawRectangle(check, 0, BLANK, GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3))); + } + + GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Combo Box control +int GuiComboBox(Rectangle bounds, const char *text, int *active) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + bounds.width -= (GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH) + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING)); + + Rectangle selector = { (float)bounds.x + bounds.width + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING), + (float)bounds.y, (float)GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH), (float)bounds.height }; + + // Get substrings items from text (items pointers, lengths and count) + int itemCount = 0; + char **items = GuiTextSplit(text, ';', &itemCount, NULL); + + if (*active < 0) *active = 0; + else if (*active > (itemCount - 1)) *active = itemCount - 1; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiControlExclusiveMode) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + if (CheckCollisionPointRec(mousePoint, bounds) || + CheckCollisionPointRec(mousePoint, selector)) + { + if (GUI_BUTTON_PRESSED) + { + *active += 1; + if (*active >= itemCount) *active = 0; // Cyclic combobox + } + + if (GUI_BUTTON_DOWN) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + // Draw combo box main + GuiDrawRectangle(bounds, GuiGetStyle(COMBOBOX, BORDER_WIDTH), GetColor(GuiGetStyle(COMBOBOX, BORDER + (state*3))), GetColor(GuiGetStyle(COMBOBOX, BASE + (state*3)))); + GuiDrawText(items[*active], GetTextBounds(COMBOBOX, bounds), GuiGetStyle(COMBOBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(COMBOBOX, TEXT + (state*3)))); + + // Draw selector using a custom button + // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + GuiButton(selector, TextFormat("%i/%i", *active + 1, itemCount)); + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + //-------------------------------------------------------------------- + + return result; +} + +// Dropdown Box control +// NOTE: Returns mouse click +int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + int itemSelected = *active; + int itemFocused = -1; + + int direction = 0; // Dropdown box open direction: down (default) + if (GuiGetStyle(DROPDOWNBOX, DROPDOWN_ROLL_UP) == 1) direction = 1; // Up + + // Get substrings items from text (items pointers, lengths and count) + int itemCount = 0; + char **items = GuiTextSplit(text, ';', &itemCount, NULL); + + Rectangle boundsOpen = bounds; + boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + if (direction == 1) boundsOpen.y -= itemCount*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)) + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING); + + Rectangle itemBounds = bounds; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1) && !guiControlExclusiveMode) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + if (editMode) + { + state = STATE_PRESSED; + + // Check if mouse has been pressed or released outside limits + if (!CheckCollisionPointRec(mousePoint, boundsOpen)) + { + if (GUI_BUTTON_PRESSED || GUI_BUTTON_RELEASED) result = 1; + } + + // Check if already selected item has been pressed again + if (CheckCollisionPointRec(mousePoint, bounds) && GUI_BUTTON_PRESSED) result = 1; + + // Check focused and selected item + for (int i = 0; i < itemCount; i++) + { + // Update item rectangle y position for next item + if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + + if (CheckCollisionPointRec(mousePoint, itemBounds)) + { + itemFocused = i; + if (GUI_BUTTON_RELEASED) + { + itemSelected = i; + result = 1; // Item selected + } + break; + } + } + + itemBounds = bounds; + } + else + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (GUI_BUTTON_PRESSED) + { + result = 1; + state = STATE_PRESSED; + } + else state = STATE_FOCUSED; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (editMode) GuiPanel(boundsOpen, NULL); + + GuiDrawRectangle(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3))); + GuiDrawText(items[itemSelected], GetTextBounds(DROPDOWNBOX, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3))); + + if (editMode) + { + // Draw visible items + for (int i = 0; i < itemCount; i++) + { + // Update item rectangle y position for next item + if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + + if (i == itemSelected) + { + GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED))); + GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED))); + } + else if (i == itemFocused) + { + GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED))); + GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED))); + } + else GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL))); + } + } + + if (!GuiGetStyle(DROPDOWNBOX, DROPDOWN_ARROW_HIDDEN)) + { + // Draw arrows (using icon if available) +#if defined(RAYGUI_NO_ICONS) + GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); +#else + GuiDrawText(direction? "#121#" : "#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL +#endif + } + //-------------------------------------------------------------------- + + *active = itemSelected; + + // TODO: Use result to return more internal states: mouse-press out-of-bounds, mouse-press over selected-item... + return result; // Mouse click: result = 1 +} + +// Text Box control +// NOTE: Returns true on ENTER pressed (useful for data validation) +int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode) +{ + #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN) + #define RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN 20 // Frames to wait for autocursor movement + #endif + #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) + #define RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY 1 // Frames delay for autocursor movement + #endif + + int result = 0; + GuiState state = guiState; + + bool multiline = false; // TODO: Consider multiline text input + int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); + + Rectangle textBounds = GetTextBounds(TEXTBOX, bounds); + int textLength = (text != NULL)? (int)strlen(text) : 0; // Get current text length + int thisCursorIndex = textBoxCursorIndex; + if (thisCursorIndex > textLength) thisCursorIndex = textLength; + int textWidth = GuiGetTextWidth(text) - GuiGetTextWidth(text + thisCursorIndex); + int textIndexOffset = 0; // Text index offset to start drawing in the box + + // Cursor rectangle + // NOTE: Position X value should be updated + Rectangle cursor = { + textBounds.x + textWidth + GuiGetStyle(DEFAULT, TEXT_SPACING), + textBounds.y + textBounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE), + 2, + (float)GuiGetStyle(DEFAULT, TEXT_SIZE)*2 + }; + + if (cursor.height >= bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2; + if (cursor.y < (bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH))) cursor.y = bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH); + + // Mouse cursor rectangle + // NOTE: Initialized outside of screen + Rectangle mouseCursor = cursor; + mouseCursor.x = -1; + mouseCursor.width = 1; + + // Blink-cursor frame counter + //if (!autoCursorMode) blinkCursorFrameCounter++; + //else blinkCursorFrameCounter = 0; + + // Update control + //-------------------------------------------------------------------- + // WARNING: Text editing is only supported under certain conditions: + if ((state != STATE_DISABLED) && // Control not disabled + !GuiGetStyle(TEXTBOX, TEXT_READONLY) && // TextBox not on read-only mode + !guiLocked && // Gui not locked + !guiControlExclusiveMode && // No gui slider on dragging + (wrapMode == TEXT_WRAP_NONE)) // No wrap mode + { + Vector2 mousePosition = GUI_POINTER_POSITION; + + if (editMode) + { + // GLOBAL: Auto-cursor movement logic + // NOTE: Keystrokes are handled repeatedly when button is held down for some time + if (GUI_KEY_DOWN(KEY_LEFT) || GUI_KEY_DOWN(KEY_RIGHT) || GUI_KEY_DOWN(KEY_UP) || GUI_KEY_DOWN(KEY_DOWN) || GUI_KEY_DOWN(KEY_BACKSPACE) || GUI_KEY_DOWN(KEY_DELETE)) autoCursorCounter++; + else autoCursorCounter = 0; + + bool autoCursorShouldTrigger = (autoCursorCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN) && ((autoCursorCounter % RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0); + + state = STATE_PRESSED; + + if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength; + + // If text does not fit in the textbox and current cursor position is out of bounds, + // adding an index offset to text for drawing only what requires depending on cursor + while (textWidth >= textBounds.width) + { + int nextCodepointSize = 0; + GetCodepointNext(text + textIndexOffset, &nextCodepointSize); + + textIndexOffset += nextCodepointSize; + + textWidth = GuiGetTextWidth(text + textIndexOffset) - GuiGetTextWidth(text + textBoxCursorIndex); + } + + int codepoint = GUI_INPUT_KEY; // Get Unicode codepoint + if (multiline && GUI_KEY_PRESSED(KEY_ENTER)) codepoint = (int)'\n'; + + // Encode codepoint as UTF-8 + int codepointSize = 0; + const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize); + + // Handle text paste action + if (GUI_KEY_PRESSED(KEY_V) && (GUI_KEY_DOWN(KEY_LEFT_CONTROL) || GUI_KEY_DOWN(KEY_RIGHT_CONTROL))) + { + const char *pasteText = GetClipboardText(); + if (pasteText != NULL) + { + int pasteLength = 0; + int pasteCodepoint; + int pasteCodepointSize; + + // Count how many codepoints to copy, stopping at the first unwanted control character + while (true) + { + pasteCodepoint = GetCodepointNext(pasteText + pasteLength, &pasteCodepointSize); + if (textLength + pasteLength + pasteCodepointSize >= textSize) break; + if (!(multiline && (pasteCodepoint == (int)'\n')) && !(pasteCodepoint >= 32)) break; + pasteLength += pasteCodepointSize; + } + + if (pasteLength > 0) + { + // Move forward data from cursor position + for (int i = textLength + pasteLength; i > textBoxCursorIndex; i--) text[i] = text[i - pasteLength]; + + // Paste data in at cursor + for (int i = 0; i < pasteLength; i++) text[textBoxCursorIndex + i] = pasteText[i]; + + textBoxCursorIndex += pasteLength; + textLength += pasteLength; + text[textLength] = '\0'; + } + } + } + else if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < textSize)) + { + // Adding codepoint to text, at current cursor position + + // Move forward data from cursor position + for (int i = (textLength + codepointSize); i > textBoxCursorIndex; i--) text[i] = text[i - codepointSize]; + + // Add new codepoint in current cursor position + for (int i = 0; i < codepointSize; i++) text[textBoxCursorIndex + i] = charEncoded[i]; + + textBoxCursorIndex += codepointSize; + textLength += codepointSize; + + // Make sure text last character is EOL + text[textLength] = '\0'; + } + + // Move cursor to start + if ((textLength > 0) && GUI_KEY_PRESSED(KEY_HOME)) textBoxCursorIndex = 0; + + // Move cursor to end + if ((textLength > textBoxCursorIndex) && GUI_KEY_PRESSED(KEY_END)) textBoxCursorIndex = textLength; + + // Delete related codepoints from text, after current cursor position + if ((textLength > textBoxCursorIndex) && GUI_KEY_PRESSED(KEY_DELETE) && (GUI_KEY_DOWN(KEY_LEFT_CONTROL) || GUI_KEY_DOWN(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + int accCodepointSize = 0; + int nextCodepointSize; + int nextCodepoint; + + // Check characters of the same type to delete (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + bool puctuation = ispunct(nextCodepoint & 0xff); + while (offset < textLength) + { + if ((puctuation && !ispunct(nextCodepoint & 0xff)) || (!puctuation && (isspace(nextCodepoint & 0xff) || ispunct(nextCodepoint & 0xff)))) + break; + offset += nextCodepointSize; + accCodepointSize += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + + // Check whitespace to delete (ASCII only) + while (offset < textLength) + { + if (!isspace(nextCodepoint & 0xff)) break; + + offset += nextCodepointSize; + accCodepointSize += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + + // Move text after cursor forward (including final null terminator) + for (int i = offset; i <= textLength; i++) text[i - accCodepointSize] = text[i]; + + textLength -= accCodepointSize; + } + + else if ((textLength > textBoxCursorIndex) && (GUI_KEY_PRESSED(KEY_DELETE) || (GUI_KEY_DOWN(KEY_DELETE) && autoCursorShouldTrigger))) + { + // Delete single codepoint from text, after current cursor position + + int nextCodepointSize = 0; + GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize); + + // Move text after cursor forward (including final null terminator) + for (int i = textBoxCursorIndex + nextCodepointSize; i <= textLength; i++) text[i - nextCodepointSize] = text[i]; + + textLength -= nextCodepointSize; + } + + // Delete related codepoints from text, before current cursor position + if ((textBoxCursorIndex > 0) && GUI_KEY_PRESSED(KEY_BACKSPACE) && (GUI_KEY_DOWN(KEY_LEFT_CONTROL) || GUI_KEY_DOWN(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + int accCodepointSize = 0; + int prevCodepointSize = 0; + int prevCodepoint = 0; + + // Check whitespace to delete (ASCII only) + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if (!isspace(prevCodepoint & 0xff)) break; + + offset -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Check characters of the same type to delete (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + bool puctuation = ispunct(prevCodepoint & 0xff); + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if ((puctuation && !ispunct(prevCodepoint & 0xff)) || (!puctuation && (isspace(prevCodepoint & 0xff) || ispunct(prevCodepoint & 0xff)))) break; + + offset -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Move text after cursor forward (including final null terminator) + for (int i = textBoxCursorIndex; i <= textLength; i++) text[i - accCodepointSize] = text[i]; + + textLength -= accCodepointSize; + textBoxCursorIndex -= accCodepointSize; + } + + else if ((textBoxCursorIndex > 0) && (GUI_KEY_PRESSED(KEY_BACKSPACE) || (GUI_KEY_DOWN(KEY_BACKSPACE) && autoCursorShouldTrigger))) + { + // Delete single codepoint from text, before current cursor position + + int prevCodepointSize = 0; + + GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + // Move text after cursor forward (including final null terminator) + for (int i = textBoxCursorIndex; i <= textLength; i++) text[i - prevCodepointSize] = text[i]; + + textLength -= prevCodepointSize; + textBoxCursorIndex -= prevCodepointSize; + } + + // Move cursor position with keys + if ((textBoxCursorIndex > 0) && GUI_KEY_PRESSED(KEY_LEFT) && (GUI_KEY_DOWN(KEY_LEFT_CONTROL) || GUI_KEY_DOWN(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + //int accCodepointSize = 0; + int prevCodepointSize = 0; + int prevCodepoint = 0; + + // Check whitespace to skip (ASCII only) + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if (!isspace(prevCodepoint & 0xff)) break; + + offset -= prevCodepointSize; + //accCodepointSize += prevCodepointSize; + } + + // Check characters of the same type to skip (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + bool puctuation = ispunct(prevCodepoint & 0xff); + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if ((puctuation && !ispunct(prevCodepoint & 0xff)) || (!puctuation && (isspace(prevCodepoint & 0xff) || ispunct(prevCodepoint & 0xff)))) break; + + offset -= prevCodepointSize; + //accCodepointSize += prevCodepointSize; + } + + textBoxCursorIndex = offset; + } + else if ((textBoxCursorIndex > 0) && (GUI_KEY_PRESSED(KEY_LEFT) || (GUI_KEY_DOWN(KEY_LEFT) && autoCursorShouldTrigger))) + { + int prevCodepointSize = 0; + GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + textBoxCursorIndex -= prevCodepointSize; + } + else if ((textLength > textBoxCursorIndex) && GUI_KEY_PRESSED(KEY_RIGHT) && (GUI_KEY_DOWN(KEY_LEFT_CONTROL) || GUI_KEY_DOWN(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + //int accCodepointSize = 0; + int nextCodepointSize; + int nextCodepoint; + + // Check characters of the same type to skip (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + bool puctuation = ispunct(nextCodepoint & 0xff); + while (offset < textLength) + { + if ((puctuation && !ispunct(nextCodepoint & 0xff)) || (!puctuation && (isspace(nextCodepoint & 0xff) || ispunct(nextCodepoint & 0xff)))) break; + + offset += nextCodepointSize; + //accCodepointSize += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + + // Check whitespace to skip (ASCII only) + while (offset < textLength) + { + if (!isspace(nextCodepoint & 0xff)) break; + + offset += nextCodepointSize; + //accCodepointSize += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + + textBoxCursorIndex = offset; + } + else if ((textLength > textBoxCursorIndex) && (GUI_KEY_PRESSED(KEY_RIGHT) || (GUI_KEY_DOWN(KEY_RIGHT) && autoCursorShouldTrigger))) + { + int nextCodepointSize = 0; + GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize); + + textBoxCursorIndex += nextCodepointSize; + } + + // Move cursor position with mouse + if (CheckCollisionPointRec(mousePosition, textBounds)) // Mouse hover text + { + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/(float)guiFont.baseSize; + int codepointIndex = 0; + float glyphWidth = 0.0f; + float widthToMouseX = 0; + int mouseCursorIndex = 0; + + for (int i = textIndexOffset; i < textLength; i += codepointSize) + { + codepoint = GetCodepointNext(&text[i], &codepointSize); + codepointIndex = GetGlyphIndex(guiFont, codepoint); + + if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor); + else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor); + + if (mousePosition.x <= (textBounds.x + (widthToMouseX + glyphWidth/2))) + { + mouseCursor.x = textBounds.x + widthToMouseX; + mouseCursorIndex = i; + break; + } + + widthToMouseX += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + + // Check if mouse cursor is at the last position + int textEndWidth = GuiGetTextWidth(text + textIndexOffset); + if (GUI_POINTER_POSITION.x >= (textBounds.x + textEndWidth - glyphWidth/2)) + { + mouseCursor.x = textBounds.x + textEndWidth; + mouseCursorIndex = textLength; + } + + // Place cursor at required index on mouse click + if ((mouseCursor.x >= 0) && GUI_BUTTON_PRESSED) + { + cursor.x = mouseCursor.x; + textBoxCursorIndex = mouseCursorIndex; + } + } + else mouseCursor.x = -1; + + // Recalculate cursor position.y depending on textBoxCursorIndex + cursor.x = bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GuiGetTextWidth(text + textIndexOffset) - GuiGetTextWidth(text + textBoxCursorIndex) + GuiGetStyle(DEFAULT, TEXT_SPACING); + //if (multiline) cursor.y = GetTextLines() + + // Finish text editing on ENTER or mouse click outside bounds + if ((!multiline && GUI_KEY_PRESSED(KEY_ENTER)) || + (!CheckCollisionPointRec(mousePosition, bounds) && GUI_BUTTON_PRESSED)) + { + textBoxCursorIndex = 0; // GLOBAL: Reset the shared cursor index + autoCursorCounter = 0; // GLOBAL: Reset counter for repeated keystrokes + result = 1; + } + } + else + { + if (CheckCollisionPointRec(mousePosition, bounds)) + { + state = STATE_FOCUSED; + + if (GUI_BUTTON_PRESSED) + { + textBoxCursorIndex = textLength; // GLOBAL: Place cursor index to the end of current text + autoCursorCounter = 0; // GLOBAL: Reset counter for repeated keystrokes + result = 1; + } + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_PRESSED) + { + GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED))); + } + else if (state == STATE_DISABLED) + { + GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED))); + } + else GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), BLANK); + + // Draw text considering index offset if required + // NOTE: Text index offset depends on cursor position + GuiDrawText(text + textIndexOffset, textBounds, GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3)))); + + // Draw cursor + if (editMode && !GuiGetStyle(TEXTBOX, TEXT_READONLY)) + { + //if (autoCursorMode || ((blinkCursorFrameCounter/40)%2 == 0)) + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED))); + + // Draw mouse position cursor (if required) + if (mouseCursor.x >= 0) GuiDrawRectangle(mouseCursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED))); + } + else if (state == STATE_FOCUSED) GuiTooltip(bounds); + //-------------------------------------------------------------------- + + return result; // Mouse button pressed: result = 1 +} + +/* +// Text Box control with multiple lines and word-wrap +// NOTE: This text-box is readonly, no editing supported by default +bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode) +{ + bool pressed = false; + + GuiSetStyle(TEXTBOX, TEXT_READONLY, 1); + GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // WARNING: If wrap mode enabled, text editing is not supported + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP); + + // TODO: Implement methods to calculate cursor position properly + pressed = GuiTextBox(bounds, text, textSize, editMode); + + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); + GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE); + GuiSetStyle(TEXTBOX, TEXT_READONLY, 0); + + return pressed; +} +*/ + +// Spinner control, returns selected value +int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode) +{ + int result = 1; + GuiState state = guiState; + + int tempValue = *value; + + Rectangle valueBoxBounds = { + bounds.x + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING), + bounds.y, + bounds.width - 2*(GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING)), bounds.height }; + Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height }; + Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.y, + (float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height }; + + Rectangle textBounds = { 0 }; + if (text != NULL) + { + textBounds.width = (float)GuiGetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + // Check spinner state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (GUI_BUTTON_DOWN) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + +#if defined(RAYGUI_NO_ICONS) + if (GuiButton(leftButtonBound, "<")) tempValue--; + if (GuiButton(rightButtonBound, ">")) tempValue++; +#else + if (GuiButton(leftButtonBound, GuiIconText(ICON_ARROW_LEFT_FILL, NULL))) tempValue--; + if (GuiButton(rightButtonBound, GuiIconText(ICON_ARROW_RIGHT_FILL, NULL))) tempValue++; +#endif + + if (!editMode) + { + if (tempValue < minValue) tempValue = minValue; + if (tempValue > maxValue) tempValue = maxValue; + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + result = GuiValueBox(valueBoxBounds, NULL, &tempValue, minValue, maxValue, editMode); + + // Draw value selector custom buttons + // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(VALUEBOX, BORDER_WIDTH)); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + + // Draw text label if provided + GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + *value = tempValue; + return result; +} + +// Value Box control, updates input text with numbers +// NOTE: Requires static variables: frameCounter +int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode) +{ + #if !defined(RAYGUI_VALUEBOX_MAX_CHARS) + #define RAYGUI_VALUEBOX_MAX_CHARS 32 + #endif + + int result = 0; + GuiState state = guiState; + + char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = { 0 }; + snprintf(textValue, RAYGUI_VALUEBOX_MAX_CHARS + 1, "%i", *value); + + Rectangle textBounds = { 0 }; + if (text != NULL) + { + textBounds.width = (float)GuiGetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + bool valueHasChanged = false; + + if (editMode) + { + state = STATE_PRESSED; + + int keyCount = (int)strlen(textValue); + + // Add or remove minus symbol + if (GUI_KEY_PRESSED(KEY_MINUS)) + { + if (textValue[0] == '-') + { + for (int i = 0 ; i < keyCount; i++) textValue[i] = textValue[i + 1]; + + keyCount--; + valueHasChanged = true; + } + else if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) + { + if (keyCount == 0) + { + textValue[0] = '0'; + textValue[1] = '\0'; + keyCount++; + } + + for (int i = keyCount ; i > -1; i--) textValue[i + 1] = textValue[i]; + + textValue[0] = '-'; + keyCount++; + valueHasChanged = true; + } + } + + // Add new digit to text value + if ((keyCount >= 0) && (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) && (GuiGetTextWidth(textValue) < bounds.width)) + { + int key = GUI_INPUT_KEY; + + // Only allow keys in range [48..57] + if ((key >= 48) && (key <= 57)) + { + textValue[keyCount] = (char)key; + keyCount++; + valueHasChanged = true; + } + } + + // Delete text + if ((keyCount > 0) && GUI_KEY_PRESSED(KEY_BACKSPACE)) + { + keyCount--; + textValue[keyCount] = '\0'; + valueHasChanged = true; + } + + if (valueHasChanged) *value = TextToInteger(textValue); + + // NOTE: Values are not clamped until user input finishes + //if (*value > maxValue) *value = maxValue; + //else if (*value < minValue) *value = minValue; + + if ((GUI_KEY_PRESSED(KEY_ENTER) || GUI_KEY_PRESSED(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && GUI_BUTTON_PRESSED)) + { + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + + result = 1; + } + } + else + { + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + if (GUI_BUTTON_PRESSED) result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + Color baseColor = BLANK; + if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)); + else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)); + + GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor); + GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3)))); + + // Draw cursor rectangle + if (editMode) + { + // NOTE: ValueBox internal text is always centered + Rectangle cursor = { bounds.x + GuiGetTextWidth(textValue)/2 + bounds.width/2 + 1, + bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + 2, + 2, bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2 - 4 }; + if (cursor.height > bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2; + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED))); + } + + // Draw text label if provided + GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Floating point Value Box control, updates input val_str with numbers +// NOTE: Requires static variables: frameCounter +int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode) +{ + #if !defined(RAYGUI_VALUEBOX_MAX_CHARS) + #define RAYGUI_VALUEBOX_MAX_CHARS 32 + #endif + + int result = 0; + GuiState state = guiState; + + //char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0"; + //snprintf(textValue, sizeof(textValue), "%2.2f", *value); + + Rectangle textBounds = { 0 }; + if (text != NULL) + { + textBounds.width = (float)GuiGetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + bool valueHasChanged = false; + + if (editMode) + { + state = STATE_PRESSED; + + int keyCount = (int)strlen(textValue); + + // Add or remove minus symbol + if (GUI_KEY_PRESSED(KEY_MINUS)) + { + if (textValue[0] == '-') + { + for (int i = 0; i < keyCount; i++) textValue[i] = textValue[i + 1]; + + keyCount--; + valueHasChanged = true; + } + else if (keyCount < (RAYGUI_VALUEBOX_MAX_CHARS - 1)) + { + if (keyCount == 0) + { + textValue[0] = '0'; + textValue[1] = '\0'; + keyCount++; + } + + for (int i = keyCount; i > -1; i--) textValue[i + 1] = textValue[i]; + + textValue[0] = '-'; + keyCount++; + valueHasChanged = true; + } + } + + // Only allow keys in range [48..57] + if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) + { + if (GuiGetTextWidth(textValue) < bounds.width) + { + int key = GUI_INPUT_KEY; + if (((key >= 48) && (key <= 57)) || + (key == '.') || + ((keyCount == 0) && (key == '+')) || // NOTE: Sign can only be in first position + ((keyCount == 0) && (key == '-'))) + { + textValue[keyCount] = (char)key; + keyCount++; + + valueHasChanged = true; + } + } + } + + // Pressed backspace + if (GUI_KEY_PRESSED(KEY_BACKSPACE)) + { + if (keyCount > 0) + { + keyCount--; + textValue[keyCount] = '\0'; + valueHasChanged = true; + } + } + + if (valueHasChanged) *value = TextToFloat(textValue); + + if ((GUI_KEY_PRESSED(KEY_ENTER) || GUI_KEY_PRESSED(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && GUI_BUTTON_PRESSED)) result = 1; + } + else + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + if (GUI_BUTTON_PRESSED) result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + Color baseColor = BLANK; + if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)); + else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)); + + GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor); + GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3)))); + + // Draw cursor + if (editMode) + { + // NOTE: ValueBox internal text is always centered + Rectangle cursor = {bounds.x + GuiGetTextWidth(textValue)/2 + bounds.width/2 + 1, + bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4, + bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH)}; + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED))); + } + + // Draw text label if provided + GuiDrawText(text, textBounds, + (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, + GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Slider control with pro parameters +// NOTE: Other GuiSlider*() controls use this one +int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + int result = 0; + GuiState state = guiState; + + float temp = (maxValue - minValue)/2.0f; + if (value == NULL) value = &temp; + float oldValue = *value; + + int sliderWidth = GuiGetStyle(SLIDER, SLIDER_WIDTH); + + Rectangle slider = { bounds.x, bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING), + 0, bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (GUI_BUTTON_DOWN) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + // Get equivalent value and slider position from mousePosition.x + *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width - sliderWidth)) + minValue; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (GUI_BUTTON_DOWN) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + if (!CheckCollisionPointRec(mousePoint, slider)) + { + // Get equivalent value and slider position from mousePosition.x + *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width - sliderWidth)) + minValue; + } + } + else state = STATE_FOCUSED; + } + + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + } + + // Control value change check + if (oldValue == *value) result = 0; + else result = 1; + + // Slider bar limits check + float sliderValue = (((*value - minValue)/(maxValue - minValue))*(bounds.width - sliderWidth - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))); + if (sliderWidth > 0) // Slider + { + slider.x += sliderValue; + slider.width = (float)sliderWidth; + if (slider.x <= (bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH); + else if ((slider.x + slider.width) >= (bounds.x + bounds.width)) slider.x = bounds.x + bounds.width - slider.width - GuiGetStyle(SLIDER, BORDER_WIDTH); + } + else if (sliderWidth == 0) // SliderBar + { + slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH); + slider.width = sliderValue; + if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH); + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED))); + + // Draw slider internal bar (depends on state) + if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED))); + else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_PRESSED))); + else if (state == STATE_DISABLED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_DISABLED))); + + // Draw left/right text if provided + if (textLeft != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(textLeft); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SLIDER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + + if (textRight != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(textRight); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + //-------------------------------------------------------------------- + + return result; +} + +// Slider Bar control extended, returns selected value +int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + int result = 0; + int preSliderWidth = GuiGetStyle(SLIDER, SLIDER_WIDTH); + GuiSetStyle(SLIDER, SLIDER_WIDTH, 0); + result = GuiSlider(bounds, textLeft, textRight, value, minValue, maxValue); + GuiSetStyle(SLIDER, SLIDER_WIDTH, preSliderWidth); + + return result; +} + +// Progress Bar control extended, shows current progress value +int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + int result = 0; + GuiState state = guiState; + + float temp = (maxValue - minValue)/2.0f; + if (value == NULL) value = &temp; + + // Progress bar + Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), + bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING), 0, + bounds.height - GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) -1 }; + + // Update control + //-------------------------------------------------------------------- + if (*value > maxValue) *value = maxValue; + + // WARNING: Working with floats could lead to rounding issues + if ((state != STATE_DISABLED)) progress.width = ((float)*value/(maxValue - minValue))*(bounds.width - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)); + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_DISABLED) + { + GuiDrawRectangle(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), BLANK); + } + else + { + if (*value > minValue) + { + // Draw progress bar with colored border, more visual + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + } + else GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + + if (*value >= maxValue) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1}, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + else + { + // Draw borders not yet reached by value + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y + bounds.height - 1, bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + } + + // Draw slider internal progress bar (depends on state) + if (GuiGetStyle(PROGRESSBAR, PROGRESS_SIDE) == 0) // Left-->Right + { + GuiDrawRectangle(progress, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED))); + } + else // Right-->Left + { + progress.x = bounds.x + bounds.width - progress.width - GuiGetStyle(PROGRESSBAR, BORDER_WIDTH); + GuiDrawRectangle(progress, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED))); + } + } + + // Draw left/right text if provided + if (textLeft != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(textLeft); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x - textBounds.width - GuiGetStyle(PROGRESSBAR, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + + if (textRight != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(textRight); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(PROGRESSBAR, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + //-------------------------------------------------------------------- + + return result; +} + +// Status Bar control +int GuiStatusBar(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(STATUSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(STATUSBAR, BORDER + (state*3))), GetColor(GuiGetStyle(STATUSBAR, BASE + (state*3)))); + GuiDrawText(text, GetTextBounds(STATUSBAR, bounds), GuiGetStyle(STATUSBAR, TEXT_ALIGNMENT), GetColor(GuiGetStyle(STATUSBAR, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Dummy rectangle control, intended for placeholding +int GuiDummyRec(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (GUI_BUTTON_DOWN) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED))); + GuiDrawText(text, GetTextBounds(DEFAULT, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(BUTTON, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED))); + //------------------------------------------------------------------ + + return result; +} + +// List View control +int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active) +{ + int result = 0; + int itemCount = 0; + char **items = NULL; + + if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); + + result = GuiListViewEx(bounds, items, itemCount, scrollIndex, active, NULL); + + return result; +} + +// List View control with extended parameters +int GuiListViewEx(Rectangle bounds, char **text, int count, int *scrollIndex, int *active, int *focus) +{ + int result = 0; + GuiState state = guiState; + + int itemFocused = (focus == NULL)? -1 : *focus; + int itemSelected = (active == NULL)? -1 : *active; + + // Check if scroll bar is needed + bool useScrollBar = false; + if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING))*count > bounds.height) useScrollBar = true; + + // Define base item rectangle [0] + Rectangle itemBounds = { 0 }; + itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING); + itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); + itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) - GuiGetStyle(DEFAULT, BORDER_WIDTH); + itemBounds.height = (float)GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT); + if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); + + // Get items on the list + int visibleItems = (int)bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + if (visibleItems > count) visibleItems = count; + + int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex; + if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0; + int endIndex = startIndex + visibleItems; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + // Check mouse inside list view + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + + // Check focused and selected item + for (int i = 0; i < visibleItems; i++) + { + if (CheckCollisionPointRec(mousePoint, itemBounds)) + { + itemFocused = startIndex + i; + if (GUI_BUTTON_PRESSED) + { + if (itemSelected == (startIndex + i)) itemSelected = -1; + else itemSelected = startIndex + i; + } + break; + } + + // Update item rectangle y position for next item + itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + } + + if (useScrollBar) + { + float scrollDelta = GUI_SCROLL_DELTA; + startIndex -= (int)scrollDelta; + + if (startIndex < 0) startIndex = 0; + else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems; + + endIndex = startIndex + visibleItems; + if (endIndex > count) endIndex = count; + } + } + else itemFocused = -1; + + // Reset item rectangle y to [0] + itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + + // Draw visible items + for (int i = 0; ((i < visibleItems) && (text != NULL)); i++) + { + if (GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_NORMAL)) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_NORMAL)), BLANK); + + if (state == STATE_DISABLED) + { + if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED))); + + GuiDrawText(text[startIndex + i], GetTextBounds(LISTVIEW, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED))); + } + else + { + if (((startIndex + i) == itemSelected) && (active != NULL)) + { + // Draw item selected + GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED))); + GuiDrawText(text[startIndex + i], GetTextBounds(LISTVIEW, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED))); + } + else if (((startIndex + i) == itemFocused)) // && (focus != NULL)) // NOTE: Items focused, despite not returned + { + // Draw item focused + GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED))); + GuiDrawText(text[startIndex + i], GetTextBounds(LISTVIEW, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED))); + } + else + { + // Draw item normal (no rectangle) + GuiDrawText(text[startIndex + i], GetTextBounds(LISTVIEW, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL))); + } + } + + // Update item rectangle y position for next item + itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + } + + if (useScrollBar) + { + Rectangle scrollBarBounds = { + bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), + bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), + bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) + }; + + // Calculate percentage of visible items and apply same percentage to scrollbar + float percentVisible = (float)(endIndex - startIndex)/count; + float sliderSize = bounds.height*percentVisible; + + int prevSliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); // Save default slider size + int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)sliderSize); // Change slider size + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed + + startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems); + + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, prevSliderSize); // Reset slider size to default + } + //-------------------------------------------------------------------- + + if (active != NULL) *active = itemSelected; + if (focus != NULL) *focus = itemFocused; + if (scrollIndex != NULL) *scrollIndex = startIndex; + + return result; +} + +// Color Panel control - Color (RGBA) variant +int GuiColorPanel(Rectangle bounds, const char *text, Color *color) +{ + int result = 0; + + Vector3 vcolor = { (float)color->r/255.0f, (float)color->g/255.0f, (float)color->b/255.0f }; + Vector3 hsv = ConvertRGBtoHSV(vcolor); + Vector3 prevHsv = hsv; // workaround to see if GuiColorPanelHSV modifies the hsv + + GuiColorPanelHSV(bounds, text, &hsv); + + // Check if the hsv was changed, only then change the color + // This is required, because the Color->HSV->Color conversion has precision errors + // Thus the assignment from HSV to Color should only be made, if the HSV has a new user-entered value + // Otherwise GuiColorPanel would often modify it's color without user input + // TODO: GuiColorPanelHSV could return 1 if the slider was dragged, to simplify this check + if (hsv.x != prevHsv.x || hsv.y != prevHsv.y || hsv.z != prevHsv.z) + { + Vector3 rgb = ConvertHSVtoRGB(hsv); + + // NOTE: Vector3ToColor() only available on raylib 1.8.1 + *color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x), + (unsigned char)(255.0f*rgb.y), + (unsigned char)(255.0f*rgb.z), + color->a }; + } + return result; +} + +// Color Bar Alpha control +// NOTE: Returns alpha value normalized [0..1] +int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) +{ + #if !defined(RAYGUI_COLORBARALPHA_CHECKED_SIZE) + #define RAYGUI_COLORBARALPHA_CHECKED_SIZE 10 + #endif + + int result = 0; + GuiState state = guiState; + Rectangle selector = { (float)bounds.x + (*alpha)*bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, + (float)bounds.y - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), + (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT), + (float)bounds.height + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2 }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (GUI_BUTTON_DOWN) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + *alpha = (mousePoint.x - bounds.x)/bounds.width; + if (*alpha <= 0.0f) *alpha = 0.0f; + if (*alpha >= 1.0f) *alpha = 1.0f; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) + { + if (GUI_BUTTON_DOWN) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + *alpha = (mousePoint.x - bounds.x)/bounds.width; + if (*alpha <= 0.0f) *alpha = 0.0f; + if (*alpha >= 1.0f) *alpha = 1.0f; + //selector.x = bounds.x + (int)(((alpha - 0)/(100 - 0))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))) - selector.width/2; + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + // Draw alpha bar: checked background + if (state != STATE_DISABLED) + { + int checksX = (int)bounds.width/RAYGUI_COLORBARALPHA_CHECKED_SIZE; + int checksY = (int)bounds.height/RAYGUI_COLORBARALPHA_CHECKED_SIZE; + + for (int x = 0; x < checksX; x++) + { + for (int y = 0; y < checksY; y++) + { + Rectangle check = { bounds.x + x*RAYGUI_COLORBARALPHA_CHECKED_SIZE, bounds.y + y*RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE }; + GuiDrawRectangle(check, 0, BLANK, ((x + y)%2)? Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.4f) : Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.4f)); + } + } + + DrawRectangleGradientEx(bounds, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha)); + } + else DrawRectangleGradientEx(bounds, Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + + // Draw alpha bar: selector + GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3))); + //-------------------------------------------------------------------- + + return result; +} + +// Color Bar Hue control +// Returns hue value normalized [0..1] +// NOTE: Other similar bars (for reference): +// Color GuiColorBarSat() [WHITE->color] +// Color GuiColorBarValue() [BLACK->color], HSV/HSL +// float GuiColorBarLuminance() [BLACK->WHITE] +int GuiColorBarHue(Rectangle bounds, const char *text, float *hue) +{ + int result = 0; + GuiState state = guiState; + Rectangle selector = { (float)bounds.x - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)bounds.y + (*hue)/360.0f*bounds.height - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, (float)bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2, (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (GUI_BUTTON_DOWN) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + *hue = (mousePoint.y - bounds.y)*360/bounds.height; + if (*hue <= 0.0f) *hue = 0.0f; + if (*hue >= 359.0f) *hue = 359.0f; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) + { + if (GUI_BUTTON_DOWN) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + *hue = (mousePoint.y - bounds.y)*360/bounds.height; + if (*hue <= 0.0f) *hue = 0.0f; + if (*hue >= 359.0f) *hue = 359.0f; + + } + else state = STATE_FOCUSED; + + /*if (GUI_KEY_DOWN(KEY_UP)) + { + hue -= 2.0f; + if (hue <= 0.0f) hue = 0.0f; + } + else if (GUI_KEY_DOWN(KEY_DOWN)) + { + hue += 2.0f; + if (hue >= 360.0f) hue = 360.0f; + }*/ + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state != STATE_DISABLED) + { + // Draw hue bar:color bars + // TODO: Use directly DrawRectangleGradientEx(bounds, color1, color2, color2, color1); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + bounds.height/6), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 2*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 3*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 4*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 5*(bounds.height/6)), (int)bounds.width, (int)(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha)); + } + else DrawRectangleGradientV((int)bounds.x, (int)bounds.y, (int)bounds.width, (int)bounds.height, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + + // Draw hue bar: selector + GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3))); + //-------------------------------------------------------------------- + + return result; +} + +// Color Picker control +// NOTE: It's divided in multiple controls: +// Color GuiColorPanel(Rectangle bounds, Color color) +// float GuiColorBarAlpha(Rectangle bounds, float alpha) +// float GuiColorBarHue(Rectangle bounds, float value) +// NOTE: bounds define GuiColorPanel() size +// NOTE: this picker converts RGB to HSV, which can cause the Hue control to jump. If you have this problem, consider using the HSV variant instead +int GuiColorPicker(Rectangle bounds, const char *text, Color *color) +{ + int result = 0; + + Color temp = { 200, 0, 0, 255 }; + if (color == NULL) color = &temp; + + GuiColorPanel(bounds, NULL, color); + + Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height }; + //Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) }; + + // NOTE: this conversion can cause low hue-resolution, if the r, g and b value are very similar, which causes the hue bar to shift around when only the GuiColorPanel is used + Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f }); + + GuiColorBarHue(boundsHue, NULL, &hsv.x); + + //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f); + Vector3 rgb = ConvertHSVtoRGB(hsv); + + *color = RAYGUI_CLITERAL(Color){ (unsigned char)roundf(rgb.x*255.0f), (unsigned char)roundf(rgb.y*255.0f), (unsigned char)roundf(rgb.z*255.0f), (*color).a }; + + return result; +} + +// Color Picker control that avoids conversion to RGB and back to HSV on each call, thus avoiding jittering +// The user can call ConvertHSVtoRGB() to convert *colorHsv value to RGB +// NOTE: It's divided in multiple controls: +// int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +// int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) +// float GuiColorBarHue(Rectangle bounds, float value) +// NOTE: bounds define GuiColorPanelHSV() size +int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +{ + int result = 0; + + Vector3 tempHsv = { 0 }; + + if (colorHsv == NULL) + { + const Vector3 tempColor = { 200.0f/255.0f, 0.0f, 0.0f }; + tempHsv = ConvertRGBtoHSV(tempColor); + colorHsv = &tempHsv; + } + + GuiColorPanelHSV(bounds, NULL, colorHsv); + + const Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height }; + + GuiColorBarHue(boundsHue, NULL, &colorHsv->x); + + return result; +} + +// Color Panel control - HSV variant +int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +{ + int result = 0; + GuiState state = guiState; + Vector2 pickerSelector = { 0 }; + + const Color colWhite = { 255, 255, 255, 255 }; + const Color colBlack = { 0, 0, 0, 255 }; + + pickerSelector.x = bounds.x + (float)colorHsv->y*bounds.width; // HSV: Saturation + pickerSelector.y = bounds.y + (1.0f - (float)colorHsv->z)*bounds.height; // HSV: Value + + Vector3 maxHue = { colorHsv->x, 1.0f, 1.0f }; + Vector3 rgbHue = ConvertHSVtoRGB(maxHue); + Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x), + (unsigned char)(255.0f*rgbHue.y), + (unsigned char)(255.0f*rgbHue.z), 255 }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (GUI_BUTTON_DOWN) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + pickerSelector = mousePoint; + + if (pickerSelector.x < bounds.x) pickerSelector.x = bounds.x; + if (pickerSelector.x > bounds.x + bounds.width) pickerSelector.x = bounds.x + bounds.width; + if (pickerSelector.y < bounds.y) pickerSelector.y = bounds.y; + if (pickerSelector.y > bounds.y + bounds.height) pickerSelector.y = bounds.y + bounds.height; + + // Calculate color from picker + Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y }; + + colorPick.x /= (float)bounds.width; // Get normalized value on x + colorPick.y /= (float)bounds.height; // Get normalized value on y + + colorHsv->y = colorPick.x; + colorHsv->z = 1.0f - colorPick.y; + + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (GUI_BUTTON_DOWN) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; + pickerSelector = mousePoint; + + // Calculate color from picker + Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y }; + + colorPick.x /= (float)bounds.width; // Get normalized value on x + colorPick.y /= (float)bounds.height; // Get normalized value on y + + colorHsv->y = colorPick.x; + colorHsv->z = 1.0f - colorPick.y; + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state != STATE_DISABLED) + { + DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha)); + DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0)); + + // Draw color picker: selector + Rectangle selector = { pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE) }; + GuiDrawRectangle(selector, 0, BLANK, colWhite); + } + else + { + DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha)); + } + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + //-------------------------------------------------------------------- + + return result; +} + +// Message Box control +int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons) +{ + #if !defined(RAYGUI_MESSAGEBOX_BUTTON_HEIGHT) + #define RAYGUI_MESSAGEBOX_BUTTON_HEIGHT 24 + #endif + #if !defined(RAYGUI_MESSAGEBOX_BUTTON_PADDING) + #define RAYGUI_MESSAGEBOX_BUTTON_PADDING 12 + #endif + + int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button + + int buttonCount = 0; + char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); + Rectangle buttonBounds = { 0 }; + buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING; + buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; + buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; + + //int textWidth = GuiGetTextWidth(message) + 2; + + Rectangle textBounds = { 0 }; + textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + textBounds.width = bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*2; + textBounds.height = bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 3*RAYGUI_MESSAGEBOX_BUTTON_PADDING - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; + + // Draw control + //-------------------------------------------------------------------- + if (GuiWindowBox(bounds, title)) result = 0; + + int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(textBounds, message); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment); + + prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + for (int i = 0; i < buttonCount; i++) + { + if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1; + buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING); + } + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevTextAlignment); + //-------------------------------------------------------------------- + + return result; +} + +// Text Input Box control, ask for text +int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive) +{ + #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT) + #define RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT 24 + #endif + #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_PADDING) + #define RAYGUI_TEXTINPUTBOX_BUTTON_PADDING 12 + #endif + #if !defined(RAYGUI_TEXTINPUTBOX_HEIGHT) + #define RAYGUI_TEXTINPUTBOX_HEIGHT 26 + #endif + + // Used to enable text edit mode + // WARNING: No more than one GuiTextInputBox() should be open at the same time + static bool textEditMode = false; + + int result = -1; + + int buttonCount = 0; + char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); + Rectangle buttonBounds = { 0 }; + buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + buttonBounds.width = (bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; + buttonBounds.height = RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT; + + int messageInputHeight = (int)bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - 2*RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + + Rectangle textBounds = { 0 }; + if (message != NULL) + { + int textSize = GuiGetTextWidth(message) + 2; + + textBounds.x = bounds.x + bounds.width/2 - textSize/2; + textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight/4 - (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + textBounds.width = (float)textSize; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + } + + Rectangle textBoxBounds = { 0 }; + textBoxBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + textBoxBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_TEXTINPUTBOX_HEIGHT/2; + if (message == NULL) textBoxBounds.y = bounds.y + 24 + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + else textBoxBounds.y += (messageInputHeight/2 + messageInputHeight/4); + textBoxBounds.width = bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*2; + textBoxBounds.height = RAYGUI_TEXTINPUTBOX_HEIGHT; + + // Draw control + //-------------------------------------------------------------------- + if (GuiWindowBox(bounds, title)) result = 0; + + // Draw message if available + if (message != NULL) + { + int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(textBounds, message); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment); + } + + int prevTextBoxAlignment = GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT); + GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + + if (secretViewActive != NULL) + { + static char stars[] = "****************"; + if (GuiTextBox(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x, textBoxBounds.y, textBoxBounds.width - 4 - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.height }, + ((*secretViewActive == 1) || textEditMode)? text : stars, textMaxSize, textEditMode)) textEditMode = !textEditMode; + + GuiToggle(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x + textBoxBounds.width - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.y, RAYGUI_TEXTINPUTBOX_HEIGHT, RAYGUI_TEXTINPUTBOX_HEIGHT }, (*secretViewActive == 1)? "#44#" : "#45#", secretViewActive); + } + else + { + if (GuiTextBox(textBoxBounds, text, textMaxSize, textEditMode)) textEditMode = !textEditMode; + } + + GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, prevTextBoxAlignment); + + int prevBtnTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + for (int i = 0; i < buttonCount; i++) + { + if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1; + buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING); + } + + if (result >= 0) textEditMode = false; + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevBtnTextAlignment); + //-------------------------------------------------------------------- + + return result; // Result is the pressed button index +} + +// Grid control +// NOTE: Returns grid mouse-hover selected cell +// About drawing lines at subpixel spacing, simple put, not easy solution: +// REF: https://stackoverflow.com/questions/4435450/2d-opengl-drawing-lines-that-dont-exactly-fit-pixel-raster +int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell) +{ + // Grid lines alpha amount + #if !defined(RAYGUI_GRID_ALPHA) + #define RAYGUI_GRID_ALPHA 0.15f + #endif + + int result = 0; + GuiState state = guiState; + + Vector2 mousePoint = GUI_POINTER_POSITION; + Vector2 currentMouseCell = { -1, -1 }; + + float spaceWidth = spacing/(float)subdivs; + int linesV = (int)(bounds.width/spaceWidth) + 1; + int linesH = (int)(bounds.height/spaceWidth) + 1; + + int color = GuiGetStyle(DEFAULT, LINE_COLOR); + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + // NOTE: Cell values must be the upper left of the cell the mouse is in + currentMouseCell.x = floorf((mousePoint.x - bounds.x)/spacing); + currentMouseCell.y = floorf((mousePoint.y - bounds.y)/spacing); + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_DISABLED) color = GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED); + + if (subdivs > 0) + { + // Draw vertical grid lines + for (int i = 0; i < linesV; i++) + { + Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height + 1 }; + GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); + } + + // Draw horizontal grid lines + for (int i = 0; i < linesH; i++) + { + Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width + 1, 1 }; + GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); + } + } + + if (mouseCell != NULL) *mouseCell = currentMouseCell; + return result; +} + +//---------------------------------------------------------------------------------- +// Tooltip management functions +// NOTE: Tooltips requires some global variables: tooltipPtr +//---------------------------------------------------------------------------------- +// Enable gui tooltips (global state) +void GuiEnableTooltip(void) { guiTooltip = true; } + +// Disable gui tooltips (global state) +void GuiDisableTooltip(void) { guiTooltip = false; } + +// Set tooltip string +void GuiSetTooltip(const char *tooltip) { guiTooltipPtr = tooltip; } + +//---------------------------------------------------------------------------------- +// Styles loading functions +//---------------------------------------------------------------------------------- + +// Load raygui style file (.rgs) +// NOTE: By default a binary file is expected, that file could contain a custom font, +// in that case, custom font image atlas is GRAY+ALPHA and pixel data can be compressed (DEFLATE) +void GuiLoadStyle(const char *fileName) +{ + #define MAX_LINE_BUFFER_SIZE 256 + + bool tryBinary = false; + if (!guiStyleLoaded) GuiLoadStyleDefault(); + + // Try reading the files as text file first + FILE *rgsFile = fopen(fileName, "rt"); + + if (rgsFile != NULL) + { + char buffer[MAX_LINE_BUFFER_SIZE] = { 0 }; + fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile); + + if (buffer[0] == '#') + { + int controlId = 0; + int propertyId = 0; + unsigned int propertyValue = 0; + + while (!feof(rgsFile)) + { + switch (buffer[0]) + { + case 'p': + { + // Style property: p + + sscanf(buffer, "p %d %d 0x%x", &controlId, &propertyId, &propertyValue); + GuiSetStyle(controlId, propertyId, (int)propertyValue); + + } break; + case 'f': + { + // Style font: f + + int fontSize = 0; + char charmapFileName[256] = { 0 }; + char fontFileName[256] = { 0 }; + sscanf(buffer, "f %d %s %[^\r\n]s", &fontSize, charmapFileName, fontFileName); + + Font font = { 0 }; + int *codepoints = NULL; + int codepointCount = 0; + + if (charmapFileName[0] != '0') + { + // Load text data from file + // NOTE: Expected an UTF-8 array of codepoints, no separation + char *textData = LoadFileText(TextFormat("%s/%s", GetDirectoryPath(fileName), charmapFileName)); + codepoints = LoadCodepoints(textData, &codepointCount); + UnloadFileText(textData); + } + + if (fontFileName[0] != '\0') + { + // In case a font is already loaded and it is not default internal font, unload it + if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture); + + if (codepointCount > 0) font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, codepoints, codepointCount); + else font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0); // Default to 95 standard codepoints + } + + // If font texture not properly loaded, revert to default font and size/spacing + if (font.texture.id == 0) + { + font = GetFontDefault(); + GuiSetStyle(DEFAULT, TEXT_SIZE, 10); + GuiSetStyle(DEFAULT, TEXT_SPACING, 1); + } + + UnloadCodepoints(codepoints); + + if ((font.texture.id > 0) && (font.glyphCount > 0)) GuiSetFont(font); + + } break; + default: break; + } + + fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile); + } + } + else tryBinary = true; + + fclose(rgsFile); + } + + if (tryBinary) + { + rgsFile = fopen(fileName, "rb"); + + if (rgsFile != NULL) + { + fseek(rgsFile, 0, SEEK_END); + int fileDataSize = ftell(rgsFile); + fseek(rgsFile, 0, SEEK_SET); + + if (fileDataSize > 0) + { + unsigned char *fileData = (unsigned char *)RAYGUI_CALLOC(fileDataSize, sizeof(unsigned char)); + if (fileData != NULL) + { + fread(fileData, sizeof(unsigned char), fileDataSize, rgsFile); + + GuiLoadStyleFromMemory(fileData, fileDataSize); + + RAYGUI_FREE(fileData); + } + } + + fclose(rgsFile); + } + } +} + +// Load style default over global style +void GuiLoadStyleDefault(void) +{ + // Setting this flag first to avoid cyclic function calls + // when calling GuiSetStyle() and GuiGetStyle() + guiStyleLoaded = true; + + // Initialize default LIGHT style property values + // WARNING: Default value are applied to all controls on set but + // they can be overwritten later on for every custom control + GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x838383ff); + GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0xc9c9c9ff); + GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0x686868ff); + GuiSetStyle(DEFAULT, BORDER_COLOR_FOCUSED, 0x5bb2d9ff); + GuiSetStyle(DEFAULT, BASE_COLOR_FOCUSED, 0xc9effeff); + GuiSetStyle(DEFAULT, TEXT_COLOR_FOCUSED, 0x6c9bbcff); + GuiSetStyle(DEFAULT, BORDER_COLOR_PRESSED, 0x0492c7ff); + GuiSetStyle(DEFAULT, BASE_COLOR_PRESSED, 0x97e8ffff); + GuiSetStyle(DEFAULT, TEXT_COLOR_PRESSED, 0x368bafff); + GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, 0xb5c1c2ff); + GuiSetStyle(DEFAULT, BASE_COLOR_DISABLED, 0xe6e9e9ff); + GuiSetStyle(DEFAULT, TEXT_COLOR_DISABLED, 0xaeb7b8ff); + GuiSetStyle(DEFAULT, BORDER_WIDTH, 1); + GuiSetStyle(DEFAULT, TEXT_PADDING, 0); + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + // Initialize default extended property values + // NOTE: By default, extended property values are initialized to 0 + GuiSetStyle(DEFAULT, TEXT_SIZE, 10); // DEFAULT, shared by all controls + GuiSetStyle(DEFAULT, TEXT_SPACING, 1); // DEFAULT, shared by all controls + GuiSetStyle(DEFAULT, LINE_COLOR, 0x90abb5ff); // DEFAULT specific property + GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xf5f5f5ff); // DEFAULT specific property + GuiSetStyle(DEFAULT, TEXT_LINE_SPACING, 5); // DEFAULT, pixels between lines, from bottom of first line to top of second + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); // DEFAULT, text aligned vertically to middle of text-bounds + + // Initialize control-specific property values + // NOTE: Those properties are in default list but require specific values by control type + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 2); + GuiSetStyle(SLIDER, TEXT_PADDING, 4); + GuiSetStyle(PROGRESSBAR, TEXT_PADDING, 4); + GuiSetStyle(CHECKBOX, TEXT_PADDING, 4); + GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, TEXT_ALIGN_RIGHT); + GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 0); + GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiSetStyle(TEXTBOX, TEXT_PADDING, 4); + GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(VALUEBOX, TEXT_PADDING, 0); + GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(STATUSBAR, TEXT_PADDING, 8); + GuiSetStyle(STATUSBAR, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + + // Initialize extended property values + // NOTE: By default, extended property values are initialized to 0 + GuiSetStyle(TOGGLE, GROUP_PADDING, 2); + GuiSetStyle(SLIDER, SLIDER_WIDTH, 16); + GuiSetStyle(SLIDER, SLIDER_PADDING, 1); + GuiSetStyle(PROGRESSBAR, PROGRESS_PADDING, 1); + GuiSetStyle(CHECKBOX, CHECK_PADDING, 1); + GuiSetStyle(COMBOBOX, COMBO_BUTTON_WIDTH, 32); + GuiSetStyle(COMBOBOX, COMBO_BUTTON_SPACING, 2); + GuiSetStyle(DROPDOWNBOX, ARROW_PADDING, 16); + GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 2); + GuiSetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH, 24); + GuiSetStyle(VALUEBOX, SPINNER_BUTTON_SPACING, 2); + GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0); + GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0); + GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6); + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, 0); + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, 16); + GuiSetStyle(SCROLLBAR, SCROLL_PADDING, 0); + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 12); + GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 28); + GuiSetStyle(LISTVIEW, LIST_ITEMS_SPACING, 2); + GuiSetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH, 1); + GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 12); + GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE); + GuiSetStyle(COLORPICKER, COLOR_SELECTOR_SIZE, 8); + GuiSetStyle(COLORPICKER, HUEBAR_WIDTH, 16); + GuiSetStyle(COLORPICKER, HUEBAR_PADDING, 8); + GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT, 8); + GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW, 2); + + if (guiFont.texture.id != GetFontDefault().texture.id) + { + // Unload previous font texture + UnloadTexture(guiFont.texture); + RAYGUI_FREE(guiFont.recs); + RAYGUI_FREE(guiFont.glyphs); + guiFont.recs = NULL; + guiFont.glyphs = NULL; + + // Setup default raylib font + guiFont = GetFontDefault(); + + // NOTE: Default raylib font character 95 is a white square + Rectangle whiteChar = guiFont.recs[95]; + + // NOTE: Setting up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering + SetShapesTexture(guiFont.texture, RAYGUI_CLITERAL(Rectangle){ whiteChar.x + 1, whiteChar.y + 1, whiteChar.width - 2, whiteChar.height - 2 }); + } +} + +// Get text with icon id prepended +// NOTE: Useful to add icons by name id (enum) instead of +// a number that can change between ricon versions +const char *GuiIconText(int iconId, const char *text) +{ +#if defined(RAYGUI_NO_ICONS) + return NULL; +#else + static char buffer[1024] = { 0 }; + static char iconBuffer[16] = { 0 }; + + if (text != NULL) + { + memset(buffer, 0, 1024); + snprintf(buffer, 1024, "#%03i#", iconId); + + for (int i = 5; i < 1024; i++) + { + buffer[i] = text[i - 5]; + if (text[i - 5] == '\0') break; + } + + return buffer; + } + else + { + snprintf(iconBuffer, 16, "#%03i#", iconId); + + return iconBuffer; + } +#endif +} + +#if !defined(RAYGUI_NO_ICONS) +// Get full icons data pointer +unsigned int *GuiGetIcons(void) { return guiIconsPtr; } + +// Load raygui icons file (.rgi) +// NOTE: In case nameIds are required, they can be requested with loadIconsName, +// they are returned as a guiIconsName[iconCount][RAYGUI_ICON_MAX_NAME_LENGTH], +// WARNING: guiIconsName[]][] memory should be manually freed! +char **GuiLoadIcons(const char *fileName, bool loadIconsName) +{ + // Style File Structure (.rgi) + // ------------------------------------------------------ + // Offset | Size | Type | Description + // ------------------------------------------------------ + // 0 | 4 | char | Signature: "rGI " + // 4 | 2 | short | Version: 100 + // 6 | 2 | short | reserved + + // 8 | 2 | short | Num icons (N) + // 10 | 2 | short | Icons size (Options: 16, 32, 64) (S) + + // Icons name id (32 bytes per name id) + // foreach (icon) + // { + // 12+32*i | 32 | char | Icon NameId + // } + + // Icons data: One bit per pixel, stored as unsigned int array (depends on icon size) + // S*S pixels/32bit per unsigned int = K unsigned int per icon + // foreach (icon) + // { + // ... | K | unsigned int | Icon Data + // } + + FILE *rgiFile = fopen(fileName, "rb"); + + char **guiIconsName = NULL; + + if (rgiFile != NULL) + { + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + short iconCount = 0; + short iconSize = 0; + + fread(signature, 1, 4, rgiFile); + fread(&version, sizeof(short), 1, rgiFile); + fread(&reserved, sizeof(short), 1, rgiFile); + fread(&iconCount, sizeof(short), 1, rgiFile); + fread(&iconSize, sizeof(short), 1, rgiFile); + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'I') && + (signature[3] == ' ')) + { + if (loadIconsName) + { + guiIconsName = (char **)RAYGUI_CALLOC(iconCount, sizeof(char *)); + for (int i = 0; i < iconCount; i++) + { + guiIconsName[i] = (char *)RAYGUI_CALLOC(RAYGUI_ICON_MAX_NAME_LENGTH, sizeof(char)); + fread(guiIconsName[i], 1, RAYGUI_ICON_MAX_NAME_LENGTH, rgiFile); + } + } + else fseek(rgiFile, iconCount*RAYGUI_ICON_MAX_NAME_LENGTH, SEEK_CUR); + + // Read icons data directly over internal icons array + fread(guiIconsPtr, sizeof(unsigned int), (int)iconCount*((int)iconSize*(int)iconSize/32), rgiFile); + } + + fclose(rgiFile); + } + + return guiIconsName; +} + +// Load icons from memory +// WARNING: Binary files only +char **GuiLoadIconsFromMemory(const unsigned char *fileData, int dataSize, bool loadIconsName) +{ + unsigned char *fileDataPtr = (unsigned char *)fileData; + char **guiIconsName = NULL; + + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + short iconCount = 0; + short iconSize = 0; + + memcpy(signature, fileDataPtr, 4); + memcpy(&version, fileDataPtr + 4, sizeof(short)); + memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short)); + memcpy(&iconCount, fileDataPtr + 4 + 2 + 2, sizeof(short)); + memcpy(&iconSize, fileDataPtr + 4 + 2 + 2 + 2, sizeof(short)); + fileDataPtr += 12; + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'I') && + (signature[3] == ' ')) + { + if (loadIconsName) + { + guiIconsName = (char **)RAYGUI_CALLOC(iconCount, sizeof(char *)); + for (int i = 0; i < iconCount; i++) + { + guiIconsName[i] = (char *)RAYGUI_CALLOC(RAYGUI_ICON_MAX_NAME_LENGTH, sizeof(char)); + memcpy(guiIconsName[i], fileDataPtr, RAYGUI_ICON_MAX_NAME_LENGTH); + fileDataPtr += RAYGUI_ICON_MAX_NAME_LENGTH; + } + } + else + { + // Skip icon name data if not required + fileDataPtr += iconCount*RAYGUI_ICON_MAX_NAME_LENGTH; + } + + int iconDataSize = iconCount*((int)iconSize*(int)iconSize/32)*(int)sizeof(unsigned int); + guiIconsPtr = (unsigned int *)RAYGUI_CALLOC(iconDataSize, 1); + + memcpy(guiIconsPtr, fileDataPtr, iconDataSize); + } + + return guiIconsName; +} + +// Draw selected icon using rectangles pixel-by-pixel +void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color) +{ + #define BIT_CHECK(a,b) ((a) & (1u<<(b))) + + for (int i = 0, y = 0; i < RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32; i++) + { + for (int k = 0; k < 32; k++) + { + if (BIT_CHECK(guiIconsPtr[iconId*RAYGUI_ICON_DATA_ELEMENTS + i], k)) + { + #if !defined(RAYGUI_STANDALONE) + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ (float)posX + (k%RAYGUI_ICON_SIZE)*pixelSize, (float)posY + y*pixelSize, (float)pixelSize, (float)pixelSize }, 0, BLANK, color); + #endif + } + + if ((k == 15) || (k == 31)) y++; + } + } +} + +// Set icon drawing size +void GuiSetIconScale(int scale) +{ + if (scale >= 1) guiIconScale = scale; +} + +// Get text width considering gui style and icon size (if required) +int GuiGetTextWidth(const char *text) +{ + #if !defined(ICON_TEXT_PADDING) + #define ICON_TEXT_PADDING 4 + #endif + + Vector2 textSize = { 0 }; + int textIconOffset = 0; + + if ((text != NULL) && (text[0] != '\0')) + { + if (text[0] == '#') + { + for (int i = 1; (i < 5) && (text[i] != '\0'); i++) + { + if (text[i] == '#') + { + textIconOffset = i; + break; + } + } + } + + text += textIconOffset; + + // Make sure guiFont is set, GuiGetStyle() initializes it lazynessly + float fontSize = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + + // Custom MeasureText() implementation + if ((guiFont.texture.id > 0) && (text != NULL)) + { + // Get size in bytes of text, considering end of line and line break + int size = 0; + for (int i = 0; i < MAX_LINE_BUFFER_SIZE; i++) + { + if ((text[i] != '\0') && (text[i] != '\n')) size++; + else break; + } + + float scaleFactor = fontSize/(float)guiFont.baseSize; + textSize.y = (float)guiFont.baseSize*scaleFactor; + float glyphWidth = 0.0f; + + for (int i = 0, codepointSize = 0; i < size; i += codepointSize) + { + int codepoint = GetCodepointNext(&text[i], &codepointSize); + int codepointIndex = GetGlyphIndex(guiFont, codepoint); + + if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor); + else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor); + + textSize.x += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + } + + if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE + ICON_TEXT_PADDING); + } + + return (int)textSize.x; +} + +#endif // !RAYGUI_NO_ICONS + +//---------------------------------------------------------------------------------- +// Module Internal Functions Definition +//---------------------------------------------------------------------------------- +// Load style from memory +// WARNING: Binary files only +static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize) +{ + unsigned char *fileDataPtr = (unsigned char *)fileData; + + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + int propertyCount = 0; + + memcpy(signature, fileDataPtr, 4); + memcpy(&version, fileDataPtr + 4, sizeof(short)); + memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short)); + memcpy(&propertyCount, fileDataPtr + 4 + 2 + 2, sizeof(int)); + fileDataPtr += 12; + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'S') && + (signature[3] == ' ')) + { + short controlId = 0; + short propertyId = 0; + unsigned int propertyValue = 0; + + for (int i = 0; i < propertyCount; i++) + { + memcpy(&controlId, fileDataPtr, sizeof(short)); + memcpy(&propertyId, fileDataPtr + 2, sizeof(short)); + memcpy(&propertyValue, fileDataPtr + 2 + 2, sizeof(unsigned int)); + fileDataPtr += 8; + + if (controlId == 0) // DEFAULT control + { + // If a DEFAULT property is loaded, it is propagated to all controls + // NOTE: All DEFAULT properties should be defined first in the file + GuiSetStyle(0, (int)propertyId, propertyValue); + + if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int j = 1; j < RAYGUI_MAX_CONTROLS; j++) GuiSetStyle(j, (int)propertyId, propertyValue); + } + else GuiSetStyle((int)controlId, (int)propertyId, propertyValue); + } + + // Font loading is highly dependant on raylib API to load font data and image + +#if !defined(RAYGUI_STANDALONE) + // Load custom font if available + int fontDataSize = 0; + memcpy(&fontDataSize, fileDataPtr, sizeof(int)); + fileDataPtr += 4; + + if (fontDataSize > 0) + { + Font font = { 0 }; + int fontType = 0; // 0-Normal, 1-SDF + + memcpy(&font.baseSize, fileDataPtr, sizeof(int)); + memcpy(&font.glyphCount, fileDataPtr + 4, sizeof(int)); + memcpy(&fontType, fileDataPtr + 4 + 4, sizeof(int)); + fileDataPtr += 12; + + // Load font white rectangle + Rectangle fontWhiteRec = { 0 }; + memcpy(&fontWhiteRec, fileDataPtr, sizeof(Rectangle)); + fileDataPtr += 16; + + // Load font image parameters + int fontImageUncompSize = 0; + int fontImageCompSize = 0; + memcpy(&fontImageUncompSize, fileDataPtr, sizeof(int)); + memcpy(&fontImageCompSize, fileDataPtr + 4, sizeof(int)); + fileDataPtr += 8; + + Image imFont = { 0 }; + imFont.mipmaps = 1; + memcpy(&imFont.width, fileDataPtr, sizeof(int)); + memcpy(&imFont.height, fileDataPtr + 4, sizeof(int)); + memcpy(&imFont.format, fileDataPtr + 4 + 4, sizeof(int)); + fileDataPtr += 12; + + if ((fontImageCompSize > 0) && (fontImageCompSize != fontImageUncompSize)) + { + // Compressed font atlas image data (DEFLATE), it requires DecompressData() + int dataUncompSize = 0; + unsigned char *compData = (unsigned char *)RAYGUI_CALLOC(fontImageCompSize, sizeof(unsigned char)); + memcpy(compData, fileDataPtr, fontImageCompSize); + fileDataPtr += fontImageCompSize; + + imFont.data = DecompressData(compData, fontImageCompSize, &dataUncompSize); + + // Security check, dataUncompSize must match the provided fontImageUncompSize + if (dataUncompSize != fontImageUncompSize) RAYGUI_LOG("WARNING: Uncompressed font atlas image data could be corrupted"); + + RAYGUI_FREE(compData); + } + else + { + // Font atlas image data is not compressed + imFont.data = (unsigned char *)RAYGUI_CALLOC(fontImageUncompSize, sizeof(unsigned char)); + memcpy(imFont.data, fileDataPtr, fontImageUncompSize); + fileDataPtr += fontImageUncompSize; + } + + if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture); + font.texture = LoadTextureFromImage(imFont); + + RAYGUI_FREE(imFont.data); + + // Validate font atlas texture was loaded correctly + if (font.texture.id != 0) + { + // Load font recs data + int recsDataSize = font.glyphCount*sizeof(Rectangle); + int recsDataCompressedSize = 0; + + // WARNING: Version 400 adds the compression size parameter + if (version >= 400) + { + // RGS files version 400 support compressed recs data + memcpy(&recsDataCompressedSize, fileDataPtr, sizeof(int)); + fileDataPtr += sizeof(int); + } + + if ((recsDataCompressedSize > 0) && (recsDataCompressedSize != recsDataSize)) + { + // Recs data is compressed, uncompress it + unsigned char *recsDataCompressed = (unsigned char *)RAYGUI_CALLOC(recsDataCompressedSize, sizeof(unsigned char)); + + memcpy(recsDataCompressed, fileDataPtr, recsDataCompressedSize); + fileDataPtr += recsDataCompressedSize; + + int recsDataUncompSize = 0; + font.recs = (Rectangle *)DecompressData(recsDataCompressed, recsDataCompressedSize, &recsDataUncompSize); + + // Security check, data uncompressed size must match the expected original data size + if (recsDataUncompSize != recsDataSize) RAYGUI_LOG("WARNING: Uncompressed font recs data could be corrupted"); + + RAYGUI_FREE(recsDataCompressed); + } + else + { + // Recs data is uncompressed + font.recs = (Rectangle *)RAYGUI_CALLOC(font.glyphCount, sizeof(Rectangle)); + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.recs[i], fileDataPtr, sizeof(Rectangle)); + fileDataPtr += sizeof(Rectangle); + } + } + + // Load font glyphs info data + int glyphsDataSize = font.glyphCount*16; // 16 bytes data per glyph + int glyphsDataCompressedSize = 0; + + // WARNING: Version 400 adds the compression size parameter + if (version >= 400) + { + // RGS files version 400 support compressed glyphs data + memcpy(&glyphsDataCompressedSize, fileDataPtr, sizeof(int)); + fileDataPtr += sizeof(int); + } + + // Allocate required glyphs space to fill with data + font.glyphs = (GlyphInfo *)RAYGUI_CALLOC(font.glyphCount, sizeof(GlyphInfo)); + + if ((glyphsDataCompressedSize > 0) && (glyphsDataCompressedSize != glyphsDataSize)) + { + // Glyphs data is compressed, uncompress it + unsigned char *glypsDataCompressed = (unsigned char *)RAYGUI_CALLOC(glyphsDataCompressedSize, sizeof(unsigned char)); + + memcpy(glypsDataCompressed, fileDataPtr, glyphsDataCompressedSize); + fileDataPtr += glyphsDataCompressedSize; + + int glyphsDataUncompSize = 0; + unsigned char *glyphsDataUncomp = DecompressData(glypsDataCompressed, glyphsDataCompressedSize, &glyphsDataUncompSize); + + // Security check, data uncompressed size must match the expected original data size + if (glyphsDataUncompSize != glyphsDataSize) RAYGUI_LOG("WARNING: Uncompressed font glyphs data could be corrupted"); + + unsigned char *glyphsDataUncompPtr = glyphsDataUncomp; + + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.glyphs[i].value, glyphsDataUncompPtr, sizeof(int)); + memcpy(&font.glyphs[i].offsetX, glyphsDataUncompPtr + 4, sizeof(int)); + memcpy(&font.glyphs[i].offsetY, glyphsDataUncompPtr + 8, sizeof(int)); + memcpy(&font.glyphs[i].advanceX, glyphsDataUncompPtr + 12, sizeof(int)); + glyphsDataUncompPtr += 16; + } + + RAYGUI_FREE(glypsDataCompressed); + RAYGUI_FREE(glyphsDataUncomp); + } + else + { + // Glyphs data is uncompressed + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.glyphs[i].value, fileDataPtr, sizeof(int)); + memcpy(&font.glyphs[i].offsetX, fileDataPtr + 4, sizeof(int)); + memcpy(&font.glyphs[i].offsetY, fileDataPtr + 8, sizeof(int)); + memcpy(&font.glyphs[i].advanceX, fileDataPtr + 12, sizeof(int)); + fileDataPtr += 16; + } + } + } + else font = GetFontDefault(); // Fallback in case of errors loading font atlas texture + + GuiSetFont(font); + + // Set font texture source rectangle to be used as white texture to draw shapes + // NOTE: It makes possible to draw shapes and text (full UI) in a single draw call + if ((fontWhiteRec.x > 0) && + (fontWhiteRec.y > 0) && + (fontWhiteRec.width > 0) && + (fontWhiteRec.height > 0)) SetShapesTexture(font.texture, fontWhiteRec); + } +#endif + } +} + +// Get text bounds considering control bounds +static Rectangle GetTextBounds(int control, Rectangle bounds) +{ + Rectangle textBounds = bounds; + + textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH); + textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH) + GuiGetStyle(control, TEXT_PADDING); + textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); + textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); // NOTE: Text is processed line per line! + + // Depending on control, TEXT_PADDING and TEXT_ALIGNMENT properties could affect the text-bounds + switch (control) + { + case COMBOBOX: + case DROPDOWNBOX: + case LISTVIEW: + // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW + case SLIDER: + case CHECKBOX: + case VALUEBOX: + case CONTROL11: + // TODO: More special cases (label on side): SLIDER, CHECKBOX, VALUEBOX, SPINNER + default: + { + // TODO: WARNING: TEXT_ALIGNMENT is already considered in GuiDrawText() + if (GuiGetStyle(control, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) textBounds.x -= GuiGetStyle(control, TEXT_PADDING); + else textBounds.x += GuiGetStyle(control, TEXT_PADDING); + } + break; + } + + return textBounds; +} + +// Get text icon if provided and move text cursor +// NOTE: Up to #999# values supported for iconId +static const char *GetTextIcon(const char *text, int *iconId) +{ +#if !defined(RAYGUI_NO_ICONS) + *iconId = -1; + if (text[0] == '#') // Maybe it is stars with an icon, ending # must be found + { + char iconValue[4] = { 0 }; // Maximum length for icon value: 3 digits + '\0' + + int pos = 1; + while ((pos < 4) && (text[pos] >= '0') && (text[pos] <= '9')) + { + iconValue[pos - 1] = text[pos]; + pos++; + } + + if (text[pos] == '#') + { + *iconId = TextToInteger(iconValue); + + // Move text pointer after icon + // WARNING: If only icon provided, it could point to EOL character: '\0' + if (*iconId >= 0) text += (pos + 1); + } + } +#endif + + return text; +} + +// Get text divided into lines (by line-breaks '\n') +// WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator! +static const char **GetTextLines(const char *text, int *count) +{ + #define RAYGUI_MAX_TEXT_LINES 128 + + static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 }; + for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings + + int textLength = (int)strlen(text); + + lines[0] = text; + *count = 1; + + for (int i = 0; (i < textLength) && (*count < RAYGUI_MAX_TEXT_LINES); i++) + { + if ((text[i] == '\n') && ((i + 1) < textLength)) + { + lines[*count] = &text[i + 1]; + *count += 1; + } + } + + return lines; +} + +// Get text width to next space for provided string +static float GetNextSpaceWidth(const char *text, int *nextSpaceIndex) +{ + float width = 0; + int codepointByteCount = 0; + int codepoint = 0; + int index = 0; + float glyphWidth = 0; + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize; + + for (int i = 0; text[i] != '\0'; i++) + { + if (text[i] != ' ') + { + codepoint = GetCodepoint(&text[i], &codepointByteCount); + index = GetGlyphIndex(guiFont, codepoint); + glyphWidth = (guiFont.glyphs[index].advanceX == 0)? guiFont.recs[index].width*scaleFactor : guiFont.glyphs[index].advanceX*scaleFactor; + width += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + else + { + *nextSpaceIndex = i; + break; + } + } + + return width; +} + +// Gui draw text using default font +static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint) +{ + #define TEXT_VALIGN_PIXEL_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect + + #if !defined(ICON_TEXT_PADDING) + #define ICON_TEXT_PADDING 4 + #endif + + if ((text == NULL) || (text[0] == '\0')) return; // Security check + + // PROCEDURE: + // - Text is processed line per line + // - For every line, horizontal alignment is defined + // - For all text, vertical alignment is defined (multiline text only) + // - For every line, wordwrap mode is checked (useful for GuitextBox(), read-only) + + // Get text lines (using '\n' as delimiter) to be processed individually + // WARNING: GuiTextSplit() function can't be used now because it can have already been used + // before the GuiDrawText() call and its buffer is static, it would be overriden :( + int lineCount = 0; + const char **lines = GetTextLines(text, &lineCount); + + // Text style variables + //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT); + int alignmentVertical = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL); + int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); // Wrap-mode only available in read-only mode, no for text editing + + // TODO: WARNING: This totalHeight is not valid for vertical alignment in case of word-wrap + float totalHeight = (float)(lineCount*GuiGetStyle(DEFAULT, TEXT_SIZE) + (lineCount - 1)*GuiGetStyle(DEFAULT, TEXT_LINE_SPACING)); + float posOffsetY = 0.0f; + + for (int i = 0; i < lineCount; i++) + { + int iconId = 0; + lines[i] = GetTextIcon(lines[i], &iconId); // Check text for icon and move cursor + + // Get text position depending on alignment and iconId + //--------------------------------------------------------------------------------- + Vector2 textBoundsPosition = { textBounds.x, textBounds.y }; + float textBoundsWidthOffset = 0.0f; + + // NOTE: Get text size after icon has been processed + // WARNING: GuiGetTextWidth() also processes text icon to get width! -> Really needed? + int textSizeX = GuiGetTextWidth(lines[i]); + + // If text requires an icon, add size to measure + if (iconId >= 0) + { + textSizeX += RAYGUI_ICON_SIZE*guiIconScale; + + // WARNING: If only icon provided, text could be pointing to EOF character: '\0' +#if !defined(RAYGUI_NO_ICONS) + if ((lines[i] != NULL) && (lines[i][0] != '\0')) textSizeX += ICON_TEXT_PADDING; +#endif + } + + // Check guiTextAlign global variables + switch (alignment) + { + case TEXT_ALIGN_LEFT: textBoundsPosition.x = textBounds.x; break; + case TEXT_ALIGN_CENTER: textBoundsPosition.x = textBounds.x + textBounds.width/2 - textSizeX/2; break; + case TEXT_ALIGN_RIGHT: textBoundsPosition.x = textBounds.x + textBounds.width - textSizeX; break; + default: break; + } + + if (textSizeX > textBounds.width && (lines[i] != NULL) && (lines[i][0] != '\0')) textBoundsPosition.x = textBounds.x; + + switch (alignmentVertical) + { + // Only valid in case of wordWrap = 0; + case TEXT_ALIGN_TOP: textBoundsPosition.y = textBounds.y + posOffsetY; break; + case TEXT_ALIGN_MIDDLE: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break; + case TEXT_ALIGN_BOTTOM: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height - totalHeight + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break; + default: break; + } + + // NOTE: Make sure getting pixel-perfect coordinates, + // In case of decimals, it could result in text positioning artifacts + textBoundsPosition.x = (float)((int)textBoundsPosition.x); + textBoundsPosition.y = (float)((int)textBoundsPosition.y); + //--------------------------------------------------------------------------------- + + // Draw text (with icon if available) + //--------------------------------------------------------------------------------- +#if !defined(RAYGUI_NO_ICONS) + if (iconId >= 0) + { + // NOTE: Considering icon height, probably different than text size + GuiDrawIcon(iconId, (int)textBoundsPosition.x, (int)(textBounds.y + textBounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height)), guiIconScale, tint); + textBoundsPosition.x += (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + textBoundsWidthOffset = (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + } +#endif + // Get size in bytes of text, + // considering end of line and line break + int lineSize = 0; + for (int c = 0; (lines[i][c] != '\0') && (lines[i][c] != '\n') && (lines[i][c] != '\r'); c++, lineSize++){ } + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize; + + int lastSpaceIndex = 0; + bool tempWrapCharMode = false; + + int textOffsetY = 0; + float textOffsetX = 0.0f; + float glyphWidth = 0; + + int ellipsisWidth = GuiGetTextWidth("..."); + bool textOverflow = false; + for (int c = 0, codepointSize = 0; c < lineSize; c += codepointSize) + { + int codepoint = GetCodepointNext(&lines[i][c], &codepointSize); + int index = GetGlyphIndex(guiFont, codepoint); + + // NOTE: Normally, exiting the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but all of the bad bytes need to be drawn using the '?' symbol, moving one byte + if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size + + // Get glyph width to check if it goes out of bounds + if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor); + else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor; + + // Wrap mode text measuring, to validate if + // it can be drawn or a new line is required + if (wrapMode == TEXT_WRAP_CHAR) + { + // Jump to next line if current character reach end of the box limits + if ((textOffsetX + glyphWidth) > textBounds.width - textBoundsWidthOffset) + { + textOffsetX = 0.0f; + textOffsetY += (GuiGetStyle(DEFAULT, TEXT_SIZE) + GuiGetStyle(DEFAULT, TEXT_LINE_SPACING)); + + if (tempWrapCharMode) // Wrap at char level when too long words + { + wrapMode = TEXT_WRAP_WORD; + tempWrapCharMode = false; + } + } + } + else if (wrapMode == TEXT_WRAP_WORD) + { + if (codepoint == 32) lastSpaceIndex = c; + + // Get width to next space in line + int nextSpaceIndex = 0; + float nextSpaceWidth = GetNextSpaceWidth(lines[i] + c, &nextSpaceIndex); + + int nextSpaceIndex2 = 0; + float nextWordSize = GetNextSpaceWidth(lines[i] + lastSpaceIndex + 1, &nextSpaceIndex2); + + if (nextWordSize > textBounds.width - textBoundsWidthOffset) + { + // Considering the case the next word is longer than bounds + tempWrapCharMode = true; + wrapMode = TEXT_WRAP_CHAR; + } + else if ((textOffsetX + nextSpaceWidth) > textBounds.width - textBoundsWidthOffset) + { + textOffsetX = 0.0f; + textOffsetY += (GuiGetStyle(DEFAULT, TEXT_SIZE) + GuiGetStyle(DEFAULT, TEXT_LINE_SPACING)); + } + } + + if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint + else + { + // TODO: There are multiple types of spaces in Unicode, + // maybe it's a good idea to add support for more: http://jkorpela.fi/chars/spaces.html + if ((codepoint != ' ') && (codepoint != '\t')) // Do not draw codepoints with no glyph + { + if (wrapMode == TEXT_WRAP_NONE) + { + // Draw only required text glyphs fitting the textBounds.width + if (textSizeX > textBounds.width) + { + if (textOffsetX <= (textBounds.width - glyphWidth - textBoundsWidthOffset - ellipsisWidth)) + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + else if (!textOverflow) + { + textOverflow = true; + + for (int j = 0; j < ellipsisWidth; j += ellipsisWidth/3) + { + DrawTextCodepoint(guiFont, '.', RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX + j, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + } + else + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) + { + // Draw only glyphs inside the bounds + if ((textBoundsPosition.y + textOffsetY) <= (textBounds.y + textBounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE))) + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + } + + if (guiFont.glyphs[index].advanceX == 0) textOffsetX += ((float)guiFont.recs[index].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + else textOffsetX += ((float)guiFont.glyphs[index].advanceX*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + } + + if (wrapMode == TEXT_WRAP_NONE) posOffsetY += (float)(GuiGetStyle(DEFAULT, TEXT_SIZE) + GuiGetStyle(DEFAULT, TEXT_LINE_SPACING)); + else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) posOffsetY += (textOffsetY + (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING)); + //--------------------------------------------------------------------------------- + } + +#if defined(RAYGUI_DEBUG_TEXT_BOUNDS) + GuiDrawRectangle(textBounds, 0, WHITE, Fade(BLUE, 0.4f)); +#endif +} + +// Gui draw rectangle using default raygui plain style with borders +static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color) +{ + if (color.a > 0) + { + // Draw rectangle filled with color + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, GuiFade(color, guiAlpha)); + } + + if (borderWidth > 0) + { + // Draw rectangle border lines with color + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x + (int)rec.width - borderWidth, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x, (int)rec.y + (int)rec.height - borderWidth, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha)); + } + +#if defined(RAYGUI_DEBUG_RECS_BOUNDS) + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, Fade(RED, 0.4f)); +#endif +} + +// Draw tooltip using control bounds +static void GuiTooltip(Rectangle controlRec) +{ + if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiControlExclusiveMode) + { + Vector2 textSize = MeasureTextEx(GuiGetFont(), guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + + if ((controlRec.x + textSize.x + 16) > GetScreenWidth()) controlRec.x -= (textSize.x + 16 - controlRec.width); + + int lineCount = 0; + GetTextLines(guiTooltipPtr, &lineCount); // Only using the line count + if ((controlRec.y + controlRec.height + textSize.y + 4 + 8*lineCount) > GetScreenHeight()) + controlRec.y -= (controlRec.height + textSize.y + 4 + 8*lineCount); + + // TODO: Probably TEXT_LINE_SPACING should be considered on panel size instead of hardcoding 8.0f + GuiPanel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, textSize.y + 8.0f*lineCount }, NULL); + + int textPadding = GuiGetStyle(LABEL, TEXT_PADDING); + int textAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_PADDING, 0); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, textSize.y + 8.0f*lineCount }, guiTooltipPtr); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, textAlignment); + GuiSetStyle(LABEL, TEXT_PADDING, textPadding); + } +} + +// Split controls text into multiple strings +// Also check for multiple columns (required by GuiToggleGroup()) +static char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow) +{ + // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) + // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, + // all used memory is static... it has some limitations: + // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS + // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE + // NOTE: Those definitions could be externally provided if required + + // TODO: HACK: GuiTextSplit() - Review how textRows are returned to user + // textRow is an externally provided array of integers that stores row number for every splitted string + + #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS) + #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128 + #endif + #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE) + #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 + #endif + + static char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data) + static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added) + memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); + + result[0] = buffer; + int counter = 1; + + if (textRow != NULL) textRow[0] = 0; + + // Count how many substrings text contains and point to every one of them + for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++) + { + buffer[i] = text[i]; + if (buffer[i] == '\0') break; + else if ((buffer[i] == delimiter) || (buffer[i] == '\n')) + { + result[counter] = buffer + i + 1; + + if (textRow != NULL) + { + if (buffer[i] == '\n') textRow[counter] = textRow[counter - 1] + 1; + else textRow[counter] = textRow[counter - 1]; + } + + buffer[i] = '\0'; // Set an end of string at this point + + counter++; + if (counter >= RAYGUI_TEXTSPLIT_MAX_ITEMS) break; + } + } + + *count = counter; + + return result; +} + +// Convert color data from RGB to HSV +// NOTE: Color data should be passed normalized +static Vector3 ConvertRGBtoHSV(Vector3 rgb) +{ + Vector3 hsv = { 0 }; + float min = 0.0f; + float max = 0.0f; + float delta = 0.0f; + + min = (rgb.x < rgb.y)? rgb.x : rgb.y; + min = (min < rgb.z)? min : rgb.z; + + max = (rgb.x > rgb.y)? rgb.x : rgb.y; + max = (max > rgb.z)? max : rgb.z; + + hsv.z = max; // Value + delta = max - min; + + if (delta < 0.00001f) + { + hsv.y = 0.0f; + hsv.x = 0.0f; // Undefined, maybe NAN? + return hsv; + } + + if (max > 0.0f) + { + // NOTE: If max is 0, this divide would cause a crash + hsv.y = (delta/max); // Saturation + } + else + { + // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined + hsv.y = 0.0f; + hsv.x = 0.0f; // Undefined, maybe NAN? + return hsv; + } + + // NOTE: Comparing float values could not work properly + if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta + else + { + if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow + else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan + } + + hsv.x *= 60.0f; // Convert to degrees + + if (hsv.x < 0.0f) hsv.x += 360.0f; + + return hsv; +} + +// Convert color data from HSV to RGB +// NOTE: Color data should be passed normalized +static Vector3 ConvertHSVtoRGB(Vector3 hsv) +{ + Vector3 rgb = { 0 }; + float hh = 0.0f, p = 0.0f, q = 0.0f, t = 0.0f, ff = 0.0f; + long i = 0; + + // NOTE: Comparing float values could not work properly + if (hsv.y <= 0.0f) + { + rgb.x = hsv.z; + rgb.y = hsv.z; + rgb.z = hsv.z; + return rgb; + } + + hh = hsv.x; + if (hh >= 360.0f) hh = 0.0f; + hh /= 60.0f; + + i = (long)hh; + ff = hh - i; + p = hsv.z*(1.0f - hsv.y); + q = hsv.z*(1.0f - (hsv.y*ff)); + t = hsv.z*(1.0f - (hsv.y*(1.0f - ff))); + + switch (i) + { + case 0: + { + rgb.x = hsv.z; + rgb.y = t; + rgb.z = p; + } break; + case 1: + { + rgb.x = q; + rgb.y = hsv.z; + rgb.z = p; + } break; + case 2: + { + rgb.x = p; + rgb.y = hsv.z; + rgb.z = t; + } break; + case 3: + { + rgb.x = p; + rgb.y = q; + rgb.z = hsv.z; + } break; + case 4: + { + rgb.x = t; + rgb.y = p; + rgb.z = hsv.z; + } break; + case 5: + default: + { + rgb.x = hsv.z; + rgb.y = p; + rgb.z = q; + } break; + } + + return rgb; +} + +// Scroll bar control (used by GuiScrollPanel()) +static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue) +{ + GuiState state = guiState; + + // Is the scrollbar horizontal or vertical? + bool isVertical = (bounds.width > bounds.height)? false : true; + + // The size (width or height depending on scrollbar type) of the spinner buttons + const int spinnerSize = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)? + (isVertical? (int)bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) : + (int)bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)) : 0; + + // Arrow buttons [<] [>] [∧] [∨] + Rectangle arrowUpLeft = { 0 }; + Rectangle arrowDownRight = { 0 }; + + // Actual area of the scrollbar excluding the arrow buttons + Rectangle scrollbar = { 0 }; + + // Slider bar that moves --[///]----- + Rectangle slider = { 0 }; + + // Normalize value + if (value > maxValue) value = maxValue; + if (value < minValue) value = minValue; + + int valueRange = maxValue - minValue; + if (valueRange <= 0) valueRange = 1; + + int sliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); + if (sliderSize < 1) sliderSize = 1; // TODO: Consider a minimum slider size + + // Calculate rectangles for all of the components + arrowUpLeft = RAYGUI_CLITERAL(Rectangle){ + (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), + (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), + (float)spinnerSize, (float)spinnerSize }; + + if (isVertical) + { + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + bounds.height - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize }; + scrollbar = RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), arrowUpLeft.y + arrowUpLeft.height, bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)), bounds.height - arrowUpLeft.height - arrowDownRight.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) }; + + // Make sure the slider won't get outside of the scrollbar + sliderSize = (sliderSize >= scrollbar.height)? ((int)scrollbar.height - 2) : sliderSize; + slider = RAYGUI_CLITERAL(Rectangle){ + bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), + scrollbar.y + (int)(((float)(value - minValue)/valueRange)*(scrollbar.height - sliderSize)), + bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)), + (float)sliderSize }; + } + else // horizontal + { + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + bounds.width - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize }; + scrollbar = RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x + arrowUpLeft.width, bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), bounds.width - arrowUpLeft.width - arrowDownRight.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)) }; + + // Make sure the slider won't get outside of the scrollbar + sliderSize = (sliderSize >= scrollbar.width)? ((int)scrollbar.width - 2) : sliderSize; + slider = RAYGUI_CLITERAL(Rectangle){ + scrollbar.x + (int)(((float)(value - minValue)/valueRange)*(scrollbar.width - sliderSize)), + bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), + (float)sliderSize, + bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)) }; + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GUI_POINTER_POSITION; + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (GUI_BUTTON_DOWN && + !CheckCollisionPointRec(mousePoint, arrowUpLeft) && + !CheckCollisionPointRec(mousePoint, arrowDownRight)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue); + else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue); + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + + // Handle mouse wheel + float scrollDelta = GUI_SCROLL_DELTA; + if (scrollDelta != 0) value += (int)scrollDelta; + + // Handle mouse button down + if (GUI_BUTTON_PRESSED) + { + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + // Check arrows click + if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + else if (CheckCollisionPointRec(mousePoint, arrowDownRight)) value += valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + else if (!CheckCollisionPointRec(mousePoint, slider)) + { + // If click on scrollbar position but not on slider, place slider directly on that position + if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue); + else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue); + } + + state = STATE_PRESSED; + } + + // Keyboard control on mouse hover scrollbar + /* + if (isVertical) + { + if (GUI_KEY_DOWN(KEY_DOWN)) value += 5; + else if (GUI_KEY_DOWN(KEY_UP)) value -= 5; + } + else + { + if (GUI_KEY_DOWN(KEY_RIGHT)) value += 5; + else if (GUI_KEY_DOWN(KEY_LEFT)) value -= 5; + } + */ + } + + // Normalize value + if (value > maxValue) value = maxValue; + if (value < minValue) value = minValue; + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SCROLLBAR, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED))); // Draw the background + + GuiDrawRectangle(scrollbar, 0, BLANK, GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL))); // Draw the scrollbar active area background + GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BORDER + state*3))); // Draw the slider bar + + // Draw arrows (using icon if available) + if (GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)) + { +#if defined(RAYGUI_NO_ICONS) + GuiDrawText(isVertical? "^" : "<", + RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); + GuiDrawText(isVertical? "v" : ">", + RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); +#else + GuiDrawText(isVertical? "#121#" : "#118#", + RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_UP_FILL / ICON_ARROW_LEFT_FILL + GuiDrawText(isVertical? "#120#" : "#119#", + RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL +#endif + } + //-------------------------------------------------------------------- + + return value; +} + +// Color fade-in or fade-out, alpha goes from 0.0f to 1.0f +// WARNING: It multiplies current alpha by alpha scale factor +static Color GuiFade(Color color, float alpha) +{ + if (alpha < 0.0f) alpha = 0.0f; + else if (alpha > 1.0f) alpha = 1.0f; + + Color result = { color.r, color.g, color.b, (unsigned char)(color.a*alpha) }; + + return result; +} + +#if defined(RAYGUI_STANDALONE) +// Returns a Color struct from hexadecimal value +static Color GetColor(int hexValue) +{ + Color color; + + color.r = (unsigned char)(hexValue >> 24) & 0xff; + color.g = (unsigned char)(hexValue >> 16) & 0xff; + color.b = (unsigned char)(hexValue >> 8) & 0xff; + color.a = (unsigned char)hexValue & 0xff; + + return color; +} + +// Returns hexadecimal value for a Color +static int ColorToInt(Color color) +{ + return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a); +} + +// Check if point is inside rectangle +static bool CheckCollisionPointRec(Vector2 point, Rectangle rec) +{ + bool collision = false; + + if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && + (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true; + + return collision; +} + +// Formatting of text with variables to 'embed' +static const char *TextFormat(const char *text, ...) +{ + #if !defined(RAYGUI_TEXTFORMAT_MAX_SIZE) + #define RAYGUI_TEXTFORMAT_MAX_SIZE 256 + #endif + + static char buffer[RAYGUI_TEXTFORMAT_MAX_SIZE]; + + va_list args; + va_start(args, text); + vsnprintf(buffer, RAYGUI_TEXTFORMAT_MAX_SIZE, text, args); + va_end(args); + + return buffer; +} + +// Draw rectangle with vertical gradient fill color +// NOTE: This function is only used by GuiColorPicker() +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2) +{ + Rectangle bounds = { (float)posX, (float)posY, (float)width, (float)height }; + DrawRectangleGradientEx(bounds, color1, color2, color2, color1); +} + +// Split string into multiple strings +char **TextSplit(const char *text, char delimiter, int *count) +{ + // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) + // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, + // all used memory is static... it has some limitations: + // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS + // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE + + #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS) + #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128 + #endif + #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE) + #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 + #endif + + static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; + static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; + memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); + + result[0] = buffer; + int counter = 0; + + if (text != NULL) + { + counter = 1; + + // Count how many substrings text contains and point to every one of them + for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++) + { + buffer[i] = text[i]; + if (buffer[i] == '\0') break; + else if (buffer[i] == delimiter) + { + buffer[i] = '\0'; // Set an end of string at this point + result[counter] = buffer + i + 1; + counter++; + + if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break; + } + } + } + + *count = counter; + return result; +} + +// Get integer value from text +// NOTE: This function replaces atoi() [stdlib.h] +static int TextToInteger(const char *text) +{ + int value = 0; + int sign = 1; + + if ((text[0] == '+') || (text[0] == '-')) + { + if (text[0] == '-') sign = -1; + text++; + } + + for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10 + (int)(text[i] - '0'); + + return value*sign; +} + +// Get float value from text +// NOTE: This function replaces atof() [stdlib.h] +// WARNING: Only '.' character is understood as decimal point +static float TextToFloat(const char *text) +{ + float value = 0.0f; + float sign = 1.0f; + + if ((text[0] == '+') || (text[0] == '-')) + { + if (text[0] == '-') sign = -1.0f; + text++; + } + + int i = 0; + for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0'); + + if (text[i++] != '.') value *= sign; + else + { + float divisor = 10.0f; + for (; ((text[i] >= '0') && (text[i] <= '9')); i++) + { + value += ((float)(text[i] - '0'))/divisor; + divisor = divisor*10.0f; + } + } + + return value; +} + +// Encode codepoint into UTF-8 text (char array size returned as parameter) +static const char *CodepointToUTF8(int codepoint, int *byteSize) +{ + static char utf8[6] = { 0 }; + int size = 0; + + if (codepoint <= 0x7f) + { + utf8[0] = (char)codepoint; + size = 1; + } + else if (codepoint <= 0x7ff) + { + utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0); + utf8[1] = (char)((codepoint & 0x3f) | 0x80); + size = 2; + } + else if (codepoint <= 0xffff) + { + utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0); + utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80); + utf8[2] = (char)((codepoint & 0x3f) | 0x80); + size = 3; + } + else if (codepoint <= 0x10ffff) + { + utf8[0] = (char)(((codepoint >> 18) & 0x07) | 0xf0); + utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80); + utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80); + utf8[3] = (char)((codepoint & 0x3f) | 0x80); + size = 4; + } + + *byteSize = size; + + return utf8; +} + +// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found +// When a invalid UTF-8 byte is encountered, exiting as soon as possible and returning a '?'(0x3f) codepoint +// Total number of bytes processed are returned as a parameter +// NOTE: The standard says U+FFFD should be returned in case of errors +// but that character is not supported by the default font in raylib +static int GetCodepointNext(const char *text, int *codepointSize) +{ + const char *ptr = text; + int codepoint = 0x3f; // Codepoint (defaults to '?') + *codepointSize = 1; + + // Get current codepoint and bytes processed + if (0xf0 == (0xf8 & ptr[0])) + { + // 4 byte UTF-8 codepoint + if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks + codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]); + *codepointSize = 4; + } + else if (0xe0 == (0xf0 & ptr[0])) + { + // 3 byte UTF-8 codepoint + if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks + codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]); + *codepointSize = 3; + } + else if (0xc0 == (0xe0 & ptr[0])) + { + // 2 byte UTF-8 codepoint + if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks + codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]); + *codepointSize = 2; + } + else if (0x00 == (0x80 & ptr[0])) + { + // 1 byte UTF-8 codepoint + codepoint = ptr[0]; + *codepointSize = 1; + } + + return codepoint; +} +#endif // RAYGUI_STANDALONE + +#endif // RAYGUI_IMPLEMENTATION From ea6292e27a4f4fceaa203fb0d381688288c665a6 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 4 Apr 2026 11:12:30 +0200 Subject: [PATCH 055/185] REVIEWED: example: `audio_amp_envelope`, code formating to follow raylib code conventions #5713 --- examples/audio/audio_amp_envelope.c | 83 +++++++++++++++-------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/examples/audio/audio_amp_envelope.c b/examples/audio/audio_amp_envelope.c index 9d6939e35..2e51306c9 100644 --- a/examples/audio/audio_amp_envelope.c +++ b/examples/audio/audio_amp_envelope.c @@ -20,10 +20,10 @@ #define RAYGUI_IMPLEMENTATION #include "raygui.h" -#include +#include // Required for: sinf() -#define BUFFER_SIZE 4096 -#define SAMPLE_RATE 44100 +#define BUFFER_SIZE 4096 +#define SAMPLE_RATE 44100 // Wave state typedef enum { @@ -47,9 +47,9 @@ typedef struct { //------------------------------------------------------------------------------------ // Module Functions Declaration //------------------------------------------------------------------------------------ -static void FillAudioBuffer(int i, float* buffer, float envelopeValue, float* audioTime); -static void UpdateEnvelope(Envelope* env); -static void DrawADSRGraph(const Envelope *env, Rectangle bounds); +static void FillAudioBuffer(int i, float *buffer, float envelopeValue, float *audioTime); +static void UpdateEnvelope(Envelope *env); +static void DrawADSRGraph(Envelope *env, Rectangle bounds); //------------------------------------------------------------------------------------ // Program main entry point @@ -93,24 +93,22 @@ int main(void) { // Update //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_SPACE)) env.state = ATTACK; - if (IsKeyPressed(KEY_SPACE)) { - env.state = ATTACK; - } + if (IsKeyReleased(KEY_SPACE) && (env.state != IDLE)) env.state = RELEASE; - if (IsKeyReleased(KEY_SPACE)) { - if (env.state != IDLE) env.state = RELEASE; - } - - if (IsAudioStreamProcessed(stream)) { - - if (env.state != IDLE || env.currentValue > 0.0f) { + if (IsAudioStreamProcessed(stream)) + { + if ((env.state != IDLE) || (env.currentValue > 0.0f)) + { for (int i = 0; i < BUFFER_SIZE; i++) { UpdateEnvelope(&env); FillAudioBuffer(i, buffer, env.currentValue, &audioTime); } - } else { + } + else + { // Clear buffer if silent to avoid looping noise for (int i = 0; i < BUFFER_SIZE; i++) buffer[i] = 0; audioTime = 0.0f; @@ -139,9 +137,11 @@ int main(void) DrawText(TextFormat("Current Gain: %2.2f", env.currentValue), 535, 345 - (env.currentValue * 100), 10, MAROON); DrawText("Press SPACE to PLAY the sound!", 200, 400, 20, LIGHTGRAY); + EndDrawing(); //---------------------------------------------------------------------------------- } + // De-Initialization //-------------------------------------------------------------------------------------- UnloadAudioStream(stream); @@ -156,57 +156,60 @@ int main(void) //------------------------------------------------------------------------------------ // Module Functions Definition //------------------------------------------------------------------------------------ -static void FillAudioBuffer(int i, float* buffer, float envelopeValue, float* audioTime) +static void FillAudioBuffer(int i, float *buffer, float envelopeValue, float *audioTime) { - int frequency = 440; - buffer[i] = envelopeValue * sinf(2.0f * PI * frequency * (*audioTime)); - *audioTime += 1.0f / SAMPLE_RATE; + buffer[i] = envelopeValue*sinf(2.0f*PI*frequency*(*audioTime)); + *audioTime += (1.0f/SAMPLE_RATE); } static void UpdateEnvelope(Envelope *env) { // Calculate the time delta for ONE sample (1/44100) - float sampleTime = 1.0f / SAMPLE_RATE; + float sampleTime = 1.0f/SAMPLE_RATE; switch(env->state) { case ATTACK: - env->currentValue += (1.0f / env->attackTime) * sampleTime; + { + env->currentValue += (1.0f/env->attackTime)*sampleTime; if (env->currentValue >= 1.0f) { env->currentValue = 1.0f; env->state = DECAY; } - break; - + + } break; case DECAY: - env->currentValue -= ((1.0f - env->sustainLevel) / env->decayTime) * sampleTime; + { + env->currentValue -= ((1.0f - env->sustainLevel)/env->decayTime)*sampleTime; if (env->currentValue <= env->sustainLevel) { env->currentValue = env->sustainLevel; env->state = SUSTAIN; } - break; - + + } break; case SUSTAIN: + { env->currentValue = env->sustainLevel; - break; - + + } break; case RELEASE: - env->currentValue -= (env->sustainLevel / env->releaseTime) * sampleTime; + { + env->currentValue -= (env->sustainLevel/env->releaseTime)*sampleTime; if (env->currentValue <= 0.001f) // Use a small threshold to avoid infinite tail { env->currentValue = 0.0f; env->state = IDLE; } - break; + } break; default: break; } } -static void DrawADSRGraph(const Envelope *env, Rectangle bounds) +static void DrawADSRGraph(Envelope *env, Rectangle bounds) { DrawRectangleRec(bounds, Fade(LIGHTGRAY, 0.3f)); DrawRectangleLinesEx(bounds, 1, GRAY); @@ -217,14 +220,14 @@ static void DrawADSRGraph(const Envelope *env, Rectangle bounds) // Total time to visualize (sum of A, D, R + a padding for Sustain) float totalTime = env->attackTime + env->decayTime + sustainWidth + env->releaseTime; - float scaleX = bounds.width / totalTime; + float scaleX = bounds.width/totalTime; float scaleY = bounds.height; - Vector2 start = { bounds.x, bounds.y + bounds.height }; - Vector2 peak = { start.x + (env->attackTime * scaleX), bounds.y }; - Vector2 sustain = { peak.x + (env->decayTime * scaleX), bounds.y + (1.0f - env->sustainLevel) * scaleY }; - Vector2 rel = { sustain.x + (sustainWidth * scaleX), sustain.y }; - Vector2 end = { rel.x + (env->releaseTime * scaleX), bounds.y + bounds.height }; + Vector2 start = { bounds.x, bounds.y + bounds.height }; + Vector2 peak = { start.x + (env->attackTime*scaleX), bounds.y }; + Vector2 sustain = { peak.x + (env->decayTime*scaleX), bounds.y + (1.0f - env->sustainLevel)*scaleY }; + Vector2 rel = { sustain.x + (sustainWidth*scaleX), sustain.y }; + Vector2 end = { rel.x + (env->releaseTime*scaleX), bounds.y + bounds.height }; DrawLineV(start, peak, SKYBLUE); DrawLineV(peak, sustain, BLUE); @@ -232,4 +235,4 @@ static void DrawADSRGraph(const Envelope *env, Rectangle bounds) DrawLineV(rel, end, ORANGE); DrawText("ADSR Visualizer", bounds.x, bounds.y - 20, 10, DARKGRAY); -} \ No newline at end of file +} From 6ff51d3a2aa3866d81f3a4ca7f4088c51325d02a Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 4 Apr 2026 11:13:29 +0200 Subject: [PATCH 056/185] Update audio_amp_envelope.c --- examples/audio/audio_amp_envelope.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/audio/audio_amp_envelope.c b/examples/audio/audio_amp_envelope.c index 2e51306c9..fcc27bf56 100644 --- a/examples/audio/audio_amp_envelope.c +++ b/examples/audio/audio_amp_envelope.c @@ -93,7 +93,7 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - if (IsKeyPressed(KEY_SPACE)) env.state = ATTACK; + if (IsKeyPressed(KEY_SPACE)) env.state = ATTACK; if (IsKeyReleased(KEY_SPACE) && (env.state != IDLE)) env.state = RELEASE; @@ -106,14 +106,14 @@ int main(void) UpdateEnvelope(&env); FillAudioBuffer(i, buffer, env.currentValue, &audioTime); } - } + } else { // Clear buffer if silent to avoid looping noise for (int i = 0; i < BUFFER_SIZE; i++) buffer[i] = 0; audioTime = 0.0f; } - + UpdateAudioStream(stream, buffer, BUFFER_SIZE); } @@ -166,7 +166,7 @@ static void FillAudioBuffer(int i, float *buffer, float envelopeValue, float *au static void UpdateEnvelope(Envelope *env) { // Calculate the time delta for ONE sample (1/44100) - float sampleTime = 1.0f/SAMPLE_RATE; + float sampleTime = 1.0f/SAMPLE_RATE; switch(env->state) { @@ -178,7 +178,7 @@ static void UpdateEnvelope(Envelope *env) env->currentValue = 1.0f; env->state = DECAY; } - + } break; case DECAY: { @@ -188,12 +188,12 @@ static void UpdateEnvelope(Envelope *env) env->currentValue = env->sustainLevel; env->state = SUSTAIN; } - + } break; case SUSTAIN: { env->currentValue = env->sustainLevel; - + } break; case RELEASE: { @@ -203,8 +203,8 @@ static void UpdateEnvelope(Envelope *env) env->currentValue = 0.0f; env->state = IDLE; } - - } break; + + } break; default: break; } } @@ -219,7 +219,7 @@ static void DrawADSRGraph(Envelope *env, Rectangle bounds) // Total time to visualize (sum of A, D, R + a padding for Sustain) float totalTime = env->attackTime + env->decayTime + sustainWidth + env->releaseTime; - + float scaleX = bounds.width/totalTime; float scaleY = bounds.height; From 138ef838d91b567a31fe782f2221a77d9076eeb6 Mon Sep 17 00:00:00 2001 From: Le Juez Victor <90587919+Bigfoot71@users.noreply.github.com> Date: Sat, 4 Apr 2026 16:47:33 +0200 Subject: [PATCH 057/185] [rlsw] Some platform fixes (#5720) * fix drm with rlsw * fix window resizing with sdl * fix window resizing with win32 --- src/platforms/rcore_desktop_sdl.c | 4 ++++ src/platforms/rcore_desktop_win32.c | 4 ++++ src/platforms/rcore_drm.c | 8 +------- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 92c1979b3..dd845131e 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -1528,6 +1528,10 @@ void PollInputEvents(void) 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; diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index afbbedffc..5b19cd41a 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -2091,6 +2091,10 @@ static void HandleWindowResize(HWND hwnd, int *width, int *height) CORE.Window.screenScale = MatrixScale( (float)CORE.Window.render.width/CORE.Window.screen.width, (float)CORE.Window.render.height/CORE.Window.screen.height, 1.0f); + + #if defined(GRAPHICS_API_OPENGL_SOFTWARE) + swResize(clientSize.cx, clientSize.cy); + #endif } // Update window style diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index faba8956a..e742cb625 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -837,14 +837,8 @@ void SwapScreenBuffer(void) uint32_t height = mode->vdisplay; // Dumb buffers use a fixed format based on bpp -#if SW_COLOR_BUFFER_BITS == 24 const uint32_t bpp = 32; // 32 bits per pixel (XRGB8888 format) const uint32_t depth = 24; // Color depth, here only 24 bits, alpha is not used -#else - // REVIEW: Not sure how it will be interpreted (RGB or RGBA?) - const uint32_t bpp = SW_COLOR_BUFFER_BITS; - const uint32_t depth = SW_COLOR_BUFFER_BITS; -#endif // Create a dumb buffer for software rendering struct drm_mode_create_dumb creq = { 0 }; @@ -899,7 +893,7 @@ void SwapScreenBuffer(void) // Copy the software rendered buffer to the dumb buffer with scaling if needed // NOTE: RLSW will make a simple copy if the dimensions match - swBlitFramebuffer(0, 0, width, height, 0, 0, width, height, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer); + swBlitPixels(0, 0, width, height, 0, 0, width, height, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer); // Unmap the buffer munmap(dumbBuffer, creq.size); From cdff3d7bea31374af661910014ac07cbe2e87fa9 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 4 Apr 2026 16:50:10 +0200 Subject: [PATCH 058/185] Update CHANGELOG --- CHANGELOG | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index cc44aac2c..92e4c6bbd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,7 +4,7 @@ changelog Current Release: raylib 5.5 (18 November 2024) ------------------------------------------------------------------------- -Release: raylib 6.0 (?? March 2026) +Release: raylib 6.0 (23 April 2026) ------------------------------------------------------------------------- KEY CHANGES: - New Software Renderer backend [rlsw] @@ -285,6 +285,7 @@ Detailed changes: [rtext] REVIEWED: `TextToFloat()`, remove removed inaccurate comment (#4596) by @hexmaster111 [rtext] REDESIGNED: `LoadFontData()`, added input parameter by @raysan5 -WARNING- [rmodels] ADDED: Support CPU animation in OpenGL 1.1 (#4925) by @JeffM2501 +[rmodels] REMOVED: `DrawModelPoints()` and `DrawModelPointsEx()`, moved to an example (#5697) by @maiconpintoabreu -WARNING- [rmodels] RENAMED: Skinning shader variables (new default naming) by @raysan5 [rmodels] REVIEWED: glTF animation framerate calculation (#4472, #5445) by @TheLazyIndianTechie [rmodels] REVIEWED: Assign meshes without bone weights to the bone they are attached to so they animate by @Jeffm2501 @@ -311,6 +312,7 @@ Detailed changes: [rmodels] REVIEWED: `LoadModelAnimationsGLTF()`, properly load 1 frame animations (#5561) by @arlez80 [rmodels] REVIEWED: `LoadModelAnimationsGLTF()`, anim correctly inherits world transform (#5206) by @ArmanOmmid [rmodels] REVIEWED: `UploadMesh()`, improve default normal and tangent values (#4763) by @Bigfoot71 +[rmodels] REVIEWED: `UplaodMesh()`, fix for devices without VAO support (#5692) by @psxdev [rmodels] REVIEWED: `GenMeshTangents()`, improvements (#4937) by @Bigfoot71 [rmodels] REVIEWED: `UpdateModelAnimation()` optimization (#5244) by @Arrangemonk [rmodels] REVIEWED: `UpdateModelAnimationBones()`, break on first mesh found and formating by @raysan5 @@ -322,6 +324,7 @@ Detailed changes: [rmodels] REVIEWED: `DrawMeshInstanced()`, breaking if instanceTransform was unused (#5469) by @al13n321 [rmodels] REVIEWED: `DrawSphereEx()`, normals support (#4926) by @karl-zylinski [rmodels] REVIEWED: `ExportMesh()`, improve OBJ vertex data precision and lower memory usage (#4496) by @mikeemm +[rmodels] REVIEWED: `CheckCollisionSpheres()`, simplified using `Vector3DistanceSqr()` (#5695) by @Bigfoot71 [raudio] REVIEWED: Fix a glitch at the end of a sound (#5578) by @mackron [raudio] REVIEWED: Improvements to device configuration (#5577) by @mackron [raudio] REVIEWED: Initialize sound alias properties as if it was a new sound (#5123) by @JeffM2501 From 92f82b4add6ac57b871dd7c9b749ce6874d3bef1 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 4 Apr 2026 16:50:15 +0200 Subject: [PATCH 059/185] Update raylib.h --- src/raylib.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index c6aad860a..6849e7176 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1539,11 +1539,11 @@ RLAPI const char *TextSubtext(const char *text, int position, int length); RLAPI const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words RLAPI char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string with new string -RLAPI char *TextReplaceAlloc(const char *text, const char *search, const char *replacement); // Replace text string with new string, memory must be MemFree() +RLAPI char *TextReplaceAlloc(const char *text, const char *search, const char *replacement); // Replace text string with new string, memory must be MemFree() RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings RLAPI char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings, memory must be MemFree() RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a defined byte position -RLAPI char *TextInsertAlloc(const char *text, const char *insert, int position); // Insert text in a defined byte position, memory must be MemFree() +RLAPI char *TextInsertAlloc(const char *text, const char *insert, int position); // Insert text in a defined byte position, memory must be MemFree() RLAPI char *TextJoin(char **textList, int count, const char *delimiter); // Join text strings with delimiter RLAPI char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor From 1122add3eeaeeac6f63406ed010db5e5e957f96b Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 4 Apr 2026 17:36:18 +0200 Subject: [PATCH 060/185] Minor format tweak --- src/external/rlsw.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 0342211d2..c9ace86cd 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -2357,7 +2357,8 @@ static inline bool sw_texture_alloc(sw_texture_t *texture, const void *data, int sw_pixel_read_color8_f readColor8 = NULL; sw_pixel_read_color_f readColor = NULL; - if (!isDepth) { + if (!isDepth) + { readColor8 = sw_pixel_get_read_color8_func(format); readColor = sw_pixel_get_read_color_func(format); } @@ -2803,7 +2804,8 @@ static const sw_blend_f SW_BLEND_TABLE[SW_BLEND_FACTOR_COUNT][SW_BLEND_FACTOR_CO // Maps a GL blend factor enum to its compact table index static inline int sw_blend_factor_index(SWfactor f) { - switch (f) { + switch (f) + { case SW_ZERO: return 0; case SW_ONE: return 1; case SW_SRC_COLOR: return 2; @@ -2821,7 +2823,8 @@ static inline int sw_blend_factor_index(SWfactor f) static bool sw_blend_factor_needs_alpha(SWfactor f) { - switch (f) { + switch (f) + { case SW_SRC_ALPHA: case SW_ONE_MINUS_SRC_ALPHA: case SW_DST_ALPHA: @@ -2829,6 +2832,7 @@ static bool sw_blend_factor_needs_alpha(SWfactor f) case SW_SRC_ALPHA_SATURATE: return true; default: break; } + return false; } From 6ef0044381c71d76ba0784e8c98aab28e26b817a Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 4 Apr 2026 17:37:25 +0200 Subject: [PATCH 061/185] REVIEWED: Window messages `WM_SIZING`, `WM_SIZE`, `WM_WINDOWPOSCHANGED` #5720 --- src/platforms/rcore_desktop_win32.c | 46 ++++++++++++++++++----------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index 5b19cd41a..07262aaea 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -1063,14 +1063,14 @@ Vector2 GetMonitorPosition(int monitor) // Get selected monitor width (currently used by monitor) int GetMonitorWidth(int monitor) { - TRACELOG(LOG_WARNING, "GetMonitorWidth not implemented"); + //TRACELOG(LOG_WARNING, "GetMonitorWidth not implemented"); return 0; } // Get selected monitor height (currently used by monitor) int GetMonitorHeight(int monitor) { - TRACELOG(LOG_WARNING, "GetMonitorHeight not implemented"); + //TRACELOG(LOG_WARNING, "GetMonitorHeight not implemented"); return 0; } @@ -1105,7 +1105,7 @@ const char *GetMonitorName(int monitor) // Get window position XY on monitor Vector2 GetWindowPosition(void) { - TRACELOG(LOG_WARNING, "GetWindowPosition not implemented"); + //TRACELOG(LOG_WARNING, "GetWindowPosition not implemented"); return (Vector2){ 0, 0 }; } @@ -1760,13 +1760,31 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara memset(CORE.Input.Keyboard.previousKeyState, 0, sizeof(CORE.Input.Keyboard.previousKeyState)); memset(CORE.Input.Keyboard.currentKeyState, 0, sizeof(CORE.Input.Keyboard.currentKeyState)); } break; - case WM_SIZING: + case WM_SIZING: // Sent to a window that the user is resizing { - if (!(CORE.Window.flags & FLAG_WINDOW_RESIZABLE)) - TRACELOG(LOG_WARNING, "WIN32: WINDOW: Trying to resize a non-resizable window"); + if (CORE.Window.flags & FLAG_WINDOW_RESIZABLE) + { + //HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight); + } result = TRUE; } break; + case WM_SIZE: + { + // WARNING: Don't trust the docs, they say this message can not be obtained if not calling DefWindowProc() + // in response to WM_WINDOWPOSCHANGED but looks like when a window is created, + // this message can be obtained without getting WM_WINDOWPOSCHANGED + +#if defined(GRAPHICS_API_OPENGL_SOFTWARE) + // WARNING: Waiting two frames before resizing because software-renderer backend is initilized with swInit() later + // than InitPlatform(), that triggers WM_SIZE, so avoid crashing + if (CORE.Time.frameCounter > 2) HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight); +#else + // NOTE: This message is only triggered on window creation + HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight); +#endif + result = 0; // If an application processes WM_SIZE message, it should return zero + } break; case WM_GETMINMAXINFO: { DWORD style = MakeWindowStyle(platform.desiredFlags); @@ -1865,19 +1883,13 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara default: break; } } break; - case WM_SIZE: - { - // WARNING: Don't trust the docs, they say this message can not be obtained if not calling DefWindowProc() - // in response to WM_WINDOWPOSCHANGED but looks like when a window is created, - // this message can be obtained without getting WM_WINDOWPOSCHANGED - // WARNING: This call fails for Software-Renderer backend - //HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight); - } break; - //case WM_MOVE + //case WM_MOVE: break; case WM_WINDOWPOSCHANGED: { WINDOWPOS *pos = (WINDOWPOS*)lparam; if (!(pos->flags & SWP_NOSIZE)) HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight); + + DefWindowProc(hwnd, msg, wparam, lparam); } break; case WM_GETDPISCALEDSIZE: { @@ -2092,9 +2104,9 @@ static void HandleWindowResize(HWND hwnd, int *width, int *height) CORE.Window.screenScale = MatrixScale( (float)CORE.Window.render.width/CORE.Window.screen.width, (float)CORE.Window.render.height/CORE.Window.screen.height, 1.0f); - #if defined(GRAPHICS_API_OPENGL_SOFTWARE) +#if defined(GRAPHICS_API_OPENGL_SOFTWARE) swResize(clientSize.cx, clientSize.cy); - #endif +#endif } // Update window style From 4a6ceb9c76125c5b0c0f2ba2cea63b4b6db931fa Mon Sep 17 00:00:00 2001 From: Krzysztof Szenk Date: Sun, 5 Apr 2026 10:50:31 +0200 Subject: [PATCH 062/185] [rcore_rgfw] Icon color format fix (#5724) After RGFW update to 2.0.0-dev in fbd83cafc7c51ecc38be7f7b19c185a42f333cb0, RGFW_window_setIcon api has changed -- not it takes pixel format enum instead of number of channels. On raylib side it was still passing 4 (number of channels in rgba) which is enum value for BGRA8. Instead we have to pass 2 now (RGFW_formatRGBA8 = 2). --- src/platforms/rcore_desktop_rgfw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 11f268d9f..28a617af9 100755 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -723,7 +723,7 @@ void SetWindowIcon(Image image) TRACELOG(LOG_WARNING, "RGFW: Window icon image must be in R8G8B8A8 pixel format"); return; } - RGFW_window_setIcon(platform.window, (u8 *)image.data, image.width, image.height, 4); + RGFW_window_setIcon(platform.window, (u8 *)image.data, image.width, image.height, RGFW_formatRGBA8); } // Set icon for window @@ -749,8 +749,8 @@ void SetWindowIcons(Image *images, int count) if ((smallIcon == NULL) || ((images[i].width < smallIcon->width) && (images[i].height > smallIcon->height))) smallIcon = &images[i]; } - if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)smallIcon->data, smallIcon->width, smallIcon->height, 4, RGFW_iconWindow); - if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)bigIcon->data, bigIcon->width, bigIcon->height, 4, RGFW_iconTaskbar); + if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)smallIcon->data, smallIcon->width, smallIcon->height, RGFW_formatRGBA8, RGFW_iconWindow); + if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)bigIcon->data, bigIcon->width, bigIcon->height, RGFW_formatRGBA8, RGFW_iconTaskbar); } } From c4bd4faab561efb4ecb9e79c9495ce4bd907cc90 Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Sun, 5 Apr 2026 10:01:44 +0100 Subject: [PATCH 063/185] [build][CMake] REVIEWED: DRM software renderer configuration (#5721) https://github.com/raysan5/raylib/pull/5720#issuecomment-4187113099 In this comment, it was pointed out that LibraryConfigurations.cmake still tries to find and link egl, gbm, and glesv2, even when using the software renderer is it not necessary. This patch addresses that. --- cmake/LibraryConfigurations.cmake | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/cmake/LibraryConfigurations.cmake b/cmake/LibraryConfigurations.cmake index 7af078de0..4a8eb7d55 100644 --- a/cmake/LibraryConfigurations.cmake +++ b/cmake/LibraryConfigurations.cmake @@ -96,21 +96,30 @@ elseif (${PLATFORM} STREQUAL "Android") elseif ("${PLATFORM}" STREQUAL "DRM") set(PLATFORM_CPP "PLATFORM_DRM") - set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") add_definitions(-D_DEFAULT_SOURCE) - add_definitions(-DEGL_NO_X11) add_definitions(-DPLATFORM_DRM) - find_library(GLESV2 GLESv2) - find_library(EGL EGL) find_library(DRM drm) - find_library(GBM gbm) if (NOT CMAKE_CROSSCOMPILING OR NOT CMAKE_SYSROOT) include_directories(/usr/include/libdrm) endif () - set(LIBS_PRIVATE ${GLESV2} ${EGL} ${DRM} ${GBM} atomic pthread dl) + + if ("${OPENGL_VERSION}" STREQUAL "Software") + # software rendering does not require EGL/GBM. + set(GRAPHICS "GRAPHICS_API_OPENGL_SOFTWARE") + set(LIBS_PRIVATE ${DRM} atomic pthread dl) + else () + set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") + add_definitions(-DEGL_NO_X11) + + find_library(GLESV2 GLESv2) + find_library(EGL EGL) + find_library(GBM gbm) + + set(LIBS_PRIVATE ${GLESV2} ${EGL} ${DRM} ${GBM} atomic pthread dl) + endif () set(LIBS_PUBLIC m) elseif ("${PLATFORM}" STREQUAL "SDL") From d3c6f426b4c9e22fd51418082ca321ed7f523321 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 5 Apr 2026 11:02:26 +0200 Subject: [PATCH 064/185] Update for software renderer on DRM #5721 --- build.zig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build.zig b/build.zig index ec254debf..1aedc58fe 100644 --- a/build.zig +++ b/build.zig @@ -202,8 +202,10 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", ""); } - raylib.root_module.linkSystemLibrary("EGL", .{}); - raylib.root_module.linkSystemLibrary("gbm", .{}); + if (options.opengl_version != .gl_soft) { + raylib.root_module.linkSystemLibrary("EGL", .{}); + raylib.root_module.linkSystemLibrary("gbm", .{}); + } raylib.root_module.linkSystemLibrary("libdrm", .{ .use_pkg_config = .force }); raylib.root_module.addCMacro("PLATFORM_DRM", ""); @@ -416,6 +418,7 @@ pub const Options = struct { pub const OpenglVersion = enum { auto, + gl_soft, gl_1_1, gl_2_1, gl_3_3, @@ -426,6 +429,7 @@ pub const OpenglVersion = enum { pub fn toCMacroStr(self: @This()) []const u8 { switch (self) { .auto => @panic("OpenglVersion.auto cannot be turned into a C macro string"), + .gl_soft => return "GRAPHICS_API_OPENGL_SOFTWARE", .gl_1_1 => return "GRAPHICS_API_OPENGL_11", .gl_2_1 => return "GRAPHICS_API_OPENGL_21", .gl_3_3 => return "GRAPHICS_API_OPENGL_33", From c5fc7716229cef1727e7baf325a695a0ac00cf27 Mon Sep 17 00:00:00 2001 From: Angshuman Kishore Mahato <148174774+angshumankishore@users.noreply.github.com> Date: Mon, 6 Apr 2026 04:08:04 +0530 Subject: [PATCH 065/185] removed the first RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEMATRICES (#5727) --- src/rlgl.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index e97bad36a..923f84dfd 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -1015,9 +1015,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS #endif -#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_BONEMATRICES - #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONEMATRICES "boneMatrices" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEMATRICES -#endif + #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM #define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM "instanceTransform" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCETRANSFORM #endif From 05a14456ae090378d8b38505008af3de45e8074d Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 9 Apr 2026 11:16:31 +0200 Subject: [PATCH 066/185] REDESIGNED: `DrawCircleGradieent()` to use Vector2 as center parameter #5738 --- CHANGELOG | 1 + src/raylib.h | 4 ++-- src/rshapes.c | 32 ++++++++++++++++---------------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 92e4c6bbd..e049512bd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -221,6 +221,7 @@ Detailed changes: [rlsw] REVIEWED: C++ support (#5291) by @alexgb0 [rshapes] ADDED: `DrawLineDashed()` (#5222) by @luis605 [rshapes] ADDED: `DrawEllipseV()` and `DrawEllipseLinesV()` (#4963) by @meowstr +[rshapes] REDESIGNED: `DrawCircleGradieent()` to use Vector2 as center parameter by @raysan5 -WARNING- [rshapes] REVIEWED: `DrawLine()`, fix pixel offset issue on drawing (#4666) by @Bigfoot71 [rshapes] REVIEWED: `DrawRectangleGradientEx()`, incorrect parameter names (#4980) by @vincent [rshapes] REVIEWED: `DrawRectangleLines`, fix pixel offset issue (#4669) by @Bigfoot71 diff --git a/src/raylib.h b/src/raylib.h index 6849e7176..c30fa9e45 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1279,10 +1279,10 @@ RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation RLAPI void DrawLineDashed(Vector2 startPos, Vector2 endPos, int dashSize, int spaceSize, Color color); // Draw a dashed line RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle +RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version) +RLAPI void DrawCircleGradient(Vector2 center, float radius, Color inner, Color outer); // Draw a gradient-filled circle RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline -RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); // Draw a gradient-filled circle -RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version) RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version) RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse diff --git a/src/rshapes.c b/src/rshapes.c index 0a927a1d7..b39ecb743 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -324,6 +324,22 @@ void DrawCircleV(Vector2 center, float radius, Color color) DrawCircleSector(center, radius, 0, 360, 36, color); } +// Draw a gradient-filled circle +void DrawCircleGradient(Vector2 center, float radius, Color inner, Color outer) +{ + rlBegin(RL_TRIANGLES); + for (int i = 0; i < 360; i += 10) + { + rlColor4ub(inner.r, inner.g, inner.b, inner.a); + rlVertex2f(center.x, center.y); + rlColor4ub(outer.r, outer.g, outer.b, outer.a); + rlVertex2f(center.x + cosf(DEG2RAD*(i + 10))*radius, center.y + sinf(DEG2RAD*(i + 10))*radius); + rlColor4ub(outer.r, outer.g, outer.b, outer.a); + rlVertex2f(center.x + cosf(DEG2RAD*i)*radius, center.y + sinf(DEG2RAD*i)*radius); + } + rlEnd(); +} + // Draw a piece of a circle void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color) { @@ -473,22 +489,6 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float rlEnd(); } -// Draw a gradient-filled circle -void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer) -{ - rlBegin(RL_TRIANGLES); - for (int i = 0; i < 360; i += 10) - { - rlColor4ub(inner.r, inner.g, inner.b, inner.a); - rlVertex2f((float)centerX, (float)centerY); - rlColor4ub(outer.r, outer.g, outer.b, outer.a); - rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius); - rlColor4ub(outer.r, outer.g, outer.b, outer.a); - rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius); - } - rlEnd(); -} - // Draw circle outline void DrawCircleLines(int centerX, int centerY, float radius, Color color) { From b202421e083bb1592cca9af50fd1123b07b948d6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:16:49 +0000 Subject: [PATCH 067/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 88 +++++++++++++-------------- tools/rlparser/output/raylib_api.lua | 43 +++++++------ tools/rlparser/output/raylib_api.txt | 35 ++++++----- tools/rlparser/output/raylib_api.xml | 23 ++++--- 4 files changed, 91 insertions(+), 98 deletions(-) diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index ed0e220d7..06abbb7f7 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -5698,6 +5698,48 @@ } ] }, + { + "name": "DrawCircleV", + "description": "Draw a color-filled circle (Vector version)", + "returnType": "void", + "params": [ + { + "type": "Vector2", + "name": "center" + }, + { + "type": "float", + "name": "radius" + }, + { + "type": "Color", + "name": "color" + } + ] + }, + { + "name": "DrawCircleGradient", + "description": "Draw a gradient-filled circle", + "returnType": "void", + "params": [ + { + "type": "Vector2", + "name": "center" + }, + { + "type": "float", + "name": "radius" + }, + { + "type": "Color", + "name": "inner" + }, + { + "type": "Color", + "name": "outer" + } + ] + }, { "name": "DrawCircleSector", "description": "Draw a piece of a circle", @@ -5760,52 +5802,6 @@ } ] }, - { - "name": "DrawCircleGradient", - "description": "Draw a gradient-filled circle", - "returnType": "void", - "params": [ - { - "type": "int", - "name": "centerX" - }, - { - "type": "int", - "name": "centerY" - }, - { - "type": "float", - "name": "radius" - }, - { - "type": "Color", - "name": "inner" - }, - { - "type": "Color", - "name": "outer" - } - ] - }, - { - "name": "DrawCircleV", - "description": "Draw a color-filled circle (Vector version)", - "returnType": "void", - "params": [ - { - "type": "Vector2", - "name": "center" - }, - { - "type": "float", - "name": "radius" - }, - { - "type": "Color", - "name": "color" - } - ] - }, { "name": "DrawCircleLines", "description": "Draw circle outline", diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index a412e513f..1fe26250c 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -4861,6 +4861,27 @@ return { {type = "Color", name = "color"} } }, + { + name = "DrawCircleV", + description = "Draw a color-filled circle (Vector version)", + returnType = "void", + params = { + {type = "Vector2", name = "center"}, + {type = "float", name = "radius"}, + {type = "Color", name = "color"} + } + }, + { + name = "DrawCircleGradient", + description = "Draw a gradient-filled circle", + returnType = "void", + params = { + {type = "Vector2", name = "center"}, + {type = "float", name = "radius"}, + {type = "Color", name = "inner"}, + {type = "Color", name = "outer"} + } + }, { name = "DrawCircleSector", description = "Draw a piece of a circle", @@ -4887,28 +4908,6 @@ return { {type = "Color", name = "color"} } }, - { - name = "DrawCircleGradient", - description = "Draw a gradient-filled circle", - returnType = "void", - params = { - {type = "int", name = "centerX"}, - {type = "int", name = "centerY"}, - {type = "float", name = "radius"}, - {type = "Color", name = "inner"}, - {type = "Color", name = "outer"} - } - }, - { - name = "DrawCircleV", - description = "Draw a color-filled circle (Vector version)", - returnType = "void", - params = { - {type = "Vector2", name = "center"}, - {type = "float", name = "radius"}, - {type = "Color", name = "color"} - } - }, { name = "DrawCircleLines", description = "Draw circle outline", diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index bdad7db98..1d82497b5 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -2262,7 +2262,22 @@ Function 230: DrawCircle() (4 input parameters) Param[2]: centerY (type: int) Param[3]: radius (type: float) Param[4]: color (type: Color) -Function 231: DrawCircleSector() (6 input parameters) +Function 231: DrawCircleV() (3 input parameters) + Name: DrawCircleV + Return type: void + Description: Draw a color-filled circle (Vector version) + Param[1]: center (type: Vector2) + Param[2]: radius (type: float) + Param[3]: color (type: Color) +Function 232: DrawCircleGradient() (4 input parameters) + Name: DrawCircleGradient + Return type: void + Description: Draw a gradient-filled circle + Param[1]: center (type: Vector2) + Param[2]: radius (type: float) + Param[3]: inner (type: Color) + Param[4]: outer (type: Color) +Function 233: DrawCircleSector() (6 input parameters) Name: DrawCircleSector Return type: void Description: Draw a piece of a circle @@ -2272,7 +2287,7 @@ Function 231: DrawCircleSector() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 232: DrawCircleSectorLines() (6 input parameters) +Function 234: DrawCircleSectorLines() (6 input parameters) Name: DrawCircleSectorLines Return type: void Description: Draw circle sector outline @@ -2282,22 +2297,6 @@ Function 232: DrawCircleSectorLines() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 233: DrawCircleGradient() (5 input parameters) - Name: DrawCircleGradient - Return type: void - Description: Draw a gradient-filled circle - Param[1]: centerX (type: int) - Param[2]: centerY (type: int) - Param[3]: radius (type: float) - Param[4]: inner (type: Color) - Param[5]: outer (type: Color) -Function 234: DrawCircleV() (3 input parameters) - Name: DrawCircleV - Return type: void - Description: Draw a color-filled circle (Vector version) - Param[1]: center (type: Vector2) - Param[2]: radius (type: float) - Param[3]: color (type: Color) Function 235: DrawCircleLines() (4 input parameters) Name: DrawCircleLines Return type: void diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 83e2bd548..37d828049 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -1409,6 +1409,17 @@ + + + + + + + + + + + @@ -1425,18 +1436,6 @@ - - - - - - - - - - - - From 53915d77e65fd55c82cb2e9ea7d159abffcc5ffe Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 9 Apr 2026 11:22:13 +0200 Subject: [PATCH 068/185] Update CHANGELOG --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index e049512bd..ec1957103 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -221,7 +221,7 @@ Detailed changes: [rlsw] REVIEWED: C++ support (#5291) by @alexgb0 [rshapes] ADDED: `DrawLineDashed()` (#5222) by @luis605 [rshapes] ADDED: `DrawEllipseV()` and `DrawEllipseLinesV()` (#4963) by @meowstr -[rshapes] REDESIGNED: `DrawCircleGradieent()` to use Vector2 as center parameter by @raysan5 -WARNING- +[rshapes] REDESIGNED: `DrawCircleGradient()` to use Vector2 as center parameter by @raysan5 -WARNING- [rshapes] REVIEWED: `DrawLine()`, fix pixel offset issue on drawing (#4666) by @Bigfoot71 [rshapes] REVIEWED: `DrawRectangleGradientEx()`, incorrect parameter names (#4980) by @vincent [rshapes] REVIEWED: `DrawRectangleLines`, fix pixel offset issue (#4669) by @Bigfoot71 From e24b01bb288a317e39c79ebf9071ec18e4e75447 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 9 Apr 2026 11:36:26 +0200 Subject: [PATCH 069/185] Update HISTORY.md --- HISTORY.md | 85 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 16 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index b68ee44f4..a6ff00468 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -526,26 +526,79 @@ Last but not least, I want to thank **raylib sponsors and all the raylib communi notes on raylib 6.0 ------------------- -A new raylib release is finally ready, after almost 1.5 years since last release. This is the biggest release ever with many improvements to the library, thanks to the support of many amazing contributors and also thanks to the financial support of NLnet/NGI0 funds. +A new `raylib` release is finally ready and, again, this is the **biggest `raylib` release ever**! Thanks to the support of many amazing contributors this release comes packed with many new features and improvements, also thanks to the financial support of [NLnet](https://nlnet.nl/) and the [NGI Zero Commond Fund](https://nlnet.nl/NGI0/) that allow me to work on this project mostly fulltime for the past few months. Some astonishing numbers for this release: - - **+320** closed issues (for a TOTAL of **+2130**!) - - **+1800** commits since previous RELEASE (for a TOTAL of **+9600**!) - - **18** functions ADDED to raylib API (for a TOTAL of **599**!) - - **+50** new examples to learn from (for a TOTAL of **212**!) - - **+200** new contributors (for a TOTAL of **+840**!) + - **+320** closed issues (for a TOTAL of **+2140**!) + - **+1950** commits since previous RELEASE (for a TOTAL of **+9700**!) + - **+20** new functions ADDED to raylib API (for a TOTAL of **600**!) + - **+50** new examples to learn from (for a TOTAL of **+210**!) + - **+210** new contributors (for a TOTAL of **+850**!) Highlights for `raylib 6.0`: - - New Software Renderer backend [rlsw] - - New rcore platform backend: Memory (memory buffer) - - New rcore platform backend: Win32 (experimental) - - New rcore platform backend: Emscripten (experimental) - - Redesigned Skeletal Animation System - - Redesigned fullscreen modes and high-dpi content scaling - - Redesigned Build Config System [config.h] - - New File System API - - New Text Management API - - New tool: [rexm] raylib examples manager + - **`NEW` Software Renderer - [`rlsw`](https://github.com/raysan5/raylib/blob/master/src/external/rlsw.h)**: The biggest addition of this new release. A new software renderer backend, that allows raylib to run purely on CPU, with no neeed for a GPU. It finally closes the circle of my search for a portable self-contained, with **no-external-dependencies**, graphics library, able to run on any device providing some CPU-power and some RAM memory. It has been possible thanks to the amazing work of **Le Juez Victor** ([@Bigfoot71](https://github.com/Bigfoot71)), who created [`rlsw`](https://github.com/raysan5/raylib/blob/master/src/external/rlsw.h), a single-file header-only library implementing OpenGL 1.1+ specification, tailored to fit into raylib [`rlgl`](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) OpenGL wrapper, and allowing to run raylib seamlessly over CPU with **no code changes required on user side**. As expected, software rendering is slower than hardware-accelerated rendering but it is still fast enough to run basic application at 30-60 fps. Actually, it already proved it usefulness on a new [raylib port for ESP32](https://components.espressif.com/components/georgik/raylib/versions/6.0.0/readme) microcontroller by Espressif, useful for industrial applications, and opens the door to the upcoming RISC-V powered devices that start arriving to the marked, and many times come with no GPU. Along the new software renderer, some of the existing platform backends have been adapted to support it (SDL, RGFW, DRM) and also **new platforms backends have been created** to accomodate it (Win32, Emscripten), incluing a new `PLATFORM_MEMORY`, that allows direct rendering to a memory framebuffer. + - **`NEW` Platform backend: Memory - [`rcore_memory`](https://github.com/raysan5/raylib/blob/master/src/platforms/rcore_memory.c)**: This new platform has been added along the **software renderer** backend, allowing 2d and 3d rendering over a **platform-agnostic memory framebuffer**, it can run headless and output frames can be directly exported to images. This new backend could also be useful for graphics rendering on servers or process images directly using the memory buffer. + + - **`NEW` Platform backend: Win32 - [`rcore_desktop_win32`](https://github.com/raysan5/raylib/blob/master/src/platforms/rcore_desktop_win32.c)**: A new **Windows platform backend** and the first step towards a potential replacement/alternative to the platform libraries currently used by raylib (GLFW/SDL/RGFW). This backend follows same API template structure than the other raylib backends, but directly implementing Win32 API calls. It allows initializing OpenGL GPU-accelerated windows and also GDI based windows, useful for the software renderer backend. This new backend approach, following a common template-structure and separating the platform logic by specific OS/Windowing system, will simplify code, improve maintenance, readability and portability for raylib, setting some bases for the future. *NOTE: This backend is new and it could require further testing, use it as an experimental backend for now.* + + - **`NEW` Platform backend: Emscripten - [`rcore_web_emscripten`](https://github.com/raysan5/raylib/blob/master/src/platforms/rcore_web_emscripten.c)**: In the same line as Win32 backend, this new web backend moves away from `libglfw.js` and **directly implements Emscripten/JS functionality**, with **no other dependencies**, adding support for the new software renderer to draw directly on a **non-accelerated 2d canvas** but also supporting a WebGL-hardware-accelerated canvas when required. *NOTE: This backend is new and it could require further testing, use it as an experimental backend for now.* + + - **`REDESIGNED` Fullscreen modes and High-DPI content scaling**: After many years and many related issues, the full-screen and high-dpi content scaling support has been **completely redesigned** from scratch. New design prioritizes **borderless fullscreen modes** and automatically detects current monitor content scaling configuration to scale window and framebuffer accordingly when required. Still, High-DPI support must be requested by user if desired enabling `FLAG_WINDOW_HIGHDPI` on window creation. This new system has been carefully tested on Windows, Linux (X11, Wayland), macOS with multiple monitors and multiple resolutions, including 4K monitors. + + - **`REDESIGNED` Skeletal Animation System**: A new animation system for 3d models has been created to support animation blending, between single frames but also between differents frames on different animations, to allow easy **timed transitions** between animations. This redesign implied reviewing several raylib structures to better accomodate animation data: `Model`, `ModelSkeleton`, `ModelAnimation`, but the API was simplified and support for GPU-skinning was improved with multiple optimizations. + + - **`REDESIGNED` Build Config System - [`config.h`](https://github.com/raysan5/raylib/blob/master/src/config.h)**: raylib allows lot of customization for specific needs (i.e. disabling modules not needed for specific applications like rmodels or raudio) but previous implementation did not allow easely disabling some features from **custom build systems**. New design not only allows disabling features with simple `-DSUPPORT_FILEFORMAT_OBJ=0` on building command-line but also the full system has been reviewed, removing useless flags and exposing new ones. + + - **`NEW` File System API**: Along the years, multiple filesystem functions have been added to raylib API as required but it felt somewhat inconsistent with some pieces missing. In this new release, the full filesystem API has beeen reviewed and reorganized, compiling all the functionality single module: [rcore](https://github.com/raysan5/raylib/blob/master/src/raylib.h#L1126), consequently `utils` module has been removed and build system has been simplified even more; **only 6-7 modules (.c) need to be compiled containing the full raylib library**. This new filesystem API will allow raylib to be used on the creation of custom build systems, as already demostrated with the new `rexm` tool for examples management. At the moment raylib includes **+40 file system management functions**, here a list with the new functions added: +```c + int FileRename(const char *fileName, const char *fileRename); // Rename file (if exists) + int FileRemove(const char *fileName); // Remove file (if exists) + int FileCopy(const char *srcPath, const char *dstPath); // Copy file from one path to another, dstPath created if it doesn't exist + int FileMove(const char *srcPath, const char *dstPath); // Move file from one directory to another, dstPath created if it doesn't exist + int FileTextReplace(const char *fileName, const char *search, const char *replacement); // Replace text in an existing file + int FileTextFindIndex(const char *fileName, const char *search); // Find text in existing file +``` + + - **`NEW` Text Management API**: Along with the new file system functionality, a new set of text management functions has been added, also very useful for text procesing and also used in custom build systems creation using raylib. At the moment raylib includes **+30 text management functions**, here a list with the new functions added: +```c + char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n') + void UnloadTextLines(char **text, int lineCount); // Unload text lines + const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words + char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings + char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string with new string + char *TextReplaceAlloc(const char *text, const char *search, const char *replacement); // Replace text string with new string, memory must be MemFree() + char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings + char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings, memory must be MemFree() + char *TextInsertAlloc(const char *text, const char *insert, int position); // Insert text in a defined byte position, memory must be MemFree() +``` + + - **`NEW` tool: raylib examples manager - [rexm](https://github.com/raysan5/raylib/tree/master/tools/rexm)**: raylib examples collection is huge, with **more than 200 examples** it was quite difficult to manage: adding, removing, renaming examples was a very costly process involving many files to be modified (including build systems), also the examples did not follow a common header convention neither a structure conventions. For that reason, a new support tool has been created: **rexm**, a raylib examples manager that allows to easely add/remove/rename examples, automatically fix inconsistencies and even **building and automated testing** on multiple platforms. +``` +USAGE: + > rexm [] + +COMMANDS: + create : Creates an empty example, from internal template + add : Add existing example to collection + rename : Rename an existing example + remove : Remove an existing example from collection + build : Build example for Desktop and Web platforms + test : Build and Test example for Desktop and Web platforms + validate : Validate examples collection, generates report + update : Validate and update examples collection, generates report +``` + + - **`NEW` +50 new examples**: Thanks to `rexm` and the simplification on examples management, this new raylib release includes +50 new examples to leearn from, most of them contributed by community. + +Make sure to check raylib [CHANGELOG](https://github.com/raysan5/raylib/blob/master/CHANGELOG) for a detailed list of changes! + +I want to **thank all the contributors (+850!**) that along the years have **greatly improved raylib** and pushed it further and better day after day. And **many thanks to raylib community and all raylib users** for supporting the library along those many years. + +Finally, I want to thank [puffer.ai](https://puffer.ai/) and [comma.ai](https://comma.ai/) for **supporting and sponsoring the project** as platinum sponsors, along many others individuals that have been sponsoring raylib along the years. Thanks to all of you for allowing me to keep working on this library! + +**After +12 years of development, `raylib 6.0` is today one of the bests libraries to enjoy games/tools/graphic programming!** + +**Enjoy graphics programming with raylib!** :) From 8e54b19d9f64f950ae22af8b91c077f38f3bf663 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 9 Apr 2026 11:46:00 +0200 Subject: [PATCH 070/185] Update shapes_basic_shapes.c --- examples/shapes/shapes_basic_shapes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shapes/shapes_basic_shapes.c b/examples/shapes/shapes_basic_shapes.c index 77f2246f0..d14e45fe0 100644 --- a/examples/shapes/shapes_basic_shapes.c +++ b/examples/shapes/shapes_basic_shapes.c @@ -50,7 +50,7 @@ int main(void) // Circle shapes and lines DrawCircle(screenWidth/5, 120, 35, DARKBLUE); - DrawCircleGradient(screenWidth/5, 220, 60, GREEN, SKYBLUE); + DrawCircleGradient((Vector2){ screenWidth/5.0f, 220.0f }, 60, GREEN, SKYBLUE); DrawCircleLines(screenWidth/5, 340, 80, DARKBLUE); DrawEllipse(screenWidth/5, 120, 25, 20, YELLOW); DrawEllipseLines(screenWidth/5, 120, 30, 25, YELLOW); From ca6f188233a46e396bb11629868e920ec583eb92 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 9 Apr 2026 11:52:04 +0200 Subject: [PATCH 071/185] Update shaders_shapes_textures.c --- examples/shaders/shaders_shapes_textures.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shaders/shaders_shapes_textures.c b/examples/shaders/shaders_shapes_textures.c index 1517f0de8..98a7c1966 100644 --- a/examples/shaders/shaders_shapes_textures.c +++ b/examples/shaders/shaders_shapes_textures.c @@ -69,7 +69,7 @@ int main(void) DrawText("USING DEFAULT SHADER", 20, 40, 10, RED); DrawCircle(80, 120, 35, DARKBLUE); - DrawCircleGradient(80, 220, 60, GREEN, SKYBLUE); + DrawCircleGradient((Vector2){ 80.0f, 220.0f }, 60, GREEN, SKYBLUE); DrawCircleLines(80, 340, 80, DARKBLUE); From fbcc8cdb554574aa2abbafecb348c32928fd713e Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 9 Apr 2026 11:52:06 +0200 Subject: [PATCH 072/185] Update shapes_top_down_lights.c --- examples/shapes/shapes_top_down_lights.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shapes/shapes_top_down_lights.c b/examples/shapes/shapes_top_down_lights.c index 4a2ea0dcd..0f76d2e40 100644 --- a/examples/shapes/shapes_top_down_lights.c +++ b/examples/shapes/shapes_top_down_lights.c @@ -341,7 +341,7 @@ static void DrawLightMask(int slot) rlSetBlendMode(BLEND_CUSTOM); // If we are valid, then draw the light radius to the alpha mask - if (lights[slot].valid) DrawCircleGradient((int)lights[slot].position.x, (int)lights[slot].position.y, lights[slot].outerRadius, ColorAlpha(WHITE, 0), WHITE); + if (lights[slot].valid) DrawCircleGradient(lights[slot].position, lights[slot].outerRadius, ColorAlpha(WHITE, 0), WHITE); rlDrawRenderBatchActive(); From de95b3aa70545eb59b44aa6fe7725e25da0f48da Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 10 Apr 2026 08:42:06 -0500 Subject: [PATCH 073/185] added gpuready check to gentexturemipmaps (#5747) --- src/rlgl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rlgl.h b/src/rlgl.h index 923f84dfd..073cecd68 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -3685,6 +3685,8 @@ void rlUnloadTexture(unsigned int id) // NOTE: Only supports GPU mipmap generation void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps) { + if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return; } + #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glBindTexture(GL_TEXTURE_2D, id); From fe5271c5688a27e3b3d75614d45d76bf739699cc Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Sun, 12 Apr 2026 03:23:09 -0500 Subject: [PATCH 074/185] update raylib.rc to 6.0 (2026) (#5748) --- src/raylib.rc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/raylib.rc b/src/raylib.rc index 7de8382bd..bd9fceaf7 100644 --- a/src/raylib.rc +++ b/src/raylib.rc @@ -1,8 +1,8 @@ GLFW_ICON ICON "raylib.ico" 1 VERSIONINFO -FILEVERSION 5,5,0,0 -PRODUCTVERSION 5,5,0,0 +FILEVERSION 6,0,0,0 +PRODUCTVERSION 6,0,0,0 BEGIN BLOCK "StringFileInfo" BEGIN @@ -11,12 +11,12 @@ BEGIN BEGIN VALUE "CompanyName", "raylib technologies" VALUE "FileDescription", "raylib application (www.raylib.com)" - VALUE "FileVersion", "5.5.0" + VALUE "FileVersion", "6.0.0" VALUE "InternalName", "raylib" - VALUE "LegalCopyright", "(c) 2025 Ramon Santamaria (@raysan5)" + VALUE "LegalCopyright", "(c) 2026 Ramon Santamaria (@raysan5)" VALUE "OriginalFilename", "raylib" VALUE "ProductName", "raylib app" - VALUE "ProductVersion", "5.5.0" + VALUE "ProductVersion", "6.0.0" END END BLOCK "VarFileInfo" From ddfbe973d4b49f725562a81860de7b46d0814e3f Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 12 Apr 2026 10:24:35 +0200 Subject: [PATCH 075/185] Updated Windows resource file --- src/raylib.dll.rc | 10 +++++----- src/raylib.dll.rc.data | Bin 7742 -> 7742 bytes src/raylib.rc.data | Bin 7726 -> 7726 bytes 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/raylib.dll.rc b/src/raylib.dll.rc index 7ad39c76f..e8d24a037 100644 --- a/src/raylib.dll.rc +++ b/src/raylib.dll.rc @@ -1,8 +1,8 @@ GLFW_ICON ICON "raylib.ico" 1 VERSIONINFO -FILEVERSION 5,5,0,0 -PRODUCTVERSION 5,5,0,0 +FILEVERSION 6,0,0,0 +PRODUCTVERSION 6,0,0,0 BEGIN BLOCK "StringFileInfo" BEGIN @@ -11,12 +11,12 @@ BEGIN BEGIN VALUE "CompanyName", "raylib technologies" VALUE "FileDescription", "raylib dynamic library (www.raylib.com)" - VALUE "FileVersion", "5.5.0" + VALUE "FileVersion", "6.0.0" VALUE "InternalName", "raylib.dll" - VALUE "LegalCopyright", "(c) 2025 Ramon Santamaria (@raysan5)" + VALUE "LegalCopyright", "(c) 2026 Ramon Santamaria (@raysan5)" VALUE "OriginalFilename", "raylib.dll" VALUE "ProductName", "raylib" - VALUE "ProductVersion", "5.5.0" + VALUE "ProductVersion", "6.0.0" END END BLOCK "VarFileInfo" diff --git a/src/raylib.dll.rc.data b/src/raylib.dll.rc.data index db6b924a70a57a674f6ece692b44bac7e11eac6d..4a8a6a19d8f8e07a34fe54f6bf946d2280dc6fdd 100644 GIT binary patch delta 54 zcmdmIv(IM36De*61~vu=V4M6=N`5n+v>YR=8G{~!!DK_3LPoR6i)AiC`IWLq0c3g& AJpcdz delta 54 zcmdmIv(IM36De+1237_T0Me5`O382Lla^y-HD%CaFr92DQ^;sKd9lnzD8EwnC;(<3 B4NL$4 diff --git a/src/raylib.rc.data b/src/raylib.rc.data index 8727d21308057ce88f30f52cc39578fe8f733620..64ed4e3c7ff728b0c7fed3bb2680d95e6a623615 100644 GIT binary patch delta 54 zcmZ2yv(9G26De*61~vu=V4M6=N`5n+v=}3+8G{~!!DLODOh&WGlVvVK`I)ju0b1G& A Date: Sun, 12 Apr 2026 03:25:59 -0500 Subject: [PATCH 076/185] update makefile for PLATFORM_MEMORY (#5750) --- src/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Makefile b/src/Makefile index 8f13b4355..247978fd4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -284,6 +284,10 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) # By default use OpenGL ES 2.0 on Android GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 endif +ifeq ($(TARGET_PLATFORM),PLATFORM_MEMORY) + # By default use OpenGL Software + GRAPHICS ?= GRAPHICS_API_OPENGL_SOFTWARE +endif # Define default C compiler and archiver to pack library: CC, AR #------------------------------------------------------------------------------------------------ From 605303f62b0a0554105fd1bcdf240b6a3cd75318 Mon Sep 17 00:00:00 2001 From: Maicon Santana Date: Sun, 12 Apr 2026 09:32:05 +0100 Subject: [PATCH 077/185] fix: pthread_mutex_lock called on a destroyed mutex (#5752) --- src/raudio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/raudio.c b/src/raudio.c index cd37ca305..8107886cb 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1763,6 +1763,8 @@ bool IsMusicValid(Music music) // Unload music stream void UnloadMusicStream(Music music) { + if (IsMusicStreamPlaying(music)) StopMusicStream(music); + UnloadAudioStream(music.stream); if (music.ctxData != NULL) From a5427bc38fe2dd9018bf657525406287bec0cbfa Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 12 Apr 2026 11:07:09 +0200 Subject: [PATCH 078/185] Update rlsw.h --- src/external/rlsw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index c9ace86cd..8f7ab4405 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -2417,7 +2417,7 @@ static inline void sw_texture_sample_nearest(float *SW_RESTRICT color, const sw_ static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex, float u, float v) { - // TODO: With a bit more cleverness thee number of operations can + // TODO: With a bit more cleverness the number of operations can // be clearly reduced, but for now it works fine float xf = (u*tex->width) - 0.5f; From 51d693607ece4d66c09157821efd9b9c2de35019 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 12 Apr 2026 11:07:19 +0200 Subject: [PATCH 079/185] Update Makefile --- src/Makefile | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/src/Makefile b/src/Makefile index 247978fd4..997165b4a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -286,7 +286,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) endif ifeq ($(TARGET_PLATFORM),PLATFORM_MEMORY) # By default use OpenGL Software - GRAPHICS ?= GRAPHICS_API_OPENGL_SOFTWARE + GRAPHICS = GRAPHICS_API_OPENGL_SOFTWARE endif # Define default C compiler and archiver to pack library: CC, AR @@ -324,7 +324,12 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) AR = $(RPI_TOOLCHAIN)/bin/$(RPI_TOOLCHAIN_NAME)-ar endif endif -ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) + # HTML5 emscripten compiler + CC = emcc + AR = emar +endif +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB_RGFW) # HTML5 emscripten compiler CC = emcc AR = emar @@ -368,7 +373,6 @@ ifneq ($(RAYLIB_CONFIG_FLAGS), NONE) endif ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) - # NOTE: When using multi-threading in the user code, it requires -pthread enabled CFLAGS += -std=gnu99 else CFLAGS += -std=c99 @@ -387,12 +391,15 @@ ifeq ($(RAYLIB_BUILD_MODE),DEBUG) endif ifeq ($(RAYLIB_BUILD_MODE),RELEASE) - ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) - CFLAGS += -Os - endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) CFLAGS += -O1 endif + ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) + CFLAGS += -Os + endif + ifeq ($(TARGET_PLATFORM),PLATFORM_WEB_RGFW) + CFLAGS += -Os + endif ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) CFLAGS += -O2 endif @@ -406,23 +413,12 @@ endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) CFLAGS += -Werror=implicit-function-declaration endif -ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) - # -Os # size optimization - # -O2 # optimization level 2, if used, also set --memory-init-file 0 - # -sUSE_GLFW=3 # Use glfw3 library (context/input management) - # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! - # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB) - # -sUSE_PTHREADS=1 # multithreading support - # -sWASM=0 # disable Web Assembly, emitted by default - # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS - # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data - # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) - # -sMINIFY_HTML=0 # minify generated html from shell.html - # --profiling # include information for code profiling - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # --preload-file resources # specify a resources folder for data compilation - # --source-map-base # allow debugging in browser with source map - # --shell-file shell.html # define a custom shell .html and output extension +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) + ifeq ($(RAYLIB_BUILD_MODE),DEBUG) + CFLAGS += --profiling + endif +endif +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB_RGFW) ifeq ($(RAYLIB_BUILD_MODE),DEBUG) CFLAGS += --profiling endif @@ -772,7 +768,6 @@ all: raylib raylib: $(OBJS) ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # Compile raylib libray for web - #$(CC) $(OBJS) -r -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc ifeq ($(RAYLIB_LIBTYPE),SHARED) @echo "WARNING: $(TARGET_PLATFORM) does not support SHARED libraries. Generating STATIC library." endif From 44e5126d089cf86a7466d98ac0457837362fcf18 Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Sun, 12 Apr 2026 12:21:09 -0500 Subject: [PATCH 080/185] update 2025->2026, 5.5->6.0 (#5754) --- BINDINGS.md | 2 +- CHANGELOG | 2 +- examples/Makefile.Android | 2 +- examples/examples.rc | 10 +++++----- projects/CMake/CMakeLists.txt | 2 +- tools/rexm/LICENSE | 2 +- tools/rexm/Makefile | 2 +- tools/rexm/rexm.c | 6 +++--- tools/rexm/rexm.rc | 2 +- tools/rlparser/rlparser.rc | 6 +++--- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/BINDINGS.md b/BINDINGS.md index 4a7680964..66467d9fa 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -6,7 +6,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | Name | raylib Version | Language | License | | :--------------------------------------------------------------------------------------- | :--------------: | :------------------------------------------------------------------: | :------------------: | -| [raylib](https://github.com/raysan5/raylib) | **5.5** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | +| [raylib](https://github.com/raysan5/raylib) | **6.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | | [raylib-ada](https://github.com/Fabien-Chouteau/raylib-ada) | **5.5** | [Ada](https://en.wikipedia.org/wiki/Ada_(programming_language)) | MIT | | [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.5** | [Beef](https://www.beeflang.org) | MIT | | [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT | diff --git a/CHANGELOG b/CHANGELOG index ec1957103..e4e06ce47 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,7 @@ changelog --------- -Current Release: raylib 5.5 (18 November 2024) +Current Release: raylib 6.0 (23 April 2026) ------------------------------------------------------------------------- Release: raylib 6.0 (23 April 2026) diff --git a/examples/Makefile.Android b/examples/Makefile.Android index cf4ad1257..0d8da9701 100644 --- a/examples/Makefile.Android +++ b/examples/Makefile.Android @@ -2,7 +2,7 @@ # # raylib makefile for Android project (APK building) # -# Copyright (c) 2017-2025 Ramon Santamaria (@raysan5) +# Copyright (c) 2017-2026 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. diff --git a/examples/examples.rc b/examples/examples.rc index 14938ae9d..4b53143fb 100644 --- a/examples/examples.rc +++ b/examples/examples.rc @@ -1,8 +1,8 @@ GLFW_ICON ICON "raylib.ico" 1 VERSIONINFO -FILEVERSION 5,5,0,0 -PRODUCTVERSION 5,5,0,0 +FILEVERSION 6,0,0,0 +PRODUCTVERSION 6,0,0,0 BEGIN BLOCK "StringFileInfo" BEGIN @@ -11,12 +11,12 @@ BEGIN BEGIN VALUE "CompanyName", "raylib technologies" VALUE "FileDescription", "raylib application (www.raylib.com)" - VALUE "FileVersion", "5.5.0" + VALUE "FileVersion", "6.0.0" VALUE "InternalName", "raylib-example" - VALUE "LegalCopyright", "(c) 2025 Ramon Santamaria (@raysan5)" + VALUE "LegalCopyright", "(c) 2026 Ramon Santamaria (@raysan5)" VALUE "OriginalFilename", "raylib-example" VALUE "ProductName", "raylib-example" - VALUE "ProductVersion", "5.5.0" + VALUE "ProductVersion", "6.0.0" END END BLOCK "VarFileInfo" diff --git a/projects/CMake/CMakeLists.txt b/projects/CMake/CMakeLists.txt index 56a5a5f51..b1d307489 100644 --- a/projects/CMake/CMakeLists.txt +++ b/projects/CMake/CMakeLists.txt @@ -5,7 +5,7 @@ project(example) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Dependencies -set(RAYLIB_VERSION 5.5) +set(RAYLIB_VERSION 6.0) find_package(raylib ${RAYLIB_VERSION} QUIET) # QUIET or REQUIRED if (NOT raylib_FOUND) # If there's none, fetch and build raylib include(FetchContent) diff --git a/tools/rexm/LICENSE b/tools/rexm/LICENSE index 7d8c7bfc5..9bcc4ed0d 100644 --- a/tools/rexm/LICENSE +++ b/tools/rexm/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2025 Ramon Santamaria (@raysan5) +Copyright (c) 2026 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. diff --git a/tools/rexm/Makefile b/tools/rexm/Makefile index c8f2490c0..6d061a6f6 100644 --- a/tools/rexm/Makefile +++ b/tools/rexm/Makefile @@ -2,7 +2,7 @@ # # raylib makefile for Desktop platforms, Web (Wasm), Raspberry Pi (DRM mode) and Android # -# Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) +# Copyright (c) 2013-2026 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. diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index 841ccbce8..84780988f 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -474,8 +474,8 @@ int main(int argc, char *argv[]) exTextUpdated[1] = TextReplaceAlloc(exTextUpdated[0], "", exName + strlen(exCategory) + 1); //TextReplaceAlloc(newExample, "", "Ray"); //TextReplaceAlloc(newExample, "@", "@raysan5"); - //TextReplaceAlloc(newExample, "", 2025); - //TextReplaceAlloc(newExample, "", 2025); + //TextReplaceAlloc(newExample, "", 2026); + //TextReplaceAlloc(newExample, "", 2026); SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), exTextUpdated[1]); for (int i = 0; i < 6; i++) { MemFree(exTextUpdated[i]); exTextUpdated[i] = NULL; } @@ -1875,7 +1875,7 @@ int main(int argc, char *argv[]) printf("\n////////////////////////////////////////////////////////////////////////////////////////////\n"); printf("// //\n"); printf("// rexm [raylib examples manager] - A simple command-line tool to manage raylib examples //\n"); - printf("// powered by raylib v5.6-dev //\n"); + printf("// powered by raylib v6.0 //\n"); printf("// //\n"); printf("// Copyright (c) 2025-2026 Ramon Santamaria (@raysan5) //\n"); printf("// //\n"); diff --git a/tools/rexm/rexm.rc b/tools/rexm/rexm.rc index 4d3785a6a..83f4e1746 100644 --- a/tools/rexm/rexm.rc +++ b/tools/rexm/rexm.rc @@ -13,7 +13,7 @@ BEGIN VALUE "FileDescription", "rexm | raylib examples manager" VALUE "FileVersion", "1.0" VALUE "InternalName", "rexm" - VALUE "LegalCopyright", "(c) 2025 Ramon Santamaria" + VALUE "LegalCopyright", "(c) 2026 Ramon Santamaria" //VALUE "OriginalFilename", "rexm.exe" VALUE "rexm", "rexm" VALUE "ProductVersion", "1.0" diff --git a/tools/rlparser/rlparser.rc b/tools/rlparser/rlparser.rc index a5bb5b7ad..e487b7a09 100644 --- a/tools/rlparser/rlparser.rc +++ b/tools/rlparser/rlparser.rc @@ -1,7 +1,7 @@ IDI_APP_ICON ICON "rlparser.ico" 1 VERSIONINFO -FILEVERSION 5,5,0,0 -PRODUCTVERSION 5,5,0,0 +FILEVERSION 6,0,0,0 +PRODUCTVERSION 6,0,0,0 BEGIN BLOCK "StringFileInfo" BEGIN @@ -11,7 +11,7 @@ BEGIN VALUE "FileDescription", "rlparser | raylib header API parser" VALUE "FileVersion", "1.0" VALUE "InternalName", "rlparser" - VALUE "LegalCopyright", "(c) 2025 Ramon Santamaria (@raysan5)" + VALUE "LegalCopyright", "(c) 2026 Ramon Santamaria (@raysan5)" VALUE "OriginalFilename", "rlparser" VALUE "ProductName", "rlparser" VALUE "ProductVersion", "1.0" From 1339ec637e49f71bb9d723d54abe7db6787576f9 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 12 Apr 2026 19:49:45 +0200 Subject: [PATCH 081/185] Update raylib.h --- src/raylib.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index c30fa9e45..34c5a6488 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1071,9 +1071,9 @@ RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Lo RLAPI bool IsShaderValid(Shader shader); // Check if a shader is valid (loaded on GPU) RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location -RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value -RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count); // Set shader uniform value vector -RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4) +RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value +RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count); // Set shader uniform value vector +RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4) RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value and bind the texture (sampler2d) RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM) @@ -1175,10 +1175,10 @@ RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int * RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree() RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string (includes NULL terminator), memory must be MemFree() RLAPI unsigned char *DecodeDataBase64(const char *text, int *outputSize); // Decode Base64 string (expected NULL terminated), memory must be MemFree() -RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code -RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes) -RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes) -RLAPI unsigned int *ComputeSHA256(unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 bytes) +RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code +RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes) +RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes) +RLAPI unsigned int *ComputeSHA256(unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 bytes) // Automation events functionality RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS @@ -1281,7 +1281,7 @@ RLAPI void DrawLineDashed(Vector2 startPos, Vector2 endPos, int dashSize, int sp RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version) RLAPI void DrawCircleGradient(Vector2 center, float radius, Color inner, Color outer); // Draw a gradient-filled circle -RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle +RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version) @@ -1290,7 +1290,7 @@ RLAPI void DrawEllipseV(Vector2 center, float radiusH, float radiusV, Color colo RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline RLAPI void DrawEllipseLinesV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse outline (Vector version) RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring -RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline +RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version) RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle @@ -1600,7 +1600,7 @@ RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, floa RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) -RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture +RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation From 970531d112fd535c13b45442468dded784b9779e Mon Sep 17 00:00:00 2001 From: Ebben Feagan Date: Sun, 12 Apr 2026 16:49:38 -0500 Subject: [PATCH 082/185] Update BINDINGS.md to add new FreeBASIC port (#5755) Added the raylib4fb port --- BINDINGS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BINDINGS.md b/BINDINGS.md index 66467d9fa..7169fbc05 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -33,6 +33,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 | | [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 | | [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 5.5 | [Factor](https://factorcode.org) | BSD | +| [raylib4fb](https://github.com/mudhairless/raylib4fb) | **5.5** | [FreeBASIC](https://www.freebasic.net) | Zlib | | [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT | | [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib | | [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC | From 034ffda88738855538c5369b0d531d94c1b647b0 Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Mon, 13 Apr 2026 11:55:45 -0500 Subject: [PATCH 083/185] [cmake] update cmake for PLATFORM_MEMORY (#5749) * update cmake for PLATFORM_MEMORY * remove opengl example for memory platform * update for winmm and cross compile --- CMakeOptions.txt | 2 +- cmake/LibraryConfigurations.cmake | 10 ++++++++++ examples/CMakeLists.txt | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CMakeOptions.txt b/CMakeOptions.txt index 0a453917d..55375116e 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -6,7 +6,7 @@ if(EMSCRIPTEN) # When configuring web builds with "emcmake cmake -B build -S .", set PLATFORM to Web by default SET(PLATFORM Web CACHE STRING "Platform to build for.") endif() -enum_option(PLATFORM "Desktop;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW" "Platform to build for.") +enum_option(PLATFORM "Desktop;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory" "Platform to build for.") enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0;Software" "Force a specific OpenGL Version?") diff --git a/cmake/LibraryConfigurations.cmake b/cmake/LibraryConfigurations.cmake index 4a8eb7d55..18680491d 100644 --- a/cmake/LibraryConfigurations.cmake +++ b/cmake/LibraryConfigurations.cmake @@ -156,6 +156,7 @@ elseif ("${PLATFORM}" STREQUAL "SDL") add_compile_definitions(USING_SDL2_PACKAGE) endif() endif() + elseif ("${PLATFORM}" STREQUAL "RGFW") set(PLATFORM_CPP "PLATFORM_DESKTOP_RGFW") @@ -181,6 +182,15 @@ elseif ("${PLATFORM}" STREQUAL "WebRGFW") set(PLATFORM_CPP "PLATFORM_WEB_RGFW") set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") + +elseif ("${PLATFORM}" STREQUAL "Memory") + set(PLATFORM_CPP "PLATFORM_MEMORY") + set(GRAPHICS "GRAPHICS_API_OPENGL_SOFTWARE") + set(OPENGL_VERSION "Software") + + if(WIN32 OR CMAKE_C_COMPILER MATCHES "mingw|mingw32|mingw64") + set(LIBS_PRIVATE winmm) + endif() endif () if (NOT ${OPENGL_VERSION} MATCHES "OFF") diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 6554d1327..ee5469eaa 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -105,6 +105,9 @@ elseif ("${PLATFORM}" STREQUAL "DRM") list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c) +elseif ("${PLATFORM}" MATCHES "Memory") + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c) + elseif ("${OPENGL_VERSION}" STREQUAL "Software") list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c) From 019cc889fc808b1cfe18e9e4bc10ccdc5de7d430 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 13 Apr 2026 19:26:28 +0200 Subject: [PATCH 084/185] Updated Notepad++ scripts and autocomplete --- projects/Notepad++/npes_saved_mingw.txt | Bin 8256 -> 0 bytes projects/Notepad++/npes_saved_w64devkit.txt | Bin 10400 -> 17762 bytes .../raylib_npp_parser/raylib_npp.xml | 371 ++++++++++++------ .../raylib_npp_parser/raylib_to_parse.h | 333 ++++++++-------- 4 files changed, 431 insertions(+), 273 deletions(-) delete mode 100644 projects/Notepad++/npes_saved_mingw.txt diff --git a/projects/Notepad++/npes_saved_mingw.txt b/projects/Notepad++/npes_saved_mingw.txt deleted file mode 100644 index c07a430da5d57bb20d6f0302f85343519e68d768..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8256 zcmeHMZEqS!5T4JK`X8=RKh#wLC61!j5|tcq2#N_7ICUdgLKvJDl^2(@)AY|bd7c@@ zw|nNmBsg^>%R=6J+1Z_$XJ($A`|#hM?8%w*C6$p3q__CZWFi;1Gscrk{GZ8GzLjs} z9MAv6RU*IQ*TwavT;a_`<{1Bt@kmEQ+&RFUcY4j)6Fi^d?N~}lw)IE3U95SGl{>O8 zZ{$##@(das;p$jkNL6ak^%VQ-%fHZU1ij;{P)1GK(!$&(g9mHdXezO!sE-^&l!Pth7XYA2sn!<$ve9^j8s2SWRrgxAOg+MU#NdLHXn5`H^q-0xvQw+s*cvz(8ICk zh~;zsm@kNr6!sxj1{n9QeZl;Z`RyTh{QtRw*`SMfsUkBmLk$<+qc69aM^?vcS&?#A zG3z=q>WU+lSY032e5(vA5xaeTzoer%@*^X#iX3!~_#Mfv{47tuy2#CHUmUB9V#{d* z#Pub{L`c3?Jk)#V4PUa}doHe_(j1~1H4xENMf!54vjYy2YQ)9-#-cDrcd8g?HL`4N zG1A8Tn^nr{SXR@Tx7q_|H5FS#)f_p95_q=`enowbp%>Xo3mB|xzIv(r?Dq?P1%&~cmg?zR5YhGVHYxk-(lx2EVn8PI&T?bU-Uvn=N4y8dq3Q9IR3ggnAiMp`zJgf@FcdcI1D>EmUWA}FsDFp8Ek3aZ)JEr)FvFeW?655 zSudQOz@jtcp)1vXn>mmBFh6^(9_ZT4x$I<=l|wD#s1;?AZ{hQbM$!O#yV6|g-M6q_ z7p+4kN*T6}?c_G|QdEe(=HYbXxn!O1!8+NYVP@ZSZJ)pCJo6!$<>qVl)wb+4Z?-B= ztL##)Ua^>wG+?1Aencbn&f_ve`W$`Z7}arY-R#Qo!i-6_$Ib&!UDUByZJ5znQh#MAj9n_3+8Aa{qZ`k+hDPEWx6L|7ta(U&Uo@N ztC+pM*HMgshi`2jTX)NATk!5nc(a;gcw~Hra?1qU`2u%>)jB{^6TgO@s9L#LN>G!S zd(X5oSvST{&)mZVS=swbtXD~z8~#COR>x2Ukqs_I}ODZp^|$u sh3vc!Xd|x4d>-!H86>-KR+)S7Q}!+0zqri6{ys%d_sdNm-Isds5z_mLIsgCw diff --git a/projects/Notepad++/npes_saved_w64devkit.txt b/projects/Notepad++/npes_saved_w64devkit.txt index 767fa274d9778860a26893655eef4c4b026e8590..262d19c2382c21394a0117d9e81a2c003ba4dcc1 100644 GIT binary patch literal 17762 zcmeI4Yj0b}5r+43f&Pcnpdad{k`gNjS{E!}Q?f!>H|SEufB-_GWZ5+(Dk5b&f4<54 z>~OWaUq{9S)Ao<+(HZwc(&Sm|}|DU;M?%bWZu6yTNuG#EDjK zaesDya+iAlR(FN_kA4qz-*fl+vT%30{z=#G{MCh?Y^u!%e^2Xcy}!}dc`qw&UO)7E zs4ms>XWa=@nYl^<~Xni3ctJ zyruC9XFVKijt83QuGZRg8=5zFb=~dh>b0|;0{?O@7%$H}w{Fybp?3G86Fh}yg?p)$ zv~`!ao1S;HzmdG$YK~p;;ln_mdH>9-E@=z0c&U5jlzV2w+rqt>)7)$|%)lsG7tIRE zC(_Q7UCGgoXljyhAj&>*tD40pKNG%q*_W2)!?)JMiB{Uy551lE7CkS8+;>Ia3vspO z{-vLE{pq#sw*$59>KBeIYIiYekk(_ZBgkHmSl;uC-atOOq7Smt(slEJ7wD15w?`ea zJURreaHxG#b058Sy6AHep3YOBjNZ4aUSbxpch}sSc1PV?sgB<*-0iz#Jw5ZIzSX*W zlGc{~BDv_1o_}|x>z?GAeYui7t4ZTr>e)ND?*1uFUud_lyQf~m_q?89)T&mWe47<- zA!v!Ez&6klx-)0=N8k-wqgvyz*BEQGUgE1&X%_b0*@SarE{mN9BUIa<<};qa0VAO4odObQCOCU3Pg}wtGu@uhy6EGJN<%h^^~2L_T}dRry}( z`W=PsHrr-9a!)#8*rxL&M*v-Er!(!%j_6`&L-7MkH18P;C$KE<7Q9lh54i_vy7@P#(zc;0%8dm>ote5Z`_x0c1$ zRa@gt@7VG}EAshUfr;=Lo+-FHWl`=b?W6AvM!fU<|A?ePj zQF7VO_l3n;3egNb7NabCea*Wi-Cjt$6R{`;_5g_XTj}+0-9L2o^xRf_?WSRCpk-hGy?{Ro2l~lYY{OjjlcGEbWY3l0O z+Nq@8&`v}i<*~zv4O2NzugwD2Wy=?dIv6q6oH>5@yVle3d>r+a#XeIBTowP*)uh*9 zWig(E$DFntEt!!4b5w{cyzvteaIGn0XDm?#p239ihut;&@F+2R(Epi%(o@MfbK3OcTu~AA6$F4kSwr z{cibu#LmEOBV&Q~KlhfA3JDCqFHN8PmmLlQEJ7T+G6 z_iwctv^KlK_AeUzQnN0!2HPvps1PS|ySCc@u8I~bqFr?>Xl${5kZV`e%mF;5qU{LQAZ9bL@z{q^ac=vfJXf(IENZ#RG+LL|ATegp66v*Bj%Cvrsna#QQ}zoV<(1YSDz?h&9xr9>y0S9wJ%xgwV(sffpAEG?65`#> zdO{Y<#=t+P4iwCZ{Q^Ur>R-la>B&3217}(_WEib3UkaaTYlbmmjb-R{U!FDfo_kZw zotQ*VmKs}gDr8Ttgum;WS*+G!e}qwX)j!^0O6O73A+C*0Kb6;D8JO?Y|2J9xlUIzE z^WfiJSB&Q26K7wQ(LTHzUR!umPTL$04{MQ-yFxPZ8e!X`V6cc#qt#zzb}ee%@~f2B zR(Cs!yOYVj?TApl8zjl{FZ1esbRK6oZ`0K7+f{WOv5h_bd!TIJrmW72q-aCxA9tD;E2MUgm?7w! zon`qcp5xE*4RJQ}NUWkcX0Wc*;@(%=(%$SNR}Jk)xW4#YP-?}BzMYz1T}rt;^VC+C z=H2I&J+ghg%vq#74$W?hD61t&8q65k7lRp~@xA2HeR}@fo`!P*^XP3<_GSF)^8CXr z^GUN7)%{c>({cHrU|C|Eem*&kvfVYjui*J48KbywatXA|PA*IKY*;Gt=kv-GEjRK{ z@xpK|?j!bp#Qu}}EsxkAZz&-B*|2{&6NomO9qR{#yjc7_Sm~5TO7Lgn=`6#&RyF-n z`u$k`E2r%Sk@Ms@H?MPoW?f;^wnjB6``h}vditZh5vtaSNo?qw1AWa| z$A%&vwBfIL{Tu3q^K>m2Pu+FJtwY5Hc7^(=(thpd#+YwKb7~>*BvsPhCW;7P7mmeeWoE7SOg3pNYNf`OIj;=U;x7 z4@fmsp-i2fo3LDud6dKnIZI($DUBMEk-0WZ)yCF_RKn?JGOboSLR~A<7n&h$bV=t+qnPpvODRRd_CKE@igM3V}=%tTkQ)Tihlf01IvDPeUT?9 zEXpvdN_LcYj}KWbZ9&RMWtwdKG+ts~=N6Ef1-|5Iunyy*$IIf0R?FXD1xe0lD$9<& zRYCK2`nbgG%w7MaMqYgb8d}^Bd&%tRaGlYS=4a>SK&Jd(AJLLotO5&3ool)h@+MYo zL|k_m`!nLMY}x(;Zo`7cj0@{U`yppNy;=3t3bZM7diopxJDc{2QVh|5 zFceSzXehgRf`k(zw*muPaPwKoU}nW2h5!an1|0?k21f=z1{a1P27e&m1uPQI;L6~% nIa=0|Wpav=9;3qKiAvF%<&<0)Cz~ndY<{48hJ}Tffr|kEat$+t diff --git a/projects/Notepad++/raylib_npp_parser/raylib_npp.xml b/projects/Notepad++/raylib_npp_parser/raylib_npp.xml index ee965bd76..21c996ee1 100644 --- a/projects/Notepad++/raylib_npp_parser/raylib_npp.xml +++ b/projects/Notepad++/raylib_npp_parser/raylib_npp.xml @@ -191,7 +191,7 @@ - + @@ -360,7 +360,7 @@ - + @@ -498,8 +498,12 @@ - - + + + + + + @@ -507,11 +511,13 @@ - - - + + + + + @@ -524,35 +530,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -588,12 +566,69 @@ - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -605,7 +640,7 @@ - + @@ -615,6 +650,11 @@ + + + + + @@ -653,7 +693,7 @@ - + @@ -667,12 +707,12 @@ - + - + @@ -694,9 +734,16 @@ - - - + + + + + + + + + + @@ -716,15 +763,15 @@ - + - - + + @@ -746,7 +793,12 @@ - + + + + + + @@ -823,6 +875,11 @@ + + + + + @@ -868,12 +925,12 @@ - + - + @@ -1098,6 +1155,15 @@ + + + + + + + + + @@ -1106,6 +1172,21 @@ + + + + + + + + + + + + + + + @@ -1126,22 +1207,6 @@ - - - - - - - - - - - - - - - - @@ -1166,6 +1231,14 @@ + + + + + + + + @@ -1175,6 +1248,14 @@ + + + + + + + + @@ -1252,8 +1333,8 @@ - + @@ -1637,7 +1718,7 @@ - + @@ -2099,7 +2180,7 @@ - + @@ -2107,7 +2188,7 @@ - + @@ -2188,13 +2269,13 @@ - + - + @@ -2388,7 +2469,7 @@ - + @@ -2405,7 +2486,7 @@ - + @@ -2419,9 +2500,10 @@ - + + @@ -2531,6 +2613,15 @@ + + + + + + + + + @@ -2604,7 +2695,20 @@ - + + + + + + + + + + + + + + @@ -2635,80 +2739,121 @@ - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - - + - + @@ -2995,7 +3140,7 @@ - + @@ -3180,22 +3325,20 @@ - + - + - - + + - - - - - - - + + + + + @@ -3333,7 +3476,7 @@ - + @@ -3406,7 +3549,7 @@ - + @@ -3514,7 +3657,7 @@ - + @@ -3598,7 +3741,7 @@ - + @@ -3638,5 +3781,3 @@ - - diff --git a/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h b/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h index 1bd26fbc3..bd6c4c3f4 100644 --- a/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h +++ b/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h @@ -49,7 +49,7 @@ RLAPI Vector2 GetWindowScaleDPI(void); // Get window RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor RLAPI void SetClipboardText(const char *text); // Set clipboard text content RLAPI const char *GetClipboardText(void); // Get clipboard text content -RLAPI Image GetClipboardImage(void); // Get clipboard image +RLAPI Image GetClipboardImage(void); // Get clipboard image content RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling @@ -91,10 +91,10 @@ RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Lo RLAPI bool IsShaderValid(Shader shader); // Check if a shader is valid (loaded on GPU) RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location -RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value -RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count); // Set shader uniform value vector -RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4) -RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value for texture (sampler2d) +RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value +RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count); // Set shader uniform value vector +RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4) +RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value and bind the texture (sampler2d) RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM) // Screen-space-related functions @@ -109,99 +109,106 @@ RLAPI Matrix GetCameraMatrix(Camera camera); // Get c RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix // Timing-related functions -RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum) -RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time) -RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow() -RLAPI int GetFPS(void); // Get current FPS +RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum) +RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time) +RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow() +RLAPI int GetFPS(void); // Get current FPS // Custom frame control functions // NOTE: Those functions are intended for advanced users that want full control over the frame processing // By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents() // To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL -RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing) -RLAPI void PollInputEvents(void); // Register all input events -RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution) +RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing) +RLAPI void PollInputEvents(void); // Register all input events +RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution) // Random values generation functions -RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator -RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included) +RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator +RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included) RLAPI int *LoadRandomSequence(unsigned int count, int min, int max); // Load random values sequence, no values repeated -RLAPI void UnloadRandomSequence(int *sequence); // Unload random values sequence +RLAPI void UnloadRandomSequence(int *sequence); // Unload random values sequence // Misc. functions -RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format) -RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS) -RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available) +RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format) +RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS) +RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available) -// NOTE: Following functions implemented in module [utils] -//------------------------------------------------------------------ -RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...) -RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level -RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator -RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator -RLAPI void MemFree(void *ptr); // Internal memory free +// Logging system +RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level +RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...) +RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log -// Set custom callbacks -// WARNING: Callbacks setup is intended for advanced users -RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log -RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader -RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver -RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader -RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver +// Memory management, using internal allocators +RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator +RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator +RLAPI void MemFree(void *ptr); // Internal memory free -// Files management functions +// File system management functions RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read) -RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData() +RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData() RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success -RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string -RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText() -RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success -//------------------------------------------------------------------ +RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string +RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText() +RLAPI bool SaveFileText(const char *fileName, const char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success -// File system functions -RLAPI bool FileExists(const char *fileName); // Check if file exists -RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists -RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav) -RLAPI int GetFileLength(const char *fileName); // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h) -RLAPI const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes dot: '.png') -RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string -RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string) -RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string) -RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) -RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string) -RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string) -RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success -RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success -RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory -RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS -RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths -RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result -RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths -RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window -RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths -RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths -RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time) +// File access custom callbacks +// WARNING: Callbacks setup is intended for advanced users +RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader +RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver +RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader +RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver + +RLAPI int FileRename(const char *fileName, const char *fileRename); // Rename file (if exists) +RLAPI int FileRemove(const char *fileName); // Remove file (if exists) +RLAPI int FileCopy(const char *srcPath, const char *dstPath); // Copy file from one path to another, dstPath created if it doesn't exist +RLAPI int FileMove(const char *srcPath, const char *dstPath); // Move file from one directory to another, dstPath created if it doesn't exist +RLAPI int FileTextReplace(const char *fileName, const char *search, const char *replacement); // Replace text in an existing file +RLAPI int FileTextFindIndex(const char *fileName, const char *search); // Find text in existing file +RLAPI bool FileExists(const char *fileName); // Check if file exists +RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists +RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (recommended include point: .png, .wav) +RLAPI int GetFileLength(const char *fileName); // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h) +RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time) +RLAPI const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes dot: '.png') +RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string +RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string) +RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string) +RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) +RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string) +RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string) +RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success +RLAPI bool ChangeDirectory(const char *dirPath); // Change working directory, return true on success +RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory +RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS +RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths, files and directories, no subdirs scan +RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*" +RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths +RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window +RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths +RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths +RLAPI unsigned int GetDirectoryFileCount(const char *dirPath); // Get the file count in a directory +RLAPI unsigned int GetDirectoryFileCountEx(const char *basePath, const char *filter, bool scanSubdirs); // Get the file count in a directory with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result // Compression/Encoding functionality RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize); // Compress data (DEFLATE algorithm), memory must be MemFree() RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree() -RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree() -RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree() -RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code -RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes) -RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes) - +RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string (includes NULL terminator), memory must be MemFree() +RLAPI unsigned char *DecodeDataBase64(const char *text, int *outputSize); // Decode Base64 string (expected NULL terminated), memory must be MemFree() +RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code +RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes) +RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes) +RLAPI unsigned int *ComputeSHA256(unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 bytes) // Automation events functionality -RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS -RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file -RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file -RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to -RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording -RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set) -RLAPI void StopAutomationEventRecording(void); // Stop recording automation events -RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event +RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS +RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file +RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file +RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to +RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording +RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set) +RLAPI void StopAutomationEventRecording(void); // Stop recording automation events +RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event //------------------------------------------------------------------------------------ // Input Handling Functions (Module: core) @@ -215,20 +222,20 @@ RLAPI bool IsKeyReleased(int key); // Check if a key RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty +RLAPI const char *GetKeyName(int key); // Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard) RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC) -RLAPI const char *GetKeyName(int key); // Get name of a QWERTY key on the current keyboard layout (eg returns string "q" for KEY_A on an AZERTY keyboard) // Input-related functions: gamepads -RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available -RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id -RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once -RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed -RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once -RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed -RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed -RLAPI int GetGamepadAxisCount(int gamepad); // Get gamepad axis count for a gamepad -RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get axis movement value for a gamepad axis -RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB) +RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available +RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id +RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once +RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed +RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once +RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed +RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed +RLAPI int GetGamepadAxisCount(int gamepad); // Get axis count for a gamepad +RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get movement value for a gamepad axis +RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB) RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration); // Set gamepad vibration for both motors (duration in seconds) // Input-related functions: mouse @@ -257,19 +264,19 @@ RLAPI int GetTouchPointCount(void); // Get number of t //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: rgestures) //------------------------------------------------------------------------------------ -RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags -RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected -RLAPI int GetGestureDetected(void); // Get latest detected gesture -RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds -RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector -RLAPI float GetGestureDragAngle(void); // Get gesture drag angle -RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta -RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle +RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags +RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected +RLAPI int GetGestureDetected(void); // Get latest detected gesture +RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds +RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector +RLAPI float GetGestureDragAngle(void); // Get gesture drag angle +RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta +RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle //------------------------------------------------------------------------------------ // Camera System Functions (Module: rcamera) //------------------------------------------------------------------------------------ -RLAPI void UpdateCamera(Camera *camera, int mode); // Update camera position for selected mode +RLAPI void UpdateCamera(Camera *camera, int mode); // Update camera position for selected mode RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom); // Update camera movement/rotation //------------------------------------------------------------------------------------ @@ -278,9 +285,9 @@ RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, f // Set texture and rectangle to be used on shapes drawing // NOTE: It can be useful when using basic shapes and one single font, // defining a font char white rectangle would allow drawing everything in a single draw call -RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing -RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing -RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing +RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing +RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing +RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing // Basic shapes drawing functions RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care] @@ -290,24 +297,27 @@ RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads) RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines) RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation +RLAPI void DrawLineDashed(Vector2 startPos, Vector2 endPos, int dashSize, int spaceSize, Color color); // Draw a dashed line RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle -RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle -RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline -RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); // Draw a gradient-filled circle RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version) +RLAPI void DrawCircleGradient(Vector2 center, float radius, Color inner, Color outer); // Draw a gradient-filled circle +RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle +RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version) RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse +RLAPI void DrawEllipseV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse (Vector version) RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline +RLAPI void DrawEllipseLinesV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse outline (Vector version) RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring -RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline +RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version) RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle -RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight); // Draw a gradient-filled rectangle with custom vertex colors +RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color bottomRight, Color topRight); // Draw a gradient-filled rectangle with custom vertex colors RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges @@ -322,11 +332,11 @@ RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters // Splines drawing functions -RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points -RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points -RLAPI void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points -RLAPI void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] -RLAPI void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] +RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points +RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points +RLAPI void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points +RLAPI void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] +RLAPI void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] RLAPI void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color); // Draw spline segment: Linear, 2 points RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: B-Spline, 4 points RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points @@ -369,7 +379,7 @@ RLAPI Image LoadImageFromScreen(void); RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters) RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM) RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success -RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer +RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer, memory must be MemFree() RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success // Image generation functions @@ -399,7 +409,7 @@ RLAPI void ImageAlphaPremultiply(Image *image); RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation RLAPI void ImageKernelConvolution(Image *image, const float *kernel, int kernelSize); // Apply custom square convolution kernel to image RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm) -RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm) +RLAPI void ImageResizeNN(Image *image, int newWidth, int newHeight); // Resize image (Nearest-Neighbor scaling algorithm) RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color RLAPI void ImageMipmaps(Image *image); // Compute all mipmap levels for a provided image RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering) @@ -440,8 +450,8 @@ RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color c RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image -RLAPI void ImageDrawTriangleFan(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center) -RLAPI void ImageDrawTriangleStrip(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image +RLAPI void ImageDrawTriangleFan(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center) +RLAPI void ImageDrawTriangleStrip(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source) RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination) RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination) @@ -456,8 +466,8 @@ RLAPI bool IsTextureValid(Texture2D texture); RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM) RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if a render texture is valid (loaded in GPU) RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM) -RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data -RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data +RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data (pixels should be able to fill texture) +RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data (pixels and rec should fit in texture) // Texture configuration functions RLAPI void GenTextureMipmaps(Texture2D *texture); // Generate GPU mipmaps for a texture @@ -498,11 +508,11 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G // Font loading/unloading functions RLAPI Font GetFontDefault(void); // Get the default Font RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) -RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height +RLAPI Font LoadFontEx(const char *fileName, int fontSize, const int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style) -RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' +RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked) -RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use +RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount, int type, int *glyphCount); // Load font data for further use RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM) RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM) @@ -520,42 +530,51 @@ RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCou RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font +RLAPI Vector2 MeasureTextCodepoints(Font font, const int *codepoints, int length, float fontSize, float spacing); // Measure string size for an existing array of codepoints for Font RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint); // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found // Text codepoints management functions (unicode characters) -RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array -RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array -RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter -RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory -RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string -RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure -RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure -RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure -RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter) +RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array +RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array +RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter +RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory +RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string +RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure +RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure +RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure +RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter) // Text strings management functions (no UTF-8 strings, only byte chars) -// NOTE: Some strings allocate memory internally for returned strings, just be careful! +// WARNING 1: Most of these functions use internal static buffers[], it's recommended to store returned data on user-side for re-use +// WARNING 2: Some functions allocate memory internally for the returned strings, those strings must be freed by user using MemFree() +RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n') +RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style) RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string -RLAPI char *TextReplace(const char *text, const char *replace, const char *by); // Replace text string (WARNING: memory must be freed!) -RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!) -RLAPI const char *TextJoin(const char **textList, int count, const char *delimiter); // Join text strings with delimiter -RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings -RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor! -RLAPI int TextFindIndex(const char *text, const char *find); // Find first text occurrence within a string -RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string -RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string -RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string -RLAPI const char *TextToSnake(const char *text); // Get Snake case notation version of provided string -RLAPI const char *TextToCamel(const char *text); // Get Camel case notation version of provided string - -RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported) -RLAPI float TextToFloat(const char *text); // Get float value from text (negative values not supported) +RLAPI const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words +RLAPI char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings +RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string with new string +RLAPI char *TextReplaceAlloc(const char *text, const char *search, const char *replacement); // Replace text string with new string, memory must be MemFree() +RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings +RLAPI char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings, memory must be MemFree() +RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a defined byte position +RLAPI char *TextInsertAlloc(const char *text, const char *insert, int position); // Insert text in a defined byte position, memory must be MemFree() +RLAPI char *TextJoin(char **textList, int count, const char *delimiter); // Join text strings with delimiter +RLAPI char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings +RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor +RLAPI int TextFindIndex(const char *text, const char *search); // Find first text occurrence within a string, -1 if not found +RLAPI char *TextToUpper(const char *text); // Get upper case version of provided string +RLAPI char *TextToLower(const char *text); // Get lower case version of provided string +RLAPI char *TextToPascal(const char *text); // Get Pascal case notation version of provided string +RLAPI char *TextToSnake(const char *text); // Get Snake case notation version of provided string +RLAPI char *TextToCamel(const char *text); // Get Camel case notation version of provided string +RLAPI int TextToInteger(const char *text); // Get integer value from text +RLAPI float TextToFloat(const char *text); // Get float value from text //------------------------------------------------------------------------------------ // Basic 3d Shapes Drawing Functions (Module: models) @@ -601,7 +620,7 @@ RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, floa RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) -RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture +RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation @@ -639,21 +658,20 @@ RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Model animations loading/unloading functions RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file -RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose (CPU) -RLAPI void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (GPU skinning) -RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data +RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, float frame); // Update model animation pose (vertex buffers and bone matrices) +RLAPI void UpdateModelAnimationEx(Model model, ModelAnimation animA, float frameA, ModelAnimation animB, float frameB, float blend); // Update model animation pose, blending two animations RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match // Collision detection functions -RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres -RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes -RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere -RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere -RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box -RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh -RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle -RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad +RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres +RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes +RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere +RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere +RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box +RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh +RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle +RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad //------------------------------------------------------------------------------------ // Audio Loading and Playing Functions (Module: audio) @@ -675,7 +693,7 @@ RLAPI Sound LoadSound(const char *fileName); // Load so RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data RLAPI bool IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized) -RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data +RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data (default data format: 32 bit float, stereo) RLAPI void UnloadWave(Wave wave); // Unload wave data RLAPI void UnloadSound(Sound sound); // Unload sound RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data) @@ -690,7 +708,7 @@ RLAPI void ResumeSound(Sound sound); // Resume RLAPI bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing RLAPI void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level) RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level) -RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (0.5 is center) +RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (-1.0 left, 0.0 center, 1.0 right) RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave RLAPI void WaveCrop(Wave *wave, int initFrame, int finalFrame); // Crop a wave to defined frames range RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format @@ -711,7 +729,7 @@ RLAPI void ResumeMusicStream(Music music); // Resume RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds) RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level) RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level) -RLAPI void SetMusicPan(Music music, float pan); // Set pan for a music (0.5 is center) +RLAPI void SetMusicPan(Music music, float pan); // Set pan for a music (-1.0 left, 0.0 center, 1.0 right) RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds) RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds) @@ -728,7 +746,7 @@ RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check i RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level) RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level) -RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (0.5 is centered) +RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered) RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data @@ -737,4 +755,3 @@ RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processo RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives frames x 2 samples as 'float' (stereo) RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline - From dfbaafa337b8c2a873ca16596e633bf77c7f484e Mon Sep 17 00:00:00 2001 From: Maicon Santana Date: Tue, 14 Apr 2026 19:57:50 +0100 Subject: [PATCH 085/185] [zig] Adjusting build.zig to run on 0.16.0 (#5758) * Adjusting build.zig to run on 0.16.0 * changing version to 6 --- build.zig | 12 +----------- build.zig.zon | 4 ++-- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/build.zig b/build.zig index 1aedc58fe..2dc6258af 100644 --- a/build.zig +++ b/build.zig @@ -1,19 +1,9 @@ const std = @import("std"); const builtin = @import("builtin"); -/// Minimum supported version of Zig -const min_ver = "0.16.0-dev.3013+abd131e33"; - const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str; const emccOutputFile = "index.html"; -comptime { - const order = std.SemanticVersion.order; - const parse = std.SemanticVersion.parse; - if (order(builtin.zig_version, parse(min_ver) catch unreachable) == .lt) - @compileError("Raylib requires zig version " ++ min_ver); -} - pub const emsdk = struct { const zemscripten = @import("zemscripten"); @@ -489,7 +479,7 @@ fn addExamples( const all = b.step(module, "All " ++ module ++ " examples"); const module_subpath = b.pathJoin(&.{ "examples", module }); - var dir = try std.Io.Dir.cwd().openDir(b.graph.io, b.pathFromRoot(module_subpath), .{ .iterate = true }); + var dir = try b.build_root.handle.openDir(b.graph.io, module_subpath, .{ .iterate = true }); defer dir.close(b.graph.io); var iter = dir.iterate(); diff --git a/build.zig.zon b/build.zig.zon index ee5a84c68..dd25fde73 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,7 +1,7 @@ .{ .name = .raylib, - .version = "5.6.0-dev", - .minimum_zig_version = "0.15.1", + .version = "6.0.0", + .minimum_zig_version = "0.16.0", .fingerprint = 0x13035e5cb8bc1ac2, // Changing this has security and trust implications. From 4628915787b5eb007e2fa8833e516be93e4f2c3c Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Wed, 15 Apr 2026 02:18:30 -0500 Subject: [PATCH 086/185] Update typos/grammar (#5759) --- src/config.h | 8 ++++---- src/raylib.h | 20 ++++++++++---------- src/raymath.h | 6 +++--- src/rcamera.h | 4 ++-- src/rcore.c | 14 +++++++------- src/rgestures.h | 6 +++--- src/rlgl.h | 8 ++++---- src/rmodels.c | 2 +- src/rshapes.c | 4 ++-- src/rtextures.c | 4 ++-- 10 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/config.h b/src/config.h index a3502d772..37a2c050e 100644 --- a/src/config.h +++ b/src/config.h @@ -73,7 +73,7 @@ #define SUPPORT_RPRAND_GENERATOR 1 #endif #ifndef SUPPORT_MOUSE_GESTURES - // Mouse gestures are directly mapped like touches and processed by gestures system + // Mouse gestures are directly mapped like touches and processed by the gestures system #define SUPPORT_MOUSE_GESTURES 1 #endif #ifndef SUPPORT_SSH_KEYBOARD_RPI @@ -125,7 +125,7 @@ #endif // rcore: Configuration values -// NOTE: Below values are alread defined inside [rcore.c] so there is no need to be +// NOTE: Below values are already defined inside [rcore.c] so there is no need to be // redefined here, in case it must be done, uncomment the required line and update // the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128 //------------------------------------------------------------------------------------ @@ -159,7 +159,7 @@ #endif // rlgl: Configuration values -// NOTE: Below values are alread defined inside [rlgl.h] so there is no need to be +// NOTE: Below values are already defined inside [rlgl.h] so there is no need to be // redefined here, in case it must be done, uncomment the required line and update // the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128 //------------------------------------------------------------------------------------ @@ -349,7 +349,7 @@ #endif // raudio: Configuration values -// NOTE: Below values are alread defined inside [rlgl.h] so there is no need to be +// NOTE: Below values are already defined inside [rlgl.h] so there is no need to be // redefined here, in case it must be done, uncomment the required line and update // the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128 //------------------------------------------------------------------------------------ diff --git a/src/raylib.h b/src/raylib.h index 34c5a6488..bdca64329 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -10,7 +10,7 @@ * - Software renderer optional, for systems with no GPU: [rlsw] * - Custom OpenGL abstraction layer (usable as standalone module): [rlgl] * - Multiple Fonts formats supported (TTF, OTF, FNT, BDF, Sprite fonts) -* - Many texture formats supportted, including compressed formats (DXT, ETC, ASTC) +* - Many texture formats supported, including compressed formats (DXT, ETC, ASTC) * - Full 3d support for 3d Shapes, Models, Billboards, Heightmaps and more! * - Flexible Materials system, supporting classic maps and PBR maps * - Animated 3D models supported (skeletal bones animation) (IQM, M3D, GLTF) @@ -35,14 +35,14 @@ * [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm * [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm * [rcore] rprand (Ramon Santamaria) for pseudo-random numbers generation -* [rtextures] qoi (Dominic Szablewski - https://phoboslab.org) for QOI image manage -* [rtextures] stb_image (Sean Barret) for images loading (BMP, TGA, PNG, JPEG, HDR...) -* [rtextures] stb_image_write (Sean Barret) for image writing (BMP, TGA, PNG, JPG) -* [rtextures] stb_image_resize2 (Sean Barret) for image resizing algorithms -* [rtextures] stb_perlin (Sean Barret) for Perlin Noise image generation +* [rtextures] qoi (Dominic Szablewski - https://phoboslab.org) for QOI image management +* [rtextures] stb_image (Sean Barrett) for images loading (BMP, TGA, PNG, JPEG, HDR...) +* [rtextures] stb_image_write (Sean Barrett) for image writing (BMP, TGA, PNG, JPG) +* [rtextures] stb_image_resize2 (Sean Barrett) for image resizing algorithms +* [rtextures] stb_perlin (Sean Barrett) for Perlin Noise image generation * [rtextures] rltexgpu (Ramon Santamaria) for GPU-compressed texture formats -* [rtext] stb_truetype (Sean Barret) for ttf fonts loading -* [rtext] stb_rect_pack (Sean Barret) for rectangles packing +* [rtext] stb_truetype (Sean Barrett) for ttf fonts loading +* [rtext] stb_rect_pack (Sean Barrett) for rectangles packing * [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation * [rmodels] tinyobj_loader_c (Syoyo Fujita) for models loading (OBJ, MTL) * [rmodels] cgltf (Johannes Kuhlmann) for models loading (glTF) @@ -51,10 +51,10 @@ * [raudio] dr_wav (David Reid) for WAV audio file loading * [raudio] dr_flac (David Reid) for FLAC audio file loading * [raudio] dr_mp3 (David Reid) for MP3 audio file loading -* [raudio] stb_vorbis (Sean Barret) for OGG audio loading +* [raudio] stb_vorbis (Sean Barrett) for OGG audio loading * [raudio] jar_xm (Joshua Reisenauer) for XM audio module loading * [raudio] jar_mod (Joshua Reisenauer) for MOD audio module loading -* [raudio] qoa (Dominic Szablewski - https://phoboslab.org) for QOA audio manage +* [raudio] qoa (Dominic Szablewski - https://phoboslab.org) for QOA audio management * * * LICENSE: zlib/libpng diff --git a/src/raymath.h b/src/raymath.h index 8a0cce1a5..4460ed3f1 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -15,7 +15,7 @@ * - Functions use always a "result" variable for return (except C++ operators) * - Functions are always defined inline * - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience) -* - No compound literals used to make sure libray is compatible with C++ +* - No compound literals used to make sure the library is compatible with C++ * * CONFIGURATION: * #define RAYMATH_IMPLEMENTATION @@ -183,7 +183,7 @@ typedef struct float16 { #if RAYMATH_USE_SIMD_INTRINSICS // SIMD is used on the most costly raymath function MatrixMultiply() // NOTE: Only SSE intrinsics support implemented - // TODO: Consider support for other SIMD instrinsics: + // TODO: Consider support for other SIMD intrinsics: // - SSEx, AVX, AVX2, FMA, NEON, RVV /* #if defined(__SSE4_2__) @@ -1151,7 +1151,7 @@ RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view) // Create quaternion from source point Quaternion quat = { source.x, source.y, source.z, 1.0f }; - // Multiply quat point by unprojecte matrix + // Multiply quat point by unprojected matrix Quaternion qtransformed = { // QuaternionTransform(quat, matViewProjInv) matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w, matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w, diff --git a/src/rcamera.h b/src/rcamera.h index 14616a771..e6f5bba21 100644 --- a/src/rcamera.h +++ b/src/rcamera.h @@ -103,7 +103,7 @@ Vector3 position; // Camera position Vector3 target; // Camera target it looks-at Vector3 up; // Camera up vector (rotation over its axis) - float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic + float fovy; // Camera field-of-view aperture in Y (degrees) in perspective, used as near plane width in orthographic int projection; // Camera projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC } Camera3D; @@ -352,7 +352,7 @@ void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget) // Rotates the camera around its right vector, pitch is "looking up and down" // - lockView prevents camera overrotation (aka "somersaults") // - rotateAroundTarget defines if rotation is around target or around its position -// - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE) +// - rotateUp rotates the up direction as well (typically only useful in CAMERA_FREE) // NOTE: [angle] must be provided in radians void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp) { diff --git a/src/rcore.c b/src/rcore.c index f93e25573..92652be0e 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -307,7 +307,7 @@ typedef struct CoreData { Size screen; // Screen current width and height Point position; // Window current position Size previousScreen; // Screen previous width and height (required on fullscreen/borderless-windowed toggle) - Point previousPosition; // Window previous position (required on fullscreeen/borderless-windowed toggle) + Point previousPosition; // Window previous position (required on fullscreen/borderless-windowed toggle) Size render; // Screen framebuffer width and height Point renderOffset; // Screen framebuffer render offset (Not required anymore?) Size currentFbo; // Current framebuffer render width and height (depends on active render texture) @@ -329,7 +329,7 @@ typedef struct CoreData { char currentKeyState[MAX_KEYBOARD_KEYS]; // Registers current frame key state char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state - // NOTE: Since key press logic involves comparing previous vs currrent key state, + // NOTE: Since key press logic involves comparing previous vs current key state, // key repeats needs to be handled specially char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame @@ -714,7 +714,7 @@ void InitWindow(int width, int height, const char *title) Rectangle rec = GetFontDefault().recs[95]; if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT)) { - // NOTE: Try to maxime rec padding to avoid pixel bleeding on MSAA filtering + // NOTE: Try to maximize rec padding to avoid pixel bleeding on MSAA filtering SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 }); } else @@ -2514,9 +2514,9 @@ const char *GetFileNameWithoutExt(const char *filePath) if (filePath != NULL) { strncpy(fileName, GetFileName(filePath), MAX_FILENAME_LENGTH - 1); // Get filename.ext without path - int fileNameLenght = (int)strlen(fileName); // Get size in bytes + int fileNameLength = (int)strlen(fileName); // Get size in bytes - for (int i = fileNameLenght; i > 0; i--) // Reverse search '.' + for (int i = fileNameLength; i > 0; i--) // Reverse search '.' { if (fileName[i] == '.') { @@ -3039,7 +3039,7 @@ unsigned char *DecompressData(const unsigned char *compData, int compDataSize, i char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize) { // Base64 conversion table from RFC 4648 [0..63] - // NOTE: They represent 64 values (6 bits), to encode 3 bytes of data into 4 "sixtets" (6bit characters) + // NOTE: They represent 64 values (6 bits), to encode 3 bytes of data into 4 "sextets" (6bit characters) static const char base64EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // Compute expected size and padding @@ -3126,7 +3126,7 @@ unsigned char *DecodeDataBase64(const char *text, int *outputSize) int outputCount = 0; for (int i = 0; i < dataSize;) { - // Every 4 sixtets must generate 3 octets + // Every 4 sextets must generate 3 octets if ((i + 2) >= dataSize) { TRACELOG(LOG_WARNING, "BASE64: Decoding error: Input data size is not valid"); diff --git a/src/rgestures.h b/src/rgestures.h index e6cb86300..bb51d72ee 100644 --- a/src/rgestures.h +++ b/src/rgestures.h @@ -124,7 +124,7 @@ void UpdateGestures(void); // Update gestures detec #if defined(RGESTURES_STANDALONE) void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags -bool IsGestureDetected(int gesture); // Check if a gesture have been detected +bool IsGestureDetected(int gesture); // Check if a gesture has been detected int GetGestureDetected(void); // Get latest detected gesture float GetGestureHoldDuration(void); // Get gesture hold time in seconds @@ -297,10 +297,10 @@ void ProcessGestureEvent(GestureEvent event) } else if (event.touchAction == TOUCH_ACTION_UP) { - // A swipe can happen while the current gesture is drag, but (specially for web) also hold, so set upPosition for both cases + // A swipe can happen while the current gesture is drag, but (especially for web) also hold, so set upPosition for both cases if (GESTURES.current == GESTURE_DRAG || GESTURES.current == GESTURE_HOLD) GESTURES.Touch.upPosition = event.position[0]; - // NOTE: GESTURES.Drag.intensity dependent on the resolution of the screen + // NOTE: GESTURES.Drag.intensity is dependent on the resolution of the screen GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition); GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((rgGetCurrentTime() - GESTURES.Swipe.startTime)); diff --git a/src/rlgl.h b/src/rlgl.h index 073cecd68..b7854e46e 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -7,10 +7,10 @@ * that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...) * * ADDITIONAL NOTES: -* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are +* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffers are * initialized on rlglInit() to accumulate vertex data * -* When an internal state change is required all the stored vertex data is rendered in batch, +* When an internal state change is required all the stored vertex data is rendered in a batch, * additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch * * Some resources are also loaded for convenience, here the complete list: @@ -29,7 +29,7 @@ * #define GRAPHICS_API_OPENGL_ES2 * #define GRAPHICS_API_OPENGL_ES3 * Use selected OpenGL graphics backend, should be supported by platform -* Those preprocessor defines are only used on rlgl module, if OpenGL version is +* Those preprocessor defines are only used on the rlgl module, if OpenGL version is * required by any other module, use rlGetVersion() to check it * * #define RLGL_IMPLEMENTATION @@ -49,7 +49,7 @@ * #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits * #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) * #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) -* #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture()) +* #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of texture units that can be activated on batch drawing (SetShaderValueTexture()) * * #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack * #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported diff --git a/src/rmodels.c b/src/rmodels.c index 3dd28c6c1..17b67302a 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -6898,7 +6898,7 @@ static Model LoadM3D(const char *fileName) mi = m3d->face[i].materialid; // Only allocate colors VertexBuffer if there's a color vertex in the model for this material batch - // if all colors are fully transparent black for all verteces of this materal, then assuming no vertex colors + // if all colors are fully transparent black for all vertices of this material, then assuming no vertex colors for (j = i, l = vcolor = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++) { if (!m3d->vertex[m3d->face[j].vertex[0]].color || diff --git a/src/rshapes.c b/src/rshapes.c index b39ecb743..daec36060 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -8,11 +8,11 @@ * are used but QUADS implementation can be selected with SUPPORT_QUADS_DRAW_MODE define * * Some functions define texture coordinates (rlTexCoord2f()) for the shapes and use a -* user-provided texture with SetShapesTexture(), the pourpouse of this implementation +* user-provided texture with SetShapesTexture(), the purpose of this implementation * is allowing to reduce draw calls when combined with a texture-atlas * * By default, raylib sets the default texture and rectangle at InitWindow()[rcore] to one -* white character of default font [rtext], this way, raylib text and shapes can be draw with +* white character of default font [rtext], this way, raylib text and shapes can be drawn with * a single draw call and it also allows users to configure it the same way with their own fonts * * CONFIGURATION: diff --git a/src/rtextures.c b/src/rtextures.c index b13f697d1..a1f6618c7 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -366,7 +366,7 @@ Image LoadImageAnim(const char *fileName, int *frames) return image; } -// Load animated image data +// Load animated image data from memory // - Image.data buffer includes all frames: [image#0][image#1][image#2][...] // - Number of frames is returned through 'frames' parameter // - All frames are returned in RGBA format @@ -1575,7 +1575,7 @@ Image ImageFromChannel(Image image, int selectedChannel) // Check for RGBA formats if (selectedChannel > 3) { - TRACELOG(LOG_WARNING, "ImageFromChannel supports channels 0 to 3 (rgba). Setting channel to alpha."); + TRACELOG(LOG_WARNING, "ImageFromChannel supports channels 0 to 3 (RGBA). Setting channel to alpha."); selectedChannel = 3; } From 0decdcd497aadc8adb05bf3e731ed22356f4eef5 Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Wed, 15 Apr 2026 05:20:51 -0500 Subject: [PATCH 087/185] update defines for new format etc (#5760) --- src/config.h | 3 +++ src/raudio.c | 18 +++++++++--------- src/rcore.c | 16 ++++++++-------- src/rmodels.c | 18 +++++++++--------- src/rshapes.c | 4 ++-- src/rtext.c | 16 ++++++++-------- src/rtextures.c | 40 ++++++++++++++++++++-------------------- 7 files changed, 59 insertions(+), 56 deletions(-) diff --git a/src/config.h b/src/config.h index 37a2c050e..c50f2bcbf 100644 --- a/src/config.h +++ b/src/config.h @@ -252,6 +252,9 @@ #ifndef SUPPORT_FILEFORMAT_PIC #define SUPPORT_FILEFORMAT_PIC 0 // Disabled by default #endif +#ifdef SUPPORT_FILEFORMAT_PNM + #define SUPPORT_FILEFORMAT_PNM 0 // Disabled by default +#endif #ifndef SUPPORT_FILEFORMAT_KTX #define SUPPORT_FILEFORMAT_KTX 0 // Disabled by default #endif diff --git a/src/raudio.c b/src/raudio.c index 8107886cb..3cd6b37aa 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -11,22 +11,22 @@ * - Play/Stop/Pause/Resume loaded audio * * CONFIGURATION: -* #define SUPPORT_MODULE_RAUDIO +* #define SUPPORT_MODULE_RAUDIO 1 * raudio module is included in the build * * #define RAUDIO_STANDALONE * Define to use the module as standalone library (independently of raylib) * Required types and functions are defined in the same module * -* #define SUPPORT_FILEFORMAT_WAV -* #define SUPPORT_FILEFORMAT_OGG -* #define SUPPORT_FILEFORMAT_MP3 -* #define SUPPORT_FILEFORMAT_QOA -* #define SUPPORT_FILEFORMAT_FLAC -* #define SUPPORT_FILEFORMAT_XM -* #define SUPPORT_FILEFORMAT_MOD +* #define SUPPORT_FILEFORMAT_WAV 1 +* #define SUPPORT_FILEFORMAT_OGG 1 +* #define SUPPORT_FILEFORMAT_MP3 1 +* #define SUPPORT_FILEFORMAT_QOA 1 +* #define SUPPORT_FILEFORMAT_FLAC 0 +* #define SUPPORT_FILEFORMAT_XM 1 +* #define SUPPORT_FILEFORMAT_MOD 1 * Selected desired fileformats to be supported for loading. Some of those formats are -* supported by default, to remove support, comment unrequired #define in this module +* supported by default, to remove support, #define as 0 in this module or your build system * * DEPENDENCIES: * miniaudio.h - Audio device management lib (https://github.com/mackron/miniaudio) diff --git a/src/rcore.c b/src/rcore.c index 92652be0e..46d964961 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -35,31 +35,31 @@ * - Memory framebuffer output, using software renderer, no OS required * * CONFIGURATION: -* #define SUPPORT_CAMERA_SYSTEM +* #define SUPPORT_CAMERA_SYSTEM 1 * Camera module is included (rcamera.h) and multiple predefined cameras are available: * free, 1st/3rd person, orbital, custom * -* #define SUPPORT_GESTURES_SYSTEM +* #define SUPPORT_GESTURES_SYSTEM 1 * Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag * -* #define SUPPORT_MOUSE_GESTURES +* #define SUPPORT_MOUSE_GESTURES 1 * Mouse gestures are directly mapped like touches and processed by gestures system * -* #define SUPPORT_BUSY_WAIT_LOOP +* #define SUPPORT_BUSY_WAIT_LOOP 1 * Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used * -* #define SUPPORT_PARTIALBUSY_WAIT_LOOP +* #define SUPPORT_PARTIALBUSY_WAIT_LOOP 0 * Use a partial-busy wait loop, in this case frame sleeps for most of the time and runs a busy-wait-loop at the end * -* #define SUPPORT_SCREEN_CAPTURE +* #define SUPPORT_SCREEN_CAPTURE 1 * Allow automatic screen capture of current screen pressing F12, defined in KeyCallback() * -* #define SUPPORT_COMPRESSION_API +* #define SUPPORT_COMPRESSION_API 1 * Support CompressData() and DecompressData() functions, those functions use zlib implementation * provided by stb_image and stb_image_write libraries, so, those libraries must be enabled on textures module * for linkage * -* #define SUPPORT_AUTOMATION_EVENTS +* #define SUPPORT_AUTOMATION_EVENTS 1 * Support automatic events recording and playing, useful for automated testing systems or AI based game playing * * DEPENDENCIES: diff --git a/src/rmodels.c b/src/rmodels.c index 17b67302a..1b39bed5c 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -3,19 +3,19 @@ * rmodels - Basic functions to draw 3d shapes and load and draw 3d models * * CONFIGURATION: -* #define SUPPORT_MODULE_RMODELS +* #define SUPPORT_MODULE_RMODELS 1 * rmodels module is included in the build * -* #define SUPPORT_FILEFORMAT_OBJ -* #define SUPPORT_FILEFORMAT_MTL -* #define SUPPORT_FILEFORMAT_IQM -* #define SUPPORT_FILEFORMAT_GLTF -* #define SUPPORT_FILEFORMAT_GLTF_WRITE -* #define SUPPORT_FILEFORMAT_VOX -* #define SUPPORT_FILEFORMAT_M3D +* #define SUPPORT_FILEFORMAT_OBJ 1 +* #define SUPPORT_FILEFORMAT_MTL 1 +* #define SUPPORT_FILEFORMAT_IQM 1 +* #define SUPPORT_FILEFORMAT_GLTF 1 +* #define SUPPORT_FILEFORMAT_GLTF_WRITE 0 +* #define SUPPORT_FILEFORMAT_VOX 1 +* #define SUPPORT_FILEFORMAT_M3D 1 * Selected desired fileformats to be supported for model data loading * -* #define SUPPORT_MESH_GENERATION +* #define SUPPORT_MESH_GENERATION 1 * Support procedural mesh generation functions, uses external par_shapes.h library * NOTE: Some generated meshes DO NOT include generated texture coordinates * diff --git a/src/rshapes.c b/src/rshapes.c index daec36060..0ceeaa68d 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -16,10 +16,10 @@ * a single draw call and it also allows users to configure it the same way with their own fonts * * CONFIGURATION: -* #define SUPPORT_MODULE_RSHAPES +* #define SUPPORT_MODULE_RSHAPES 1 * rshapes module is included in the build * -* #define SUPPORT_QUADS_DRAW_MODE +* #define SUPPORT_QUADS_DRAW_MODE 1 * Use QUADS instead of TRIANGLES for drawing when possible. Lines-based shapes still use LINES * * diff --git a/src/rtext.c b/src/rtext.c index f71991e33..41f943f26 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -3,22 +3,22 @@ * rtext - Basic functions to load fonts and draw text * * CONFIGURATION: -* #define SUPPORT_MODULE_RTEXT +* #define SUPPORT_MODULE_RTEXT 1 * rtext module is included in the build * -* #define SUPPORT_FILEFORMAT_FNT -* #define SUPPORT_FILEFORMAT_TTF -* #define SUPPORT_FILEFORMAT_BDF +* #define SUPPORT_FILEFORMAT_FNT 1 +* #define SUPPORT_FILEFORMAT_TTF 1 +* #define SUPPORT_FILEFORMAT_BDF 0 * Selected desired fileformats to be supported for loading. Some of those formats are -* supported by default, to remove support, comment unrequired #define in this module +* supported by default, to remove support, #define as 0 in this module or your build system * -* #define TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH +* #define MAX_TEXT_BUFFER_LENGTH 1024 * TextSplit() function static buffer max size * -* #define MAX_TEXTSPLIT_COUNT +* #define MAX_TEXTSPLIT_COUNT 128 * TextSplit() function static substrings pointers array (pointing to static buffer) * -* #define FONT_ATLAS_CORNER_REC_SIZE +* #define FONT_ATLAS_CORNER_REC_SIZE 3 * On font atlas image generation [GenImageFontAtlas()], add a NxN pixels white rectangle * at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow * drawing text and shapes with a single draw call [SetShapesTexture()] diff --git a/src/rtextures.c b/src/rtextures.c index a1f6618c7..8a815abef 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -3,31 +3,31 @@ * rtextures - Basic functions to load and draw textures * * CONFIGURATION: -* #define SUPPORT_MODULE_RTEXTURES +* #define SUPPORT_MODULE_RTEXTURES 1 * rtextures module is included in the build * -* #define SUPPORT_FILEFORMAT_BMP -* #define SUPPORT_FILEFORMAT_PNG -* #define SUPPORT_FILEFORMAT_TGA -* #define SUPPORT_FILEFORMAT_JPG -* #define SUPPORT_FILEFORMAT_GIF -* #define SUPPORT_FILEFORMAT_QOI -* #define SUPPORT_FILEFORMAT_PSD -* #define SUPPORT_FILEFORMAT_HDR -* #define SUPPORT_FILEFORMAT_PIC -* #define SUPPORT_FILEFORMAT_PNM -* #define SUPPORT_FILEFORMAT_DDS -* #define SUPPORT_FILEFORMAT_PKM -* #define SUPPORT_FILEFORMAT_KTX -* #define SUPPORT_FILEFORMAT_PVR -* #define SUPPORT_FILEFORMAT_ASTC -* Select desired fileformats to be supported for image data loading. Some of those formats are -* supported by default, to remove support, comment unrequired #define in this module +* #define SUPPORT_FILEFORMAT_BMP 1 +* #define SUPPORT_FILEFORMAT_PNG 1 +* #define SUPPORT_FILEFORMAT_TGA 0 +* #define SUPPORT_FILEFORMAT_JPG 0 +* #define SUPPORT_FILEFORMAT_GIF 1 +* #define SUPPORT_FILEFORMAT_QOI 1 +* #define SUPPORT_FILEFORMAT_PSD 0 +* #define SUPPORT_FILEFORMAT_HDR 0 +* #define SUPPORT_FILEFORMAT_PIC 0 +* #define SUPPORT_FILEFORMAT_PNM 0 +* #define SUPPORT_FILEFORMAT_DDS 1 +* #define SUPPORT_FILEFORMAT_PKM 0 +* #define SUPPORT_FILEFORMAT_KTX 0 +* #define SUPPORT_FILEFORMAT_PVR 0 +* #define SUPPORT_FILEFORMAT_ASTC 0 +* Selected desired fileformats to be supported for image data loading. Some of those formats are +* supported by default, to remove support, #define as 0 in this module or your build system * -* #define SUPPORT_IMAGE_EXPORT +* #define SUPPORT_IMAGE_EXPORT 1 * Support image export in multiple file formats * -* #define SUPPORT_IMAGE_GENERATION +* #define SUPPORT_IMAGE_GENERATION 1 * Support procedural image generation functionality (gradient, spot, perlin-noise, cellular) * * DEPENDENCIES: From 82e980bd42389d6fb2a2c34d093478709b38736b Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Apr 2026 12:37:42 +0200 Subject: [PATCH 088/185] Log info about HighDPI content scaling on display initialization --- src/platforms/rcore_desktop_rgfw.c | 3 ++- src/platforms/rcore_desktop_sdl.c | 3 ++- src/platforms/rcore_desktop_win32.c | 3 ++- src/platforms/rcore_drm.c | 11 +++-------- src/platforms/rcore_template.c | 9 ++------- src/platforms/rcore_web.c | 3 ++- src/platforms/rcore_web_emscripten.c | 3 ++- 7 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 28a617af9..6b021ce66 100755 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -1719,7 +1719,8 @@ int InitPlatform(void) #endif } - TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); + 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); diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index dd845131e..277421720 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -2068,7 +2068,8 @@ int InitPlatform(void) CORE.Window.currentFbo.width = CORE.Window.render.width; CORE.Window.currentFbo.height = CORE.Window.render.height; - TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); + 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); diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index 07262aaea..3f2dcd8e3 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -1643,7 +1643,8 @@ int InitPlatform(void) 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"); + 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); diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index e742cb625..708a78004 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -1549,12 +1549,6 @@ int InitPlatform(void) 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"); - 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); } else { @@ -1580,13 +1574,14 @@ int InitPlatform(void) CORE.Window.render.height = CORE.Window.screen.height; CORE.Window.currentFbo.width = CORE.Window.render.width; CORE.Window.currentFbo.height = CORE.Window.render.height; +#endif - TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully (Software Rendering)"); + 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); -#endif if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED)) MinimizeWindow(); diff --git a/src/platforms/rcore_template.c b/src/platforms/rcore_template.c index 368dd3e77..c48484abb 100644 --- a/src/platforms/rcore_template.c +++ b/src/platforms/rcore_template.c @@ -474,12 +474,6 @@ int InitPlatform(void) 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"); - 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); } else { @@ -494,7 +488,8 @@ int InitPlatform(void) CORE.Window.currentFbo.width = CORE.Window.render.width; CORE.Window.currentFbo.height = CORE.Window.render.height; - TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); + 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); diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 8835ecdcc..e7e174127 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -1423,7 +1423,8 @@ int InitPlatform(void) CORE.Window.currentFbo.width = fbWidth; CORE.Window.currentFbo.height = fbHeight; - TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); + 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); diff --git a/src/platforms/rcore_web_emscripten.c b/src/platforms/rcore_web_emscripten.c index 3b6064255..186813f49 100644 --- a/src/platforms/rcore_web_emscripten.c +++ b/src/platforms/rcore_web_emscripten.c @@ -1245,7 +1245,8 @@ int InitPlatform(void) CORE.Window.currentFbo.width = fbWidth; CORE.Window.currentFbo.height = fbHeight; - TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); + 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); From d8ebeb8939c179de3e163e66eb2da25d10a3f040 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Apr 2026 21:03:25 +0200 Subject: [PATCH 089/185] Update raymath.h --- src/raymath.h | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/raymath.h b/src/raymath.h index 4460ed3f1..3d59266c5 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -1264,19 +1264,21 @@ RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r) //---------------------------------------------------------------------------------- // Module Functions Definition - Vector4 math //---------------------------------------------------------------------------------- - +// Get vector zero RMAPI Vector4 Vector4Zero(void) { Vector4 result = { 0.0f, 0.0f, 0.0f, 0.0f }; return result; } +// Get vector one RMAPI Vector4 Vector4One(void) { Vector4 result = { 1.0f, 1.0f, 1.0f, 1.0f }; return result; } +// Add two vectors RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2) { Vector4 result = { @@ -1288,6 +1290,7 @@ RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2) return result; } +// Add value to vector components RMAPI Vector4 Vector4AddValue(Vector4 v, float add) { Vector4 result = { @@ -1299,6 +1302,7 @@ RMAPI Vector4 Vector4AddValue(Vector4 v, float add) return result; } +// Substract vectors RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2) { Vector4 result = { @@ -1310,6 +1314,7 @@ RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2) return result; } +// Substract value from vector components RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add) { Vector4 result = { @@ -1321,18 +1326,21 @@ RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add) return result; } +// Vector length RMAPI float Vector4Length(Vector4 v) { float result = sqrtf((v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w)); return result; } +// Vector square length RMAPI float Vector4LengthSqr(Vector4 v) { float result = (v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w); return result; } +// Vectors dot product RMAPI float Vector4DotProduct(Vector4 v1, Vector4 v2) { float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w); @@ -1358,6 +1366,7 @@ RMAPI float Vector4DistanceSqr(Vector4 v1, Vector4 v2) return result; } +// Scale vector components by value (multiply) RMAPI Vector4 Vector4Scale(Vector4 v, float scale) { Vector4 result = { v.x*scale, v.y*scale, v.z*scale, v.w*scale }; @@ -1753,13 +1762,14 @@ RMAPI Matrix MatrixMultiply(Matrix left, Matrix right) return result; } +// Multiply matrix components by value RMAPI Matrix MatrixMultiplyValue(Matrix left, float value) { Matrix result = { - left.m0 * value, left.m4 * value, left.m8 * value, left.m12 * value, - left.m1 * value, left.m5 * value, left.m9 * value, left.m13 * value, - left.m2 * value, left.m6 * value, left.m10 * value, left.m14 * value, - left.m3 * value, left.m7 * value, left.m11 * value, left.m15 * value + left.m0*value, left.m4*value, left.m8*value, left.m12*value, + left.m1*value, left.m5*value, left.m9*value, left.m13*value, + left.m2*value, left.m6*value, left.m10*value, left.m14*value, + left.m3*value, left.m7*value, left.m11*value, left.m15*value }; return result; From 21897f4bb9e326955d9c26772bb3fdef436d8534 Mon Sep 17 00:00:00 2001 From: nadav78 <95895660+nadav78@users.noreply.github.com> Date: Thu, 16 Apr 2026 00:51:47 +0300 Subject: [PATCH 090/185] Remap stb_vorbis malloc/free calls to RL_MALLOC/RL_FREE (#5763) --- src/raudio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/raudio.c b/src/raudio.c index 3cd6b37aa..9ca5e9c7d 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -210,8 +210,11 @@ typedef struct tagBITMAPINFOHEADER { #endif #if SUPPORT_FILEFORMAT_OGG - // TODO: Remap stb_vorbis malloc()/free() calls to RL_MALLOC/RL_FREE + #define malloc RL_MALLOC + #define free RL_FREE #include "external/stb_vorbis.c" // OGG loading functions + #undef malloc + #undef free #endif #if SUPPORT_FILEFORMAT_MP3 From 1e43c1d3724dd4248a784e3150377c1590488c14 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Apr 2026 23:58:05 +0200 Subject: [PATCH 091/185] Revert "Remap stb_vorbis malloc/free calls to RL_MALLOC/RL_FREE (#5763)" This reverts commit 21897f4bb9e326955d9c26772bb3fdef436d8534. --- src/raudio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/raudio.c b/src/raudio.c index 9ca5e9c7d..3cd6b37aa 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -210,11 +210,8 @@ typedef struct tagBITMAPINFOHEADER { #endif #if SUPPORT_FILEFORMAT_OGG - #define malloc RL_MALLOC - #define free RL_FREE + // TODO: Remap stb_vorbis malloc()/free() calls to RL_MALLOC/RL_FREE #include "external/stb_vorbis.c" // OGG loading functions - #undef malloc - #undef free #endif #if SUPPORT_FILEFORMAT_MP3 From 96e30549f5f79611bd11c1899e36fb6008e886a1 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 16 Apr 2026 00:05:23 +0200 Subject: [PATCH 092/185] Align default values on comments for config variables --- src/raudio.c | 16 ++++++++-------- src/rcore.c | 14 +++++++------- src/rmodels.c | 18 +++++++++--------- src/rshapes.c | 4 ++-- src/rtext.c | 16 ++++++++-------- src/rtextures.c | 36 ++++++++++++++++++------------------ 6 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/raudio.c b/src/raudio.c index 3cd6b37aa..d624755ad 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -11,20 +11,20 @@ * - Play/Stop/Pause/Resume loaded audio * * CONFIGURATION: -* #define SUPPORT_MODULE_RAUDIO 1 +* #define SUPPORT_MODULE_RAUDIO 1 * raudio module is included in the build * * #define RAUDIO_STANDALONE * Define to use the module as standalone library (independently of raylib) * Required types and functions are defined in the same module * -* #define SUPPORT_FILEFORMAT_WAV 1 -* #define SUPPORT_FILEFORMAT_OGG 1 -* #define SUPPORT_FILEFORMAT_MP3 1 -* #define SUPPORT_FILEFORMAT_QOA 1 -* #define SUPPORT_FILEFORMAT_FLAC 0 -* #define SUPPORT_FILEFORMAT_XM 1 -* #define SUPPORT_FILEFORMAT_MOD 1 +* #define SUPPORT_FILEFORMAT_WAV 1 +* #define SUPPORT_FILEFORMAT_OGG 1 +* #define SUPPORT_FILEFORMAT_MP3 1 +* #define SUPPORT_FILEFORMAT_QOA 1 +* #define SUPPORT_FILEFORMAT_FLAC 0 +* #define SUPPORT_FILEFORMAT_XM 1 +* #define SUPPORT_FILEFORMAT_MOD 1 * Selected desired fileformats to be supported for loading. Some of those formats are * supported by default, to remove support, #define as 0 in this module or your build system * diff --git a/src/rcore.c b/src/rcore.c index 46d964961..eb48cc9ad 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -35,31 +35,31 @@ * - Memory framebuffer output, using software renderer, no OS required * * CONFIGURATION: -* #define SUPPORT_CAMERA_SYSTEM 1 +* #define SUPPORT_CAMERA_SYSTEM 1 * Camera module is included (rcamera.h) and multiple predefined cameras are available: * free, 1st/3rd person, orbital, custom * -* #define SUPPORT_GESTURES_SYSTEM 1 +* #define SUPPORT_GESTURES_SYSTEM 1 * Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag * -* #define SUPPORT_MOUSE_GESTURES 1 +* #define SUPPORT_MOUSE_GESTURES 1 * Mouse gestures are directly mapped like touches and processed by gestures system * -* #define SUPPORT_BUSY_WAIT_LOOP 1 +* #define SUPPORT_BUSY_WAIT_LOOP 1 * Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used * * #define SUPPORT_PARTIALBUSY_WAIT_LOOP 0 * Use a partial-busy wait loop, in this case frame sleeps for most of the time and runs a busy-wait-loop at the end * -* #define SUPPORT_SCREEN_CAPTURE 1 +* #define SUPPORT_SCREEN_CAPTURE 1 * Allow automatic screen capture of current screen pressing F12, defined in KeyCallback() * -* #define SUPPORT_COMPRESSION_API 1 +* #define SUPPORT_COMPRESSION_API 1 * Support CompressData() and DecompressData() functions, those functions use zlib implementation * provided by stb_image and stb_image_write libraries, so, those libraries must be enabled on textures module * for linkage * -* #define SUPPORT_AUTOMATION_EVENTS 1 +* #define SUPPORT_AUTOMATION_EVENTS 1 * Support automatic events recording and playing, useful for automated testing systems or AI based game playing * * DEPENDENCIES: diff --git a/src/rmodels.c b/src/rmodels.c index 1b39bed5c..012bf24c3 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -3,19 +3,19 @@ * rmodels - Basic functions to draw 3d shapes and load and draw 3d models * * CONFIGURATION: -* #define SUPPORT_MODULE_RMODELS 1 +* #define SUPPORT_MODULE_RMODELS 1 * rmodels module is included in the build * -* #define SUPPORT_FILEFORMAT_OBJ 1 -* #define SUPPORT_FILEFORMAT_MTL 1 -* #define SUPPORT_FILEFORMAT_IQM 1 -* #define SUPPORT_FILEFORMAT_GLTF 1 -* #define SUPPORT_FILEFORMAT_GLTF_WRITE 0 -* #define SUPPORT_FILEFORMAT_VOX 1 -* #define SUPPORT_FILEFORMAT_M3D 1 +* #define SUPPORT_FILEFORMAT_OBJ 1 +* #define SUPPORT_FILEFORMAT_MTL 1 +* #define SUPPORT_FILEFORMAT_IQM 1 +* #define SUPPORT_FILEFORMAT_GLTF 1 +* #define SUPPORT_FILEFORMAT_GLTF_WRITE 0 +* #define SUPPORT_FILEFORMAT_VOX 1 +* #define SUPPORT_FILEFORMAT_M3D 1 * Selected desired fileformats to be supported for model data loading * -* #define SUPPORT_MESH_GENERATION 1 +* #define SUPPORT_MESH_GENERATION 1 * Support procedural mesh generation functions, uses external par_shapes.h library * NOTE: Some generated meshes DO NOT include generated texture coordinates * diff --git a/src/rshapes.c b/src/rshapes.c index 0ceeaa68d..cdd440cf0 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -16,10 +16,10 @@ * a single draw call and it also allows users to configure it the same way with their own fonts * * CONFIGURATION: -* #define SUPPORT_MODULE_RSHAPES 1 +* #define SUPPORT_MODULE_RSHAPES 1 * rshapes module is included in the build * -* #define SUPPORT_QUADS_DRAW_MODE 1 +* #define SUPPORT_QUADS_DRAW_MODE 1 * Use QUADS instead of TRIANGLES for drawing when possible. Lines-based shapes still use LINES * * diff --git a/src/rtext.c b/src/rtext.c index 41f943f26..7b9d5f2c8 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -3,22 +3,22 @@ * rtext - Basic functions to load fonts and draw text * * CONFIGURATION: -* #define SUPPORT_MODULE_RTEXT 1 +* #define SUPPORT_MODULE_RTEXT 1 * rtext module is included in the build * -* #define SUPPORT_FILEFORMAT_FNT 1 -* #define SUPPORT_FILEFORMAT_TTF 1 -* #define SUPPORT_FILEFORMAT_BDF 0 +* #define SUPPORT_FILEFORMAT_FNT 1 +* #define SUPPORT_FILEFORMAT_TTF 1 +* #define SUPPORT_FILEFORMAT_BDF 0 * Selected desired fileformats to be supported for loading. Some of those formats are * supported by default, to remove support, #define as 0 in this module or your build system * -* #define MAX_TEXT_BUFFER_LENGTH 1024 -* TextSplit() function static buffer max size +* #define MAX_TEXT_BUFFER_LENGTH 1024 +* Text functions using static buffer max size * -* #define MAX_TEXTSPLIT_COUNT 128 +* #define MAX_TEXTSPLIT_COUNT 128 * TextSplit() function static substrings pointers array (pointing to static buffer) * -* #define FONT_ATLAS_CORNER_REC_SIZE 3 +* #define FONT_ATLAS_CORNER_REC_SIZE 3 * On font atlas image generation [GenImageFontAtlas()], add a NxN pixels white rectangle * at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow * drawing text and shapes with a single draw call [SetShapesTexture()] diff --git a/src/rtextures.c b/src/rtextures.c index 8a815abef..bfe9efe36 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -3,31 +3,31 @@ * rtextures - Basic functions to load and draw textures * * CONFIGURATION: -* #define SUPPORT_MODULE_RTEXTURES 1 +* #define SUPPORT_MODULE_RTEXTURES 1 * rtextures module is included in the build * -* #define SUPPORT_FILEFORMAT_BMP 1 -* #define SUPPORT_FILEFORMAT_PNG 1 -* #define SUPPORT_FILEFORMAT_TGA 0 -* #define SUPPORT_FILEFORMAT_JPG 0 -* #define SUPPORT_FILEFORMAT_GIF 1 -* #define SUPPORT_FILEFORMAT_QOI 1 -* #define SUPPORT_FILEFORMAT_PSD 0 -* #define SUPPORT_FILEFORMAT_HDR 0 -* #define SUPPORT_FILEFORMAT_PIC 0 -* #define SUPPORT_FILEFORMAT_PNM 0 -* #define SUPPORT_FILEFORMAT_DDS 1 -* #define SUPPORT_FILEFORMAT_PKM 0 -* #define SUPPORT_FILEFORMAT_KTX 0 -* #define SUPPORT_FILEFORMAT_PVR 0 -* #define SUPPORT_FILEFORMAT_ASTC 0 +* #define SUPPORT_FILEFORMAT_BMP 1 +* #define SUPPORT_FILEFORMAT_PNG 1 +* #define SUPPORT_FILEFORMAT_TGA 0 +* #define SUPPORT_FILEFORMAT_JPG 0 +* #define SUPPORT_FILEFORMAT_GIF 1 +* #define SUPPORT_FILEFORMAT_QOI 1 +* #define SUPPORT_FILEFORMAT_PSD 0 +* #define SUPPORT_FILEFORMAT_HDR 0 +* #define SUPPORT_FILEFORMAT_PIC 0 +* #define SUPPORT_FILEFORMAT_PNM 0 +* #define SUPPORT_FILEFORMAT_DDS 1 +* #define SUPPORT_FILEFORMAT_PKM 0 +* #define SUPPORT_FILEFORMAT_KTX 0 +* #define SUPPORT_FILEFORMAT_PVR 0 +* #define SUPPORT_FILEFORMAT_ASTC 0 * Selected desired fileformats to be supported for image data loading. Some of those formats are * supported by default, to remove support, #define as 0 in this module or your build system * -* #define SUPPORT_IMAGE_EXPORT 1 +* #define SUPPORT_IMAGE_EXPORT 1 * Support image export in multiple file formats * -* #define SUPPORT_IMAGE_GENERATION 1 +* #define SUPPORT_IMAGE_GENERATION 1 * Support procedural image generation functionality (gradient, spot, perlin-noise, cellular) * * DEPENDENCIES: From 86aa0950bd8c25da78fe1fc05b2a7b5f7eaa8b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nilso=20J=C3=BAnior?= <162613094+nilsojunior@users.noreply.github.com> Date: Thu, 16 Apr 2026 03:37:04 -0300 Subject: [PATCH 093/185] [raymath] Refactor `QuaternionFromAxisAngle` (#5766) Checking if lenght equals 0 inside the if statement is not necessary. --- src/raymath.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/raymath.h b/src/raymath.h index 3d59266c5..9398258dd 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -2505,19 +2505,14 @@ RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) { Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; - float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); + float length = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); - if (axisLength != 0.0f) + if (length != 0.0f) { angle *= 0.5f; - float length = 0.0f; - float ilength = 0.0f; - // Vector3Normalize(axis) - length = axisLength; - if (length == 0.0f) length = 1.0f; - ilength = 1.0f/length; + float ilength = 1.0f/length; axis.x *= ilength; axis.y *= ilength; axis.z *= ilength; From 49f88dc6ed674a3432a74fe52d98ff2c60886537 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 16 Apr 2026 11:12:50 +0200 Subject: [PATCH 094/185] Update config.h --- src/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.h b/src/config.h index c50f2bcbf..97f5ba544 100644 --- a/src/config.h +++ b/src/config.h @@ -252,7 +252,7 @@ #ifndef SUPPORT_FILEFORMAT_PIC #define SUPPORT_FILEFORMAT_PIC 0 // Disabled by default #endif -#ifdef SUPPORT_FILEFORMAT_PNM +#ifndef SUPPORT_FILEFORMAT_PNM #define SUPPORT_FILEFORMAT_PNM 0 // Disabled by default #endif #ifndef SUPPORT_FILEFORMAT_KTX From 6ef36c0a1733a04ed38990e7094a5e710ce1164b Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Thu, 16 Apr 2026 06:01:54 -0500 Subject: [PATCH 095/185] fix examples makefile define (#5767) --- examples/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Makefile b/examples/Makefile index 6b15d22ff..334f59694 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -510,7 +510,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32) # Libraries for Windows desktop compilation LDFLAGS += -L..\src LDLIBS = -lraylib -lgdi32 -lwinmm -lshcore - ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_11_SOFTWARE) + ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_SOFTWARE) LDLIBS += -lopengl32 endif endif From be768e27f9a599b1dc6463a1867606a526985ef2 Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 17 Apr 2026 10:55:04 -0500 Subject: [PATCH 096/185] fix issue with gettime (#5772) --- src/platforms/rcore_desktop_rgfw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 6b021ce66..fc357e364 100755 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -1131,7 +1131,9 @@ void SwapScreenBuffer(void) // Get elapsed time measure in seconds since InitTimer() double GetTime(void) { - double time = get_time_seconds() - CORE.Time.base; + // CORE.Time.base is nanoseconds as integer + double baseTime = (double)CORE.Time.base / 1e9; + double time = get_time_seconds() - baseTime; return time; } @@ -1654,7 +1656,6 @@ int InitPlatform(void) RGFW_setGlobalHints_OpenGL(hints); platform.window = RGFW_createWindow((CORE.Window.title != 0)? CORE.Window.title : " ", 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, flags | RGFW_windowOpenGL); - CORE.Time.base = get_time_seconds(); #ifndef PLATFORM_WEB_RGFW i32 screenSizeWidth; From 94f3c094e73112bccbb558819485d3b3d803e999 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Apr 2026 17:56:47 +0200 Subject: [PATCH 097/185] Update raudio.c --- src/raudio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/raudio.c b/src/raudio.c index d624755ad..f05567cc8 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1702,8 +1702,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, // Copy data to allocated memory for default UnloadMusicStream unsigned char *newData = (unsigned char *)RL_MALLOC(dataSize); - int it = dataSize/sizeof(unsigned char); - for (int i = 0; i < it; i++) newData[i] = data[i]; + for (int i = 0; i < dataSize; i++) newData[i] = data[i]; // Memory loaded version for jar_mod_load_file() if (dataSize && (dataSize < 32*1024*1024)) From 14fe0cbfd8c74ce179f23b3aaaf75c846e741390 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Apr 2026 17:56:49 +0200 Subject: [PATCH 098/185] Update rlgl.h --- src/rlgl.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index b7854e46e..5c6e95afb 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -1139,21 +1139,23 @@ typedef struct rlglData { //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- +static bool isGpuReady = false; static double rlCullDistanceNear = RL_CULL_DISTANCE_NEAR; static double rlCullDistanceFar = RL_CULL_DISTANCE_FAR; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) static rlglData RLGL = { 0 }; -#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 -static bool isGpuReady = false; +#endif #if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3) +// VAO functions entry points // NOTE: VAO functionality is exposed through extensions (OES) static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL; static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL; static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays = NULL; -// NOTE: Instancing functionality could also be available through extension +// Instancing functionality entry points +// NOTE: Instancing functionality could be available through extensions static PFNGLDRAWARRAYSINSTANCEDEXTPROC glDrawArraysInstanced = NULL; static PFNGLDRAWELEMENTSINSTANCEDEXTPROC glDrawElementsInstanced = NULL; static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL; From 7c96c24cf936235afccbebe6100ca1b0fc7db4fe Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Apr 2026 17:57:05 +0200 Subject: [PATCH 099/185] Update rcore.c --- src/rcore.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index eb48cc9ad..b36d9f825 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -379,14 +379,14 @@ typedef struct CoreData { } Gamepad; } Input; struct { - double current; // Current time measure - double previous; // Previous time measure - double update; // Time measure for frame update - double draw; // Time measure for frame draw - double frame; // Time measure for one frame - double target; // Desired time for one frame, if 0 not applied - unsigned long long int base; // Base time measure for hi-res timer (PLATFORM_ANDROID, PLATFORM_DRM) - unsigned int frameCounter; // Frame counter + double current; // Current time measure (seconds) + double previous; // Previous time measure (seconds) + double update; // Time measure for frame update (seconds) + double draw; // Time measure for frame draw (seconds) + double frame; // Time measure for one frame (seconds) + double target; // Desired time for one frame, if 0 not applied (seconds) + unsigned long long int base; // Base time measure for hi-res timer (ticks or nanoseconds) + unsigned int frameCounter; // Frame counter (frames) } Time; } CoreData; From 1cbe438f9385c782116fec1e7574c1a86693fc17 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Apr 2026 18:03:29 +0200 Subject: [PATCH 100/185] Update rcore_desktop_rgfw.c --- src/platforms/rcore_desktop_rgfw.c | 36 ++++++++++++++++-------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index fc357e364..a1ba74f52 100755 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -1132,7 +1132,7 @@ void SwapScreenBuffer(void) double GetTime(void) { // CORE.Time.base is nanoseconds as integer - double baseTime = (double)CORE.Time.base / 1e9; + double baseTime = (double)CORE.Time.base*1e-9; double time = get_time_seconds() - baseTime; return time; @@ -1793,34 +1793,36 @@ double get_time_seconds(void) #if defined(_WIN32) static LARGE_INTEGER freq = { 0 }; - static int freq_init = 0; - LARGE_INTEGER counter; - if (!freq_init) { + static bool freqInitialized = false; + LARGE_INTEGER counter = { 0 }; + if (!freqInitialized) + { + // Lazy initialization QueryPerformanceFrequency(&freq); - freq_init = 1; + freqInitialized = true; } QueryPerformanceCounter(&counter); - currentTime = (double)counter.QuadPart / (double)freq.QuadPart; + currentTime = (double)counter.QuadPart/(double)freq.QuadPart; #elif defined(__EMSCRIPTEN__) - currentTime = emscripten_get_now() / 1000.0; + currentTime = emscripten_get_now()/1000.0; #elif defined(__APPLE__) - static mach_timebase_info_data_t tb; - static int tb_initialized = 0; - - if (!tb_initialized) { + static mach_timebase_info_data_t tb = { 0 }; + static bool tbInitialized = false; + if (!tbInitialized) + { mach_timebase_info(&tb); - tb_initialized = 1; + tbInitialized = true; } uint64_t ticks = mach_absolute_time(); - currentTime = (double)ticks * (double)tb.numer / (double)tb.denom / 1e9; + currentTime = (double)ticks*(double)tb.numer/(double)tb.denom/1e9; #elif defined(__linux__) - struct timespec ts; + struct timespec ts = { 0 }; clock_gettime(CLOCK_MONOTONIC, &ts); - currentTime = (double)ts.tv_sec + (double)ts.tv_nsec / 1e9; + currentTime = (double)ts.tv_sec + (double)ts.tv_nsec/1e9; #else - // fallback to cstd - currentTime = (double)clock() / (double)CLOCKS_PER_SEC; + // Fallback to cstd + currentTime = (double)clock()/(double)CLOCKS_PER_SEC; #endif return currentTime; From dde8c8e07e1936a2879fd9b68517340697296375 Mon Sep 17 00:00:00 2001 From: areynaldo <49327220+areynaldo@users.noreply.github.com> Date: Fri, 17 Apr 2026 18:04:08 +0200 Subject: [PATCH 101/185] [build-windows.bat] Update build-windows script (#5769) * Update build-windows script * Use vswhere in build-windows script --- projects/scripts/build-windows.bat | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/projects/scripts/build-windows.bat b/projects/scripts/build-windows.bat index 2c085f8d6..311da23f7 100644 --- a/projects/scripts/build-windows.bat +++ b/projects/scripts/build-windows.bat @@ -26,13 +26,13 @@ REM Checks if cl is available and skips to the argument loop if it is REM (Prevents calling vcvarsall every time you run this script) WHERE cl >nul 2>nul IF %ERRORLEVEL% == 0 goto READ_ARGS + REM Activate the msvc build environment if cl isn't available yet -IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" ( - set VC_INIT="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" -) ELSE IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" ( - set VC_INIT="C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" -) ELSE IF EXIST "C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat" ( - set VC_INIT="C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat" +for /f "tokens=*" %%i in ( + '"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath 2^>nul' +) do set VS_PATH=%%i +IF defined VS_PATH ( + set VC_INIT="%VS_PATH%\VC\Auxiliary\Build\vcvarsall.bat" ) ELSE ( REM Initialize your vc environment here if the defaults don't work REM set VC_INIT="C:\your\path\here\vcvarsall.bat" @@ -167,7 +167,7 @@ IF NOT EXIST !TEMP_DIR!\ ( cd !TEMP_DIR! REM raylib source folder set "RAYLIB_DEFINES=/D_DEFAULT_SOURCE /DPLATFORM_DESKTOP /DGRAPHICS_API_OPENGL_33" - set RAYLIB_C_FILES="!RAYLIB_SRC!\rcore.c" "!RAYLIB_SRC!\rshapes.c" "!RAYLIB_SRC!\rtextures.c" "!RAYLIB_SRC!\rtext.c" "!RAYLIB_SRC!\rmodels.c" "!RAYLIB_SRC!\utils.c" "!RAYLIB_SRC!\raudio.c" "!RAYLIB_SRC!\rglfw.c" + set RAYLIB_C_FILES="!RAYLIB_SRC!\rcore.c" "!RAYLIB_SRC!\rshapes.c" "!RAYLIB_SRC!\rtextures.c" "!RAYLIB_SRC!\rtext.c" "!RAYLIB_SRC!\rmodels.c" "!RAYLIB_SRC!\raudio.c" "!RAYLIB_SRC!\rglfw.c" set RAYLIB_INCLUDE_FLAGS=/I"!RAYLIB_SRC!" /I"!RAYLIB_SRC!\external\glfw\include" IF DEFINED REALLY_QUIET ( From f0a043bb75c54974cba1642df0d24333c4315d6f Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 17 Apr 2026 11:09:57 -0500 Subject: [PATCH 102/185] [Platform/RGFW] add support for software rendering (#5773) * add support for software rendering * null check on freeing * add back line * rename framebuffer to surface * add guard on free * update makefile to prevent software on web * update for mac --- src/Makefile | 11 +- src/platforms/rcore_desktop_rgfw.c | 185 +++++++++++++++++++++++++++-- 2 files changed, 186 insertions(+), 10 deletions(-) diff --git a/src/Makefile b/src/Makefile index 997165b4a..13f132707 100644 --- a/src/Makefile +++ b/src/Makefile @@ -275,11 +275,20 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 #GRAPHICS = GRAPHICS_API_OPENGL_SOFTWARE # Uncomment to use software rendering endif -ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) # On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0 GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 #GRAPHICS = GRAPHICS_API_OPENGL_ES3 endif +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB_RGFW) + # On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0 + GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 + #GRAPHICS = GRAPHICS_API_OPENGL_ES3 + + ifeq ($(GRAPHICS),GRAPHICS_API_OPENGL_SOFTWARE) + $(error WEB_RGFW: Software rendering not supported!) + endif +endif ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) # By default use OpenGL ES 2.0 on Android GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index a1ba74f52..1a4831bf1 100755 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -177,6 +177,13 @@ typedef struct { RGFW_window *window; // Native display device (physical screen connection) RGFW_monitor *monitor; mg_gamepads minigamepad; + + #if defined(GRAPHICS_API_OPENGL_SOFTWARE) + RGFW_surface *surface; + u8 *surfacePixels; + i32 surfaceWidth; + i32 surfaceHeight; + #endif } PlatformData; //---------------------------------------------------------------------------------- @@ -1121,7 +1128,35 @@ void DisableCursor(void) // Swap back buffer with front buffer (screen drawing) void SwapScreenBuffer(void) { - RGFW_window_swapBuffers_OpenGL(platform.window); + #if defined(GRAPHICS_API_OPENGL_SOFTWARE) + { + if (platform.surface) + { + // copy rlsw pixel data to the surface framebuffer + swReadPixels(0, 0, platform.surfaceWidth, platform.surfaceHeight, SW_RGBA, SW_UNSIGNED_BYTE, platform.surfacePixels); + + // Mac wants a different pixel order. I cant seem to get this to work any other way + #if defined(__APPLE__) + unsigned char temp = 0; + unsigned char *p = NULL; + for (int i = 0; i < (platform.surfaceWidth * platform.surfaceHeight); i += 1) + { + p = platform.surfacePixels + (i * 4); + temp = p[0]; + p[0] = p[2]; + p[2] = temp; + } + #endif + + // blit surface to the window + RGFW_window_blitSurface(platform.window, platform.surface); + } + } + #else + { + RGFW_window_swapBuffers_OpenGL(platform.window); + } + #endif } //---------------------------------------------------------------------------------- @@ -1315,6 +1350,9 @@ void PollInputEvents(void) // Window events are also polled (Minimized, maximized, close...) case RGFW_windowResized: { + // set flag that the window was resized + CORE.Window.resizedLastFrame = true; + #if defined(__APPLE__) if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) { @@ -1363,7 +1401,42 @@ void PollInputEvents(void) CORE.Window.currentFbo.width = CORE.Window.screen.width; CORE.Window.currentFbo.height = CORE.Window.screen.height; #endif - CORE.Window.resizedLastFrame = true; + + #if defined(GRAPHICS_API_OPENGL_SOFTWARE) + #if defined(__APPLE__) + RGFW_monitor* currentMonitor = RGFW_window_getMonitor(platform.window); + CORE.Window.screenScale = MatrixScale(currentMonitor->pixelRatio, currentMonitor->pixelRatio, 1.0f); + SetupViewport(platform.window->w * currentMonitor->pixelRatio, platform.window->h * currentMonitor->pixelRatio); + + CORE.Window.render.width = CORE.Window.screen.width * currentMonitor->pixelRatio; + CORE.Window.render.height = CORE.Window.screen.height * currentMonitor->pixelRatio; + CORE.Window.currentFbo.width = CORE.Window.render.width; + CORE.Window.currentFbo.height = CORE.Window.render.height; + #endif + platform.surfaceWidth = CORE.Window.currentFbo.width; + platform.surfaceHeight = CORE.Window.currentFbo.height; + + // in software mode we dont have the viewport so we need to reverse the highdpi changes + if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) + { + Vector2 scaleDpi = GetWindowScaleDPI(); + platform.surfaceWidth *= scaleDpi.x; + platform.surfaceHeight *= scaleDpi.y; + } + + if (platform.surfacePixels != NULL) + { + RL_FREE(platform.surfacePixels); + platform.surfacePixels = RL_MALLOC(platform.surfaceWidth * platform.surfaceHeight * 4); + } + + if (platform.surface != NULL) + { + RGFW_surface_free(platform.surface); + platform.surface = RGFW_window_createSurface(platform.window, platform.surfacePixels, platform.surfaceWidth, platform.surfaceHeight, RGFW_formatBGRA8); + swResize(platform.surfaceWidth, platform.surfaceHeight); + } + #endif } break; case RGFW_windowMaximized: { @@ -1641,6 +1714,12 @@ int InitPlatform(void) hints->major = 4; hints->minor = 3; } + else if (rlGetVersion() == RL_OPENGL_SOFTWARE) + { + hints->major = 1; + hints->minor = 1; + hints->renderer = RGFW_glSoftware; + } if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT)) hints->samples = 4; @@ -1720,6 +1799,39 @@ int InitPlatform(void) #endif } + #if defined(GRAPHICS_API_OPENGL_SOFTWARE) + // apple always scales for retina + #if defined(__APPLE__) + RGFW_monitor* currentMonitor = RGFW_window_getMonitor(platform.window); + CORE.Window.screenScale = MatrixScale(currentMonitor->pixelRatio, currentMonitor->pixelRatio, 1.0f); + + CORE.Window.render.width = CORE.Window.screen.width * currentMonitor->pixelRatio; + CORE.Window.render.height = CORE.Window.screen.height * currentMonitor->pixelRatio; + CORE.Window.currentFbo.width = CORE.Window.render.width; + CORE.Window.currentFbo.height = CORE.Window.render.height; + #endif + + platform.surfaceWidth = CORE.Window.currentFbo.width; + platform.surfaceHeight = CORE.Window.currentFbo.height; + + platform.surfacePixels = RL_MALLOC(platform.surfaceWidth * platform.surfaceHeight * 4); + if (platform.surfacePixels == NULL) + { + TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize software pixel buffer"); + return -1; + } + + platform.surface = RGFW_window_createSurface(platform.window, platform.surfacePixels, platform.surfaceWidth, platform.surfaceHeight, RGFW_formatBGRA8); + + if (platform.surface == NULL) + { + RL_FREE(platform.surfacePixels); + + TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize software surface"); + return -1; + } + #endif + 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); @@ -1750,20 +1862,63 @@ int InitPlatform(void) //---------------------------------------------------------------------------- #if defined(RGFW_WAYLAND) - if (RGFW_usingWayland()) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland): Initialized successfully"); - else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (fallback)): Initialized successfully"); + if (rlGetVersion() == RL_OPENGL_SOFTWARE) + { + if (RGFW_usingWayland()) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland, Software): Initialized successfully"); + else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, Software (fallback)): Initialized successfully"); + } + else + { + if (RGFW_usingWayland()) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland): Initialized successfully"); + else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (fallback)): Initialized successfully"); + } #elif defined(RGFW_X11) #if defined(__APPLE__) - TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (MacOS)): Initialized successfully"); + if (rlGetVersion() == RL_OPENGL_SOFTWARE) + { + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, Software, (MacOS)): Initialized successfully"); + } + else + { + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, (MacOS)): Initialized successfully"); + } #else - TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11): Initialized successfully"); + if (rlGetVersion() == RL_OPENGL_SOFTWARE) + { + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, Software): Initialized successfully"); + } + else + { + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11): Initialized successfully"); + } #endif #elif defined (RGFW_WINDOWS) - TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32): Initialized successfully"); + if (rlGetVersion() == RL_OPENGL_SOFTWARE) + { + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32, Software): Initialized successfully"); + } + else + { + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32): Initialized successfully"); + } #elif defined(RGFW_WASM) - TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs): Initialized successfully"); + if (rlGetVersion() == RL_OPENGL_SOFTWARE) + { + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs, Software): Initialized successfully"); + } + else + { + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs): Initialized successfully"); + } #elif defined(RGFW_MACOS) - TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS): Initialized successfully"); + if (rlGetVersion() == RL_OPENGL_SOFTWARE) + { + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS, Software): Initialized successfully"); + } + else + { + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS): Initialized successfully"); + } #endif mg_gamepads_init(&platform.minigamepad); @@ -1776,6 +1931,18 @@ void ClosePlatform(void) { mg_gamepads_free(&platform.minigamepad); RGFW_window_close(platform.window); + + #if defined(GRAPHICS_API_OPENGL_SOFTWARE) + if (platform.surfacePixels != NULL) + { + RL_FREE(platform.surfacePixels); + } + + if (platform.surface != NULL) + { + RGFW_surface_free(platform.surface); + } + #endif } // Keycode mapping From 9a3283f698881963c3f8e589353ddcb4599ab5d7 Mon Sep 17 00:00:00 2001 From: Ziya Date: Sat, 18 Apr 2026 20:40:07 +0400 Subject: [PATCH 103/185] [examples] `shapes_collision_ellipses` (#5722) * Added shapes_collision_ellipses example * Address review comments from raysan * Address review comments * update collision ellipses screenshot * Restore shapes_following_eyes.c to upstream * Rename shapes_collision_ellipses to shapes_ellipse_collision and fix header --- examples/shapes/shapes_ellipse_collision.c | 133 +++++++++++++++++++ examples/shapes/shapes_ellipse_collision.png | Bin 0 -> 16967 bytes 2 files changed, 133 insertions(+) create mode 100644 examples/shapes/shapes_ellipse_collision.c create mode 100644 examples/shapes/shapes_ellipse_collision.png diff --git a/examples/shapes/shapes_ellipse_collision.c b/examples/shapes/shapes_ellipse_collision.c new file mode 100644 index 000000000..4a6d7e911 --- /dev/null +++ b/examples/shapes/shapes_ellipse_collision.c @@ -0,0 +1,133 @@ +/******************************************************************************************* +* +* raylib [shapes] example - ellipse collision +* +* Example complexity rating: [★★☆☆] 2/4 +* +* Example originally created with raylib 5.5, last time updated with raylib 5.5 +* +* Example contributed by Ziya (@Monjaris) +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2025 Ziya (@Monjaris) +* +********************************************************************************************/ + +#include "raylib.h" +#include + +// Check if point is inside ellipse +static bool CheckCollisionPointEllipse(Vector2 point, Vector2 center, float rx, float ry) +{ + float dx = (point.x - center.x)/rx; + float dy = (point.y - center.y)/ry; + return (dx*dx + dy*dy) <= 1.0f; +} + +// Check if two ellipses collide +// Uses radial boundary distance in the direction between centers — scales correctly with radii +static bool CheckCollisionEllipses(Vector2 c1, float rx1, float ry1, Vector2 c2, float rx2, float ry2) +{ + float dx = c2.x - c1.x; + float dy = c2.y - c1.y; + float dist = sqrtf(dx*dx + dy*dy); + + // Ellipses are on top of each other + if (dist == 0.0f) return true; + + float theta = atan2f(dy, dx); + float cosT = cosf(theta); + float sinT = sinf(theta); + + // Radial distance from center to ellipse boundary in direction theta + // r(theta) = (rx * ry) / sqrt((ry*cos)^2 + (rx*sin)^2) + float r1 = (rx1*ry1)/sqrtf((ry1*cosT)*(ry1*cosT) + (rx1*sinT)*(rx1*sinT)); + float r2 = (rx2*ry2)/sqrtf((ry2*cosT)*(ry2*cosT) + (rx2*sinT)*(rx2*sinT)); + + return dist <= (r1 + r2); +} + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - collision ellipses"); + SetTargetFPS(60); + + Vector2 ellipseACenter = { (float)screenWidth/4, (float)screenHeight/2 }; + float ellipseARx = 120.0f; + float ellipseARy = 70.0f; + + Vector2 ellipseBCenter = { (float)screenWidth*3/4, (float)screenHeight/2 }; + float ellipseBRx = 90.0f; + float ellipseBRy = 140.0f; + + // 0 = controlling A, 1 = controlling B + int controlled = 0; + + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_A)) controlled = 0; + if (IsKeyPressed(KEY_B)) controlled = 1; + + if (controlled == 0) ellipseACenter = GetMousePosition(); + else ellipseBCenter = GetMousePosition(); + + bool ellipsesCollide = CheckCollisionEllipses( + ellipseACenter, ellipseARx, ellipseARy, + ellipseBCenter, ellipseBRx, ellipseBRy + ); + + bool mouseInA = CheckCollisionPointEllipse(GetMousePosition(), ellipseACenter, ellipseARx, ellipseARy); + bool mouseInB = CheckCollisionPointEllipse(GetMousePosition(), ellipseBCenter, ellipseBRx, ellipseBRy); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawEllipse((int)ellipseACenter.x, (int)ellipseACenter.y, ellipseARx, ellipseARy, ellipsesCollide ? RED : BLUE); + + DrawEllipse((int)ellipseBCenter.x, (int)ellipseBCenter.y, ellipseBRx, ellipseBRy, ellipsesCollide ? RED : GREEN); + + DrawEllipseLines((int)ellipseACenter.x, (int)ellipseACenter.y, ellipseARx, ellipseARy, WHITE); + + DrawEllipseLines((int)ellipseBCenter.x, (int)ellipseBCenter.y, ellipseBRx, ellipseBRy, WHITE); + + DrawCircleV(ellipseACenter, 4, WHITE); + DrawCircleV(ellipseBCenter, 4, WHITE); + + if (ellipsesCollide) DrawText("ELLIPSES COLLIDE", screenWidth/2 - 120, 40, 28, RED); + else DrawText("NO COLLISION", screenWidth/2 - 80, 40, 28, DARKGRAY); + + DrawText(controlled == 0 ? "Controlling: A" : "Controlling: B", 20, screenHeight - 40, 20, YELLOW); + + if (mouseInA && controlled != 0) DrawText("Mouse inside ellipse A", 20, screenHeight - 70, 20, BLUE); + if (mouseInB && controlled != 1) DrawText("Mouse inside ellipse B", 20, screenHeight - 70, 20, GREEN); + + DrawText("Press [A] or [B] to switch control", 20, 20, 20, GRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + CloseWindow(); + + return 0; +} diff --git a/examples/shapes/shapes_ellipse_collision.png b/examples/shapes/shapes_ellipse_collision.png new file mode 100644 index 0000000000000000000000000000000000000000..30c66c164a3ad2ef0e4f17d7bd2d9b6a4ec638e0 GIT binary patch literal 16967 zcmeHOdt8&%|9=JxhjJNWxD5~%h*y-$Km{S(XhRJpr2nOPUx8 zP7#yLgi0w5L<3Wa37R09=_r$`d)tD*Q@?mkK;V&e9q_c{#>^@ zWP-%JC$A?(QRZWV0w+j<8JNo4%2sms6C`Vr<};&?VC%pS0Y+u|n~N8_!71 z@8%suOUH=hY*w-sj!&PYl z{kkI~;2SolNv?GHx?38G2n}C$O9LXIsvG)%ggb+BuQc{NTa% zu+S+}USE5x+B;)fqf}rg{-Cb24&7vPrmpnLG!~1b0%lhq4K_xh+ZbaU>Rql_kBc!< zL_~~vIQ(G!OP(pAtx5gAGx4#L)_d2Tb}0H@cJ-%v-tv7<+{2!Xs4HDsxYt3i@SFK= zKE@uI_ax6aMsVI(D2rN}mtI#jI9goVtM`6&eL#3m+gQ&v>V?NTkY1_PINxU}yv@$j8Bd~#s z16>!don=wvKXYeHGk0_1#Vx|mS_>x(KbmVf>4fou%k%PXC-6Q$Pv;EPhsdQH1;%nI zesurF&rj9$!GEv=9PaLjb6#J2O*6z?sVJ4rwe7^vwf1<&QP0{D>+`v;ECzoEW`mSv z^_*uYi(4&&8$7$SFm(L1S7`*@xD|Nm2@%NK~-PB#WD zGOY=*{7thmQhSAR5ES5Rq35#>$fEI-GGiBaj~EkyE(H~ zHU}*})~x{I0Ano5WivV}h}P`D;*`TmcomE*Umq)~Hf7WdZfItKV_&S~M!fir&0IsToChPub_C3L| zGu>YDxj2ThgIq(-(|uxnUu+D!+g(XVgL%F&#Px!>bRXftVSe$kV_tcF51Y<^qq#Do z1DGEn7;yzeo|-}(o?sGrX4jaeZ=cRtHuA!V+ELt7nFjY9Ez+8^(_(C@cT%Xm=|4zs zN2zT0AMhEVwqLKQ^PwLh@?|244O${#n!Ld>yINxw|I+1#{Nu8XhJh6TKT%9aPiCdB zUFkya$ZXiJpual&13D;}XwB?L4Lds$BssESOI>Bmc(Jdux+cM3p+7!&_k00UW@l8M zm9F8YCkD?gw_m5JD3_h31@?Ra$D!Lu@rL10m+J&$M3=q;qq-sN04;l6*J zdA_Gd(Y&a_19Ssr{3yZ(u?FI*RLCorC|#^W;QT;wl|hOc(hobcPyx?qBt$Bk&&W;} zzigyFQ6R4Rfo^On2fVHtoVpCG{k(goa}ZDyzE;!hL6_SOlA<0{DkwLwSzqyb#!gs2 z#3NIoGd08;`2n2k=5DZp7_Pux&6V4bReR~HsKwakCYPm}C2G>kWJh*M$Q5enq)EZ# z!1Uf!=8=0oN@T(6a#;~QAYcTNtx8kTAIoGy2Q%;tR@{h2_R@KrLBkvl4UaDTj!W!` z@q~B{eyKk*AT3q%k+HvP9ln3q)Ys9H5t(zeMzW{ zx08$5H})Wj?4O0z5BYH9cT!;~(6Y|n0?{JO3bV^Eus_-|H}0*d!qJ3Bx8N_Z`iGP_ z;L>QZ^_}^M;jE=!`c(V&YdG8w5ik!EQ0j#Vi2bk}ZU_V%^{vAM)N}fcJCR==`~^~- z6GhmW)ssL;;O7jw_`7@Ne91W2UbwHUdH$9rM{mE3iZ#lO31nM7xz~~)Aa)(x%eOad zJJx1qeo_xdlbYDKnkQ_^PA_jb9u`snMRJ`T)rBHIpefYdcgHKFYA8x=pM>p$9b-=VPi4*0IPP@Z`nN)H5FyD zm9X@lP&zVBD30;V+tMP55sAmI#}X+4Q-#pAaFh(-8zjP!h~)d(oFB7PnsCe7oo$*L zm1f<0nAUx8u1m8h*FkpWh+{cheM9lThlmSO_l~Z@DLd^ZWmV zB^Ho^QNr9Jh{*P$j8*B+G>IG#1&kOusZ9nCOb{sCsGMNa_vCU=5M&f3qwVMSFGN)S zKzsl~8}P?|MIh9hWwPzy1X@-VOE{i@@*#2hor-85Jv)8z*69YX-%!D3?X(0W%wnX_3DodONQv zS!rWJRsnLtDj)SyFtp`Lm;FG;XnsIOxC*qca>89TXi;wrJ@T^zKO^yb_#+gOw2HDj zL9e4#LTnE5jbzok0^oX0hK30lY0_|}%&QlY^R(Rw$cE$b{VE6JyTlS;!}?_S(H`0e z;2hZNC{#O=MlkdIdU?RzM^FBvVQ9H*5KegmJ|aBcqZjWQtm5BUS0W{lVxwdegFn*f8mudM;CzvVVs$WZ{#sskt`alWkrQ1q(TPXMi9B*5aZC7B zXRK0D13p3OmgtVvEtXue5?e?YA6=w^sTPF6MxZlrTpXq`U@Y0l@=cMnnVGL)q6-dZ zruv!ALNHUb794=JM`k~KMN}UEJ*w3@+s*-P=TMs}A)w)W4y0idC76mOpt8oiihEX} zLCQ71p_PrJ3$yK;yEy}mn`}Ae2iHRCSm2-@WdANp9zCXQ{I-}!51P))0<`u-y+M3I z2qu}OpyGcs-oe;%P8MPTfqc_4W$w%wK+B-BG9P>o$Nt2|F?dq*SeI_dz}1PZ3HY?L zmfB6^;;FZcFf2X6bX9L42wXefL4J-X>BsGQ)qzdVFA31H!b>d1vRzZtwkCTmo7~uN zZ;z&T>ZefSQFvv}#n(%PNG@`Tr0O`L6L>9OD3ETckofjfua53uXLW?GEJPP$JBanN zyGQR62mo`C5?t)%k-40(4Dh}mRK^UVL;bA*>$L3-@6QxegG-&}TfW%(jErUWIh(o~ ze$MqQlFsf;pvOghqXhO?ESE^7r-dHq8t|nH%^3+%=&NFDBQIbxXpSG*hyY&gi)>Vi zF8N9}R8s*sp`eNwFq=rTFa2HyMyt!|)PSeJ{>(h!O+zwu&ooSZ*PsB`tOZvc1Y1E| ze&P#p0p$vGbI;0Juxknc`~cI*%m!8i6)yQe1;nZd-pA>aZxgM*A&wUWIG+Iaiuhzm zQUJm6Apu~>uvdI`IN572?DZYl%ZIj?7J29C^Z--@fqw${AGB9I-V3>32*F(|VO7i+ zvGqBSBUJH_pZ{3T8)GiE*XEA7WPAS5t`eCjn<|&R0-KkBkt0obUq^sQnoUw06CIUI zAf+us6ZI+^l*KYiZ~@C$PNE2l24YvHP~tU#+zymsGKnCuQA)LZH)tUs+3NI4r&6|1 z6+;R{Trzdrr9iQu@c)HHI<;?_5_-pe_!5J;8Krz59mspSl;s$Ux z0u6*Ltt7;%#fF1FOh~n%>WU6IvcX=Ldu7)3fQV;UDK9t$*b1Ho#Yx5{&V=hEq`^0& zB}h^TFbB|E$|xQ7qMhvRx%vRSc_^lT~1pI)^7EI@5xJ zIJDOhSTzl>Zkh7dQ%-O!D(gK=ROXfe0}m3@Xw{3q!;{W5Z2N%H0c>ak%&GBSnUJ*V zDm4lr@hpwmfKd~m%8P90!v3ic>X(y?{^$@2N1JkkRe&)lCjhL@ z)Jrs{kI_)I289Q%OqDNR`Q|pUlMLw=C1J^Z`Z*2?*~&HFpXmx%#%+RJJdrctzvyW@`IJO&ruRoCe^MZ0>_Gkm8QtFSc%wv814> zkllo0?@NGU0}+KNyho1GNAfgdD8M(jl!5ATyx4so*$`}{pCmxZVaqZ(A zuoYX4r0P0|9C--n0@S8J*#eS{-~&#Ol5CoimixP&IrY$MgFqNSb7$ZnzgQ5(JiJUjY+R z{WGHhC8Ef_8~ksA4TqnVZSU7;pP}hvfYeDq4ph){f0}L!$P40nC^cuCYkX^8#XZ^U zdh-QK2mcz{5%2DXNf_SWa}J(`;smpyo312rsx4l>9qzme3zvm7$=xeEFQEHYY#PSRAi> zeNwr-h00PqaX-(MW>r9iH$kazfQsp?>=B_F+x=?$btRjRihb=ml<`blaD+DqJYk-l z(IX#cb=F!a461j%ofiF2ZxZnIh+GYUVv8=8X{=A6lOXRR-HKNx|=Qg)(a+ho1&I z0{QYU7-@Uz{igW39C+eedz^D>za9zTsgPLaN;ok!ncAxuahRJ}a&Z(l>lEkIa)Xsn zPe88bI$D`RjVf?SI(9-`z*X0@#|0R%r$Gdm?2nh>J8~chbZt-{UwQy6a883db}88I zJeFIU_!gaLy2!yrRt~|Oj_tlFI~@_jqU)2+U*PW);NPI3=JGdsD!S~sTN*Gw{;h4D z{{<2t?=JS>oi)%Eo>8*s()Z0v^Ve{;@zPE7ct@E65P;yObStoSGY1l|1$Vj`Uj@1R5dD@mrEZzAG1Rq>+Ty{@aEQYdN zGv}hFk3kw52o)nqq+qjFwW)=GnSf0F4Lk|m2L2yNo0c)sDbrc!-=7}Cf$0BM9}y7j zn|Z%*pg!P`Rt1=Pnoo@@%`P0xOT#)}3a%Nosk&`aw-=^5mT;wn%7^^5$+o8hPjfI`TZ%%S^)g33cEodPU`ShCu`Jv}#wm-Pjl z{~*7im@{H~hRf|7HsmRlk}61+l=&p!d1MfR(OkjvD`o$3=)DFZzg2=@wdFO)LFE3K z{-6t2NVs?AS#w~|w&PAvVgx<~N<$tFC<%TtQ(%w;(>S0jW&Aa_7%~E~f$3?vc_lEw z2PG*yv;$>8G?euxvit7nc+p`7XkOnk<_6zNf-Lmm3T197$h!td@241a6fjWI_8P;V zq=HckajHkYW`h?h>i|nziN8kESq5CBM;(7b!K9>!^S~I2(1@iMkiVq{VqXF?!0idK z;Zr9C=xmuU=1W+>mIO!j*ljR0SoAbfa0uVFm;ji~pN`U;P>pqrc>Sw>ppeij$->(> zlFY?V7d~_fDLR?m5?qLkW<)>@0cx#=B~LoX4Mg$WIIoK)1_x=hi%|qf8;W>jG*(U$ z+(z6#=}HD&u>TU6!Asm=Ry72p&~<9YT^qSJebLQBcH(0f8=c|~ zC)DhJk&OnDVw&SXKyO454oU-vX2nJs>XZJGT~Nd!8x2Hm08vCXdY#mvaHBvs*+ds` z7rgFxeYg>Q4ogbv+dZ98(cxWf(Sb38B=Vor_cl1Mlk$kD7_2@n7N{?Sv=G0Gx+-84 zv>_Ea;2EmkF<~MIil9|x*!DX2WjcULXDD%m;ukb*Rx_bi3nlT~kB|pqEFjiH8Y>;| zj*{fgaZCUde^52Q&lS)DD4AR0qpy$#Z z6$s_^@(FIJvi=gD^Pyl$2hBN)^w)OA1?nhhE5c#ZNy9LWI9v4#I9nBTGz%P^hSVb_ z+4RBtSCjrr1nIXUaCSuVUVJB~yGSOzR%2GqBpmR2ft*Rc9UIa`QyHj0hgNQNI|5P1 zaD{m5Y8iAVBSvBlS8AIkGhcv@p~eHs+FuF{A{JI!u&MeatV!) zaF=7Lc5EDhF+!UyOO-e_4h`{~B%v;cSg?gYfJY4$Uw*Us17rzeGX61?*vm(HdohM_ zr!000vlUHltjBSluGxbcBH9py0so)Cnv=8wHO5Qu8PM!;Ti)7o|Ea7{Z|v|CkV5tC z+xMKQa-zA!DXAx)y1qoNWGuWRHipgvh8B~_1dnNR)Y)WA%~}|~0j8Fe(WC~3#*`2Y z!kChd;0Az6@8s_Wa>!!aQxSD?;fGXkJWR;FTFp zh}TXG(Wc*3=8P~2^GafU{9;yq731FJhMgbEw*zSBy(TWR0m(k_;mi1)HQb5b4hKi&EU4PSfJV3iyI}k+1YtVfgg?i24O94xLH(=eL$<-0UAN{D-)}u$lSc z>ZDa$oSjxYc|2}Y$f|=MO?yy(ug|c>s=@wY>wcA{-PRoGGW3`a01Q3R4K(D|V>o&O zAxd*T4o;5d1=){s*d03~J7#vO`9sa4ey(42uvGj{01SkZanBmek#h6)i5=VrED|$w zGeYmXt=N9UcHm;R?X89nMKb#dN$-7eQpPpNv~?CXngj^%J*&(SX7Wzh<=XM`Sy#42 zT-TH)Rv+rSqbTY0{9SL3T>I^B$(1KhhSZ$!hy81I@(eTTm z_XPPct;*vE+#D39_T;M@yQq!Ad>>@>w81?+_TeXlLGpzG0Uw%(ZyRx!4N4G96OZ3! zh*M-CN>|OwwdtzP&C?e`hFUq>l6A1aws7mq{QCme8IdbP7hf)#m-N=d`KtI8tlfj= z$9c~xtk#Fa`fXrp4ZD|TrCjYlmAay!K98OvuF{9PG%o<-2QWW{L{A$(=%h=WLp`EC z8Su5{5Ldmk%QL0g_V-A`SM}O}Pz8!Z*H+JIzIIo0y33@qeHvIB717y6(wgV}+~&nI yO?^; Date: Sat, 18 Apr 2026 18:53:03 +0200 Subject: [PATCH 104/185] Update rcore_drm.c --- src/platforms/rcore_drm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index 708a78004..98c35f7e8 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -1426,7 +1426,7 @@ int InitPlatform(void) if (eglGetPlatformDisplayEXT != NULL) platform.device = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR, platform.gbmDevice, NULL); } - // In case extension not found or display could not be retrieved, try useing legacy version + // In case extension not found or display could not be retrieved, try using legacy version if (platform.device == EGL_NO_DISPLAY) platform.device = eglGetDisplay((EGLNativeDisplayType)platform.gbmDevice); #endif if (platform.device == EGL_NO_DISPLAY) From 9060ac7c95c371bdae7fbfafd2b54dd485c32832 Mon Sep 17 00:00:00 2001 From: Itwerntme <72857681+Itwernme@users.noreply.github.com> Date: Sun, 19 Apr 2026 12:50:15 +0100 Subject: [PATCH 105/185] Mouse delta calculation with scaling (#5779) Added scaling from SetMouseScale to mouse GetMouseDelta --- src/rcore.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index b36d9f825..d99919b62 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -4125,8 +4125,8 @@ Vector2 GetMouseDelta(void) { 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; + delta.x = (CORE.Input.Mouse.currentPosition.x - CORE.Input.Mouse.previousPosition.x)*CORE.Input.Mouse.scale.x; + delta.y = (CORE.Input.Mouse.currentPosition.y - CORE.Input.Mouse.previousPosition.y)*CORE.Input.Mouse.scale.y; return delta; } From 90e9145978d9dfffae19e60d819080d171b16450 Mon Sep 17 00:00:00 2001 From: Maicon Santana Date: Sun, 19 Apr 2026 12:51:52 +0100 Subject: [PATCH 106/185] Making it similar to CheckCollisionSpheres to remove pow function (#5776) --- src/rmodels.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 012bf24c3..62b8a51e5 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -4131,18 +4131,15 @@ bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius) { bool collision = false; - float dmin = 0; + Vector3 closestPoint = { + Clamp(center.x, box.min.x, box.max.x), + Clamp(center.y, box.min.y, box.max.y), + Clamp(center.z, box.min.z, box.max.z) + }; - if (center.x < box.min.x) dmin += powf(center.x - box.min.x, 2); - else if (center.x > box.max.x) dmin += powf(center.x - box.max.x, 2); + float distanceSquared = Vector3DistanceSqr(center, closestPoint); - if (center.y < box.min.y) dmin += powf(center.y - box.min.y, 2); - else if (center.y > box.max.y) dmin += powf(center.y - box.max.y, 2); - - if (center.z < box.min.z) dmin += powf(center.z - box.min.z, 2); - else if (center.z > box.max.z) dmin += powf(center.z - box.max.z, 2); - - if (dmin <= (radius*radius)) collision = true; + collision = distanceSquared <= (radius * radius); return collision; } From cc752037b9bcf7bebc141830f3f94bea16e244b9 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 19 Apr 2026 13:54:39 +0200 Subject: [PATCH 107/185] Update rmodels.c --- src/rmodels.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 62b8a51e5..6d3169ec0 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -4105,7 +4105,7 @@ bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, floa // Check for distances squared to avoid sqrtf() float radSum = radius1 + radius2; - if (Vector3DistanceSqr(center1, center2) <= radSum*radSum) collision = true; + if (Vector3DistanceSqr(center1, center2) <= (radSum*radSum)) collision = true; return collision; } @@ -4137,9 +4137,7 @@ bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius) Clamp(center.z, box.min.z, box.max.z) }; - float distanceSquared = Vector3DistanceSqr(center, closestPoint); - - collision = distanceSquared <= (radius * radius); + if (Vector3DistanceSqr(center, closestPoint) <= (radius*radius)) collision = true; return collision; } From a32b53f4d633d54fcc0a3ba825cdfc850af83f99 Mon Sep 17 00:00:00 2001 From: HaxSam Date: Sun, 19 Apr 2026 13:57:58 +0200 Subject: [PATCH 108/185] [build.zig] Refactor (#5764) * Add better structure for build.zig Temporarily disabled the tests * Cleanup build.zig a bit * Fixed zemscripten and cleanup other platforms * Make opengl_version selection more restritive * Add traslateC to build; Renable examples * Add raygui build to build.zig * Deny glfw from android target * Fix android platform includes * Add Zig project example * Add Zig project mention to README * Set right name for web build in zig example * Cleanup last parts of build.zig * Add linking method for build.zig * Fix lshcore link for glfw and rgfw build.zig * Fix weird sdl linkage build.zig * Add zig example to zig project * Fix win32, mac build bugs in build.zig * Rename argument lshcore to shcore build.zig --- build.zig | 860 +++++++++++++++---------- build.zig.zon | 5 + projects/README.md | 1 + projects/Zig/README.md | 84 +++ projects/Zig/build.zig | 87 +++ projects/Zig/build.zig.zon | 23 + projects/Zig/src/core_basic_window.c | 83 +++ projects/Zig/src/core_basic_window.zig | 73 +++ 8 files changed, 858 insertions(+), 358 deletions(-) create mode 100644 projects/Zig/README.md create mode 100644 projects/Zig/build.zig create mode 100644 projects/Zig/build.zig.zon create mode 100644 projects/Zig/src/core_basic_window.c create mode 100644 projects/Zig/src/core_basic_window.zig diff --git a/build.zig b/build.zig index 2dc6258af..eb1eb5cc6 100644 --- a/build.zig +++ b/build.zig @@ -1,14 +1,11 @@ const std = @import("std"); const builtin = @import("builtin"); -const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str; -const emccOutputFile = "index.html"; - pub const emsdk = struct { const zemscripten = @import("zemscripten"); - pub fn shell(b: *std.Build) std.Build.LazyPath { - return b.dependency("raylib", .{}).path("src/shell.html"); + pub fn shell(raylib_dep: *std.Build.Dependency) std.Build.LazyPath { + return raylib_dep.path("src/shell.html"); } pub const FlagsOptions = struct { @@ -30,7 +27,10 @@ pub const emsdk = struct { pub const SettingsOptions = struct { optimize: std.builtin.OptimizeMode, - es3: bool = true, + es3: bool = false, + glfw3: bool = true, + memory_growth: bool = false, + total_memory: u32 = 134217728, emsdk_allocator: zemscripten.EmsdkAllocator = .emmalloc, }; @@ -40,10 +40,24 @@ pub const emsdk = struct { .emsdk_allocator = options.emsdk_allocator, }); - if (options.es3) + if (options.es3) { emcc_settings.put("FULL_ES3", "1") catch unreachable; - emcc_settings.put("USE_GLFW", "3") catch unreachable; + emcc_settings.put("MIN_WEBGL_VERSION", "2") catch unreachable; + emcc_settings.put("MAX_WEBGL_VERSION", "2") catch unreachable; + } + if (options.glfw3) { + emcc_settings.put("USE_GLFW", "3") catch unreachable; + } + + const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch unreachable; + emcc_settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch unreachable; + emcc_settings.put("TOTAL_MEMORY", total_memory) catch unreachable; + emcc_settings.put("FORCE_FILESYSTEM", "1") catch unreachable; + emcc_settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch unreachable; + + if (options.memory_growth) + emcc_settings.put("ALLOW_MEMORY_GROWTH", "1") catch unreachable; return emcc_settings; } @@ -70,45 +84,96 @@ pub const emsdk = struct { } }; -fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void { - switch (platform) { - .glfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_GLFW", ""), - .rgfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_RGFW", ""), - .sdl => raylib.root_module.addCMacro("PLATFORM_DESKTOP_SDL", ""), - .android => raylib.root_module.addCMacro("PLATFORM_ANDROID", ""), - else => {}, +pub fn linkWindows(mod: *std.Build.Module, opengl: bool, comptime shcore: bool) void { + if (opengl) mod.linkSystemLibrary("opengl32", .{}); + mod.linkSystemLibrary("winmm", .{}); + mod.linkSystemLibrary("gdi32", .{}); + if (shcore) mod.linkSystemLibrary("shcore", .{}); +} + +fn findWaylandScanner(b: *std.Build) void { + _ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch { + std.log.err( + \\ `wayland-scanner` may not be installed on the system. + \\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend` + , .{}); + @panic("`wayland-scanner` not found"); + }; +} + +pub fn linkLinux(mod: *std.Build.Module, comptime display_backend: LinuxDisplayBackend) void { + if (display_backend == .None) { + mod.linkSystemLibrary("GL", .{}); + } + + if (display_backend == .X11) { + mod.linkSystemLibrary("X11", .{}); + mod.linkSystemLibrary("Xrandr", .{}); + mod.linkSystemLibrary("Xinerama", .{}); + mod.linkSystemLibrary("Xi", .{}); + mod.linkSystemLibrary("Xcursor", .{}); + } + + if (display_backend == .Wayland) { + mod.linkSystemLibrary("wayland-client", .{}); + mod.linkSystemLibrary("wayland-cursor", .{}); + mod.linkSystemLibrary("wayland-egl", .{}); + mod.linkSystemLibrary("xkbcommon", .{}); } } +pub fn linkBSD(_: *std.Build, mod: *std.Build.Module) void { + mod.linkSystemLibrary("GL", .{}); +} + +pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) void { + // Include xcode_frameworks for cross compilation + if (b.lazyDependency("xcode_frameworks", .{})) |dep| { + mod.addSystemFrameworkPath(dep.path("Frameworks")); + mod.addSystemIncludePath(dep.path("include")); + mod.addLibraryPath(dep.path("lib")); + } + + mod.linkFramework("Foundation", .{}); + mod.linkFramework("CoreServices", .{}); + mod.linkFramework("CoreGraphics", .{}); + mod.linkFramework("AppKit", .{}); + mod.linkFramework("IOKit", .{}); +} + fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { + const raylib_mod = b.createModule(.{ + .optimize = optimize, + .target = target, + .link_libc = true, + }); + const raylib = b.addLibrary(.{ .name = "raylib", .linkage = options.linkage, - .root_module = b.createModule(.{ - .optimize = optimize, - .target = target, - .link_libc = true, - }), + .root_module = raylib_mod, }); - raylib.root_module.addCMacro("_GNU_SOURCE", ""); - raylib.root_module.addCMacro("GL_SILENCE_DEPRECATION", "199309L"); + raylib_mod.addCMacro("_GNU_SOURCE", ""); + raylib_mod.addCMacro("GL_SILENCE_DEPRECATION", "199309L"); - var raylib_flags_arr: std.ArrayList([]const u8) = .empty; - defer raylib_flags_arr.deinit(b.allocator); + var arena: std.heap.ArenaAllocator = .init(b.allocator); + defer arena.deinit(); - try raylib_flags_arr.append( - b.allocator, - "-std=gnu99", - ); + var raylib_flags_arr: std.array_list.Managed([]const u8) = .init(arena.allocator()); + var c_source_files: std.array_list.Managed([]const u8) = .init(arena.allocator()); + + try c_source_files.append("src/rcore.c"); + + if (target.result.os.tag == .emscripten) { + try raylib_flags_arr.append("-std=gnu99"); + } else { + try raylib_flags_arr.append("-std=c99"); + } if (options.linkage == .dynamic) { - try raylib_flags_arr.append( - b.allocator, - "-fPIC", - ); - - raylib.root_module.addCMacro("BUILD_LIBTYPE_SHARED", ""); + raylib_mod.pic = true; + raylib_mod.addCMacro("BUILD_LIBTYPE_SHARED", ""); } if (options.config.len > 0) { @@ -120,237 +185,290 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. // Apply config flags supplied by the user while (config_iter.next()) |config_flag| { - try raylib_flags_arr.append(b.allocator, config_flag); + try raylib_flags_arr.append(config_flag); } } - // No GLFW required on PLATFORM_DRM - if (options.platform != .drm) { - raylib.root_module.addIncludePath(b.path("src/external/glfw/include")); - } - - var c_source_files: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 2); - c_source_files.appendSliceAssumeCapacity(&.{"src/rcore.c"}); - + raylib_mod.addCMacro("SUPPORT_MODULE_RSHAPES", &.{@as(u8, @intFromBool(options.rshapes)) + 0x30}); if (options.rshapes) { - raylib.root_module.addCMacro("SUPPORT_MODULE_RSHAPES", "1"); - try c_source_files.append(b.allocator, "src/rshapes.c"); - } else { - raylib.root_module.addCMacro("SUPPORT_MODULE_RSHAPES", "0"); + try c_source_files.append("src/rshapes.c"); } - + raylib_mod.addCMacro("SUPPORT_MODULE_RTEXTURES", &.{@as(u8, @intFromBool(options.rtextures)) + 0x30}); if (options.rtextures) { - raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXTURES", "1"); - try c_source_files.append(b.allocator, "src/rtextures.c"); - } else { - raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXTURES", "0"); + try c_source_files.append("src/rtextures.c"); } - + raylib_mod.addCMacro("SUPPORT_MODULE_RTEXT", &.{@as(u8, @intFromBool(options.rtext)) + 0x30}); if (options.rtext) { - raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXT", "1"); - try c_source_files.append(b.allocator, "src/rtext.c"); - } else { - raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXT", "0"); + try c_source_files.append("src/rtext.c"); } - + raylib_mod.addCMacro("SUPPORT_MODULE_RMODELS", &.{@as(u8, @intFromBool(options.rmodels)) + 0x30}); if (options.rmodels) { - raylib.root_module.addCMacro("SUPPORT_MODULE_RMODELS", "1"); - try c_source_files.append(b.allocator, "src/rmodels.c"); - } else { - raylib.root_module.addCMacro("SUPPORT_MODULE_RMODELS", "0"); + try c_source_files.append("src/rmodels.c"); } - + raylib_mod.addCMacro("SUPPORT_MODULE_RAUDIO", &.{@as(u8, @intFromBool(options.raudio)) + 0x30}); if (options.raudio) { - raylib.root_module.addCMacro("SUPPORT_MODULE_RAUDIO", "1"); - try c_source_files.append(b.allocator, "src/raudio.c"); - } else { - raylib.root_module.addCMacro("SUPPORT_MODULE_RAUDIO", "0"); + try c_source_files.append("src/raudio.c"); } - if (options.opengl_version != .auto) { - raylib.root_module.addCMacro(options.opengl_version.toCMacroStr(), ""); - } - - raylib.root_module.addIncludePath(b.path("src/platforms")); - switch (target.result.os.tag) { - .windows => { - switch (options.platform) { - .glfw => try c_source_files.append(b.allocator, "src/rglfw.c"), - .rgfw, .sdl, .drm, .android => {}, + raylib_mod.addIncludePath(b.path("src/platforms")); + switch (options.platform) { + .glfw => { + var opengl_version: OpenglVersion = options.opengl_version; + if (opengl_version == .gl_soft) { + @panic("The opengl version is not supported by this platform"); } - raylib.root_module.linkSystemLibrary("winmm", .{}); - raylib.root_module.linkSystemLibrary("gdi32", .{}); - raylib.root_module.linkSystemLibrary("opengl32", .{}); + raylib_mod.addIncludePath(b.path("src/external/glfw/include")); - setDesktopPlatform(raylib, options.platform); - }, - .linux => { - if (options.platform == .drm) { - if (options.opengl_version == .auto) { - raylib.root_module.linkSystemLibrary("GLESv2", .{}); - raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", ""); + if (target.result.os.tag != .emscripten) { + if (opengl_version == .auto) { + opengl_version = OpenglVersion.gl_3_3; } - - if (options.opengl_version != .gl_soft) { - raylib.root_module.linkSystemLibrary("EGL", .{}); - raylib.root_module.linkSystemLibrary("gbm", .{}); - } - raylib.root_module.linkSystemLibrary("libdrm", .{ .use_pkg_config = .force }); - - raylib.root_module.addCMacro("PLATFORM_DRM", ""); - raylib.root_module.addCMacro("EGL_NO_X11", ""); - raylib.root_module.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", ""); - } else if (target.result.abi.isAndroid()) { - - //these are the only tag options per https://developer.android.com/ndk/guides/other_build_systems - const hostTuple = switch (builtin.target.os.tag) { - .linux => "linux-x86_64", - .windows => "windows-x86_64", - .macos => "darwin-x86_64", - else => @panic("unsupported host OS"), - }; - - const androidTriple = switch (target.result.cpu.arch) { - .x86 => "i686-linux-android", - .x86_64 => "x86_64-linux-android", - .arm => "arm-linux-androideabi", - .aarch64 => "aarch64-linux-android", - .riscv64 => "riscv64-linux-android", - else => error.InvalidAndroidTarget, - } catch @panic("invalid android target!"); - const androidNdkPathString: []const u8 = options.android_ndk; - if (androidNdkPathString.len < 1) @panic("no ndk path provided and ANDROID_NDK_HOME is not set"); - const androidApiLevel: []const u8 = options.android_api_version; - - const androidSysroot = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/toolchains/llvm/prebuilt/", hostTuple, "/sysroot" }); - const androidLibPath = try std.fs.path.join(b.allocator, &.{ androidSysroot, "/usr/lib/", androidTriple }); - const androidApiSpecificPath = try std.fs.path.join(b.allocator, &.{ androidLibPath, androidApiLevel }); - const androidIncludePath = try std.fs.path.join(b.allocator, &.{ androidSysroot, "/usr/include" }); - const androidArchIncludePath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, androidTriple }); - const androidAsmPath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, "/asm-generic" }); - const androidGluePath = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/sources/android/native_app_glue/" }); - - raylib.root_module.addLibraryPath(.{ .cwd_relative = androidLibPath }); - raylib.root_module.addLibraryPath(.{ .cwd_relative = androidApiSpecificPath }); - raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidIncludePath }); - raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidArchIncludePath }); - raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidAsmPath }); - raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidGluePath }); - - var libcData: std.ArrayList(u8) = .empty; - var aw: std.Io.Writer.Allocating = .fromArrayList(b.allocator, &libcData); - try (std.zig.LibCInstallation{ - .include_dir = androidIncludePath, - .sys_include_dir = androidIncludePath, - .crt_dir = androidApiSpecificPath, - }).render(&aw.writer); - const libcFile = b.addWriteFiles().add("android-libc.txt", try libcData.toOwnedSlice(b.allocator)); - raylib.setLibCFile(libcFile); - - if (options.opengl_version == .auto) { - raylib.root_module.linkSystemLibrary("GLESv2", .{}); - raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", ""); - } - raylib.root_module.linkSystemLibrary("EGL", .{}); - - setDesktopPlatform(raylib, .android); - } else { - switch (options.platform) { - .glfw => try c_source_files.append(b.allocator, "src/rglfw.c"), - .rgfw, .sdl, .drm, .android => {}, - } - - if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { - raylib.root_module.addCMacro("_GLFW_X11", ""); - raylib.root_module.linkSystemLibrary("GLX", .{}); - raylib.root_module.linkSystemLibrary("X11", .{}); - raylib.root_module.linkSystemLibrary("Xcursor", .{}); - raylib.root_module.linkSystemLibrary("Xext", .{}); - raylib.root_module.linkSystemLibrary("Xfixes", .{}); - raylib.root_module.linkSystemLibrary("Xi", .{}); - raylib.root_module.linkSystemLibrary("Xinerama", .{}); - raylib.root_module.linkSystemLibrary("Xrandr", .{}); - raylib.root_module.linkSystemLibrary("Xrender", .{}); - } - - if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) { - _ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch { - std.log.err( - \\ `wayland-scanner` may not be installed on the system. - \\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend` - , .{}); - @panic("`wayland-scanner` not found"); - }; - raylib.root_module.addCMacro("_GLFW_WAYLAND", ""); - raylib.root_module.linkSystemLibrary("EGL", .{}); - raylib.root_module.linkSystemLibrary("wayland-client", .{}); - raylib.root_module.linkSystemLibrary("xkbcommon", .{}); - waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol"); - waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol"); - waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol"); - waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol"); - waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol"); - waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol"); - waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol"); - waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol"); - waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol"); - } - setDesktopPlatform(raylib, options.platform); - } - }, - .freebsd, .openbsd, .netbsd, .dragonfly => { - try c_source_files.append(b.allocator, "src/rglfw.c"); - raylib.root_module.linkSystemLibrary("GL", .{}); - raylib.root_module.linkSystemLibrary("rt", .{}); - raylib.root_module.linkSystemLibrary("dl", .{}); - raylib.root_module.linkSystemLibrary("m", .{}); - raylib.root_module.linkSystemLibrary("X11", .{}); - raylib.root_module.linkSystemLibrary("Xrandr", .{}); - raylib.root_module.linkSystemLibrary("Xinerama", .{}); - raylib.root_module.linkSystemLibrary("Xi", .{}); - raylib.root_module.linkSystemLibrary("Xxf86vm", .{}); - raylib.root_module.linkSystemLibrary("Xcursor", .{}); - - setDesktopPlatform(raylib, options.platform); - }, - .macos => { - // Include xcode_frameworks for cross compilation - if (b.lazyDependency("xcode_frameworks", .{})) |dep| { - raylib.root_module.addSystemFrameworkPath(dep.path("Frameworks")); - raylib.root_module.addSystemIncludePath(dep.path("include")); - raylib.root_module.addLibraryPath(dep.path("lib")); + raylib_mod.addCMacro("PLATFORM_DESKTOP_GLFW", ""); + try c_source_files.append("src/rglfw.c"); } - // On macos rglfw.c include Objective-C files. - try raylib_flags_arr.append(b.allocator, "-ObjC"); - raylib.root_module.addCSourceFile(.{ - .file = b.path("src/rglfw.c"), - .flags = raylib_flags_arr.items, - }); - _ = raylib_flags_arr.pop(); - raylib.root_module.linkFramework("Foundation", .{}); - raylib.root_module.linkFramework("CoreServices", .{}); - raylib.root_module.linkFramework("CoreGraphics", .{}); - raylib.root_module.linkFramework("AppKit", .{}); - raylib.root_module.linkFramework("IOKit", .{}); + switch (target.result.os.tag) { + .windows => linkWindows(raylib_mod, true, false), + .linux => { + if (target.result.abi.isAndroid()) { + @panic("Target is not supported with this platform"); + } - setDesktopPlatform(raylib, options.platform); + linkLinux(raylib_mod, .None); + + if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { + raylib_mod.addCMacro("_GLFW_X11", ""); + linkLinux(raylib_mod, .X11); + } + + if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) { + findWaylandScanner(b); + + raylib_mod.addCMacro("_GLFW_WAYLAND", ""); + linkLinux(raylib_mod, .Wayland); + try waylandGenerate(b, raylib, "src/external/glfw/deps/wayland/", false); + } + }, + .freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod), + .macos => { + // On macos rglfw.c include Objective-C files. + _ = c_source_files.pop(); + try raylib_flags_arr.append("-ObjC"); + raylib_mod.addCSourceFile(.{ + .file = b.path("src/rglfw.c"), + .flags = raylib_flags_arr.items, + }); + _ = raylib_flags_arr.pop(); + + linkMacOS(b, raylib_mod); + }, + .emscripten => { + switch (opengl_version) { + .auto => opengl_version = OpenglVersion.gles_2, + .gles_2, .gles_3, .gl_soft => {}, + else => @panic("opengl version not supported"), + } + + raylib_mod.addCMacro("PLATFORM_WEB", ""); + + const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b); + raylib.step.dependOn(activate_emsdk_step); + }, + else => @panic("Target is not supported with this platform"), + } + raylib_mod.addCMacro(opengl_version.toCMacroStr(), ""); }, - .emscripten => { - const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b); - raylib.step.dependOn(activate_emsdk_step); - raylib.root_module.addCMacro("PLATFORM_WEB", ""); + .rgfw => { + var opengl_version: OpenglVersion = options.opengl_version; + + if (target.result.os.tag != .emscripten) { + if (opengl_version == .auto) { + opengl_version = OpenglVersion.gl_3_3; + } + raylib_mod.addCMacro("PLATFORM_DESKTOP_RGFW", ""); + } + + switch (target.result.os.tag) { + .windows => linkWindows(raylib_mod, true, false), + .linux => { + if (target.result.abi.isAndroid()) { + @panic("Target is not supported with this platform"); + } + + linkLinux(raylib_mod, .None); + + if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { + raylib_mod.addCMacro("RGFW_X11", ""); + raylib_mod.addCMacro("RGFW_UNIX", ""); + + linkLinux(raylib_mod, .X11); + } + + if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) { + findWaylandScanner(b); + + if (options.linux_display_backend != .Both) { + raylib_mod.addCMacro("RGFW_NO_X11", ""); + } + + raylib_mod.addCMacro("RGFW_WAYLAND", ""); + raylib_mod.addCMacro("EGLAPIENTRY", ""); + + linkLinux(raylib_mod, .Wayland); + + try waylandGenerate(b, raylib, "src/external/RGFW/deps/wayland/", true); + } + }, + .freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod), + .macos => linkMacOS(b, raylib_mod), + .emscripten => { + switch (opengl_version) { + .auto => opengl_version = OpenglVersion.gles_2, + .gles_2, .gles_3, .gl_soft => {}, + else => @panic("opengl version not supported"), + } + + raylib_mod.addCMacro("PLATFORM_WEB_RGFW", ""); + const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b); + raylib.step.dependOn(activate_emsdk_step); + }, + else => @panic("Target is not supported with this platform"), + } + + raylib_mod.addCMacro(opengl_version.toCMacroStr(), ""); + }, + .sdl, .sdl2, .sdl3 => { if (options.opengl_version == .auto) { - raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES3", ""); + raylib_mod.addCMacro(OpenglVersion.gl_3_3.toCMacroStr(), ""); + } else { + raylib_mod.addCMacro(options.opengl_version.toCMacroStr(), ""); + } + + raylib_mod.addCMacro("PLATFORM_DESKTOP_SDL", ""); + + if (options.platform == .sdl2) { + raylib_mod.addCMacro("USING_SDL2_PACKAGE", ""); + } + if (options.platform == .sdl3) { + raylib_mod.addCMacro("USING_SDL3_PACKAGE", ""); } }, - else => { - @panic("Unsupported OS"); + .memory => { + if (options.opengl_version != .auto and options.opengl_version != .gl_soft) { + @panic("The opengl version is not supported by this platform"); + } + raylib_mod.addCMacro(OpenglVersion.gl_soft.toCMacroStr(), ""); + raylib_mod.addCMacro("PLATFORM_MEMORY", ""); + }, + .win32 => { + if (target.result.os.tag != .windows) { + @panic("Target is not supported with this platform"); + } + + if (options.opengl_version == .auto) { + raylib_mod.addCMacro(OpenglVersion.gl_3_3.toCMacroStr(), ""); + } else { + raylib_mod.addCMacro(options.opengl_version.toCMacroStr(), ""); + } + + raylib_mod.addCMacro("PLATFORM_DESKTOP_WIN32", ""); + + linkWindows(raylib_mod, options.opengl_version != .gl_soft, true); + }, + .drm => { + if (target.result.os.tag != .linux) { + @panic("Target is not supported with this platform"); + } + + raylib_mod.addCMacro("PLATFORM_DRM", ""); + raylib_mod.addCMacro("EGL_NO_X11", ""); + raylib_mod.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", ""); + + try raylib_flags_arr.append("-Werror=implicit-function-declaration"); + + raylib_mod.linkSystemLibrary("libdrm", .{ .use_pkg_config = .force }); + raylib_mod.linkSystemLibrary("drm", .{}); + raylib_mod.linkSystemLibrary("gbm", .{}); + + switch (options.opengl_version) { + .auto, .gles_2 => { + raylib_mod.addCMacro(OpenglVersion.gles_2.toCMacroStr(), ""); + raylib_mod.linkSystemLibrary("GLESv2", .{}); + raylib_mod.linkSystemLibrary("EGL", .{}); + }, + .gl_soft => {}, + else => @panic("The opengl version is not supported by this platform"), + } + }, + .android => { + if (!target.result.abi.isAndroid()) { + @panic("Target is not supported with this platform"); + } + + raylib_mod.addCMacro("PLATFORM_ANDROID", ""); + + raylib_mod.linkSystemLibrary("EGL", .{}); + switch (options.opengl_version) { + .auto, .gles_2 => { + raylib_mod.addCMacro(OpenglVersion.gles_2.toCMacroStr(), ""); + raylib_mod.linkSystemLibrary("GLESv2", .{}); + }, + else => @panic("The opengl version is not supported by this platform"), + } + + //these are the only tag options per https://developer.android.com/ndk/guides/other_build_systems + const hostTuple = switch (builtin.target.os.tag) { + .linux => "linux-x86_64", + .windows => "windows-x86_64", + .macos => "darwin-x86_64", + else => @panic("unsupported host OS"), + }; + + const androidTriple = switch (target.result.cpu.arch) { + .x86 => "i686-linux-android", + .x86_64 => "x86_64-linux-android", + .arm => "arm-linux-androideabi", + .aarch64 => "aarch64-linux-android", + .riscv64 => "riscv64-linux-android", + else => error.InvalidAndroidTarget, + } catch @panic("invalid android target!"); + const androidNdkPathString: []const u8 = options.android_ndk; + if (androidNdkPathString.len < 1) @panic("no ndk path provided and ANDROID_NDK_HOME is not set"); + const androidApiLevel: []const u8 = options.android_api_version; + + const androidSysroot = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/toolchains/llvm/prebuilt/", hostTuple, "/sysroot" }); + const androidLibPath = try std.fs.path.join(b.allocator, &.{ androidSysroot, "/usr/lib/", androidTriple }); + const androidApiSpecificPath = try std.fs.path.join(b.allocator, &.{ androidLibPath, androidApiLevel }); + const androidIncludePath = try std.fs.path.join(b.allocator, &.{ androidSysroot, "/usr/include" }); + const androidArchIncludePath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, androidTriple }); + const androidAsmPath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, "/asm-generic" }); + const androidGluePath = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/sources/android/native_app_glue/" }); + + raylib_mod.addLibraryPath(.{ .cwd_relative = androidLibPath }); + raylib_mod.addLibraryPath(.{ .cwd_relative = androidApiSpecificPath }); + raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidIncludePath }); + raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidArchIncludePath }); + raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidAsmPath }); + raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidGluePath }); + + const libc_data = try std.fmt.allocPrint(b.allocator, + \\include_dir={0s}/sysroot/usr/include + \\sys_include_dir={0s}/sysroot/usr/include/aarch64-linux-android + \\crt_dir={0s}/sysroot/usr/lib/aarch64-linux-android/24 + \\static_lib_dir={0s}/sysroot/usr/lib/aarch64-linux-android/24 + \\msvc_lib_dir= + \\kernel32_lib_dir= + \\gcc_dir= + \\ + , .{androidNdkPathString}); + const write_step = b.addWriteFiles(); + const libcFile = write_step.add("android-libc.txt", libc_data); + raylib.setLibCFile(libcFile); }, } - raylib.root_module.addCSourceFiles(.{ + raylib_mod.addCSourceFiles(.{ .files = c_source_files.items, .flags = raylib_flags_arr.items, }); @@ -358,17 +476,33 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. return raylib; } -pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency, options: Options) void { - const raylib_dep = b.dependencyFromBuildZig(@This(), options); - var gen_step = b.addWriteFiles(); - raylib.step.dependOn(&gen_step.step); +fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) void { + if (b.lazyDependency("raygui", .{ + .target = target, + .optimize = optimize, + .link_libc = true, + })) |raygui_dep| { + var gen_step = b.addWriteFiles(); + raylib.step.dependOn(&gen_step.step); - const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n"); - raylib.root_module.addCSourceFile(.{ .file = raygui_c_path }); - raylib.root_module.addIncludePath(raygui_dep.path("src")); - raylib.root_module.addIncludePath(raylib_dep.path("src")); + const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n"); + raylib.root_module.addCSourceFile(.{ .file = raygui_c_path }); + raylib.root_module.addIncludePath(raygui_dep.path("src")); + raylib.root_module.addIncludePath(b.path("src")); - raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h"); + raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h"); + + const c = b.addTranslateC(.{ + .root_source_file = raygui_dep.path("src/raygui.h"), + .target = target, + .optimize = optimize, + .link_libc = true, + }); + c.addIncludePath(b.path("src")); + const c_mod = c.createModule(); + c_mod.linkLibrary(raylib); + b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM"); + } } pub const Options = struct { @@ -377,6 +511,7 @@ pub const Options = struct { rshapes: bool = true, rtext: bool = true, rtextures: bool = true, + raygui: bool = false, platform: PlatformBackend = .glfw, linkage: std.builtin.LinkMode = .static, linux_display_backend: LinuxDisplayBackend = .X11, @@ -396,6 +531,7 @@ pub const Options = struct { .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, .rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures, .rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes, + .raygui = b.option(bool, "raygui", "Include raygui") orelse defaults.raygui, .linkage = b.option(std.builtin.LinkMode, "linkage", "Compile as shared or static library") orelse defaults.linkage, .linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend, .opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version, @@ -441,15 +577,38 @@ pub const PlatformBackend = enum { glfw, rgfw, sdl, + sdl2, + sdl3, + memory, + win32, drm, android, }; +fn translateCMod( + comptime header: []const u8, + b: *std.Build, + target: std.Build.ResolvedTarget, + optimize: std.builtin.OptimizeMode, + raylib: *std.Build.Step.Compile, +) void { + const c = b.addTranslateC(.{ + .root_source_file = b.path("src/" ++ header ++ ".h"), + .target = target, + .optimize = optimize, + .link_libc = true, + }); + const c_mod = c.createModule(); + c_mod.linkLibrary(raylib); + b.modules.put(b.graph.arena, header, c_mod) catch @panic("OOM"); +} + pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); + const options: Options = .getOptions(b); - const lib = try compileRaylib(b, target, optimize, Options.getOptions(b)); + const lib = try compileRaylib(b, target, optimize, options); lib.installHeader(b.path("src/raylib.h"), "raylib.h"); lib.installHeader(b.path("src/rcamera.h"), "rcamera.h"); @@ -458,15 +617,24 @@ pub fn build(b: *std.Build) !void { b.installArtifact(lib); - const examples = b.step("examples", "Build/Install all examples"); - examples.dependOn(try addExamples("audio", b, target, optimize, lib)); - examples.dependOn(try addExamples("core", b, target, optimize, lib)); - examples.dependOn(try addExamples("models", b, target, optimize, lib)); - examples.dependOn(try addExamples("others", b, target, optimize, lib)); - examples.dependOn(try addExamples("shaders", b, target, optimize, lib)); - examples.dependOn(try addExamples("shapes", b, target, optimize, lib)); - examples.dependOn(try addExamples("text", b, target, optimize, lib)); - examples.dependOn(try addExamples("textures", b, target, optimize, lib)); + translateCMod("raylib", b, target, optimize, lib); + translateCMod("rcamera", b, target, optimize, lib); + translateCMod("raymath", b, target, optimize, lib); + translateCMod("rlgl", b, target, optimize, lib); + + if (options.raygui) { + addRaygui(b, target, optimize, lib); + } + + const examples = b.step("examples", "build/install all examples"); + examples.dependOn(try addExamples("core", b, target, optimize, lib, options.platform)); + examples.dependOn(try addExamples("audio", b, target, optimize, lib, options.platform)); + examples.dependOn(try addExamples("models", b, target, optimize, lib, options.platform)); + examples.dependOn(try addExamples("shaders", b, target, optimize, lib, options.platform)); + examples.dependOn(try addExamples("shapes", b, target, optimize, lib, options.platform)); + examples.dependOn(try addExamples("text", b, target, optimize, lib, options.platform)); + examples.dependOn(try addExamples("textures", b, target, optimize, lib, options.platform)); + examples.dependOn(try addExamples("others", b, target, optimize, lib, options.platform)); } fn addExamples( @@ -475,6 +643,7 @@ fn addExamples( target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile, + platform: PlatformBackend, ) !*std.Build.Step { const all = b.step(module, "All " ++ module ++ " examples"); const module_subpath = b.pathJoin(&.{ "examples", module }); @@ -485,118 +654,88 @@ fn addExamples( var iter = dir.iterate(); while (try iter.next(b.graph.io)) |entry| { if (entry.kind != .file) continue; - const extension_idx = std.mem.lastIndexOf(u8, entry.name, ".c") orelse continue; - const name = entry.name[0..extension_idx]; - const filename = try std.fmt.allocPrint(b.allocator, "{s}.c", .{name}); - const path = b.pathJoin(&.{ module_subpath, filename }); - // zig's mingw headers do not include pthread.h - if (std.mem.eql(u8, "core_loading_thread", name) and target.result.os.tag == .windows) continue; + const filetype = std.fs.path.extension(entry.name); + if (!std.mem.eql(u8, filetype, ".c")) continue; + + const filename = std.fs.path.stem(entry.name); + const path = b.pathJoin(&.{ module_subpath, entry.name }); const exe_mod = b.createModule(.{ .target = target, .optimize = optimize, + .link_libc = true, }); - exe_mod.addCSourceFile(.{ .file = b.path(path), .flags = &.{} }); + exe_mod.addCSourceFile(.{ .file = b.path(path) }); exe_mod.linkLibrary(raylib); - const run_step = b.step(name, name); + if (platform == .sdl) { + exe_mod.linkSystemLibrary("SDL2", .{}); + exe_mod.linkSystemLibrary("SDL3", .{}); + } + if (platform == .sdl2) { + exe_mod.linkSystemLibrary("SDL2", .{}); + } + if (platform == .sdl3) { + exe_mod.linkSystemLibrary("SDL3", .{}); + } + + if (std.mem.eql(u8, filename, "rlgl_standalone")) { + if (platform != .glfw) continue; + exe_mod.addIncludePath(b.path("src")); + exe_mod.addIncludePath(b.path("src/external/glfw/include")); + } + if (std.mem.eql(u8, filename, "raylib_opengl_interop")) { + if (platform == .drm) continue; + if (target.result.os.tag == .macos) continue; + exe_mod.addIncludePath(b.path("src/external")); + } + + const run_step = b.step(filename, filename); + + // web exports are completely separate + if (target.query.os_tag == .emscripten) { + exe_mod.addCMacro("PLATFORM_WEB", ""); - if (target.result.os.tag == .emscripten) { const wasm = b.addLibrary(.{ - .name = name, - .linkage = .static, + .name = filename, .root_module = exe_mod, }); - if (std.mem.eql(u8, name, "rlgl_standalone")) { - exe_mod.addIncludePath(b.path("src")); - exe_mod.addIncludePath(b.path("src/external/glfw/include")); - } - if (std.mem.eql(u8, name, "raylib_opengl_interop")) { - exe_mod.addIncludePath(b.path("src/external")); - } - + const install_dir: std.Build.InstallDir = .{ .custom = b.fmt("web/{s}/{s}", .{ module, filename }) }; const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize }); const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize }); - const install_dir: std.Build.InstallDir = .{ .custom = "htmlout" }; const emcc_step = emsdk.emccStep(b, raylib, wasm, .{ .optimize = optimize, .flags = emcc_flags, .settings = emcc_settings, .shell_file_path = b.path("src/shell.html"), - .embed_paths = &.{ - .{ - .src_path = b.pathJoin(&.{ module_subpath, "resources" }), - .virtual_path = "resources", - }, - }, .install_dir = install_dir, }); + b.getInstallStep().dependOn(emcc_step); const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name}); const emrun_step = emsdk.emrunStep( b, b.getInstallPath(install_dir, html_filename), - &.{"--no_browser"}, + &.{}, ); - emrun_step.dependOn(emcc_step); + emrun_step.dependOn(emcc_step); run_step.dependOn(emrun_step); all.dependOn(emcc_step); } else { - // special examples that test using these external dependencies directly - // alongside raylib - if (std.mem.eql(u8, name, "rlgl_standalone")) { - exe_mod.addIncludePath(b.path("src")); - exe_mod.addIncludePath(b.path("src/external/glfw/include")); - if (!hasCSource(raylib.root_module, "rglfw.c")) { - exe_mod.addCSourceFile(.{ .file = b.path("src/rglfw.c"), .flags = &.{} }); - } - } - if (std.mem.eql(u8, name, "raylib_opengl_interop")) { - exe_mod.addIncludePath(b.path("src/external")); - } - - switch (target.result.os.tag) { - .windows => { - exe_mod.linkSystemLibrary("winmm", .{}); - exe_mod.linkSystemLibrary("gdi32", .{}); - exe_mod.linkSystemLibrary("opengl32", .{}); - - exe_mod.addCMacro("PLATFORM_DESKTOP", ""); - }, - .linux => { - exe_mod.linkSystemLibrary("GL", .{}); - exe_mod.linkSystemLibrary("rt", .{}); - exe_mod.linkSystemLibrary("dl", .{}); - exe_mod.linkSystemLibrary("m", .{}); - exe_mod.linkSystemLibrary("X11", .{}); - - exe_mod.addCMacro("PLATFORM_DESKTOP", ""); - }, - .macos => { - exe_mod.linkFramework("Foundation", .{}); - exe_mod.linkFramework("Cocoa", .{}); - exe_mod.linkFramework("OpenGL", .{}); - exe_mod.linkFramework("CoreAudio", .{}); - exe_mod.linkFramework("CoreVideo", .{}); - exe_mod.linkFramework("IOKit", .{}); - - exe_mod.addCMacro("PLATFORM_DESKTOP", ""); - }, - else => { - @panic("Unsupported OS"); - }, - } + exe_mod.addCMacro("PLATFORM_DESKTOP", ""); const exe = b.addExecutable(.{ - .name = name, + .name = filename, .root_module = exe_mod, + .use_lld = target.result.os.tag == .windows, }); + b.installArtifact(exe); - const install_cmd = b.addInstallArtifact(exe, .{}); + const install_cmd = b.addInstallArtifact(exe, .{ .dest_sub_path = b.fmt("{s}/{s}", .{ module, filename }) }); const run_cmd = b.addRunArtifact(exe); run_cmd.cwd = b.path(module_subpath); @@ -606,41 +745,46 @@ fn addExamples( all.dependOn(&install_cmd.step); } } - return all; } fn waylandGenerate( b: *std.Build, raylib: *std.Build.Step.Compile, - comptime protocol: []const u8, - comptime basename: []const u8, -) void { - const waylandDir = "src/external/glfw/deps/wayland"; - const protocolDir = b.pathJoin(&.{ waylandDir, protocol }); - const clientHeader = basename ++ ".h"; - const privateCode = basename ++ "-code.h"; + comptime waylandDir: []const u8, + comptime source: bool, +) !void { + const dir = try b.build_root.handle.openDir(b.graph.io, waylandDir, .{ .iterate = true }); + defer dir.close(b.graph.io); - const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" }); - client_step.addFileArg(b.path(protocolDir)); - raylib.root_module.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname()); + var iter = dir.iterate(); + while (try iter.next(b.graph.io)) |entry| { + if (entry.kind != .file) continue; + const protocolDir = b.pathJoin(&.{ waylandDir, entry.name }); - const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" }); - private_step.addFileArg(b.path(protocolDir)); - raylib.root_module.addIncludePath(private_step.addOutputFileArg(privateCode).dirname()); + const filename = std.fs.path.stem(entry.name); - raylib.step.dependOn(&client_step.step); - raylib.step.dependOn(&private_step.step); -} - -fn hasCSource(module: *std.Build.Module, name: []const u8) bool { - for (module.link_objects.items) |o| switch (o) { - .c_source_file => |c| if (switch (c.file) { - .src_path => |s| std.ascii.endsWithIgnoreCase(s.sub_path, name), - .generated, .cwd_relative, .dependency => false, - }) return true, - .c_source_files => |s| for (s.files) |c| if (std.ascii.endsWithIgnoreCase(c, name)) return true, - else => {}, - }; - return false; + const clientHeader = b.fmt("{s}-client-protocol.h", .{filename}); + const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" }); + client_step.addFileArg(b.path(protocolDir)); + raylib.root_module.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname()); + raylib.step.dependOn(&client_step.step); + + if (comptime source) { + const privateCode = b.fmt("{s}-client-protocol-code.c", .{filename}); + const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" }); + private_step.addFileArg(b.path(protocolDir)); + raylib.root_module.addCSourceFile(.{ + .file = private_step.addOutputFileArg(privateCode), + .flags = &.{ "-std=c99", "-O2" }, + }); + raylib.step.dependOn(&private_step.step); + } else { + const privateCodeHeader = b.fmt("{s}-client-protocol-code.h", .{filename}); + const private_head_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" }); + private_head_step.addFileArg(b.path(protocolDir)); + raylib.root_module.addIncludePath(private_head_step.addOutputFileArg(privateCodeHeader).dirname()); + raylib.step.dependOn(&private_head_step.step); + } + } } diff --git a/build.zig.zon b/build.zig.zon index dd25fde73..07a1f7400 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -11,6 +11,11 @@ .hash = "N-V-__8AALShqgXkvqYU6f__FrA22SMWmi2TXCJjNTO1m8XJ", .lazy = true, }, + .raygui = .{ + .url = "git+https://github.com/raysan5/raygui#3b2855842ab578a034f827c38cf8f62c042fc983", + .hash = "N-V-__8AAHvybwBw1kyBGn0BW_s1RqIpycNjLf_XbE-fpLUF", + .lazy = true, + }, .emsdk = .{ .url = "git+https://github.com/emscripten-core/emsdk#4.0.9", .hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ", diff --git a/projects/README.md b/projects/README.md index af24f1547..2758cb86e 100644 --- a/projects/README.md +++ b/projects/README.md @@ -13,6 +13,7 @@ IDE | Platform(s) | Source | Example(s) [SublimeText](https://www.sublimetext.com/) | Windows, Linux, macOS | ✔️ | ✔️ [VS2019](https://www.visualstudio.com) | Windows | ✔️ | ✔️ [VSCode](https://code.visualstudio.com/) | Windows, macOS | ❌ | ✔️ +[Zig](https://ziglang.org) | Windows, Linux, macOS, Web | ✔️ | ✔️ scripts | Windows, Linux, macOS | ✔️ | ✔️ *New IDEs config files are welcome!* diff --git a/projects/Zig/README.md b/projects/Zig/README.md new file mode 100644 index 000000000..a7c24e093 --- /dev/null +++ b/projects/Zig/README.md @@ -0,0 +1,84 @@ +# Starting your raylib project with Zig (0.16.0) + +## How to compile and run it + +To compile the project: + +```sh +zig build +``` + +To run the project: + +```sh +zig build run +``` + +## Compile with different optimization + +To change from debug to release build you can do it with the `-Doptimze=` flag. + +``` +Debug +ReleaseSafe +ReleaseFast +ReleaseSmall +``` + +## Choose a different platform + +To compile with a different platform you can use the `-Dplatform=` flag. +Here all the options: + +``` +glfw +rgfw +sdl +sdl2 +sdl3 +memory +win32 +drm +android +``` + +In this example the platform `sdl` and `sdl2` are not supported + +Important for the android platform you also have to compile for the right target + +## Compile for a different target + +To compile for a different [target](https://ziglang.org/download/0.16.0/release-notes.html#Support-Table) you can use the `-Dtarget=` flag. +Not all targets are supported + +## Example: Compile for web and run it + +To compile for the web we use emscripten and you run it like that: + +```sh +zig build -Dtarget=wasm32-emscripten +``` + +To run it we do: + +```sh +zig build run -Dtarget=wasm32-emscripten +``` + +And to make a relase build we do: + +```sh +zig build -Dtarget=wasm32-emscripten -Doptimize=ReleaseFast +``` + +If we want to use rgfw for the web build we could do: + +```sh +zig build -Dplatform=rgfw -Dtarget=wasm32-emscripten -Doptimize=ReleaseFast +``` + +## Compiling the Zig code? Just add `-Dzig` and try out zig ;) + +## More Resources + +See [Zig Build System](https://ziglang.org/learn/build-system/) diff --git a/projects/Zig/build.zig b/projects/Zig/build.zig new file mode 100644 index 000000000..917e97b71 --- /dev/null +++ b/projects/Zig/build.zig @@ -0,0 +1,87 @@ +const std = @import("std"); +const rl = @import("raylib"); + +pub fn build(b: *std.Build) !void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + const platform = b.option(rl.PlatformBackend, "platform", "select the platform") orelse rl.PlatformBackend.glfw; + const zig = b.option(bool, "zig", "compile zig code") orelse false; + + const raylib_dep = b.dependency("raylib", .{ + .target = target, + .optimize = optimize, + .platform = platform, + }); + const raylib_artifact = raylib_dep.artifact("raylib"); + + if (platform == .sdl3) { + if (b.lazyDependency("sdl3", .{ .optimize = optimize, .target = target })) |dep| { + raylib_artifact.root_module.linkLibrary(dep.artifact("SDL3")); + } + } + + var exe_mod: *std.Build.Module = undefined; + + if (zig) { + exe_mod = b.createModule(.{ + .root_source_file = b.path("src/core_basic_window.zig"), + .target = target, + .optimize = optimize, + }); + exe_mod.addImport("raylib", raylib_dep.module("raylib")); + } else { + exe_mod = b.createModule(.{ + .target = target, + .optimize = optimize, + .link_libc = true, + }); + exe_mod.addCSourceFile(.{ .file = b.path("src/core_basic_window.c") }); + exe_mod.linkLibrary(raylib_artifact); + } + + const run_step = b.step("run", "Run the app"); + + // web exports are completely separate + if (target.query.os_tag == .emscripten) { + const emsdk = rl.emsdk; + const wasm = b.addLibrary(.{ + .name = "core_basic_window_web", + .root_module = exe_mod, + }); + + const install_dir: std.Build.InstallDir = .{ .custom = "web" }; + const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize }); + const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize }); + + const emcc_step = emsdk.emccStep(b, raylib_artifact, wasm, .{ + .optimize = optimize, + .flags = emcc_flags, + .settings = emcc_settings, + .shell_file_path = emsdk.shell(raylib_dep), + .install_dir = install_dir, + }); + b.getInstallStep().dependOn(emcc_step); + + const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name}); + const emrun_step = emsdk.emrunStep( + b, + b.getInstallPath(install_dir, html_filename), + &.{}, + ); + + emrun_step.dependOn(emcc_step); + run_step.dependOn(emrun_step); + } else { + const exe = b.addExecutable(.{ + .name = "core_basic_window", + .root_module = exe_mod, + .use_lld = target.result.os.tag == .windows, + }); + b.installArtifact(exe); + + const run_cmd = b.addRunArtifact(exe); + run_cmd.step.dependOn(b.getInstallStep()); + + run_step.dependOn(&run_cmd.step); + } +} diff --git a/projects/Zig/build.zig.zon b/projects/Zig/build.zig.zon new file mode 100644 index 000000000..77bf4291c --- /dev/null +++ b/projects/Zig/build.zig.zon @@ -0,0 +1,23 @@ +.{ + .name = .example, + .version = "0.0.1", + .minimum_zig_version = "0.16.0", + .paths = .{""}, + + .dependencies = .{ + .raylib = .{ + .path = "../../", + }, + .emsdk = .{ + .url = "git+https://github.com/emscripten-core/emsdk?ref=4.0.9#3bcf1dcd01f040f370e10fe673a092d9ed79ebb5", + .hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ", + }, + .sdl3 = .{ + .url = "git+https://codeberg.org/7Games/zig-sdl3?ref=master#6d418ef3ddae99098414a96a88bf5e5fdb41785e", + .hash = "sdl3-0.1.9-NmT1QwiEJwByePqkmArtppCHQn8Y7kiSWcncT_Mop8ie", + .lazy = true, + }, + }, + + .fingerprint = 0x6eec9b9f1a9d7aca, +} diff --git a/projects/Zig/src/core_basic_window.c b/projects/Zig/src/core_basic_window.c new file mode 100644 index 000000000..cb23a6f87 --- /dev/null +++ b/projects/Zig/src/core_basic_window.c @@ -0,0 +1,83 @@ +/******************************************************************************************* +* +* raylib [core] example - Basic window (adapted for HTML5 platform) +* +* This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP +* As you will notice, code structure is slightly different to the other examples... +* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning +* +* This example has been created using raylib 1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +int screenWidth = 800; +int screenHeight = 450; + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +void UpdateDrawFrame(void); // Update and Draw one frame + +//---------------------------------------------------------------------------------- +// Program main entry point +//---------------------------------------------------------------------------------- +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + UpdateDrawFrame(); + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- +void UpdateDrawFrame(void) +{ + // Update + //---------------------------------------------------------------------------------- + // TODO: Update your variables here + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- +} diff --git a/projects/Zig/src/core_basic_window.zig b/projects/Zig/src/core_basic_window.zig new file mode 100644 index 000000000..c26efc0d6 --- /dev/null +++ b/projects/Zig/src/core_basic_window.zig @@ -0,0 +1,73 @@ +//******************************************************************************************* +//* +//* raylib [core] example - Basic window (adapted for HTML5 platform) +//* +//* This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP +//* As you will notice, code structure is slightly different to the other examples... +//* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning +//* +//* This example has been created using raylib 6.0 (www.raylib.com) +//* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +//* +//* Copyright (c) 2015 Ramon Santamaria (@raysan5) +//* Rewrite in Zig by HaxSam (@haxsam) +//* +//******************************************************************************************* + +const rl = @import("raylib"); +const std = @import("std"); +const builtin = @import("builtin"); + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +const screenWidth: c_int = 800; +const screenHeight: c_int = 450; + +//---------------------------------------------------------------------------------- +// Program main entry point +//---------------------------------------------------------------------------------- +pub fn main() void { + // Initialization + //-------------------------------------------------------------------------------------- + rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); + + if (builtin.os.tag == .emscripten) { + std.os.emscripten.emscripten_set_main_loop(UpdateDrawFrame, 0, 1); + } else { + rl.SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!rl.WindowShouldClose()) // Detect window close button or ESC key + { + UpdateDrawFrame(); + } + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + rl.CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- +fn UpdateDrawFrame() callconv(.c) void { + // Update + //---------------------------------------------------------------------------------- + // TODO: Update your variables here + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + rl.BeginDrawing(); + + rl.ClearBackground(rl.RAYWHITE); + + rl.DrawText("Congrats! You created your first window!", 190, 200, 20, rl.LIGHTGRAY); + + rl.EndDrawing(); + //---------------------------------------------------------------------------------- +} From d87bf55607008253419ba92687ffcc0005a87aff Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 19 Apr 2026 20:03:29 +0200 Subject: [PATCH 109/185] Update CHANGELOG --- CHANGELOG | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index e4e06ce47..31ed2f74d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -115,6 +115,7 @@ Detailed changes: [rcore][GLFW] REVIEWED: `GetGamepadButtonPressed()`, return GAMEPAD_BUTTON_*_TRIGGER_2 if pressed (#4742) by @whaleymar [rcore][GLFW] REVIEWED: Update `mappings.h` using `GenerateMappings.cmake` by @sleeptightAnsiC [rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley +[rcore][RGFW] ADDED: Support for software rendering (#5773) by @CrackedPixel [rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX [rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc [rcore][RGFW] REVIEWED: Duplicate entries removed from `keyMappingRGFW` (#5242) by @iamahuman1395 @@ -326,6 +327,7 @@ Detailed changes: [rmodels] REVIEWED: `DrawSphereEx()`, normals support (#4926) by @karl-zylinski [rmodels] REVIEWED: `ExportMesh()`, improve OBJ vertex data precision and lower memory usage (#4496) by @mikeemm [rmodels] REVIEWED: `CheckCollisionSpheres()`, simplified using `Vector3DistanceSqr()` (#5695) by @Bigfoot71 +[rmodels] REVIEWED: `CheckCollisionBoxSphere()`, improved performance and consistency (#5776) by @maiconpintoabreu [raudio] REVIEWED: Fix a glitch at the end of a sound (#5578) by @mackron [raudio] REVIEWED: Improvements to device configuration (#5577) by @mackron [raudio] REVIEWED: Initialize sound alias properties as if it was a new sound (#5123) by @JeffM2501 @@ -410,11 +412,12 @@ Detailed changes: [build][CMake] REVIEWED: Set `libm` as public so it can be linked by consumer (#5193) by @brccabral [build][Cmake] REVIEWED: Expose PLATFORM_WEB_RGFW (#5579) by @crisserpl2 [build][Zig] ADDED: Android target to build by @lumenkeyes +[build][Zig] REDESIGNED: Complete refactor of build.zig to support Zig 0.16.0 (#5764) by @HaxSam [build][Zig] REVIEWED: Link EGL for Android by @lumenkeyes [build][Zig] REVIEWED: Approach to build for web with zig-build (#5157) by @haxsam [build][Zig] REVIEWED: Fix build accessing env vars (#5490) by @iisakki [build][Zig] REVIEWED: Fix emscripten building by @johnnymarler -[build][Zig] REVIWED: Move examples/build.zig into main build.zig by @johnnymarler +[build][Zig] REVIEWED: Move examples/build.zig into main build.zig by @johnnymarler [build][Zig] REVIEWED: Fix raygui inclusion in windows crosscompilation (#4489) by @kimierik [build][Zig] REVIEWED: Issue on emscripten run if the user has not installed emsdk by @emilhakimov415 [build][Zig] REVIEWED: Make X11 the default display backend instead of choosing at runtime (#5168) by @Not-Nik @@ -462,6 +465,7 @@ Detailed changes: [examples] ADDED: `shapes_rlgl_triangle` example (#5353) by @robinsaviary [examples] ADDED: `shapes_starfield` (#5255) by @themushroompirates [examples] ADDED: `shapes_triangle_strip` (#5240) by @Jopestpe +[examples] ADDED: `shapes_collision_ellipses` (#5722) by @Monjaris [examples] ADDED: `text_inline_styling` by @raysan5 [examples] ADDED: `text_strings_management` (#5379) by @davidbuzatto [examples] ADDED: `text_words_alignment` (#5254) by @themushroompirates From d6445b55d62d950911f86f3863e7713eae825838 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 19 Apr 2026 20:03:31 +0200 Subject: [PATCH 110/185] Update core_basic_window.c --- examples/core/core_basic_window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/core/core_basic_window.c b/examples/core/core_basic_window.c index 73d75683a..c1009fc76 100644 --- a/examples/core/core_basic_window.c +++ b/examples/core/core_basic_window.c @@ -22,7 +22,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) +* Copyright (c) 2013-2026 Ramon Santamaria (@raysan5) * ********************************************************************************************/ From a4680fc67734754138650138f11c54dc798ede56 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 19 Apr 2026 20:03:35 +0200 Subject: [PATCH 111/185] Update HISTORY.md --- HISTORY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index a6ff00468..1ef03e474 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -530,8 +530,8 @@ A new `raylib` release is finally ready and, again, this is the **biggest `rayli Some astonishing numbers for this release: - - **+320** closed issues (for a TOTAL of **+2140**!) - - **+1950** commits since previous RELEASE (for a TOTAL of **+9700**!) + - **+330** closed issues (for a TOTAL of **+2150**!) + - **+2000** commits since previous RELEASE (for a TOTAL of **+9760**!) - **+20** new functions ADDED to raylib API (for a TOTAL of **600**!) - **+50** new examples to learn from (for a TOTAL of **+210**!) - **+210** new contributors (for a TOTAL of **+850**!) From 7495a77a79b706d6d59cdafa7becc2403fb009b4 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 22 Apr 2026 13:41:15 +0200 Subject: [PATCH 112/185] Update CHANGELOG --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 31ed2f74d..eaf467294 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,7 +17,7 @@ KEY CHANGES: - New File System API - New Text Management API - New tool: [rexm] raylib examples manager - - Added +50 new examples to learn from + - Added +70 new examples to learn from Detailed changes: From 932558ca7a54a867f04db3fe4e237ebd887fb8cc Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 22 Apr 2026 13:41:27 +0200 Subject: [PATCH 113/185] Update HISTORY.md --- HISTORY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 1ef03e474..2d6a4b77d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -533,7 +533,7 @@ Some astonishing numbers for this release: - **+330** closed issues (for a TOTAL of **+2150**!) - **+2000** commits since previous RELEASE (for a TOTAL of **+9760**!) - **+20** new functions ADDED to raylib API (for a TOTAL of **600**!) - - **+50** new examples to learn from (for a TOTAL of **+210**!) + - **+70** new examples to learn from (for a TOTAL of **+215**!) - **+210** new contributors (for a TOTAL of **+850**!) Highlights for `raylib 6.0`: @@ -591,7 +591,7 @@ COMMANDS: update : Validate and update examples collection, generates report ``` - - **`NEW` +50 new examples**: Thanks to `rexm` and the simplification on examples management, this new raylib release includes +50 new examples to leearn from, most of them contributed by community. + - **`NEW` +70 new examples**: Thanks to `rexm` and the simplification on examples management, this new raylib release includes +70 new examples to learn from, most of them contributed by community. Multiple examples have also been renamed for consistency and all examples header and structure have been reviewed and unified. Make sure to check raylib [CHANGELOG](https://github.com/raysan5/raylib/blob/master/CHANGELOG) for a detailed list of changes! From dbc56a87da87d973a9c5baa4e7438a9d20121d28 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 23 Apr 2026 00:18:40 +0200 Subject: [PATCH 114/185] Update HISTORY.md --- HISTORY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 2d6a4b77d..a1b60a49c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -597,8 +597,8 @@ Make sure to check raylib [CHANGELOG](https://github.com/raysan5/raylib/blob/mas I want to **thank all the contributors (+850!**) that along the years have **greatly improved raylib** and pushed it further and better day after day. And **many thanks to raylib community and all raylib users** for supporting the library along those many years. -Finally, I want to thank [puffer.ai](https://puffer.ai/) and [comma.ai](https://comma.ai/) for **supporting and sponsoring the project** as platinum sponsors, along many others individuals that have been sponsoring raylib along the years. Thanks to all of you for allowing me to keep working on this library! +Finally, I want to thank [puffer.ai](https://puffer.ai/) and [comma.ai](https://comma.ai/) for **using raylib and supporting the project** as platinum sponsors, along many others individuals that have been sponsoring raylib along the years. Thanks to all of you for allowing me to keep working on this library! -**After +12 years of development, `raylib 6.0` is today one of the bests libraries to enjoy games/tools/graphic programming!** +**After +12 years of development, `raylib 6.0` is today one of the bests libraries to enjoy games/tools/graphics programming!** **Enjoy graphics programming with raylib!** :) From f220848896ec1749017b9486518af9c3a9202b89 Mon Sep 17 00:00:00 2001 From: Vadim Gunko Date: Thu, 23 Apr 2026 16:27:42 +0500 Subject: [PATCH 115/185] Update pascal binding (#5784) * Update BINDINGS.md added support for Delphi * Update BINDINGS.md --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 7169fbc05..7e8f3f6e0 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -64,7 +64,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT | | [raylib-ocaml](https://github.com/tjammer/raylib-ocaml) | **5.0** | [OCaml](https://ocaml.org) | MIT | | [TurboRaylib](https://github.com/turborium/TurboRaylib) | 4.5 | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT | -| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **5.5** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)/[Delphi](https://en.wikipedia.org/wiki/Delphi_(software)) | Zlib | +| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **6.0** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)/[Delphi](https://en.wikipedia.org/wiki/Delphi_(software)) | Zlib | | [Raylib.4.0.Pascal](https://github.com/sysrpl/Raylib.4.0.Pascal) | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib | | [pyraylib](https://github.com/Ho011/pyraylib) | 3.7 | [Python](https://www.python.org) | Zlib | | [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) | **5.5** | [Python](https://www.python.org) | EPL-2.0 | From de8419cc8b83a0b122207af532b2dfc0bb2a672c Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Thu, 23 Apr 2026 06:28:34 -0500 Subject: [PATCH 116/185] removed web_basic_window mentions (#5782) --- examples/CMakeLists.txt | 1 - .../VS2022/examples/web_basic_window.vcxproj | 569 ------------------ tools/rexm/rexm.c | 3 +- 3 files changed, 1 insertion(+), 572 deletions(-) delete mode 100644 projects/VS2022/examples/web_basic_window.vcxproj diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index ee5469eaa..079b9cb01 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -98,7 +98,6 @@ if (${PLATFORM} MATCHES "Android") elseif (${PLATFORM} MATCHES "Web") set(example_sources) # clear example_sources - list(APPEND example_sources others/web_basic_window.c) list(APPEND example_sources core/core_input_gestures_testbed.c) elseif ("${PLATFORM}" STREQUAL "DRM") diff --git a/projects/VS2022/examples/web_basic_window.vcxproj b/projects/VS2022/examples/web_basic_window.vcxproj deleted file mode 100644 index 6c0c7ab1f..000000000 --- a/projects/VS2022/examples/web_basic_window.vcxproj +++ /dev/null @@ -1,569 +0,0 @@ - - - - - Debug.DLL - ARM64 - - - Debug.DLL - Win32 - - - Debug.DLL - x64 - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release.DLL - ARM64 - - - Release.DLL - Win32 - - - Release.DLL - x64 - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC} - Win32Proj - web_basic_window - 10.0 - web_basic_window - - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - true - $(DefaultPlatformToolset) - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - Application - false - $(DefaultPlatformToolset) - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - $(SolutionDir)..\..\examples\others - WindowsLocalDebugger - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - /FS %(AdditionalOptions) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - /FS %(AdditionalOptions) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - Copy Debug DLL to output directory - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - Copy Debug DLL to output directory - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) - CompileAsC - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - - - Console - true - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - Copy Debug DLL to output directory - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - - - Copy Release DLL to output directory - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - - - Copy Release DLL to output directory - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP - $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) - CompileAsC - true - - - Console - true - true - true - raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ - - - xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" - - - Copy Release DLL to output directory - - - - - - - - - - - {e89d61ac-55de-4482-afd4-df7242ebc859} - - - - - - \ No newline at end of file diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index 84780988f..71404dcf8 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -1268,8 +1268,7 @@ int main(int argc, char *argv[]) // NOTE: Some examples should be excluded from VS2022 solution because // they have specific platform/linkage requirements: - if ((strcmp(exInfo->name, "web_basic_window") == 0) || - (strcmp(exInfo->name, "raylib_opengl_interop") == 0)) continue; + if (strcmp(exInfo->name, "raylib_opengl_interop") == 0) continue; // Review: Add: raylib/projects/VS2022/examples/_example_name.vcxproj // Review: Add: raylib/projects/VS2022/raylib.sln From e9caf5a9811a9c1a126398795915b13ef488618e Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Thu, 23 Apr 2026 09:01:58 -0400 Subject: [PATCH 117/185] BINDINGS: Update raylib-cpp version to 6.0 (#5785) The C++ wrapper, [raylib-cpp](https://github.com/RobLoach/raylib-cpp), now works with raylib 6.0: https://github.com/RobLoach/raylib-cpp/releases/tag/v6.0.0 --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 7e8f3f6e0..07ae7ab08 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -112,7 +112,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's paradigm. | Name | raylib Version | Language | License | | ---------------------------------------------------- | :------------: | :------------------------------------------: | :-----: | -| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **5.5** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib | +| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **6.0** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib | | [claylib](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib | | [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT | | [DOOR](https://github.com/RealDoigt/DOOR) | 4.0 | [D](https://dlang.org) | MIT | From 1c5cd35372d46ff31b45d3ad44e20812ce3647cb Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Fri, 24 Apr 2026 07:55:59 -0400 Subject: [PATCH 118/185] Add sola-raylib to BINDINGS.md (#5790) Rust bindings and wrapper library. A maintained fork of raylib-rs with bug fixes in the 5.5.x series and upcoming support for 6.0. --- BINDINGS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BINDINGS.md b/BINDINGS.md index 07ae7ab08..e0024f61b 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -77,6 +77,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylibr](https://github.com/jeroenjanssens/raylibr) | 4.0 | [R](https://www.r-project.org) | MIT | | [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 | | [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib | +| [sola-raylib](https://github.com/brettchalupa/sola-raylib) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib | | [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib | | [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** | | [racket-raylib](https://github.com/eutro/racket-raylib) | **5.5** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 | From 3b23200b85299f592146488f0b1f73d65f008c60 Mon Sep 17 00:00:00 2001 From: "Italo F. Capasso B." <44873757+edwood-grant@users.noreply.github.com> Date: Fri, 24 Apr 2026 06:56:30 -0500 Subject: [PATCH 119/185] Update BINDINGS.md to add vala-vapi version update (#5789) --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index e0024f61b..54c9d2785 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -87,7 +87,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-umka](https://github.com/robloach/raylib-umka) | 4.5 | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib | | [raylib-v](https://github.com/vlang/raylib) | 5.5 | [V](https://vlang.io) | MIT/Unlicense | | [raylib.v](https://github.com/irishgreencitrus/raylib.v) | 4.2 | [V](https://vlang.io) | Zlib | -| [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **5.0** | [Vala](https://vala.dev) | Zlib | +| [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **6.0** | [Vala](https://vala.dev) | Zlib | | [raylib-wave](https://github.com/wavefnd/raylib-wave) | **auto** |[Wave](http://wave-lang.dev) | Zlib | | [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.5 | [Wren](http://wren.io) | ISC | | [raylib-zig](https://github.com/raylib-zig/raylib-zig) | **5.6-dev** | [Zig](https://ziglang.org) | MIT | From 5608460901ba5e4cac9eafa64fb8e72d43c8351e Mon Sep 17 00:00:00 2001 From: rigidatoms Date: Fri, 24 Apr 2026 08:57:20 -0300 Subject: [PATCH 120/185] add missing UnloadFileData() (#5787) Adds missing function necessary for using the module as a standalone library. --- src/raudio.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/raudio.c b/src/raudio.c index f05567cc8..b9c4eda05 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -434,6 +434,7 @@ static const char *GetFileName(const char *filePath); // Get point static const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string) static unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read) +static void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData() static bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write) static bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated #endif @@ -2882,6 +2883,12 @@ static unsigned char *LoadFileData(const char *fileName, int *dataSize) return data; } +// Unload file data allocated by LoadFileData() +void UnloadFileData(unsigned char *data) +{ + RL_FREE(data); +} + // Save data to file from buffer static bool SaveFileData(const char *fileName, void *data, int dataSize) { From 254953611e6273a5d0e8015cad9891c0191afb23 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 24 Apr 2026 13:58:52 +0200 Subject: [PATCH 121/185] Update rcore.c --- src/rcore.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index d99919b62..c3d61f3da 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -106,7 +106,7 @@ #include "config.h" // Defines module configuration flags -#include // Required for: srand(), rand(), atexit(), exit() +#include // Required for: srand(), rand(), exit() #include // Required for: FILE, fopen(), fseek(), ftell(), fread(), fwrite(), fprintf(), vprintf(), fclose(), sprintf() [Used in OpenURL()] #include // Required for: strlen(), strncpy(), strcmp(), strrchr(), memset(), strcat() #include // Required for: va_list, va_start(), va_end() [Used in TraceLog()] @@ -1757,9 +1757,9 @@ int GetRandomValue(int min, int max) else { // Rejection sampling to get a uniform integer in [min, max] - unsigned long c = (unsigned long)RAND_MAX + 1UL; // number of possible rand() results - unsigned long m = (unsigned long)range; // size of the target interval - unsigned long t = c - (c%m); // largest multiple of m <= c + unsigned long c = (unsigned long)RAND_MAX + 1UL; // Number of possible results + unsigned long m = (unsigned long)range; // Size of the target interval + unsigned long t = c - (c%m); // Largest multiple of m <= c unsigned long r = 0; for (;;) From 07a056441a5ad4b5e05f3872504de154c4e216f7 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 24 Apr 2026 13:59:41 +0200 Subject: [PATCH 122/185] Update raudio.c --- src/raudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raudio.c b/src/raudio.c index b9c4eda05..bae26d734 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -2884,7 +2884,7 @@ static unsigned char *LoadFileData(const char *fileName, int *dataSize) } // Unload file data allocated by LoadFileData() -void UnloadFileData(unsigned char *data) +static void UnloadFileData(unsigned char *data) { RL_FREE(data); } From 4cae4ba9d559fa785d1beff635fc762d1cec9b31 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 24 Apr 2026 14:03:59 +0200 Subject: [PATCH 123/185] REVIEWED: `IsModelValid()` #5780 --- src/rmodels.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 6d3169ec0..8288c3172 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1182,16 +1182,17 @@ bool IsModelValid(Model model) // but some VBOs could not be used, it depends on Mesh vertex data for (int i = 0; i < model.meshCount; i++) { - if ((model.meshes[i].vertices != NULL) && (model.meshes[i].vboId[0] == 0)) { result = false; break; } // Vertex position buffer not uploaded to GPU + if ((model.meshes[i].vertices != NULL) && (model.meshes[i].vboId[0] == 0)) { result = false; break; } // Vertex position buffer not uploaded to GPU if ((model.meshes[i].texcoords != NULL) && (model.meshes[i].vboId[1] == 0)) { result = false; break; } // Vertex textcoords buffer not uploaded to GPU - if ((model.meshes[i].normals != NULL) && (model.meshes[i].vboId[2] == 0)) { result = false; break; } // Vertex normals buffer not uploaded to GPU - if ((model.meshes[i].colors != NULL) && (model.meshes[i].vboId[3] == 0)) { result = false; break; } // Vertex colors buffer not uploaded to GPU - if ((model.meshes[i].tangents != NULL) && (model.meshes[i].vboId[4] == 0)) { result = false; break; } // Vertex tangents buffer not uploaded to GPU - if ((model.meshes[i].texcoords2 != NULL) && (model.meshes[i].vboId[5] == 0)) { result = false; break; } // Vertex texcoords2 buffer not uploaded to GPU - if ((model.meshes[i].indices != NULL) && (model.meshes[i].vboId[6] == 0)) { result = false; break; } // Vertex indices buffer not uploaded to GPU - if ((model.meshes[i].boneIndices != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; } // Vertex boneIndices buffer not uploaded to GPU - if ((model.meshes[i].boneWeights != NULL) && (model.meshes[i].vboId[8] == 0)) { result = false; break; } // Vertex boneWeights buffer not uploaded to GPU - + if ((model.meshes[i].normals != NULL) && (model.meshes[i].vboId[2] == 0)) { result = false; break; } // Vertex normals buffer not uploaded to GPU + if ((model.meshes[i].colors != NULL) && (model.meshes[i].vboId[3] == 0)) { result = false; break; } // Vertex colors buffer not uploaded to GPU + if ((model.meshes[i].tangents != NULL) && (model.meshes[i].vboId[4] == 0)) { result = false; break; } // Vertex tangents buffer not uploaded to GPU + if ((model.meshes[i].texcoords2 != NULL) && (model.meshes[i].vboId[5] == 0)) { result = false; break; } // Vertex texcoords2 buffer not uploaded to GPU + if ((model.meshes[i].indices != NULL) && (model.meshes[i].vboId[6] == 0)) { result = false; break; } // Vertex indices buffer not uploaded to GPU +#if SUPPORT_GPU_SKINNING + if ((model.meshes[i].boneIndices != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; } // Vertex boneIndices buffer not uploaded to GPU + if ((model.meshes[i].boneWeights != NULL) && (model.meshes[i].vboId[8] == 0)) { result = false; break; } // Vertex boneWeights buffer not uploaded to GPU +#endif // NOTE: Some OpenGL versions do not support VAO, so avoid below check //if (model.meshes[i].vaoId == 0) { result = false; break } } From 61dd488b763ae7b7be47fbd2c8e98c4fec1d3ce6 Mon Sep 17 00:00:00 2001 From: Sebbl0508 <28149337+Sebbl0508@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:09:02 +0200 Subject: [PATCH 124/185] [examples] Move window for ball shake (#5791) --- examples/shapes/shapes_ball_physics.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/examples/shapes/shapes_ball_physics.c b/examples/shapes/shapes_ball_physics.c index 2a4cc8f18..2424ea738 100644 --- a/examples/shapes/shapes_ball_physics.c +++ b/examples/shapes/shapes_ball_physics.c @@ -16,6 +16,7 @@ ********************************************************************************************/ #include "raylib.h" +#include "raymath.h" #include // Required for: malloc(), free() #include // Required for: hypot() @@ -68,6 +69,8 @@ int main(void) Vector2 pressOffset = { 0 }; // Mouse press offset relative to the ball that grabbedd float gravity = 100; // World gravity + + Vector2 windowPosition = GetWindowPosition(); SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- @@ -128,6 +131,15 @@ int main(void) } } + Vector2 windowPositionDiff = Vector2Subtract(windowPosition, GetWindowPosition()); + if (Vector2Length(windowPositionDiff) > 5.0f) { + for (int i = 0; i < ballCount; i++) { + if (!balls[i].grabbed) { + balls[i].speed = Vector2Add(balls[i].speed, Vector2Scale(windowPositionDiff, 10.0f)); + } + } + } + // Shake balls if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE)) { @@ -194,6 +206,8 @@ int main(void) ball->prevPosition = ball->position; } } + + windowPosition = GetWindowPosition(); //---------------------------------------------------------------------------------- // Draw @@ -226,4 +240,4 @@ int main(void) //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +} From d892f3ba4ae07d38e008ad37a55c5ffa29be66af Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 24 Apr 2026 15:11:39 +0200 Subject: [PATCH 125/185] Update shapes_ball_physics.c --- examples/shapes/shapes_ball_physics.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/shapes/shapes_ball_physics.c b/examples/shapes/shapes_ball_physics.c index 2424ea738..d94cc438a 100644 --- a/examples/shapes/shapes_ball_physics.c +++ b/examples/shapes/shapes_ball_physics.c @@ -16,6 +16,7 @@ ********************************************************************************************/ #include "raylib.h" + #include "raymath.h" #include // Required for: malloc(), free() @@ -131,12 +132,14 @@ int main(void) } } - Vector2 windowPositionDiff = Vector2Subtract(windowPosition, GetWindowPosition()); - if (Vector2Length(windowPositionDiff) > 5.0f) { - for (int i = 0; i < ballCount; i++) { - if (!balls[i].grabbed) { - balls[i].speed = Vector2Add(balls[i].speed, Vector2Scale(windowPositionDiff, 10.0f)); - } + // Get window position change for shaking + Vector2 windowPositionDelta = Vector2Subtract(windowPosition, GetWindowPosition()); + + if (Vector2Length(windowPositionDelta) > 5.0f) + { + for (int i = 0; i < ballCount; i++) + { + if (!balls[i].grabbed) balls[i].speed = Vector2Add(balls[i].speed, Vector2Scale(windowPositionDelta, 10.0f)); } } @@ -236,6 +239,7 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- RL_FREE(balls); + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- From 4ee2013169c215c8ccf226b466c4931e79e20007 Mon Sep 17 00:00:00 2001 From: Caleb Norton Date: Fri, 24 Apr 2026 14:08:20 -0500 Subject: [PATCH 126/185] various rlparser fixes (#5794) --- .gitignore | 4 ++-- tools/rlparser/README.md | 2 +- tools/rlparser/rlparser.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index a0fa8db1c..b5be212d7 100644 --- a/.gitignore +++ b/.gitignore @@ -125,8 +125,8 @@ build-*/ docgen_tmp/ # Tools stuff -tools/parser/rlparser.exe -tools/parser/rlparser +tools/rlparser/rlparser.exe +tools/rlparser/rlparser tools/rexm/rexm.exe tools/rexm/rexm diff --git a/tools/rlparser/README.md b/tools/rlparser/README.md index cf009a891..cf5531e5f 100644 --- a/tools/rlparser/README.md +++ b/tools/rlparser/README.md @@ -1,6 +1,6 @@ # rlparser - raylib parser -This parser scans [`raylib.h`](../src/raylib.h) to get information about `defines`, `structs`, `enums` and `functions`. +This parser scans [`raylib.h`](../../src/raylib.h) to get information about `defines`, `structs`, `enums` and `functions`. All data is separated into parts, usually as strings. The following types are used for data: - `struct DefineInfo` diff --git a/tools/rlparser/rlparser.c b/tools/rlparser/rlparser.c index c2aad0794..dc2afe114 100644 --- a/tools/rlparser/rlparser.c +++ b/tools/rlparser/rlparser.c @@ -202,7 +202,7 @@ int main(int argc, char *argv[]) { if (argc > 1) ProcessCommandLine(argc, argv); - const char *raylibhPath = "../src/raylib.h\0"; + const char *raylibhPath = "../../src/raylib.h\0"; const char *raylibapiPath = "raylib_api.txt\0"; const char *rlapiPath = "RLAPI\0"; if (inFileName[0] == '\0') MemoryCopy(inFileName, raylibhPath, TextLength(raylibhPath) + 1); @@ -1154,7 +1154,7 @@ static void ProcessCommandLine(int argc, char *argv[]) else if (IsTextEqual(argv[i + 1], "JSON\0", 5)) outputFormat = JSON; else if (IsTextEqual(argv[i + 1], "XML\0", 4)) outputFormat = XML; else if (IsTextEqual(argv[i + 1], "LUA\0", 4)) outputFormat = LUA; - else if (IsTextEqual(argv[i + 1], "CODE\0", 4)) outputFormat = CODE; + else if (IsTextEqual(argv[i + 1], "CODE\0", 5)) outputFormat = CODE; } else printf("WARNING: No format parameters provided\n"); } From 386eabb9328fecfd7c285a674fac0c72ff856241 Mon Sep 17 00:00:00 2001 From: Brett Chalupa Date: Fri, 24 Apr 2026 16:22:34 -0400 Subject: [PATCH 127/185] Update sola-raylib Raylib supported version to 6 (#5795) I just published crate version 6.0.0 which supports Raylib 6's new functions and platforms. --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 54c9d2785..50c3a8dcc 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -77,7 +77,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylibr](https://github.com/jeroenjanssens/raylibr) | 4.0 | [R](https://www.r-project.org) | MIT | | [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 | | [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib | -| [sola-raylib](https://github.com/brettchalupa/sola-raylib) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib | +| [sola-raylib](https://github.com/brettchalupa/sola-raylib) | **6.0** | [Rust](https://www.rust-lang.org) | Zlib | | [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib | | [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** | | [racket-raylib](https://github.com/eutro/racket-raylib) | **5.5** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 | From ccc0d7452aa88739cbc07863896f1a4477863c69 Mon Sep 17 00:00:00 2001 From: Steven Schveighoffer Date: Sat, 25 Apr 2026 08:49:29 -0400 Subject: [PATCH 128/185] chore(bindings): Update binding version for raylib-d to 6.0 (#5799) --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 50c3a8dcc..5ccd69cf4 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -28,7 +28,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [dart-raylib](https://gitlab.com/wolfenrain/dart-raylib) | 4.0 | [Dart](https://dart.dev) | MIT | | [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 | | [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) | Apache-2.0 | -| [raylib-d](https://github.com/schveiguy/raylib-d) | **5.5** | [D](https://dlang.org) | Zlib | +| [raylib-d](https://github.com/schveiguy/raylib-d) | **6.0** | [D](https://dlang.org) | Zlib | | [DenoRaylib550](https://github.com/JJLDonley/DenoRaylib550) | **5.5** | [Deno](https://deno.land) | MIT | | [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 | | [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 | From c2ea6a38b59a1da77084cf91bccece5e69fcf6a0 Mon Sep 17 00:00:00 2001 From: bielern <917465+bielern@users.noreply.github.com> Date: Sat, 25 Apr 2026 19:53:34 +0200 Subject: [PATCH 129/185] Fix: Add NULL check to CheckCollisionLines (#5802) --- src/rshapes.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/rshapes.c b/src/rshapes.c index cdd440cf0..de7476ce9 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -2387,8 +2387,11 @@ bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, if ((0.0f <= t) && (t <= 1.0f) && (0.0f <= u) && (u <= 1.0f)) { - collisionPoint->x = startPos1.x + t*rx; - collisionPoint->y = startPos1.y + t*ry; + if (collisionPoint) + { + collisionPoint->x = startPos1.x + t*rx; + collisionPoint->y = startPos1.y + t*ry; + } collision = true; } From 0f98d78a67c14ccca99e603091e52f5fd014af73 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 25 Apr 2026 21:02:34 +0200 Subject: [PATCH 130/185] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 00929215c..7fc704e25 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html) [![GitHub Releases Downloads](https://img.shields.io/github/downloads/raysan5/raylib/total)](https://github.com/raysan5/raylib/releases) [![GitHub Stars](https://img.shields.io/github/stars/raysan5/raylib?style=flat&label=stars)](https://github.com/raysan5/raylib/stargazers) -[![GitHub commits since tagged version](https://img.shields.io/github/commits-since/raysan5/raylib/5.5)](https://github.com/raysan5/raylib/commits/master) +[![GitHub commits since tagged version](https://img.shields.io/github/commits-since/raysan5/raylib/6.0)](https://github.com/raysan5/raylib/commits/master) [![GitHub Sponsors](https://img.shields.io/github/sponsors/raysan5?label=sponsors)](https://github.com/sponsors/raysan5) [![Packaging Status](https://repology.org/badge/tiny-repos/raylib.svg)](https://repology.org/project/raylib/versions) [![License](https://img.shields.io/badge/license-zlib%2Flibpng-blue.svg)](LICENSE) From dff07d020cffe31bea93a939884558f6531e4901 Mon Sep 17 00:00:00 2001 From: Luca Duran Date: Sun, 26 Apr 2026 14:15:33 -0400 Subject: [PATCH 131/185] Fix FileMove from delete file if FileCopy did not work (#5806) --- src/rcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rcore.c b/src/rcore.c index c3d61f3da..95fb93e20 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -2283,7 +2283,7 @@ int FileMove(const char *srcPath, const char *dstPath) if (FileExists(srcPath)) { - if (FileCopy(srcPath, dstPath) == 0) result = FileRemove(srcPath); + if (FileCopy(srcPath, dstPath)) result = FileRemove(srcPath); else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to copy file to [%s]", srcPath, dstPath); } else TRACELOG(LOG_WARNING, "FILEIO: [%s] Source file does not exist", srcPath); From 8e82249f6572ae2683a9cade6addd9b404abd710 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Sun, 26 Apr 2026 11:16:35 -0700 Subject: [PATCH 132/185] Update to latest DR libs to fix some warnings in MSVC (#5808) --- src/external/dr_flac.h | 68 ++++++++++++++++++++++++++++++++---------- src/external/dr_mp3.h | 61 ++++++++++++++++++++++++++----------- src/external/dr_wav.h | 63 ++++++++++++++++++++++++++++++++------ 3 files changed, 151 insertions(+), 41 deletions(-) diff --git a/src/external/dr_flac.h b/src/external/dr_flac.h index 2891194c7..72bc6b762 100644 --- a/src/external/dr_flac.h +++ b/src/external/dr_flac.h @@ -1,6 +1,6 @@ /* FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file. -dr_flac - v0.13.3 - 2026-01-17 +dr_flac - v0.13.4 - TBD David Reid - mackron@gmail.com @@ -126,7 +126,7 @@ extern "C" { #define DRFLAC_VERSION_MAJOR 0 #define DRFLAC_VERSION_MINOR 13 -#define DRFLAC_VERSION_REVISION 3 +#define DRFLAC_VERSION_REVISION 4 #define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION) #include /* For size_t. */ @@ -1547,6 +1547,8 @@ static DRFLAC_INLINE drflac_bool32 drflac_has_sse41(void) #define DRFLAC_ZERO_OBJECT(p) DRFLAC_ZERO_MEMORY((p), sizeof(*(p))) #endif +#define DRFLAC_MIN(a, b) (((a) < (b)) ? (a) : (b)) + #define DRFLAC_MAX_SIMD_VECTOR_SIZE 64 /* 64 for AVX-512 in the future. */ /* Result Codes */ @@ -5980,8 +5982,6 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p break; /* Failed to seek to FLAC frame. */ } } else { - const float approxCompressionRatio = (drflac_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((drflac_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0f); - if (pcmRangeLo > pcmFrameIndex) { /* We seeked too far forward. We need to move our target byte backward and try again. */ byteRangeHi = lastSuccessfulSeekOffset; @@ -6004,12 +6004,14 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p break; /* Failed to seek to FLAC frame. */ } } else { + const double approxCompressionRatio = (drflac_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((drflac_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0); + byteRangeLo = lastSuccessfulSeekOffset; if (byteRangeHi < byteRangeLo) { byteRangeHi = byteRangeLo; } - targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((drflac_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0f) * approxCompressionRatio); + targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((drflac_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0) * approxCompressionRatio); if (targetByte > byteRangeHi) { targetByte = byteRangeHi; } @@ -6402,7 +6404,7 @@ static void* drflac__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, } if (p != NULL) { - DRFLAC_COPY_MEMORY(p2, p, szOld); + DRFLAC_COPY_MEMORY(p2, p, DRFLAC_MIN(szNew, szOld)); pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData); } @@ -6430,11 +6432,22 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that we'll be sitting on byte 42. */ - drflac_uint64 runningFilePos = 42; - drflac_uint64 seektablePos = 0; - drflac_uint32 seektableSize = 0; + drflac_uint64 runningFilePos = 42; + drflac_uint64 seektablePos = 0; + drflac_uint32 seektableSize = 0; + drflac_int64 fileSize = 0; + drflac_bool32 hasKnownFileSize = DRFLAC_FALSE; - (void)onTell; + /* We'll be doing some memory allocations here against untrusted data. We'll do a basic validation check that they don't exceed the size of the file. */ + if (onTell != NULL && onSeek != NULL) { + if (onSeek(pUserData, 0, DRFLAC_SEEK_END)) { + if (onTell(pUserData, &fileSize)) { + hasKnownFileSize = DRFLAC_TRUE; + } + + onSeek(pUserData, runningFilePos, DRFLAC_SEEK_SET); + } + } for (;;) { drflac_metadata metadata; @@ -6444,6 +6457,11 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) { return DRFLAC_FALSE; } + + if (hasKnownFileSize && (blockSize > ((drflac_uint64)fileSize - runningFilePos))) { + return DRFLAC_FALSE; /* Block size exceeds the size of the file. */ + } + runningFilePos += 4; metadata.type = blockType; @@ -6559,7 +6577,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d drflac__free_from_callbacks(pRawData, pAllocationCallbacks); return DRFLAC_FALSE; } - metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength; + metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength; metadata.data.vorbis_comment.commentCount = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4; /* Need space for 'commentCount' comments after the block, which at minimum is a drflac_uint32 per comment */ @@ -6747,13 +6765,18 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d blockSizeRemaining -= 4; metadata.data.picture.mimeLength = drflac__be2host_32(metadata.data.picture.mimeLength); + if (blockSizeRemaining < metadata.data.picture.mimeLength) { + result = DRFLAC_FALSE; + goto done_flac; + } + pMime = (char*)drflac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); /* +1 for null terminator. */ if (pMime == NULL) { result = DRFLAC_FALSE; goto done_flac; } - if (blockSizeRemaining < metadata.data.picture.mimeLength || onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) { + if (onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) { result = DRFLAC_FALSE; goto done_flac; } @@ -6769,13 +6792,18 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d blockSizeRemaining -= 4; metadata.data.picture.descriptionLength = drflac__be2host_32(metadata.data.picture.descriptionLength); + if (blockSizeRemaining < metadata.data.picture.descriptionLength) { + result = DRFLAC_FALSE; + goto done_flac; + } + pDescription = (char*)drflac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); /* +1 for null terminator. */ if (pDescription == NULL) { result = DRFLAC_FALSE; goto done_flac; } - if (blockSizeRemaining < metadata.data.picture.descriptionLength || onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) { + if (onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) { result = DRFLAC_FALSE; goto done_flac; } @@ -8094,11 +8122,17 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac return NULL; } + if ((0xFFFFFFFF - (seekpointCount * sizeof(drflac_seekpoint))) < allocationSize) { + #ifndef DR_FLAC_NO_OGG + drflac__free_from_callbacks(pOggbs, &allocationCallbacks); + #endif + return NULL; + } + allocationSize += seekpointCount * sizeof(drflac_seekpoint); } - - pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks); + pFlac = (drflac*)drflac__malloc_from_callbacks((size_t)allocationSize, &allocationCallbacks); if (pFlac == NULL) { #ifndef DR_FLAC_NO_OGG drflac__free_from_callbacks(pOggbs, &allocationCallbacks); @@ -12169,6 +12203,10 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat /* REVISION HISTORY ================ +v0.13.4 - TBD + - Add a bounds check when allocating memory during metadata processing. + - Fix a possible overflow error when parsing picture metadata. + v0.13.3 - 2026-01-17 - Fix a compiler compatibility issue with some inlined assembly. - Fix a compilation warning. diff --git a/src/external/dr_mp3.h b/src/external/dr_mp3.h index c0969c476..a458d86cf 100644 --- a/src/external/dr_mp3.h +++ b/src/external/dr_mp3.h @@ -3188,6 +3188,10 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8); pTagData = pTagDataBeg; + if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 8) { + goto done_xing_info; /* Frame too small for a Xing/Info tag. */ + } + /* Check for both "Xing" and "Info" identifiers. */ isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g'); isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o'); @@ -3199,42 +3203,60 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm pTagData += 8; /* Skip past the ID and flags. */ if (flags & 0x01) { /* FRAMES flag. */ + if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) { + goto done_xing_info; /* Invalid Xing/Info tag. */ + } + detectedMP3FrameCount = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3]; pTagData += 4; } if (flags & 0x02) { /* BYTES flag. */ + if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) { + goto done_xing_info; /* Invalid Xing/Info tag. */ + } + bytes = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3]; (void)bytes; /* <-- Just to silence a warning about `bytes` being assigned but unused. Want to leave this here in case I want to make use of it later. */ pTagData += 4; } if (flags & 0x04) { /* TOC flag. */ + if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 100) { + goto done_xing_info; /* Invalid Xing/Info tag. */ + } + /* TODO: Extract and bind seek points. */ pTagData += 100; } if (flags & 0x08) { /* SCALE flag. */ + if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) { + goto done_xing_info; /* Invalid Xing/Info tag. */ + } + pTagData += 4; } /* At this point we're done with the Xing/Info header. Now we can look at the LAME data. */ if (pTagData[0]) { + int delayInPCMFrames; + int paddingInPCMFrames; + + if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 36) { + goto done_xing_info; /* Invalid Xing/Info tag. */ + } + pTagData += 21; - if (pTagData - pFirstFrameData + 14 < firstFrameInfo.frame_bytes) { - int delayInPCMFrames; - int paddingInPCMFrames; - - delayInPCMFrames = (( (drmp3_uint32)pTagData[0] << 4) | ((drmp3_uint32)pTagData[1] >> 4)) + (528 + 1); - paddingInPCMFrames = ((((drmp3_uint32)pTagData[1] & 0xF) << 8) | ((drmp3_uint32)pTagData[2] )) - (528 + 1); - if (paddingInPCMFrames < 0) { - paddingInPCMFrames = 0; /* Padding cannot be negative. Probably a malformed file. Ignore. */ - } - - pMP3->delayInPCMFrames = (drmp3_uint32)delayInPCMFrames; - pMP3->paddingInPCMFrames = (drmp3_uint32)paddingInPCMFrames; + delayInPCMFrames = (( (drmp3_uint32)pTagData[0] << 4) | ((drmp3_uint32)pTagData[1] >> 4)) + (528 + 1); + paddingInPCMFrames = ((((drmp3_uint32)pTagData[1] & 0xF) << 8) | ((drmp3_uint32)pTagData[2] )) - (528 + 1); + if (paddingInPCMFrames < 0) { + paddingInPCMFrames = 0; /* Padding cannot be negative. Probably a malformed file. Ignore. */ } + + pMP3->delayInPCMFrames = (drmp3_uint32)delayInPCMFrames; + pMP3->paddingInPCMFrames = (drmp3_uint32)paddingInPCMFrames; } /* @@ -3273,6 +3295,8 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm */ drmp3dec_init(&pMP3->decoder); } + + done_xing_info:; } else { /* Failed to read the side info. */ } @@ -3285,7 +3309,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm } if (detectedMP3FrameCount != 0xFFFFFFFF) { - pMP3->totalPCMFrameCount = detectedMP3FrameCount * firstFramePCMFrameCount; + pMP3->totalPCMFrameCount = (drmp3_uint64)detectedMP3FrameCount * firstFramePCMFrameCount; } pMP3->channels = pMP3->mp3FrameChannels; @@ -4247,7 +4271,7 @@ DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 frame #else /* Slow path. Convert from s16 to f32. */ { - drmp3_int16 pTempS16[8192]; + drmp3_int16 pTempS16[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */ drmp3_uint64 totalPCMFramesRead = 0; while (totalPCMFramesRead < framesToRead) { @@ -4284,7 +4308,7 @@ DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_s16(drmp3* pMP3, drmp3_uint64 frame #else /* Slow path. Convert from f32 to s16. */ { - float pTempF32[4096]; + float pTempF32[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */ drmp3_uint64 totalPCMFramesRead = 0; while (totalPCMFramesRead < framesToRead) { @@ -4772,7 +4796,7 @@ static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64 totalFramesRead = 0; drmp3_uint64 framesCapacity = 0; float* pFrames = NULL; - float temp[4096]; + float temp[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */ DRMP3_ASSERT(pMP3 != NULL); @@ -4841,7 +4865,7 @@ static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pC drmp3_uint64 totalFramesRead = 0; drmp3_uint64 framesCapacity = 0; drmp3_int16* pFrames = NULL; - drmp3_int16 temp[4096]; + drmp3_int16 temp[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */ DRMP3_ASSERT(pMP3 != NULL); @@ -5010,6 +5034,9 @@ DIFFERENCES BETWEEN minimp3 AND dr_mp3 REVISION HISTORY ================ v0.7.4 - TBD + - Fix an overflow error with "Xing" and "Info" tag parsing. + - Add some validation checks for "Xing" and "Info" tag parsing. + - Reduce size of some stack allocations. - Improvements to SIMD detection. v0.7.3 - 2026-01-17 diff --git a/src/external/dr_wav.h b/src/external/dr_wav.h index c7bd89fa3..a18bc043f 100644 --- a/src/external/dr_wav.h +++ b/src/external/dr_wav.h @@ -1,6 +1,6 @@ /* WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file. -dr_wav - v0.14.5 - 2026-03-03 +dr_wav - v0.14.6 - TBD David Reid - mackron@gmail.com @@ -147,7 +147,7 @@ extern "C" { #define DRWAV_VERSION_MAJOR 0 #define DRWAV_VERSION_MINOR 14 -#define DRWAV_VERSION_REVISION 5 +#define DRWAV_VERSION_REVISION 6 #define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION) #include /* For size_t. */ @@ -1971,7 +1971,15 @@ DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void return DRWAV_INVALID_FILE; } - pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes) - 24; /* <-- Subtract 24 because w64 includes the size of the header. */ + pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes); + + /* Subtract 24 from the size because with w64 the reported chunk size includes the size of the header itself. */ + if (pHeaderOut->sizeInBytes >= 24) { + pHeaderOut->sizeInBytes -= 24; + } else { + return DRWAV_INVALID_FILE; + } + pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes); *pRunningBytesReadOut += 24; } else { @@ -2201,7 +2209,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars so it's consistent with how we do it in the first stage. */ loopCount = drwav_bytes_to_u32(smplHeaderData + 28); - calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES; + calculatedLoopCount = (drwav_uint32)((pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES); if (loopCount != calculatedLoopCount) { return totalBytesRead; } @@ -2580,8 +2588,10 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_bext_to_metadata_obj(drwav__metadata_pars pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1); DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL); - bytesRead += drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL); - pMetadata->data.bext.codingHistorySize = (drwav_uint32)drwav__strlen(pMetadata->data.bext.pCodingHistory); + pMetadata->data.bext.codingHistorySize = (drwav_uint32)drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL); + pMetadata->data.bext.pCodingHistory[pMetadata->data.bext.codingHistorySize] = '\0'; /* <-- Explicit null terminator in case of a badly formed file. */ + + bytesRead += pMetadata->data.bext.codingHistorySize; } else { pMetadata->data.bext.pCodingHistory = NULL; pMetadata->data.bext.codingHistorySize = 0; @@ -2755,10 +2765,10 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser* bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead); if (bytesJustRead == sizeof(buffer)) { drwav_uint32 loopCount = drwav_bytes_to_u32(buffer); - drwav_uint64 calculatedLoopCount; + drwav_uint32 calculatedLoopCount; /* The loop count must be validated against the size of the chunk. */ - calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES; + calculatedLoopCount = (drwav_uint32)((pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES); if (calculatedLoopCount == loopCount) { bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead); if (bytesJustRead == sizeof(buffer)) { @@ -2860,7 +2870,9 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser* return bytesRead; } allocSizeNeeded += drwav__strlen(buffer) + 1; - allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES + 1; /* Coding history. */ + + /* Coding history. */ + allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES + 1; drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1); @@ -3321,6 +3333,10 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) { drwav_uint8 fmtData[16]; + if (header.sizeInBytes < sizeof(fmtData)) { + return DRWAV_FALSE; /* Invalid fmt chunk. */ + } + foundChunk_fmt = DRWAV_TRUE; if (pWav->onRead(pWav->pUserData, fmtData, sizeof(fmtData)) != sizeof(fmtData)) { @@ -3833,6 +3849,11 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */ totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels); + if (totalBlockHeaderSizeInBytes >= dataChunkSize) { /* <-- We'll be subtracting totalBlockHeaderSizeInBytes from dataChunkSize next so it must be validated. */ + drwav_free(pWav->pMetadata, &pWav->allocationCallbacks); + return DRWAV_FALSE; /* Invalid file. */ + } + pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels; } if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) { @@ -3846,6 +3867,11 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */ totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels); + if (totalBlockHeaderSizeInBytes >= dataChunkSize) { /* <-- We'll be subtracting totalBlockHeaderSizeInBytes from dataChunkSize next so it must be validated. */ + drwav_free(pWav->pMetadata, &pWav->allocationCallbacks); + return DRWAV_FALSE; /* Invalid file. */ + } + pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels; /* The header includes a decoded sample for each channel which acts as the initial predictor sample. */ @@ -6725,6 +6751,10 @@ DRWAV_PRIVATE void drwav__pcm_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, shift += 8; } + if (!drwav__is_little_endian()) { + sample = drwav__bswap64(sample); + } + pIn += j; *pOut++ = (drwav_int16)((drwav_int64)sample >> 48); } @@ -7166,6 +7196,10 @@ DRWAV_PRIVATE void drwav__pcm_to_f32(float* pOut, const drwav_uint8* pIn, size_t shift += 8; } + if (!drwav__is_little_endian()) { + sample = drwav__bswap64(sample); + } + pIn += j; *pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0); } @@ -7650,6 +7684,10 @@ DRWAV_PRIVATE void drwav__pcm_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, shift += 8; } + if (!drwav__is_little_endian()) { + sample = drwav__bswap64(sample); + } + pIn += j; *pOut++ = (drwav_int32)((drwav_int64)sample >> 32); } @@ -8557,6 +8595,13 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b) /* REVISION HISTORY ================ +v0.14.6 - TBD + - Fix an error when loading files with a malformed "bext" chunk. + - Fix an error when loading files with a malformed "fmt" chunk. + - Fix an underflow error with badly formed ADPCM encoded files. + - Fix an underflow error with badly formed W64 files. + - Fix an error when converting from >32 bit samples to s16/f32/s32 on big-endian architectures. + v0.14.5 - 2026-03-03 - Fix a crash when loading files with a malformed "smpl" chunk. - Fix a signed overflow bug with the MS-ADPCM decoder. From ba72d258675a0069c13a305fc860777ffefc871f Mon Sep 17 00:00:00 2001 From: RaZe <97209503+rose-mtz@users.noreply.github.com> Date: Mon, 27 Apr 2026 03:08:12 -0500 Subject: [PATCH 133/185] [examples] Improve `core_smooth_pixelperfect` (#5803) * Improve smooth pixel-perfect example: add overscan and smoothing toggles * Add render size --- examples/core/core_smooth_pixelperfect.c | 34 ++++++++++++++++++--- examples/core/core_smooth_pixelperfect.png | Bin 15791 -> 3442 bytes 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/examples/core/core_smooth_pixelperfect.c b/examples/core/core_smooth_pixelperfect.c index 2b01f3fef..24f77e4ad 100644 --- a/examples/core/core_smooth_pixelperfect.c +++ b/examples/core/core_smooth_pixelperfect.c @@ -52,7 +52,7 @@ int main(void) // The target's height is flipped (in the source Rectangle), due to OpenGL reasons Rectangle sourceRec = { 0.0f, 0.0f, (float)target.texture.width, -(float)target.texture.height }; - Rectangle destRec = { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) }; + Rectangle destRec = { (screenWidth - screenWidth/1.25f)/2.0f, (screenHeight - screenHeight/1.25f)/2.0f, screenWidth/1.25f, screenHeight/1.25f }; Vector2 origin = { 0.0f, 0.0f }; @@ -61,6 +61,9 @@ int main(void) float cameraX = 0.0f; float cameraY = 0.0f; + bool smoothOn = true; + bool overscan = false; + SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -86,6 +89,18 @@ int main(void) worldSpaceCamera.target.y = truncf(screenSpaceCamera.target.y); screenSpaceCamera.target.y -= worldSpaceCamera.target.y; screenSpaceCamera.target.y *= virtualRatio; + + if (IsKeyPressed(KEY_S)) smoothOn = !smoothOn; + if (IsKeyPressed(KEY_O)) overscan = !overscan; + + if (overscan) + { + destRec = (Rectangle) { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) }; + } + else + { + destRec = (Rectangle) { (screenWidth - screenWidth/1.25f)/2.0f, (screenHeight - screenHeight/1.25f)/2.0f, screenWidth/1.25f, screenHeight/1.25f }; + } //---------------------------------------------------------------------------------- // Draw @@ -101,14 +116,23 @@ int main(void) EndTextureMode(); BeginDrawing(); - ClearBackground(RED); + ClearBackground(LIGHTGRAY); - BeginMode2D(screenSpaceCamera); + if (smoothOn) + { + BeginMode2D(screenSpaceCamera); + DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE); + EndMode2D(); + } + else + { DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE); - EndMode2D(); + } DrawText(TextFormat("Screen resolution: %ix%i", screenWidth, screenHeight), 10, 10, 20, DARKBLUE); DrawText(TextFormat("World resolution: %ix%i", virtualScreenWidth, virtualScreenHeight), 10, 40, 20, DARKGREEN); + DrawText(TextFormat("Smooth: %s", (smoothOn ? "ON" : "OFF")), 10, screenHeight - 60, 20, RED); + DrawText(TextFormat("Overscan: %s", (overscan ? "ON" : "OFF")), 10, screenHeight - 30, 20, RED); DrawFPS(GetScreenWidth() - 95, 10); EndDrawing(); //---------------------------------------------------------------------------------- @@ -122,4 +146,4 @@ int main(void) //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +} diff --git a/examples/core/core_smooth_pixelperfect.png b/examples/core/core_smooth_pixelperfect.png index d3b6ce012612eced58a845efc19c9bc957df9fae..30c8ec52312bcda4dde0f1453bbf20334440337a 100644 GIT binary patch literal 3442 zcmeHKYfzI{8a~{FNI}F=B$P`R6jv#Ca3M%sMbIL!Z56g4B&c{<jT`{SGMOwRev zd*0`Lp69%|{HO2`v$g28006TC`-8p!z`y|jy+~tXLkB5lmQlUqojl?=P-XpbV&$aay4maA%9S$eIesnSAyY0^VC7!!MZ19r| z*Du^Hc)h6#XNfK6Z|5qXiz;jjx9O49Z?FFxUsfFfK*q{Fxe)*XHs_6i#fCov;PC;2 z2AY^fQYl%10Z-Ma4MZCFLSIUqmOlaJ#r&8D!(+(|v6Ll0#o zLChQ&S=mKoCrRunR|SPfo*J402SumhWY;PMOG~0exP|5O{!r~XS16QagUqAHMd@Vr zQ>W7^l`N!^73ujy*~tsgDQ(K|1+9|gz9EcDOod`sNm7Lpck)%)qGYw9|dejQj(e-@SHC`top2 z_?X0gWHLG}Wz1oN3&`agZ@9CC`B|t->9*nGXFW;Nl!cKSuLe~mf<+JDmiWx+ZL`eH zFKwx~Wlbqw4|LsSn#2scz8n(Me;(Xwue^^*Ic{tUqPIe*HjFl!gcP!*>GNW4W1g^j zDRDDpp_|YaEIPmBMc)~fIP<$BWcCs!Q}A)Enq)}ybj%5rM)E8POiRs4pkme0^}y&Y zDjdjg6WD$5zaNmxRu!|?u$1Nb)5~wLrbTVMMZcFsd6O`+Pljz8RHkMNiwA01>gR2< z$LdM)CY&kg)+886#aHBXUH)kY|DS~M{=c6Z&*l`B(tJPli;zbH_eU`5nR3HKQ8vaS zRBSeQxK3Tm^iIf9%4HQbGDiWfH?px|cEJ!Ry5XgpA{gPxg3Gr!0V|Cy6|0qkeU2yN z(#&K%E~S>S%ksD!wWQcja0pD%P*A>SuA+Ej=+cWWw7&Zn6y}|wjkP|$3V`>6@u8x4 z_UwqNxTLtdc}jV3CIjG84l)2Zx_84J8LCgkt}dHkV~ze|CQ}|BqX$0hJu9UrtLnSo z%nYIl>kIAES5}U+(;4k{;HCy(^8xQ9k{JLIPvC=Yg?G~b|KNWU1jPW)3V{2B0K1Wu zN$;?jSX7Hgr#`rZf_c&Le!%Y(eGJY_3nP`5E4>emVM%Hmoy>^a9WsH(%G{vj!AR+^$F#OIdLmVr$V+d|(=Mh@_NSwXH@Czh?dK^mPoNBXw*q z>>1--d)Hw%{gZU&gPkSdnJqxu2|4SKC^n9pgEJ|RSGiRkhpqZUFBA{^s|H}FzgXM2WEv4^#<>r! zk8Gm+xN%W(0yz&Q@{V7hjc+elRO(<6Tvprqb~ymV-$x10wsLPSuDqF4<6a;s6}a6P zw4NfT2#sfs9Mu`9qd>7Vq1c5C!|%*SgLnQAp6#M%Sc+0QucOd#uDMspQ*}5U4p|AY zz`{$n3ao4?YPFOVj@^;>iEapqu``)`dV)l)x%sr2`zp*J_hfTwL51Kq*m~}eIS8N% zMVlvz({%|k!5i=^g!K(xn%+a(*x_T_5HI>DqR0#;k|uEk7N>nF^ydU5u7A8myvs8i1V1;XGtqNN%|`M+?-S2P}Lo3`1N+3brx< z-2a|XJCG@Q^$qfK*r?dC-$42i2}hTX)5?z_=+ICTz0Dw(a4yaKI+705Ed(%XS2^{S zRE9L3OltM%$wZKwL}cVl-r(^iNN;3&qJjH!v{KViX;%}Ll&Z*>DTt?Q${A=fID>mg zCjON>LcZd9;>FwBt`DYF1Ul(zR!vkJ7vg=9rpNG|kE){wkVT48F<X}bv!sVUcW0I-R5Wsh>+k8iCpSHbsP zZeeZWB5OZxQ%`v9XaDf0F4y<*dYcok}icitAnz)#eD;zru{fPnx_Js%4@4;XA7g+AqzW@LL literal 15791 zcmeHOdt8!d8wPdC3YD@Hv{dHi)|%y#W$I8w16x_HY?-wrDi?|I)BFE&dGDo`l$+G+m2!SRchJn!jzxSsc= ztF4iU*v|_KgU*u%*_(5vIQ%PL(CkzR(`+fJK){nQG5lA&xboLhXjY}KeiM8_Je(^f zWJ>+X{h2{IiNm*X_|7N#wV@cX;aI;mKql1mV;?Y~9WfzzP)$HvhnJL(J(Kz(knvi*B&3FbSKavNsldoO%UtoM$* zaIpnj!F<_o-t1d|5mz_lm7bs_@2eMEcD74?SQOAW9pz?5{=Axg`HvE_#o{L(#BE`h z1e>Ij;#7YX{(bP%A~#3Tif^>uk(mF6~hh0yZT1uG)|ie;r_6|ajH zXLqDTIh!=rr(8#~i=F1aV9xhejmt)|$-$(>?YQ69p zhrfMz|MfZ?y}fDVjogeD%OV0QywS^(8aRKmed_^6Y2vI_`^?vNrVNYOpWw_)inKV? zY*{oXF>TGn(@*^$+gr&9Hj!;}2?uwLVP|ic+D0aeM;g~-Ev|-byVhPkK1px`t!gag zD9&+Bl`;9xfa>#4HePCkqS&3FBZ`u)&WH8AqNaXJ69AVC10x7)vZ@c&epMfWaHSR% zOxsr@90YyIL|0GaNm+;KeaWvKaM9RIX?edUxHg~(fySyvsUdFJM3WGj(;B%Wc%hh; zt5+|XLWs}pV)|#OgDRGb!+*Wuv#c3!(-_)v3T;kjf0&JGq%v4mJS;^siDH>xLdN(z6?11rdg7xW6I?`Ee&pQ7;Tu!Dv(_R( z4#x0fzH$g`R|}q)NLgjJG`G@`?;LWS%DG86&K)+7>W0rPcG$rVU+#)YH9pi_(?Aw= zFV@QL0N@fbK(7d`cjQ?Gq1VX|LX3-e*`ZEVVth`KkE!P#j9{ne%KZjEuKgle!-7wP zBOYK*uVzK8Dzw&2+#^W3p3quZA9PzAv3^gPS@7ATTpq5d{(KEPR>HWIz!`t`QsaH! z0v3g7%DcYDpGn(1yH`}j!g;w(T6iTO+&!(PtT*@6GTGWrX{cJ&rdh&KuAQVS%4FV- znZALoi$;YC&I+4dfZJ{y2*`ONC|%}|v&(vRO+C|7b0y|n?lAbth3>kZoQ=+z6J&K} z9)p#;`xgu$@&J8HvDwnX=rO992+M~Ydn2e&NuSFfH;N}|X=@ctW2(j?%@X~+m*c4$ zSypFEvu{MztrBo7Wwz_WpRqC@&iwY-&V5y8kx%^EO1xYXR_>p( zFoD|g!vxy!DlMt9Zw-e37(l=hwJcIy6Kgn{cDK8;mtLmutf?Oco0mXgj<6R!OXW8o zSA8ghfd>>6_>PXpaixJRqI85JDOAR(sPrzyq3>qhjr|bReEP|~bG(A+ z?mr77YD;lOHz)59UbrgvXeJ0Vq*ip*JIoK!%BW~uv4BDa6eR~-O>-cM0tz{=UzN^n zvN7U^olAbF|isYJMUxTV7c&N5QI9OgJ#L|68`y6S*gMh4IGC*mS_cBZXCc}J#m1sLyfuB0`(m5qUlo7T%kH;D-#uDCZ21D?G^H# zDU!p=NMv_y)4XCr<4SMRz162;KlzW(@z_EN;+AFv%FA^@x$fH2+dlmb@xumWuO25~ zoRR3{cA;|_?At9P;bf`l(Ge+zZVWL*vfKfrji6K-V2uS;o90moC7pYcpL!IZ-qRtr zFBzLu_>-+Uw+U$<#<2%A5oobghrqs)zv{lvhrL3`8AQ5+bg{#rH?-fGNBkj=1vXCs+Rw{ zk=YO>CNhJOH*bw6nND%iafHa;Y;B03iNY(0qe9`VJ z^zUGdMJFO?<*g0&@=7y=QqbF)=mr|dgaZtL-0PgS_dkenHrSCH zBMTX@qxaDe?~DE^-gl*zD0U!PW(fU6Ee5rPqTkL9my)|W_lpAnqY+M3;r=!$D}f3 z5uMU<&}kn8UOtvcnhFCi_98McIP&@$LjUwa|G)r3W%+z0+K=(kZ7?g0A%8e|gy2qw z#k+@~ba>|pEFS_aklghd)N~LjklCEO*v?1>yrnCg$t^tO$*uhf+vF<`&+qOmjz8Uq3vJ@^6~~3%}U-)A}NOTsO>n% zWo1)bCg%%j!;(Nv0r~Rr0; z=~n-mX$#1NL{@YJcLB$Maair^W1Rtj8NFQ^FjiGj<^cT;SiGiHo+sEB2xM&j$3Vs_ zumEBOXa>?Jp|w8)O?uv}Thp&rq25T*m!oY{P;plrewy(j)GZV%be1UVY>T|-NFLmt zBhDwIZzD}I(x^P|9+o~m|x8oR)6^Sk$MmDf{pwHV}$NWVz5%Q6BOn&`!7($~dHg$YKsO>J%w>E3c zb5tloHJk5_iQLSHV)p(HtFZ$EU~A9RiPNSmZ}W2Jr0~&hER_4`F(f+z`p3 z8$}1i1eG4b*2s@!B5vdh+e}|bF>2*hItrQdu2RJT)#&I~-G<1G-PLqx3l*D#lbk5U z-=aOx5M3~dm4ZqGWA+-&O8Y;8ZwUT^j_Bwbv%fj@=+n>xFvT2n6Hxc-kB0RMX^-IO zwhu!;-tHs%(lf>HZj|{I=5ytt6QEthK%ay8WV&M0OErJtJr(^)Y=F%QTAZg+FYa>% zqf~*=IY%kKq&P=!7`^6P>C0HPtvEh!V9-mseK^7a^fDE6H?RF~*h_f?~e?M1r8 z%SzVOFmymjK_OZ|E_xvex>q$pK|?benbTBiH3y1R)!Wd(_-CLEW2eu7mEQ{^G^QD7 zHW-5fh++@wutOc9RHLnQUNzVRf~H7n2NG1bB@80+z?7tK6GuZa4Nx1RdtdeKORBd{ z?C{B5b7f#PuCV8j0ZW~h`v+7)Lnr43amHha(uYn+D+Znl%u#Xn+diFai0zS~Vi+n0 z!0u2J_=Y?)_J^Ece6dj4DfJeh#BC`q#>E~c8?hj$s{IbKsux$W*A}y(7NkA z%B+9vKEw<|%mAkUZ~FlH5Hk!h12o3_JO3YuBIEA5%)3n@fq%qCO`AH?{|J?_;eWdb B0Ji`D From 47bb749ce992e52ebee9e62f0da77320364a3e1d Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 10:21:50 +0200 Subject: [PATCH 134/185] RVIEWED: Comment to avoid invalid json gneration #5809 --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index bdca64329..54e8f2c92 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1162,7 +1162,7 @@ RLAPI bool ChangeDirectory(const char *dirPath); // Change wo RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths, files and directories, no subdirs scan -RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*" +RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: `*.*`,`FILES*`,`DIRS*` RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths From 3d3e6996b0bf3d972b3b8b0d7f616feabfe9035b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 08:22:08 +0000 Subject: [PATCH 135/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 2 +- tools/rlparser/output/raylib_api.lua | 2 +- tools/rlparser/output/raylib_api.txt | 2 +- tools/rlparser/output/raylib_api.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index 06abbb7f7..ea062de71 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -4696,7 +4696,7 @@ }, { "name": "LoadDirectoryFilesEx", - "description": "Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"", + "description": "Load directory filepaths with extension filtering and subdir scan; some filters available: `*.*`,`FILES*`,`DIRS*`", "returnType": "FilePathList", "params": [ { diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index 1fe26250c..3ab890e0b 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -4207,7 +4207,7 @@ return { }, { name = "LoadDirectoryFilesEx", - description = "Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"", + description = "Load directory filepaths with extension filtering and subdir scan; some filters available: `*.*`,`FILES*`,`DIRS*`", returnType = "FilePathList", params = { {type = "const char *", name = "basePath"}, diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index 1d82497b5..b230c469d 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -1789,7 +1789,7 @@ Function 146: LoadDirectoryFiles() (1 input parameters) Function 147: LoadDirectoryFilesEx() (3 input parameters) Name: LoadDirectoryFilesEx Return type: FilePathList - Description: Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*" + Description: Load directory filepaths with extension filtering and subdir scan; some filters available: `*.*`,`FILES*`,`DIRS*` Param[1]: basePath (type: const char *) Param[2]: filter (type: const char *) Param[3]: scanSubdirs (type: bool) diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 37d828049..1f8d96c97 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -1125,7 +1125,7 @@ - + From 00f3af78e369449de5eb02dcf55bedc42b64c753 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 10:22:31 +0200 Subject: [PATCH 136/185] UPDATED: Set version to `raylib 6.1-dev` to avoid confusions --- src/raylib.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 54e8f2c92..4ae5a4e47 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib v6.0 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) +* raylib v6.1-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) * * FEATURES: * - NO external dependencies, all required libraries included with raylib @@ -87,9 +87,9 @@ #include // Required for: va_list - Only used by TraceLogCallback #define RAYLIB_VERSION_MAJOR 6 -#define RAYLIB_VERSION_MINOR 0 +#define RAYLIB_VERSION_MINOR 1 #define RAYLIB_VERSION_PATCH 0 -#define RAYLIB_VERSION "6.0" +#define RAYLIB_VERSION "6.1-dev" // Function specifiers in case library is build/used as a shared library // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll From aa1100817abc2ccefaa94d8cf6ee12f568f321b6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 08:23:03 +0000 Subject: [PATCH 137/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 4 ++-- tools/rlparser/output/raylib_api.lua | 4 ++-- tools/rlparser/output/raylib_api.txt | 4 ++-- tools/rlparser/output/raylib_api.xml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index ea062de71..f79961a15 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -15,7 +15,7 @@ { "name": "RAYLIB_VERSION_MINOR", "type": "INT", - "value": 0, + "value": 1, "description": "" }, { @@ -27,7 +27,7 @@ { "name": "RAYLIB_VERSION", "type": "STRING", - "value": "6.0", + "value": "6.1-dev", "description": "" }, { diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index 3ab890e0b..2825e5244 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -15,7 +15,7 @@ return { { name = "RAYLIB_VERSION_MINOR", type = "INT", - value = 0, + value = 1, description = "" }, { @@ -27,7 +27,7 @@ return { { name = "RAYLIB_VERSION", type = "STRING", - value = "6.0", + value = "6.1-dev", description = "" }, { diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index b230c469d..c428650e8 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -14,7 +14,7 @@ Define 002: RAYLIB_VERSION_MAJOR Define 003: RAYLIB_VERSION_MINOR Name: RAYLIB_VERSION_MINOR Type: INT - Value: 0 + Value: 1 Description: Define 004: RAYLIB_VERSION_PATCH Name: RAYLIB_VERSION_PATCH @@ -24,7 +24,7 @@ Define 004: RAYLIB_VERSION_PATCH Define 005: RAYLIB_VERSION Name: RAYLIB_VERSION Type: STRING - Value: "6.0" + Value: "6.1-dev" Description: Define 006: __declspec(x) Name: __declspec(x) diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 1f8d96c97..98a52749e 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -3,9 +3,9 @@ - + - + From 6ae16c9895ab1d98ecf0da45a547db9a09e3f6bf Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 10:23:28 +0200 Subject: [PATCH 138/185] REVIEWED: `FileMove()`, additional security checks --- src/rcore.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rcore.c b/src/rcore.c index 95fb93e20..085c2a064 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -2283,7 +2283,10 @@ int FileMove(const char *srcPath, const char *dstPath) if (FileExists(srcPath)) { - if (FileCopy(srcPath, dstPath)) result = FileRemove(srcPath); + FileCopy(srcPath, dstPath); + + // Make sure file has been correctly copied before removing + if (FileExists(dstPath) && (GetFileLength(srcPath) == GetFileLength(dstPath))) result = FileRemove(srcPath); else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to copy file to [%s]", srcPath, dstPath); } else TRACELOG(LOG_WARNING, "FILEIO: [%s] Source file does not exist", srcPath); From 06621eb3b7bad68a512391743e0d0026e62ce5a3 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 11:34:58 +0200 Subject: [PATCH 139/185] REVIEWED: Comments for consistency and spelling --- src/external/rlsw.h | 2 +- src/platforms/rcore_android.c | 4 +- src/platforms/rcore_desktop_glfw.c | 6 +-- src/platforms/rcore_desktop_rgfw.c | 6 +-- src/platforms/rcore_desktop_sdl.c | 6 +-- src/platforms/rcore_desktop_win32.c | 4 +- src/platforms/rcore_drm.c | 6 +-- src/platforms/rcore_memory.c | 6 +-- src/platforms/rcore_template.c | 6 +-- src/platforms/rcore_web.c | 6 +-- src/platforms/rcore_web_emscripten.c | 6 +-- src/raudio.c | 14 +++--- src/raylib.h | 67 ++++++++++++++-------------- src/rcore.c | 22 ++++----- src/rmodels.c | 4 +- src/rshapes.c | 2 +- src/rtext.c | 6 +-- src/rtextures.c | 4 +- 18 files changed, 89 insertions(+), 88 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 8f7ab4405..1155eee41 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -153,7 +153,7 @@ #define SW_MAX_TEXTURES 128 #endif -// Enables the use of a lookup table for uint8_t to float conversion +// Enable the use of a lookup table for uint8_t to float conversion // Requires an additional 1KB of global memory // Disabled when SIMD intrinsics are enabled #ifndef SW_USE_COLOR_LUT diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index f501fba8a..c427d7a58 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -616,13 +616,13 @@ void ShowCursor(void) CORE.Input.Mouse.cursorHidden = false; } -// Hides mouse cursor +// Hide mouse cursor void HideCursor(void) { CORE.Input.Mouse.cursorHidden = true; } -// Enables cursor (unlock cursor) +// Enable cursor (unlock cursor) void EnableCursor(void) { // Set cursor position in the middle diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 9b6881d40..c2bd869e7 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1129,7 +1129,7 @@ void ShowCursor(void) CORE.Input.Mouse.cursorHidden = false; } -// Hides mouse cursor +// Hide mouse cursor void HideCursor(void) { glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); @@ -1137,7 +1137,7 @@ void HideCursor(void) CORE.Input.Mouse.cursorHidden = true; } -// Enables cursor (unlock cursor) +// Enable cursor (unlock cursor) void EnableCursor(void) { glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL); @@ -1151,7 +1151,7 @@ void EnableCursor(void) CORE.Input.Mouse.cursorLocked = false; } -// Disables cursor (lock cursor) +// Disable cursor (lock cursor) void DisableCursor(void) { // Reset mouse position within the window area before disabling cursor diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 1a4831bf1..43d80c77d 100755 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -1097,14 +1097,14 @@ void ShowCursor(void) CORE.Input.Mouse.cursorHidden = false; } -// Hides mouse cursor +// Hide mouse cursor void HideCursor(void) { RGFW_window_showMouse(platform.window, false); CORE.Input.Mouse.cursorHidden = true; } -// Enables cursor (unlock cursor) +// Enable cursor (unlock cursor) void EnableCursor(void) { RGFW_window_captureRawMouse(platform.window, false); @@ -1116,7 +1116,7 @@ void EnableCursor(void) CORE.Input.Mouse.cursorLocked = true; } -// Disables cursor (lock cursor) +// Disable cursor (lock cursor) void DisableCursor(void) { RGFW_window_captureRawMouse(platform.window, true); diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 277421720..901b86dd7 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -1227,7 +1227,7 @@ void ShowCursor(void) CORE.Input.Mouse.cursorHidden = false; } -// Hides mouse cursor +// Hide mouse cursor void HideCursor(void) { #if defined(USING_VERSION_SDL3) @@ -1238,7 +1238,7 @@ void HideCursor(void) CORE.Input.Mouse.cursorHidden = true; } -// Enables cursor (unlock cursor) +// Enable cursor (unlock cursor) void EnableCursor(void) { SDL_SetRelativeMouseMode(SDL_FALSE); @@ -1247,7 +1247,7 @@ void EnableCursor(void) CORE.Input.Mouse.cursorLocked = false; } -// Disables cursor (lock cursor) +// Disable cursor (lock cursor) void DisableCursor(void) { SDL_SetRelativeMouseMode(SDL_TRUE); diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index 3f2dcd8e3..86a6c01c0 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -1146,7 +1146,7 @@ void ShowCursor(void) CORE.Input.Mouse.cursorHidden = false; } -// Hides mouse cursor +// Hide mouse cursor void HideCursor(void) { // NOTE: Using SetCursor() instead of ShowCursor() because @@ -1155,7 +1155,7 @@ void HideCursor(void) CORE.Input.Mouse.cursorHidden = true; } -// Enables cursor (unlock cursor) +// Enable cursor (unlock cursor) void EnableCursor(void) { if (CORE.Input.Mouse.cursorLocked) diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index 98c35f7e8..da53223ef 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -561,13 +561,13 @@ void ShowCursor(void) CORE.Input.Mouse.cursorHidden = false; } -// Hides mouse cursor +// Hide mouse cursor void HideCursor(void) { CORE.Input.Mouse.cursorHidden = true; } -// Enables cursor (unlock cursor) +// Enable cursor (unlock cursor) void EnableCursor(void) { // Set cursor position in the middle @@ -577,7 +577,7 @@ void EnableCursor(void) CORE.Input.Mouse.cursorLocked = false; } -// Disables cursor (lock cursor) +// Disable cursor (lock cursor) void DisableCursor(void) { // Set cursor position in the middle diff --git a/src/platforms/rcore_memory.c b/src/platforms/rcore_memory.c index 1512e7bf4..b06187018 100644 --- a/src/platforms/rcore_memory.c +++ b/src/platforms/rcore_memory.c @@ -324,13 +324,13 @@ void ShowCursor(void) CORE.Input.Mouse.cursorHidden = false; } -// Hides mouse cursor +// Hide mouse cursor void HideCursor(void) { CORE.Input.Mouse.cursorHidden = true; } -// Enables cursor (unlock cursor) +// Enable cursor (unlock cursor) void EnableCursor(void) { // Set cursor position in the middle @@ -339,7 +339,7 @@ void EnableCursor(void) CORE.Input.Mouse.cursorHidden = false; } -// Disables cursor (lock cursor) +// Disable cursor (lock cursor) void DisableCursor(void) { // Set cursor position in the middle diff --git a/src/platforms/rcore_template.c b/src/platforms/rcore_template.c index c48484abb..ee766867a 100644 --- a/src/platforms/rcore_template.c +++ b/src/platforms/rcore_template.c @@ -303,13 +303,13 @@ void ShowCursor(void) CORE.Input.Mouse.cursorHidden = false; } -// Hides mouse cursor +// Hide mouse cursor void HideCursor(void) { CORE.Input.Mouse.cursorHidden = true; } -// Enables cursor (unlock cursor) +// Enable cursor (unlock cursor) void EnableCursor(void) { // Set cursor position in the middle @@ -318,7 +318,7 @@ void EnableCursor(void) CORE.Input.Mouse.cursorHidden = false; } -// Disables cursor (lock cursor) +// Disable cursor (lock cursor) void DisableCursor(void) { // Set cursor position in the middle diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index e7e174127..b01672215 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -913,7 +913,7 @@ void ShowCursor(void) } } -// Hides mouse cursor +// Hide mouse cursor void HideCursor(void) { if (!CORE.Input.Mouse.cursorHidden) @@ -924,7 +924,7 @@ void HideCursor(void) } } -// Enables cursor (unlock cursor) +// Enable cursor (unlock cursor) void EnableCursor(void) { emscripten_exit_pointerlock(); @@ -935,7 +935,7 @@ void EnableCursor(void) // NOTE: CORE.Input.Mouse.cursorLocked handled by EmscriptenPointerlockCallback() } -// Disables cursor (lock cursor) +// Disable cursor (lock cursor) void DisableCursor(void) { emscripten_request_pointerlock(platform.canvasId, 1); diff --git a/src/platforms/rcore_web_emscripten.c b/src/platforms/rcore_web_emscripten.c index 186813f49..71388e19b 100644 --- a/src/platforms/rcore_web_emscripten.c +++ b/src/platforms/rcore_web_emscripten.c @@ -891,7 +891,7 @@ void ShowCursor(void) } } -// Hides mouse cursor +// Hide mouse cursor void HideCursor(void) { if (!CORE.Input.Mouse.cursorHidden) @@ -902,7 +902,7 @@ void HideCursor(void) } } -// Enables cursor (unlock cursor) +// Enable cursor (unlock cursor) void EnableCursor(void) { emscripten_exit_pointerlock(); @@ -913,7 +913,7 @@ void EnableCursor(void) // NOTE: CORE.Input.Mouse.cursorLocked handled by EmscriptenPointerlockCallback() } -// Disables cursor (lock cursor) +// Disable cursor (lock cursor) void DisableCursor(void) { emscripten_request_pointerlock(platform.canvasId, 1); diff --git a/src/raudio.c b/src/raudio.c index bae26d734..a007a1092 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -378,7 +378,7 @@ struct rAudioProcessor { rAudioProcessor *prev; // Previous audio processor on the list }; -#define AudioBuffer rAudioBuffer // HACK: To avoid CoreAudio (macOS) symbol collision +#define AudioBuffer rAudioBuffer // WARNING: Renamed to avoid symbol collision with CoreAudio (macOS) AudioBuffer type // Audio data context typedef struct AudioData { @@ -913,7 +913,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int return wave; } -// Checks if wave data is valid (data loaded and parameters) +// Check if wave data is valid (data loaded and parameters) bool IsWaveValid(Wave wave) { bool result = false; @@ -981,7 +981,7 @@ Sound LoadSoundFromWave(Wave wave) return sound; } -// Clone sound from existing sound data, clone does not own wave data +// Load sound alias, clone sound from existing sound data, clone does not own wave data // NOTE: Wave data must be unallocated manually and will be shared across all clones Sound LoadSoundAlias(Sound source) { @@ -1013,7 +1013,7 @@ Sound LoadSoundAlias(Sound source) return sound; } -// Checks if a sound is valid (data loaded and buffers initialized) +// Check if a sound is valid (data loaded and buffers initialized) bool IsSoundValid(Sound sound) { bool result = false; @@ -1750,7 +1750,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, return music; } -// Checks if a music stream is valid (context and buffers initialized) +// Check if a music stream is valid (context and buffers initialized) bool IsMusicValid(Music music) { return ((music.ctxData != NULL) && // Validate context loaded @@ -2067,7 +2067,7 @@ void SetMusicPitch(Music music, float pitch) SetAudioBufferPitch(music.stream.buffer, pitch); } -// Set pan for a music +// Set pan for music void SetMusicPan(Music music, float pan) { SetAudioBufferPan(music.stream.buffer, pan); @@ -2155,7 +2155,7 @@ AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, un return stream; } -// Checks if an audio stream is valid (buffers initialized) +// Check if an audio stream is valid (buffers initialized) bool IsAudioStreamValid(AudioStream stream) { return ((stream.buffer != NULL) && // Validate stream buffer diff --git a/src/raylib.h b/src/raylib.h index 4ae5a4e47..3795de752 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1034,23 +1034,23 @@ RLAPI void EnableEventWaiting(void); // Enable wait RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling // Cursor-related functions -RLAPI void ShowCursor(void); // Shows cursor -RLAPI void HideCursor(void); // Hides cursor +RLAPI void ShowCursor(void); // Show cursor +RLAPI void HideCursor(void); // Hide cursor RLAPI bool IsCursorHidden(void); // Check if cursor is not visible -RLAPI void EnableCursor(void); // Enables cursor (unlock cursor) -RLAPI void DisableCursor(void); // Disables cursor (lock cursor) +RLAPI void EnableCursor(void); // Enable cursor (unlock cursor) +RLAPI void DisableCursor(void); // Disable cursor (lock cursor) RLAPI bool IsCursorOnScreen(void); // Check if cursor is on the screen // Drawing-related functions -RLAPI void ClearBackground(Color color); // Set background color (framebuffer clear color) -RLAPI void BeginDrawing(void); // Setup canvas (framebuffer) to start drawing -RLAPI void EndDrawing(void); // End canvas drawing and swap buffers (double buffering) +RLAPI void ClearBackground(Color color); // Clear background (framebuffer) to color +RLAPI void BeginDrawing(void); // Begin canvas (framebuffer) drawing +RLAPI void EndDrawing(void); // End canvas (framebuffer) drawing and swap buffers (double buffering) RLAPI void BeginMode2D(Camera2D camera); // Begin 2D mode with custom camera (2D) -RLAPI void EndMode2D(void); // Ends 2D mode with custom camera +RLAPI void EndMode2D(void); // End 2D mode with custom camera RLAPI void BeginMode3D(Camera3D camera); // Begin 3D mode with custom camera (3D) -RLAPI void EndMode3D(void); // Ends 3D mode and returns to default 2D orthographic mode +RLAPI void EndMode3D(void); // End 3D mode and returns to default 2D orthographic mode RLAPI void BeginTextureMode(RenderTexture2D target); // Begin drawing to render texture -RLAPI void EndTextureMode(void); // Ends drawing to render texture +RLAPI void EndTextureMode(void); // End drawing to render texture RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader) RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied, subtract, custom) @@ -1081,10 +1081,10 @@ RLAPI void UnloadShader(Shader shader); // Un #define GetMouseRay GetScreenToWorldRay // Compatibility hack for previous raylib versions RLAPI Ray GetScreenToWorldRay(Vector2 position, Camera camera); // Get a ray trace from screen position (i.e mouse) RLAPI Ray GetScreenToWorldRayEx(Vector2 position, Camera camera, int width, int height); // Get a ray trace from screen position (i.e mouse) in a viewport -RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get the screen space position for a 3d world space position -RLAPI Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height); // Get size position for a 3d world space position -RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the screen space position for a 2d camera world space position -RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get the world space position for a 2d camera screen space position +RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get screen space position for a 3d world space position +RLAPI Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height); // Get sized screen space position for a 3d world space position +RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get screen space position for a 2d camera world space position +RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get world space position for a 2d camera screen space position RLAPI Matrix GetCameraMatrix(Camera camera); // Get camera transform matrix (view matrix) RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix @@ -1110,7 +1110,7 @@ RLAPI void UnloadRandomSequence(int *sequence); // Unload random values // Misc. functions RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format) -RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS) +RLAPI void SetConfigFlags(unsigned int flags); // Set up init configuration flags (view FLAGS) RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available) // Logging system @@ -1245,7 +1245,7 @@ RLAPI int GetTouchPointCount(void); // Get number of t // Gestures and Touch Handling Functions (Module: rgestures) //------------------------------------------------------------------------------------ RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags -RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected +RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture has been detected RLAPI int GetGestureDetected(void); // Get latest detected gesture RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector @@ -1302,12 +1302,13 @@ RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color c RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle lines with rounded edges -RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline +RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle lines with rounded edges outline RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) +RLAPI void DrawTriangleGradient(Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors (vertex in counter-clockwise order!) RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!) RLAPI void DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center) RLAPI void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points -RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version) +RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon of n sides RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters @@ -1334,7 +1335,7 @@ RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vect RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle -RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created betweeen two points [p1] and [p2] +RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created between two points [p1] and [p2] RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle @@ -1355,7 +1356,7 @@ RLAPI Image LoadImageAnim(const char *fileName, int *frames); RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png' RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data -RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot) +RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer (screenshot) RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters) RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM) RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success @@ -1460,7 +1461,7 @@ RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters RLAPI void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters -RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely +RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a texture (or part of it) that stretches or shrinks nicely // Color/pixel related functions RLAPI bool ColorIsEqual(Color col1, Color col2); // Check if two colors are equal @@ -1504,7 +1505,7 @@ RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color co RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation) RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint) -RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint) +RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple characters (codepoint) // Text font info functions RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks @@ -1532,7 +1533,7 @@ RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n') RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied -RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal +RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text strings are equal RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style) RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string @@ -1668,15 +1669,15 @@ RLAPI float GetMasterVolume(void); // Get mas // Wave/Sound loading/unloading functions RLAPI Wave LoadWave(const char *fileName); // Load wave data from file RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav' -RLAPI bool IsWaveValid(Wave wave); // Checks if wave data is valid (data loaded and parameters) +RLAPI bool IsWaveValid(Wave wave); // Check if wave data is valid (data loaded and parameters) RLAPI Sound LoadSound(const char *fileName); // Load sound from file RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data -RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data -RLAPI bool IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized) RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data (default data format: 32 bit float, stereo) +RLAPI Sound LoadSoundAlias(Sound source); // Load sound alias, new sound that shares the same sample data as the source sound, does not own the sound data +RLAPI bool IsSoundValid(Sound sound); // Check if a sound is valid (data loaded and buffers initialized) RLAPI void UnloadWave(Wave wave); // Unload wave data RLAPI void UnloadSound(Sound sound); // Unload sound -RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data) +RLAPI void UnloadSoundAlias(Sound alias); // Unload sound alias (does not deallocate sample data) RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success @@ -1698,24 +1699,24 @@ RLAPI void UnloadWaveSamples(float *samples); // Unload // Music management functions RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data -RLAPI bool IsMusicValid(Music music); // Checks if a music stream is valid (context and buffers initialized) +RLAPI bool IsMusicValid(Music music); // Check if a music stream is valid (context and buffers initialized) RLAPI void UnloadMusicStream(Music music); // Unload music stream RLAPI void PlayMusicStream(Music music); // Start music playing RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing -RLAPI void UpdateMusicStream(Music music); // Updates buffers for music streaming +RLAPI void UpdateMusicStream(Music music); // Update buffers for music streaming RLAPI void StopMusicStream(Music music); // Stop music playing RLAPI void PauseMusicStream(Music music); // Pause music playing RLAPI void ResumeMusicStream(Music music); // Resume playing paused music RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds) RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level) -RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level) -RLAPI void SetMusicPan(Music music, float pan); // Set pan for a music (-1.0 left, 0.0 center, 1.0 right) +RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for music (1.0 is base level) +RLAPI void SetMusicPan(Music music, float pan); // Set pan for music (-1.0 left, 0.0 center, 1.0 right) RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds) RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds) // AudioStream management functions RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data) -RLAPI bool IsAudioStreamValid(AudioStream stream); // Checks if an audio stream is valid (buffers initialized) +RLAPI bool IsAudioStreamValid(AudioStream stream); // Check if an audio stream is valid (buffers initialized) RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill @@ -1726,7 +1727,7 @@ RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check i RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level) RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level) -RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered) +RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (-1.0 left, 0.0 center, 1.0 right) RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data diff --git a/src/rcore.c b/src/rcore.c index 085c2a064..b5040089b 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -869,14 +869,14 @@ bool IsCursorOnScreen(void) // Module Functions Definition: Screen Drawing //---------------------------------------------------------------------------------- -// Set background color (framebuffer clear color) +// Clear background (framebuffer) to color void ClearBackground(Color color) { rlClearColor(color.r, color.g, color.b, color.a); // Set clear color rlClearScreenBuffers(); // Clear current framebuffers } -// Setup canvas (framebuffer) to start drawing +// Begin canvas (framebuffer) drawing void BeginDrawing(void) { // WARNING: Previously to BeginDrawing() other render textures drawing could happen, @@ -893,7 +893,7 @@ void BeginDrawing(void) // NOTE: Not required with OpenGL 3.3+ } -// End canvas drawing and swap buffers (double buffering) +// End canvas (framebuffer) drawing and swap buffers (double buffering) void EndDrawing(void) { rlDrawRenderBatchActive(); // Update and draw internal render batch @@ -949,7 +949,7 @@ void BeginMode2D(Camera2D camera) rlMultMatrixf(MatrixToFloat(GetCameraMatrix2D(camera))); } -// Ends 2D mode with custom camera +// End 2D mode with custom camera void EndMode2D(void) { rlDrawRenderBatchActive(); // Update and draw internal render batch @@ -998,7 +998,7 @@ void BeginMode3D(Camera camera) rlEnableDepthTest(); // Enable DEPTH_TEST for 3D } -// Ends 3D mode and returns to default 2D orthographic mode +// End 3D mode and returns to default 2D orthographic mode void EndMode3D(void) { rlDrawRenderBatchActive(); // Update and draw internal render batch @@ -1045,7 +1045,7 @@ void BeginTextureMode(RenderTexture2D target) CORE.Window.usingFbo = true; } -// Ends drawing to render texture +// End drawing to render texture void EndTextureMode(void) { rlDrawRenderBatchActive(); // Update and draw internal render batch @@ -1514,7 +1514,7 @@ Matrix GetCameraMatrix2D(Camera2D camera) return matTransform; } -// Get the screen space position from a 3d world space position +// Get screen space position from a 3d world space position Vector2 GetWorldToScreen(Vector3 position, Camera camera) { Vector2 screenPosition = GetWorldToScreenEx(position, camera, GetScreenWidth(), GetScreenHeight()); @@ -1522,7 +1522,7 @@ Vector2 GetWorldToScreen(Vector3 position, Camera camera) return screenPosition; } -// Get size position for a 3d world space position (useful for texture drawing) +// Get sized screen space position for a 3d world space position (useful for texture drawing) Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height) { // Calculate projection matrix (from perspective instead of frustum @@ -1564,7 +1564,7 @@ Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int heigh return screenPosition; } -// Get the screen space position for a 2d camera world space position +// Get screen space position for a 2d camera world space position Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera) { Matrix matCamera = GetCameraMatrix2D(camera); @@ -1573,7 +1573,7 @@ Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera) return (Vector2){ transform.x, transform.y }; } -// Get the world space position for a 2d camera screen space position +// Get world space position for a 2d camera screen space position Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera) { Matrix invMatCamera = MatrixInvert(GetCameraMatrix2D(camera)); @@ -1853,7 +1853,7 @@ void TakeScreenshot(const char *fileName) #endif } -// Setup window configuration flags (view FLAGS) +// Set up window configuration flags (view FLAGS) // NOTE: This function is expected to be called before window creation, // because it sets up some flags for the window creation process // To configure window states after creation, use SetWindowState() diff --git a/src/rmodels.c b/src/rmodels.c index 8288c3172..bcc481962 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -85,7 +85,7 @@ #define VOX_FREE RL_FREE #define VOX_LOADER_IMPLEMENTATION - #include "external/vox_loader.h" // VOX file format loading (MagikaVoxel) + #include "external/vox_loader.h" // VOX file format loading (MagicaVoxel) #endif #if SUPPORT_FILEFORMAT_M3D @@ -3936,7 +3936,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota Color colDiffuse = mat.maps[MATERIAL_MAP_DIFFUSE].color; // Applying color tint directly to material diffuse map, - // because is comes as an input paramter to the function + // because it comes as an input parameter to the function Color colTinted = { 0 }; colTinted.r = (unsigned char)(((int)colDiffuse.r*(int)tint.r)/255); colTinted.g = (unsigned char)(((int)colDiffuse.g*(int)tint.g)/255); diff --git a/src/rshapes.c b/src/rshapes.c index de7476ce9..f09b972eb 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -1531,7 +1531,7 @@ void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color) } } -// Draw a regular polygon of n sides (Vector version) +// Draw a polygon of n sides void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color) { if (sides < 3) sides = 3; diff --git a/src/rtext.c b/src/rtext.c index 7b9d5f2c8..dbf411ad0 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -156,7 +156,7 @@ extern void LoadFontDefault(void) { #define BIT_CHECK(a,b) ((a) & (1u << (b))) - // Check to see if the font for an image has alreeady been allocated, + // Check to see if the font for an image has already been allocated, // and if no need to upload, then return if (defaultFont.glyphs != NULL) return; @@ -1279,7 +1279,7 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz DrawTexturePro(font.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, tint); } -// Draw multiple character (codepoints) +// Draw multiple characters (codepoints) void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint) { float textOffsetY = 0; // Offset between lines (on linebreak '\n') @@ -1674,7 +1674,7 @@ int TextCopy(char *dst, const char *src) return bytes; } -// Check if two text string are equal +// Check if two text strings are equal // REQUIRES: strcmp() bool TextIsEqual(const char *text1, const char *text2) { diff --git a/src/rtextures.c b/src/rtextures.c index bfe9efe36..45282ec20 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -580,7 +580,7 @@ Image LoadImageFromTexture(Texture2D texture) return image; } -// Load image from screen buffer and (screenshot) +// Load image from screen buffer (screenshot) Image LoadImageFromScreen(void) { Image image = { 0 }; @@ -4624,7 +4624,7 @@ void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 } } -// Draws a texture (or part of it) that stretches or shrinks nicely using n-patch info +// Draw a texture (or part of it) that stretches or shrinks nicely using n-patch info void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint) { if (texture.id > 0) From 52dc7658daa9a0e05d65fb31664c126774bfbed9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:35:19 +0000 Subject: [PATCH 140/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 137 +++-- tools/rlparser/output/raylib_api.lua | 107 ++-- tools/rlparser/output/raylib_api.txt | 780 +++++++++++++------------- tools/rlparser/output/raylib_api.xml | 84 +-- 4 files changed, 585 insertions(+), 523 deletions(-) diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index f79961a15..7bb3ca5a3 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -3573,12 +3573,12 @@ }, { "name": "ShowCursor", - "description": "Shows cursor", + "description": "Show cursor", "returnType": "void" }, { "name": "HideCursor", - "description": "Hides cursor", + "description": "Hide cursor", "returnType": "void" }, { @@ -3588,12 +3588,12 @@ }, { "name": "EnableCursor", - "description": "Enables cursor (unlock cursor)", + "description": "Enable cursor (unlock cursor)", "returnType": "void" }, { "name": "DisableCursor", - "description": "Disables cursor (lock cursor)", + "description": "Disable cursor (lock cursor)", "returnType": "void" }, { @@ -3603,7 +3603,7 @@ }, { "name": "ClearBackground", - "description": "Set background color (framebuffer clear color)", + "description": "Clear background (framebuffer) to color", "returnType": "void", "params": [ { @@ -3614,12 +3614,12 @@ }, { "name": "BeginDrawing", - "description": "Setup canvas (framebuffer) to start drawing", + "description": "Begin canvas (framebuffer) drawing", "returnType": "void" }, { "name": "EndDrawing", - "description": "End canvas drawing and swap buffers (double buffering)", + "description": "End canvas (framebuffer) drawing and swap buffers (double buffering)", "returnType": "void" }, { @@ -3635,7 +3635,7 @@ }, { "name": "EndMode2D", - "description": "Ends 2D mode with custom camera", + "description": "End 2D mode with custom camera", "returnType": "void" }, { @@ -3651,7 +3651,7 @@ }, { "name": "EndMode3D", - "description": "Ends 3D mode and returns to default 2D orthographic mode", + "description": "End 3D mode and returns to default 2D orthographic mode", "returnType": "void" }, { @@ -3667,7 +3667,7 @@ }, { "name": "EndTextureMode", - "description": "Ends drawing to render texture", + "description": "End drawing to render texture", "returnType": "void" }, { @@ -3978,7 +3978,7 @@ }, { "name": "GetWorldToScreen", - "description": "Get the screen space position for a 3d world space position", + "description": "Get screen space position for a 3d world space position", "returnType": "Vector2", "params": [ { @@ -3993,7 +3993,7 @@ }, { "name": "GetWorldToScreenEx", - "description": "Get size position for a 3d world space position", + "description": "Get sized screen space position for a 3d world space position", "returnType": "Vector2", "params": [ { @@ -4016,7 +4016,7 @@ }, { "name": "GetWorldToScreen2D", - "description": "Get the screen space position for a 2d camera world space position", + "description": "Get screen space position for a 2d camera world space position", "returnType": "Vector2", "params": [ { @@ -4031,7 +4031,7 @@ }, { "name": "GetScreenToWorld2D", - "description": "Get the world space position for a 2d camera screen space position", + "description": "Get world space position for a 2d camera screen space position", "returnType": "Vector2", "params": [ { @@ -4182,7 +4182,7 @@ }, { "name": "SetConfigFlags", - "description": "Setup init configuration flags (view FLAGS)", + "description": "Set up init configuration flags (view FLAGS)", "returnType": "void", "params": [ { @@ -5401,7 +5401,7 @@ }, { "name": "IsGestureDetected", - "description": "Check if a gesture have been detected", + "description": "Check if a gesture has been detected", "returnType": "bool", "params": [ { @@ -6281,7 +6281,7 @@ }, { "name": "DrawRectangleRoundedLinesEx", - "description": "Draw rectangle with rounded edges outline", + "description": "Draw rectangle lines with rounded edges outline", "returnType": "void", "params": [ { @@ -6329,6 +6329,37 @@ } ] }, + { + "name": "DrawTriangleGradient", + "description": "Draw triangle with interpolated colors (vertex in counter-clockwise order!)", + "returnType": "void", + "params": [ + { + "type": "Vector2", + "name": "v1" + }, + { + "type": "Vector2", + "name": "v2" + }, + { + "type": "Vector2", + "name": "v3" + }, + { + "type": "Color", + "name": "c1" + }, + { + "type": "Color", + "name": "c2" + }, + { + "type": "Color", + "name": "c3" + } + ] + }, { "name": "DrawTriangleLines", "description": "Draw triangle outline (vertex in counter-clockwise order!)", @@ -6392,7 +6423,7 @@ }, { "name": "DrawPoly", - "description": "Draw a regular polygon (Vector version)", + "description": "Draw a polygon of n sides", "returnType": "void", "params": [ { @@ -6915,7 +6946,7 @@ }, { "name": "CheckCollisionCircleLine", - "description": "Check if circle collides with a line created betweeen two points [p1] and [p2]", + "description": "Check if circle collides with a line created between two points [p1] and [p2]", "returnType": "bool", "params": [ { @@ -7185,7 +7216,7 @@ }, { "name": "LoadImageFromScreen", - "description": "Load image from screen buffer and (screenshot)", + "description": "Load image from screen buffer (screenshot)", "returnType": "Image" }, { @@ -8896,7 +8927,7 @@ }, { "name": "DrawTextureNPatch", - "description": "Draws a texture (or part of it) that stretches or shrinks nicely", + "description": "Draw a texture (or part of it) that stretches or shrinks nicely", "returnType": "void", "params": [ { @@ -9528,7 +9559,7 @@ }, { "name": "DrawTextCodepoints", - "description": "Draw multiple character (codepoint)", + "description": "Draw multiple characters (codepoint)", "returnType": "void", "params": [ { @@ -9852,7 +9883,7 @@ }, { "name": "TextIsEqual", - "description": "Check if two text string are equal", + "description": "Check if two text strings are equal", "returnType": "bool", "params": [ { @@ -11747,7 +11778,7 @@ }, { "name": "IsWaveValid", - "description": "Checks if wave data is valid (data loaded and parameters)", + "description": "Check if wave data is valid (data loaded and parameters)", "returnType": "bool", "params": [ { @@ -11778,28 +11809,6 @@ } ] }, - { - "name": "LoadSoundAlias", - "description": "Create a new sound that shares the same sample data as the source sound, does not own the sound data", - "returnType": "Sound", - "params": [ - { - "type": "Sound", - "name": "source" - } - ] - }, - { - "name": "IsSoundValid", - "description": "Checks if a sound is valid (data loaded and buffers initialized)", - "returnType": "bool", - "params": [ - { - "type": "Sound", - "name": "sound" - } - ] - }, { "name": "UpdateSound", "description": "Update sound buffer with new data (default data format: 32 bit float, stereo)", @@ -11819,6 +11828,28 @@ } ] }, + { + "name": "LoadSoundAlias", + "description": "Load sound alias, new sound that shares the same sample data as the source sound, does not own the sound data", + "returnType": "Sound", + "params": [ + { + "type": "Sound", + "name": "source" + } + ] + }, + { + "name": "IsSoundValid", + "description": "Check if a sound is valid (data loaded and buffers initialized)", + "returnType": "bool", + "params": [ + { + "type": "Sound", + "name": "sound" + } + ] + }, { "name": "UnloadWave", "description": "Unload wave data", @@ -11843,7 +11874,7 @@ }, { "name": "UnloadSoundAlias", - "description": "Unload a sound alias (does not deallocate sample data)", + "description": "Unload sound alias (does not deallocate sample data)", "returnType": "void", "params": [ { @@ -12089,7 +12120,7 @@ }, { "name": "IsMusicValid", - "description": "Checks if a music stream is valid (context and buffers initialized)", + "description": "Check if a music stream is valid (context and buffers initialized)", "returnType": "bool", "params": [ { @@ -12133,7 +12164,7 @@ }, { "name": "UpdateMusicStream", - "description": "Updates buffers for music streaming", + "description": "Update buffers for music streaming", "returnType": "void", "params": [ { @@ -12207,7 +12238,7 @@ }, { "name": "SetMusicPitch", - "description": "Set pitch for a music (1.0 is base level)", + "description": "Set pitch for music (1.0 is base level)", "returnType": "void", "params": [ { @@ -12222,7 +12253,7 @@ }, { "name": "SetMusicPan", - "description": "Set pan for a music (-1.0 left, 0.0 center, 1.0 right)", + "description": "Set pan for music (-1.0 left, 0.0 center, 1.0 right)", "returnType": "void", "params": [ { @@ -12278,7 +12309,7 @@ }, { "name": "IsAudioStreamValid", - "description": "Checks if an audio stream is valid (buffers initialized)", + "description": "Check if an audio stream is valid (buffers initialized)", "returnType": "bool", "params": [ { @@ -12415,7 +12446,7 @@ }, { "name": "SetAudioStreamPan", - "description": "Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered)", + "description": "Set pan for audio stream (-1.0 left, 0.0 center, 1.0 right)", "returnType": "void", "params": [ { diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index 2825e5244..7a6bb8b06 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -3450,12 +3450,12 @@ return { }, { name = "ShowCursor", - description = "Shows cursor", + description = "Show cursor", returnType = "void" }, { name = "HideCursor", - description = "Hides cursor", + description = "Hide cursor", returnType = "void" }, { @@ -3465,12 +3465,12 @@ return { }, { name = "EnableCursor", - description = "Enables cursor (unlock cursor)", + description = "Enable cursor (unlock cursor)", returnType = "void" }, { name = "DisableCursor", - description = "Disables cursor (lock cursor)", + description = "Disable cursor (lock cursor)", returnType = "void" }, { @@ -3480,7 +3480,7 @@ return { }, { name = "ClearBackground", - description = "Set background color (framebuffer clear color)", + description = "Clear background (framebuffer) to color", returnType = "void", params = { {type = "Color", name = "color"} @@ -3488,12 +3488,12 @@ return { }, { name = "BeginDrawing", - description = "Setup canvas (framebuffer) to start drawing", + description = "Begin canvas (framebuffer) drawing", returnType = "void" }, { name = "EndDrawing", - description = "End canvas drawing and swap buffers (double buffering)", + description = "End canvas (framebuffer) drawing and swap buffers (double buffering)", returnType = "void" }, { @@ -3506,7 +3506,7 @@ return { }, { name = "EndMode2D", - description = "Ends 2D mode with custom camera", + description = "End 2D mode with custom camera", returnType = "void" }, { @@ -3519,7 +3519,7 @@ return { }, { name = "EndMode3D", - description = "Ends 3D mode and returns to default 2D orthographic mode", + description = "End 3D mode and returns to default 2D orthographic mode", returnType = "void" }, { @@ -3532,7 +3532,7 @@ return { }, { name = "EndTextureMode", - description = "Ends drawing to render texture", + description = "End drawing to render texture", returnType = "void" }, { @@ -3723,7 +3723,7 @@ return { }, { name = "GetWorldToScreen", - description = "Get the screen space position for a 3d world space position", + description = "Get screen space position for a 3d world space position", returnType = "Vector2", params = { {type = "Vector3", name = "position"}, @@ -3732,7 +3732,7 @@ return { }, { name = "GetWorldToScreenEx", - description = "Get size position for a 3d world space position", + description = "Get sized screen space position for a 3d world space position", returnType = "Vector2", params = { {type = "Vector3", name = "position"}, @@ -3743,7 +3743,7 @@ return { }, { name = "GetWorldToScreen2D", - description = "Get the screen space position for a 2d camera world space position", + description = "Get screen space position for a 2d camera world space position", returnType = "Vector2", params = { {type = "Vector2", name = "position"}, @@ -3752,7 +3752,7 @@ return { }, { name = "GetScreenToWorld2D", - description = "Get the world space position for a 2d camera screen space position", + description = "Get world space position for a 2d camera screen space position", returnType = "Vector2", params = { {type = "Vector2", name = "position"}, @@ -3861,7 +3861,7 @@ return { }, { name = "SetConfigFlags", - description = "Setup init configuration flags (view FLAGS)", + description = "Set up init configuration flags (view FLAGS)", returnType = "void", params = { {type = "unsigned int", name = "flags"} @@ -4690,7 +4690,7 @@ return { }, { name = "IsGestureDetected", - description = "Check if a gesture have been detected", + description = "Check if a gesture has been detected", returnType = "bool", params = { {type = "unsigned int", name = "gesture"} @@ -5129,7 +5129,7 @@ return { }, { name = "DrawRectangleRoundedLinesEx", - description = "Draw rectangle with rounded edges outline", + description = "Draw rectangle lines with rounded edges outline", returnType = "void", params = { {type = "Rectangle", name = "rec"}, @@ -5150,6 +5150,19 @@ return { {type = "Color", name = "color"} } }, + { + name = "DrawTriangleGradient", + description = "Draw triangle with interpolated colors (vertex in counter-clockwise order!)", + returnType = "void", + params = { + {type = "Vector2", name = "v1"}, + {type = "Vector2", name = "v2"}, + {type = "Vector2", name = "v3"}, + {type = "Color", name = "c1"}, + {type = "Color", name = "c2"}, + {type = "Color", name = "c3"} + } + }, { name = "DrawTriangleLines", description = "Draw triangle outline (vertex in counter-clockwise order!)", @@ -5183,7 +5196,7 @@ return { }, { name = "DrawPoly", - description = "Draw a regular polygon (Vector version)", + description = "Draw a polygon of n sides", returnType = "void", params = { {type = "Vector2", name = "center"}, @@ -5424,7 +5437,7 @@ return { }, { name = "CheckCollisionCircleLine", - description = "Check if circle collides with a line created betweeen two points [p1] and [p2]", + description = "Check if circle collides with a line created between two points [p1] and [p2]", returnType = "bool", params = { {type = "Vector2", name = "center"}, @@ -5565,7 +5578,7 @@ return { }, { name = "LoadImageFromScreen", - description = "Load image from screen buffer and (screenshot)", + description = "Load image from screen buffer (screenshot)", returnType = "Image" }, { @@ -6469,7 +6482,7 @@ return { }, { name = "DrawTextureNPatch", - description = "Draws a texture (or part of it) that stretches or shrinks nicely", + description = "Draw a texture (or part of it) that stretches or shrinks nicely", returnType = "void", params = { {type = "Texture2D", name = "texture"}, @@ -6804,7 +6817,7 @@ return { }, { name = "DrawTextCodepoints", - description = "Draw multiple character (codepoint)", + description = "Draw multiple characters (codepoint)", returnType = "void", params = { {type = "Font", name = "font"}, @@ -6990,7 +7003,7 @@ return { }, { name = "TextIsEqual", - description = "Check if two text string are equal", + description = "Check if two text strings are equal", returnType = "bool", params = { {type = "const char *", name = "text1"}, @@ -7997,7 +8010,7 @@ return { }, { name = "IsWaveValid", - description = "Checks if wave data is valid (data loaded and parameters)", + description = "Check if wave data is valid (data loaded and parameters)", returnType = "bool", params = { {type = "Wave", name = "wave"} @@ -8019,22 +8032,6 @@ return { {type = "Wave", name = "wave"} } }, - { - name = "LoadSoundAlias", - description = "Create a new sound that shares the same sample data as the source sound, does not own the sound data", - returnType = "Sound", - params = { - {type = "Sound", name = "source"} - } - }, - { - name = "IsSoundValid", - description = "Checks if a sound is valid (data loaded and buffers initialized)", - returnType = "bool", - params = { - {type = "Sound", name = "sound"} - } - }, { name = "UpdateSound", description = "Update sound buffer with new data (default data format: 32 bit float, stereo)", @@ -8045,6 +8042,22 @@ return { {type = "int", name = "sampleCount"} } }, + { + name = "LoadSoundAlias", + description = "Load sound alias, new sound that shares the same sample data as the source sound, does not own the sound data", + returnType = "Sound", + params = { + {type = "Sound", name = "source"} + } + }, + { + name = "IsSoundValid", + description = "Check if a sound is valid (data loaded and buffers initialized)", + returnType = "bool", + params = { + {type = "Sound", name = "sound"} + } + }, { name = "UnloadWave", description = "Unload wave data", @@ -8063,7 +8076,7 @@ return { }, { name = "UnloadSoundAlias", - description = "Unload a sound alias (does not deallocate sample data)", + description = "Unload sound alias (does not deallocate sample data)", returnType = "void", params = { {type = "Sound", name = "alias"} @@ -8219,7 +8232,7 @@ return { }, { name = "IsMusicValid", - description = "Checks if a music stream is valid (context and buffers initialized)", + description = "Check if a music stream is valid (context and buffers initialized)", returnType = "bool", params = { {type = "Music", name = "music"} @@ -8251,7 +8264,7 @@ return { }, { name = "UpdateMusicStream", - description = "Updates buffers for music streaming", + description = "Update buffers for music streaming", returnType = "void", params = { {type = "Music", name = "music"} @@ -8301,7 +8314,7 @@ return { }, { name = "SetMusicPitch", - description = "Set pitch for a music (1.0 is base level)", + description = "Set pitch for music (1.0 is base level)", returnType = "void", params = { {type = "Music", name = "music"}, @@ -8310,7 +8323,7 @@ return { }, { name = "SetMusicPan", - description = "Set pan for a music (-1.0 left, 0.0 center, 1.0 right)", + description = "Set pan for music (-1.0 left, 0.0 center, 1.0 right)", returnType = "void", params = { {type = "Music", name = "music"}, @@ -8345,7 +8358,7 @@ return { }, { name = "IsAudioStreamValid", - description = "Checks if an audio stream is valid (buffers initialized)", + description = "Check if an audio stream is valid (buffers initialized)", returnType = "bool", params = { {type = "AudioStream", name = "stream"} @@ -8437,7 +8450,7 @@ return { }, { name = "SetAudioStreamPan", - description = "Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered)", + description = "Set pan for audio stream (-1.0 left, 0.0 center, 1.0 right)", returnType = "void", params = { {type = "AudioStream", name = "stream"}, diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index c428650e8..7df03e619 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -1000,7 +1000,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 600 +Functions found: 601 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -1257,12 +1257,12 @@ Function 049: DisableEventWaiting() (0 input parameters) Function 050: ShowCursor() (0 input parameters) Name: ShowCursor Return type: void - Description: Shows cursor + Description: Show cursor No input parameters Function 051: HideCursor() (0 input parameters) Name: HideCursor Return type: void - Description: Hides cursor + Description: Hide cursor No input parameters Function 052: IsCursorHidden() (0 input parameters) Name: IsCursorHidden @@ -1272,12 +1272,12 @@ Function 052: IsCursorHidden() (0 input parameters) Function 053: EnableCursor() (0 input parameters) Name: EnableCursor Return type: void - Description: Enables cursor (unlock cursor) + Description: Enable cursor (unlock cursor) No input parameters Function 054: DisableCursor() (0 input parameters) Name: DisableCursor Return type: void - Description: Disables cursor (lock cursor) + Description: Disable cursor (lock cursor) No input parameters Function 055: IsCursorOnScreen() (0 input parameters) Name: IsCursorOnScreen @@ -1287,17 +1287,17 @@ Function 055: IsCursorOnScreen() (0 input parameters) Function 056: ClearBackground() (1 input parameters) Name: ClearBackground Return type: void - Description: Set background color (framebuffer clear color) + Description: Clear background (framebuffer) to color Param[1]: color (type: Color) Function 057: BeginDrawing() (0 input parameters) Name: BeginDrawing Return type: void - Description: Setup canvas (framebuffer) to start drawing + Description: Begin canvas (framebuffer) drawing No input parameters Function 058: EndDrawing() (0 input parameters) Name: EndDrawing Return type: void - Description: End canvas drawing and swap buffers (double buffering) + Description: End canvas (framebuffer) drawing and swap buffers (double buffering) No input parameters Function 059: BeginMode2D() (1 input parameters) Name: BeginMode2D @@ -1307,7 +1307,7 @@ Function 059: BeginMode2D() (1 input parameters) Function 060: EndMode2D() (0 input parameters) Name: EndMode2D Return type: void - Description: Ends 2D mode with custom camera + Description: End 2D mode with custom camera No input parameters Function 061: BeginMode3D() (1 input parameters) Name: BeginMode3D @@ -1317,7 +1317,7 @@ Function 061: BeginMode3D() (1 input parameters) Function 062: EndMode3D() (0 input parameters) Name: EndMode3D Return type: void - Description: Ends 3D mode and returns to default 2D orthographic mode + Description: End 3D mode and returns to default 2D orthographic mode No input parameters Function 063: BeginTextureMode() (1 input parameters) Name: BeginTextureMode @@ -1327,7 +1327,7 @@ Function 063: BeginTextureMode() (1 input parameters) Function 064: EndTextureMode() (0 input parameters) Name: EndTextureMode Return type: void - Description: Ends drawing to render texture + Description: End drawing to render texture No input parameters Function 065: BeginShaderMode() (1 input parameters) Name: BeginShaderMode @@ -1464,13 +1464,13 @@ Function 086: GetScreenToWorldRayEx() (4 input parameters) Function 087: GetWorldToScreen() (2 input parameters) Name: GetWorldToScreen Return type: Vector2 - Description: Get the screen space position for a 3d world space position + Description: Get screen space position for a 3d world space position Param[1]: position (type: Vector3) Param[2]: camera (type: Camera) Function 088: GetWorldToScreenEx() (4 input parameters) Name: GetWorldToScreenEx Return type: Vector2 - Description: Get size position for a 3d world space position + Description: Get sized screen space position for a 3d world space position Param[1]: position (type: Vector3) Param[2]: camera (type: Camera) Param[3]: width (type: int) @@ -1478,13 +1478,13 @@ Function 088: GetWorldToScreenEx() (4 input parameters) Function 089: GetWorldToScreen2D() (2 input parameters) Name: GetWorldToScreen2D Return type: Vector2 - Description: Get the screen space position for a 2d camera world space position + Description: Get screen space position for a 2d camera world space position Param[1]: position (type: Vector2) Param[2]: camera (type: Camera2D) Function 090: GetScreenToWorld2D() (2 input parameters) Name: GetScreenToWorld2D Return type: Vector2 - Description: Get the world space position for a 2d camera screen space position + Description: Get world space position for a 2d camera screen space position Param[1]: position (type: Vector2) Param[2]: camera (type: Camera2D) Function 091: GetCameraMatrix() (1 input parameters) @@ -1563,7 +1563,7 @@ Function 104: TakeScreenshot() (1 input parameters) Function 105: SetConfigFlags() (1 input parameters) Name: SetConfigFlags Return type: void - Description: Setup init configuration flags (view FLAGS) + Description: Set up init configuration flags (view FLAGS) Param[1]: flags (type: unsigned int) Function 106: OpenURL() (1 input parameters) Name: OpenURL @@ -2131,7 +2131,7 @@ Function 209: SetGesturesEnabled() (1 input parameters) Function 210: IsGestureDetected() (1 input parameters) Name: IsGestureDetected Return type: bool - Description: Check if a gesture have been detected + Description: Check if a gesture has been detected Param[1]: gesture (type: unsigned int) Function 211: GetGestureDetected() (0 input parameters) Name: GetGestureDetected @@ -2462,7 +2462,7 @@ Function 253: DrawRectangleRoundedLines() (4 input parameters) Function 254: DrawRectangleRoundedLinesEx() (5 input parameters) Name: DrawRectangleRoundedLinesEx Return type: void - Description: Draw rectangle with rounded edges outline + Description: Draw rectangle lines with rounded edges outline Param[1]: rec (type: Rectangle) Param[2]: roundness (type: float) Param[3]: segments (type: int) @@ -2476,7 +2476,17 @@ Function 255: DrawTriangle() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 256: DrawTriangleLines() (4 input parameters) +Function 256: DrawTriangleGradient() (6 input parameters) + Name: DrawTriangleGradient + Return type: void + Description: Draw triangle with interpolated colors (vertex in counter-clockwise order!) + Param[1]: v1 (type: Vector2) + Param[2]: v2 (type: Vector2) + Param[3]: v3 (type: Vector2) + Param[4]: c1 (type: Color) + Param[5]: c2 (type: Color) + Param[6]: c3 (type: Color) +Function 257: DrawTriangleLines() (4 input parameters) Name: DrawTriangleLines Return type: void Description: Draw triangle outline (vertex in counter-clockwise order!) @@ -2484,30 +2494,30 @@ Function 256: DrawTriangleLines() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 257: DrawTriangleFan() (3 input parameters) +Function 258: DrawTriangleFan() (3 input parameters) Name: DrawTriangleFan Return type: void Description: Draw a triangle fan defined by points (first vertex is the center) Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 258: DrawTriangleStrip() (3 input parameters) +Function 259: DrawTriangleStrip() (3 input parameters) Name: DrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 259: DrawPoly() (5 input parameters) +Function 260: DrawPoly() (5 input parameters) Name: DrawPoly Return type: void - Description: Draw a regular polygon (Vector version) + Description: Draw a polygon of n sides Param[1]: center (type: Vector2) Param[2]: sides (type: int) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 260: DrawPolyLines() (5 input parameters) +Function 261: DrawPolyLines() (5 input parameters) Name: DrawPolyLines Return type: void Description: Draw a polygon outline of n sides @@ -2516,7 +2526,7 @@ Function 260: DrawPolyLines() (5 input parameters) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 261: DrawPolyLinesEx() (6 input parameters) +Function 262: DrawPolyLinesEx() (6 input parameters) Name: DrawPolyLinesEx Return type: void Description: Draw a polygon outline of n sides with extended parameters @@ -2526,7 +2536,7 @@ Function 261: DrawPolyLinesEx() (6 input parameters) Param[4]: rotation (type: float) Param[5]: lineThick (type: float) Param[6]: color (type: Color) -Function 262: DrawSplineLinear() (4 input parameters) +Function 263: DrawSplineLinear() (4 input parameters) Name: DrawSplineLinear Return type: void Description: Draw spline: Linear, minimum 2 points @@ -2534,7 +2544,7 @@ Function 262: DrawSplineLinear() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 263: DrawSplineBasis() (4 input parameters) +Function 264: DrawSplineBasis() (4 input parameters) Name: DrawSplineBasis Return type: void Description: Draw spline: B-Spline, minimum 4 points @@ -2542,7 +2552,7 @@ Function 263: DrawSplineBasis() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 264: DrawSplineCatmullRom() (4 input parameters) +Function 265: DrawSplineCatmullRom() (4 input parameters) Name: DrawSplineCatmullRom Return type: void Description: Draw spline: Catmull-Rom, minimum 4 points @@ -2550,7 +2560,7 @@ Function 264: DrawSplineCatmullRom() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 265: DrawSplineBezierQuadratic() (4 input parameters) +Function 266: DrawSplineBezierQuadratic() (4 input parameters) Name: DrawSplineBezierQuadratic Return type: void Description: Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] @@ -2558,7 +2568,7 @@ Function 265: DrawSplineBezierQuadratic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 266: DrawSplineBezierCubic() (4 input parameters) +Function 267: DrawSplineBezierCubic() (4 input parameters) Name: DrawSplineBezierCubic Return type: void Description: Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] @@ -2566,7 +2576,7 @@ Function 266: DrawSplineBezierCubic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 267: DrawSplineSegmentLinear() (4 input parameters) +Function 268: DrawSplineSegmentLinear() (4 input parameters) Name: DrawSplineSegmentLinear Return type: void Description: Draw spline segment: Linear, 2 points @@ -2574,7 +2584,7 @@ Function 267: DrawSplineSegmentLinear() (4 input parameters) Param[2]: p2 (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 268: DrawSplineSegmentBasis() (6 input parameters) +Function 269: DrawSplineSegmentBasis() (6 input parameters) Name: DrawSplineSegmentBasis Return type: void Description: Draw spline segment: B-Spline, 4 points @@ -2584,7 +2594,7 @@ Function 268: DrawSplineSegmentBasis() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 269: DrawSplineSegmentCatmullRom() (6 input parameters) +Function 270: DrawSplineSegmentCatmullRom() (6 input parameters) Name: DrawSplineSegmentCatmullRom Return type: void Description: Draw spline segment: Catmull-Rom, 4 points @@ -2594,7 +2604,7 @@ Function 269: DrawSplineSegmentCatmullRom() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 270: DrawSplineSegmentBezierQuadratic() (5 input parameters) +Function 271: DrawSplineSegmentBezierQuadratic() (5 input parameters) Name: DrawSplineSegmentBezierQuadratic Return type: void Description: Draw spline segment: Quadratic Bezier, 2 points, 1 control point @@ -2603,7 +2613,7 @@ Function 270: DrawSplineSegmentBezierQuadratic() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: thick (type: float) Param[5]: color (type: Color) -Function 271: DrawSplineSegmentBezierCubic() (6 input parameters) +Function 272: DrawSplineSegmentBezierCubic() (6 input parameters) Name: DrawSplineSegmentBezierCubic Return type: void Description: Draw spline segment: Cubic Bezier, 2 points, 2 control points @@ -2613,14 +2623,14 @@ Function 271: DrawSplineSegmentBezierCubic() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 272: GetSplinePointLinear() (3 input parameters) +Function 273: GetSplinePointLinear() (3 input parameters) Name: GetSplinePointLinear Return type: Vector2 Description: Get (evaluate) spline point: Linear Param[1]: startPos (type: Vector2) Param[2]: endPos (type: Vector2) Param[3]: t (type: float) -Function 273: GetSplinePointBasis() (5 input parameters) +Function 274: GetSplinePointBasis() (5 input parameters) Name: GetSplinePointBasis Return type: Vector2 Description: Get (evaluate) spline point: B-Spline @@ -2629,7 +2639,7 @@ Function 273: GetSplinePointBasis() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 274: GetSplinePointCatmullRom() (5 input parameters) +Function 275: GetSplinePointCatmullRom() (5 input parameters) Name: GetSplinePointCatmullRom Return type: Vector2 Description: Get (evaluate) spline point: Catmull-Rom @@ -2638,7 +2648,7 @@ Function 274: GetSplinePointCatmullRom() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 275: GetSplinePointBezierQuad() (4 input parameters) +Function 276: GetSplinePointBezierQuad() (4 input parameters) Name: GetSplinePointBezierQuad Return type: Vector2 Description: Get (evaluate) spline point: Quadratic Bezier @@ -2646,7 +2656,7 @@ Function 275: GetSplinePointBezierQuad() (4 input parameters) Param[2]: c2 (type: Vector2) Param[3]: p3 (type: Vector2) Param[4]: t (type: float) -Function 276: GetSplinePointBezierCubic() (5 input parameters) +Function 277: GetSplinePointBezierCubic() (5 input parameters) Name: GetSplinePointBezierCubic Return type: Vector2 Description: Get (evaluate) spline point: Cubic Bezier @@ -2655,13 +2665,13 @@ Function 276: GetSplinePointBezierCubic() (5 input parameters) Param[3]: c3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 277: CheckCollisionRecs() (2 input parameters) +Function 278: CheckCollisionRecs() (2 input parameters) Name: CheckCollisionRecs Return type: bool Description: Check collision between two rectangles Param[1]: rec1 (type: Rectangle) Param[2]: rec2 (type: Rectangle) -Function 278: CheckCollisionCircles() (4 input parameters) +Function 279: CheckCollisionCircles() (4 input parameters) Name: CheckCollisionCircles Return type: bool Description: Check collision between two circles @@ -2669,35 +2679,35 @@ Function 278: CheckCollisionCircles() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector2) Param[4]: radius2 (type: float) -Function 279: CheckCollisionCircleRec() (3 input parameters) +Function 280: CheckCollisionCircleRec() (3 input parameters) Name: CheckCollisionCircleRec Return type: bool Description: Check collision between circle and rectangle Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: rec (type: Rectangle) -Function 280: CheckCollisionCircleLine() (4 input parameters) +Function 281: CheckCollisionCircleLine() (4 input parameters) Name: CheckCollisionCircleLine Return type: bool - Description: Check if circle collides with a line created betweeen two points [p1] and [p2] + Description: Check if circle collides with a line created between two points [p1] and [p2] Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: p1 (type: Vector2) Param[4]: p2 (type: Vector2) -Function 281: CheckCollisionPointRec() (2 input parameters) +Function 282: CheckCollisionPointRec() (2 input parameters) Name: CheckCollisionPointRec Return type: bool Description: Check if point is inside rectangle Param[1]: point (type: Vector2) Param[2]: rec (type: Rectangle) -Function 282: CheckCollisionPointCircle() (3 input parameters) +Function 283: CheckCollisionPointCircle() (3 input parameters) Name: CheckCollisionPointCircle Return type: bool Description: Check if point is inside circle Param[1]: point (type: Vector2) Param[2]: center (type: Vector2) Param[3]: radius (type: float) -Function 283: CheckCollisionPointTriangle() (4 input parameters) +Function 284: CheckCollisionPointTriangle() (4 input parameters) Name: CheckCollisionPointTriangle Return type: bool Description: Check if point is inside a triangle @@ -2705,7 +2715,7 @@ Function 283: CheckCollisionPointTriangle() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: p3 (type: Vector2) -Function 284: CheckCollisionPointLine() (4 input parameters) +Function 285: CheckCollisionPointLine() (4 input parameters) Name: CheckCollisionPointLine Return type: bool Description: Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] @@ -2713,14 +2723,14 @@ Function 284: CheckCollisionPointLine() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: threshold (type: int) -Function 285: CheckCollisionPointPoly() (3 input parameters) +Function 286: CheckCollisionPointPoly() (3 input parameters) Name: CheckCollisionPointPoly Return type: bool Description: Check if point is within a polygon described by array of vertices Param[1]: point (type: Vector2) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) -Function 286: CheckCollisionLines() (5 input parameters) +Function 287: CheckCollisionLines() (5 input parameters) Name: CheckCollisionLines Return type: bool Description: Check the collision between two lines defined by two points each, returns collision point by reference @@ -2729,18 +2739,18 @@ Function 286: CheckCollisionLines() (5 input parameters) Param[3]: startPos2 (type: Vector2) Param[4]: endPos2 (type: Vector2) Param[5]: collisionPoint (type: Vector2 *) -Function 287: GetCollisionRec() (2 input parameters) +Function 288: GetCollisionRec() (2 input parameters) Name: GetCollisionRec Return type: Rectangle Description: Get collision rectangle for two rectangles collision Param[1]: rec1 (type: Rectangle) Param[2]: rec2 (type: Rectangle) -Function 288: LoadImage() (1 input parameters) +Function 289: LoadImage() (1 input parameters) Name: LoadImage Return type: Image Description: Load image from file into CPU memory (RAM) Param[1]: fileName (type: const char *) -Function 289: LoadImageRaw() (5 input parameters) +Function 290: LoadImageRaw() (5 input parameters) Name: LoadImageRaw Return type: Image Description: Load image from RAW file data @@ -2749,13 +2759,13 @@ Function 289: LoadImageRaw() (5 input parameters) Param[3]: height (type: int) Param[4]: format (type: int) Param[5]: headerSize (type: int) -Function 290: LoadImageAnim() (2 input parameters) +Function 291: LoadImageAnim() (2 input parameters) Name: LoadImageAnim Return type: Image Description: Load image sequence from file (frames appended to image.data) Param[1]: fileName (type: const char *) Param[2]: frames (type: int *) -Function 291: LoadImageAnimFromMemory() (4 input parameters) +Function 292: LoadImageAnimFromMemory() (4 input parameters) Name: LoadImageAnimFromMemory Return type: Image Description: Load image sequence from memory buffer @@ -2763,60 +2773,60 @@ Function 291: LoadImageAnimFromMemory() (4 input parameters) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) Param[4]: frames (type: int *) -Function 292: LoadImageFromMemory() (3 input parameters) +Function 293: LoadImageFromMemory() (3 input parameters) Name: LoadImageFromMemory Return type: Image Description: Load image from memory buffer, fileType refers to extension: i.e. '.png' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 293: LoadImageFromTexture() (1 input parameters) +Function 294: LoadImageFromTexture() (1 input parameters) Name: LoadImageFromTexture Return type: Image Description: Load image from GPU texture data Param[1]: texture (type: Texture2D) -Function 294: LoadImageFromScreen() (0 input parameters) +Function 295: LoadImageFromScreen() (0 input parameters) Name: LoadImageFromScreen Return type: Image - Description: Load image from screen buffer and (screenshot) + Description: Load image from screen buffer (screenshot) No input parameters -Function 295: IsImageValid() (1 input parameters) +Function 296: IsImageValid() (1 input parameters) Name: IsImageValid Return type: bool Description: Check if an image is valid (data and parameters) Param[1]: image (type: Image) -Function 296: UnloadImage() (1 input parameters) +Function 297: UnloadImage() (1 input parameters) Name: UnloadImage Return type: void Description: Unload image from CPU memory (RAM) Param[1]: image (type: Image) -Function 297: ExportImage() (2 input parameters) +Function 298: ExportImage() (2 input parameters) Name: ExportImage Return type: bool Description: Export image data to file, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 298: ExportImageToMemory() (3 input parameters) +Function 299: ExportImageToMemory() (3 input parameters) Name: ExportImageToMemory Return type: unsigned char * Description: Export image to memory buffer, memory must be MemFree() Param[1]: image (type: Image) Param[2]: fileType (type: const char *) Param[3]: fileSize (type: int *) -Function 299: ExportImageAsCode() (2 input parameters) +Function 300: ExportImageAsCode() (2 input parameters) Name: ExportImageAsCode Return type: bool Description: Export image as code file defining an array of bytes, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 300: GenImageColor() (3 input parameters) +Function 301: GenImageColor() (3 input parameters) Name: GenImageColor Return type: Image Description: Generate image: plain color Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: color (type: Color) -Function 301: GenImageGradientLinear() (5 input parameters) +Function 302: GenImageGradientLinear() (5 input parameters) Name: GenImageGradientLinear Return type: Image Description: Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient @@ -2825,7 +2835,7 @@ Function 301: GenImageGradientLinear() (5 input parameters) Param[3]: direction (type: int) Param[4]: start (type: Color) Param[5]: end (type: Color) -Function 302: GenImageGradientRadial() (5 input parameters) +Function 303: GenImageGradientRadial() (5 input parameters) Name: GenImageGradientRadial Return type: Image Description: Generate image: radial gradient @@ -2834,7 +2844,7 @@ Function 302: GenImageGradientRadial() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 303: GenImageGradientSquare() (5 input parameters) +Function 304: GenImageGradientSquare() (5 input parameters) Name: GenImageGradientSquare Return type: Image Description: Generate image: square gradient @@ -2843,7 +2853,7 @@ Function 303: GenImageGradientSquare() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 304: GenImageChecked() (6 input parameters) +Function 305: GenImageChecked() (6 input parameters) Name: GenImageChecked Return type: Image Description: Generate image: checked @@ -2853,14 +2863,14 @@ Function 304: GenImageChecked() (6 input parameters) Param[4]: checksY (type: int) Param[5]: col1 (type: Color) Param[6]: col2 (type: Color) -Function 305: GenImageWhiteNoise() (3 input parameters) +Function 306: GenImageWhiteNoise() (3 input parameters) Name: GenImageWhiteNoise Return type: Image Description: Generate image: white noise Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: factor (type: float) -Function 306: GenImagePerlinNoise() (5 input parameters) +Function 307: GenImagePerlinNoise() (5 input parameters) Name: GenImagePerlinNoise Return type: Image Description: Generate image: perlin noise @@ -2869,45 +2879,45 @@ Function 306: GenImagePerlinNoise() (5 input parameters) Param[3]: offsetX (type: int) Param[4]: offsetY (type: int) Param[5]: scale (type: float) -Function 307: GenImageCellular() (3 input parameters) +Function 308: GenImageCellular() (3 input parameters) Name: GenImageCellular Return type: Image Description: Generate image: cellular algorithm, bigger tileSize means bigger cells Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: tileSize (type: int) -Function 308: GenImageText() (3 input parameters) +Function 309: GenImageText() (3 input parameters) Name: GenImageText Return type: Image Description: Generate image: grayscale image from text data Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: text (type: const char *) -Function 309: ImageCopy() (1 input parameters) +Function 310: ImageCopy() (1 input parameters) Name: ImageCopy Return type: Image Description: Create an image duplicate (useful for transformations) Param[1]: image (type: Image) -Function 310: ImageFromImage() (2 input parameters) +Function 311: ImageFromImage() (2 input parameters) Name: ImageFromImage Return type: Image Description: Create an image from another image piece Param[1]: image (type: Image) Param[2]: rec (type: Rectangle) -Function 311: ImageFromChannel() (2 input parameters) +Function 312: ImageFromChannel() (2 input parameters) Name: ImageFromChannel Return type: Image Description: Create an image from a selected channel of another image (GRAYSCALE) Param[1]: image (type: Image) Param[2]: selectedChannel (type: int) -Function 312: ImageText() (3 input parameters) +Function 313: ImageText() (3 input parameters) Name: ImageText Return type: Image Description: Create an image from text (default font) Param[1]: text (type: const char *) Param[2]: fontSize (type: int) Param[3]: color (type: Color) -Function 313: ImageTextEx() (5 input parameters) +Function 314: ImageTextEx() (5 input parameters) Name: ImageTextEx Return type: Image Description: Create an image from text (custom sprite font) @@ -2916,76 +2926,76 @@ Function 313: ImageTextEx() (5 input parameters) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) Param[5]: tint (type: Color) -Function 314: ImageFormat() (2 input parameters) +Function 315: ImageFormat() (2 input parameters) Name: ImageFormat Return type: void Description: Convert image data to desired format Param[1]: image (type: Image *) Param[2]: newFormat (type: int) -Function 315: ImageToPOT() (2 input parameters) +Function 316: ImageToPOT() (2 input parameters) Name: ImageToPOT Return type: void Description: Convert image to POT (power-of-two) Param[1]: image (type: Image *) Param[2]: fill (type: Color) -Function 316: ImageCrop() (2 input parameters) +Function 317: ImageCrop() (2 input parameters) Name: ImageCrop Return type: void Description: Crop an image to a defined rectangle Param[1]: image (type: Image *) Param[2]: crop (type: Rectangle) -Function 317: ImageAlphaCrop() (2 input parameters) +Function 318: ImageAlphaCrop() (2 input parameters) Name: ImageAlphaCrop Return type: void Description: Crop image depending on alpha value Param[1]: image (type: Image *) Param[2]: threshold (type: float) -Function 318: ImageAlphaClear() (3 input parameters) +Function 319: ImageAlphaClear() (3 input parameters) Name: ImageAlphaClear Return type: void Description: Clear alpha channel to desired color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: threshold (type: float) -Function 319: ImageAlphaMask() (2 input parameters) +Function 320: ImageAlphaMask() (2 input parameters) Name: ImageAlphaMask Return type: void Description: Apply alpha mask to image Param[1]: image (type: Image *) Param[2]: alphaMask (type: Image) -Function 320: ImageAlphaPremultiply() (1 input parameters) +Function 321: ImageAlphaPremultiply() (1 input parameters) Name: ImageAlphaPremultiply Return type: void Description: Premultiply alpha channel Param[1]: image (type: Image *) -Function 321: ImageBlurGaussian() (2 input parameters) +Function 322: ImageBlurGaussian() (2 input parameters) Name: ImageBlurGaussian Return type: void Description: Apply Gaussian blur using a box blur approximation Param[1]: image (type: Image *) Param[2]: blurSize (type: int) -Function 322: ImageKernelConvolution() (3 input parameters) +Function 323: ImageKernelConvolution() (3 input parameters) Name: ImageKernelConvolution Return type: void Description: Apply custom square convolution kernel to image Param[1]: image (type: Image *) Param[2]: kernel (type: const float *) Param[3]: kernelSize (type: int) -Function 323: ImageResize() (3 input parameters) +Function 324: ImageResize() (3 input parameters) Name: ImageResize Return type: void Description: Resize image (Bicubic scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 324: ImageResizeNN() (3 input parameters) +Function 325: ImageResizeNN() (3 input parameters) Name: ImageResizeNN Return type: void Description: Resize image (Nearest-Neighbor scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 325: ImageResizeCanvas() (6 input parameters) +Function 326: ImageResizeCanvas() (6 input parameters) Name: ImageResizeCanvas Return type: void Description: Resize canvas and fill with color @@ -2995,12 +3005,12 @@ Function 325: ImageResizeCanvas() (6 input parameters) Param[4]: offsetX (type: int) Param[5]: offsetY (type: int) Param[6]: fill (type: Color) -Function 326: ImageMipmaps() (1 input parameters) +Function 327: ImageMipmaps() (1 input parameters) Name: ImageMipmaps Return type: void Description: Compute all mipmap levels for a provided image Param[1]: image (type: Image *) -Function 327: ImageDither() (5 input parameters) +Function 328: ImageDither() (5 input parameters) Name: ImageDither Return type: void Description: Dither image data to 16bpp or lower (Floyd-Steinberg dithering) @@ -3009,109 +3019,109 @@ Function 327: ImageDither() (5 input parameters) Param[3]: gBpp (type: int) Param[4]: bBpp (type: int) Param[5]: aBpp (type: int) -Function 328: ImageFlipVertical() (1 input parameters) +Function 329: ImageFlipVertical() (1 input parameters) Name: ImageFlipVertical Return type: void Description: Flip image vertically Param[1]: image (type: Image *) -Function 329: ImageFlipHorizontal() (1 input parameters) +Function 330: ImageFlipHorizontal() (1 input parameters) Name: ImageFlipHorizontal Return type: void Description: Flip image horizontally Param[1]: image (type: Image *) -Function 330: ImageRotate() (2 input parameters) +Function 331: ImageRotate() (2 input parameters) Name: ImageRotate Return type: void Description: Rotate image by input angle in degrees (-359 to 359) Param[1]: image (type: Image *) Param[2]: degrees (type: int) -Function 331: ImageRotateCW() (1 input parameters) +Function 332: ImageRotateCW() (1 input parameters) Name: ImageRotateCW Return type: void Description: Rotate image clockwise 90deg Param[1]: image (type: Image *) -Function 332: ImageRotateCCW() (1 input parameters) +Function 333: ImageRotateCCW() (1 input parameters) Name: ImageRotateCCW Return type: void Description: Rotate image counter-clockwise 90deg Param[1]: image (type: Image *) -Function 333: ImageColorTint() (2 input parameters) +Function 334: ImageColorTint() (2 input parameters) Name: ImageColorTint Return type: void Description: Modify image color: tint Param[1]: image (type: Image *) Param[2]: color (type: Color) -Function 334: ImageColorInvert() (1 input parameters) +Function 335: ImageColorInvert() (1 input parameters) Name: ImageColorInvert Return type: void Description: Modify image color: invert Param[1]: image (type: Image *) -Function 335: ImageColorGrayscale() (1 input parameters) +Function 336: ImageColorGrayscale() (1 input parameters) Name: ImageColorGrayscale Return type: void Description: Modify image color: grayscale Param[1]: image (type: Image *) -Function 336: ImageColorContrast() (2 input parameters) +Function 337: ImageColorContrast() (2 input parameters) Name: ImageColorContrast Return type: void Description: Modify image color: contrast (-100 to 100) Param[1]: image (type: Image *) Param[2]: contrast (type: float) -Function 337: ImageColorBrightness() (2 input parameters) +Function 338: ImageColorBrightness() (2 input parameters) Name: ImageColorBrightness Return type: void Description: Modify image color: brightness (-255 to 255) Param[1]: image (type: Image *) Param[2]: brightness (type: int) -Function 338: ImageColorReplace() (3 input parameters) +Function 339: ImageColorReplace() (3 input parameters) Name: ImageColorReplace Return type: void Description: Modify image color: replace color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: replace (type: Color) -Function 339: LoadImageColors() (1 input parameters) +Function 340: LoadImageColors() (1 input parameters) Name: LoadImageColors Return type: Color * Description: Load color data from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) -Function 340: LoadImagePalette() (3 input parameters) +Function 341: LoadImagePalette() (3 input parameters) Name: LoadImagePalette Return type: Color * Description: Load colors palette from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) Param[2]: maxPaletteSize (type: int) Param[3]: colorCount (type: int *) -Function 341: UnloadImageColors() (1 input parameters) +Function 342: UnloadImageColors() (1 input parameters) Name: UnloadImageColors Return type: void Description: Unload color data loaded with LoadImageColors() Param[1]: colors (type: Color *) -Function 342: UnloadImagePalette() (1 input parameters) +Function 343: UnloadImagePalette() (1 input parameters) Name: UnloadImagePalette Return type: void Description: Unload colors palette loaded with LoadImagePalette() Param[1]: colors (type: Color *) -Function 343: GetImageAlphaBorder() (2 input parameters) +Function 344: GetImageAlphaBorder() (2 input parameters) Name: GetImageAlphaBorder Return type: Rectangle Description: Get image alpha border rectangle Param[1]: image (type: Image) Param[2]: threshold (type: float) -Function 344: GetImageColor() (3 input parameters) +Function 345: GetImageColor() (3 input parameters) Name: GetImageColor Return type: Color Description: Get image pixel color at (x, y) position Param[1]: image (type: Image) Param[2]: x (type: int) Param[3]: y (type: int) -Function 345: ImageClearBackground() (2 input parameters) +Function 346: ImageClearBackground() (2 input parameters) Name: ImageClearBackground Return type: void Description: Clear image background with given color Param[1]: dst (type: Image *) Param[2]: color (type: Color) -Function 346: ImageDrawPixel() (4 input parameters) +Function 347: ImageDrawPixel() (4 input parameters) Name: ImageDrawPixel Return type: void Description: Draw pixel within an image @@ -3119,14 +3129,14 @@ Function 346: ImageDrawPixel() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: color (type: Color) -Function 347: ImageDrawPixelV() (3 input parameters) +Function 348: ImageDrawPixelV() (3 input parameters) Name: ImageDrawPixelV Return type: void Description: Draw pixel within an image (Vector version) Param[1]: dst (type: Image *) Param[2]: position (type: Vector2) Param[3]: color (type: Color) -Function 348: ImageDrawLine() (6 input parameters) +Function 349: ImageDrawLine() (6 input parameters) Name: ImageDrawLine Return type: void Description: Draw line within an image @@ -3136,7 +3146,7 @@ Function 348: ImageDrawLine() (6 input parameters) Param[4]: endPosX (type: int) Param[5]: endPosY (type: int) Param[6]: color (type: Color) -Function 349: ImageDrawLineV() (4 input parameters) +Function 350: ImageDrawLineV() (4 input parameters) Name: ImageDrawLineV Return type: void Description: Draw line within an image (Vector version) @@ -3144,7 +3154,7 @@ Function 349: ImageDrawLineV() (4 input parameters) Param[2]: start (type: Vector2) Param[3]: end (type: Vector2) Param[4]: color (type: Color) -Function 350: ImageDrawLineEx() (5 input parameters) +Function 351: ImageDrawLineEx() (5 input parameters) Name: ImageDrawLineEx Return type: void Description: Draw a line defining thickness within an image @@ -3153,7 +3163,7 @@ Function 350: ImageDrawLineEx() (5 input parameters) Param[3]: end (type: Vector2) Param[4]: thick (type: int) Param[5]: color (type: Color) -Function 351: ImageDrawCircle() (5 input parameters) +Function 352: ImageDrawCircle() (5 input parameters) Name: ImageDrawCircle Return type: void Description: Draw a filled circle within an image @@ -3162,7 +3172,7 @@ Function 351: ImageDrawCircle() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 352: ImageDrawCircleV() (4 input parameters) +Function 353: ImageDrawCircleV() (4 input parameters) Name: ImageDrawCircleV Return type: void Description: Draw a filled circle within an image (Vector version) @@ -3170,7 +3180,7 @@ Function 352: ImageDrawCircleV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 353: ImageDrawCircleLines() (5 input parameters) +Function 354: ImageDrawCircleLines() (5 input parameters) Name: ImageDrawCircleLines Return type: void Description: Draw circle outline within an image @@ -3179,7 +3189,7 @@ Function 353: ImageDrawCircleLines() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 354: ImageDrawCircleLinesV() (4 input parameters) +Function 355: ImageDrawCircleLinesV() (4 input parameters) Name: ImageDrawCircleLinesV Return type: void Description: Draw circle outline within an image (Vector version) @@ -3187,7 +3197,7 @@ Function 354: ImageDrawCircleLinesV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 355: ImageDrawRectangle() (6 input parameters) +Function 356: ImageDrawRectangle() (6 input parameters) Name: ImageDrawRectangle Return type: void Description: Draw rectangle within an image @@ -3197,7 +3207,7 @@ Function 355: ImageDrawRectangle() (6 input parameters) Param[4]: width (type: int) Param[5]: height (type: int) Param[6]: color (type: Color) -Function 356: ImageDrawRectangleV() (4 input parameters) +Function 357: ImageDrawRectangleV() (4 input parameters) Name: ImageDrawRectangleV Return type: void Description: Draw rectangle within an image (Vector version) @@ -3205,14 +3215,14 @@ Function 356: ImageDrawRectangleV() (4 input parameters) Param[2]: position (type: Vector2) Param[3]: size (type: Vector2) Param[4]: color (type: Color) -Function 357: ImageDrawRectangleRec() (3 input parameters) +Function 358: ImageDrawRectangleRec() (3 input parameters) Name: ImageDrawRectangleRec Return type: void Description: Draw rectangle within an image Param[1]: dst (type: Image *) Param[2]: rec (type: Rectangle) Param[3]: color (type: Color) -Function 358: ImageDrawRectangleLines() (4 input parameters) +Function 359: ImageDrawRectangleLines() (4 input parameters) Name: ImageDrawRectangleLines Return type: void Description: Draw rectangle lines within an image @@ -3220,7 +3230,7 @@ Function 358: ImageDrawRectangleLines() (4 input parameters) Param[2]: rec (type: Rectangle) Param[3]: thick (type: int) Param[4]: color (type: Color) -Function 359: ImageDrawTriangle() (5 input parameters) +Function 360: ImageDrawTriangle() (5 input parameters) Name: ImageDrawTriangle Return type: void Description: Draw triangle within an image @@ -3229,7 +3239,7 @@ Function 359: ImageDrawTriangle() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 360: ImageDrawTriangleEx() (7 input parameters) +Function 361: ImageDrawTriangleEx() (7 input parameters) Name: ImageDrawTriangleEx Return type: void Description: Draw triangle with interpolated colors within an image @@ -3240,7 +3250,7 @@ Function 360: ImageDrawTriangleEx() (7 input parameters) Param[5]: c1 (type: Color) Param[6]: c2 (type: Color) Param[7]: c3 (type: Color) -Function 361: ImageDrawTriangleLines() (5 input parameters) +Function 362: ImageDrawTriangleLines() (5 input parameters) Name: ImageDrawTriangleLines Return type: void Description: Draw triangle outline within an image @@ -3249,7 +3259,7 @@ Function 361: ImageDrawTriangleLines() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 362: ImageDrawTriangleFan() (4 input parameters) +Function 363: ImageDrawTriangleFan() (4 input parameters) Name: ImageDrawTriangleFan Return type: void Description: Draw a triangle fan defined by points within an image (first vertex is the center) @@ -3257,7 +3267,7 @@ Function 362: ImageDrawTriangleFan() (4 input parameters) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 363: ImageDrawTriangleStrip() (4 input parameters) +Function 364: ImageDrawTriangleStrip() (4 input parameters) Name: ImageDrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points within an image @@ -3265,7 +3275,7 @@ Function 363: ImageDrawTriangleStrip() (4 input parameters) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 364: ImageDraw() (5 input parameters) +Function 365: ImageDraw() (5 input parameters) Name: ImageDraw Return type: void Description: Draw a source image within a destination image (tint applied to source) @@ -3274,7 +3284,7 @@ Function 364: ImageDraw() (5 input parameters) Param[3]: srcRec (type: Rectangle) Param[4]: dstRec (type: Rectangle) Param[5]: tint (type: Color) -Function 365: ImageDrawText() (6 input parameters) +Function 366: ImageDrawText() (6 input parameters) Name: ImageDrawText Return type: void Description: Draw text (using default font) within an image (destination) @@ -3284,7 +3294,7 @@ Function 365: ImageDrawText() (6 input parameters) Param[4]: posY (type: int) Param[5]: fontSize (type: int) Param[6]: color (type: Color) -Function 366: ImageDrawTextEx() (7 input parameters) +Function 367: ImageDrawTextEx() (7 input parameters) Name: ImageDrawTextEx Return type: void Description: Draw text (custom sprite font) within an image (destination) @@ -3295,79 +3305,79 @@ Function 366: ImageDrawTextEx() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 367: LoadTexture() (1 input parameters) +Function 368: LoadTexture() (1 input parameters) Name: LoadTexture Return type: Texture2D Description: Load texture from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 368: LoadTextureFromImage() (1 input parameters) +Function 369: LoadTextureFromImage() (1 input parameters) Name: LoadTextureFromImage Return type: Texture2D Description: Load texture from image data Param[1]: image (type: Image) -Function 369: LoadTextureCubemap() (2 input parameters) +Function 370: LoadTextureCubemap() (2 input parameters) Name: LoadTextureCubemap Return type: TextureCubemap Description: Load cubemap from image, multiple image cubemap layouts supported Param[1]: image (type: Image) Param[2]: layout (type: int) -Function 370: LoadRenderTexture() (2 input parameters) +Function 371: LoadRenderTexture() (2 input parameters) Name: LoadRenderTexture Return type: RenderTexture2D Description: Load texture for rendering (framebuffer) Param[1]: width (type: int) Param[2]: height (type: int) -Function 371: IsTextureValid() (1 input parameters) +Function 372: IsTextureValid() (1 input parameters) Name: IsTextureValid Return type: bool Description: Check if a texture is valid (loaded in GPU) Param[1]: texture (type: Texture2D) -Function 372: UnloadTexture() (1 input parameters) +Function 373: UnloadTexture() (1 input parameters) Name: UnloadTexture Return type: void Description: Unload texture from GPU memory (VRAM) Param[1]: texture (type: Texture2D) -Function 373: IsRenderTextureValid() (1 input parameters) +Function 374: IsRenderTextureValid() (1 input parameters) Name: IsRenderTextureValid Return type: bool Description: Check if a render texture is valid (loaded in GPU) Param[1]: target (type: RenderTexture2D) -Function 374: UnloadRenderTexture() (1 input parameters) +Function 375: UnloadRenderTexture() (1 input parameters) Name: UnloadRenderTexture Return type: void Description: Unload render texture from GPU memory (VRAM) Param[1]: target (type: RenderTexture2D) -Function 375: UpdateTexture() (2 input parameters) +Function 376: UpdateTexture() (2 input parameters) Name: UpdateTexture Return type: void Description: Update GPU texture with new data (pixels should be able to fill texture) Param[1]: texture (type: Texture2D) Param[2]: pixels (type: const void *) -Function 376: UpdateTextureRec() (3 input parameters) +Function 377: UpdateTextureRec() (3 input parameters) Name: UpdateTextureRec Return type: void Description: Update GPU texture rectangle with new data (pixels and rec should fit in texture) Param[1]: texture (type: Texture2D) Param[2]: rec (type: Rectangle) Param[3]: pixels (type: const void *) -Function 377: GenTextureMipmaps() (1 input parameters) +Function 378: GenTextureMipmaps() (1 input parameters) Name: GenTextureMipmaps Return type: void Description: Generate GPU mipmaps for a texture Param[1]: texture (type: Texture2D *) -Function 378: SetTextureFilter() (2 input parameters) +Function 379: SetTextureFilter() (2 input parameters) Name: SetTextureFilter Return type: void Description: Set texture scaling filter mode Param[1]: texture (type: Texture2D) Param[2]: filter (type: int) -Function 379: SetTextureWrap() (2 input parameters) +Function 380: SetTextureWrap() (2 input parameters) Name: SetTextureWrap Return type: void Description: Set texture wrapping mode Param[1]: texture (type: Texture2D) Param[2]: wrap (type: int) -Function 380: DrawTexture() (4 input parameters) +Function 381: DrawTexture() (4 input parameters) Name: DrawTexture Return type: void Description: Draw a Texture2D @@ -3375,14 +3385,14 @@ Function 380: DrawTexture() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: tint (type: Color) -Function 381: DrawTextureV() (3 input parameters) +Function 382: DrawTextureV() (3 input parameters) Name: DrawTextureV Return type: void Description: Draw a Texture2D with position defined as Vector2 Param[1]: texture (type: Texture2D) Param[2]: position (type: Vector2) Param[3]: tint (type: Color) -Function 382: DrawTextureEx() (5 input parameters) +Function 383: DrawTextureEx() (5 input parameters) Name: DrawTextureEx Return type: void Description: Draw a Texture2D with extended parameters @@ -3391,7 +3401,7 @@ Function 382: DrawTextureEx() (5 input parameters) Param[3]: rotation (type: float) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 383: DrawTextureRec() (4 input parameters) +Function 384: DrawTextureRec() (4 input parameters) Name: DrawTextureRec Return type: void Description: Draw a part of a texture defined by a rectangle @@ -3399,7 +3409,7 @@ Function 383: DrawTextureRec() (4 input parameters) Param[2]: source (type: Rectangle) Param[3]: position (type: Vector2) Param[4]: tint (type: Color) -Function 384: DrawTexturePro() (6 input parameters) +Function 385: DrawTexturePro() (6 input parameters) Name: DrawTexturePro Return type: void Description: Draw a part of a texture defined by a rectangle with 'pro' parameters @@ -3409,129 +3419,129 @@ Function 384: DrawTexturePro() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 385: DrawTextureNPatch() (6 input parameters) +Function 386: DrawTextureNPatch() (6 input parameters) Name: DrawTextureNPatch Return type: void - Description: Draws a texture (or part of it) that stretches or shrinks nicely + Description: Draw a texture (or part of it) that stretches or shrinks nicely Param[1]: texture (type: Texture2D) Param[2]: nPatchInfo (type: NPatchInfo) Param[3]: dest (type: Rectangle) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 386: ColorIsEqual() (2 input parameters) +Function 387: ColorIsEqual() (2 input parameters) Name: ColorIsEqual Return type: bool Description: Check if two colors are equal Param[1]: col1 (type: Color) Param[2]: col2 (type: Color) -Function 387: Fade() (2 input parameters) +Function 388: Fade() (2 input parameters) Name: Fade Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 388: ColorToInt() (1 input parameters) +Function 389: ColorToInt() (1 input parameters) Name: ColorToInt Return type: int Description: Get hexadecimal value for a Color (0xRRGGBBAA) Param[1]: color (type: Color) -Function 389: ColorNormalize() (1 input parameters) +Function 390: ColorNormalize() (1 input parameters) Name: ColorNormalize Return type: Vector4 Description: Get Color normalized as float [0..1] Param[1]: color (type: Color) -Function 390: ColorFromNormalized() (1 input parameters) +Function 391: ColorFromNormalized() (1 input parameters) Name: ColorFromNormalized Return type: Color Description: Get Color from normalized values [0..1] Param[1]: normalized (type: Vector4) -Function 391: ColorToHSV() (1 input parameters) +Function 392: ColorToHSV() (1 input parameters) Name: ColorToHSV Return type: Vector3 Description: Get HSV values for a Color, hue [0..360], saturation/value [0..1] Param[1]: color (type: Color) -Function 392: ColorFromHSV() (3 input parameters) +Function 393: ColorFromHSV() (3 input parameters) Name: ColorFromHSV Return type: Color Description: Get a Color from HSV values, hue [0..360], saturation/value [0..1] Param[1]: hue (type: float) Param[2]: saturation (type: float) Param[3]: value (type: float) -Function 393: ColorTint() (2 input parameters) +Function 394: ColorTint() (2 input parameters) Name: ColorTint Return type: Color Description: Get color multiplied with another color Param[1]: color (type: Color) Param[2]: tint (type: Color) -Function 394: ColorBrightness() (2 input parameters) +Function 395: ColorBrightness() (2 input parameters) Name: ColorBrightness Return type: Color Description: Get color with brightness correction, brightness factor goes from -1.0f to 1.0f Param[1]: color (type: Color) Param[2]: factor (type: float) -Function 395: ColorContrast() (2 input parameters) +Function 396: ColorContrast() (2 input parameters) Name: ColorContrast Return type: Color Description: Get color with contrast correction, contrast values between -1.0f and 1.0f Param[1]: color (type: Color) Param[2]: contrast (type: float) -Function 396: ColorAlpha() (2 input parameters) +Function 397: ColorAlpha() (2 input parameters) Name: ColorAlpha Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 397: ColorAlphaBlend() (3 input parameters) +Function 398: ColorAlphaBlend() (3 input parameters) Name: ColorAlphaBlend Return type: Color Description: Get src alpha-blended into dst color with tint Param[1]: dst (type: Color) Param[2]: src (type: Color) Param[3]: tint (type: Color) -Function 398: ColorLerp() (3 input parameters) +Function 399: ColorLerp() (3 input parameters) Name: ColorLerp Return type: Color Description: Get color lerp interpolation between two colors, factor [0.0f..1.0f] Param[1]: color1 (type: Color) Param[2]: color2 (type: Color) Param[3]: factor (type: float) -Function 399: GetColor() (1 input parameters) +Function 400: GetColor() (1 input parameters) Name: GetColor Return type: Color Description: Get Color structure from hexadecimal value Param[1]: hexValue (type: unsigned int) -Function 400: GetPixelColor() (2 input parameters) +Function 401: GetPixelColor() (2 input parameters) Name: GetPixelColor Return type: Color Description: Get Color from a source pixel pointer of certain format Param[1]: srcPtr (type: void *) Param[2]: format (type: int) -Function 401: SetPixelColor() (3 input parameters) +Function 402: SetPixelColor() (3 input parameters) Name: SetPixelColor Return type: void Description: Set color formatted into destination pixel pointer Param[1]: dstPtr (type: void *) Param[2]: color (type: Color) Param[3]: format (type: int) -Function 402: GetPixelDataSize() (3 input parameters) +Function 403: GetPixelDataSize() (3 input parameters) Name: GetPixelDataSize Return type: int Description: Get pixel data size in bytes for certain format Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: format (type: int) -Function 403: GetFontDefault() (0 input parameters) +Function 404: GetFontDefault() (0 input parameters) Name: GetFontDefault Return type: Font Description: Get the default Font No input parameters -Function 404: LoadFont() (1 input parameters) +Function 405: LoadFont() (1 input parameters) Name: LoadFont Return type: Font Description: Load font from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 405: LoadFontEx() (4 input parameters) +Function 406: LoadFontEx() (4 input parameters) Name: LoadFontEx Return type: Font Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height @@ -3539,14 +3549,14 @@ Function 405: LoadFontEx() (4 input parameters) Param[2]: fontSize (type: int) Param[3]: codepoints (type: const int *) Param[4]: codepointCount (type: int) -Function 406: LoadFontFromImage() (3 input parameters) +Function 407: LoadFontFromImage() (3 input parameters) Name: LoadFontFromImage Return type: Font Description: Load font from Image (XNA style) Param[1]: image (type: Image) Param[2]: key (type: Color) Param[3]: firstChar (type: int) -Function 407: LoadFontFromMemory() (6 input parameters) +Function 408: LoadFontFromMemory() (6 input parameters) Name: LoadFontFromMemory Return type: Font Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf' @@ -3556,12 +3566,12 @@ Function 407: LoadFontFromMemory() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: codepoints (type: const int *) Param[6]: codepointCount (type: int) -Function 408: IsFontValid() (1 input parameters) +Function 409: IsFontValid() (1 input parameters) Name: IsFontValid Return type: bool Description: Check if a font is valid (font data loaded, WARNING: GPU texture not checked) Param[1]: font (type: Font) -Function 409: LoadFontData() (7 input parameters) +Function 410: LoadFontData() (7 input parameters) Name: LoadFontData Return type: GlyphInfo * Description: Load font data for further use @@ -3572,7 +3582,7 @@ Function 409: LoadFontData() (7 input parameters) Param[5]: codepointCount (type: int) Param[6]: type (type: int) Param[7]: glyphCount (type: int *) -Function 410: GenImageFontAtlas() (6 input parameters) +Function 411: GenImageFontAtlas() (6 input parameters) Name: GenImageFontAtlas Return type: Image Description: Generate image font atlas using chars info @@ -3582,30 +3592,30 @@ Function 410: GenImageFontAtlas() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: padding (type: int) Param[6]: packMethod (type: int) -Function 411: UnloadFontData() (2 input parameters) +Function 412: UnloadFontData() (2 input parameters) Name: UnloadFontData Return type: void Description: Unload font chars info data (RAM) Param[1]: glyphs (type: GlyphInfo *) Param[2]: glyphCount (type: int) -Function 412: UnloadFont() (1 input parameters) +Function 413: UnloadFont() (1 input parameters) Name: UnloadFont Return type: void Description: Unload font from GPU memory (VRAM) Param[1]: font (type: Font) -Function 413: ExportFontAsCode() (2 input parameters) +Function 414: ExportFontAsCode() (2 input parameters) Name: ExportFontAsCode Return type: bool Description: Export font as code file, returns true on success Param[1]: font (type: Font) Param[2]: fileName (type: const char *) -Function 414: DrawFPS() (2 input parameters) +Function 415: DrawFPS() (2 input parameters) Name: DrawFPS Return type: void Description: Draw current FPS Param[1]: posX (type: int) Param[2]: posY (type: int) -Function 415: DrawText() (5 input parameters) +Function 416: DrawText() (5 input parameters) Name: DrawText Return type: void Description: Draw text (using default font) @@ -3614,7 +3624,7 @@ Function 415: DrawText() (5 input parameters) Param[3]: posY (type: int) Param[4]: fontSize (type: int) Param[5]: color (type: Color) -Function 416: DrawTextEx() (6 input parameters) +Function 417: DrawTextEx() (6 input parameters) Name: DrawTextEx Return type: void Description: Draw text using font and additional parameters @@ -3624,7 +3634,7 @@ Function 416: DrawTextEx() (6 input parameters) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) Param[6]: tint (type: Color) -Function 417: DrawTextPro() (8 input parameters) +Function 418: DrawTextPro() (8 input parameters) Name: DrawTextPro Return type: void Description: Draw text using Font and pro parameters (rotation) @@ -3636,7 +3646,7 @@ Function 417: DrawTextPro() (8 input parameters) Param[6]: fontSize (type: float) Param[7]: spacing (type: float) Param[8]: tint (type: Color) -Function 418: DrawTextCodepoint() (5 input parameters) +Function 419: DrawTextCodepoint() (5 input parameters) Name: DrawTextCodepoint Return type: void Description: Draw one character (codepoint) @@ -3645,10 +3655,10 @@ Function 418: DrawTextCodepoint() (5 input parameters) Param[3]: position (type: Vector2) Param[4]: fontSize (type: float) Param[5]: tint (type: Color) -Function 419: DrawTextCodepoints() (7 input parameters) +Function 420: DrawTextCodepoints() (7 input parameters) Name: DrawTextCodepoints Return type: void - Description: Draw multiple character (codepoint) + Description: Draw multiple characters (codepoint) Param[1]: font (type: Font) Param[2]: codepoints (type: const int *) Param[3]: codepointCount (type: int) @@ -3656,18 +3666,18 @@ Function 419: DrawTextCodepoints() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 420: SetTextLineSpacing() (1 input parameters) +Function 421: SetTextLineSpacing() (1 input parameters) Name: SetTextLineSpacing Return type: void Description: Set vertical line spacing when drawing with line-breaks Param[1]: spacing (type: int) -Function 421: MeasureText() (2 input parameters) +Function 422: MeasureText() (2 input parameters) Name: MeasureText Return type: int Description: Measure string width for default font Param[1]: text (type: const char *) Param[2]: fontSize (type: int) -Function 422: MeasureTextEx() (4 input parameters) +Function 423: MeasureTextEx() (4 input parameters) Name: MeasureTextEx Return type: Vector2 Description: Measure string size for Font @@ -3675,7 +3685,7 @@ Function 422: MeasureTextEx() (4 input parameters) Param[2]: text (type: const char *) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) -Function 423: MeasureTextCodepoints() (5 input parameters) +Function 424: MeasureTextCodepoints() (5 input parameters) Name: MeasureTextCodepoints Return type: Vector2 Description: Measure string size for an existing array of codepoints for Font @@ -3684,144 +3694,144 @@ Function 423: MeasureTextCodepoints() (5 input parameters) Param[3]: length (type: int) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) -Function 424: GetGlyphIndex() (2 input parameters) +Function 425: GetGlyphIndex() (2 input parameters) Name: GetGlyphIndex Return type: int Description: Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 425: GetGlyphInfo() (2 input parameters) +Function 426: GetGlyphInfo() (2 input parameters) Name: GetGlyphInfo Return type: GlyphInfo Description: Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 426: GetGlyphAtlasRec() (2 input parameters) +Function 427: GetGlyphAtlasRec() (2 input parameters) Name: GetGlyphAtlasRec Return type: Rectangle Description: Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 427: LoadUTF8() (2 input parameters) +Function 428: LoadUTF8() (2 input parameters) Name: LoadUTF8 Return type: char * Description: Load UTF-8 text encoded from codepoints array Param[1]: codepoints (type: const int *) Param[2]: length (type: int) -Function 428: UnloadUTF8() (1 input parameters) +Function 429: UnloadUTF8() (1 input parameters) Name: UnloadUTF8 Return type: void Description: Unload UTF-8 text encoded from codepoints array Param[1]: text (type: char *) -Function 429: LoadCodepoints() (2 input parameters) +Function 430: LoadCodepoints() (2 input parameters) Name: LoadCodepoints Return type: int * Description: Load all codepoints from a UTF-8 text string, codepoints count returned by parameter Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 430: UnloadCodepoints() (1 input parameters) +Function 431: UnloadCodepoints() (1 input parameters) Name: UnloadCodepoints Return type: void Description: Unload codepoints data from memory Param[1]: codepoints (type: int *) -Function 431: GetCodepointCount() (1 input parameters) +Function 432: GetCodepointCount() (1 input parameters) Name: GetCodepointCount Return type: int Description: Get total number of codepoints in a UTF-8 encoded string Param[1]: text (type: const char *) -Function 432: GetCodepoint() (2 input parameters) +Function 433: GetCodepoint() (2 input parameters) Name: GetCodepoint Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 433: GetCodepointNext() (2 input parameters) +Function 434: GetCodepointNext() (2 input parameters) Name: GetCodepointNext Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 434: GetCodepointPrevious() (2 input parameters) +Function 435: GetCodepointPrevious() (2 input parameters) Name: GetCodepointPrevious Return type: int Description: Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 435: CodepointToUTF8() (2 input parameters) +Function 436: CodepointToUTF8() (2 input parameters) Name: CodepointToUTF8 Return type: const char * Description: Encode one codepoint into UTF-8 byte array (array length returned as parameter) Param[1]: codepoint (type: int) Param[2]: utf8Size (type: int *) -Function 436: LoadTextLines() (2 input parameters) +Function 437: LoadTextLines() (2 input parameters) Name: LoadTextLines Return type: char ** Description: Load text as separate lines ('\n') Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 437: UnloadTextLines() (2 input parameters) +Function 438: UnloadTextLines() (2 input parameters) Name: UnloadTextLines Return type: void Description: Unload text lines Param[1]: text (type: char **) Param[2]: lineCount (type: int) -Function 438: TextCopy() (2 input parameters) +Function 439: TextCopy() (2 input parameters) Name: TextCopy Return type: int Description: Copy one string to another, returns bytes copied Param[1]: dst (type: char *) Param[2]: src (type: const char *) -Function 439: TextIsEqual() (2 input parameters) +Function 440: TextIsEqual() (2 input parameters) Name: TextIsEqual Return type: bool - Description: Check if two text string are equal + Description: Check if two text strings are equal Param[1]: text1 (type: const char *) Param[2]: text2 (type: const char *) -Function 440: TextLength() (1 input parameters) +Function 441: TextLength() (1 input parameters) Name: TextLength Return type: unsigned int Description: Get text length, checks for '\0' ending Param[1]: text (type: const char *) -Function 441: TextFormat() (2 input parameters) +Function 442: TextFormat() (2 input parameters) Name: TextFormat Return type: const char * Description: Text formatting with variables (sprintf() style) Param[1]: text (type: const char *) Param[2]: args (type: ...) -Function 442: TextSubtext() (3 input parameters) +Function 443: TextSubtext() (3 input parameters) Name: TextSubtext Return type: const char * Description: Get a piece of a text string Param[1]: text (type: const char *) Param[2]: position (type: int) Param[3]: length (type: int) -Function 443: TextRemoveSpaces() (1 input parameters) +Function 444: TextRemoveSpaces() (1 input parameters) Name: TextRemoveSpaces Return type: const char * Description: Remove text spaces, concat words Param[1]: text (type: const char *) -Function 444: GetTextBetween() (3 input parameters) +Function 445: GetTextBetween() (3 input parameters) Name: GetTextBetween Return type: char * Description: Get text between two strings Param[1]: text (type: const char *) Param[2]: begin (type: const char *) Param[3]: end (type: const char *) -Function 445: TextReplace() (3 input parameters) +Function 446: TextReplace() (3 input parameters) Name: TextReplace Return type: char * Description: Replace text string with new string Param[1]: text (type: const char *) Param[2]: search (type: const char *) Param[3]: replacement (type: const char *) -Function 446: TextReplaceAlloc() (3 input parameters) +Function 447: TextReplaceAlloc() (3 input parameters) Name: TextReplaceAlloc Return type: char * Description: Replace text string with new string, memory must be MemFree() Param[1]: text (type: const char *) Param[2]: search (type: const char *) Param[3]: replacement (type: const char *) -Function 447: TextReplaceBetween() (4 input parameters) +Function 448: TextReplaceBetween() (4 input parameters) Name: TextReplaceBetween Return type: char * Description: Replace text between two specific strings @@ -3829,7 +3839,7 @@ Function 447: TextReplaceBetween() (4 input parameters) Param[2]: begin (type: const char *) Param[3]: end (type: const char *) Param[4]: replacement (type: const char *) -Function 448: TextReplaceBetweenAlloc() (4 input parameters) +Function 449: TextReplaceBetweenAlloc() (4 input parameters) Name: TextReplaceBetweenAlloc Return type: char * Description: Replace text between two specific strings, memory must be MemFree() @@ -3837,96 +3847,96 @@ Function 448: TextReplaceBetweenAlloc() (4 input parameters) Param[2]: begin (type: const char *) Param[3]: end (type: const char *) Param[4]: replacement (type: const char *) -Function 449: TextInsert() (3 input parameters) +Function 450: TextInsert() (3 input parameters) Name: TextInsert Return type: char * Description: Insert text in a defined byte position Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 450: TextInsertAlloc() (3 input parameters) +Function 451: TextInsertAlloc() (3 input parameters) Name: TextInsertAlloc Return type: char * Description: Insert text in a defined byte position, memory must be MemFree() Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 451: TextJoin() (3 input parameters) +Function 452: TextJoin() (3 input parameters) Name: TextJoin Return type: char * Description: Join text strings with delimiter Param[1]: textList (type: char **) Param[2]: count (type: int) Param[3]: delimiter (type: const char *) -Function 452: TextSplit() (3 input parameters) +Function 453: TextSplit() (3 input parameters) Name: TextSplit Return type: char ** Description: Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings Param[1]: text (type: const char *) Param[2]: delimiter (type: char) Param[3]: count (type: int *) -Function 453: TextAppend() (3 input parameters) +Function 454: TextAppend() (3 input parameters) Name: TextAppend Return type: void Description: Append text at specific position and move cursor Param[1]: text (type: char *) Param[2]: append (type: const char *) Param[3]: position (type: int *) -Function 454: TextFindIndex() (2 input parameters) +Function 455: TextFindIndex() (2 input parameters) Name: TextFindIndex Return type: int Description: Find first text occurrence within a string, -1 if not found Param[1]: text (type: const char *) Param[2]: search (type: const char *) -Function 455: TextToUpper() (1 input parameters) +Function 456: TextToUpper() (1 input parameters) Name: TextToUpper Return type: char * Description: Get upper case version of provided string Param[1]: text (type: const char *) -Function 456: TextToLower() (1 input parameters) +Function 457: TextToLower() (1 input parameters) Name: TextToLower Return type: char * Description: Get lower case version of provided string Param[1]: text (type: const char *) -Function 457: TextToPascal() (1 input parameters) +Function 458: TextToPascal() (1 input parameters) Name: TextToPascal Return type: char * Description: Get Pascal case notation version of provided string Param[1]: text (type: const char *) -Function 458: TextToSnake() (1 input parameters) +Function 459: TextToSnake() (1 input parameters) Name: TextToSnake Return type: char * Description: Get Snake case notation version of provided string Param[1]: text (type: const char *) -Function 459: TextToCamel() (1 input parameters) +Function 460: TextToCamel() (1 input parameters) Name: TextToCamel Return type: char * Description: Get Camel case notation version of provided string Param[1]: text (type: const char *) -Function 460: TextToInteger() (1 input parameters) +Function 461: TextToInteger() (1 input parameters) Name: TextToInteger Return type: int Description: Get integer value from text Param[1]: text (type: const char *) -Function 461: TextToFloat() (1 input parameters) +Function 462: TextToFloat() (1 input parameters) Name: TextToFloat Return type: float Description: Get float value from text Param[1]: text (type: const char *) -Function 462: DrawLine3D() (3 input parameters) +Function 463: DrawLine3D() (3 input parameters) Name: DrawLine3D Return type: void Description: Draw a line in 3D world space Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: color (type: Color) -Function 463: DrawPoint3D() (2 input parameters) +Function 464: DrawPoint3D() (2 input parameters) Name: DrawPoint3D Return type: void Description: Draw a point in 3D space, actually a small line Param[1]: position (type: Vector3) Param[2]: color (type: Color) -Function 464: DrawCircle3D() (5 input parameters) +Function 465: DrawCircle3D() (5 input parameters) Name: DrawCircle3D Return type: void Description: Draw a circle in 3D world space @@ -3935,7 +3945,7 @@ Function 464: DrawCircle3D() (5 input parameters) Param[3]: rotationAxis (type: Vector3) Param[4]: rotationAngle (type: float) Param[5]: color (type: Color) -Function 465: DrawTriangle3D() (4 input parameters) +Function 466: DrawTriangle3D() (4 input parameters) Name: DrawTriangle3D Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -3943,14 +3953,14 @@ Function 465: DrawTriangle3D() (4 input parameters) Param[2]: v2 (type: Vector3) Param[3]: v3 (type: Vector3) Param[4]: color (type: Color) -Function 466: DrawTriangleStrip3D() (3 input parameters) +Function 467: DrawTriangleStrip3D() (3 input parameters) Name: DrawTriangleStrip3D Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector3 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 467: DrawCube() (5 input parameters) +Function 468: DrawCube() (5 input parameters) Name: DrawCube Return type: void Description: Draw cube @@ -3959,14 +3969,14 @@ Function 467: DrawCube() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 468: DrawCubeV() (3 input parameters) +Function 469: DrawCubeV() (3 input parameters) Name: DrawCubeV Return type: void Description: Draw cube (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 469: DrawCubeWires() (5 input parameters) +Function 470: DrawCubeWires() (5 input parameters) Name: DrawCubeWires Return type: void Description: Draw cube wires @@ -3975,21 +3985,21 @@ Function 469: DrawCubeWires() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 470: DrawCubeWiresV() (3 input parameters) +Function 471: DrawCubeWiresV() (3 input parameters) Name: DrawCubeWiresV Return type: void Description: Draw cube wires (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 471: DrawSphere() (3 input parameters) +Function 472: DrawSphere() (3 input parameters) Name: DrawSphere Return type: void Description: Draw sphere Param[1]: centerPos (type: Vector3) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 472: DrawSphereEx() (5 input parameters) +Function 473: DrawSphereEx() (5 input parameters) Name: DrawSphereEx Return type: void Description: Draw sphere with extended parameters @@ -3998,7 +4008,7 @@ Function 472: DrawSphereEx() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 473: DrawSphereWires() (5 input parameters) +Function 474: DrawSphereWires() (5 input parameters) Name: DrawSphereWires Return type: void Description: Draw sphere wires @@ -4007,7 +4017,7 @@ Function 473: DrawSphereWires() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 474: DrawCylinder() (6 input parameters) +Function 475: DrawCylinder() (6 input parameters) Name: DrawCylinder Return type: void Description: Draw a cylinder/cone @@ -4017,7 +4027,7 @@ Function 474: DrawCylinder() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 475: DrawCylinderEx() (6 input parameters) +Function 476: DrawCylinderEx() (6 input parameters) Name: DrawCylinderEx Return type: void Description: Draw a cylinder with base at startPos and top at endPos @@ -4027,7 +4037,7 @@ Function 475: DrawCylinderEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 476: DrawCylinderWires() (6 input parameters) +Function 477: DrawCylinderWires() (6 input parameters) Name: DrawCylinderWires Return type: void Description: Draw a cylinder/cone wires @@ -4037,7 +4047,7 @@ Function 476: DrawCylinderWires() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 477: DrawCylinderWiresEx() (6 input parameters) +Function 478: DrawCylinderWiresEx() (6 input parameters) Name: DrawCylinderWiresEx Return type: void Description: Draw a cylinder wires with base at startPos and top at endPos @@ -4047,7 +4057,7 @@ Function 477: DrawCylinderWiresEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 478: DrawCapsule() (6 input parameters) +Function 479: DrawCapsule() (6 input parameters) Name: DrawCapsule Return type: void Description: Draw a capsule with the center of its sphere caps at startPos and endPos @@ -4057,7 +4067,7 @@ Function 478: DrawCapsule() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 479: DrawCapsuleWires() (6 input parameters) +Function 480: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires Return type: void Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos @@ -4067,51 +4077,51 @@ Function 479: DrawCapsuleWires() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 480: DrawPlane() (3 input parameters) +Function 481: DrawPlane() (3 input parameters) Name: DrawPlane Return type: void Description: Draw a plane XZ Param[1]: centerPos (type: Vector3) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 481: DrawRay() (2 input parameters) +Function 482: DrawRay() (2 input parameters) Name: DrawRay Return type: void Description: Draw a ray line Param[1]: ray (type: Ray) Param[2]: color (type: Color) -Function 482: DrawGrid() (2 input parameters) +Function 483: DrawGrid() (2 input parameters) Name: DrawGrid Return type: void Description: Draw a grid (centered at (0, 0, 0)) Param[1]: slices (type: int) Param[2]: spacing (type: float) -Function 483: LoadModel() (1 input parameters) +Function 484: LoadModel() (1 input parameters) Name: LoadModel Return type: Model Description: Load model from files (meshes and materials) Param[1]: fileName (type: const char *) -Function 484: LoadModelFromMesh() (1 input parameters) +Function 485: LoadModelFromMesh() (1 input parameters) Name: LoadModelFromMesh Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 485: IsModelValid() (1 input parameters) +Function 486: IsModelValid() (1 input parameters) Name: IsModelValid Return type: bool Description: Check if a model is valid (loaded in GPU, VAO/VBOs) Param[1]: model (type: Model) -Function 486: UnloadModel() (1 input parameters) +Function 487: UnloadModel() (1 input parameters) Name: UnloadModel Return type: void Description: Unload model (including meshes) from memory (RAM and/or VRAM) Param[1]: model (type: Model) -Function 487: GetModelBoundingBox() (1 input parameters) +Function 488: GetModelBoundingBox() (1 input parameters) Name: GetModelBoundingBox Return type: BoundingBox Description: Compute model bounding box limits (considers all meshes) Param[1]: model (type: Model) -Function 488: DrawModel() (4 input parameters) +Function 489: DrawModel() (4 input parameters) Name: DrawModel Return type: void Description: Draw a model (with texture if set) @@ -4119,7 +4129,7 @@ Function 488: DrawModel() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 489: DrawModelEx() (6 input parameters) +Function 490: DrawModelEx() (6 input parameters) Name: DrawModelEx Return type: void Description: Draw a model with extended parameters @@ -4129,7 +4139,7 @@ Function 489: DrawModelEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 490: DrawModelWires() (4 input parameters) +Function 491: DrawModelWires() (4 input parameters) Name: DrawModelWires Return type: void Description: Draw a model wires (with texture if set) @@ -4137,7 +4147,7 @@ Function 490: DrawModelWires() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 491: DrawModelWiresEx() (6 input parameters) +Function 492: DrawModelWiresEx() (6 input parameters) Name: DrawModelWiresEx Return type: void Description: Draw a model wires (with texture if set) with extended parameters @@ -4147,13 +4157,13 @@ Function 491: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 492: DrawBoundingBox() (2 input parameters) +Function 493: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 493: DrawBillboard() (5 input parameters) +Function 494: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -4162,7 +4172,7 @@ Function 493: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 494: DrawBillboardRec() (6 input parameters) +Function 495: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -4172,7 +4182,7 @@ Function 494: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 495: DrawBillboardPro() (9 input parameters) +Function 496: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -4185,13 +4195,13 @@ Function 495: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 496: UploadMesh() (2 input parameters) +Function 497: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 497: UpdateMeshBuffer() (5 input parameters) +Function 498: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4200,19 +4210,19 @@ Function 497: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 498: UnloadMesh() (1 input parameters) +Function 499: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 499: DrawMesh() (3 input parameters) +Function 500: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 500: DrawMeshInstanced() (4 input parameters) +Function 501: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4220,35 +4230,35 @@ Function 500: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 501: GetMeshBoundingBox() (1 input parameters) +Function 502: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 502: GenMeshTangents() (1 input parameters) +Function 503: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 503: ExportMesh() (2 input parameters) +Function 504: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 504: ExportMeshAsCode() (2 input parameters) +Function 505: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 505: GenMeshPoly() (2 input parameters) +Function 506: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 506: GenMeshPlane() (4 input parameters) +Function 507: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4256,42 +4266,42 @@ Function 506: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 507: GenMeshCube() (3 input parameters) +Function 508: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 508: GenMeshSphere() (3 input parameters) +Function 509: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 509: GenMeshHemiSphere() (3 input parameters) +Function 510: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 510: GenMeshCylinder() (3 input parameters) +Function 511: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 511: GenMeshCone() (3 input parameters) +Function 512: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 512: GenMeshTorus() (4 input parameters) +Function 513: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4299,7 +4309,7 @@ Function 512: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 513: GenMeshKnot() (4 input parameters) +Function 514: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4307,67 +4317,67 @@ Function 513: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 514: GenMeshHeightmap() (2 input parameters) +Function 515: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 515: GenMeshCubicmap() (2 input parameters) +Function 516: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 516: LoadMaterials() (2 input parameters) +Function 517: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 517: LoadMaterialDefault() (0 input parameters) +Function 518: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 518: IsMaterialValid() (1 input parameters) +Function 519: IsMaterialValid() (1 input parameters) Name: IsMaterialValid Return type: bool Description: Check if a material is valid (shader assigned, map textures loaded in GPU) Param[1]: material (type: Material) -Function 519: UnloadMaterial() (1 input parameters) +Function 520: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 520: SetMaterialTexture() (3 input parameters) +Function 521: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 521: SetModelMeshMaterial() (3 input parameters) +Function 522: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 522: LoadModelAnimations() (2 input parameters) +Function 523: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 523: UpdateModelAnimation() (3 input parameters) +Function 524: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose (vertex buffers and bone matrices) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: float) -Function 524: UpdateModelAnimationEx() (6 input parameters) +Function 525: UpdateModelAnimationEx() (6 input parameters) Name: UpdateModelAnimationEx Return type: void Description: Update model animation pose, blending two animations @@ -4377,19 +4387,19 @@ Function 524: UpdateModelAnimationEx() (6 input parameters) Param[4]: animB (type: ModelAnimation) Param[5]: frameB (type: float) Param[6]: blend (type: float) -Function 525: UnloadModelAnimations() (2 input parameters) +Function 526: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 526: IsModelAnimationValid() (2 input parameters) +Function 527: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 527: CheckCollisionSpheres() (4 input parameters) +Function 528: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4397,40 +4407,40 @@ Function 527: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 528: CheckCollisionBoxes() (2 input parameters) +Function 529: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 529: CheckCollisionBoxSphere() (3 input parameters) +Function 530: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 530: GetRayCollisionSphere() (3 input parameters) +Function 531: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 531: GetRayCollisionBox() (2 input parameters) +Function 532: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 532: GetRayCollisionMesh() (3 input parameters) +Function 533: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 533: GetRayCollisionTriangle() (4 input parameters) +Function 534: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4438,7 +4448,7 @@ Function 533: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 534: GetRayCollisionQuad() (5 input parameters) +Function 535: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4447,158 +4457,158 @@ Function 534: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 535: InitAudioDevice() (0 input parameters) +Function 536: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 536: CloseAudioDevice() (0 input parameters) +Function 537: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 537: IsAudioDeviceReady() (0 input parameters) +Function 538: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 538: SetMasterVolume() (1 input parameters) +Function 539: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 539: GetMasterVolume() (0 input parameters) +Function 540: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 540: LoadWave() (1 input parameters) +Function 541: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 541: LoadWaveFromMemory() (3 input parameters) +Function 542: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 542: IsWaveValid() (1 input parameters) +Function 543: IsWaveValid() (1 input parameters) Name: IsWaveValid Return type: bool - Description: Checks if wave data is valid (data loaded and parameters) + Description: Check if wave data is valid (data loaded and parameters) Param[1]: wave (type: Wave) -Function 543: LoadSound() (1 input parameters) +Function 544: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 544: LoadSoundFromWave() (1 input parameters) +Function 545: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 545: LoadSoundAlias() (1 input parameters) - Name: LoadSoundAlias - Return type: Sound - Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data - Param[1]: source (type: Sound) -Function 546: IsSoundValid() (1 input parameters) - Name: IsSoundValid - Return type: bool - Description: Checks if a sound is valid (data loaded and buffers initialized) - Param[1]: sound (type: Sound) -Function 547: UpdateSound() (3 input parameters) +Function 546: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data (default data format: 32 bit float, stereo) Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 548: UnloadWave() (1 input parameters) +Function 547: LoadSoundAlias() (1 input parameters) + Name: LoadSoundAlias + Return type: Sound + Description: Load sound alias, new sound that shares the same sample data as the source sound, does not own the sound data + Param[1]: source (type: Sound) +Function 548: IsSoundValid() (1 input parameters) + Name: IsSoundValid + Return type: bool + Description: Check if a sound is valid (data loaded and buffers initialized) + Param[1]: sound (type: Sound) +Function 549: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 549: UnloadSound() (1 input parameters) +Function 550: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 550: UnloadSoundAlias() (1 input parameters) +Function 551: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void - Description: Unload a sound alias (does not deallocate sample data) + Description: Unload sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 551: ExportWave() (2 input parameters) +Function 552: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 552: ExportWaveAsCode() (2 input parameters) +Function 553: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 553: PlaySound() (1 input parameters) +Function 554: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 554: StopSound() (1 input parameters) +Function 555: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 555: PauseSound() (1 input parameters) +Function 556: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 556: ResumeSound() (1 input parameters) +Function 557: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 557: IsSoundPlaying() (1 input parameters) +Function 558: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 558: SetSoundVolume() (2 input parameters) +Function 559: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 559: SetSoundPitch() (2 input parameters) +Function 560: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 560: SetSoundPan() (2 input parameters) +Function 561: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (-1.0 left, 0.0 center, 1.0 right) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 561: WaveCopy() (1 input parameters) +Function 562: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 562: WaveCrop() (3 input parameters) +Function 563: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 563: WaveFormat() (4 input parameters) +Function 564: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4606,203 +4616,203 @@ Function 563: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 564: LoadWaveSamples() (1 input parameters) +Function 565: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 565: UnloadWaveSamples() (1 input parameters) +Function 566: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 566: LoadMusicStream() (1 input parameters) +Function 567: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 567: LoadMusicStreamFromMemory() (3 input parameters) +Function 568: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 568: IsMusicValid() (1 input parameters) +Function 569: IsMusicValid() (1 input parameters) Name: IsMusicValid Return type: bool - Description: Checks if a music stream is valid (context and buffers initialized) + Description: Check if a music stream is valid (context and buffers initialized) Param[1]: music (type: Music) -Function 569: UnloadMusicStream() (1 input parameters) +Function 570: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 570: PlayMusicStream() (1 input parameters) +Function 571: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 571: IsMusicStreamPlaying() (1 input parameters) +Function 572: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 572: UpdateMusicStream() (1 input parameters) +Function 573: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void - Description: Updates buffers for music streaming + Description: Update buffers for music streaming Param[1]: music (type: Music) -Function 573: StopMusicStream() (1 input parameters) +Function 574: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 574: PauseMusicStream() (1 input parameters) +Function 575: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 575: ResumeMusicStream() (1 input parameters) +Function 576: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 576: SeekMusicStream() (2 input parameters) +Function 577: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 577: SetMusicVolume() (2 input parameters) +Function 578: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 578: SetMusicPitch() (2 input parameters) +Function 579: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void - Description: Set pitch for a music (1.0 is base level) + Description: Set pitch for music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 579: SetMusicPan() (2 input parameters) +Function 580: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void - Description: Set pan for a music (-1.0 left, 0.0 center, 1.0 right) + Description: Set pan for music (-1.0 left, 0.0 center, 1.0 right) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 580: GetMusicTimeLength() (1 input parameters) +Function 581: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 581: GetMusicTimePlayed() (1 input parameters) +Function 582: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 582: LoadAudioStream() (3 input parameters) +Function 583: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 583: IsAudioStreamValid() (1 input parameters) +Function 584: IsAudioStreamValid() (1 input parameters) Name: IsAudioStreamValid Return type: bool - Description: Checks if an audio stream is valid (buffers initialized) + Description: Check if an audio stream is valid (buffers initialized) Param[1]: stream (type: AudioStream) -Function 584: UnloadAudioStream() (1 input parameters) +Function 585: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 585: UpdateAudioStream() (3 input parameters) +Function 586: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 586: IsAudioStreamProcessed() (1 input parameters) +Function 587: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 587: PlayAudioStream() (1 input parameters) +Function 588: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 588: PauseAudioStream() (1 input parameters) +Function 589: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 589: ResumeAudioStream() (1 input parameters) +Function 590: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 590: IsAudioStreamPlaying() (1 input parameters) +Function 591: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 591: StopAudioStream() (1 input parameters) +Function 592: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 592: SetAudioStreamVolume() (2 input parameters) +Function 593: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 593: SetAudioStreamPitch() (2 input parameters) +Function 594: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 594: SetAudioStreamPan() (2 input parameters) +Function 595: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void - Description: Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered) + Description: Set pan for audio stream (-1.0 left, 0.0 center, 1.0 right) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 595: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 596: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 596: SetAudioStreamCallback() (2 input parameters) +Function 597: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 597: AttachAudioStreamProcessor() (2 input parameters) +Function 598: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives frames x 2 samples as 'float' (stereo) Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 598: DetachAudioStreamProcessor() (2 input parameters) +Function 599: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 599: AttachAudioMixedProcessor() (1 input parameters) +Function 600: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives frames x 2 samples as 'float' (stereo) Param[1]: processor (type: AudioCallback) -Function 600: DetachAudioMixedProcessor() (1 input parameters) +Function 601: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 98a52749e..91cfe8451 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -682,7 +682,7 @@ - + @@ -809,39 +809,39 @@ - + - + - + - + - + - + - + - + - + - + @@ -927,21 +927,21 @@ - + - + - + - + @@ -985,7 +985,7 @@ - + @@ -1325,7 +1325,7 @@ - + @@ -1560,7 +1560,7 @@ - + @@ -1573,6 +1573,14 @@ + + + + + + + + @@ -1589,7 +1597,7 @@ - + @@ -1725,7 +1733,7 @@ - + @@ -1796,7 +1804,7 @@ - + @@ -2247,7 +2255,7 @@ - + @@ -2414,7 +2422,7 @@ - + @@ -2500,7 +2508,7 @@ - + @@ -3002,7 +3010,7 @@ - + @@ -3011,24 +3019,24 @@ - - - - - - + + + + + + - + @@ -3094,7 +3102,7 @@ - + @@ -3106,7 +3114,7 @@ - + @@ -3126,11 +3134,11 @@ - + - + @@ -3145,7 +3153,7 @@ - + @@ -3182,7 +3190,7 @@ - + From 620b21bfce33acc25befc663d6d322932ef583fa Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 11:36:32 +0200 Subject: [PATCH 141/185] REVIEWED: Several functions `const` correctness --- src/raylib.h | 10 +++++----- src/rcore.c | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 3795de752..b1a55060d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1126,7 +1126,7 @@ RLAPI void MemFree(void *ptr); // Internal memo // File system management functions RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read) RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData() -RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success +RLAPI bool SaveFileData(const char *fileName, const void *data, int dataSize); // Save data to file from byte array (write), returns true on success RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText() @@ -1175,10 +1175,10 @@ RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int * RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree() RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string (includes NULL terminator), memory must be MemFree() RLAPI unsigned char *DecodeDataBase64(const char *text, int *outputSize); // Decode Base64 string (expected NULL terminated), memory must be MemFree() -RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code -RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes) -RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes) -RLAPI unsigned int *ComputeSHA256(unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 bytes) +RLAPI unsigned int ComputeCRC32(const unsigned char *data, int dataSize); // Compute CRC32 hash code +RLAPI unsigned int *ComputeMD5(const unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes) +RLAPI unsigned int *ComputeSHA1(const unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes) +RLAPI unsigned int *ComputeSHA256(const unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 bytes) // Automation events functionality RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS diff --git a/src/rcore.c b/src/rcore.c index b5040089b..8ee85a072 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -2028,7 +2028,7 @@ void UnloadFileData(unsigned char *data) } // Save data to file from buffer -bool SaveFileData(const char *fileName, void *data, int dataSize) +bool SaveFileData(const char *fileName, const void *data, int dataSize) { bool result = false; @@ -3163,7 +3163,7 @@ unsigned char *DecodeDataBase64(const char *text, int *outputSize) } // Compute CRC32 hash code -unsigned int ComputeCRC32(unsigned char *data, int dataSize) +unsigned int ComputeCRC32(const unsigned char *data, int dataSize) { static unsigned int crcTable[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, @@ -3209,7 +3209,7 @@ unsigned int ComputeCRC32(unsigned char *data, int dataSize) // Compute MD5 hash code // NOTE: Returns a static int[4] array (16 bytes) -unsigned int *ComputeMD5(unsigned char *data, int dataSize) +unsigned int *ComputeMD5(const unsigned char *data, int dataSize) { #define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) @@ -3327,7 +3327,7 @@ unsigned int *ComputeMD5(unsigned char *data, int dataSize) // Compute SHA-1 hash code // NOTE: Returns a static int[5] array (20 bytes) -unsigned int *ComputeSHA1(unsigned char *data, int dataSize) +unsigned int *ComputeSHA1(const unsigned char *data, int dataSize) { #define SHA1_ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) @@ -3437,7 +3437,7 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize) // Compute SHA-256 hash code // NOTE: Returns a static int[8] array (32 bytes) -unsigned int *ComputeSHA256(unsigned char *data, int dataSize) +unsigned int *ComputeSHA256(const unsigned char *data, int dataSize) { #define SHA256_ROTATE_RIGHT(x, c) ((x >> c) | (x << ((sizeof(unsigned int)*8) - c))) #define SHA256_A0(x) (SHA256_ROTATE_RIGHT(x, 7) ^ SHA256_ROTATE_RIGHT(x, 18) ^ (x >> 3)) From 826ca42d8362412fe238c2ea14577b2cfa7a175e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:36:49 +0000 Subject: [PATCH 142/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 10 +++++----- tools/rlparser/output/raylib_api.lua | 10 +++++----- tools/rlparser/output/raylib_api.txt | 10 +++++----- tools/rlparser/output/raylib_api.xml | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index 7bb3ca5a3..b2e66650f 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -4316,7 +4316,7 @@ "name": "fileName" }, { - "type": "void *", + "type": "const void *", "name": "data" }, { @@ -4853,7 +4853,7 @@ "returnType": "unsigned int", "params": [ { - "type": "unsigned char *", + "type": "const unsigned char *", "name": "data" }, { @@ -4868,7 +4868,7 @@ "returnType": "unsigned int *", "params": [ { - "type": "unsigned char *", + "type": "const unsigned char *", "name": "data" }, { @@ -4883,7 +4883,7 @@ "returnType": "unsigned int *", "params": [ { - "type": "unsigned char *", + "type": "const unsigned char *", "name": "data" }, { @@ -4898,7 +4898,7 @@ "returnType": "unsigned int *", "params": [ { - "type": "unsigned char *", + "type": "const unsigned char *", "name": "data" }, { diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index 7a6bb8b06..45059c0b2 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -3949,7 +3949,7 @@ return { returnType = "bool", params = { {type = "const char *", name = "fileName"}, - {type = "void *", name = "data"}, + {type = "const void *", name = "data"}, {type = "int", name = "dataSize"} } }, @@ -4303,7 +4303,7 @@ return { description = "Compute CRC32 hash code", returnType = "unsigned int", params = { - {type = "unsigned char *", name = "data"}, + {type = "const unsigned char *", name = "data"}, {type = "int", name = "dataSize"} } }, @@ -4312,7 +4312,7 @@ return { description = "Compute MD5 hash code, returns static int[4] (16 bytes)", returnType = "unsigned int *", params = { - {type = "unsigned char *", name = "data"}, + {type = "const unsigned char *", name = "data"}, {type = "int", name = "dataSize"} } }, @@ -4321,7 +4321,7 @@ return { description = "Compute SHA1 hash code, returns static int[5] (20 bytes)", returnType = "unsigned int *", params = { - {type = "unsigned char *", name = "data"}, + {type = "const unsigned char *", name = "data"}, {type = "int", name = "dataSize"} } }, @@ -4330,7 +4330,7 @@ return { description = "Compute SHA256 hash code, returns static int[8] (32 bytes)", returnType = "unsigned int *", params = { - {type = "unsigned char *", name = "data"}, + {type = "const unsigned char *", name = "data"}, {type = "int", name = "dataSize"} } }, diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index 7df03e619..36f184a13 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -1619,7 +1619,7 @@ Function 115: SaveFileData() (3 input parameters) Return type: bool Description: Save data to file from byte array (write), returns true on success Param[1]: fileName (type: const char *) - Param[2]: data (type: void *) + Param[2]: data (type: const void *) Param[3]: dataSize (type: int) Function 116: ExportDataAsCode() (3 input parameters) Name: ExportDataAsCode @@ -1856,25 +1856,25 @@ Function 158: ComputeCRC32() (2 input parameters) Name: ComputeCRC32 Return type: unsigned int Description: Compute CRC32 hash code - Param[1]: data (type: unsigned char *) + Param[1]: data (type: const unsigned char *) Param[2]: dataSize (type: int) Function 159: ComputeMD5() (2 input parameters) Name: ComputeMD5 Return type: unsigned int * Description: Compute MD5 hash code, returns static int[4] (16 bytes) - Param[1]: data (type: unsigned char *) + Param[1]: data (type: const unsigned char *) Param[2]: dataSize (type: int) Function 160: ComputeSHA1() (2 input parameters) Name: ComputeSHA1 Return type: unsigned int * Description: Compute SHA1 hash code, returns static int[5] (20 bytes) - Param[1]: data (type: unsigned char *) + Param[1]: data (type: const unsigned char *) Param[2]: dataSize (type: int) Function 161: ComputeSHA256() (2 input parameters) Name: ComputeSHA256 Return type: unsigned int * Description: Compute SHA256 hash code, returns static int[8] (32 bytes) - Param[1]: data (type: unsigned char *) + Param[1]: data (type: const unsigned char *) Param[2]: dataSize (type: int) Function 162: LoadAutomationEventList() (1 input parameters) Name: LoadAutomationEventList diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 91cfe8451..8f65730c0 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -1021,7 +1021,7 @@ - + @@ -1168,19 +1168,19 @@ - + - + - + - + From 636269f6afedd2581b31be848bd3838a4fa11bcf Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 11:37:48 +0200 Subject: [PATCH 143/185] ADDED: `DrawTriangleGradient()` --- src/rshapes.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/rshapes.c b/src/rshapes.c index f09b972eb..5c4fec282 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -1421,6 +1421,12 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f // Draw a triangle // NOTE: Vertex must be provided in counter-clockwise order void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) +{ + DrawTriangleGradient(v1, v2, v3, color, color, color); +} + +// Draw triangle with interpolated colors (vertex in counter-clockwise order!) +void DrawTriangleGradient(Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3) { #if SUPPORT_QUADS_DRAW_MODE rlSetTexture(GetShapesTexture().id); @@ -1428,17 +1434,20 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) rlBegin(RL_QUADS); rlNormal3f(0.0f, 0.0f, 1.0f); - rlColor4ub(color.r, color.g, color.b, color.a); - + + rlColor4ub(c1.r, c1.g, c1.b, c1.a); rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); rlVertex2f(v1.x, v1.y); + rlColor4ub(c2.r, c2.g, c2.b, c2.a); rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); rlVertex2f(v2.x, v2.y); + rlColor4ub(c3.r, c3.g, c3.b, c3.a); rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); rlVertex2f(v3.x, v3.y); + rlColor4ub(c3.r, c3.g, c3.b, c3.a); rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); rlVertex2f(v3.x, v3.y); rlEnd(); @@ -1446,9 +1455,11 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) rlSetTexture(0); #else rlBegin(RL_TRIANGLES); - rlColor4ub(color.r, color.g, color.b, color.a); + rlColor4ub(c1.r, c1.g, c1.b, c1.a); rlVertex2f(v1.x, v1.y); + rlColor4ub(c2.r, c2.g, c2.b, c2.a); rlVertex2f(v2.x, v2.y); + rlColor4ub(c3.r, c3.g, c3.b, c3.a); rlVertex2f(v3.x, v3.y); rlEnd(); #endif From 3b70f83c7d77bb839f30e5c7c17a9ba41003a620 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 11:38:23 +0200 Subject: [PATCH 144/185] Update raylib.h --- src/raylib.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index b1a55060d..cfaf7ab7f 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -963,10 +963,10 @@ typedef enum { // Callbacks to hook some internal functions // WARNING: These callbacks are intended for advanced users -typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages -typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data -typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data -typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data +typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages +typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data +typedef bool (*SaveFileDataCallback)(const char *fileName, const void *data, int dataSize); // FileIO: Save binary data +typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data typedef bool (*SaveFileTextCallback)(const char *fileName, const char *text); // FileIO: Save text data //------------------------------------------------------------------------------------ From a685b812d9c547167d66ab29c6a96f2bbad9c46b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:38:41 +0000 Subject: [PATCH 145/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 2 +- tools/rlparser/output/raylib_api.lua | 2 +- tools/rlparser/output/raylib_api.txt | 2 +- tools/rlparser/output/raylib_api.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index b2e66650f..a8d7c4fb1 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -3120,7 +3120,7 @@ "name": "fileName" }, { - "type": "void *", + "type": "const void *", "name": "data" }, { diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index 45059c0b2..6cc3fdef3 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -3101,7 +3101,7 @@ return { returnType = "bool", params = { {type = "const char *", name = "fileName"}, - {type = "void *", name = "data"}, + {type = "const void *", name = "data"}, {type = "int", name = "dataSize"} } }, diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index 36f184a13..773865686 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -980,7 +980,7 @@ Callback 003: SaveFileDataCallback() (3 input parameters) Return type: bool Description: FileIO: Save binary data Param[1]: fileName (type: const char *) - Param[2]: data (type: void *) + Param[2]: data (type: const void *) Param[3]: dataSize (type: int) Callback 004: LoadFileTextCallback() (1 input parameters) Name: LoadFileTextCallback diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 8f65730c0..ae898be4e 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -667,7 +667,7 @@ - + From 3d2008c70b4eaf631a99a9ed9a8c7328327694b0 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 11:40:14 +0200 Subject: [PATCH 146/185] RENAMED: `ImageDrawTriangleEx()` to `ImageDrawTriangleGradient()` For consistency with the new `DrawTriangleGradient()` --- src/raylib.h | 2 +- src/rtextures.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index cfaf7ab7f..6c343d7b5 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1429,7 +1429,7 @@ RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image -RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image +RLAPI void ImageDrawTriangleGradient(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image RLAPI void ImageDrawTriangleFan(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center) RLAPI void ImageDrawTriangleStrip(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image diff --git a/src/rtextures.c b/src/rtextures.c index 45282ec20..773720e76 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -3806,7 +3806,7 @@ void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color col } // Draw triangle with interpolated colors within an image -void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3) +void ImageDrawTriangleGradient(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3) { // Calculate the 2D bounding box of the triangle // Determine the minimum and maximum x and y coordinates of the triangle vertices From 5082f5a813f9fd4cb6694747a78cd5a0cce89bb7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:40:32 +0000 Subject: [PATCH 147/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 2 +- tools/rlparser/output/raylib_api.lua | 2 +- tools/rlparser/output/raylib_api.txt | 4 ++-- tools/rlparser/output/raylib_api.xml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index a8d7c4fb1..4148dd9ca 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -8431,7 +8431,7 @@ ] }, { - "name": "ImageDrawTriangleEx", + "name": "ImageDrawTriangleGradient", "description": "Draw triangle with interpolated colors within an image", "returnType": "void", "params": [ diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index 6cc3fdef3..3cbe3f0ae 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -6226,7 +6226,7 @@ return { } }, { - name = "ImageDrawTriangleEx", + name = "ImageDrawTriangleGradient", description = "Draw triangle with interpolated colors within an image", returnType = "void", params = { diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index 773865686..30d44a5db 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -3239,8 +3239,8 @@ Function 360: ImageDrawTriangle() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 361: ImageDrawTriangleEx() (7 input parameters) - Name: ImageDrawTriangleEx +Function 361: ImageDrawTriangleGradient() (7 input parameters) + Name: ImageDrawTriangleGradient Return type: void Description: Draw triangle with interpolated colors within an image Param[1]: dst (type: Image *) diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index ae898be4e..9c833d685 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -2125,7 +2125,7 @@ - + From 361dcb2a1ffe7c958639f47333695c01d750459f Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 11:42:53 +0200 Subject: [PATCH 148/185] WARNING: REVIEWED: `DrawCapsule()`/`DrawCapsuleWires()` parameter order for consistency with `DrawSphere*()` --- src/raylib.h | 6 +++--- src/rmodels.c | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 6c343d7b5..42ca7eabd 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1577,9 +1577,9 @@ RLAPI void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slice RLAPI void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone RLAPI void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder with base at startPos and top at endPos RLAPI void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires -RLAPI void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder wires with base at startPos and top at endPos -RLAPI void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw a capsule with the center of its sphere caps at startPos and endPos -RLAPI void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw capsule wireframe with the center of its sphere caps at startPos and endPos +RLAPI void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int slices, Color color); // Draw a cylinder wires with base at startPos and top at endPos +RLAPI void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int rings, int slices, Color color); // Draw a capsule with the center of its sphere caps at startPos and endPos +RLAPI void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int rings, int slices, Color color); // Draw capsule wireframe with the center of its sphere caps at startPos and endPos RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0)) diff --git a/src/rmodels.c b/src/rmodels.c index bcc481962..eb7f30cb8 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -724,9 +724,9 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl // Draw a wired cylinder with base at startPos and top at endPos // NOTE: It could be also used for pyramid and cone -void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color) +void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int slices, Color color) { - if (sides < 3) sides = 3; + if (slices < 3) slices = 3; Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z }; if ((direction.x == 0) && (direction.y == 0) && (direction.z == 0)) return; // Security check @@ -735,12 +735,12 @@ void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, fl Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction)); Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction)); - float baseAngle = (2.0f*PI)/sides; + float baseAngle = (2.0f*PI)/slices; rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); - for (int i = 0; i < sides; i++) + for (int i = 0; i < slices; i++) { // Compute the four vertices float s1 = sinf(baseAngle*(i + 0))*startRadius; @@ -769,7 +769,7 @@ void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, fl } // Draw a capsule with the center of its sphere caps at startPos and endPos -void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color) +void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int rings, int slices, Color color) { if (slices < 3) slices = 3; @@ -908,7 +908,7 @@ void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int } // Draw capsule wires with the center of its sphere caps at startPos and endPos -void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color) +void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int rings, int slices, Color color) { if (slices < 3) slices = 3; From a627cd5b6539dc1a53f66ac4ffef2b5e8371589c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:43:37 +0000 Subject: [PATCH 149/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 10 +++++----- tools/rlparser/output/raylib_api.lua | 6 +++--- tools/rlparser/output/raylib_api.txt | 10 +++++----- tools/rlparser/output/raylib_api.xml | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index 4148dd9ca..2e21430aa 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -10626,7 +10626,7 @@ }, { "type": "int", - "name": "sides" + "name": "slices" }, { "type": "Color", @@ -10653,11 +10653,11 @@ }, { "type": "int", - "name": "slices" + "name": "rings" }, { "type": "int", - "name": "rings" + "name": "slices" }, { "type": "Color", @@ -10684,11 +10684,11 @@ }, { "type": "int", - "name": "slices" + "name": "rings" }, { "type": "int", - "name": "rings" + "name": "slices" }, { "type": "Color", diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index 3cbe3f0ae..e8989a3c6 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -7390,7 +7390,7 @@ return { {type = "Vector3", name = "endPos"}, {type = "float", name = "startRadius"}, {type = "float", name = "endRadius"}, - {type = "int", name = "sides"}, + {type = "int", name = "slices"}, {type = "Color", name = "color"} } }, @@ -7402,8 +7402,8 @@ return { {type = "Vector3", name = "startPos"}, {type = "Vector3", name = "endPos"}, {type = "float", name = "radius"}, - {type = "int", name = "slices"}, {type = "int", name = "rings"}, + {type = "int", name = "slices"}, {type = "Color", name = "color"} } }, @@ -7415,8 +7415,8 @@ return { {type = "Vector3", name = "startPos"}, {type = "Vector3", name = "endPos"}, {type = "float", name = "radius"}, - {type = "int", name = "slices"}, {type = "int", name = "rings"}, + {type = "int", name = "slices"}, {type = "Color", name = "color"} } }, diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index 30d44a5db..440113aa7 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -4055,7 +4055,7 @@ Function 478: DrawCylinderWiresEx() (6 input parameters) Param[2]: endPos (type: Vector3) Param[3]: startRadius (type: float) Param[4]: endRadius (type: float) - Param[5]: sides (type: int) + Param[5]: slices (type: int) Param[6]: color (type: Color) Function 479: DrawCapsule() (6 input parameters) Name: DrawCapsule @@ -4064,8 +4064,8 @@ Function 479: DrawCapsule() (6 input parameters) Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: radius (type: float) - Param[4]: slices (type: int) - Param[5]: rings (type: int) + Param[4]: rings (type: int) + Param[5]: slices (type: int) Param[6]: color (type: Color) Function 480: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires @@ -4074,8 +4074,8 @@ Function 480: DrawCapsuleWires() (6 input parameters) Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: radius (type: float) - Param[4]: slices (type: int) - Param[5]: rings (type: int) + Param[4]: rings (type: int) + Param[5]: slices (type: int) Param[6]: color (type: Color) Function 481: DrawPlane() (3 input parameters) Name: DrawPlane diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 9c833d685..b7d1bdc17 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -2703,23 +2703,23 @@ - + - + - + From 275283783928d792844afa1520ada7323b103694 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 11:44:14 +0200 Subject: [PATCH 150/185] REVIEWED: `UpdateSound()`, missleading parameter name! --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index 42ca7eabd..3f098d86c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1672,9 +1672,9 @@ RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileDat RLAPI bool IsWaveValid(Wave wave); // Check if wave data is valid (data loaded and parameters) RLAPI Sound LoadSound(const char *fileName); // Load sound from file RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data -RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data (default data format: 32 bit float, stereo) RLAPI Sound LoadSoundAlias(Sound source); // Load sound alias, new sound that shares the same sample data as the source sound, does not own the sound data RLAPI bool IsSoundValid(Sound sound); // Check if a sound is valid (data loaded and buffers initialized) +RLAPI void UpdateSound(Sound sound, const void *data, int frameCount); // Update sound buffer with new data (default data format: 32 bit float, stereo) RLAPI void UnloadWave(Wave wave); // Unload wave data RLAPI void UnloadSound(Sound sound); // Unload sound RLAPI void UnloadSoundAlias(Sound alias); // Unload sound alias (does not deallocate sample data) From 0e68f812b5a487424f0839cb0f1ed78df90845dd Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 11:45:50 +0200 Subject: [PATCH 151/185] WARNING: REDESIGNED: `ImageDrawRectangleLines()`, consistency with `DrawRectangleLines()` ADDED: `ImageDrawRectangleLinesEx()` --- src/raylib.h | 3 ++- src/rtextures.c | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 3f098d86c..f7eebd08b 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1427,7 +1427,8 @@ RLAPI void ImageDrawCircleLinesV(Image *dst, Vector2 center, int radius, Color c RLAPI void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle within an image RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version) RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image -RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image +RLAPI void ImageDrawRectangleLines(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle lines within an image +RLAPI void ImageDrawRectangleLinesEx(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image with extended parameters RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image RLAPI void ImageDrawTriangleGradient(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image diff --git a/src/rtextures.c b/src/rtextures.c index 773720e76..80206ecf7 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -3730,7 +3730,14 @@ void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color) } // Draw rectangle lines within an image -void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color) +void ImageDrawRectangleLines(Image *dst, int posX, int posY, int width, int height, Color color) +{ + Rectangle rec = { posX, posY, width, height }; + ImageDrawRectangleLinesEx(dst, rec, 1, color); +} + +// Draw rectangle lines within an image with extended parameters +void ImageDrawRectangleLinesEx(Image *dst, Rectangle rec, int thick, Color color) { ImageDrawRectangle(dst, (int)rec.x, (int)rec.y, (int)rec.width, thick, color); ImageDrawRectangle(dst, (int)rec.x, (int)(rec.y + thick), thick, (int)(rec.height - thick*2), color); From c9c26d80714bf8bbe3dfb45bd11f02411f6dfca6 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 11:46:43 +0200 Subject: [PATCH 152/185] REVIEWED: `ImageColorContrast()` parameter type, consistent with other `Image*()` functions --- src/raylib.h | 2 +- src/rtextures.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index f7eebd08b..d85a97cfb 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1402,7 +1402,7 @@ RLAPI void ImageRotateCCW(Image *image); RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint RLAPI void ImageColorInvert(Image *image); // Modify image color: invert RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale -RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100) +RLAPI void ImageColorContrast(Image *image, int contrast); // Modify image color: contrast (-100 to 100) RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255) RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit) diff --git a/src/rtextures.c b/src/rtextures.c index 80206ecf7..ba50d9d02 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -2795,7 +2795,7 @@ void ImageColorGrayscale(Image *image) // Modify image color: contrast // NOTE: Contrast values between -100 and 100 -void ImageColorContrast(Image *image, float contrast) +void ImageColorContrast(Image *image, int contrast) { // Security check to avoid program crash if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return; @@ -2803,8 +2803,8 @@ void ImageColorContrast(Image *image, float contrast) if (contrast < -100) contrast = -100; if (contrast > 100) contrast = 100; - contrast = (100.0f + contrast)/100.0f; - contrast *= contrast; + float factor = (float)(100.0f + contrast)/100.0f; + factor *= factor; Color *pixels = LoadImageColors(*image); @@ -2812,7 +2812,7 @@ void ImageColorContrast(Image *image, float contrast) { float pR = (float)pixels[i].r/255.0f; pR -= 0.5f; - pR *= contrast; + pR *= factor; pR += 0.5f; pR *= 255; if (pR < 0) pR = 0; @@ -2820,7 +2820,7 @@ void ImageColorContrast(Image *image, float contrast) float pG = (float)pixels[i].g/255.0f; pG -= 0.5f; - pG *= contrast; + pG *= factor; pG += 0.5f; pG *= 255; if (pG < 0) pG = 0; @@ -2828,7 +2828,7 @@ void ImageColorContrast(Image *image, float contrast) float pB = (float)pixels[i].b/255.0f; pB -= 0.5f; - pB *= contrast; + pB *= factor; pB += 0.5f; pB *= 255; if (pB < 0) pB = 0; From 98efce4b0d2b717c9abd4df1e07bfcb6e98a643a Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 11:47:48 +0200 Subject: [PATCH 153/185] WARNING: RENAMED: `GetSplinePointBezierQuad()` to `GetSplinePointBezierQuadratic()` Consistent with similar spline functions and avoid confusion with `Quad` related functions. --- src/raylib.h | 2 +- src/rshapes.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index d85a97cfb..48f2724e1 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1328,7 +1328,7 @@ RLAPI void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vect RLAPI Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t); // Get (evaluate) spline point: Linear RLAPI Vector2 GetSplinePointBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: B-Spline RLAPI Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: Catmull-Rom -RLAPI Vector2 GetSplinePointBezierQuad(Vector2 p1, Vector2 c2, Vector2 p3, float t); // Get (evaluate) spline point: Quadratic Bezier +RLAPI Vector2 GetSplinePointBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float t); // Get (evaluate) spline point: Quadratic Bezier RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float t); // Get (evaluate) spline point: Cubic Bezier // Basic shapes collision detection functions diff --git a/src/rshapes.c b/src/rshapes.c index 5c4fec282..fa7f2cf2f 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -2225,7 +2225,7 @@ Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, } // Get spline point for a given t [0.0f .. 1.0f], Quadratic Bezier -Vector2 GetSplinePointBezierQuad(Vector2 startPos, Vector2 controlPos, Vector2 endPos, float t) +Vector2 GetSplinePointBezierQuadratic(Vector2 startPos, Vector2 controlPos, Vector2 endPos, float t) { Vector2 point = { 0 }; From 79d5353cfd849a92bf2e1d62daacb9ceafde47b9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:48:08 +0000 Subject: [PATCH 154/185] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 73 ++-- tools/rlparser/output/raylib_api.lua | 37 +- tools/rlparser/output/raylib_api.txt | 512 +++++++++++++------------- tools/rlparser/output/raylib_api.xml | 26 +- 4 files changed, 355 insertions(+), 293 deletions(-) diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index 2e21430aa..aa018051a 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -6838,7 +6838,7 @@ ] }, { - "name": "GetSplinePointBezierQuad", + "name": "GetSplinePointBezierQuadratic", "description": "Get (evaluate) spline point: Quadratic Bezier", "returnType": "Vector2", "params": [ @@ -7944,7 +7944,7 @@ "name": "image" }, { - "type": "float", + "type": "int", "name": "contrast" } ] @@ -8384,6 +8384,37 @@ "name": "ImageDrawRectangleLines", "description": "Draw rectangle lines within an image", "returnType": "void", + "params": [ + { + "type": "Image *", + "name": "dst" + }, + { + "type": "int", + "name": "posX" + }, + { + "type": "int", + "name": "posY" + }, + { + "type": "int", + "name": "width" + }, + { + "type": "int", + "name": "height" + }, + { + "type": "Color", + "name": "color" + } + ] + }, + { + "name": "ImageDrawRectangleLinesEx", + "description": "Draw rectangle lines within an image with extended parameters", + "returnType": "void", "params": [ { "type": "Image *", @@ -11809,25 +11840,6 @@ } ] }, - { - "name": "UpdateSound", - "description": "Update sound buffer with new data (default data format: 32 bit float, stereo)", - "returnType": "void", - "params": [ - { - "type": "Sound", - "name": "sound" - }, - { - "type": "const void *", - "name": "data" - }, - { - "type": "int", - "name": "sampleCount" - } - ] - }, { "name": "LoadSoundAlias", "description": "Load sound alias, new sound that shares the same sample data as the source sound, does not own the sound data", @@ -11850,6 +11862,25 @@ } ] }, + { + "name": "UpdateSound", + "description": "Update sound buffer with new data (default data format: 32 bit float, stereo)", + "returnType": "void", + "params": [ + { + "type": "Sound", + "name": "sound" + }, + { + "type": "const void *", + "name": "data" + }, + { + "type": "int", + "name": "frameCount" + } + ] + }, { "name": "UnloadWave", "description": "Unload wave data", diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index e8989a3c6..e88db0b7e 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -5383,7 +5383,7 @@ return { } }, { - name = "GetSplinePointBezierQuad", + name = "GetSplinePointBezierQuadratic", description = "Get (evaluate) spline point: Quadratic Bezier", returnType = "Vector2", params = { @@ -5981,7 +5981,7 @@ return { returnType = "void", params = { {type = "Image *", name = "image"}, - {type = "float", name = "contrast"} + {type = "int", name = "contrast"} } }, { @@ -6206,6 +6206,19 @@ return { name = "ImageDrawRectangleLines", description = "Draw rectangle lines within an image", returnType = "void", + params = { + {type = "Image *", name = "dst"}, + {type = "int", name = "posX"}, + {type = "int", name = "posY"}, + {type = "int", name = "width"}, + {type = "int", name = "height"}, + {type = "Color", name = "color"} + } + }, + { + name = "ImageDrawRectangleLinesEx", + description = "Draw rectangle lines within an image with extended parameters", + returnType = "void", params = { {type = "Image *", name = "dst"}, {type = "Rectangle", name = "rec"}, @@ -8032,16 +8045,6 @@ return { {type = "Wave", name = "wave"} } }, - { - name = "UpdateSound", - description = "Update sound buffer with new data (default data format: 32 bit float, stereo)", - returnType = "void", - params = { - {type = "Sound", name = "sound"}, - {type = "const void *", name = "data"}, - {type = "int", name = "sampleCount"} - } - }, { name = "LoadSoundAlias", description = "Load sound alias, new sound that shares the same sample data as the source sound, does not own the sound data", @@ -8058,6 +8061,16 @@ return { {type = "Sound", name = "sound"} } }, + { + name = "UpdateSound", + description = "Update sound buffer with new data (default data format: 32 bit float, stereo)", + returnType = "void", + params = { + {type = "Sound", name = "sound"}, + {type = "const void *", name = "data"}, + {type = "int", name = "frameCount"} + } + }, { name = "UnloadWave", description = "Unload wave data", diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index 440113aa7..0447edd23 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -1000,7 +1000,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 601 +Functions found: 602 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -2648,8 +2648,8 @@ Function 275: GetSplinePointCatmullRom() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 276: GetSplinePointBezierQuad() (4 input parameters) - Name: GetSplinePointBezierQuad +Function 276: GetSplinePointBezierQuadratic() (4 input parameters) + Name: GetSplinePointBezierQuadratic Return type: Vector2 Description: Get (evaluate) spline point: Quadratic Bezier Param[1]: p1 (type: Vector2) @@ -3066,7 +3066,7 @@ Function 337: ImageColorContrast() (2 input parameters) Return type: void Description: Modify image color: contrast (-100 to 100) Param[1]: image (type: Image *) - Param[2]: contrast (type: float) + Param[2]: contrast (type: int) Function 338: ImageColorBrightness() (2 input parameters) Name: ImageColorBrightness Return type: void @@ -3222,15 +3222,25 @@ Function 358: ImageDrawRectangleRec() (3 input parameters) Param[1]: dst (type: Image *) Param[2]: rec (type: Rectangle) Param[3]: color (type: Color) -Function 359: ImageDrawRectangleLines() (4 input parameters) +Function 359: ImageDrawRectangleLines() (6 input parameters) Name: ImageDrawRectangleLines Return type: void Description: Draw rectangle lines within an image Param[1]: dst (type: Image *) + Param[2]: posX (type: int) + Param[3]: posY (type: int) + Param[4]: width (type: int) + Param[5]: height (type: int) + Param[6]: color (type: Color) +Function 360: ImageDrawRectangleLinesEx() (4 input parameters) + Name: ImageDrawRectangleLinesEx + Return type: void + Description: Draw rectangle lines within an image with extended parameters + Param[1]: dst (type: Image *) Param[2]: rec (type: Rectangle) Param[3]: thick (type: int) Param[4]: color (type: Color) -Function 360: ImageDrawTriangle() (5 input parameters) +Function 361: ImageDrawTriangle() (5 input parameters) Name: ImageDrawTriangle Return type: void Description: Draw triangle within an image @@ -3239,7 +3249,7 @@ Function 360: ImageDrawTriangle() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 361: ImageDrawTriangleGradient() (7 input parameters) +Function 362: ImageDrawTriangleGradient() (7 input parameters) Name: ImageDrawTriangleGradient Return type: void Description: Draw triangle with interpolated colors within an image @@ -3250,7 +3260,7 @@ Function 361: ImageDrawTriangleGradient() (7 input parameters) Param[5]: c1 (type: Color) Param[6]: c2 (type: Color) Param[7]: c3 (type: Color) -Function 362: ImageDrawTriangleLines() (5 input parameters) +Function 363: ImageDrawTriangleLines() (5 input parameters) Name: ImageDrawTriangleLines Return type: void Description: Draw triangle outline within an image @@ -3259,7 +3269,7 @@ Function 362: ImageDrawTriangleLines() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 363: ImageDrawTriangleFan() (4 input parameters) +Function 364: ImageDrawTriangleFan() (4 input parameters) Name: ImageDrawTriangleFan Return type: void Description: Draw a triangle fan defined by points within an image (first vertex is the center) @@ -3267,7 +3277,7 @@ Function 363: ImageDrawTriangleFan() (4 input parameters) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 364: ImageDrawTriangleStrip() (4 input parameters) +Function 365: ImageDrawTriangleStrip() (4 input parameters) Name: ImageDrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points within an image @@ -3275,7 +3285,7 @@ Function 364: ImageDrawTriangleStrip() (4 input parameters) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 365: ImageDraw() (5 input parameters) +Function 366: ImageDraw() (5 input parameters) Name: ImageDraw Return type: void Description: Draw a source image within a destination image (tint applied to source) @@ -3284,7 +3294,7 @@ Function 365: ImageDraw() (5 input parameters) Param[3]: srcRec (type: Rectangle) Param[4]: dstRec (type: Rectangle) Param[5]: tint (type: Color) -Function 366: ImageDrawText() (6 input parameters) +Function 367: ImageDrawText() (6 input parameters) Name: ImageDrawText Return type: void Description: Draw text (using default font) within an image (destination) @@ -3294,7 +3304,7 @@ Function 366: ImageDrawText() (6 input parameters) Param[4]: posY (type: int) Param[5]: fontSize (type: int) Param[6]: color (type: Color) -Function 367: ImageDrawTextEx() (7 input parameters) +Function 368: ImageDrawTextEx() (7 input parameters) Name: ImageDrawTextEx Return type: void Description: Draw text (custom sprite font) within an image (destination) @@ -3305,79 +3315,79 @@ Function 367: ImageDrawTextEx() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 368: LoadTexture() (1 input parameters) +Function 369: LoadTexture() (1 input parameters) Name: LoadTexture Return type: Texture2D Description: Load texture from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 369: LoadTextureFromImage() (1 input parameters) +Function 370: LoadTextureFromImage() (1 input parameters) Name: LoadTextureFromImage Return type: Texture2D Description: Load texture from image data Param[1]: image (type: Image) -Function 370: LoadTextureCubemap() (2 input parameters) +Function 371: LoadTextureCubemap() (2 input parameters) Name: LoadTextureCubemap Return type: TextureCubemap Description: Load cubemap from image, multiple image cubemap layouts supported Param[1]: image (type: Image) Param[2]: layout (type: int) -Function 371: LoadRenderTexture() (2 input parameters) +Function 372: LoadRenderTexture() (2 input parameters) Name: LoadRenderTexture Return type: RenderTexture2D Description: Load texture for rendering (framebuffer) Param[1]: width (type: int) Param[2]: height (type: int) -Function 372: IsTextureValid() (1 input parameters) +Function 373: IsTextureValid() (1 input parameters) Name: IsTextureValid Return type: bool Description: Check if a texture is valid (loaded in GPU) Param[1]: texture (type: Texture2D) -Function 373: UnloadTexture() (1 input parameters) +Function 374: UnloadTexture() (1 input parameters) Name: UnloadTexture Return type: void Description: Unload texture from GPU memory (VRAM) Param[1]: texture (type: Texture2D) -Function 374: IsRenderTextureValid() (1 input parameters) +Function 375: IsRenderTextureValid() (1 input parameters) Name: IsRenderTextureValid Return type: bool Description: Check if a render texture is valid (loaded in GPU) Param[1]: target (type: RenderTexture2D) -Function 375: UnloadRenderTexture() (1 input parameters) +Function 376: UnloadRenderTexture() (1 input parameters) Name: UnloadRenderTexture Return type: void Description: Unload render texture from GPU memory (VRAM) Param[1]: target (type: RenderTexture2D) -Function 376: UpdateTexture() (2 input parameters) +Function 377: UpdateTexture() (2 input parameters) Name: UpdateTexture Return type: void Description: Update GPU texture with new data (pixels should be able to fill texture) Param[1]: texture (type: Texture2D) Param[2]: pixels (type: const void *) -Function 377: UpdateTextureRec() (3 input parameters) +Function 378: UpdateTextureRec() (3 input parameters) Name: UpdateTextureRec Return type: void Description: Update GPU texture rectangle with new data (pixels and rec should fit in texture) Param[1]: texture (type: Texture2D) Param[2]: rec (type: Rectangle) Param[3]: pixels (type: const void *) -Function 378: GenTextureMipmaps() (1 input parameters) +Function 379: GenTextureMipmaps() (1 input parameters) Name: GenTextureMipmaps Return type: void Description: Generate GPU mipmaps for a texture Param[1]: texture (type: Texture2D *) -Function 379: SetTextureFilter() (2 input parameters) +Function 380: SetTextureFilter() (2 input parameters) Name: SetTextureFilter Return type: void Description: Set texture scaling filter mode Param[1]: texture (type: Texture2D) Param[2]: filter (type: int) -Function 380: SetTextureWrap() (2 input parameters) +Function 381: SetTextureWrap() (2 input parameters) Name: SetTextureWrap Return type: void Description: Set texture wrapping mode Param[1]: texture (type: Texture2D) Param[2]: wrap (type: int) -Function 381: DrawTexture() (4 input parameters) +Function 382: DrawTexture() (4 input parameters) Name: DrawTexture Return type: void Description: Draw a Texture2D @@ -3385,14 +3395,14 @@ Function 381: DrawTexture() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: tint (type: Color) -Function 382: DrawTextureV() (3 input parameters) +Function 383: DrawTextureV() (3 input parameters) Name: DrawTextureV Return type: void Description: Draw a Texture2D with position defined as Vector2 Param[1]: texture (type: Texture2D) Param[2]: position (type: Vector2) Param[3]: tint (type: Color) -Function 383: DrawTextureEx() (5 input parameters) +Function 384: DrawTextureEx() (5 input parameters) Name: DrawTextureEx Return type: void Description: Draw a Texture2D with extended parameters @@ -3401,7 +3411,7 @@ Function 383: DrawTextureEx() (5 input parameters) Param[3]: rotation (type: float) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 384: DrawTextureRec() (4 input parameters) +Function 385: DrawTextureRec() (4 input parameters) Name: DrawTextureRec Return type: void Description: Draw a part of a texture defined by a rectangle @@ -3409,7 +3419,7 @@ Function 384: DrawTextureRec() (4 input parameters) Param[2]: source (type: Rectangle) Param[3]: position (type: Vector2) Param[4]: tint (type: Color) -Function 385: DrawTexturePro() (6 input parameters) +Function 386: DrawTexturePro() (6 input parameters) Name: DrawTexturePro Return type: void Description: Draw a part of a texture defined by a rectangle with 'pro' parameters @@ -3419,7 +3429,7 @@ Function 385: DrawTexturePro() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 386: DrawTextureNPatch() (6 input parameters) +Function 387: DrawTextureNPatch() (6 input parameters) Name: DrawTextureNPatch Return type: void Description: Draw a texture (or part of it) that stretches or shrinks nicely @@ -3429,119 +3439,119 @@ Function 386: DrawTextureNPatch() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 387: ColorIsEqual() (2 input parameters) +Function 388: ColorIsEqual() (2 input parameters) Name: ColorIsEqual Return type: bool Description: Check if two colors are equal Param[1]: col1 (type: Color) Param[2]: col2 (type: Color) -Function 388: Fade() (2 input parameters) +Function 389: Fade() (2 input parameters) Name: Fade Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 389: ColorToInt() (1 input parameters) +Function 390: ColorToInt() (1 input parameters) Name: ColorToInt Return type: int Description: Get hexadecimal value for a Color (0xRRGGBBAA) Param[1]: color (type: Color) -Function 390: ColorNormalize() (1 input parameters) +Function 391: ColorNormalize() (1 input parameters) Name: ColorNormalize Return type: Vector4 Description: Get Color normalized as float [0..1] Param[1]: color (type: Color) -Function 391: ColorFromNormalized() (1 input parameters) +Function 392: ColorFromNormalized() (1 input parameters) Name: ColorFromNormalized Return type: Color Description: Get Color from normalized values [0..1] Param[1]: normalized (type: Vector4) -Function 392: ColorToHSV() (1 input parameters) +Function 393: ColorToHSV() (1 input parameters) Name: ColorToHSV Return type: Vector3 Description: Get HSV values for a Color, hue [0..360], saturation/value [0..1] Param[1]: color (type: Color) -Function 393: ColorFromHSV() (3 input parameters) +Function 394: ColorFromHSV() (3 input parameters) Name: ColorFromHSV Return type: Color Description: Get a Color from HSV values, hue [0..360], saturation/value [0..1] Param[1]: hue (type: float) Param[2]: saturation (type: float) Param[3]: value (type: float) -Function 394: ColorTint() (2 input parameters) +Function 395: ColorTint() (2 input parameters) Name: ColorTint Return type: Color Description: Get color multiplied with another color Param[1]: color (type: Color) Param[2]: tint (type: Color) -Function 395: ColorBrightness() (2 input parameters) +Function 396: ColorBrightness() (2 input parameters) Name: ColorBrightness Return type: Color Description: Get color with brightness correction, brightness factor goes from -1.0f to 1.0f Param[1]: color (type: Color) Param[2]: factor (type: float) -Function 396: ColorContrast() (2 input parameters) +Function 397: ColorContrast() (2 input parameters) Name: ColorContrast Return type: Color Description: Get color with contrast correction, contrast values between -1.0f and 1.0f Param[1]: color (type: Color) Param[2]: contrast (type: float) -Function 397: ColorAlpha() (2 input parameters) +Function 398: ColorAlpha() (2 input parameters) Name: ColorAlpha Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 398: ColorAlphaBlend() (3 input parameters) +Function 399: ColorAlphaBlend() (3 input parameters) Name: ColorAlphaBlend Return type: Color Description: Get src alpha-blended into dst color with tint Param[1]: dst (type: Color) Param[2]: src (type: Color) Param[3]: tint (type: Color) -Function 399: ColorLerp() (3 input parameters) +Function 400: ColorLerp() (3 input parameters) Name: ColorLerp Return type: Color Description: Get color lerp interpolation between two colors, factor [0.0f..1.0f] Param[1]: color1 (type: Color) Param[2]: color2 (type: Color) Param[3]: factor (type: float) -Function 400: GetColor() (1 input parameters) +Function 401: GetColor() (1 input parameters) Name: GetColor Return type: Color Description: Get Color structure from hexadecimal value Param[1]: hexValue (type: unsigned int) -Function 401: GetPixelColor() (2 input parameters) +Function 402: GetPixelColor() (2 input parameters) Name: GetPixelColor Return type: Color Description: Get Color from a source pixel pointer of certain format Param[1]: srcPtr (type: void *) Param[2]: format (type: int) -Function 402: SetPixelColor() (3 input parameters) +Function 403: SetPixelColor() (3 input parameters) Name: SetPixelColor Return type: void Description: Set color formatted into destination pixel pointer Param[1]: dstPtr (type: void *) Param[2]: color (type: Color) Param[3]: format (type: int) -Function 403: GetPixelDataSize() (3 input parameters) +Function 404: GetPixelDataSize() (3 input parameters) Name: GetPixelDataSize Return type: int Description: Get pixel data size in bytes for certain format Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: format (type: int) -Function 404: GetFontDefault() (0 input parameters) +Function 405: GetFontDefault() (0 input parameters) Name: GetFontDefault Return type: Font Description: Get the default Font No input parameters -Function 405: LoadFont() (1 input parameters) +Function 406: LoadFont() (1 input parameters) Name: LoadFont Return type: Font Description: Load font from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 406: LoadFontEx() (4 input parameters) +Function 407: LoadFontEx() (4 input parameters) Name: LoadFontEx Return type: Font Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height @@ -3549,14 +3559,14 @@ Function 406: LoadFontEx() (4 input parameters) Param[2]: fontSize (type: int) Param[3]: codepoints (type: const int *) Param[4]: codepointCount (type: int) -Function 407: LoadFontFromImage() (3 input parameters) +Function 408: LoadFontFromImage() (3 input parameters) Name: LoadFontFromImage Return type: Font Description: Load font from Image (XNA style) Param[1]: image (type: Image) Param[2]: key (type: Color) Param[3]: firstChar (type: int) -Function 408: LoadFontFromMemory() (6 input parameters) +Function 409: LoadFontFromMemory() (6 input parameters) Name: LoadFontFromMemory Return type: Font Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf' @@ -3566,12 +3576,12 @@ Function 408: LoadFontFromMemory() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: codepoints (type: const int *) Param[6]: codepointCount (type: int) -Function 409: IsFontValid() (1 input parameters) +Function 410: IsFontValid() (1 input parameters) Name: IsFontValid Return type: bool Description: Check if a font is valid (font data loaded, WARNING: GPU texture not checked) Param[1]: font (type: Font) -Function 410: LoadFontData() (7 input parameters) +Function 411: LoadFontData() (7 input parameters) Name: LoadFontData Return type: GlyphInfo * Description: Load font data for further use @@ -3582,7 +3592,7 @@ Function 410: LoadFontData() (7 input parameters) Param[5]: codepointCount (type: int) Param[6]: type (type: int) Param[7]: glyphCount (type: int *) -Function 411: GenImageFontAtlas() (6 input parameters) +Function 412: GenImageFontAtlas() (6 input parameters) Name: GenImageFontAtlas Return type: Image Description: Generate image font atlas using chars info @@ -3592,30 +3602,30 @@ Function 411: GenImageFontAtlas() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: padding (type: int) Param[6]: packMethod (type: int) -Function 412: UnloadFontData() (2 input parameters) +Function 413: UnloadFontData() (2 input parameters) Name: UnloadFontData Return type: void Description: Unload font chars info data (RAM) Param[1]: glyphs (type: GlyphInfo *) Param[2]: glyphCount (type: int) -Function 413: UnloadFont() (1 input parameters) +Function 414: UnloadFont() (1 input parameters) Name: UnloadFont Return type: void Description: Unload font from GPU memory (VRAM) Param[1]: font (type: Font) -Function 414: ExportFontAsCode() (2 input parameters) +Function 415: ExportFontAsCode() (2 input parameters) Name: ExportFontAsCode Return type: bool Description: Export font as code file, returns true on success Param[1]: font (type: Font) Param[2]: fileName (type: const char *) -Function 415: DrawFPS() (2 input parameters) +Function 416: DrawFPS() (2 input parameters) Name: DrawFPS Return type: void Description: Draw current FPS Param[1]: posX (type: int) Param[2]: posY (type: int) -Function 416: DrawText() (5 input parameters) +Function 417: DrawText() (5 input parameters) Name: DrawText Return type: void Description: Draw text (using default font) @@ -3624,7 +3634,7 @@ Function 416: DrawText() (5 input parameters) Param[3]: posY (type: int) Param[4]: fontSize (type: int) Param[5]: color (type: Color) -Function 417: DrawTextEx() (6 input parameters) +Function 418: DrawTextEx() (6 input parameters) Name: DrawTextEx Return type: void Description: Draw text using font and additional parameters @@ -3634,7 +3644,7 @@ Function 417: DrawTextEx() (6 input parameters) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) Param[6]: tint (type: Color) -Function 418: DrawTextPro() (8 input parameters) +Function 419: DrawTextPro() (8 input parameters) Name: DrawTextPro Return type: void Description: Draw text using Font and pro parameters (rotation) @@ -3646,7 +3656,7 @@ Function 418: DrawTextPro() (8 input parameters) Param[6]: fontSize (type: float) Param[7]: spacing (type: float) Param[8]: tint (type: Color) -Function 419: DrawTextCodepoint() (5 input parameters) +Function 420: DrawTextCodepoint() (5 input parameters) Name: DrawTextCodepoint Return type: void Description: Draw one character (codepoint) @@ -3655,7 +3665,7 @@ Function 419: DrawTextCodepoint() (5 input parameters) Param[3]: position (type: Vector2) Param[4]: fontSize (type: float) Param[5]: tint (type: Color) -Function 420: DrawTextCodepoints() (7 input parameters) +Function 421: DrawTextCodepoints() (7 input parameters) Name: DrawTextCodepoints Return type: void Description: Draw multiple characters (codepoint) @@ -3666,18 +3676,18 @@ Function 420: DrawTextCodepoints() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 421: SetTextLineSpacing() (1 input parameters) +Function 422: SetTextLineSpacing() (1 input parameters) Name: SetTextLineSpacing Return type: void Description: Set vertical line spacing when drawing with line-breaks Param[1]: spacing (type: int) -Function 422: MeasureText() (2 input parameters) +Function 423: MeasureText() (2 input parameters) Name: MeasureText Return type: int Description: Measure string width for default font Param[1]: text (type: const char *) Param[2]: fontSize (type: int) -Function 423: MeasureTextEx() (4 input parameters) +Function 424: MeasureTextEx() (4 input parameters) Name: MeasureTextEx Return type: Vector2 Description: Measure string size for Font @@ -3685,7 +3695,7 @@ Function 423: MeasureTextEx() (4 input parameters) Param[2]: text (type: const char *) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) -Function 424: MeasureTextCodepoints() (5 input parameters) +Function 425: MeasureTextCodepoints() (5 input parameters) Name: MeasureTextCodepoints Return type: Vector2 Description: Measure string size for an existing array of codepoints for Font @@ -3694,144 +3704,144 @@ Function 424: MeasureTextCodepoints() (5 input parameters) Param[3]: length (type: int) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) -Function 425: GetGlyphIndex() (2 input parameters) +Function 426: GetGlyphIndex() (2 input parameters) Name: GetGlyphIndex Return type: int Description: Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 426: GetGlyphInfo() (2 input parameters) +Function 427: GetGlyphInfo() (2 input parameters) Name: GetGlyphInfo Return type: GlyphInfo Description: Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 427: GetGlyphAtlasRec() (2 input parameters) +Function 428: GetGlyphAtlasRec() (2 input parameters) Name: GetGlyphAtlasRec Return type: Rectangle Description: Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 428: LoadUTF8() (2 input parameters) +Function 429: LoadUTF8() (2 input parameters) Name: LoadUTF8 Return type: char * Description: Load UTF-8 text encoded from codepoints array Param[1]: codepoints (type: const int *) Param[2]: length (type: int) -Function 429: UnloadUTF8() (1 input parameters) +Function 430: UnloadUTF8() (1 input parameters) Name: UnloadUTF8 Return type: void Description: Unload UTF-8 text encoded from codepoints array Param[1]: text (type: char *) -Function 430: LoadCodepoints() (2 input parameters) +Function 431: LoadCodepoints() (2 input parameters) Name: LoadCodepoints Return type: int * Description: Load all codepoints from a UTF-8 text string, codepoints count returned by parameter Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 431: UnloadCodepoints() (1 input parameters) +Function 432: UnloadCodepoints() (1 input parameters) Name: UnloadCodepoints Return type: void Description: Unload codepoints data from memory Param[1]: codepoints (type: int *) -Function 432: GetCodepointCount() (1 input parameters) +Function 433: GetCodepointCount() (1 input parameters) Name: GetCodepointCount Return type: int Description: Get total number of codepoints in a UTF-8 encoded string Param[1]: text (type: const char *) -Function 433: GetCodepoint() (2 input parameters) +Function 434: GetCodepoint() (2 input parameters) Name: GetCodepoint Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 434: GetCodepointNext() (2 input parameters) +Function 435: GetCodepointNext() (2 input parameters) Name: GetCodepointNext Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 435: GetCodepointPrevious() (2 input parameters) +Function 436: GetCodepointPrevious() (2 input parameters) Name: GetCodepointPrevious Return type: int Description: Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 436: CodepointToUTF8() (2 input parameters) +Function 437: CodepointToUTF8() (2 input parameters) Name: CodepointToUTF8 Return type: const char * Description: Encode one codepoint into UTF-8 byte array (array length returned as parameter) Param[1]: codepoint (type: int) Param[2]: utf8Size (type: int *) -Function 437: LoadTextLines() (2 input parameters) +Function 438: LoadTextLines() (2 input parameters) Name: LoadTextLines Return type: char ** Description: Load text as separate lines ('\n') Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 438: UnloadTextLines() (2 input parameters) +Function 439: UnloadTextLines() (2 input parameters) Name: UnloadTextLines Return type: void Description: Unload text lines Param[1]: text (type: char **) Param[2]: lineCount (type: int) -Function 439: TextCopy() (2 input parameters) +Function 440: TextCopy() (2 input parameters) Name: TextCopy Return type: int Description: Copy one string to another, returns bytes copied Param[1]: dst (type: char *) Param[2]: src (type: const char *) -Function 440: TextIsEqual() (2 input parameters) +Function 441: TextIsEqual() (2 input parameters) Name: TextIsEqual Return type: bool Description: Check if two text strings are equal Param[1]: text1 (type: const char *) Param[2]: text2 (type: const char *) -Function 441: TextLength() (1 input parameters) +Function 442: TextLength() (1 input parameters) Name: TextLength Return type: unsigned int Description: Get text length, checks for '\0' ending Param[1]: text (type: const char *) -Function 442: TextFormat() (2 input parameters) +Function 443: TextFormat() (2 input parameters) Name: TextFormat Return type: const char * Description: Text formatting with variables (sprintf() style) Param[1]: text (type: const char *) Param[2]: args (type: ...) -Function 443: TextSubtext() (3 input parameters) +Function 444: TextSubtext() (3 input parameters) Name: TextSubtext Return type: const char * Description: Get a piece of a text string Param[1]: text (type: const char *) Param[2]: position (type: int) Param[3]: length (type: int) -Function 444: TextRemoveSpaces() (1 input parameters) +Function 445: TextRemoveSpaces() (1 input parameters) Name: TextRemoveSpaces Return type: const char * Description: Remove text spaces, concat words Param[1]: text (type: const char *) -Function 445: GetTextBetween() (3 input parameters) +Function 446: GetTextBetween() (3 input parameters) Name: GetTextBetween Return type: char * Description: Get text between two strings Param[1]: text (type: const char *) Param[2]: begin (type: const char *) Param[3]: end (type: const char *) -Function 446: TextReplace() (3 input parameters) +Function 447: TextReplace() (3 input parameters) Name: TextReplace Return type: char * Description: Replace text string with new string Param[1]: text (type: const char *) Param[2]: search (type: const char *) Param[3]: replacement (type: const char *) -Function 447: TextReplaceAlloc() (3 input parameters) +Function 448: TextReplaceAlloc() (3 input parameters) Name: TextReplaceAlloc Return type: char * Description: Replace text string with new string, memory must be MemFree() Param[1]: text (type: const char *) Param[2]: search (type: const char *) Param[3]: replacement (type: const char *) -Function 448: TextReplaceBetween() (4 input parameters) +Function 449: TextReplaceBetween() (4 input parameters) Name: TextReplaceBetween Return type: char * Description: Replace text between two specific strings @@ -3839,7 +3849,7 @@ Function 448: TextReplaceBetween() (4 input parameters) Param[2]: begin (type: const char *) Param[3]: end (type: const char *) Param[4]: replacement (type: const char *) -Function 449: TextReplaceBetweenAlloc() (4 input parameters) +Function 450: TextReplaceBetweenAlloc() (4 input parameters) Name: TextReplaceBetweenAlloc Return type: char * Description: Replace text between two specific strings, memory must be MemFree() @@ -3847,96 +3857,96 @@ Function 449: TextReplaceBetweenAlloc() (4 input parameters) Param[2]: begin (type: const char *) Param[3]: end (type: const char *) Param[4]: replacement (type: const char *) -Function 450: TextInsert() (3 input parameters) +Function 451: TextInsert() (3 input parameters) Name: TextInsert Return type: char * Description: Insert text in a defined byte position Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 451: TextInsertAlloc() (3 input parameters) +Function 452: TextInsertAlloc() (3 input parameters) Name: TextInsertAlloc Return type: char * Description: Insert text in a defined byte position, memory must be MemFree() Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 452: TextJoin() (3 input parameters) +Function 453: TextJoin() (3 input parameters) Name: TextJoin Return type: char * Description: Join text strings with delimiter Param[1]: textList (type: char **) Param[2]: count (type: int) Param[3]: delimiter (type: const char *) -Function 453: TextSplit() (3 input parameters) +Function 454: TextSplit() (3 input parameters) Name: TextSplit Return type: char ** Description: Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings Param[1]: text (type: const char *) Param[2]: delimiter (type: char) Param[3]: count (type: int *) -Function 454: TextAppend() (3 input parameters) +Function 455: TextAppend() (3 input parameters) Name: TextAppend Return type: void Description: Append text at specific position and move cursor Param[1]: text (type: char *) Param[2]: append (type: const char *) Param[3]: position (type: int *) -Function 455: TextFindIndex() (2 input parameters) +Function 456: TextFindIndex() (2 input parameters) Name: TextFindIndex Return type: int Description: Find first text occurrence within a string, -1 if not found Param[1]: text (type: const char *) Param[2]: search (type: const char *) -Function 456: TextToUpper() (1 input parameters) +Function 457: TextToUpper() (1 input parameters) Name: TextToUpper Return type: char * Description: Get upper case version of provided string Param[1]: text (type: const char *) -Function 457: TextToLower() (1 input parameters) +Function 458: TextToLower() (1 input parameters) Name: TextToLower Return type: char * Description: Get lower case version of provided string Param[1]: text (type: const char *) -Function 458: TextToPascal() (1 input parameters) +Function 459: TextToPascal() (1 input parameters) Name: TextToPascal Return type: char * Description: Get Pascal case notation version of provided string Param[1]: text (type: const char *) -Function 459: TextToSnake() (1 input parameters) +Function 460: TextToSnake() (1 input parameters) Name: TextToSnake Return type: char * Description: Get Snake case notation version of provided string Param[1]: text (type: const char *) -Function 460: TextToCamel() (1 input parameters) +Function 461: TextToCamel() (1 input parameters) Name: TextToCamel Return type: char * Description: Get Camel case notation version of provided string Param[1]: text (type: const char *) -Function 461: TextToInteger() (1 input parameters) +Function 462: TextToInteger() (1 input parameters) Name: TextToInteger Return type: int Description: Get integer value from text Param[1]: text (type: const char *) -Function 462: TextToFloat() (1 input parameters) +Function 463: TextToFloat() (1 input parameters) Name: TextToFloat Return type: float Description: Get float value from text Param[1]: text (type: const char *) -Function 463: DrawLine3D() (3 input parameters) +Function 464: DrawLine3D() (3 input parameters) Name: DrawLine3D Return type: void Description: Draw a line in 3D world space Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: color (type: Color) -Function 464: DrawPoint3D() (2 input parameters) +Function 465: DrawPoint3D() (2 input parameters) Name: DrawPoint3D Return type: void Description: Draw a point in 3D space, actually a small line Param[1]: position (type: Vector3) Param[2]: color (type: Color) -Function 465: DrawCircle3D() (5 input parameters) +Function 466: DrawCircle3D() (5 input parameters) Name: DrawCircle3D Return type: void Description: Draw a circle in 3D world space @@ -3945,7 +3955,7 @@ Function 465: DrawCircle3D() (5 input parameters) Param[3]: rotationAxis (type: Vector3) Param[4]: rotationAngle (type: float) Param[5]: color (type: Color) -Function 466: DrawTriangle3D() (4 input parameters) +Function 467: DrawTriangle3D() (4 input parameters) Name: DrawTriangle3D Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -3953,14 +3963,14 @@ Function 466: DrawTriangle3D() (4 input parameters) Param[2]: v2 (type: Vector3) Param[3]: v3 (type: Vector3) Param[4]: color (type: Color) -Function 467: DrawTriangleStrip3D() (3 input parameters) +Function 468: DrawTriangleStrip3D() (3 input parameters) Name: DrawTriangleStrip3D Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector3 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 468: DrawCube() (5 input parameters) +Function 469: DrawCube() (5 input parameters) Name: DrawCube Return type: void Description: Draw cube @@ -3969,14 +3979,14 @@ Function 468: DrawCube() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 469: DrawCubeV() (3 input parameters) +Function 470: DrawCubeV() (3 input parameters) Name: DrawCubeV Return type: void Description: Draw cube (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 470: DrawCubeWires() (5 input parameters) +Function 471: DrawCubeWires() (5 input parameters) Name: DrawCubeWires Return type: void Description: Draw cube wires @@ -3985,21 +3995,21 @@ Function 470: DrawCubeWires() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 471: DrawCubeWiresV() (3 input parameters) +Function 472: DrawCubeWiresV() (3 input parameters) Name: DrawCubeWiresV Return type: void Description: Draw cube wires (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 472: DrawSphere() (3 input parameters) +Function 473: DrawSphere() (3 input parameters) Name: DrawSphere Return type: void Description: Draw sphere Param[1]: centerPos (type: Vector3) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 473: DrawSphereEx() (5 input parameters) +Function 474: DrawSphereEx() (5 input parameters) Name: DrawSphereEx Return type: void Description: Draw sphere with extended parameters @@ -4008,7 +4018,7 @@ Function 473: DrawSphereEx() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 474: DrawSphereWires() (5 input parameters) +Function 475: DrawSphereWires() (5 input parameters) Name: DrawSphereWires Return type: void Description: Draw sphere wires @@ -4017,7 +4027,7 @@ Function 474: DrawSphereWires() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 475: DrawCylinder() (6 input parameters) +Function 476: DrawCylinder() (6 input parameters) Name: DrawCylinder Return type: void Description: Draw a cylinder/cone @@ -4027,7 +4037,7 @@ Function 475: DrawCylinder() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 476: DrawCylinderEx() (6 input parameters) +Function 477: DrawCylinderEx() (6 input parameters) Name: DrawCylinderEx Return type: void Description: Draw a cylinder with base at startPos and top at endPos @@ -4037,7 +4047,7 @@ Function 476: DrawCylinderEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 477: DrawCylinderWires() (6 input parameters) +Function 478: DrawCylinderWires() (6 input parameters) Name: DrawCylinderWires Return type: void Description: Draw a cylinder/cone wires @@ -4047,7 +4057,7 @@ Function 477: DrawCylinderWires() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 478: DrawCylinderWiresEx() (6 input parameters) +Function 479: DrawCylinderWiresEx() (6 input parameters) Name: DrawCylinderWiresEx Return type: void Description: Draw a cylinder wires with base at startPos and top at endPos @@ -4057,7 +4067,7 @@ Function 478: DrawCylinderWiresEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 479: DrawCapsule() (6 input parameters) +Function 480: DrawCapsule() (6 input parameters) Name: DrawCapsule Return type: void Description: Draw a capsule with the center of its sphere caps at startPos and endPos @@ -4067,7 +4077,7 @@ Function 479: DrawCapsule() (6 input parameters) Param[4]: rings (type: int) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 480: DrawCapsuleWires() (6 input parameters) +Function 481: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires Return type: void Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos @@ -4077,51 +4087,51 @@ Function 480: DrawCapsuleWires() (6 input parameters) Param[4]: rings (type: int) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 481: DrawPlane() (3 input parameters) +Function 482: DrawPlane() (3 input parameters) Name: DrawPlane Return type: void Description: Draw a plane XZ Param[1]: centerPos (type: Vector3) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 482: DrawRay() (2 input parameters) +Function 483: DrawRay() (2 input parameters) Name: DrawRay Return type: void Description: Draw a ray line Param[1]: ray (type: Ray) Param[2]: color (type: Color) -Function 483: DrawGrid() (2 input parameters) +Function 484: DrawGrid() (2 input parameters) Name: DrawGrid Return type: void Description: Draw a grid (centered at (0, 0, 0)) Param[1]: slices (type: int) Param[2]: spacing (type: float) -Function 484: LoadModel() (1 input parameters) +Function 485: LoadModel() (1 input parameters) Name: LoadModel Return type: Model Description: Load model from files (meshes and materials) Param[1]: fileName (type: const char *) -Function 485: LoadModelFromMesh() (1 input parameters) +Function 486: LoadModelFromMesh() (1 input parameters) Name: LoadModelFromMesh Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 486: IsModelValid() (1 input parameters) +Function 487: IsModelValid() (1 input parameters) Name: IsModelValid Return type: bool Description: Check if a model is valid (loaded in GPU, VAO/VBOs) Param[1]: model (type: Model) -Function 487: UnloadModel() (1 input parameters) +Function 488: UnloadModel() (1 input parameters) Name: UnloadModel Return type: void Description: Unload model (including meshes) from memory (RAM and/or VRAM) Param[1]: model (type: Model) -Function 488: GetModelBoundingBox() (1 input parameters) +Function 489: GetModelBoundingBox() (1 input parameters) Name: GetModelBoundingBox Return type: BoundingBox Description: Compute model bounding box limits (considers all meshes) Param[1]: model (type: Model) -Function 489: DrawModel() (4 input parameters) +Function 490: DrawModel() (4 input parameters) Name: DrawModel Return type: void Description: Draw a model (with texture if set) @@ -4129,7 +4139,7 @@ Function 489: DrawModel() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 490: DrawModelEx() (6 input parameters) +Function 491: DrawModelEx() (6 input parameters) Name: DrawModelEx Return type: void Description: Draw a model with extended parameters @@ -4139,7 +4149,7 @@ Function 490: DrawModelEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 491: DrawModelWires() (4 input parameters) +Function 492: DrawModelWires() (4 input parameters) Name: DrawModelWires Return type: void Description: Draw a model wires (with texture if set) @@ -4147,7 +4157,7 @@ Function 491: DrawModelWires() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 492: DrawModelWiresEx() (6 input parameters) +Function 493: DrawModelWiresEx() (6 input parameters) Name: DrawModelWiresEx Return type: void Description: Draw a model wires (with texture if set) with extended parameters @@ -4157,13 +4167,13 @@ Function 492: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 493: DrawBoundingBox() (2 input parameters) +Function 494: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 494: DrawBillboard() (5 input parameters) +Function 495: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -4172,7 +4182,7 @@ Function 494: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 495: DrawBillboardRec() (6 input parameters) +Function 496: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -4182,7 +4192,7 @@ Function 495: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 496: DrawBillboardPro() (9 input parameters) +Function 497: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -4195,13 +4205,13 @@ Function 496: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 497: UploadMesh() (2 input parameters) +Function 498: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 498: UpdateMeshBuffer() (5 input parameters) +Function 499: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4210,19 +4220,19 @@ Function 498: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 499: UnloadMesh() (1 input parameters) +Function 500: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 500: DrawMesh() (3 input parameters) +Function 501: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 501: DrawMeshInstanced() (4 input parameters) +Function 502: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4230,35 +4240,35 @@ Function 501: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 502: GetMeshBoundingBox() (1 input parameters) +Function 503: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 503: GenMeshTangents() (1 input parameters) +Function 504: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 504: ExportMesh() (2 input parameters) +Function 505: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 505: ExportMeshAsCode() (2 input parameters) +Function 506: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 506: GenMeshPoly() (2 input parameters) +Function 507: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 507: GenMeshPlane() (4 input parameters) +Function 508: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4266,42 +4276,42 @@ Function 507: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 508: GenMeshCube() (3 input parameters) +Function 509: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 509: GenMeshSphere() (3 input parameters) +Function 510: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 510: GenMeshHemiSphere() (3 input parameters) +Function 511: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 511: GenMeshCylinder() (3 input parameters) +Function 512: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 512: GenMeshCone() (3 input parameters) +Function 513: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 513: GenMeshTorus() (4 input parameters) +Function 514: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4309,7 +4319,7 @@ Function 513: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 514: GenMeshKnot() (4 input parameters) +Function 515: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4317,67 +4327,67 @@ Function 514: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 515: GenMeshHeightmap() (2 input parameters) +Function 516: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 516: GenMeshCubicmap() (2 input parameters) +Function 517: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 517: LoadMaterials() (2 input parameters) +Function 518: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 518: LoadMaterialDefault() (0 input parameters) +Function 519: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 519: IsMaterialValid() (1 input parameters) +Function 520: IsMaterialValid() (1 input parameters) Name: IsMaterialValid Return type: bool Description: Check if a material is valid (shader assigned, map textures loaded in GPU) Param[1]: material (type: Material) -Function 520: UnloadMaterial() (1 input parameters) +Function 521: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 521: SetMaterialTexture() (3 input parameters) +Function 522: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 522: SetModelMeshMaterial() (3 input parameters) +Function 523: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 523: LoadModelAnimations() (2 input parameters) +Function 524: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 524: UpdateModelAnimation() (3 input parameters) +Function 525: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose (vertex buffers and bone matrices) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: float) -Function 525: UpdateModelAnimationEx() (6 input parameters) +Function 526: UpdateModelAnimationEx() (6 input parameters) Name: UpdateModelAnimationEx Return type: void Description: Update model animation pose, blending two animations @@ -4387,19 +4397,19 @@ Function 525: UpdateModelAnimationEx() (6 input parameters) Param[4]: animB (type: ModelAnimation) Param[5]: frameB (type: float) Param[6]: blend (type: float) -Function 526: UnloadModelAnimations() (2 input parameters) +Function 527: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 527: IsModelAnimationValid() (2 input parameters) +Function 528: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 528: CheckCollisionSpheres() (4 input parameters) +Function 529: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4407,40 +4417,40 @@ Function 528: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 529: CheckCollisionBoxes() (2 input parameters) +Function 530: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 530: CheckCollisionBoxSphere() (3 input parameters) +Function 531: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 531: GetRayCollisionSphere() (3 input parameters) +Function 532: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 532: GetRayCollisionBox() (2 input parameters) +Function 533: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 533: GetRayCollisionMesh() (3 input parameters) +Function 534: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 534: GetRayCollisionTriangle() (4 input parameters) +Function 535: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4448,7 +4458,7 @@ Function 534: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 535: GetRayCollisionQuad() (5 input parameters) +Function 536: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4457,65 +4467,58 @@ Function 535: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 536: InitAudioDevice() (0 input parameters) +Function 537: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 537: CloseAudioDevice() (0 input parameters) +Function 538: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 538: IsAudioDeviceReady() (0 input parameters) +Function 539: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 539: SetMasterVolume() (1 input parameters) +Function 540: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 540: GetMasterVolume() (0 input parameters) +Function 541: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 541: LoadWave() (1 input parameters) +Function 542: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 542: LoadWaveFromMemory() (3 input parameters) +Function 543: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 543: IsWaveValid() (1 input parameters) +Function 544: IsWaveValid() (1 input parameters) Name: IsWaveValid Return type: bool Description: Check if wave data is valid (data loaded and parameters) Param[1]: wave (type: Wave) -Function 544: LoadSound() (1 input parameters) +Function 545: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 545: LoadSoundFromWave() (1 input parameters) +Function 546: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 546: UpdateSound() (3 input parameters) - Name: UpdateSound - Return type: void - Description: Update sound buffer with new data (default data format: 32 bit float, stereo) - Param[1]: sound (type: Sound) - Param[2]: data (type: const void *) - Param[3]: sampleCount (type: int) Function 547: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound @@ -4526,89 +4529,96 @@ Function 548: IsSoundValid() (1 input parameters) Return type: bool Description: Check if a sound is valid (data loaded and buffers initialized) Param[1]: sound (type: Sound) -Function 549: UnloadWave() (1 input parameters) +Function 549: UpdateSound() (3 input parameters) + Name: UpdateSound + Return type: void + Description: Update sound buffer with new data (default data format: 32 bit float, stereo) + Param[1]: sound (type: Sound) + Param[2]: data (type: const void *) + Param[3]: frameCount (type: int) +Function 550: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 550: UnloadSound() (1 input parameters) +Function 551: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 551: UnloadSoundAlias() (1 input parameters) +Function 552: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 552: ExportWave() (2 input parameters) +Function 553: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 553: ExportWaveAsCode() (2 input parameters) +Function 554: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 554: PlaySound() (1 input parameters) +Function 555: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 555: StopSound() (1 input parameters) +Function 556: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 556: PauseSound() (1 input parameters) +Function 557: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 557: ResumeSound() (1 input parameters) +Function 558: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 558: IsSoundPlaying() (1 input parameters) +Function 559: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 559: SetSoundVolume() (2 input parameters) +Function 560: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 560: SetSoundPitch() (2 input parameters) +Function 561: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 561: SetSoundPan() (2 input parameters) +Function 562: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (-1.0 left, 0.0 center, 1.0 right) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 562: WaveCopy() (1 input parameters) +Function 563: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 563: WaveCrop() (3 input parameters) +Function 564: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 564: WaveFormat() (4 input parameters) +Function 565: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4616,203 +4626,203 @@ Function 564: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 565: LoadWaveSamples() (1 input parameters) +Function 566: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 566: UnloadWaveSamples() (1 input parameters) +Function 567: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 567: LoadMusicStream() (1 input parameters) +Function 568: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 568: LoadMusicStreamFromMemory() (3 input parameters) +Function 569: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 569: IsMusicValid() (1 input parameters) +Function 570: IsMusicValid() (1 input parameters) Name: IsMusicValid Return type: bool Description: Check if a music stream is valid (context and buffers initialized) Param[1]: music (type: Music) -Function 570: UnloadMusicStream() (1 input parameters) +Function 571: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 571: PlayMusicStream() (1 input parameters) +Function 572: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 572: IsMusicStreamPlaying() (1 input parameters) +Function 573: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 573: UpdateMusicStream() (1 input parameters) +Function 574: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Update buffers for music streaming Param[1]: music (type: Music) -Function 574: StopMusicStream() (1 input parameters) +Function 575: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 575: PauseMusicStream() (1 input parameters) +Function 576: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 576: ResumeMusicStream() (1 input parameters) +Function 577: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 577: SeekMusicStream() (2 input parameters) +Function 578: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 578: SetMusicVolume() (2 input parameters) +Function 579: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 579: SetMusicPitch() (2 input parameters) +Function 580: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 580: SetMusicPan() (2 input parameters) +Function 581: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for music (-1.0 left, 0.0 center, 1.0 right) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 581: GetMusicTimeLength() (1 input parameters) +Function 582: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 582: GetMusicTimePlayed() (1 input parameters) +Function 583: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 583: LoadAudioStream() (3 input parameters) +Function 584: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 584: IsAudioStreamValid() (1 input parameters) +Function 585: IsAudioStreamValid() (1 input parameters) Name: IsAudioStreamValid Return type: bool Description: Check if an audio stream is valid (buffers initialized) Param[1]: stream (type: AudioStream) -Function 585: UnloadAudioStream() (1 input parameters) +Function 586: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 586: UpdateAudioStream() (3 input parameters) +Function 587: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 587: IsAudioStreamProcessed() (1 input parameters) +Function 588: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 588: PlayAudioStream() (1 input parameters) +Function 589: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 589: PauseAudioStream() (1 input parameters) +Function 590: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 590: ResumeAudioStream() (1 input parameters) +Function 591: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 591: IsAudioStreamPlaying() (1 input parameters) +Function 592: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 592: StopAudioStream() (1 input parameters) +Function 593: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 593: SetAudioStreamVolume() (2 input parameters) +Function 594: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 594: SetAudioStreamPitch() (2 input parameters) +Function 595: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 595: SetAudioStreamPan() (2 input parameters) +Function 596: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (-1.0 left, 0.0 center, 1.0 right) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 596: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 597: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 597: SetAudioStreamCallback() (2 input parameters) +Function 598: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 598: AttachAudioStreamProcessor() (2 input parameters) +Function 599: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives frames x 2 samples as 'float' (stereo) Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 599: DetachAudioStreamProcessor() (2 input parameters) +Function 600: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 600: AttachAudioMixedProcessor() (1 input parameters) +Function 601: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives frames x 2 samples as 'float' (stereo) Param[1]: processor (type: AudioCallback) -Function 601: DetachAudioMixedProcessor() (1 input parameters) +Function 602: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index b7d1bdc17..e9db25846 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -682,7 +682,7 @@ - + @@ -1705,7 +1705,7 @@ - + @@ -1997,7 +1997,7 @@ - + @@ -2112,7 +2112,15 @@ - + + + + + + + + + @@ -3019,17 +3027,17 @@ - - - - - + + + + + From 72a341a37fbd9ccc1d8ec284ff20aeb5b991ad75 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Apr 2026 12:34:43 +0200 Subject: [PATCH 155/185] Update rtext.c --- src/rtext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtext.c b/src/rtext.c index dbf411ad0..a3ec016f5 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -1724,7 +1724,7 @@ const char *TextRemoveSpaces(const char *text) if (text != NULL) { // Avoid copying the ' ' characters - for (int i = 0, j = 0; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[j] != '\0'); i++) + for (int i = 0, j = 0; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[i] != '\0'); i++) { if (text[i] != ' ') { buffer[j] = text[i]; j++; } } From 3c82b48b1f4941300313b520d91df903ebdd3034 Mon Sep 17 00:00:00 2001 From: Ebben Feagan Date: Mon, 27 Apr 2026 15:27:13 -0500 Subject: [PATCH 156/185] Update BINDINGS.md to reflect raylib4fb project supporting 6.0 (#5813) --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 5ccd69cf4..02740f42b 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -33,7 +33,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 | | [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 | | [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 5.5 | [Factor](https://factorcode.org) | BSD | -| [raylib4fb](https://github.com/mudhairless/raylib4fb) | **5.5** | [FreeBASIC](https://www.freebasic.net) | Zlib | +| [raylib4fb](https://github.com/mudhairless/raylib4fb) | **6.0** | [FreeBASIC](https://www.freebasic.net) | Zlib | | [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT | | [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib | | [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC | From 6a430eb8348860ccb09e2cb5fe7510c8a2be3c7a Mon Sep 17 00:00:00 2001 From: Jim Price Date: Tue, 28 Apr 2026 03:26:30 -0700 Subject: [PATCH 157/185] [examples] Update build.zig to support wasm examples (#5811) * Include resource preloads when building wasm examples with Zig. List of resources derived from examples/Makefile.Web * Move resource list to zon file to reduce build.zig bloat --- build.zig | 7 + examples/example_resources.zon | 1422 ++++++++++++++++++++++++++++++++ 2 files changed, 1429 insertions(+) create mode 100644 examples/example_resources.zon diff --git a/build.zig b/build.zig index eb1eb5cc6..5485cda47 100644 --- a/build.zig +++ b/build.zig @@ -706,10 +706,16 @@ fn addExamples( const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize }); const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize }); + const EmccExamplesPreloadMap = std.static_string_map.StaticStringMap([]const emsdk.zemscripten.EmccFilePath); + const EmccExamplesPreloadKV = struct { []const u8, []const emsdk.zemscripten.EmccFilePath }; + const emcc_examples_preloads: []const EmccExamplesPreloadKV = @import("examples/example_resources.zon"); + const emcc_examples_preloads_map = EmccExamplesPreloadMap.initComptime(emcc_examples_preloads); + const emcc_step = emsdk.emccStep(b, raylib, wasm, .{ .optimize = optimize, .flags = emcc_flags, .settings = emcc_settings, + .preload_paths = emcc_examples_preloads_map.get(filename) orelse &.{}, .shell_file_path = b.path("src/shell.html"), .install_dir = install_dir, }); @@ -788,3 +794,4 @@ fn waylandGenerate( } } } + diff --git a/examples/example_resources.zon b/examples/example_resources.zon new file mode 100644 index 000000000..e577fc6fc --- /dev/null +++ b/examples/example_resources.zon @@ -0,0 +1,1422 @@ +.{ + .{ + "core_input_gamepad", + .{ + .{ + .src_path = "examples/core/resources/ps3.png", + .virtual_path = "resources/ps3.png", + }, + .{ + .src_path = "examples/core/resources/xbox.png", + .virtual_path = "resources/xbox.png", + }, + }, + }, + .{ + "core_text_file_loading", + .{ + .{ + .src_path = "examples/core/resources/text_file.txt", + .virtual_path = "resources/text_file.txt", + }, + }, + }, + .{ + "core_vr_simulator", + .{ + .{ + .src_path = "examples/core/resources/shaders/glsl100/distortion.fs", + .virtual_path = "resources/shaders/glsl100/distortion.fs", + }, + }, + }, + .{ + "textures_background_scrolling", + .{ + .{ + .src_path = "examples/textures/resources/cyberpunk_street_background.png", + .virtual_path = "resources/cyberpunk_street_background.png", + }, + .{ + .src_path = "examples/textures/resources/cyberpunk_street_midground.png", + .virtual_path = "resources/cyberpunk_street_midground.png", + }, + .{ + .src_path = "examples/textures/resources/cyberpunk_street_foreground.png", + .virtual_path = "resources/cyberpunk_street_foreground.png", + }, + }, + }, + .{ + "textures_blend_modes", + .{ + .{ + .src_path = "examples/textures/resources/cyberpunk_street_background.png", + .virtual_path = "resources/cyberpunk_street_background.png", + }, + .{ + .src_path = "examples/textures/resources/cyberpunk_street_foreground.png", + .virtual_path = "resources/cyberpunk_street_foreground.png", + }, + }, + }, + .{ + "textures_bunnymark", + .{ + .{ + .src_path = "examples/textures/resources/raybunny.png", + .virtual_path = "resources/raybunny.png", + }, + }, + }, + .{ + "textures_gif_player", + .{ + .{ + .src_path = "examples/textures/resources/scarfy_run.gif", + .virtual_path = "resources/scarfy_run.gif", + }, + }, + }, + .{ + "textures_image_channel", + .{ + .{ + .src_path = "examples/textures/resources/fudesumi.png", + .virtual_path = "resources/fudesumi.png", + }, + }, + }, + .{ + "textures_image_drawing", + .{ + .{ + .src_path = "examples/textures/resources/cat.png", + .virtual_path = "resources/cat.png", + }, + .{ + .src_path = "examples/textures/resources/parrots.png", + .virtual_path = "resources/parrots.png", + }, + .{ + .src_path = "examples/textures/resources/custom_jupiter_crash.png", + .virtual_path = "resources/custom_jupiter_crash.png", + }, + }, + }, + .{ + "textures_image_kernel", + .{ + .{ + .src_path = "examples/textures/resources/cat.png", + .virtual_path = "resources/cat.png", + }, + }, + }, + .{ + "textures_image_loading", + .{ + .{ + .src_path = "examples/textures/resources/raylib_logo.png", + .virtual_path = "resources/raylib_logo.png", + }, + }, + }, + .{ + "textures_image_processing", + .{ + .{ + .src_path = "examples/textures/resources/parrots.png", + .virtual_path = "resources/parrots.png", + }, + }, + }, + .{ + "textures_image_rotate", + .{ + .{ + .src_path = "examples/textures/resources/raylib_logo.png", + .virtual_path = "resources/raylib_logo.png", + }, + }, + }, + .{ + "textures_image_text", + .{ + .{ + .src_path = "examples/textures/resources/parrots.png", + .virtual_path = "resources/parrots.png", + }, + .{ + .src_path = "examples/textures/resources/KAISG.ttf", + .virtual_path = "resources/KAISG.ttf", + }, + }, + }, + .{ + "textures_logo_raylib", + .{ + .{ + .src_path = "examples/textures/resources/raylib_logo.png", + .virtual_path = "resources/raylib_logo.png", + }, + }, + }, + .{ + "textures_magnifying_glass", + .{ + .{ + .src_path = "examples/textures/resources/raybunny.png", + .virtual_path = "resources/raybunny.png", + }, + .{ + .src_path = "examples/textures/resources/parrots.png", + .virtual_path = "resources/parrots.png", + }, + }, + }, + .{ + "textures_npatch_drawing", + .{ + .{ + .src_path = "examples/textures/resources/ninepatch_button.png", + .virtual_path = "resources/ninepatch_button.png", + }, + }, + }, + .{ + "textures_particles_blending", + .{ + .{ + .src_path = "examples/textures/resources/spark_flame.png", + .virtual_path = "resources/spark_flame.png", + }, + }, + }, + .{ + "textures_polygon_drawing", + .{ + .{ + .src_path = "examples/textures/resources/cat.png", + .virtual_path = "resources/cat.png", + }, + }, + }, + .{ + "textures_raw_data", + .{ + .{ + .src_path = "examples/textures/resources/fudesumi.raw", + .virtual_path = "resources/fudesumi.raw", + }, + }, + }, + .{ + "textures_sprite_animation", + .{ + .{ + .src_path = "examples/textures/resources/scarfy.png", + .virtual_path = "resources/scarfy.png", + }, + }, + }, + .{ + "textures_sprite_button", + .{ + .{ + .src_path = "examples/textures/resources/buttonfx.wav", + .virtual_path = "resources/buttonfx.wav", + }, + .{ + .src_path = "examples/textures/resources/button.png", + .virtual_path = "resources/button.png", + }, + }, + }, + .{ + "textures_sprite_explosion", + .{ + .{ + .src_path = "examples/textures/resources/boom.wav", + .virtual_path = "resources/boom.wav", + }, + .{ + .src_path = "examples/textures/resources/explosion.png", + .virtual_path = "resources/explosion.png", + }, + }, + }, + .{ + "textures_sprite_stacking", + .{ + .{ + .src_path = "examples/textures/resources/booth.png", + .virtual_path = "resources/booth.png", + }, + }, + }, + .{ + "textures_srcrec_dstrec", + .{ + .{ + .src_path = "examples/textures/resources/scarfy.png", + .virtual_path = "resources/scarfy.png", + }, + }, + }, + .{ + "textures_textured_curve", + .{ + .{ + .src_path = "examples/textures/resources/road.png", + .virtual_path = "resources/road.png", + }, + }, + }, + .{ + "textures_tiled_drawing", + .{ + .{ + .src_path = "examples/textures/resources/patterns.png", + .virtual_path = "resources/patterns.png", + }, + }, + }, + .{ + "textures_to_image", + .{ + .{ + .src_path = "examples/textures/resources/raylib_logo.png", + .virtual_path = "resources/raylib_logo.png", + }, + }, + }, + .{ + "text_3d_drawing", + .{ + .{ + .src_path = "examples/text/resources/shaders/glsl100/alpha_discard.fs", + .virtual_path = "resources/shaders/glsl100/alpha_discard.fs", + }, + }, + }, + .{ + "text_codepoints_loading", + .{ + .{ + .src_path = "examples/text/resources/DotGothic16-Regular.ttf", + .virtual_path = "resources/DotGothic16-Regular.ttf", + }, + }, + }, + .{ + "text_font_filters", + .{ + .{ + .src_path = "examples/text/resources/KAISG.ttf", + .virtual_path = "resources/KAISG.ttf", + }, + }, + }, + .{ + "text_font_loading", + .{ + .{ + .src_path = "examples/text/resources/pixantiqua.fnt", + .virtual_path = "resources/pixantiqua.fnt", + }, + .{ + .src_path = "examples/text/resources/pixantiqua.png", + .virtual_path = "resources/pixantiqua.png", + }, + .{ + .src_path = "examples/text/resources/pixantiqua.ttf", + .virtual_path = "resources/pixantiqua.ttf", + }, + }, + }, + .{ + "text_font_sdf", + .{ + .{ + .src_path = "examples/text/resources/anonymous_pro_bold.ttf", + .virtual_path = "resources/anonymous_pro_bold.ttf", + }, + .{ + .src_path = "examples/text/resources/shaders/glsl100/sdf.fs", + .virtual_path = "resources/shaders/glsl100/sdf.fs", + }, + }, + }, + .{ + "text_font_spritefont", + .{ + .{ + .src_path = "examples/text/resources/custom_mecha.png", + .virtual_path = "resources/custom_mecha.png", + }, + .{ + .src_path = "examples/text/resources/custom_alagard.png", + .virtual_path = "resources/custom_alagard.png", + }, + .{ + .src_path = "examples/text/resources/custom_jupiter_crash.png", + .virtual_path = "resources/custom_jupiter_crash.png", + }, + }, + }, + .{ + "text_sprite_fonts", + .{ + .{ + .src_path = "examples/text/resources/sprite_fonts/alagard.png", + .virtual_path = "resources/sprite_fonts/alagard.png", + }, + .{ + .src_path = "examples/text/resources/sprite_fonts/pixelplay.png", + .virtual_path = "resources/sprite_fonts/pixelplay.png", + }, + .{ + .src_path = "examples/text/resources/sprite_fonts/mecha.png", + .virtual_path = "resources/sprite_fonts/mecha.png", + }, + .{ + .src_path = "examples/text/resources/sprite_fonts/setback.png", + .virtual_path = "resources/sprite_fonts/setback.png", + }, + .{ + .src_path = "examples/text/resources/sprite_fonts/romulus.png", + .virtual_path = "resources/sprite_fonts/romulus.png", + }, + .{ + .src_path = "examples/text/resources/sprite_fonts/pixantiqua.png", + .virtual_path = "resources/sprite_fonts/pixantiqua.png", + }, + .{ + .src_path = "examples/text/resources/sprite_fonts/alpha_beta.png", + .virtual_path = "resources/sprite_fonts/alpha_beta.png", + }, + .{ + .src_path = "examples/text/resources/sprite_fonts/jupiter_crash.png", + .virtual_path = "resources/sprite_fonts/jupiter_crash.png", + }, + }, + }, + .{ + "text_unicode_emojis", + .{ + .{ + .src_path = "examples/text/resources/dejavu.fnt", + .virtual_path = "resources/dejavu.fnt", + }, + .{ + .src_path = "examples/text/resources/dejavu.png", + .virtual_path = "resources/dejavu.png", + }, + .{ + .src_path = "examples/text/resources/noto_cjk.fnt", + .virtual_path = "resources/noto_cjk.fnt", + }, + .{ + .src_path = "examples/text/resources/noto_cjk.png", + .virtual_path = "resources/noto_cjk.png", + }, + .{ + .src_path = "examples/text/resources/symbola.fnt", + .virtual_path = "resources/symbola.fnt", + }, + .{ + .src_path = "examples/text/resources/symbola.png", + .virtual_path = "resources/symbola.png", + }, + }, + }, + .{ + "text_unicode_ranges", + .{ + .{ + .src_path = "examples/text/resources/NotoSansTC-Regular.ttf", + .virtual_path = "resources/NotoSansTC-Regular.ttf", + }, + }, + }, + .{ + "models_animation_blend_custom", + .{ + .{ + .src_path = "examples/models/resources/models/gltf/greenman.glb", + .virtual_path = "resources/models/gltf/greenman.glb", + }, + .{ + .src_path = "examples/models/resources/shaders/glsl100/skinning.vs", + .virtual_path = "resources/shaders/glsl100/skinning.vs", + }, + .{ + .src_path = "examples/models/resources/shaders/glsl100/skinning.fs", + .virtual_path = "resources/shaders/glsl100/skinning.fs", + }, + }, + }, + .{ + "models_animation_blending", + .{ + .{ + .src_path = "examples/models/resources/models/gltf/robot.glb", + .virtual_path = "resources/models/gltf/robot.glb", + }, + .{ + .src_path = "examples/models/resources/shaders/glsl100/skinning.vs", + .virtual_path = "resources/shaders/glsl100/skinning.vs", + }, + .{ + .src_path = "examples/models/resources/shaders/glsl100/skinning.fs", + .virtual_path = "resources/shaders/glsl100/skinning.fs", + }, + }, + }, + .{ + "models_animation_gpu_skinning", + .{ + .{ + .src_path = "examples/models/resources/models/gltf/greenman.glb", + .virtual_path = "resources/models/gltf/greenman.glb", + }, + .{ + .src_path = "examples/models/resources/shaders/glsl100/skinning.vs", + .virtual_path = "resources/shaders/glsl100/skinning.vs", + }, + .{ + .src_path = "examples/models/resources/shaders/glsl100/skinning.fs", + .virtual_path = "resources/shaders/glsl100/skinning.fs", + }, + }, + }, + .{ + "models_animation_timing", + .{ + .{ + .src_path = "examples/models/resources/models/gltf/robot.glb", + .virtual_path = "resources/models/gltf/robot.glb", + }, + }, + }, + .{ + "models_billboard_rendering", + .{ + .{ + .src_path = "examples/models/resources/billboard.png", + .virtual_path = "resources/billboard.png", + }, + }, + }, + .{ + "models_bone_socket", + .{ + .{ + .src_path = "examples/models/resources/models/gltf/greenman.glb", + .virtual_path = "resources/models/gltf/greenman.glb", + }, + .{ + .src_path = "examples/models/resources/models/gltf/greenman_hat.glb", + .virtual_path = "resources/models/gltf/greenman_hat.glb", + }, + .{ + .src_path = "examples/models/resources/models/gltf/greenman_sword.glb", + .virtual_path = "resources/models/gltf/greenman_sword.glb", + }, + .{ + .src_path = "examples/models/resources/models/gltf/greenman_shield.glb", + .virtual_path = "resources/models/gltf/greenman_shield.glb", + }, + }, + }, + .{ + "models_cubicmap_rendering", + .{ + .{ + .src_path = "examples/models/resources/cubicmap.png", + .virtual_path = "resources/cubicmap.png", + }, + .{ + .src_path = "examples/models/resources/cubicmap_atlas.png", + .virtual_path = "resources/cubicmap_atlas.png", + }, + }, + }, + .{ + "models_decals", + .{ + .{ + .src_path = "examples/models/resources/models/obj/character.obj", + .virtual_path = "resources/models/obj/character.obj", + }, + .{ + .src_path = "examples/models/resources/models/obj/character_diffuse.png", + .virtual_path = "resources/models/obj/character_diffuse.png", + }, + .{ + .src_path = "examples/models/resources/raylib_logo.png", + .virtual_path = "resources/raylib_logo.png", + }, + }, + }, + .{ + "models_directional_billboard", + .{ + .{ + .src_path = "examples/models/resources/skillbot.png", + .virtual_path = "resources/skillbot.png", + }, + }, + }, + .{ + "models_first_person_maze", + .{ + .{ + .src_path = "examples/models/resources/cubicmap.png", + .virtual_path = "resources/cubicmap.png", + }, + .{ + .src_path = "examples/models/resources/cubicmap_atlas.png", + .virtual_path = "resources/cubicmap_atlas.png", + }, + }, + }, + .{ + "models_heightmap_rendering", + .{ + .{ + .src_path = "examples/models/resources/heightmap.png", + .virtual_path = "resources/heightmap.png", + }, + }, + }, + .{ + "models_loading", + .{ + .{ + .src_path = "examples/models/resources/models/obj/castle.obj", + .virtual_path = "resources/models/obj/castle.obj", + }, + .{ + .src_path = "examples/models/resources/models/obj/castle_diffuse.png", + .virtual_path = "resources/models/obj/castle_diffuse.png", + }, + }, + }, + .{ + "models_loading_gltf", + .{ + .{ + .src_path = "examples/models/resources/models/gltf/robot.glb", + .virtual_path = "resources/models/gltf/robot.glb", + }, + }, + }, + .{ + "models_loading_iqm", + .{ + .{ + .src_path = "examples/models/resources/models/iqm/guy.iqm", + .virtual_path = "resources/models/iqm/guy.iqm", + }, + .{ + .src_path = "examples/models/resources/models/iqm/guytex.png", + .virtual_path = "resources/models/iqm/guytex.png", + }, + .{ + .src_path = "examples/models/resources/models/iqm/guyanim.iqm", + .virtual_path = "resources/models/iqm/guyanim.iqm", + }, + }, + }, + .{ + "models_loading_m3d", + .{ + .{ + .src_path = "examples/models/resources/models/m3d/cesium_man.m3d", + .virtual_path = "resources/models/m3d/cesium_man.m3d", + }, + }, + }, + .{ + "models_loading_vox", + .{ + .{ + .src_path = "examples/models/resources/models/vox/chr_knight.vox", + .virtual_path = "resources/models/vox/chr_knight.vox", + }, + .{ + .src_path = "examples/models/resources/models/vox/chr_sword.vox", + .virtual_path = "resources/models/vox/chr_sword.vox", + }, + .{ + .src_path = "examples/models/resources/models/vox/monu9.vox", + .virtual_path = "resources/models/vox/monu9.vox", + }, + .{ + .src_path = "examples/models/resources/models/vox/fez.vox", + .virtual_path = "resources/models/vox/fez.vox", + }, + .{ + .src_path = "examples/models/resources/shaders/glsl100/voxel_lighting.vs", + .virtual_path = "resources/shaders/glsl100/voxel_lighting.vs", + }, + .{ + .src_path = "examples/models/resources/shaders/glsl100/voxel_lighting.fs", + .virtual_path = "resources/shaders/glsl100/voxel_lighting.fs", + }, + }, + }, + .{ + "models_mesh_picking", + .{ + .{ + .src_path = "examples/models/resources/models/obj/turret.obj", + .virtual_path = "resources/models/obj/turret.obj", + }, + .{ + .src_path = "examples/models/resources/models/obj/turret_diffuse.png", + .virtual_path = "resources/models/obj/turret_diffuse.png", + }, + }, + }, + .{ + "models_rotating_cube", + .{ + .{ + .src_path = "examples/models/resources/cubicmap_atlas.png", + .virtual_path = "resources/cubicmap_atlas.png", + }, + }, + }, + .{ + "models_skybox_rendering", + .{ + .{ + .src_path = "examples/models/resources/shaders/glsl100/skybox.vs", + .virtual_path = "resources/shaders/glsl100/skybox.vs", + }, + .{ + .src_path = "examples/models/resources/shaders/glsl100/skybox.fs", + .virtual_path = "resources/shaders/glsl100/skybox.fs", + }, + .{ + .src_path = "examples/models/resources/shaders/glsl100/cubemap.vs", + .virtual_path = "resources/shaders/glsl100/cubemap.vs", + }, + .{ + .src_path = "examples/models/resources/shaders/glsl100/cubemap.fs", + .virtual_path = "resources/shaders/glsl100/cubemap.fs", + }, + .{ + .src_path = "examples/models/resources/dresden_square_2k.hdr", + .virtual_path = "resources/dresden_square_2k.hdr", + }, + .{ + .src_path = "examples/models/resources/skybox.png", + .virtual_path = "resources/skybox.png", + }, + }, + }, + .{ + "models_textured_cube", + .{ + .{ + .src_path = "examples/models/resources/cubicmap_atlas.png", + .virtual_path = "resources/cubicmap_atlas.png", + }, + }, + }, + .{ + "models_yaw_pitch_roll", + .{ + .{ + .src_path = "examples/models/resources/models/obj/plane.obj", + .virtual_path = "resources/models/obj/plane.obj", + }, + .{ + .src_path = "examples/models/resources/models/obj/plane_diffuse.png", + .virtual_path = "resources/models/obj/plane_diffuse.png", + }, + }, + }, + .{ + "shaders_ascii_rendering", + .{ + .{ + .src_path = "examples/shaders/resources/fudesumi.png", + .virtual_path = "resources/fudesumi.png", + }, + .{ + .src_path = "examples/shaders/resources/raysan.png", + .virtual_path = "resources/raysan.png", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/ascii.fs", + .virtual_path = "resources/shaders/glsl100/ascii.fs", + }, + }, + }, + .{ + "shaders_basic_lighting", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/lighting.vs", + .virtual_path = "resources/shaders/glsl100/lighting.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/lighting.fs", + .virtual_path = "resources/shaders/glsl100/lighting.fs", + }, + }, + }, + .{ + "shaders_basic_pbr", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/pbr.vs", + .virtual_path = "resources/shaders/glsl100/pbr.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/pbr.fs", + .virtual_path = "resources/shaders/glsl100/pbr.fs", + }, + .{ + .src_path = "examples/shaders/resources/models/old_car_new.glb", + .virtual_path = "resources/models/old_car_new.glb", + }, + .{ + .src_path = "examples/shaders/resources/old_car_d.png", + .virtual_path = "resources/old_car_d.png", + }, + .{ + .src_path = "examples/shaders/resources/old_car_mra.png", + .virtual_path = "resources/old_car_mra.png", + }, + .{ + .src_path = "examples/shaders/resources/old_car_n.png", + .virtual_path = "resources/old_car_n.png", + }, + .{ + .src_path = "examples/shaders/resources/old_car_e.png", + .virtual_path = "resources/old_car_e.png", + }, + .{ + .src_path = "examples/shaders/resources/models/plane.glb", + .virtual_path = "resources/models/plane.glb", + }, + .{ + .src_path = "examples/shaders/resources/road_a.png", + .virtual_path = "resources/road_a.png", + }, + .{ + .src_path = "examples/shaders/resources/road_mra.png", + .virtual_path = "resources/road_mra.png", + }, + .{ + .src_path = "examples/shaders/resources/road_n.png", + .virtual_path = "resources/road_n.png", + }, + }, + }, + .{ + "shaders_cel_shading", + .{ + .{ + .src_path = "examples/shaders/resources/models/old_car_new.glb", + .virtual_path = "resources/models/old_car_new.glb", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/cel.vs", + .virtual_path = "resources/shaders/glsl100/cel.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/cel.fs", + .virtual_path = "resources/shaders/glsl100/cel.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/outline_hull.vs", + .virtual_path = "resources/shaders/glsl100/outline_hull.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/outline_hull.fs", + .virtual_path = "resources/shaders/glsl100/outline_hull.fs", + }, + }, + }, + .{ + "shaders_color_correction", + .{ + .{ + .src_path = "examples/shaders/resources/parrots.png", + .virtual_path = "resources/parrots.png", + }, + .{ + .src_path = "examples/shaders/resources/cat.png", + .virtual_path = "resources/cat.png", + }, + .{ + .src_path = "examples/shaders/resources/mandrill.png", + .virtual_path = "resources/mandrill.png", + }, + .{ + .src_path = "examples/shaders/resources/fudesumi.png", + .virtual_path = "resources/fudesumi.png", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/color_correction.fs", + .virtual_path = "resources/shaders/glsl100/color_correction.fs", + }, + }, + }, + .{ + "shaders_custom_uniform", + .{ + .{ + .src_path = "examples/shaders/resources/models/barracks.obj", + .virtual_path = "resources/models/barracks.obj", + }, + .{ + .src_path = "examples/shaders/resources/models/barracks_diffuse.png", + .virtual_path = "resources/models/barracks_diffuse.png", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/swirl.fs", + .virtual_path = "resources/shaders/glsl100/swirl.fs", + }, + }, + }, + .{ + "shaders_deferred_rendering", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/gbuffer.vs", + .virtual_path = "resources/shaders/glsl100/gbuffer.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/gbuffer.fs", + .virtual_path = "resources/shaders/glsl100/gbuffer.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/deferred_shading.vs", + .virtual_path = "resources/shaders/glsl100/deferred_shading.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/deferred_shading.fs", + .virtual_path = "resources/shaders/glsl100/deferred_shading.fs", + }, + }, + }, + .{ + "shaders_depth_rendering", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/depth_render.fs", + .virtual_path = "resources/shaders/glsl100/depth_render.fs", + }, + }, + }, + .{ + "shaders_depth_writing", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/depth_write.fs", + .virtual_path = "resources/shaders/glsl100/depth_write.fs", + }, + }, + }, + .{ + "shaders_eratosthenes_sieve", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/eratosthenes.fs", + .virtual_path = "resources/shaders/glsl100/eratosthenes.fs", + }, + }, + }, + .{ + "shaders_fog_rendering", + .{ + .{ + .src_path = "examples/shaders/resources/texel_checker.png", + .virtual_path = "resources/texel_checker.png", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/lighting.vs", + .virtual_path = "resources/shaders/glsl100/lighting.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/fog.fs", + .virtual_path = "resources/shaders/glsl100/fog.fs", + }, + }, + }, + .{ + "shaders_game_of_life", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/game_of_life.fs", + .virtual_path = "resources/shaders/glsl100/game_of_life.fs", + }, + .{ + .src_path = "examples/shaders/resources/game_of_life/r_pentomino.png", + .virtual_path = "resources/game_of_life/r_pentomino.png", + }, + .{ + .src_path = "examples/shaders/resources/game_of_life/glider.png", + .virtual_path = "resources/game_of_life/glider.png", + }, + .{ + .src_path = "examples/shaders/resources/game_of_life/acorn.png", + .virtual_path = "resources/game_of_life/acorn.png", + }, + .{ + .src_path = "examples/shaders/resources/game_of_life/spaceships.png", + .virtual_path = "resources/game_of_life/spaceships.png", + }, + .{ + .src_path = "examples/shaders/resources/game_of_life/still_lifes.png", + .virtual_path = "resources/game_of_life/still_lifes.png", + }, + .{ + .src_path = "examples/shaders/resources/game_of_life/oscillators.png", + .virtual_path = "resources/game_of_life/oscillators.png", + }, + .{ + .src_path = "examples/shaders/resources/game_of_life/puffer_train.png", + .virtual_path = "resources/game_of_life/puffer_train.png", + }, + .{ + .src_path = "examples/shaders/resources/game_of_life/glider_gun.png", + .virtual_path = "resources/game_of_life/glider_gun.png", + }, + .{ + .src_path = "examples/shaders/resources/game_of_life/breeder.png", + .virtual_path = "resources/game_of_life/breeder.png", + }, + }, + }, + .{ + "shaders_hot_reloading", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/reload.fs", + .virtual_path = "resources/shaders/glsl100/reload.fs", + }, + }, + }, + .{ + "shaders_hybrid_rendering", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/hybrid_raymarch.fs", + .virtual_path = "resources/shaders/glsl100/hybrid_raymarch.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/hybrid_raster.fs", + .virtual_path = "resources/shaders/glsl100/hybrid_raster.fs", + }, + }, + }, + .{ + "shaders_julia_set", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/julia_set.fs", + .virtual_path = "resources/shaders/glsl100/julia_set.fs", + }, + }, + }, + .{ + "shaders_lightmap_rendering", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/lightmap.vs", + .virtual_path = "resources/shaders/glsl100/lightmap.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/lightmap.fs", + .virtual_path = "resources/shaders/glsl100/lightmap.fs", + }, + .{ + .src_path = "examples/shaders/resources/cubicmap_atlas.png", + .virtual_path = "resources/cubicmap_atlas.png", + }, + .{ + .src_path = "examples/shaders/resources/spark_flame.png", + .virtual_path = "resources/spark_flame.png", + }, + }, + }, + .{ + "shaders_mandelbrot_set", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs", + .virtual_path = "resources/shaders/glsl100/mandelbrot_set.fs", + }, + }, + }, + .{ + "shaders_mesh_instancing", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/lighting_instancing.vs", + .virtual_path = "resources/shaders/glsl100/lighting_instancing.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/lighting.fs", + .virtual_path = "resources/shaders/glsl100/lighting.fs", + }, + }, + }, + .{ + "shaders_model_shader", + .{ + .{ + .src_path = "examples/shaders/resources/models/watermill.obj", + .virtual_path = "resources/models/watermill.obj", + }, + .{ + .src_path = "examples/shaders/resources/models/watermill_diffuse.png", + .virtual_path = "resources/models/watermill_diffuse.png", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/grayscale.fs", + .virtual_path = "resources/shaders/glsl100/grayscale.fs", + }, + }, + }, + .{ + "shaders_multi_sample2d", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/color_mix.fs", + .virtual_path = "resources/shaders/glsl100/color_mix.fs", + }, + }, + }, + .{ + "shaders_normalmap_rendering", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/normalmap.vs", + .virtual_path = "resources/shaders/glsl100/normalmap.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/normalmap.fs", + .virtual_path = "resources/shaders/glsl100/normalmap.fs", + }, + .{ + .src_path = "examples/shaders/resources/models/plane.glb", + .virtual_path = "resources/models/plane.glb", + }, + .{ + .src_path = "examples/shaders/resources/tiles_diffuse.png", + .virtual_path = "resources/tiles_diffuse.png", + }, + .{ + .src_path = "examples/shaders/resources/tiles_normal.png", + .virtual_path = "resources/tiles_normal.png", + }, + }, + }, + .{ + "shaders_palette_switch", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/palette_switch.fs", + .virtual_path = "resources/shaders/glsl100/palette_switch.fs", + }, + }, + }, + .{ + "shaders_postprocessing", + .{ + .{ + .src_path = "examples/shaders/resources/models/church.obj", + .virtual_path = "resources/models/church.obj", + }, + .{ + .src_path = "examples/shaders/resources/models/church_diffuse.png", + .virtual_path = "resources/models/church_diffuse.png", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/grayscale.fs", + .virtual_path = "resources/shaders/glsl100/grayscale.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/posterization.fs", + .virtual_path = "resources/shaders/glsl100/posterization.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/dream_vision.fs", + .virtual_path = "resources/shaders/glsl100/dream_vision.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/pixelizer.fs", + .virtual_path = "resources/shaders/glsl100/pixelizer.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/cross_hatching.fs", + .virtual_path = "resources/shaders/glsl100/cross_hatching.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/cross_stitching.fs", + .virtual_path = "resources/shaders/glsl100/cross_stitching.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/predator.fs", + .virtual_path = "resources/shaders/glsl100/predator.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/scanlines.fs", + .virtual_path = "resources/shaders/glsl100/scanlines.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/fisheye.fs", + .virtual_path = "resources/shaders/glsl100/fisheye.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/sobel.fs", + .virtual_path = "resources/shaders/glsl100/sobel.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/bloom.fs", + .virtual_path = "resources/shaders/glsl100/bloom.fs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/blur.fs", + .virtual_path = "resources/shaders/glsl100/blur.fs", + }, + }, + }, + .{ + "shaders_raymarching_rendering", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/raymarching.fs", + .virtual_path = "resources/shaders/glsl100/raymarching.fs", + }, + }, + }, + .{ + "shaders_rounded_rectangle", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/base.vs", + .virtual_path = "resources/shaders/glsl100/base.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/rounded_rectangle.fs", + .virtual_path = "resources/shaders/glsl100/rounded_rectangle.fs", + }, + }, + }, + .{ + "shaders_shadowmap_rendering", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/shadowmap.vs", + .virtual_path = "resources/shaders/glsl100/shadowmap.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/shadowmap.fs", + .virtual_path = "resources/shaders/glsl100/shadowmap.fs", + }, + .{ + .src_path = "examples/shaders/resources/models/robot.glb", + .virtual_path = "resources/models/robot.glb", + }, + }, + }, + .{ + "shaders_shapes_textures", + .{ + .{ + .src_path = "examples/shaders/resources/fudesumi.png", + .virtual_path = "resources/fudesumi.png", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/grayscale.fs", + .virtual_path = "resources/shaders/glsl100/grayscale.fs", + }, + }, + }, + .{ + "shaders_simple_mask", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/mask.fs", + .virtual_path = "resources/shaders/glsl100/mask.fs", + }, + .{ + .src_path = "examples/shaders/resources/plasma.png", + .virtual_path = "resources/plasma.png", + }, + .{ + .src_path = "examples/shaders/resources/mask.png", + .virtual_path = "resources/mask.png", + }, + }, + }, + .{ + "shaders_spotlight_rendering", + .{ + .{ + .src_path = "examples/shaders/resources/raysan.png", + .virtual_path = "resources/raysan.png", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/spotlight.fs", + .virtual_path = "resources/shaders/glsl100/spotlight.fs", + }, + }, + }, + .{ + "shaders_texture_outline", + .{ + .{ + .src_path = "examples/shaders/resources/fudesumi.png", + .virtual_path = "resources/fudesumi.png", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/outline.fs", + .virtual_path = "resources/shaders/glsl100/outline.fs", + }, + }, + }, + .{ + "shaders_texture_rendering", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/cubes_panning.fs", + .virtual_path = "resources/shaders/glsl100/cubes_panning.fs", + }, + }, + }, + .{ + "shaders_texture_tiling", + .{ + .{ + .src_path = "examples/shaders/resources/cubicmap_atlas.png", + .virtual_path = "resources/cubicmap_atlas.png", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/tiling.fs", + .virtual_path = "resources/shaders/glsl100/tiling.fs", + }, + }, + }, + .{ + "shaders_texture_waves", + .{ + .{ + .src_path = "examples/shaders/resources/space.png", + .virtual_path = "resources/space.png", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/wave.fs", + .virtual_path = "resources/shaders/glsl100/wave.fs", + }, + }, + }, + .{ + "shaders_vertex_displacement", + .{ + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/vertex_displacement.vs", + .virtual_path = "resources/shaders/glsl100/vertex_displacement.vs", + }, + .{ + .src_path = "examples/shaders/resources/shaders/glsl100/vertex_displacement.fs", + .virtual_path = "resources/shaders/glsl100/vertex_displacement.fs", + }, + }, + }, + .{ + "audio_mixed_processor", + .{ + .{ + .src_path = "examples/audio/resources/country.mp3", + .virtual_path = "resources/country.mp3", + }, + .{ + .src_path = "examples/audio/resources/coin.wav", + .virtual_path = "resources/coin.wav", + }, + }, + }, + .{ + "audio_module_playing", + .{ + .{ + .src_path = "examples/audio/resources/mini1111.xm", + .virtual_path = "resources/mini1111.xm", + }, + }, + }, + .{ + "audio_music_stream", + .{ + .{ + .src_path = "examples/audio/resources/country.mp3", + .virtual_path = "resources/country.mp3", + }, + }, + }, + .{ + "audio_sound_loading", + .{ + .{ + .src_path = "examples/audio/resources/sound.wav", + .virtual_path = "resources/sound.wav", + }, + .{ + .src_path = "examples/audio/resources/target.ogg", + .virtual_path = "resources/target.ogg", + }, + }, + }, + .{ + "audio_sound_multi", + .{ + .{ + .src_path = "examples/audio/resources/sound.wav", + .virtual_path = "resources/sound.wav", + }, + }, + }, + .{ + "audio_sound_positioning", + .{ + .{ + .src_path = "examples/audio/resources/coin.wav", + .virtual_path = "resources/coin.wav", + }, + }, + }, + .{ + "audio_spectrum_visualizer", + .{ + .{ + .src_path = "examples/audio/resources/shaders/glsl100/fft.fs", + .virtual_path = "resources/shaders/glsl100/fft.fs", + }, + .{ + .src_path = "examples/audio/resources/country.mp3", + .virtual_path = "resources/country.mp3", + }, + }, + }, + .{ + "audio_stream_effects", + .{ + .{ + .src_path = "examples/audio/resources/country.mp3", + .virtual_path = "resources/country.mp3", + }, + }, + }, +} From 638c1cb339ebddf40078f4c6dce98d3c8b1bbaaa Mon Sep 17 00:00:00 2001 From: surrealism <77070074+surrealism21@users.noreply.github.com> Date: Tue, 28 Apr 2026 17:10:15 -0400 Subject: [PATCH 158/185] Update BINDINGS.md (#5819) Raylib 6.0 support has been released for C3 --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 02740f42b..8cc499b4d 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -10,7 +10,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-ada](https://github.com/Fabien-Chouteau/raylib-ada) | **5.5** | [Ada](https://en.wikipedia.org/wiki/Ada_(programming_language)) | MIT | | [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.5** | [Beef](https://www.beeflang.org) | MIT | | [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT | -| [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib55.c3l) | **5.5** | [C3](https://c3-lang.org) | MIT | +| [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib6.c3l) | **6** | [C3](https://c3-lang.org) | MIT | | [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | | [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | | [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | From 168e2c43d0fddf823f8518ec013f5b1e68076072 Mon Sep 17 00:00:00 2001 From: Huang Zhaobin <52552971+zhaob1n@users.noreply.github.com> Date: Wed, 29 Apr 2026 06:18:33 +0800 Subject: [PATCH 159/185] fix(rcore): correct string boundary handling (#5812) Co-authored-by: Huang Zhaobin --- src/rcore.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index 8ee85a072..61bb10386 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -2004,7 +2004,7 @@ unsigned char *LoadFileData(const char *fileName, int *dataSize) { *dataSize = (int)count; - if ((*dataSize) != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded (%i bytes out of %i)", fileName, dataSize, count); + if ((*dataSize) != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded (%i bytes out of %i)", fileName, *dataSize, size); else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName); } } @@ -2365,8 +2365,7 @@ bool IsFileExtension(const char *fileName, const char *ext) { int fileExtLength = (int)strlen(fileExt); char fileExtLower[16] = { 0 }; - char *fileExtLowerPtr = fileExtLower; - for (int i = 0; (i < fileExtLength) && (i < 16); i++) + for (int i = 0; (i < fileExtLength) && (i < 15); i++) { // Copy and convert to lower-case if ((fileExt[i] >= 'A') && (fileExt[i] <= 'Z')) fileExtLower[i] = fileExt[i] + 32; @@ -2377,7 +2376,7 @@ bool IsFileExtension(const char *fileName, const char *ext) int extLength = (int)strlen(ext); char *extList = (char *)RL_CALLOC(extLength + 1, 1); char *extListPtrs[MAX_FILE_EXTENSIONS] = { 0 }; - strncpy(extList, ext, extLength); + memcpy(extList, ext, extLength); extListPtrs[0] = extList; for (int i = 0; i < extLength; i++) @@ -2386,11 +2385,15 @@ bool IsFileExtension(const char *fileName, const char *ext) if ((extList[i] >= 'A') && (extList[i] <= 'Z')) extList[i] += 32; // Get pointer to next extension and add null-terminator - if ((extList[i] == ';') && (extCount < (MAX_FILE_EXTENSIONS - 1))) + if (extList[i] == ';') { extList[i] = '\0'; - extListPtrs[extCount] = extList + i + 1; - extCount++; + + if (extCount < MAX_FILE_EXTENSIONS) + { + extListPtrs[extCount] = extList + i + 1; + extCount++; + } } } @@ -2398,7 +2401,7 @@ bool IsFileExtension(const char *fileName, const char *ext) { // Consider the case where extension provided // does not start with the '.' - fileExtLowerPtr = fileExtLower; + char *fileExtLowerPtr = fileExtLower; if (extListPtrs[i][0] != '.') fileExtLowerPtr++; if (strcmp(fileExtLowerPtr, extListPtrs[i]) == 0) @@ -2611,7 +2614,7 @@ const char *GetWorkingDirectory(void) static char currentDir[MAX_FILEPATH_LENGTH] = { 0 }; memset(currentDir, 0, MAX_FILEPATH_LENGTH); - char *path = GETCWD(currentDir, MAX_FILEPATH_LENGTH - 1); + char *path = GETCWD(currentDir, MAX_FILEPATH_LENGTH); return path; } @@ -2958,9 +2961,9 @@ unsigned int GetDirectoryFileCountEx(const char *basePath, const char *filter, b { // Construct new path from our base path #if defined(_WIN32) - int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", basePath, entity->d_name); + int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s\\%s", basePath, entity->d_name); #else - int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", basePath, entity->d_name); + int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s/%s", basePath, entity->d_name); #endif // Don't add to count if path too long if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH)) @@ -4286,9 +4289,9 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const { // Construct new path from our base path #if defined(_WIN32) - int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", basePath, dp->d_name); + int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s\\%s", basePath, dp->d_name); #else - int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", basePath, dp->d_name); + int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s/%s", basePath, dp->d_name); #endif if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH)) @@ -4300,7 +4303,7 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const if ((filter == NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL) || (strstr(filter, FILE_FILTER_TAG_FILE_ONLY) != NULL) || IsFileExtension(path, filter)) { - strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); + memcpy(files->paths[files->count], path, pathLength); files->count++; } } @@ -4308,7 +4311,7 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const { if ((filter != NULL) && ((strstr(filter, FILE_FILTER_TAG_DIR_ONLY) != NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL))) { - strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); + memcpy(files->paths[files->count], path, pathLength); files->count++; } From 2dd8d7e8b15e8167e621e96ebfc15d5b1139ea93 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 29 Apr 2026 01:08:16 +0200 Subject: [PATCH 160/185] Update rcore_desktop_sdl.c --- src/platforms/rcore_desktop_sdl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 901b86dd7..d0c6de258 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -1144,7 +1144,7 @@ const char *GetClipboardText(void) char *clipboard = SDL_GetClipboardText(); - int clipboardSize = snprintf(buffer, sizeof(buffer), "%s", clipboard); + int clipboardSize = snprintf(buffer, MAX_CLIPBOARD_BUFFER_LENGTH, "%s", clipboard); if (clipboardSize >= MAX_CLIPBOARD_BUFFER_LENGTH) { char *truncate = buffer + MAX_CLIPBOARD_BUFFER_LENGTH - 4; From e5702a716fd8237f3baa9f81b044aa21166f5801 Mon Sep 17 00:00:00 2001 From: Jeremiah Donley <108106416+JJLDonley@users.noreply.github.com> Date: Wed, 29 Apr 2026 02:41:48 -0400 Subject: [PATCH 161/185] Update DenoRaylib550 to Deno-Raylib with version 6.0 (#5821) --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 8cc499b4d..d6fd107bd 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -29,7 +29,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 | | [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) | Apache-2.0 | | [raylib-d](https://github.com/schveiguy/raylib-d) | **6.0** | [D](https://dlang.org) | Zlib | -| [DenoRaylib550](https://github.com/JJLDonley/DenoRaylib550) | **5.5** | [Deno](https://deno.land) | MIT | +| [Deno-Raylib](https://github.com/JJLDonley/Deno-Raylib) | **6.0** | [Deno / TS](https://deno.land) | MIT | | [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 | | [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 | | [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 5.5 | [Factor](https://factorcode.org) | BSD | From da55d9067c46c9270526b9469b8eb06899772d46 Mon Sep 17 00:00:00 2001 From: nate Date: Wed, 29 Apr 2026 16:43:50 +1000 Subject: [PATCH 162/185] added NPOT check to rlLoadTexture to match rlGenTextureMipmaps and WebGL 1.0 standard (#5820) --- src/rlgl.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/rlgl.h b/src/rlgl.h index 5c6e95afb..539f409df 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -3366,8 +3366,15 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format, // Texture parameters configuration // NOTE: glTexParameteri does NOT affect texture uploading #if defined(GRAPHICS_API_OPENGL_ES2) + + // Check if texture is power-of-two (POT) + bool texIsPOT = false; + + if (((width > 0) && ((width & (width - 1)) == 0)) && + ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true; + // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used - if (RLGL.ExtSupported.texNPOT) + if ((texIsPOT) || (RLGL.ExtSupported.texNPOT)) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis From d9427b1e6fcfbd02748402e2842664362103c759 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 29 Apr 2026 17:42:51 +0200 Subject: [PATCH 163/185] REVIEWED: Avoid static variable floating around and include it to PlatformData struct --- src/platforms/rcore_desktop_glfw.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index c2bd869e7..191a3130e 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -111,6 +111,12 @@ //---------------------------------------------------------------------------------- typedef struct { GLFWwindow *handle; // GLFW window handle (graphic device) +#if defined(__linux__) && defined(_GLFW_X11) + // Local storage for the window handle returned by glfwGetX11Window + // This is needed as X11 handles are integers and may not fit inside a pointer depending on platform + // Storing the handle locally and returning a pointer in GetWindowHandle allows the code to work regardless of pointer width + XID windowHandleX11; +#endif } PlatformData; //---------------------------------------------------------------------------------- @@ -755,12 +761,6 @@ void SetWindowFocused(void) glfwFocusWindow(platform.handle); } -#if defined(__linux__) && defined(_GLFW_X11) -// Local storage for the window handle returned by glfwGetX11Window -// This is needed as X11 handles are integers and may not fit inside a pointer depending on platform -// Storing the handle locally and returning a pointer in GetWindowHandle allows the code to work regardless of pointer width -static XID X11WindowHandle; -#endif // Get native window handle void *GetWindowHandle(void) { @@ -778,17 +778,16 @@ void *GetWindowHandle(void) } else { - X11WindowHandle = glfwGetX11Window(platform.handle); - return &X11WindowHandle; + platform.windowHandleX11 = glfwGetX11Window(platform.handle); + return &platform.windowHandleX11; } #else return glfwGetWaylandWindow(platform.handle); #endif #elif defined(_GLFW_X11) // Store the window handle localy and return a pointer to the variable instead - // Reasoning detailed in the declaration of X11WindowHandle - X11WindowHandle = glfwGetX11Window(platform.handle); - return &X11WindowHandle; + platform.windowHandleX11 = glfwGetX11Window(platform.handle); + return &platform.windowHandleX11; #endif #endif #if defined(__APPLE__) From 7b7ded566cf8852641f32e3a5f3798bb83c12c0e Mon Sep 17 00:00:00 2001 From: LLM Vector Engineer Date: Wed, 29 Apr 2026 19:45:25 +0400 Subject: [PATCH 164/185] Fix directory navigation in core_directory_files (#5823) Co-authored-by: zhanlong9890 --- examples/core/core_directory_files.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/examples/core/core_directory_files.c b/examples/core/core_directory_files.c index a5b19078f..2724db62e 100644 --- a/examples/core/core_directory_files.c +++ b/examples/core/core_directory_files.c @@ -21,6 +21,7 @@ #include "raygui.h" // Required for GUI controls #define MAX_FILEPATH_SIZE 1024 +#define FILE_FILTER "DIRS*;.png;.c" //------------------------------------------------------------------------------------ // Program main entry point @@ -41,7 +42,7 @@ int main(void) // NOTE: LoadDirectoryFiles() loads files and directories by default, // use LoadDirectoryFilesEx() for custom filters and recursive directories loading //FilePathList files = LoadDirectoryFiles(directory); - FilePathList files = LoadDirectoryFilesEx(directory, ".png;.c", false); + FilePathList files = LoadDirectoryFilesEx(directory, FILE_FILTER, false); int btnBackPressed = false; @@ -61,7 +62,22 @@ int main(void) { TextCopy(directory, GetPrevDirectoryPath(directory)); UnloadDirectoryFiles(files); - files = LoadDirectoryFiles(directory); + files = LoadDirectoryFilesEx(directory, FILE_FILTER, false); + + listScrollIndex = 0; + listItemActive = -1; + listItemFocused = -1; + } + + if ((listItemActive >= 0) && (listItemActive < (int)files.count) && DirectoryExists(files.paths[listItemActive])) + { + TextCopy(directory, files.paths[listItemActive]); + UnloadDirectoryFiles(files); + files = LoadDirectoryFilesEx(directory, FILE_FILTER, false); + + listScrollIndex = 0; + listItemActive = -1; + listItemFocused = -1; } //---------------------------------------------------------------------------------- From d580c475040590f17867cc7805627071f79b763a Mon Sep 17 00:00:00 2001 From: alphahex99 <57233055+alphahex99@users.noreply.github.com> Date: Wed, 29 Apr 2026 17:49:23 +0200 Subject: [PATCH 165/185] [raymath.h] Add missing (float * Vector) operator overloads (#5815) --- src/raymath.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/raymath.h b/src/raymath.h index 9398258dd..9f6ce22b1 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -2802,6 +2802,11 @@ inline const Vector2& operator -= (Vector2& lhs, const Vector2& rhs) return lhs; } +inline Vector2 operator * (const float& lhs, const Vector2& rhs) +{ + return Vector2Scale(rhs, lhs); +} + inline Vector2 operator * (const Vector2& lhs, const float& rhs) { return Vector2Scale(lhs, rhs); @@ -2896,6 +2901,11 @@ inline const Vector3& operator -= (Vector3& lhs, const Vector3& rhs) return lhs; } +inline Vector3 operator * (const float& lhs, const Vector3& rhs) +{ + return Vector3Scale(rhs, lhs); +} + inline Vector3 operator * (const Vector3& lhs, const float& rhs) { return Vector3Scale(lhs, rhs); @@ -2991,6 +3001,11 @@ inline const Vector4& operator -= (Vector4& lhs, const Vector4& rhs) return lhs; } +inline Vector4 operator * (const float& lhs, const Vector4& rhs) +{ + return Vector4Scale(rhs, lhs); +} + inline Vector4 operator * (const Vector4& lhs, const float& rhs) { return Vector4Scale(lhs, rhs); From d768dae402c8fad503aebd24dc17c38dbfa0b1e3 Mon Sep 17 00:00:00 2001 From: Lam Wei Lun Date: Thu, 30 Apr 2026 00:02:49 +0800 Subject: [PATCH 166/185] [build] Shift `__cplusplus` check to a higher level for `bool` type define (#5804) * Adds a missing macro definition check * Shifts __cplusplus check to a higher level for bool define * Copy same change to rgestures.h and rlgl.h * Fixes float comparison issues in raymath functions * Revert "Fixes float comparison issues in raymath functions" This reverts commit a266d0bbaae4a692deb48dae5f6c528a3b3d5048. --- src/raylib.h | 4 +++- src/rgestures.h | 5 ++++- src/rlgl.h | 8 +++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 48f2724e1..e8164073f 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -203,12 +203,14 @@ // Types and Structures Definition //---------------------------------------------------------------------------------- // Boolean type +#if !defined(__cplusplus) #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800) #include -#elif !defined(__cplusplus) && !defined(bool) +#elif !defined(bool) typedef enum bool { false = 0, true = !false } bool; #define RL_BOOL_TYPE #endif +#endif // Vector2, 2 components typedef struct Vector2 { diff --git a/src/rgestures.h b/src/rgestures.h index bb51d72ee..734d33f0f 100644 --- a/src/rgestures.h +++ b/src/rgestures.h @@ -59,10 +59,13 @@ // NOTE: Below types are required for standalone usage //---------------------------------------------------------------------------------- // Boolean type +#if !defined(__cplusplus) #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800) #include -#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE) +#elif !defined(bool) typedef enum bool { false = 0, true = !false } bool; + #define RL_BOOL_TYPE +#endif #endif #if !defined(RL_VECTOR2_TYPE) diff --git a/src/rlgl.h b/src/rlgl.h index 539f409df..76b765e2e 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -358,11 +358,13 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- +#if !defined(__cplusplus) #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800) #include -#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE) - // Boolean type -typedef enum bool { false = 0, true = !false } bool; +#elif !defined(bool) + typedef enum bool { false = 0, true = !false } bool; + #define RL_BOOL_TYPE +#endif #endif #if !defined(RL_MATRIX_TYPE) From 05c15c8ba775d2e05ddbe6ef4b248d6f2bfd3ace Mon Sep 17 00:00:00 2001 From: Tanguy Date: Fri, 1 May 2026 19:29:51 +0200 Subject: [PATCH 167/185] SDL: Use precise mouse wheel values (#5830) --- src/platforms/rcore_desktop_sdl.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index d0c6de258..1b434b5d2 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -1675,8 +1675,13 @@ void PollInputEvents(void) } break; case SDL_MOUSEWHEEL: { - CORE.Input.Mouse.currentWheelMove.x = (float)event.wheel.x; - CORE.Input.Mouse.currentWheelMove.y = (float)event.wheel.y; +#if defined(USING_VERSION_SDL3) + CORE.Input.Mouse.currentWheelMove.x = event.wheel.x; + CORE.Input.Mouse.currentWheelMove.y = event.wheel.y; +#else + CORE.Input.Mouse.currentWheelMove.x = event.wheel.preciseX; + CORE.Input.Mouse.currentWheelMove.y = event.wheel.preciseY; +#endif } break; case SDL_MOUSEMOTION: { From 0a2b81b128dc82aaad8b30f6d29cc67ff8c60c9f Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 2 May 2026 09:09:40 +0200 Subject: [PATCH 168/185] Update rcore_web.c --- src/platforms/rcore_web.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index b01672215..9d16c3e87 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -76,7 +76,6 @@ typedef struct { char canvasId[64]; // Keep current canvas id where wasm app is running // NOTE: Useful when trying to run multiple wasms in different canvases in same webpage - #if defined(GRAPHICS_API_OPENGL_SOFTWARE) unsigned int *pixels; // Pointer to pixel data buffer (RGBA 32bit format) #endif From cf9f27db545dd686b03f9f773cfbdb8a8dd9f72f Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 2 May 2026 09:09:50 +0200 Subject: [PATCH 169/185] Update raymath.h --- src/raymath.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raymath.h b/src/raymath.h index 9f6ce22b1..4751cf00e 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raymath v2.0 - Math functions to work with Vector2, Vector3, Matrix and Quaternions +* raymath v2.0 - Math functions to work with Vector2, Vector3, Vector4, Matrix and Quaternions * * CONVENTIONS: * - Matrix structure is defined as row-major (memory layout) but parameters naming AND all From 7207c03c7251d939293fc5477d99e9e9f88ca25b Mon Sep 17 00:00:00 2001 From: Jens Roth <98889125+jensroth-git@users.noreply.github.com> Date: Wed, 6 May 2026 12:38:52 +0200 Subject: [PATCH 170/185] [rlsw] ESP32 optimizations (#5827) * [rlsw] Add sw_rcp helper using Xtensa recip0.s for hot-path divisions Adds a `sw_rcp(x)` inline reciprocal that on Xtensa (ESP32 / ESP32-S3 LX6/LX7) emits a `recip0.s` seed plus two Newton-Raphson refinement steps -- 1-ULP accurate in ~7 instructions, all in FPU registers. On every other target it expands to plain `1.0f/x`, so generated code is byte-identical to before for non-Xtensa builds. Replaces the hot-path `1.0f/x` calls that were previously compiling to the `__divsf3` software helper on Xtensa: - perspective divide (1/w) in triangle clip-and-project (PCT and PC paths) - line and point clip-and-project NDC conversion - triangle span setup: dxRcp, blockLenRcp, wRcpA, wRcpB - triangle scanline setup: h02Rcp, h01Rcp, h12Rcp - axis-aligned quad: wRcp, hRcp - line rasterizer: stepRcp Other `1.0f/x` uses (matrix translate/normalize, texture init `tx`/`ty`, sw_matrix_rotate inverse-length) are not on the per-pixel hot path and are left untouched. Measured on ESP32-S3 @ 240 MHz, R5G6B5 240x240, textured 3D model: contributes to a ~10-15% rasterization speedup. Made-with: Cursor * [rlsw] Use ESP-DSP for 4x4 matrix multiply and per-vertex MVP transform Adds an opt-in ESP-DSP code path for ESP32 / ESP32-S3 builds. ESP-DSP is ESP-IDF's official optimized math library and ships hand-vectorized kernels that beat the scalar implementations on Xtensa. Two integration points: 1. `sw_matrix_mul_rst` -> `dspm_mult_4x4x4_f32` for any 4x4*4x4 multiply (used for MVP build, gluLookAt, push/multiply, etc.). rlsw stores matrices column-major and ESP-DSP reads row-major; the comment on the call site explains why the flat-buffer call still produces the correct column-major product (transpose-of-transposes equivalence). 2. `sw_immediate_push_vertex` -> `dspm_mult_4x4x1_f32` for the per-vertex clip-space transform. Because ESP-DSP expects a row-major matrix in this case, a row-major copy `matMVP_rm[16]` is maintained alongside `matMVP` and refreshed once per `isDirtyMVP` rebuild in `sw_immediate_begin`. Cost is 16 scalar copies per matrix update, amortized over thousands of vertices per frame. Detection is **opt-in** via `SW_USE_ESP_DSP` so existing ESP-IDF projects that don't depend on the `esp-dsp` component keep building unchanged. A user enables it from CMakeLists.txt (or anywhere before including rlgl.h): target_compile_definitions(${COMPONENT_LIB} PRIVATE SW_USE_ESP_DSP=1) and adds the dependency to `idf_component.yml`: espressif/esp-dsp: "^1.4.0" Measured on ESP32-S3 @ 240 MHz, R5G6B5 240x240, textured 3D model: contributes meaningfully to the overall frame-time improvement (combined with sw_rcp). Made-with: Cursor * [rlsw] Add SW_TEXTURE_REPEAT_POT_FAST opt-in for POT bitmask wrap Adds an opt-in compile-time flag that replaces the SW_REPEAT wrap chain with a bitmask (`x & (size-1)`) for power-of-two textures. NPOT textures keep using the original `sw_fract` / signed-modulo paths via a runtime `(size & (size-1)) == 0` check, so SW_REPEAT remains correct for them. Affects two samplers: - `sw_texture_sample_nearest`: drops the `floorf` + multiply + cast for POT textures in REPEAT mode (saves a software call on Xtensa). - `sw_texture_sample_linear`: replaces the `(x % w + w) % w` two-step modulo (a software divide on Xtensa) with a single bitwise AND for POT textures in REPEAT mode. Two's-complement int wrap covers negative coordinates correctly. Off by default: for POT textures sampled with negative UVs, bitmask wrap can differ from `sw_fract` wrap by one texel at the boundary. That is imperceptible at typical resolutions but technically a behavior change, so existing users get bit-for-bit identical output. Opt in if you control your asset UVs and want the speedup: #define SW_TEXTURE_REPEAT_POT_FAST This addresses the long-standing TODO comment "If the textures are POT, avoid the division for SW_REPEAT" in `sw_texture_sample_linear`. Made-with: Cursor --- src/external/rlsw.h | 157 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 136 insertions(+), 21 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 1155eee41..852f78ff7 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -164,6 +164,19 @@ #endif #endif +// Fast power-of-two texture wrap (SW_REPEAT mode only) +// When defined, textures whose width/height are powers of two use a bitmask +// wrap (`x & (size-1)`) instead of `floorf`-based fractional wrap or the +// signed `%` chain in the linear sampler. Saves a software divide on Xtensa +// and a few instructions everywhere. NPOT textures keep using the original +// path via a runtime `(size & (size-1)) == 0` check, so SW_REPEAT remains +// correct for them. The only observable behavior change is for POT textures +// sampled with negative UV coordinates: bitmask wrap (two's complement) can +// differ from `sw_fract` by one texel. Off by default to keep bit-for-bit +// behavior; opt in if you control your asset UVs. +// +// #define SW_TEXTURE_REPEAT_POT_FAST + //---------------------------------------------------------------------------------- // OpenGL Compatibility Types //---------------------------------------------------------------------------------- @@ -844,6 +857,17 @@ SWAPI void swGetFramebufferAttachmentParameteriv(SWattachment attachment, SWatta #endif #endif +// ESP-DSP acceleration: ESP-IDF ships an optimized math library that includes +// `dspm_mult_4x4x4_f32` (4x4 matrix multiply) and `dspm_mult_4x4x1_f32` +// (matrix * vector). These are S3-tuned hand-vectorized kernels that beat the +// scalar versions for both throughput and code-size. Detection is opt-in to +// keep the dependency optional: define SW_USE_ESP_DSP from your build system +// (or rely on the `idf_component.yml` example shown in the rlsw docs). +#if defined(ESP_PLATFORM) && defined(SW_USE_ESP_DSP) + #define SW_HAS_ESP_DSP + #include "dspm_mult.h" +#endif + #ifdef __cplusplus #define SW_CURLY_INIT(name) name #else @@ -1038,6 +1062,9 @@ typedef struct { SWmatrix currentMatrixMode; // Current matrix mode (e.g., sw_MODELVIEW, sw_PROJECTION) sw_matrix_t *currentMatrix; // Pointer to the currently used matrix according to the mode sw_matrix_t matMVP; // Model view projection matrix, calculated and used internally +#ifdef SW_HAS_ESP_DSP + float matMVP_rm[16]; // Row-major MVP, kept in sync for esp-dsp dspm_mult_4x4x1_f32 vertex transform +#endif bool isDirtyMVP; // Indicates if the MVP matrix should be rebuilt sw_handle_t boundFramebufferId; // Framebuffer currently bound @@ -1141,6 +1168,14 @@ static inline void sw_matrix_id(sw_matrix_t dst) static inline void sw_matrix_mul_rst(float *SW_RESTRICT dst, const float *SW_RESTRICT left, const float *SW_RESTRICT right) { +#ifdef SW_HAS_ESP_DSP + // dspm_mult_4x4x4_f32 treats its operands as row-major. rlsw stores matrices + // column-major, so passing them flat is equivalent to passing transposes: + // dspm_mult(L^T, R^T) computes (L^T)*(R^T) = (R*L)^T, written back into a + // flat array gives the same bit pattern as the column-major product (R*L) + // -- exactly the semantic the scalar fallback below has. + dspm_mult_4x4x4_f32(left, right, dst); +#else float l00 = left[0], l01 = left[1], l02 = left[2], l03 = left[3]; float l10 = left[4], l11 = left[5], l12 = left[6], l13 = left[7]; float l20 = left[8], l21 = left[9], l22 = left[10], l23 = left[11]; @@ -1165,6 +1200,7 @@ static inline void sw_matrix_mul_rst(float *SW_RESTRICT dst, const float *SW_RES dst[7] = l10*right[3] + l11*right[7] + l12*right[11] + l13*right[15]; dst[11] = l20*right[3] + l21*right[7] + l22*right[11] + l23*right[15]; dst[15] = l30*right[3] + l31*right[7] + l32*right[11] + l33*right[15]; +#endif } static inline void sw_matrix_mul(sw_matrix_t dst, const sw_matrix_t left, const sw_matrix_t right) @@ -1210,6 +1246,33 @@ static inline float sw_fract(float x) return (x - floorf(x)); } +// Fast reciprocal: 1-ULP accurate in ~7 instructions on Xtensa using the +// hardware `recip0.s` seed + two Newton-Raphson refinement steps. All work +// stays in FPU registers — no `__divsf3` software call. Hot-path divisions +// in the rasterizer (span/triangle setup, perspective divide, etc.) call +// this. On non-Xtensa targets it transparently expands to `1.0f / x`, so +// generated code is identical to before. +#if defined(__XTENSA__) +__attribute__((always_inline)) +static inline float sw_rcp(float x) +{ + float result, temp; + __asm__( + "recip0.s %0, %2\n" + "const.s %1, 1\n" + "msub.s %1, %2, %0\n" + "madd.s %0, %0, %1\n" + "const.s %1, 1\n" + "msub.s %1, %2, %0\n" + "maddn.s %0, %0, %1\n" + : "=&f"(result), "=&f"(temp) : "f"(x) + ); + return result; +} +#else +static inline float sw_rcp(float x) { return 1.0f/x; } +#endif + static inline uint8_t sw_luminance8(const uint8_t *color) { return (uint8_t)((color[0]*77 + color[1]*150 + color[2]*29) >> 8); @@ -2406,11 +2469,31 @@ static inline void sw_texture_free(sw_texture_t *texture) static inline void sw_texture_sample_nearest(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex, float u, float v) { - u = (tex->sWrap == SW_REPEAT)? sw_fract(u) : sw_saturate(u); - v = (tex->tWrap == SW_REPEAT)? sw_fract(v) : sw_saturate(v); + int x, y; - int x = u*tex->width; - int y = v*tex->height; +#ifdef SW_TEXTURE_REPEAT_POT_FAST + if ((tex->sWrap == SW_REPEAT) && ((tex->width & tex->wMinus1) == 0)) + { + x = (int)(u*tex->width) & tex->wMinus1; + } + else +#endif + { + u = (tex->sWrap == SW_REPEAT)? sw_fract(u) : sw_saturate(u); + x = (int)(u*tex->width); + } + +#ifdef SW_TEXTURE_REPEAT_POT_FAST + if ((tex->tWrap == SW_REPEAT) && ((tex->height & tex->hMinus1) == 0)) + { + y = (int)(v*tex->height) & tex->hMinus1; + } + else +#endif + { + v = (tex->tWrap == SW_REPEAT)? sw_fract(v) : sw_saturate(v); + y = (int)(v*tex->height); + } tex->readColor(color, tex->pixels, y*tex->width + x); } @@ -2432,13 +2515,19 @@ static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_t int x1 = x0 + 1; int y1 = y0 + 1; - // NOTE: If the textures are POT, avoid the division for SW_REPEAT - if (tex->sWrap == SW_CLAMP) { x0 = (x0 > tex->wMinus1)? tex->wMinus1 : x0; x1 = (x1 > tex->wMinus1)? tex->wMinus1 : x1; } +#ifdef SW_TEXTURE_REPEAT_POT_FAST + else if ((tex->width & tex->wMinus1) == 0) + { + // POT fast path: bitmask wrap covers negative ints via two's complement + x0 = x0 & tex->wMinus1; + x1 = x1 & tex->wMinus1; + } +#endif else { x0 = (x0%tex->width + tex->width)%tex->width; @@ -2450,6 +2539,13 @@ static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_t y0 = (y0 > tex->hMinus1)? tex->hMinus1 : y0; y1 = (y1 > tex->hMinus1)? tex->hMinus1 : y1; } +#ifdef SW_TEXTURE_REPEAT_POT_FAST + else if ((tex->height & tex->hMinus1) == 0) + { + y0 = y0 & tex->hMinus1; + y1 = y1 & tex->hMinus1; + } +#endif else { y0 = (y0%tex->height + tex->height)%tex->height; @@ -3366,7 +3462,7 @@ static void sw_triangle_clip_and_project(void) // Calculation of the reciprocal of W for normalization // as well as perspective-correct attributes - const float wRcp = 1.0f/v->position[3]; + const float wRcp = sw_rcp(v->position[3]); // Division of XYZ coordinates by weight v->position[0] *= wRcp; @@ -3481,7 +3577,7 @@ static void sw_quad_clip_and_project(void) // Calculation of the reciprocal of W for normalization // as well as perspective-correct attributes - const float wRcp = 1.0f/v->position[3]; + const float wRcp = sw_rcp(v->position[3]); // Division of XYZ coordinates by weight v->position[0] *= wRcp; @@ -3659,8 +3755,8 @@ static bool sw_line_clip_and_project(sw_vertex_t *v0, sw_vertex_t *v1) if (!sw_line_clip(v0, v1)) return false; // Convert clip coordinates to NDC - v0->position[3] = 1.0f/v0->position[3]; - v1->position[3] = 1.0f/v1->position[3]; + v0->position[3] = sw_rcp(v0->position[3]); + v1->position[3] = sw_rcp(v1->position[3]); for (int i = 0; i < 3; i++) { v0->position[i] *= v0->position[3]; @@ -3709,7 +3805,7 @@ static bool sw_point_clip_and_project(sw_vertex_t *v) if ((v->position[i] < -v->position[3]) || (v->position[i] > v->position[3])) return false; } - v->position[3] = 1.0f/v->position[3]; + v->position[3] = sw_rcp(v->position[3]); v->position[0] *= v->position[3]; v->position[1] *= v->position[3]; v->position[2] *= v->position[3]; @@ -3791,6 +3887,19 @@ static void sw_immediate_begin(SWdraw mode) RLSW.stackModelview[RLSW.stackModelviewCounter - 1], RLSW.stackProjection[RLSW.stackProjectionCounter - 1]); +#ifdef SW_HAS_ESP_DSP + // Pre-transpose to row-major so dspm_mult_4x4x1_f32(matMVP_rm, v, out) + // computes M*v directly in the per-vertex hot path. 16 scalar copies + // per MVP update vs. saving ~20 cycles per vertex transform. + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + RLSW.matMVP_rm[4*i + j] = RLSW.matMVP[4*j + i]; + } + } +#endif + RLSW.isDirtyMVP = false; } @@ -3842,11 +3951,17 @@ static void sw_immediate_push_vertex(const float position[4]) sw_vertex_t *vertex = &RLSW.primitive.buffer[RLSW.primitive.vertexCount++]; // Calculate clip coordinates +#ifdef SW_HAS_ESP_DSP + // dspm_mult_4x4x1_f32 declares its inputs non-const; rlsw treats them as + // read-only and the cast is safe (the kernel only loads from B). + dspm_mult_4x4x1_f32(RLSW.matMVP_rm, (float *)position, vertex->position); +#else const float *m = RLSW.matMVP; vertex->position[0] = m[0]*position[0] + m[4]*position[1] + m[8]*position[2] + m[12]*position[3]; vertex->position[1] = m[1]*position[0] + m[5]*position[1] + m[9]*position[2] + m[13]*position[3]; vertex->position[2] = m[2]*position[0] + m[6]*position[1] + m[10]*position[2] + m[14]*position[3]; vertex->position[3] = m[3]*position[0] + m[7]*position[1] + m[11]*position[2] + m[15]*position[3]; +#endif // Copy the attributes in the current vertex for (int i = 0; i < 4; i++) vertex->color[i] = RLSW.primitive.color[i]; @@ -5272,7 +5387,7 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t if (xStart == xEnd) return; // Compute the inverse horizontal distance along the X axis - float dxRcp = 1.0f/(end->position[0] - start->position[0]); + float dxRcp = sw_rcp(end->position[0] - start->position[0]); // Compute the interpolation steps along the X axis float dWdx = (end->position[3] - start->position[3])*dxRcp; @@ -5326,12 +5441,12 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t int blockEnd = x + SW_AFFINE_BLOCK; if (blockEnd > xEnd) blockEnd = xEnd; float blockLenF = (float)(blockEnd - x); - float blockLenRcp = 1.0f/blockLenF; + float blockLenRcp = sw_rcp(blockLenF); // Only 2 '1/w' here; none inside the pixel loop - float wRcpA = 1.0f/w; + float wRcpA = sw_rcp(w); float wB = w + dWdx*blockLenF; - float wRcpB = 1.0f/wB; + float wRcpB = sw_rcp(wB); // Perspective-correct color at both block endpoints, then affine gradient float srcColor[4] = { @@ -5459,9 +5574,9 @@ static void SW_RASTER_TRIANGLE(const sw_vertex_t *v0, const sw_vertex_t *v1, con if (h02 < 1e-6f) return; // Inverse edge dy for per-edge dV/dy (scanline interpolation) - float h02Rcp = 1.0f/h02; - float h01Rcp = (h01 > 1e-6f)? 1.0f/h01 : 0.0f; - float h12Rcp = (h12 > 1e-6f)? 1.0f/h12 : 0.0f; + float h02Rcp = sw_rcp(h02); + float h01Rcp = (h01 > 1e-6f)? sw_rcp(h01) : 0.0f; + float h12Rcp = (h12 > 1e-6f)? sw_rcp(h12) : 0.0f; // Compute gradients for each side of the triangle sw_vertex_t dVXdy02, dVXdy01, dVXdy12; @@ -5560,8 +5675,8 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b, float h = (float)(yMax - yMin); if ((w <= 0) || (h <= 0)) return; - float wRcp = 1.0f/w; - float hRcp = 1.0f/h; + float wRcp = sw_rcp(w); + float hRcp = sw_rcp(h); // Subpixel corrections float xSubstep = 1.0f - sw_fract(tl->position[0]); @@ -5746,7 +5861,7 @@ static void SW_RASTER_LINE(const sw_vertex_t *v0, const sw_vertex_t *v1) // Compute per pixel increments float xInc = dx/steps; float yInc = dy/steps; - float stepRcp = 1.0f/steps; + float stepRcp = sw_rcp(steps); #ifdef SW_ENABLE_DEPTH_TEST float zInc = (v1->position[2] - v0->position[2])*stepRcp; #endif From 080f5c94bd851d19e12aacdef24e5e8b2ebef401 Mon Sep 17 00:00:00 2001 From: Colin James Wood <82226641+NighthowlerStudios@users.noreply.github.com> Date: Thu, 7 May 2026 14:17:20 +0100 Subject: [PATCH 171/185] [rlsw][rcore_drm] Silence warnings when using PLATFORM_DRM and GRAPHICS_API_OPENGL_SOFTWARE (#5839) * fix warnings: goto label not used outside of SW_ENABLE_DEPTH_TEST * comment out x coordinates that aren't used in SW_RASTER_TRIANGLE * silence warnings: unused DrmModeConnector functions in rcore_drm.c when using GRAPHICS_API_OPENGL_SOFTWARE --- src/external/rlsw.h | 16 +++++++++++++--- src/platforms/rcore_drm.c | 5 +++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 852f78ff7..a1835d5f8 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -5517,7 +5517,9 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t } #endif + #ifdef SW_ENABLE_DEPTH_TEST discard: + #endif srcColor[0] += dSrcColordx[0]; srcColor[1] += dSrcColordx[1]; srcColor[2] += dSrcColordx[2]; @@ -5562,9 +5564,13 @@ static void SW_RASTER_TRIANGLE(const sw_vertex_t *v0, const sw_vertex_t *v1, con if (v0->position[1] > v1->position[1]) { const sw_vertex_t *tmp = v0; v0 = v1; v1 = tmp; } // Extracting coordinates from the sorted vertices - float x0 = v0->position[0], y0 = v0->position[1]; - float x1 = v1->position[0], y1 = v1->position[1]; - float x2 = v2->position[0], y2 = v2->position[1]; + // Put x away for safe keeping. Only y is used right now. Silences warnings. + //float x0 = v0->position[0]; + float y0 = v0->position[1]; + //float x1 = v1->position[0]; + float y1 = v1->position[1]; + //float x2 = v2->position[0]; + float y2 = v2->position[1]; // Compute height differences float h02 = y2 - y0; @@ -5774,7 +5780,9 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b, } #endif + #ifdef SW_ENABLE_DEPTH_TEST discard: + #endif color[0] += dCdx[0]; color[1] += dCdx[1]; color[2] += dCdx[2]; @@ -5927,7 +5935,9 @@ static void SW_RASTER_LINE(const sw_vertex_t *v0, const sw_vertex_t *v1) } #endif + #ifdef SW_ENABLE_DEPTH_TEST discard: + #endif x += xInc; y += yInc; #ifdef SW_ENABLE_DEPTH_TEST diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index da53223ef..748b8aab8 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -266,9 +266,12 @@ static void PollKeyboardEvents(void); // Process evdev keyboard events static void PollGamepadEvents(void); // Process evdev gamepad events static void PollMouseEvents(void); // Process evdev mouse events +// Not used by software rendering. +#if !defined(GRAPHICS_API_OPENGL_SOFTWARE) static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list static int FindNearestConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search the nearest matching DRM connector mode in connector's list +#endif static void SetupFramebuffer(int width, int height); // Setup main framebuffer (required by InitPlatform()) @@ -2560,6 +2563,7 @@ static void PollMouseEvents(void) } } +#if !defined(GRAPHICS_API_OPENGL_SOFTWARE) // Search matching DRM mode in connector's mode list static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode) { @@ -2648,6 +2652,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt return nearestIndex; } +#endif // Compute framebuffer size relative to screen size and display size // NOTE: Global variables CORE.Window.render.width/CORE.Window.render.height and CORE.Window.renderOffset.x/CORE.Window.renderOffset.y can be modified From 61537200c0f426018bafbbddf198f9d257ba3b0e Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 7 May 2026 15:18:42 +0200 Subject: [PATCH 172/185] Code cleaning --- src/platforms/rcore_desktop_rgfw.c | 14 +++++++------- src/platforms/rcore_desktop_win32.c | 5 ++--- src/rcore.c | 22 ---------------------- src/rshapes.c | 2 +- 4 files changed, 10 insertions(+), 33 deletions(-) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 43d80c77d..e9263cb04 100755 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -178,12 +178,12 @@ typedef struct { RGFW_monitor *monitor; mg_gamepads minigamepad; - #if defined(GRAPHICS_API_OPENGL_SOFTWARE) - RGFW_surface *surface; - u8 *surfacePixels; - i32 surfaceWidth; - i32 surfaceHeight; - #endif +#if defined(GRAPHICS_API_OPENGL_SOFTWARE) + RGFW_surface *surface; + u8 *surfacePixels; + i32 surfaceWidth; + i32 surfaceHeight; +#endif } PlatformData; //---------------------------------------------------------------------------------- @@ -1352,7 +1352,7 @@ void PollInputEvents(void) { // set flag that the window was resized CORE.Window.resizedLastFrame = true; - + #if defined(__APPLE__) if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) { diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index 86a6c01c0..a797234ba 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -1526,7 +1526,6 @@ int InitPlatform(void) if (hr < 0) TRACELOG(LOG_ERROR, "%s failed, hresult=0x%lx", "SetProcessDpiAwareness", (DWORD)hr); } */ - HINSTANCE hInstance = GetModuleHandleW(0); // Define window class @@ -1775,9 +1774,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara // WARNING: Don't trust the docs, they say this message can not be obtained if not calling DefWindowProc() // in response to WM_WINDOWPOSCHANGED but looks like when a window is created, // this message can be obtained without getting WM_WINDOWPOSCHANGED - + #if defined(GRAPHICS_API_OPENGL_SOFTWARE) - // WARNING: Waiting two frames before resizing because software-renderer backend is initilized with swInit() later + // WARNING: Waiting two frames before resizing because software-renderer backend is initilized with swInit() later // than InitPlatform(), that triggers WM_SIZE, so avoid crashing if (CORE.Time.frameCounter > 2) HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight); #else diff --git a/src/rcore.c b/src/rcore.c index 61bb10386..6672302dd 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -442,18 +442,6 @@ typedef enum AutomationEventType { ACTION_SETTARGETFPS // param[0]: fps } AutomationEventType; -// Event type to config events flags -// WARNING: Not used at the moment -typedef enum { - EVENT_INPUT_KEYBOARD = 0, - EVENT_INPUT_MOUSE = 1, - EVENT_INPUT_GAMEPAD = 2, - EVENT_INPUT_TOUCH = 4, - EVENT_INPUT_GESTURE = 8, - EVENT_WINDOW = 16, - EVENT_CUSTOM = 32 -} EventType; - // Event type name strings, required for export static const char *autoEventTypeName[] = { "EVENT_NONE", @@ -482,16 +470,6 @@ static const char *autoEventTypeName[] = { "ACTION_SETTARGETFPS" }; -/* -// Automation event (24 bytes) -// NOTE: Opaque struct, internal to raylib -struct AutomationEvent { - unsigned int frame; // Event frame - unsigned int type; // Event type (AutomationEventType) - int params[4]; // Event parameters (if required) -}; -*/ - static AutomationEventList *currentEventList = NULL; // Current automation events list, set by user, keep internal pointer static bool automationEventRecording = false; // Recording automation events flag //static short automationEventEnabled = 0b0000001111111111; // TODO: Automation events enabled for recording/playing diff --git a/src/rshapes.c b/src/rshapes.c index fa7f2cf2f..c06f20462 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -1434,7 +1434,7 @@ void DrawTriangleGradient(Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2 rlBegin(RL_QUADS); rlNormal3f(0.0f, 0.0f, 1.0f); - + rlColor4ub(c1.r, c1.g, c1.b, c1.a); rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); rlVertex2f(v1.x, v1.y); From 33e889907e26513c4aa03301ee5c3564d3449e0e Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 7 May 2026 15:20:24 +0200 Subject: [PATCH 173/185] ADDED: `GL_SHADING_LANGUAGE_VERSION` for `swGetString()` --- src/external/rlsw.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index a1835d5f8..cc786750c 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -213,6 +213,7 @@ typedef double GLclampd; #define GL_RENDERER 0x1F01 #define GL_VERSION 0x1F02 #define GL_EXTENSIONS 0x1F03 +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C //#define GL_ATTRIB_STACK_DEPTH 0x0BB0 //#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 @@ -520,6 +521,7 @@ typedef enum { SW_RENDERER = GL_RENDERER, SW_VERSION = GL_VERSION, SW_EXTENSIONS = GL_EXTENSIONS, + SW_SHADING_LANGUAGE_VERSION = GL_SHADING_LANGUAGE_VERSION, SW_COLOR_CLEAR_VALUE = GL_COLOR_CLEAR_VALUE, SW_DEPTH_CLEAR_VALUE = GL_DEPTH_CLEAR_VALUE, SW_CURRENT_COLOR = GL_CURRENT_COLOR, @@ -4279,6 +4281,7 @@ const char *swGetString(SWget name) case SW_RENDERER: result = "RLSW OpenGL Software Renderer"; break; case SW_VERSION: result = RLSW_VERSION; break; case SW_EXTENSIONS: result = "None"; break; + case SW_SHADING_LANGUAGE_VERSION: result = "Not supported"; break; default: RLSW.errCode = SW_INVALID_ENUM; break; } @@ -5565,11 +5568,8 @@ static void SW_RASTER_TRIANGLE(const sw_vertex_t *v0, const sw_vertex_t *v1, con // Extracting coordinates from the sorted vertices // Put x away for safe keeping. Only y is used right now. Silences warnings. - //float x0 = v0->position[0]; float y0 = v0->position[1]; - //float x1 = v1->position[0]; float y1 = v1->position[1]; - //float x2 = v2->position[0]; float y2 = v2->position[1]; // Compute height differences From aceb8ce3a8677758b1c0791c3bfdbb01cdb299b7 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 7 May 2026 15:24:08 +0200 Subject: [PATCH 174/185] Re-enable `GLFW_LINUX_ENABLE_WAYLAND` flag by default #5816 Wayland should be more stable at this point... --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 13f132707..118e6aae7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -119,7 +119,7 @@ USE_EXTERNAL_GLFW ?= FALSE # Enable support for X11 by default on Linux when using GLFW # NOTE: Wayland is disabled by default, only enable if you are sure -GLFW_LINUX_ENABLE_WAYLAND ?= FALSE +GLFW_LINUX_ENABLE_WAYLAND ?= TRUE GLFW_LINUX_ENABLE_X11 ?= TRUE # Enable support for X11 by default on Linux when using RGFW From 95bfa196fdfb737356b8a09ab2944e765a71280a Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Fri, 8 May 2026 09:08:09 +0100 Subject: [PATCH 175/185] [cmake] Fix config.h parsing into cmake options (#5844) Parse SUPPORT_ defines from src/config.h by their actual 0/1 values so CUSTOMIZE_BUILD exposes the correct defaults. Apply INCLUDE_EVERYTHING explicitly when registering dependent options. --- CMakeOptions.txt | 8 ++++++-- cmake/ParseConfigHeader.cmake | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CMakeOptions.txt b/CMakeOptions.txt index 55375116e..5eff4c311 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -29,11 +29,15 @@ option(GLFW_BUILD_WAYLAND "Build the bundled GLFW with Wayland support" OFF) option(GLFW_BUILD_X11 "Build the bundled GLFW with X11 support" ON) option(INCLUDE_EVERYTHING "Include everything disabled by default (for CI usage)" OFF) -set(OFF ${INCLUDE_EVERYTHING} CACHE INTERNAL "Replace any OFF by default with \${OFF} to have it covered by this option") include(ParseConfigHeader) foreach(FLAG IN LISTS CONFIG_HEADER_FLAGS) string(REGEX MATCH "([^=]+)=(.+)" _ ${FLAG}) - cmake_dependent_option(${CMAKE_MATCH_1} "" ${CMAKE_MATCH_2} CUSTOMIZE_BUILD ${CMAKE_MATCH_2}) + set(CONFIG_HEADER_FLAG_DEFAULT ${CMAKE_MATCH_2}) + if (INCLUDE_EVERYTHING AND "${CONFIG_HEADER_FLAG_DEFAULT}" STREQUAL "OFF") + set(CONFIG_HEADER_FLAG_DEFAULT ON) + endif() + + cmake_dependent_option(${CMAKE_MATCH_1} "" ${CONFIG_HEADER_FLAG_DEFAULT} CUSTOMIZE_BUILD ${CONFIG_HEADER_FLAG_DEFAULT}) endforeach() diff --git a/cmake/ParseConfigHeader.cmake b/cmake/ParseConfigHeader.cmake index 797eea3cd..6a4b96145 100644 --- a/cmake/ParseConfigHeader.cmake +++ b/cmake/ParseConfigHeader.cmake @@ -10,7 +10,9 @@ string(REGEX MATCHALL ${MACRO_REGEX} MACRO_LIST ${CONFIG_HEADER_CONTENT}) set(CONFIG_HEADER_FLAGS ${MACRO_LIST}) list(FILTER CONFIG_HEADER_FLAGS INCLUDE REGEX "^.+SUPPORT_") list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=OFF]] REGEX "^//") -list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=ON]]) +list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=\3]] REGEX "^[^/]") +list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE [[=0$]] [[=OFF]]) +list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE [[=1$]] [[=ON]]) set(CONFIG_HEADER_VALUES ${MACRO_LIST}) list(FILTER CONFIG_HEADER_VALUES EXCLUDE REGEX "(^.+SUPPORT_)|(^//)") From d840a100a7ca0a3495126f7c01ecf50d6920e688 Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Fri, 8 May 2026 19:16:45 +0100 Subject: [PATCH 176/185] [CMake] Add configure-time test for libatomic requirement (#5847) CMake now checks if -latomic is required for 64-bit atomics, and links it if it's required. Miniaudio is the only thing in raylib that needs it, so it's put behind SUPPORT_MODULE_RAUDIO. --- cmake/LibraryConfigurations.cmake | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/cmake/LibraryConfigurations.cmake b/cmake/LibraryConfigurations.cmake index 18680491d..ad026474f 100644 --- a/cmake/LibraryConfigurations.cmake +++ b/cmake/LibraryConfigurations.cmake @@ -7,6 +7,30 @@ if(POLICY CMP0072) cmake_policy(SET CMP0072 NEW) endif() +include(CheckCSourceCompiles) +include(CMakePushCheckState) + +function(raylib_check_libatomic_required result) + set(_atomic_test_source " +int main(void) +{ + volatile long long value = 0; + return (int)__atomic_fetch_add(&value, 1, __ATOMIC_SEQ_CST); +}") + + check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITHOUT_LIBATOMIC) + + if (RAYLIB_ATOMICS_WITHOUT_LIBATOMIC) + set(${result} FALSE PARENT_SCOPE) + else () + cmake_push_check_state() + list(APPEND CMAKE_REQUIRED_LIBRARIES atomic) + check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITH_LIBATOMIC) + cmake_pop_check_state() + set(${result} ${RAYLIB_ATOMICS_WITH_LIBATOMIC} PARENT_SCOPE) + endif () +endfunction() + set(RAYLIB_DEPENDENCIES "include(CMakeFindDependencyMacro)") if (${PLATFORM} STREQUAL "Desktop") @@ -222,6 +246,14 @@ endif () set(LIBS_PRIVATE ${LIBS_PRIVATE} ${OPENAL_LIBRARY}) +if (SUPPORT_MODULE_RAUDIO AND UNIX AND NOT APPLE) + raylib_check_libatomic_required(RAYLIB_LIBATOMIC_REQUIRED) + if (RAYLIB_LIBATOMIC_REQUIRED) + message(STATUS "64-bit atomics require libatomic") + list(APPEND LIBS_PRIVATE atomic) + endif () +endif () + if (${PLATFORM} MATCHES "Desktop") set(LIBS_PRIVATE ${LIBS_PRIVATE} glfw) endif () From 29ff1f02e94ac1d88d8f53f31dc09e3064fdbc33 Mon Sep 17 00:00:00 2001 From: mjt Date: Fri, 8 May 2026 21:19:08 +0300 Subject: [PATCH 177/185] Update Makefile comment (#5846) --- src/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 118e6aae7..f3c7d5d61 100644 --- a/src/Makefile +++ b/src/Makefile @@ -117,8 +117,7 @@ RAYLIB_MODULE_RAYGUI_PATH ?= $(RAYLIB_SRC_PATH)/../../raygui/src # Use external GLFW library instead of rglfw module USE_EXTERNAL_GLFW ?= FALSE -# Enable support for X11 by default on Linux when using GLFW -# NOTE: Wayland is disabled by default, only enable if you are sure +# Enable support for Wayland and X11 by default on Linux when using GLFW GLFW_LINUX_ENABLE_WAYLAND ?= TRUE GLFW_LINUX_ENABLE_X11 ?= TRUE From b2ea5eae5e24f10ed6d0aacc456b46f14650cbd4 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 8 May 2026 22:59:55 +0200 Subject: [PATCH 178/185] REVIEWED: `long long` usage in all raylib, minimize REVIEWED: Using `long long` format instead of `long long int`, more consistent with the `short` alternative for smaller `int`, instead of `short int` --- src/external/win32_clipboard.h | 12 +++++------ src/platforms/rcore_android.c | 4 ++-- src/platforms/rcore_desktop_glfw.c | 7 ++++--- src/platforms/rcore_desktop_rgfw.c | 10 +++++----- src/platforms/rcore_drm.c | 4 ++-- src/platforms/rcore_memory.c | 12 ++++++----- src/platforms/rcore_template.c | 6 ++++-- src/raudio.c | 8 ++++---- src/rcore.c | 32 +++++++++++++++--------------- src/rgestures.h | 27 ++++++++++++------------- src/rlgl.h | 2 +- 11 files changed, 64 insertions(+), 60 deletions(-) diff --git a/src/external/win32_clipboard.h b/src/external/win32_clipboard.h index 5c30fbd2e..ea0a34bd3 100644 --- a/src/external/win32_clipboard.h +++ b/src/external/win32_clipboard.h @@ -4,14 +4,14 @@ #ifndef WIN32_CLIPBOARD_ #define WIN32_CLIPBOARD_ -unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize); +unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned int *dataSize); #endif // WIN32_CLIPBOARD_ #ifdef WIN32_CLIPBOARD_IMPLEMENTATION #include #include #include -#include +#include // NOTE: These search for architecture is taken from "windows.h", and it's necessary to avoid including windows.h // and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. ) can cause problems is these are not defined @@ -213,7 +213,7 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih); // Get pixel data offset fr //---------------------------------------------------------------------------------- // Module Functions Definition //---------------------------------------------------------------------------------- -unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize) +unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned int *dataSize) { unsigned char *bmpData = NULL; @@ -228,7 +228,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long *width = bmpInfoHeader->biWidth; *height = bmpInfoHeader->biHeight; SIZE_T clipDataSize = GlobalSize(clipHandle); - if (clipDataSize >= sizeof(BITMAPINFOHEADER)) + if ((clipDataSize >= sizeof(BITMAPINFOHEADER)) && (clipDataSize < INT_MAX)) { int pixelOffset = GetPixelDataOffset(*bmpInfoHeader); @@ -236,7 +236,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long //------------------------------------------------------------------------ BITMAPFILEHEADER bmpFileHeader = { 0 }; SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize; - *dataSize = bmpFileSize; + *dataSize = (unsigned int)bmpFileSize; bmpFileHeader.bfType = 0x4D42; // BMP fil type constant bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine @@ -254,7 +254,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long } else { - TRACELOG(LOG_WARNING, "Clipboard data is malformed"); + TRACELOG(LOG_WARNING, "Clipboard data is not supported (>2GB?)"); GlobalUnlock(clipHandle); CloseClipboard(); } diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index c427d7a58..ca0de7239 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -656,9 +656,9 @@ double GetTime(void) double time = 0.0; struct timespec ts = { 0 }; clock_gettime(CLOCK_MONOTONIC, &ts); - unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; + unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec; - time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() + time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() return time; } diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 191a3130e..b1e100cf4 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1054,12 +1054,13 @@ Image GetClipboardImage(void) #if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES #if defined(_WIN32) - unsigned long long int dataSize = 0; + + unsigned int dataSize = 0; void *bmpData = NULL; int width = 0; int height = 0; - bmpData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize); + bmpData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize); if (bmpData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data."); else image = LoadImageFromMemory(".bmp", (const unsigned char *)bmpData, (int)dataSize); @@ -1112,7 +1113,7 @@ Image GetClipboardImage(void) XCloseDisplay(dpy); #else TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform"); -#endif // defined(_WIN32) +#endif // _WIN32 #else TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly"); #endif // SUPPORT_CLIPBOARD_IMAGE diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index e9263cb04..a71dbb15e 100755 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -1024,15 +1024,15 @@ Image GetClipboardImage(void) #if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES #if defined(_WIN32) - unsigned long long int dataSize = 0; // moved into _WIN32 scope until other platforms gain support - void *fileData = NULL; // moved into _WIN32 scope until other platforms gain support + unsigned int dataSize = 0; + void *fileData = NULL; int width = 0; int height = 0; - fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize); + fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize); if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data"); - else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, dataSize); + else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, (int)dataSize); #elif defined(__linux__) && defined(DRGFW_X11) @@ -1082,7 +1082,7 @@ Image GetClipboardImage(void) XCloseDisplay(dpy); #else TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement GetClipboardImage() for this OS"); -#endif // defined(_WIN32) +#endif // _WIN32 #else TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly"); #endif // SUPPORT_CLIPBOARD_IMAGE diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index 748b8aab8..659c80011 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -1006,9 +1006,9 @@ double GetTime(void) double time = 0.0; struct timespec ts = { 0 }; clock_gettime(CLOCK_MONOTONIC, &ts); - unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; + unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec; - time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() + time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() return time; } diff --git a/src/platforms/rcore_memory.c b/src/platforms/rcore_memory.c index b06187018..6926d8f4e 100644 --- a/src/platforms/rcore_memory.c +++ b/src/platforms/rcore_memory.c @@ -364,14 +364,16 @@ double GetTime(void) { double time = 0.0; #if defined(_WIN32) - LARGE_INTEGER now = { 0 }; - QueryPerformanceCounter(&now); - return (double)(now.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart; + LARGE_INTEGER currentTicks = { 0 }; + QueryPerformanceCounter(¤tTicks); + + time = (double)(currentTicks.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart; #elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__) struct timespec ts = { 0 }; clock_gettime(CLOCK_MONOTONIC, &ts); - unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; - time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() + unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec; + + time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() #endif return time; } diff --git a/src/platforms/rcore_template.c b/src/platforms/rcore_template.c index ee766867a..353d32d11 100644 --- a/src/platforms/rcore_template.c +++ b/src/platforms/rcore_template.c @@ -341,10 +341,12 @@ void SwapScreenBuffer(void) double GetTime(void) { double time = 0.0; + struct timespec ts = { 0 }; clock_gettime(CLOCK_MONOTONIC, &ts); - unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; - time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() + unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec; + + time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() return time; } diff --git a/src/raudio.c b/src/raudio.c index a007a1092..e4d36611c 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -858,7 +858,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0)) { drmp3_config config = { 0 }; - unsigned long long int totalFrameCount = 0; + unsigned long long totalFrameCount = 0; // NOTE: Forcing conversion to 32bit float sample size on reading wave.data = drmp3_open_memory_and_read_pcm_frames_f32(fileData, dataSize, &config, &totalFrameCount, NULL); @@ -868,7 +868,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int { wave.channels = config.channels; wave.sampleRate = config.sampleRate; - wave.frameCount = (int)totalFrameCount; + wave.frameCount = (unsigned int)totalFrameCount; // WARNING: Potential loss of data } else TRACELOG(LOG_WARNING, "WAVE: Failed to load MP3 data"); @@ -896,13 +896,13 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int #if SUPPORT_FILEFORMAT_FLAC else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0)) { - unsigned long long int totalFrameCount = 0; + unsigned long long totalFrameCount = 0; // NOTE: Forcing conversion to 16bit sample size on reading wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL); wave.sampleSize = 16; - if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount; + if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount; // WARNING: Potential loss of data else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data"); } #endif diff --git a/src/rcore.c b/src/rcore.c index 6672302dd..0dad0cd96 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -385,7 +385,7 @@ typedef struct CoreData { double draw; // Time measure for frame draw (seconds) double frame; // Time measure for one frame (seconds) double target; // Desired time for one frame, if 0 not applied (seconds) - unsigned long long int base; // Base time measure for hi-res timer (ticks or nanoseconds) + unsigned long long base; // Base time measure for hi-res timer (ticks or nanoseconds) unsigned int frameCounter; // Frame counter (frames) } Time; @@ -1970,7 +1970,7 @@ unsigned char *LoadFileData(const char *fileName, int *dataSize) size_t count = fread(data, sizeof(unsigned char), size, file); // WARNING: fread() returns a size_t value, usually 'unsigned int' (32bit compilation) and 'unsigned long long' (64bit compilation) - // dataSize is unified along raylib as a 'int' type, so, for file-sizes > INT_MAX (2147483647 bytes) there is a limitation + // dataSize is unified along raylib as a 'int' type, so, for file-sizes >INT_MAX (2147483647 bytes) there is a limitation if (count > 2147483647) { TRACELOG(LOG_WARNING, "FILEIO: [%s] File is bigger than 2147483647 bytes, avoid using LoadFileData()", fileName); @@ -3336,15 +3336,15 @@ unsigned int *ComputeSHA1(const unsigned char *data, int dataSize) memcpy(msg, data, dataSize); msg[dataSize] = 128; // Write the '1' bit - unsigned long long bitsLen = 8ULL * dataSize; - msg[newDataSize-1] = (unsigned char)(bitsLen); - msg[newDataSize-2] = (unsigned char)(bitsLen >> 8); - msg[newDataSize-3] = (unsigned char)(bitsLen >> 16); - msg[newDataSize-4] = (unsigned char)(bitsLen >> 24); - msg[newDataSize-5] = (unsigned char)(bitsLen >> 32); - msg[newDataSize-6] = (unsigned char)(bitsLen >> 40); - msg[newDataSize-7] = (unsigned char)(bitsLen >> 48); - msg[newDataSize-8] = (unsigned char)(bitsLen >> 56); + unsigned long long bitsLen = 8ULL*dataSize; + msg[newDataSize - 1] = (unsigned char)(bitsLen); + msg[newDataSize - 2] = (unsigned char)(bitsLen >> 8); + msg[newDataSize - 3] = (unsigned char)(bitsLen >> 16); + msg[newDataSize - 4] = (unsigned char)(bitsLen >> 24); + msg[newDataSize - 5] = (unsigned char)(bitsLen >> 32); + msg[newDataSize - 6] = (unsigned char)(bitsLen >> 40); + msg[newDataSize - 7] = (unsigned char)(bitsLen >> 48); + msg[newDataSize - 8] = (unsigned char)(bitsLen >> 56); // Process the message in successive 512-bit chunks for (int offset = 0; offset < newDataSize; offset += (512/8)) @@ -3453,8 +3453,8 @@ unsigned int *ComputeSHA256(const unsigned char *data, int dataSize) hash[6] = 0x1f83d9ab; hash[7] = 0x5be0cd19; - const unsigned long long int bitLen = ((unsigned long long int)dataSize)*8; - unsigned long long int paddedSize = dataSize + sizeof(dataSize); + const unsigned long long bitLen = 8ULL*dataSize; + unsigned long long paddedSize = dataSize + sizeof(dataSize); paddedSize += (64 - (paddedSize%64)); unsigned char *buffer = (unsigned char *)RL_CALLOC(paddedSize, sizeof(unsigned char)); @@ -3465,7 +3465,7 @@ unsigned int *ComputeSHA256(const unsigned char *data, int dataSize) buffer[(paddedSize - sizeof(bitLen)) + (i - 1)] = (bitLen >> (8*(sizeof(bitLen) - i))) & 0xFF; } - for (unsigned long long int blockN = 0; blockN < paddedSize/64; blockN++) + for (unsigned long long blockN = 0; blockN < paddedSize/64; blockN++) { unsigned int a = hash[0]; unsigned int b = hash[1]; @@ -3487,7 +3487,7 @@ unsigned int *ComputeSHA256(const unsigned char *data, int dataSize) } for (int t = 16; t < 64; t++) w[t] = SHA256_A1(w[t - 2]) + w[t - 7] + SHA256_A0(w[t - 15]) + w[t - 16]; - for (unsigned long long int t = 0; t < 64; t++) + for (int t = 0; t < 64; t++) { unsigned int e1 = (SHA256_ROTATE_RIGHT(e, 6) ^ SHA256_ROTATE_RIGHT(e, 11) ^ SHA256_ROTATE_RIGHT(e, 25)); unsigned int ch = ((e & f) ^ (~e & g)); @@ -4219,7 +4219,7 @@ void InitTimer(void) if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success { - CORE.Time.base = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; + CORE.Time.base = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec; } else TRACELOG(LOG_WARNING, "TIMER: Hi-resolution timer not available"); #endif diff --git a/src/rgestures.h b/src/rgestures.h index 734d33f0f..248e1f71a 100644 --- a/src/rgestures.h +++ b/src/rgestures.h @@ -157,8 +157,8 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang extern "C" { // Prevents name mangling of functions #endif // Functions required to query time on Windows - int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount); - int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency); + int __stdcall QueryPerformanceCounter(unsigned long long *lpPerformanceCount); + int __stdcall QueryPerformanceFrequency(unsigned long long *lpFrequency); #if defined(__cplusplus) } #endif @@ -518,37 +518,36 @@ static double rgGetCurrentTime(void) time = GetTime(); #else #if defined(_WIN32) - unsigned long long int clockFrequency, currentTime; + unsigned long long clockFrequency = 0; + unsigned long long currentClockTicks = 0; QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation! - QueryPerformanceCounter(¤tTime); + QueryPerformanceCounter(¤tClockTicks); - time = (double)currentTime/clockFrequency; // Time in seconds + time = (double)currentClockTicks/clockFrequency; // Time in seconds #endif - #if defined(__linux__) // NOTE: Only for Linux-based systems - struct timespec now; + struct timespec now = { 0 }; clock_gettime(CLOCK_MONOTONIC, &now); - unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds + unsigned long long nanoSeconds = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec; - time = ((double)nowTime*1e-9); // Time in seconds + time = ((double)nanoSeconds*1e-9); // Time in seconds #endif - #if defined(__APPLE__) //#define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01 //#define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time - clock_serv_t cclock; - mach_timespec_t now; + clock_serv_t cclock = { 0 }; + mach_timespec_t now = { 0 }; host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); // NOTE: OS X does not have clock_gettime(), using clock_get_time() clock_get_time(cclock, &now); mach_port_deallocate(mach_task_self(), cclock); - unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds + unsigned long long nanoSeconds = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec; - time = ((double)nowTime*1e-9); // Time in seconds + time = ((double)nanoSeconds*1e-9); // Time in seconds #endif #endif diff --git a/src/rlgl.h b/src/rlgl.h index 76b765e2e..ea5673397 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -3647,7 +3647,7 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break; case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break; case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break; - #else // defined(GRAPHICS_API_OPENGL_ES2) + #else // GRAPHICS_API_OPENGL_ES2 case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float From cd4599b447690c5be3e793fd24ba98fca9aaf7ae Mon Sep 17 00:00:00 2001 From: GnuChanOS <117280480+gnuchanos@users.noreply.github.com> Date: Sat, 9 May 2026 19:48:10 +0300 Subject: [PATCH 179/185] Update BINDINGS.md (#5850) --- BINDINGS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index d6fd107bd..7d1c43ca8 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -105,7 +105,8 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-jai](https://github.com/ahmedqarmout2/raylib-jai) | **5.5** | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | MIT | | [fnl-raylib](https://github.com/0riginaln0/fnl-raylib) | **5.5** | [Fennel](https://fennel-lang.org/) | MIT | | [Rayua](https://github.com/uiua-lang/rayua) | **5.5** | [Uiua](https://www.uiua.org/) | **???** | -| [Target](https://github.com/FinnDemonCat/Target/tree/main/libs/raylib) | **5.5** | [Dart](https://dart.dev/) | Apache-2.0 license | +| [Target](https://github.com/FinnDemonCat/Target/tree/main/libs/raylib) | **5.5** | [Dart](https://dart.dev/) | Apache-2.0 license | +| [gclang-raylib](https://github.com/gnuchanos/gcLang_Compiler/tree/main/windows_version/raylib_version)| **6.0** | [gclang](https://github.com/gnuchanos/gcLang_Compiler) | AGPL-3.0 | ### Utility Wrapers From 07b729d5d6d759ef91532b03617cac5939b9b748 Mon Sep 17 00:00:00 2001 From: Faraz Fallahi Date: Sat, 9 May 2026 09:55:02 -0700 Subject: [PATCH 180/185] fix: check fread return value in jar_mod_load_file (#5840) --- src/external/jar_mod.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/external/jar_mod.h b/src/external/jar_mod.h index 7ecf9f437..12b8101c4 100644 --- a/src/external/jar_mod.h +++ b/src/external/jar_mod.h @@ -1538,10 +1538,10 @@ mulong jar_mod_load_file(jar_mod_context_t * modctx, const char* filename) modctx->modfile = (muchar *) JARMOD_MALLOC(fsize); modctx->modfilesize = fsize; memset(modctx->modfile, 0, fsize); - fread(modctx->modfile, fsize, 1, f); + if(fread(modctx->modfile, fsize, 1, f) != 1) fsize = 0; fclose(f); - if(!jar_mod_load(modctx, (void *)modctx->modfile, fsize)) fsize = 0; + if(fsize && !jar_mod_load(modctx, (void *)modctx->modfile, fsize)) fsize = 0; } else fsize = 0; } return fsize; From dcb0ca5d14771d7e26daae8a418c40c2e9c0ce8a Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Sun, 10 May 2026 14:01:38 +0100 Subject: [PATCH 181/185] [raudio]: free converterResidual in UnloadSoundAlias to prevent leak (#5857) The example audio_sound_multi was leaking memory every single time the spacebar was pressed. ```c Direct leak of 576 byte(s) in 9 object(s) allocated from: #0 0x758a41019447 in calloc (/usr/lib/liblsan.so.0+0x19447) (BuildId: 8ee115309adc591d231c961c43d245cfa68d9aa7) #1 0x562dfbd2c4f3 in LoadAudioBuffer (/home/peter/raylib/examples/audio/audio_sound_multi+0xfa4f3) (BuildId: ea2a6f45d724abeccf904143a32012266f259f93) ``` This patch fixes that leak. --- src/raudio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/raudio.c b/src/raudio.c index e4d36611c..ff90d8e43 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1048,6 +1048,7 @@ void UnloadSoundAlias(Sound alias) { UntrackAudioBuffer(alias.stream.buffer); ma_data_converter_uninit(&alias.stream.buffer->converter, NULL); + RL_FREE(alias.stream.buffer->converterResidual); RL_FREE(alias.stream.buffer); } } From ae315eecb9d7fa10edd8cd7aacc1909754a25dc9 Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Sun, 10 May 2026 12:09:24 -0500 Subject: [PATCH 182/185] added win32 to cmake + examples (#5855) --- CMakeOptions.txt | 2 +- cmake/LibraryConfigurations.cmake | 15 +++++++++++++++ examples/Makefile | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CMakeOptions.txt b/CMakeOptions.txt index 5eff4c311..9e253dc55 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -6,7 +6,7 @@ if(EMSCRIPTEN) # When configuring web builds with "emcmake cmake -B build -S .", set PLATFORM to Web by default SET(PLATFORM Web CACHE STRING "Platform to build for.") endif() -enum_option(PLATFORM "Desktop;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory" "Platform to build for.") +enum_option(PLATFORM "Desktop;Win32;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory" "Platform to build for.") enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0;Software" "Force a specific OpenGL Version?") diff --git a/cmake/LibraryConfigurations.cmake b/cmake/LibraryConfigurations.cmake index ad026474f..262150be0 100644 --- a/cmake/LibraryConfigurations.cmake +++ b/cmake/LibraryConfigurations.cmake @@ -91,6 +91,21 @@ if (${PLATFORM} STREQUAL "Desktop") endif () endif () +elseif (${PLATFORM} STREQUAL "Win32") + if ((NOT WIN32) AND (NOT CMAKE_C_COMPILER MATCHES "mingw|mingw32|mingw64")) + message(FATAL_ERROR "Win32 platform requires Windows or a cross compiler.") + endif () + + set(PLATFORM_CPP "PLATFORM_DESKTOP_WIN32") + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + + if (${OPENGL_VERSION} MATCHES "Software") + set(GRAPHICS "GRAPHICS_API_OPENGL_SOFTWARE") + endif () + + find_package(OpenGL QUIET) + set(LIBS_PRIVATE ${OPENGL_LIBRARIES} winmm) + elseif (${PLATFORM} STREQUAL "Web") set(PLATFORM_CPP "PLATFORM_WEB") if(NOT GRAPHICS) diff --git a/examples/Makefile b/examples/Makefile index 334f59694..3e1844fc3 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -20,6 +20,8 @@ # - Linux (X11 desktop mode) # - macOS/OSX (x64, arm64 (not tested)) # - Others (not tested) +# > PLATFORM_DESKTOP_WIN32 (native Win32): +# - Windows (Win32, Win64) # > PLATFORM_WEB_RGFW: # - HTML5 (WebAssembly) # > PLATFORM_WEB: @@ -794,6 +796,23 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) rm -f *.o endif endif +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32) + ifeq ($(PLATFORM_OS),WINDOWS) + del *.o *.exe /s + endif + ifeq ($(PLATFORM_OS),BSD) + find . -type f -perm -ugo+x -delete + rm -fv *.o + endif + ifeq ($(PLATFORM_OS),LINUX) + find . -type f -executable -delete + rm -fv *.o + endif + ifeq ($(PLATFORM_OS),OSX) + find . -type f -perm +ugo+x -delete + rm -f *.o + endif +endif ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) find . -type f -executable -delete rm -fv *.o From a005a044dac0d55d6e7b0eb783541e4fa88138d3 Mon Sep 17 00:00:00 2001 From: Tubbles Date: Sun, 10 May 2026 19:20:35 +0200 Subject: [PATCH 183/185] [rcore_android] Restore face-button input on Android gamepads (#5824) The KEYBOARD-source veto added in #5439 drops face-button key events that arrive with both AINPUT_SOURCE_KEYBOARD and AINPUT_SOURCE_GAMEPAD set on the source bitmask. Confirmed reproducible on GameSir X2 Type-C and 8BitDo Ultimate Bluetooth, both reporting source 0x501 on every face-button key event. This source-bit pattern is general AOSP behaviour since Android 3.2 (commit 6f2fba4 in frameworks/base, Feb 2011): EventHub adds InputDeviceClass::KEYBOARD to any device whose evdev keyBitmask claims gamepad buttons (BTN_JOYSTICK..BTN_DIGI), and KeyboardInputMapper::getEventSource stamps the resulting KEYBOARD|GAMEPAD source on every outgoing key event. Use AndroidTranslateGamepadButton(keycode) as the discriminator instead. Recognised gamepad keycodes route to the gamepad path; unknown keycodes fall through to the keyboard handler. Assisted-by: Claude:claude-opus-4-7 --- src/platforms/rcore_android.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index ca0de7239..990b2fe6a 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -1273,27 +1273,28 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) int32_t keycode = AKeyEvent_getKeyCode(event); //int32_t AKeyEvent_getMetaState(event); - // Handle gamepad button presses and releases - // NOTE: Skip gamepad handling if this is a keyboard event, as some devices - // report both AINPUT_SOURCE_KEYBOARD and AINPUT_SOURCE_GAMEPAD flags - if ((FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) || - FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) && - !FLAG_IS_SET(source, AINPUT_SOURCE_KEYBOARD)) + // Handle gamepad button presses and releases. AOSP stamps the + // KEYBOARD source bit on every key event from a gamepad, so + // discriminate on the keycode rather than gating on source bits. + if (FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) || + FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) { - // Assuming a single gamepad, "detected" on its input event - CORE.Input.Gamepad.ready[0] = true; - GamepadButton button = AndroidTranslateGamepadButton(keycode); - if (button == GAMEPAD_BUTTON_UNKNOWN) return 1; - - if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) + if (button != GAMEPAD_BUTTON_UNKNOWN) { - CORE.Input.Gamepad.currentButtonState[0][button] = 1; - } - else CORE.Input.Gamepad.currentButtonState[0][button] = 0; // Key up + // Assuming a single gamepad, "detected" on its input event + CORE.Input.Gamepad.ready[0] = true; - return 1; // Handled gamepad button + 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 + } + // Unknown keycode: fall through to the keyboard handler below. } KeyboardKey key = ((keycode > 0) && (keycode < KEYCODE_MAP_SIZE))? mapKeycode[keycode] : KEY_NULL; From 094edcd32e153e4a0363dec1c096881cd9e31db0 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 10 May 2026 19:31:19 +0200 Subject: [PATCH 184/185] Update Makefile --- src/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index f3c7d5d61..13f132707 100644 --- a/src/Makefile +++ b/src/Makefile @@ -117,8 +117,9 @@ RAYLIB_MODULE_RAYGUI_PATH ?= $(RAYLIB_SRC_PATH)/../../raygui/src # Use external GLFW library instead of rglfw module USE_EXTERNAL_GLFW ?= FALSE -# Enable support for Wayland and X11 by default on Linux when using GLFW -GLFW_LINUX_ENABLE_WAYLAND ?= TRUE +# Enable support for X11 by default on Linux when using GLFW +# NOTE: Wayland is disabled by default, only enable if you are sure +GLFW_LINUX_ENABLE_WAYLAND ?= FALSE GLFW_LINUX_ENABLE_X11 ?= TRUE # Enable support for X11 by default on Linux when using RGFW From 9400199b80450a586afdae898de6a168b2fb13a4 Mon Sep 17 00:00:00 2001 From: Keks137 Date: Mon, 11 May 2026 23:25:00 +0200 Subject: [PATCH 185/185] [rcore][RGFW] Add fullscreen behaviour on size 0 window creation (#5859) * port glfw's behaviour on size 0 window creation to rgfw * updates with change suggestions * don't do the FLAG_FULLSCREEN_MODE check twice for no reason --------- Co-authored-by: CrackedPixel <5776225+CrackedPixel@users.noreply.github.com> --- src/platforms/rcore_desktop_rgfw.c | 79 +++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 19 deletions(-) mode change 100755 => 100644 src/platforms/rcore_desktop_rgfw.c diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c old mode 100755 new mode 100644 index a71dbb15e..f99cab433 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -1677,10 +1677,62 @@ int InitPlatform(void) // Initialize RGFW internal global state, only required systems unsigned int flags = RGFW_windowCenter | RGFW_windowAllowDND; + if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNDECORATED)) FLAG_SET(flags, RGFW_windowNoBorder); + if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_RESIZABLE)) FLAG_SET(flags, RGFW_windowNoResize); + if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_TRANSPARENT)) FLAG_SET(flags, RGFW_windowTransparent); + if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIDDEN)) FLAG_SET(flags, RGFW_windowHide); + if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED)) FLAG_SET(flags, RGFW_windowMaximize); + if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) FLAG_SET(flags, RGFW_windowFocusOnShow | RGFW_windowFocus); + + if ((CORE.Window.screen.width == 0) || (CORE.Window.screen.height == 0)) + { + FLAG_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE); + } + // Check window creation flags + + // Init window in fullscreen mode if requested + // NOTE: Keeping original screen size for toggle if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE)) { FLAG_SET(flags, RGFW_windowFullscreen); + int result = RGFW_init(); + if (result != 0) + { + TRACELOG(LOG_WARNING, "RGFW: Failed to initialize RGFW"); + return -1; + } + + // NOTE: Fullscreen applications default to the primary monitor + RGFW_monitor *monitor = RGFW_getPrimaryMonitor(); + if (!monitor) + { + TRACELOG(LOG_WARNING, "RGFW: Failed to get primary monitor"); + return -1; + } + + // Default display resolution to that of the current mode + CORE.Window.display.width = monitor->mode.w; + CORE.Window.display.height = monitor->mode.h; + + // Check if user requested some screen size + if ((CORE.Window.screen.width == 0) || (CORE.Window.screen.height == 0)) + { + // Set some default screen size in case user decides to exit fullscreen mode + CORE.Window.previousScreen.width = 800; + CORE.Window.previousScreen.height = 450; + CORE.Window.previousPosition.x = (CORE.Window.display.width - CORE.Window.previousScreen.width)/2; + CORE.Window.previousPosition.y = (CORE.Window.display.height - CORE.Window.previousScreen.height)/2; + + // Set screen width/height to the display width/height + 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; + } + else + { + CORE.Window.previousScreen = CORE.Window.screen; + CORE.Window.screen = CORE.Window.display; + } } if (FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE)) @@ -1688,16 +1740,16 @@ int InitPlatform(void) FLAG_SET(flags, RGFW_windowedFullscreen); } - if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNDECORATED)) FLAG_SET(flags, RGFW_windowNoBorder); - if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_RESIZABLE)) FLAG_SET(flags, RGFW_windowNoResize); - if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_TRANSPARENT)) FLAG_SET(flags, RGFW_windowTransparent); - if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE)) FLAG_SET(flags, RGFW_windowFullscreen); - if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIDDEN)) FLAG_SET(flags, RGFW_windowHide); - if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED)) FLAG_SET(flags, RGFW_windowMaximize); + if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) + { + #if !defined(__APPLE__) + CORE.Window.screen.width = CORE.Window.screen.width * GetWindowScaleDPI().x; + CORE.Window.screen.height = CORE.Window.screen.height * GetWindowScaleDPI().y; + #endif + } // NOTE: Some OpenGL context attributes must be set before window creation // Check selection OpenGL version - RGFW_glHints* hints = RGFW_getGlobalHints_OpenGL(); if (rlGetVersion() == RL_OPENGL_21) { @@ -1720,20 +1772,9 @@ int InitPlatform(void) hints->minor = 1; hints->renderer = RGFW_glSoftware; } - if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT)) hints->samples = 4; - - if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) FLAG_SET(flags, RGFW_windowFocusOnShow | RGFW_windowFocus); - - if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) - { - #if !defined(__APPLE__) - CORE.Window.screen.width = CORE.Window.screen.width * GetWindowScaleDPI().x; - CORE.Window.screen.height = CORE.Window.screen.height * GetWindowScaleDPI().y; - #endif - } - RGFW_setGlobalHints_OpenGL(hints); + platform.window = RGFW_createWindow((CORE.Window.title != 0)? CORE.Window.title : " ", 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, flags | RGFW_windowOpenGL); #ifndef PLATFORM_WEB_RGFW