Merge branch 'raysan5:master' into master

This commit is contained in:
Jon Daniel 2025-07-19 23:50:38 +02:00 committed by GitHub
commit 6402b90a41
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 1602 additions and 673 deletions

View File

@ -61,7 +61,9 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL) #ifndef PLATFORM_WEB // NOTE: On non web platforms the PollInputEvents just works before the inputs checks
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
#endif
if (IsKeyPressed(KEY_SPACE)) pause = !pause; if (IsKeyPressed(KEY_SPACE)) pause = !pause;
@ -76,6 +78,10 @@ int main(void)
if (position >= GetScreenWidth()) position = 0; if (position >= GetScreenWidth()) position = 0;
timeCounter += deltaTime; // We count time (seconds) timeCounter += deltaTime; // We count time (seconds)
} }
#ifdef PLATFORM_WEB // NOTE: On web platform for some reason the PollInputEvents only works after the inputs check, so just call it after check all your inputs (on web)
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw

View File

@ -868,7 +868,7 @@ clean: clean_shell_$(PLATFORM_SHELL)
@echo "removed all generated files!" @echo "removed all generated files!"
clean_shell_sh: clean_shell_sh:
rm -fv *.o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so* raygui.c $(RAYLIB_RELEASE_PATH)/*-protocol.h $(RAYLIB_RELEASE_PATH)/*-protocol-code.h rm -fv *.o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).web.a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so* raygui.c $(RAYLIB_RELEASE_PATH)/*-protocol.h $(RAYLIB_RELEASE_PATH)/*-protocol-code.h
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
rm -fv $(NATIVE_APP_GLUE)/android_native_app_glue.o rm -fv $(NATIVE_APP_GLUE)/android_native_app_glue.o
endif endif
@ -879,6 +879,7 @@ clean_shell_cmd:
del *.o /s del *.o /s
cd $(RAYLIB_RELEASE_PATH) & \ cd $(RAYLIB_RELEASE_PATH) & \
del lib$(RAYLIB_LIB_NAME).a /s & \ del lib$(RAYLIB_LIB_NAME).a /s & \
del lib$(RAYLIB_LIB_NAME).web.a /s & \
del lib$(RAYLIB_LIB_NAME)dll.a /s & \ del lib$(RAYLIB_LIB_NAME)dll.a /s & \
del $(RAYLIB_LIB_NAME).dll /s & \ del $(RAYLIB_LIB_NAME).dll /s & \
del raygui.c /s & \ del raygui.c /s & \

File diff suppressed because it is too large Load Diff

42
src/external/rprand.h vendored
View File

@ -15,15 +15,15 @@
* - Support 64 bits generation * - Support 64 bits generation
* *
* ADDITIONAL NOTES: * ADDITIONAL NOTES:
* This library implements two pseudo-random number generation algorithms: * This library implements two pseudo-random number generation algorithms:
* *
* - Xoshiro128** : https://prng.di.unimi.it/xoshiro128starstar.c * - Xoshiro128** : https://prng.di.unimi.it/xoshiro128starstar.c
* - SplitMix64 : https://prng.di.unimi.it/splitmix64.c * - SplitMix64 : https://prng.di.unimi.it/splitmix64.c
* *
* SplitMix64 is used to initialize the Xoshiro128** state, from a provided seed * SplitMix64 is used to initialize the Xoshiro128** state, from a provided seed
* *
* It's suggested to use SplitMix64 to initialize the state of the generators starting from * It's suggested to use SplitMix64 to initialize the state of the generators starting from
* a 64-bit seed, as research has shown that initialization must be performed with a generator * a 64-bit seed, as research has shown that initialization must be performed with a generator
* radically different in nature from the one initialized to avoid correlation on similar seeds. * radically different in nature from the one initialized to avoid correlation on similar seeds.
* *
* CONFIGURATION: * CONFIGURATION:
@ -31,7 +31,7 @@
* Generates the implementation of the library into the included file. * 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 * 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. * or source files without problems. But only ONE file should hold the implementation.
* *
* DEPENDENCIES: none * DEPENDENCIES: none
* *
* VERSIONS HISTORY: * VERSIONS HISTORY:
@ -153,7 +153,7 @@ static uint32_t rprand_state[4] = { // Xoshiro128** state, initializ
0x218b21e5, 0x218b21e5,
0xaa91febd, 0xaa91febd,
0x976414d4 0x976414d4
}; };
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module internal functions declaration // Module internal functions declaration
@ -190,8 +190,8 @@ int rprand_get_value(int min, int max)
int *rprand_load_sequence(unsigned int count, int min, int max) int *rprand_load_sequence(unsigned int count, int min, int max)
{ {
int *sequence = NULL; int *sequence = NULL;
if (count > (unsigned int)(abs(max - min) + 1)) if (count > (unsigned int)(abs(max - min) + 1))
{ {
RPRAND_LOG("WARNING: Sequence count required is greater than range provided\n"); RPRAND_LOG("WARNING: Sequence count required is greater than range provided\n");
//count = (max - min); //count = (max - min);
@ -244,26 +244,26 @@ static inline uint32_t rprand_rotate_left(const uint32_t x, int k)
} }
// Xoshiro128** generator info: // Xoshiro128** generator info:
// //
// Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) // Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
// //
// To the extent possible under law, the author has dedicated all copyright // To the extent possible under law, the author has dedicated all copyright
// and related and neighboring rights to this software to the public domain // and related and neighboring rights to this software to the public domain
// worldwide. This software is distributed without any warranty. // worldwide. This software is distributed without any warranty.
// //
// See <http://creativecommons.org/publicdomain/zero/1.0/>. // See <http://creativecommons.org/publicdomain/zero/1.0/>.
// //
// This is xoshiro128** 1.1, one of our 32-bit all-purpose, rock-solid // This is xoshiro128** 1.1, one of our 32-bit all-purpose, rock-solid
// generators. It has excellent speed, a state size (128 bits) that is // generators. It has excellent speed, a state size (128 bits) that is
// large enough for mild parallelism, and it passes all tests we are aware // large enough for mild parallelism, and it passes all tests we are aware
// of. // of.
// //
// Note that version 1.0 had mistakenly s[0] instead of s[1] as state // Note that version 1.0 had mistakenly s[0] instead of s[1] as state
// word passed to the scrambler. // word passed to the scrambler.
// //
// For generating just single-precision (i.e., 32-bit) floating-point // For generating just single-precision (i.e., 32-bit) floating-point
// numbers, xoshiro128+ is even faster. // numbers, xoshiro128+ is even faster.
// //
// The state must be seeded so that it is not everywhere zero. // The state must be seeded so that it is not everywhere zero.
// //
uint32_t rprand_xoshiro(void) uint32_t rprand_xoshiro(void)
@ -275,29 +275,29 @@ uint32_t rprand_xoshiro(void)
rprand_state[3] ^= rprand_state[1]; rprand_state[3] ^= rprand_state[1];
rprand_state[1] ^= rprand_state[2]; rprand_state[1] ^= rprand_state[2];
rprand_state[0] ^= rprand_state[3]; rprand_state[0] ^= rprand_state[3];
rprand_state[2] ^= t; rprand_state[2] ^= t;
rprand_state[3] = rprand_rotate_left(rprand_state[3], 11); rprand_state[3] = rprand_rotate_left(rprand_state[3], 11);
return result; return result;
} }
// SplitMix64 generator info: // SplitMix64 generator info:
// //
// Written in 2015 by Sebastiano Vigna (vigna@acm.org) // Written in 2015 by Sebastiano Vigna (vigna@acm.org)
// //
// To the extent possible under law, the author has dedicated all copyright // To the extent possible under law, the author has dedicated all copyright
// and related and neighboring rights to this software to the public domain // and related and neighboring rights to this software to the public domain
// worldwide. This software is distributed without any warranty. // worldwide. This software is distributed without any warranty.
// //
// See <http://creativecommons.org/publicdomain/zero/1.0/>. // See <http://creativecommons.org/publicdomain/zero/1.0/>.
// //
// //
// This is a fixed-increment version of Java 8's SplittableRandom generator // This is a fixed-increment version of Java 8's SplittableRandom generator
// See http://dx.doi.org/10.1145/2714064.2660195 and // See http://dx.doi.org/10.1145/2714064.2660195 and
// http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html // http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html
// //
// It is a very fast generator passing BigCrush, and it can be useful if // It is a very fast generator passing BigCrush, and it can be useful if
// for some reason you absolutely want 64 bits of state. // for some reason you absolutely want 64 bits of state.
uint64_t rprand_splitmix64() uint64_t rprand_splitmix64()

View File

@ -1871,6 +1871,7 @@ void SeekMusicStream(Music music, float position)
void UpdateMusicStream(Music music) void UpdateMusicStream(Music music)
{ {
if (music.stream.buffer == NULL) return; if (music.stream.buffer == NULL) return;
if (!music.stream.buffer->playing) return;
ma_mutex_lock(&AUDIO.System.lock); ma_mutex_lock(&AUDIO.System.lock);
@ -1890,14 +1891,28 @@ void UpdateMusicStream(Music music)
// Check both sub-buffers to check if they require refilling // Check both sub-buffers to check if they require refilling
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (!music.stream.buffer->isSubBufferProcessed[i]) continue; // No refilling required, move to next sub-buffer
unsigned int framesLeft = music.frameCount - music.stream.buffer->framesProcessed; // Frames left to be processed unsigned int framesLeft = music.frameCount - music.stream.buffer->framesProcessed; // Frames left to be processed
unsigned int framesToStream = 0; // Total frames to be streamed unsigned int framesToStream = 0; // Total frames to be streamed
if ((framesLeft >= subBufferSizeInFrames) || music.looping) framesToStream = subBufferSizeInFrames; if ((framesLeft >= subBufferSizeInFrames) || music.looping) framesToStream = subBufferSizeInFrames;
else framesToStream = framesLeft; else framesToStream = framesLeft;
if (framesToStream == 0)
{
// Check if both buffers have been processed
if (music.stream.buffer->isSubBufferProcessed[0] && music.stream.buffer->isSubBufferProcessed[1])
{
ma_mutex_unlock(&AUDIO.System.lock);
StopMusicStream(music);
return;
}
ma_mutex_unlock(&AUDIO.System.lock);
return;
}
if (!music.stream.buffer->isSubBufferProcessed[i]) continue; // No refilling required, move to next sub-buffer
int frameCountStillNeeded = framesToStream; int frameCountStillNeeded = framesToStream;
int frameCountReadTotal = 0; int frameCountReadTotal = 0;
@ -2010,19 +2025,6 @@ void UpdateMusicStream(Music music)
} }
UpdateAudioStreamInLockedState(music.stream, AUDIO.System.pcmBuffer, framesToStream); UpdateAudioStreamInLockedState(music.stream, AUDIO.System.pcmBuffer, framesToStream);
music.stream.buffer->framesProcessed = music.stream.buffer->framesProcessed%music.frameCount;
if (framesLeft <= subBufferSizeInFrames)
{
if (!music.looping)
{
ma_mutex_unlock(&AUDIO.System.lock);
// Streaming is ending, we filled latest frames from input
StopMusicStream(music);
return;
}
}
} }
ma_mutex_unlock(&AUDIO.System.lock); ma_mutex_unlock(&AUDIO.System.lock);
@ -2085,8 +2087,12 @@ float GetMusicTimePlayed(Music music)
int subBufferSize = (int)music.stream.buffer->sizeInFrames/2; int subBufferSize = (int)music.stream.buffer->sizeInFrames/2;
int framesInFirstBuffer = music.stream.buffer->isSubBufferProcessed[0]? 0 : subBufferSize; int framesInFirstBuffer = music.stream.buffer->isSubBufferProcessed[0]? 0 : subBufferSize;
int framesInSecondBuffer = music.stream.buffer->isSubBufferProcessed[1]? 0 : subBufferSize; int framesInSecondBuffer = music.stream.buffer->isSubBufferProcessed[1]? 0 : subBufferSize;
int framesInBuffers = framesInFirstBuffer + framesInSecondBuffer;
if (framesInBuffers > music.frameCount) {
if (!music.looping) framesInBuffers = music.frameCount;
}
int framesSentToMix = music.stream.buffer->frameCursorPos%subBufferSize; int framesSentToMix = music.stream.buffer->frameCursorPos%subBufferSize;
int framesPlayed = (framesProcessed - framesInFirstBuffer - framesInSecondBuffer + framesSentToMix)%(int)music.frameCount; int framesPlayed = (framesProcessed - framesInBuffers + framesSentToMix)%(int)music.frameCount;
if (framesPlayed < 0) framesPlayed += music.frameCount; if (framesPlayed < 0) framesPlayed += music.frameCount;
secondsPlayed = (float)framesPlayed/music.stream.sampleRate; secondsPlayed = (float)framesPlayed/music.stream.sampleRate;
ma_mutex_unlock(&AUDIO.System.lock); ma_mutex_unlock(&AUDIO.System.lock);
@ -2683,8 +2689,7 @@ static void UpdateAudioStreamInLockedState(AudioStream stream, const void *data,
ma_uint32 subBufferSizeInFrames = stream.buffer->sizeInFrames/2; ma_uint32 subBufferSizeInFrames = stream.buffer->sizeInFrames/2;
unsigned char *subBuffer = stream.buffer->data + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate); unsigned char *subBuffer = stream.buffer->data + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate);
// Total frames processed in buffer is always the complete size, filled with 0 if required stream.buffer->framesProcessed += frameCount;
stream.buffer->framesProcessed += subBufferSizeInFrames;
// Does this API expect a whole buffer to be updated in one go? // Does this API expect a whole buffer to be updated in one go?
// Assuming so, but if not will need to change this logic // Assuming so, but if not will need to change this logic

View File

@ -1885,7 +1885,7 @@ void rlActiveDrawBuffers(int count)
if (count > 0) if (count > 0)
{ {
if (count > 8) TRACELOG(LOG_WARNING, "GL: Max color buffers limited to 8"); if (count > 8) TRACELOG(RL_LOG_WARNING, "GL: Max color buffers limited to 8");
else else
{ {
unsigned int buffers[8] = { unsigned int buffers[8] = {
@ -1902,7 +1902,7 @@ void rlActiveDrawBuffers(int count)
glDrawBuffers(count, buffers); glDrawBuffers(count, buffers);
} }
} }
else TRACELOG(LOG_WARNING, "GL: One color buffer active by default"); else TRACELOG(RL_LOG_WARNING, "GL: One color buffer active by default");
#endif #endif
} }
@ -2219,10 +2219,10 @@ static void GLAPIENTRY rlDebugMessageCallback(GLenum source, GLenum type, GLuint
default: break; default: break;
} }
TRACELOG(LOG_WARNING, "GL: OpenGL debug message: %s", message); TRACELOG(RL_LOG_WARNING, "GL: OpenGL debug message: %s", message);
TRACELOG(LOG_WARNING, " > Type: %s", msgType); TRACELOG(RL_LOG_WARNING, " > Type: %s", msgType);
TRACELOG(LOG_WARNING, " > Source = %s", msgSource); TRACELOG(RL_LOG_WARNING, " > Source = %s", msgSource);
TRACELOG(LOG_WARNING, " > Severity = %s", msgSeverity); TRACELOG(RL_LOG_WARNING, " > Severity = %s", msgSeverity);
} }
#endif #endif
@ -4178,7 +4178,7 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
RL_FREE(log); RL_FREE(log);
} }
// Unload object allocated by glCreateShader(), // Unload object allocated by glCreateShader(),
// despite failing in the compilation process // despite failing in the compilation process
glDeleteShader(shader); glDeleteShader(shader);
shader = 0; shader = 0;

View File

@ -391,7 +391,7 @@ Font LoadFont(const char *fileName)
else else
{ {
SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default, we set point filter (the best performance) SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default, we set point filter (the best performance)
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS); TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", font.baseSize, font.glyphCount);
} }
} }

View File

@ -2217,9 +2217,9 @@ void ImageBlurGaussian(Image *image, int blurSize)
else if (pixelsCopy1[i].w <= 255.0f) else if (pixelsCopy1[i].w <= 255.0f)
{ {
float alpha = (float)pixelsCopy1[i].w/255.0f; float alpha = (float)pixelsCopy1[i].w/255.0f;
pixels[i].r = (unsigned char)((float)pixelsCopy1[i].x/alpha); pixels[i].r = (unsigned char)fminf((float)pixelsCopy1[i].x/alpha, 255.0);
pixels[i].g = (unsigned char)((float)pixelsCopy1[i].y/alpha); pixels[i].g = (unsigned char)fminf((float)pixelsCopy1[i].y/alpha, 255.0);
pixels[i].b = (unsigned char)((float)pixelsCopy1[i].z/alpha); pixels[i].b = (unsigned char)fminf((float)pixelsCopy1[i].z/alpha, 255.0);
pixels[i].a = (unsigned char) pixelsCopy1[i].w; pixels[i].a = (unsigned char) pixelsCopy1[i].w;
} }
} }
@ -2927,7 +2927,16 @@ void ImageColorReplace(Image *image, Color color, Color replace)
image->data = pixels; image->data = pixels;
image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
ImageFormat(image, format); // Only convert back to original format if it supported alpha
if ((format == PIXELFORMAT_UNCOMPRESSED_R8G8B8) ||
(format == PIXELFORMAT_UNCOMPRESSED_R5G6B5) ||
(format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) ||
(format == PIXELFORMAT_UNCOMPRESSED_R32G32B32) ||
(format == PIXELFORMAT_UNCOMPRESSED_R16G16B16) ||
(format == PIXELFORMAT_COMPRESSED_DXT1_RGB) ||
(format == PIXELFORMAT_COMPRESSED_ETC1_RGB) ||
(format == PIXELFORMAT_COMPRESSED_ETC2_RGB) ||
(format == PIXELFORMAT_COMPRESSED_PVRT_RGB)) ImageFormat(image, format);
} }
#endif // SUPPORT_IMAGE_MANIPULATION #endif // SUPPORT_IMAGE_MANIPULATION
@ -3565,34 +3574,43 @@ void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color co
int dx = x2 - x1; int dx = x2 - x1;
int dy = y2 - y1; int dy = y2 - y1;
// Draw the main line between (x1, y1) and (x2, y2)
ImageDrawLine(dst, x1, y1, x2, y2, color);
// Determine if the line is more horizontal or vertical // Determine if the line is more horizontal or vertical
if ((dx != 0) && (abs(dy/dx) < 1)) if ((dx != 0) && (abs(dy/dx) < 1))
{ {
// Line is more horizontal // Line is more horizontal
// Calculate half the width of the line
int wy = (thick - 1)*(int)sqrtf((float)(dx*dx + dy*dy))/(2*abs(dx));
// Draw additional lines above and below the main line // How many additional lines to draw
for (int i = 1; i <= wy; i++) int wy = thick - 1;
// Draw the main line and lower half
for (int i = 0; i <= ((wy+1)/2); i++)
{ {
ImageDrawLine(dst, x1, y1 - i, x2, y2 - i, color); // Draw above the main line ImageDrawLine(dst, x1, y1 + i, x2, y2 + i, color);
ImageDrawLine(dst, x1, y1 + i, x2, y2 + i, color); // Draw below the main line }
// Draw the upper half
for (int i = 1; i <= (wy/2); i++)
{
ImageDrawLine(dst, x1, y1 - i, x2, y2 - i, color);
} }
} }
else if (dy != 0) else if (dy != 0)
{ {
// Line is more vertical or perfectly horizontal // Line is more vertical or perfectly horizontal
// Calculate half the width of the line
int wx = (thick - 1)*(int)sqrtf((float)(dx*dx + dy*dy))/(2*abs(dy));
// Draw additional lines to the left and right of the main line // How many additional lines to draw
for (int i = 1; i <= wx; i++) int wx = thick - 1;
//Draw the main line and right half
for (int i = 0; i <= ((wx+1)/2); i++)
{ {
ImageDrawLine(dst, x1 - i, y1, x2 - i, y2, color); // Draw left of the main line ImageDrawLine(dst, x1 + i, y1, x2 + i, y2, color);
ImageDrawLine(dst, x1 + i, y1, x2 + i, y2, color); // Draw right of the main line }
// Draw the left half
for (int i = 1; i <= (wx/2); i++)
{
ImageDrawLine(dst, x1 - i, y1, x2 - i, y2, color);
} }
} }
} }
@ -5400,7 +5418,7 @@ static float HalfToFloat(unsigned short x)
} uni; } uni;
const unsigned int e = (x & 0x7c00) >> 10; // Exponent const unsigned int e = (x & 0x7c00) >> 10; // Exponent
const unsigned int m = (x & 0x03cc) << 13; // Mantissa const unsigned int m = (x & 0x03ff) << 13; // Mantissa
uni.fm = (float)m; uni.fm = (float)m;
const unsigned int v = uni.ui >> 23; // Evil log2 bit hack to count leading zeros in denormalized format const unsigned int v = uni.ui >> 23; // Evil log2 bit hack to count leading zeros in denormalized format
uni.ui = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007fe000)); // sign : normalized : denormalized uni.ui = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007fe000)); // sign : normalized : denormalized