diff --git a/BINDINGS.md b/BINDINGS.md
index 7d350a9b0..710a7a1ed 100644
--- a/BINDINGS.md
+++ b/BINDINGS.md
@@ -49,7 +49,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [Raylib.jl](https://github.com/chengchingwen/Raylib.jl) | 4.2 | [Julia](https://julialang.org) | Zlib |
| [kaylib](https://github.com/electronstudio/kaylib) | 3.7 | [Kotlin/native](https://kotlinlang.org) | **???** |
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
-| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.0 | [Lua](http://www.lua.org) | ISC |
+| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.5 | [Lua](http://www.lua.org) | ISC |
| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 5.5 | [Lua](http://www.lua.org) | ISC |
| [ReiLua](https://github.com/nullstare/ReiLua) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
diff --git a/src/external/rlsw.h b/src/external/rlsw.h
index 7e153adbc..ffbdaae81 100644
--- a/src/external/rlsw.h
+++ b/src/external/rlsw.h
@@ -5385,6 +5385,16 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
int xEnd = (int)end->position[0];
if (xStart == xEnd) return;
+ // Intercept the span bounds to ensure to not write before the framebuffer
+ int xLoopStart = (xStart >= 0)? xStart : 0;
+ int xLoopEnd = (xEnd <= RLSW.colorBuffer->width)? xEnd : RLSW.colorBuffer->width;
+ if (xLoopStart >= xLoopEnd) return; // Nothing to draw
+
+ // Get the current row and skip if outside the framebuffer
+ // Maybe this check is better suited elsewhere?
+ int y = (int)start->position[1];
+ if (y < 0 || y >= RLSW.colorBuffer->height) return;
+
// Compute the inverse horizontal distance along the X axis
float dxRcp = sw_rcp(end->position[0] - start->position[0]);
@@ -5405,27 +5415,29 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
#endif
// Compute the subpixel distance to traverse before the first pixel
+ // Also step further into them to move away from the colorbuffer edge
float xSubstep = 1.0f - sw_fract(start->position[0]);
+ float dxStart = (float)(xLoopStart - xStart);
+ float xOffset = xSubstep + dxStart;
// Initializing the interpolation starting values
- float w = start->position[3] + dWdx*xSubstep;
+ float w = start->position[3] + dWdx*xOffset;
float color[4] = {
- start->color[0] + dCdx[0]*xSubstep,
- start->color[1] + dCdx[1]*xSubstep,
- start->color[2] + dCdx[2]*xSubstep,
- start->color[3] + dCdx[3]*xSubstep
+ start->color[0] + dCdx[0]*xOffset,
+ start->color[1] + dCdx[1]*xOffset,
+ start->color[2] + dCdx[2]*xOffset,
+ start->color[3] + dCdx[3]*xOffset
};
#ifdef SW_ENABLE_DEPTH_TEST
- float z = start->position[2] + dZdx*xSubstep;
+ float z = start->position[2] + dZdx*xOffset;
#endif
#ifdef SW_ENABLE_TEXTURE
- float u = start->texcoord[0] + dUdx*xSubstep;
- float v = start->texcoord[1] + dVdx*xSubstep;
+ float u = start->texcoord[0] + dUdx*xOffset;
+ float v = start->texcoord[1] + dVdx*xOffset;
#endif
// Pre-calculate the starting pointers for the framebuffer row
- int y = (int)start->position[1];
- int baseOffset = y*RLSW.colorBuffer->width + xStart;
+ int baseOffset = y*RLSW.colorBuffer->width + xLoopStart;
uint8_t *cPtr = (uint8_t *)(RLSW.colorBuffer->pixels) + baseOffset*SW_FRAMEBUFFER_COLOR_SIZE;
#ifdef SW_ENABLE_DEPTH_TEST
uint8_t *dPtr = (uint8_t *)(RLSW.depthBuffer->pixels) + baseOffset*SW_FRAMEBUFFER_DEPTH_SIZE;
@@ -5433,12 +5445,12 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
#define SW_AFFINE_BLOCK 16
- int x = xStart;
- while (x < xEnd)
+ int x = xLoopStart;
+ while (x < xLoopEnd)
{
// Clamp last block to remaining pixels
int blockEnd = x + SW_AFFINE_BLOCK;
- if (blockEnd > xEnd) blockEnd = xEnd;
+ if (blockEnd > xLoopEnd) blockEnd = xLoopEnd;
float blockLenF = (float)(blockEnd - x);
float blockLenRcp = sw_rcp(blockLenF);
@@ -5673,6 +5685,14 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
int xMax = (int)br->position[0];
int yMax = (int)br->position[1];
+ // Exit early if no pixels to draw. Use these later for loop boundaries
+ int yLoopMin = (yMin >= 0)? yMin : 0;
+ int xLoopMin = (xMin >= 0)? xMin : 0;
+ int yLoopMax = (yMax <= RLSW.colorBuffer->height)? yMax : RLSW.colorBuffer->height;
+ int xLoopMax = (xMax <= RLSW.colorBuffer->width)? xMax : RLSW.colorBuffer->width;
+
+ if (yLoopMin >= yLoopMax || xLoopMin >= xLoopMax) return;
+
float w = (float)(xMax - xMin);
float h = (float)(yMax - yMin);
if ((w <= 0) || (h <= 0)) return;
@@ -5726,21 +5746,44 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
uint8_t *dPixels = RLSW.depthBuffer->pixels;
#endif
- for (int y = yMin; y < yMax; y++)
+ // Calculate the distance the in-bounds boundary is from the quad's edges, only on the left and top
+ float dxMin = (float)(xLoopMin - xMin);
+ float dyMin = (float)(yLoopMin - yMin);
+
+ // Correct our start by how far it's clipped outside the framebuffer
+ cRow[0] += dCdx[0]*dxMin + dCdy[0]*dyMin;
+ cRow[1] += dCdx[1]*dxMin + dCdy[1]*dyMin;
+ cRow[2] += dCdx[2]*dxMin + dCdy[2]*dyMin;
+ cRow[3] += dCdx[3]*dxMin + dCdy[3]*dyMin;
+ #ifdef SW_ENABLE_DEPTH_TEST
+ zRow += dZdy*dyMin + dZdx*dxMin;
+ #endif
+ #ifdef SW_ENABLE_TEXTURE
+ uRow += dUdy*dyMin + dUdx*dxMin;
+ vRow += dVdy*dyMin + dVdx*dxMin;
+ #endif
+
+ for (int y = yLoopMin; y < yLoopMax; y++)
{
- int baseOffset = y*stride + xMin;
+ int baseOffset = y*stride + xLoopMin;
uint8_t *cPtr = cPixels + baseOffset*SW_FRAMEBUFFER_COLOR_SIZE;
#ifdef SW_ENABLE_DEPTH_TEST
uint8_t *dPtr = dPixels + baseOffset*SW_FRAMEBUFFER_DEPTH_SIZE;
+ // Copy the cursors without destroying the offset maths
float z = zRow;
#endif
#ifdef SW_ENABLE_TEXTURE
float u = uRow;
float v = vRow;
#endif
- float color[4] = { cRow[0], cRow[1], cRow[2], cRow[3] };
+ float color[4] = {
+ cRow[0],
+ cRow[1],
+ cRow[2],
+ cRow[3]
+ };
- for (int x = xMin; x < xMax; x++)
+ for (int x = xLoopMin; x < xLoopMax; x++)
{
float srcColor[4] = { color[0], color[1], color[2], color[3] };
@@ -5779,6 +5822,7 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
#ifdef SW_ENABLE_DEPTH_TEST
discard:
#endif
+ // Move one pixel over without touching the original "start offset"
color[0] += dCdx[0];
color[1] += dCdx[1];
color[2] += dCdx[2];
@@ -5801,6 +5845,9 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
cPtr += SW_FRAMEBUFFER_COLOR_SIZE;
}
+ // The for loop is clamped to the right side of the screen
+ // However, these cursor start vars are still on the left
+ // That's fine, advancing to the next row
cRow[0] += dCdy[0];
cRow[1] += dCdy[1];
cRow[2] += dCdy[2];
diff --git a/src/raylib.h b/src/raylib.h
index e8164073f..286f33c28 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -1164,7 +1164,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
diff --git a/src/rshapes.c b/src/rshapes.c
index 69c1dacea..5ef988e38 100644
--- a/src/rshapes.c
+++ b/src/rshapes.c
@@ -361,7 +361,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
{
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
- segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
+ segments = (int)ceilf((endAngle - startAngle)*(2*PI/th)/360.0f);
if (segments <= 0) segments = minSegments;
}
@@ -453,7 +453,7 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float
{
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
- segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
+ segments = (int)ceilf((endAngle - startAngle)*(2*PI/th)/360.0f);
if (segments <= 0) segments = minSegments;
}
@@ -579,7 +579,7 @@ void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startA
{
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
- segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
+ segments = (int)ceilf((endAngle - startAngle)*(2*PI/th)/360.0f);
if (segments <= 0) segments = minSegments;
}
@@ -670,7 +670,7 @@ void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float s
{
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
- segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
+ segments = (int)ceilf((endAngle - startAngle)*(2*PI/th)/360.0f);
if (segments <= 0) segments = minSegments;
}
@@ -960,7 +960,7 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
{
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
- segments = (int)(ceilf(2*PI/th)/2.0f);
+ segments = (int)ceilf((2*PI/th)/4.0f);
if (segments <= 0) segments = 4;
}
@@ -1195,7 +1195,7 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f
{
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
- segments = (int)(ceilf(2*PI/th)/2.0f);
+ segments = (int)ceilf((2*PI/th)/4.0f);
if (segments <= 0) segments = 4;
}
diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json
index aa018051a..b42fd2d61 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 e88db0b7e..859ef38ba 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 0447edd23..0051c6a14 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 e9db25846..fdc1481ec 100644
--- a/tools/rlparser/output/raylib_api.xml
+++ b/tools/rlparser/output/raylib_api.xml
@@ -1125,7 +1125,7 @@
-
+