Merge upstream

This commit is contained in:
Luiz Pestana 2022-05-27 20:56:18 -03:00
commit 03534f2ec6
39 changed files with 30844 additions and 9492 deletions

View File

@ -21,17 +21,19 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| nelua-raylib | 4.0 | [nelua](https://nelua.io/) | MIT | https://github.com/AKDev21/nelua-raylib | | nelua-raylib | 4.0 | [nelua](https://nelua.io/) | MIT | https://github.com/AKDev21/nelua-raylib |
| NimraylibNow! | 4.0 | [Nim](https://nim-lang.org/) | MIT | https://github.com/greenfork/nimraylib_now | | NimraylibNow! | 4.0 | [Nim](https://nim-lang.org/) | MIT | https://github.com/greenfork/nimraylib_now |
| raylib-Forever | auto | [Nim](https://nim-lang.org/) | ? | https://github.com/Guevara-chan/Raylib-Forever | | raylib-Forever | auto | [Nim](https://nim-lang.org/) | ? | https://github.com/Guevara-chan/Raylib-Forever |
| naylib | auto | [Nim](https://nim-lang.org/) | MIT | https://github.com/planetis-m/naylib |
| Ray4Laz | **4.0** | [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))| Zlib | https://github.com/GuvaCode/Ray4Laz | | Ray4Laz | **4.0** | [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))| Zlib | https://github.com/GuvaCode/Ray4Laz |
| pyraylib | 3.7 | [Python](https://www.python.org/) | Zlib | https://github.com/Ho011/pyraylib | | pyraylib | 3.7 | [Python](https://www.python.org/) | Zlib | https://github.com/Ho011/pyraylib |
| raylib-python-cffi | **4.0** | [Python](https://www.python.org/) | EPL-2.0 | https://github.com/electronstudio/raylib-python-cffi | | raylib-python-cffi | **4.0** | [Python](https://www.python.org/) | EPL-2.0 | https://github.com/electronstudio/raylib-python-cffi |
| jaylib | **4.0** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3 | https://github.com/electronstudio/jaylib/ | | jaylib | **4.0** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3 | https://github.com/electronstudio/jaylib/ |
| raylib-j | **4.0** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib | https://github.com/CreedVI/Raylib-J | | raylib-j | **4.0** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib | https://github.com/CreedVI/Raylib-J |
| node-raylib | 3.5 | [Node.js](https://nodejs.org/en/) | Zlib | https://github.com/RobLoach/node-raylib | | raylib.jl | **4.0** | [Julia](https://julialang.org/) | Zlib | https://github.com/irishgreencitrus/raylib.jl |
| node-raylib | **4.0** | [Node.js](https://nodejs.org/en/) | Zlib | https://github.com/RobLoach/node-raylib |
| raylib-php | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | https://github.com/joseph-montanez/raylib-php | | raylib-php | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | https://github.com/joseph-montanez/raylib-php |
| raylib-phpcpp | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | https://github.com/oraoto/raylib-phpcpp | | raylib-phpcpp | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | https://github.com/oraoto/raylib-phpcpp |
| raylib-factor | 3.5 | [Factor](https://factorcode.org/) | MIT | https://github.com/ArnautDaniel/raylib-factor | | raylib-factor | **4.0** | [Factor](https://factorcode.org/) | BSD | https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor |
| gforth-raylib | 3.5 | [Gforth](https://gforth.org/) | MIT | https://github.com/ArnautDaniel/gforth-raylib | | gforth-raylib | 3.5 | [Gforth](https://gforth.org/) | MIT | https://github.com/ArnautDaniel/gforth-raylib |
| hxRaylib | 4.0 | [Haxe](https://haxe.org/) | Zlib | https://github.com/ForeignSasquatch/hxRaylib | | raylib-hx | 4.0 | [Haxe](https://haxe.org/) | Zlib | https://github.com/foreignsasquatch/raylib-hx |
| raylib-wren | **4.0** | [Wren](http://wren.io/) | ISC | https://github.com/TSnake41/raylib-wren | | raylib-wren | **4.0** | [Wren](http://wren.io/) | ISC | https://github.com/TSnake41/raylib-wren |
| raylib_odin_bindings | 4.0-dev | [Odin](https://odin-lang.org/) | MIT | https://github.com/Deathbat2190/raylib_odin_bindings | | raylib_odin_bindings | 4.0-dev | [Odin](https://odin-lang.org/) | MIT | https://github.com/Deathbat2190/raylib_odin_bindings |
| raylib-odin | **4.0** | [Odin](https://odin-lang.org/) | BSD-3Clause | https://github.com/odin-lang/Odin/tree/master/vendor/raylib | | raylib-odin | **4.0** | [Odin](https://odin-lang.org/) | BSD-3Clause | https://github.com/odin-lang/Odin/tree/master/vendor/raylib |
@ -48,6 +50,9 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| dart-raylib | **4.0** | [Dart](https://dart.dev/) | MIT | https://gitlab.com/wolfenrain/dart-raylib | | dart-raylib | **4.0** | [Dart](https://dart.dev/) | MIT | https://gitlab.com/wolfenrain/dart-raylib |
| raylib-scopes | auto | [Scopes](http://scopes.rocks) | MIT | https://github.com/salotz/raylib-scopes | | raylib-scopes | auto | [Scopes](http://scopes.rocks) | MIT | https://github.com/salotz/raylib-scopes |
| raylib-smallBasic | 4.1-dev | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 | https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib | | raylib-smallBasic | 4.1-dev | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 | https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib |
| raylib-zig | **4.0** | [Zig](https://ziglang.org/) | MIT | https://github.com/Not-Nik/raylib-zig |
| raylib.zig | **4.1-dev** | [Zig](https://ziglang.org/) | MIT | https://github.com/ryupold/raylib.zig |
| racket-raylib | **4.0** | [Racket](https://racket-lang.org/) | MIT/Apache-2.0 | https://github.com/eutro/racket-raylib |
### Utility Wrapers ### Utility Wrapers
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 pardigm. 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 pardigm.
@ -105,8 +110,7 @@ These are older raylib bindings that are more than 2 versions old or have not be
| Euraylib | 3.0 | [Euphoria](https://openeuphoria.org/) | https://github.com/gAndy50/Euraylib | | Euraylib | 3.0 | [Euphoria](https://openeuphoria.org/) | https://github.com/gAndy50/Euraylib |
| raylib-odin | 3.0 | [Odin](https://odin-lang.org/) | https://github.com/kevinw/raylib-odin | | raylib-odin | 3.0 | [Odin](https://odin-lang.org/) | https://github.com/kevinw/raylib-odin |
| vraylib | 3.5 | [V](https://vlang.io/) | https://github.com/waotzi/vraylib | | vraylib | 3.5 | [V](https://vlang.io/) | https://github.com/waotzi/vraylib |
| raylib-zig | 3.0 | [Zig](https://ziglang.org/) | https://github.com/Not-Nik/raylib-zig | | raylib-jai | 3.1-dev | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | https://github.com/kujukuju/raylib-jai |
| raylib-jai | 3.1-dev | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | https://github.com/kevinw/raylib-jai |
| ray.zig | 2.5 | [Zig](https://ziglang.org/) | https://github.com/BitPuffin/zig-raylib-experiments | | ray.zig | 2.5 | [Zig](https://ziglang.org/) | https://github.com/BitPuffin/zig-raylib-experiments |
| raylib-Ada | 3.0 | [Ada](https://www.adacore.com/about-ada) | https://github.com/mimo/raylib-Ada | | raylib-Ada | 3.0 | [Ada](https://www.adacore.com/about-ada) | https://github.com/mimo/raylib-Ada |
| jaylib | 3.0 | [Janet](https://janet-lang.org/) | https://github.com/janet-lang/jaylib | | jaylib | 3.0 | [Janet](https://janet-lang.org/) | https://github.com/janet-lang/jaylib |

View File

@ -4,7 +4,7 @@ This is the repository of the Nintendo Switch port of the raylib using LibNX run
Please, follow the wiki page in order to install and use it: Please, follow the wiki page in order to install and use it:
- [Working on Switch](https://github.com/luizpestana/raylib-nx/wiki/Working-on-Switch) - [Working on Switch](https://github.com/lucaskyer/raylib-nx/wiki/Working-on-Switch)
--- ---
@ -22,16 +22,19 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html)
<br> <br>
[![GitHub contributors](https://img.shields.io/github/contributors/raysan5/raylib)](https://github.com/raysan5/raylib/graphs/contributors) [![GitHub Contributors](https://img.shields.io/github/contributors/raysan5/raylib)](https://github.com/raysan5/raylib/graphs/contributors)
[![GitHub All Releases](https://img.shields.io/github/downloads/raysan5/raylib/total)](https://github.com/raysan5/raylib/releases) [![GitHub Releases Downloads](https://img.shields.io/github/downloads/raysan5/raylib/total)](https://github.com/raysan5/raylib/releases)
[![Packaging status](https://repology.org/badge/tiny-repos/raylib.svg)](https://repology.org/project/raylib/versions) [![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/4.0.0)](https://github.com/raysan5/raylib/commits/master) [![GitHub commits since tagged version](https://img.shields.io/github/commits-since/raysan5/raylib/4.0.0)](https://github.com/raysan5/raylib/commits/master)
[![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) [![License](https://img.shields.io/badge/license-zlib%2Flibpng-blue.svg)](LICENSE)
[![Chat on Discord](https://img.shields.io/discord/426912293134270465.svg?logo=discord)](https://discord.gg/raylib) [![Discord Members](https://img.shields.io/discord/426912293134270465.svg?label=Discord&logo=discord)](https://discord.gg/raylib)
[![GitHub stars](https://img.shields.io/github/stars/raysan5/raylib?style=social)](https://github.com/raysan5/raylib/stargazers) [![Subreddit Subscribers](https://img.shields.io/reddit/subreddit-subscribers/raylib?label=reddit%20r%2Fraylib&logo=reddit)](https://www.reddit.com/r/raylib/)
[![Twitter Follow](https://img.shields.io/twitter/follow/raysan5?style=social)](https://twitter.com/raysan5) [![Youtube Subscribers](https://img.shields.io/youtube/channel/subscribers/UC8WIBkhYb5sBNqXO1mZ7WSQ?style=flat&label=Youtube&logo=youtube)](https://www.youtube.com/c/raylib)
[![Subreddit subscribers](https://img.shields.io/reddit/subreddit-subscribers/raylib?style=social)](https://www.reddit.com/r/raylib/) [![Twitch Status](https://img.shields.io/twitch/status/raysan5?style=flat&label=Twitch&logo=twitch)](https://www.twitch.tv/raysan5)
[![Twitter Followers](https://img.shields.io/twitter/follow/raysan5?style=flat&label=@raysan5&color=1da1f2&logo=twitter)](https://twitter.com/raysan5)
[![Windows](https://github.com/raysan5/raylib/workflows/Windows/badge.svg)](https://github.com/raysan5/raylib/actions?query=workflow%3AWindows) [![Windows](https://github.com/raysan5/raylib/workflows/Windows/badge.svg)](https://github.com/raysan5/raylib/actions?query=workflow%3AWindows)
[![Linux](https://github.com/raysan5/raylib/workflows/Linux/badge.svg)](https://github.com/raysan5/raylib/actions?query=workflow%3ALinux) [![Linux](https://github.com/raysan5/raylib/workflows/Linux/badge.svg)](https://github.com/raysan5/raylib/actions?query=workflow%3ALinux)

View File

@ -30,6 +30,7 @@ The following people are currently [**sponsoring raylib**](https://github.com/sp
- Matthew Owens ([@MatthewOwens](https://github.com/MatthewOwens)) - Matthew Owens ([@MatthewOwens](https://github.com/MatthewOwens))
- Tim Eilers ([@eilerstim](https://github.com/eilerstim)) - Tim Eilers ([@eilerstim](https://github.com/eilerstim))
- Laurentino Luna ([@catmanl](https://github.com/catmanl)) - Laurentino Luna ([@catmanl](https://github.com/catmanl))
- ZimonIsHim ([@ZimonIsHim](https://github.com/ZimonIsHim))
### Past raylib GitHub Sponsors ### Past raylib GitHub Sponsors

View File

@ -44,7 +44,7 @@ elseif (${PLATFORM} MATCHES "Android")
set(PLATFORM_CPP "PLATFORM_ANDROID") set(PLATFORM_CPP "PLATFORM_ANDROID")
set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") set(GRAPHICS "GRAPHICS_API_OPENGL_ES2")
set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(raylib_sources "${raylib_sources} ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c") list(APPEND raylib_sources ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
add_definitions(-DANDROID -D__ANDROID_API__=21) add_definitions(-DANDROID -D__ANDROID_API__=21)
include_directories(${ANDROID_NDK}/sources/android/native_app_glue) include_directories(${ANDROID_NDK}/sources/android/native_app_glue)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libatomic.a -Wl,--build-id -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -u ANativeActivity_onCreate -Wl,-undefined,dynamic_lookup") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libatomic.a -Wl,--build-id -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -u ANativeActivity_onCreate -Wl,-undefined,dynamic_lookup")
@ -87,7 +87,9 @@ endif ()
if (${OPENGL_VERSION}) if (${OPENGL_VERSION})
set(${SUGGESTED_GRAPHICS} "${GRAPHICS}") set(${SUGGESTED_GRAPHICS} "${GRAPHICS}")
if (${OPENGL_VERSION} MATCHES "3.3") if (${OPENGL_VERSION} MATCHES "4.3")
set(GRAPHICS "GRAPHICS_API_OPENGL_43")
elseif (${OPENGL_VERSION} MATCHES "3.3")
set(GRAPHICS "GRAPHICS_API_OPENGL_33") set(GRAPHICS "GRAPHICS_API_OPENGL_33")
elseif (${OPENGL_VERSION} MATCHES "2.1") elseif (${OPENGL_VERSION} MATCHES "2.1")
set(GRAPHICS "GRAPHICS_API_OPENGL_21") set(GRAPHICS "GRAPHICS_API_OPENGL_21")

View File

@ -379,7 +379,7 @@ endif
ifeq ($(PLATFORM),PLATFORM_RPI) ifeq ($(PLATFORM),PLATFORM_RPI)
# Libraries for Raspberry Pi compiling # Libraries for Raspberry Pi compiling
# NOTE: Required packages: libasound2-dev (ALSA) # NOTE: Required packages: libasound2-dev (ALSA)
LDLIBS = -lraylib -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl LDLIBS = -lraylib -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl -latomic
ifeq ($(USE_RPI_CROSS_COMPILER),TRUE) ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
LDLIBS += -lvchiq_arm -lvcos LDLIBS += -lvchiq_arm -lvcos
endif endif
@ -387,7 +387,7 @@ endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
# Libraries for DRM compiling # Libraries for DRM compiling
# NOTE: Required packages: libasound2-dev (ALSA) # NOTE: Required packages: libasound2-dev (ALSA)
LDLIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lgbm -ldrm -ldl LDLIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lgbm -ldrm -ldl -latomic
endif endif
ifeq ($(PLATFORM),PLATFORM_WEB) ifeq ($(PLATFORM),PLATFORM_WEB)
# Libraries for web (HTML5) compiling # Libraries for web (HTML5) compiling

View File

@ -11,6 +11,49 @@
#include "raylib.h" #include "raylib.h"
#include <stdlib.h> // Required for: NULL
// Audio effect: lowpass filter
static void AudioProcessEffectLPF(void *buffer, unsigned int frames)
{
static float low[2] = { 0.0f, 0.0f };
static const float cutoff = 70.0f / 44100.0f; // 70 Hz lowpass filter
const float k = cutoff / (cutoff + 0.1591549431f); // RC filter formula
for (unsigned int i = 0; i < frames*2; i += 2)
{
float l = ((float *)buffer)[i], r = ((float *)buffer)[i + 1];
low[0] += k * (l - low[0]);
low[1] += k * (r - low[1]);
((float *)buffer)[i] = low[0];
((float *)buffer)[i + 1] = low[1];
}
}
static float *delayBuffer = NULL;
static unsigned int delayBufferSize = 0;
static unsigned int delayReadIndex = 2;
static unsigned int delayWriteIndex = 0;
// Audio effect: delay
static void AudioProcessEffectDelay(void *buffer, unsigned int frames)
{
for (unsigned int i = 0; i < frames*2; i += 2)
{
float leftDelay = delayBuffer[delayReadIndex++]; // ERROR: Reading buffer -> WHY??? Maybe thread related???
float rightDelay = delayBuffer[delayReadIndex++];
if (delayReadIndex == delayBufferSize) delayReadIndex = 0;
((float *)buffer)[i] = 0.5f*((float *)buffer)[i] + 0.5f*leftDelay;
((float *)buffer)[i + 1] = 0.5f*((float *)buffer)[i + 1] + 0.5f*rightDelay;
delayBuffer[delayWriteIndex++] = ((float *)buffer)[i];
delayBuffer[delayWriteIndex++] = ((float *)buffer)[i + 1];
if (delayWriteIndex == delayBufferSize) delayWriteIndex = 0;
}
}
int main(void) int main(void)
{ {
// Initialization // Initialization
@ -24,11 +67,18 @@ int main(void)
Music music = LoadMusicStream("resources/country.mp3"); Music music = LoadMusicStream("resources/country.mp3");
// Allocate buffer for the delay effect
delayBufferSize = 48000 * 2;
delayBuffer = (float *)RL_CALLOC(delayBufferSize, sizeof(float)); // 1 second delay (device sampleRate*channels)
PlayMusicStream(music); PlayMusicStream(music);
float timePlayed = 0.0f; float timePlayed = 0.0f;
bool pause = false; bool pause = false;
bool hasFilter = true;
bool hasDelay = true;
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -55,6 +105,22 @@ int main(void)
else ResumeMusicStream(music); else ResumeMusicStream(music);
} }
// Add/Remove effect: lowpass filter
if (IsKeyPressed(KEY_F))
{
hasFilter = !hasFilter;
if (hasFilter) AttachAudioStreamProcessor(music.stream, AudioProcessEffectLPF);
else DetachAudioStreamProcessor(music.stream, AudioProcessEffectLPF);
}
// Add/Remove effect: delay
if (IsKeyPressed(KEY_D))
{
hasDelay = !hasDelay;
if (hasDelay) AttachAudioStreamProcessor(music.stream, AudioProcessEffectDelay);
else DetachAudioStreamProcessor(music.stream, AudioProcessEffectDelay);
}
// Get timePlayed scaled to bar dimensions (400 pixels) // Get timePlayed scaled to bar dimensions (400 pixels)
timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*400; timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*400;
@ -86,6 +152,8 @@ int main(void)
CloseAudioDevice(); // Close audio device (music streaming is automatically stopped) CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
RL_FREE(delayBuffer); // Free delay buffer
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

View File

@ -20,6 +20,36 @@
#define MAX_SAMPLES 512 #define MAX_SAMPLES 512
#define MAX_SAMPLES_PER_UPDATE 4096 #define MAX_SAMPLES_PER_UPDATE 4096
// Cycles per second (hz)
float frequency = 440.0f;
// Audio frequency, for smoothing
float audioFrequency = 440.0f;
// Previous value, used to test if sine needs to be rewritten, and to smoothly modulate frequency
float oldFrequency = 1.0f;
// Index for audio rendering
float sineIdx = 0.0f;
// Audio input processing callback
void AudioInputCallback(void *buffer, unsigned int frames)
{
audioFrequency = frequency + (audioFrequency - frequency)*0.95f;
audioFrequency += 1.0f;
audioFrequency -= 1.0f;
float incr = audioFrequency/44100.0f;
short *d = (short *)buffer;
for (int i = 0; i < frames; i++)
{
d[i] = (short)(32000.0f*sinf(2*PI*sineIdx));
sineIdx += incr;
if (sineIdx > 1.0f) sineIdx -= 1.0f;
}
}
int main(void) int main(void)
{ {
// Initialization // Initialization
@ -33,9 +63,11 @@ int main(void)
SetAudioStreamBufferSizeDefault(MAX_SAMPLES_PER_UPDATE); SetAudioStreamBufferSizeDefault(MAX_SAMPLES_PER_UPDATE);
// Init raw audio stream (sample rate: 22050, sample size: 16bit-short, channels: 1-mono) // Init raw audio stream (sample rate: 44100, sample size: 16bit-short, channels: 1-mono)
AudioStream stream = LoadAudioStream(44100, 16, 1); AudioStream stream = LoadAudioStream(44100, 16, 1);
SetAudioStreamCallback(stream, AudioInputCallback);
// Buffer for the single cycle waveform we are synthesizing // Buffer for the single cycle waveform we are synthesizing
short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES); short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES);
@ -47,6 +79,7 @@ int main(void)
// Position read in to determine next frequency // Position read in to determine next frequency
Vector2 mousePosition = { -100.0f, -100.0f }; Vector2 mousePosition = { -100.0f, -100.0f };
/*
// Cycles per second (hz) // Cycles per second (hz)
float frequency = 440.0f; float frequency = 440.0f;
@ -55,6 +88,7 @@ int main(void)
// Cursor to read and copy the samples of the sine wave buffer // Cursor to read and copy the samples of the sine wave buffer
int readCursor = 0; int readCursor = 0;
*/
// Computed size in samples of the sine wave // Computed size in samples of the sine wave
int waveLength = 1; int waveLength = 1;
@ -82,7 +116,7 @@ int main(void)
SetAudioStreamPan(stream, pan); SetAudioStreamPan(stream, pan);
} }
// Rewrite the sine wave. // Rewrite the sine wave
// Compute two cycles to allow the buffer padding, simplifying any modulation, resampling, etc. // Compute two cycles to allow the buffer padding, simplifying any modulation, resampling, etc.
if (frequency != oldFrequency) if (frequency != oldFrequency)
{ {
@ -92,17 +126,18 @@ int main(void)
if (waveLength > MAX_SAMPLES/2) waveLength = MAX_SAMPLES/2; if (waveLength > MAX_SAMPLES/2) waveLength = MAX_SAMPLES/2;
if (waveLength < 1) waveLength = 1; if (waveLength < 1) waveLength = 1;
// Write sine wave. // Write sine wave
for (int i = 0; i < waveLength*2; i++) for (int i = 0; i < waveLength*2; i++)
{ {
data[i] = (short)(sinf(((2*PI*(float)i/waveLength)))*32000); data[i] = (short)(sinf(((2*PI*(float)i/waveLength)))*32000);
} }
// Scale read cursor's position to minimize transition artifacts // Scale read cursor's position to minimize transition artifacts
readCursor = (int)(readCursor * ((float)waveLength / (float)oldWavelength)); //readCursor = (int)(readCursor * ((float)waveLength / (float)oldWavelength));
oldFrequency = frequency; oldFrequency = frequency;
} }
/*
// Refill audio stream if required // Refill audio stream if required
if (IsAudioStreamProcessed(stream)) if (IsAudioStreamProcessed(stream))
{ {
@ -131,6 +166,7 @@ int main(void)
// Copy finished frame to audio stream // Copy finished frame to audio stream
UpdateAudioStream(stream, writeBuf, MAX_SAMPLES_PER_UPDATE); UpdateAudioStream(stream, writeBuf, MAX_SAMPLES_PER_UPDATE);
} }
*/
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw

View File

@ -24,8 +24,8 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global Variables Definition // Global Variables Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
int screenWidth = 800; const int screenWidth = 800;
int screenHeight = 450; const int screenHeight = 450;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Declaration // Module Functions Declaration

View File

@ -92,20 +92,20 @@ int main(void)
// Draw axis: left joystick // Draw axis: left joystick
DrawCircle(259, 152, 39, BLACK); DrawCircle(259, 152, 39, BLACK);
DrawCircle(259, 152, 34, LIGHTGRAY); DrawCircle(259, 152, 34, LIGHTGRAY);
DrawCircle(259 + ((int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X)*20), DrawCircle(259 + (int)(GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X)*20),
152 + ((int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y)*20), 25, BLACK); 152 + (int)(GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y)*20), 25, BLACK);
// Draw axis: right joystick // Draw axis: right joystick
DrawCircle(461, 237, 38, BLACK); DrawCircle(461, 237, 38, BLACK);
DrawCircle(461, 237, 33, LIGHTGRAY); DrawCircle(461, 237, 33, LIGHTGRAY);
DrawCircle(461 + ((int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*20), DrawCircle(461 + (int)(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*20),
237 + ((int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*20), 25, BLACK); 237 + (int)(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*20), 25, BLACK);
// Draw axis: left-right triggers // Draw axis: left-right triggers
DrawRectangle(170, 30, 15, 70, GRAY); DrawRectangle(170, 30, 15, 70, GRAY);
DrawRectangle(604, 30, 15, 70, GRAY); DrawRectangle(604, 30, 15, 70, GRAY);
DrawRectangle(170, 30, 15, (((1 + (int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_TRIGGER))/2)*70), RED); DrawRectangle(170, 30, 15, (int)(((1 + GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_TRIGGER))/2)*70), RED);
DrawRectangle(604, 30, 15, (((1 + (int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_TRIGGER))/2)*70), RED); DrawRectangle(604, 30, 15, (int)(((1 + GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_TRIGGER))/2)*70), RED);
//DrawText(TextFormat("Xbox axis LT: %02.02f", GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_TRIGGER)), 10, 40, 10, BLACK); //DrawText(TextFormat("Xbox axis LT: %02.02f", GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_TRIGGER)), 10, 40, 10, BLACK);
//DrawText(TextFormat("Xbox axis RT: %02.02f", GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_TRIGGER)), 10, 60, 10, BLACK); //DrawText(TextFormat("Xbox axis RT: %02.02f", GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_TRIGGER)), 10, 60, 10, BLACK);
@ -140,20 +140,20 @@ int main(void)
// Draw axis: left joystick // Draw axis: left joystick
DrawCircle(319, 255, 35, BLACK); DrawCircle(319, 255, 35, BLACK);
DrawCircle(319, 255, 31, LIGHTGRAY); DrawCircle(319, 255, 31, LIGHTGRAY);
DrawCircle(319 + ((int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) * 20), DrawCircle(319 + (int)(GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) * 20),
255 + ((int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) * 20), 25, BLACK); 255 + (int)(GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) * 20), 25, BLACK);
// Draw axis: right joystick // Draw axis: right joystick
DrawCircle(475, 255, 35, BLACK); DrawCircle(475, 255, 35, BLACK);
DrawCircle(475, 255, 31, LIGHTGRAY); DrawCircle(475, 255, 31, LIGHTGRAY);
DrawCircle(475 + ((int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*20), DrawCircle(475 + (int)(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X) * 20),
255 + ((int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*20), 25, BLACK); 255 + (int)(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y) * 20), 25, BLACK);
// Draw axis: left-right triggers // Draw axis: left-right triggers
DrawRectangle(169, 48, 15, 70, GRAY); DrawRectangle(169, 48, 15, 70, GRAY);
DrawRectangle(611, 48, 15, 70, GRAY); DrawRectangle(611, 48, 15, 70, GRAY);
DrawRectangle(169, 48, 15, (((1 - (int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_TRIGGER)) / 2) * 70), RED); DrawRectangle(169, 48, 15, (int)(((1 - GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_TRIGGER)) / 2) * 70), RED);
DrawRectangle(611, 48, 15, (((1 - (int)GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_TRIGGER)) / 2) * 70), RED); DrawRectangle(611, 48, 15, (int)(((1 - GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_TRIGGER)) / 2) * 70), RED);
} }
else else
{ {

View File

@ -78,7 +78,11 @@ int main(void)
// Initialize framebuffer for stereo rendering // Initialize framebuffer for stereo rendering
// NOTE: Screen size should match HMD aspect ratio // NOTE: Screen size should match HMD aspect ratio
RenderTexture2D target = LoadRenderTexture(GetScreenWidth(), GetScreenHeight()); RenderTexture2D target = LoadRenderTexture(device.hResolution, device.vResolution);
// 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 = { 0.0f, 0.0f, (float)GetScreenWidth(), (float)GetScreenHeight() };
// Define the camera to look into our 3d world // Define the camera to look into our 3d world
Camera camera = { 0 }; Camera camera = { 0 };
@ -121,8 +125,7 @@ int main(void)
BeginDrawing(); BeginDrawing();
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
BeginShaderMode(distortion); BeginShaderMode(distortion);
DrawTextureRec(target.texture, (Rectangle){ 0, 0, (float)target.texture.width, DrawTexturePro(target.texture, sourceRec, destRec, (Vector2){ 0.0f, 0.0f }, 0.0f, WHITE);
(float)-target.texture.height }, (Vector2){ 0.0f, 0.0f }, WHITE);
EndShaderMode(); EndShaderMode();
DrawFPS(10, 10); DrawFPS(10, 10);
EndDrawing(); EndDrawing();

View File

@ -121,9 +121,22 @@ int main(void)
cursorColor = ORANGE; cursorColor = ORANGE;
hitObjectName = "Box"; hitObjectName = "Box";
// Check ray collision against model // Check ray collision against model meshes
// NOTE: It considers model.transform matrix! RayCollision meshHitInfo = { 0 };
RayCollision meshHitInfo = GetRayCollisionModel(ray, tower); for (int m = 0; m < tower.meshCount; m++)
{
// NOTE: We consider the model.transform for the collision check but
// it can be checked against any transform Matrix, used when checking against same
// model drawn multiple times with multiple transforms
meshHitInfo = GetRayCollisionMesh(ray, tower.meshes[m], tower.transform);
if (meshHitInfo.hit)
{
// Save the closest hit mesh
if ((!collision.hit) || (collision.distance > meshHitInfo.distance)) collision = meshHitInfo;
break; // Stop once one mesh collision is detected, the colliding mesh is m
}
}
if (meshHitInfo.hit) if (meshHitInfo.hit)
{ {

View File

@ -27,8 +27,8 @@ int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
int screenWidth = 800; const int screenWidth = 800;
int screenHeight = 450; const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - hot reloading"); InitWindow(screenWidth, screenHeight, "raylib [shaders] example - hot reloading");

View File

@ -217,6 +217,12 @@ int main(void)
// De-Initialization // De-Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Free allocated matrices
RL_FREE(rotations);
RL_FREE(rotationsInc);
RL_FREE(translations);
RL_FREE(transforms);
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

View File

@ -24,8 +24,8 @@ int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
int screenWidth = 800; const int screenWidth = 800;
int screenHeight = 450; const int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_RESIZABLE); SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - raymarching shapes"); InitWindow(screenWidth, screenHeight, "raylib [shaders] example - raymarching shapes");
@ -77,9 +77,7 @@ int main(void)
// Check if screen is resized // Check if screen is resized
if (IsWindowResized()) if (IsWindowResized())
{ {
screenWidth = GetScreenWidth(); float resolution[2] = { (float)GetScreenWidth(), (float)GetScreenHeight() };
screenHeight = GetScreenHeight();
float resolution[2] = { (float)screenWidth, (float)screenHeight };
SetShaderValue(shader, resolutionLoc, resolution, SHADER_UNIFORM_VEC2); SetShaderValue(shader, resolutionLoc, resolution, SHADER_UNIFORM_VEC2);
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -93,10 +91,10 @@ int main(void)
// We only draw a white full-screen rectangle, // We only draw a white full-screen rectangle,
// frame is generated in shader using raymarching // frame is generated in shader using raymarching
BeginShaderMode(shader); BeginShaderMode(shader);
DrawRectangle(0, 0, screenWidth, screenHeight, WHITE); DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), WHITE);
EndShaderMode(); EndShaderMode();
DrawText("(c) Raymarching shader by Iñigo Quilez. MIT License.", screenWidth - 280, screenHeight - 20, 10, BLACK); DrawText("(c) Raymarching shader by Iñigo Quilez. MIT License.", GetScreenWidth() - 280, GetScreenHeight() - 20, 10, BLACK);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -41,8 +41,7 @@ int main(void)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
mousePosition = GetMousePosition(); mousePosition = GetMousePosition();
if (CheckCollisionPointRec(mousePosition, rec) && if (CheckCollisionPointRec(mousePosition, (Rectangle){ rec.x + rec.width - MOUSE_SCALE_MARK_SIZE, rec.y + rec.height - MOUSE_SCALE_MARK_SIZE, MOUSE_SCALE_MARK_SIZE, MOUSE_SCALE_MARK_SIZE }))
CheckCollisionPointRec(mousePosition, (Rectangle){ rec.x + rec.width - MOUSE_SCALE_MARK_SIZE, rec.y + rec.height - MOUSE_SCALE_MARK_SIZE, MOUSE_SCALE_MARK_SIZE, MOUSE_SCALE_MARK_SIZE }))
{ {
mouseScaleReady = true; mouseScaleReady = true;
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) mouseScaleMode = true; if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) mouseScaleMode = true;
@ -56,8 +55,13 @@ int main(void)
rec.width = (mousePosition.x - rec.x); rec.width = (mousePosition.x - rec.x);
rec.height = (mousePosition.y - rec.y); rec.height = (mousePosition.y - rec.y);
// Check minimum rec size
if (rec.width < MOUSE_SCALE_MARK_SIZE) rec.width = MOUSE_SCALE_MARK_SIZE; if (rec.width < MOUSE_SCALE_MARK_SIZE) rec.width = MOUSE_SCALE_MARK_SIZE;
if (rec.height < MOUSE_SCALE_MARK_SIZE) rec.height = MOUSE_SCALE_MARK_SIZE; if (rec.height < MOUSE_SCALE_MARK_SIZE) rec.height = MOUSE_SCALE_MARK_SIZE;
// Check maximum rec size
if (rec.width > (GetScreenWidth() - rec.x)) rec.width = GetScreenWidth() - rec.x;
if (rec.height > (GetScreenHeight() - rec.y)) rec.height = GetScreenHeight() - rec.y;
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) mouseScaleMode = false; if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) mouseScaleMode = false;
} }

View File

@ -19,8 +19,8 @@ int main(int argc, char **argv)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
int screenWidth = 800; const int screenWidth = 800;
int screenHeight = 450; const int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_RESIZABLE); // Make the window resizable SetConfigFlags(FLAG_WINDOW_RESIZABLE); // Make the window resizable
InitWindow(screenWidth, screenHeight, "raylib [textures] example - Draw part of a texture tiled"); InitWindow(screenWidth, screenHeight, "raylib [textures] example - Draw part of a texture tiled");
@ -71,9 +71,6 @@ int main(int argc, char **argv)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
screenWidth = GetScreenWidth();
screenHeight = GetScreenHeight();
// Handle mouse // Handle mouse
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
{ {
@ -122,11 +119,11 @@ int main(int argc, char **argv)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
// Draw the tiled area // Draw the tiled area
DrawTextureTiled(texPattern, recPattern[activePattern], (Rectangle){(float)OPT_WIDTH+MARGIN_SIZE, (float)MARGIN_SIZE, screenWidth - OPT_WIDTH - 2.0f*MARGIN_SIZE, screenHeight - 2.0f*MARGIN_SIZE}, DrawTextureTiled(texPattern, recPattern[activePattern], (Rectangle){(float)OPT_WIDTH+MARGIN_SIZE, (float)MARGIN_SIZE, GetScreenWidth() - OPT_WIDTH - 2.0f*MARGIN_SIZE, GetScreenHeight() - 2.0f*MARGIN_SIZE},
(Vector2){0.0f, 0.0f}, rotation, scale, colors[activeCol]); (Vector2){0.0f, 0.0f}, rotation, scale, colors[activeCol]);
// Draw options // Draw options
DrawRectangle(MARGIN_SIZE, MARGIN_SIZE, OPT_WIDTH - MARGIN_SIZE, screenHeight - 2*MARGIN_SIZE, ColorAlpha(LIGHTGRAY, 0.5f)); DrawRectangle(MARGIN_SIZE, MARGIN_SIZE, OPT_WIDTH - MARGIN_SIZE, GetScreenHeight() - 2*MARGIN_SIZE, ColorAlpha(LIGHTGRAY, 0.5f));
DrawText("Select Pattern", 2 + MARGIN_SIZE, 30 + MARGIN_SIZE, 10, BLACK); DrawText("Select Pattern", 2 + MARGIN_SIZE, 30 + MARGIN_SIZE, 10, BLACK);
DrawTexture(texPattern, 2 + MARGIN_SIZE, 40 + MARGIN_SIZE, BLACK); DrawTexture(texPattern, 2 + MARGIN_SIZE, 40 + MARGIN_SIZE, BLACK);

View File

@ -19,10 +19,10 @@ parse:
./raylib_parser -i ../src/raylib.h -o raylib_api.$(EXTENSION) -f $(FORMAT) -d RLAPI ./raylib_parser -i ../src/raylib.h -o raylib_api.$(EXTENSION) -f $(FORMAT) -d RLAPI
./raylib_parser -i ../src/raymath.h -o raymath_api.$(EXTENSION) -f $(FORMAT) -d RMAPI ./raylib_parser -i ../src/raymath.h -o raymath_api.$(EXTENSION) -f $(FORMAT) -d RMAPI
./raylib_parser -i ../src/extras/easings.h -o easings_api.$(EXTENSION) -f $(FORMAT) -d EASEDEF ./raylib_parser -i ../src/extras/easings.h -o easings_api.$(EXTENSION) -f $(FORMAT) -d EASEDEF
./raylib_parser -i ../src/extras/physac.h -o physac_api.$(EXTENSION) -f $(FORMAT) -d PHYSACDEF ./raylib_parser -i ../src/extras/physac.h -o physac_api.$(EXTENSION) -f $(FORMAT) -d PHYSACDEF -t "PHYSAC IMPLEMENTATION"
./raylib_parser -i ../src/extras/raygui.h -o raygui_api.$(EXTENSION) -f $(FORMAT) -d RAYGUIAPI ./raylib_parser -i ../src/extras/raygui.h -o raygui_api.$(EXTENSION) -f $(FORMAT) -d RAYGUIAPI -t "RAYGUI IMPLEMENTATION"
./raylib_parser -i ../src/extras/rmem.h -o rmem_api.$(EXTENSION) -f $(FORMAT) -d RMEMAPI ./raylib_parser -i ../src/extras/rmem.h -o rmem_api.$(EXTENSION) -f $(FORMAT) -d RMEMAPI -t "RMEM IMPLEMENTATION"
./raylib_parser -i ../src/rlgl.h -o rlgl_api.$(EXTENSION) -f $(FORMAT) -d RLAPI ./raylib_parser -i ../src/rlgl.h -o rlgl_api.$(EXTENSION) -f $(FORMAT) -d RLAPI -t "RLGL IMPLEMENTATION"
clean: clean:
rm -f raylib_parser *.json *.txt *.xml *.lua rm -f raylib_parser *.json *.txt *.xml *.lua

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,59 @@
<?xml version="1.0" encoding="Windows-1252" ?> <?xml version="1.0" encoding="Windows-1252" ?>
<raylibAPI> <raylibAPI>
<Defines count="52">
<Define name="RAYLIB_H" type="GUARD" value="" desc="" />
<Define name="RAYLIB_VERSION" type="STRING" value="4.1-dev" desc="" />
<Define name="RLAPI" type="UNKNOWN" value="__declspec(dllexport)" desc="We are building the library as a Win32 shared library (.dll)" />
<Define name="PI" type="FLOAT" value="3.14159265358979323846" desc="" />
<Define name="DEG2RAD" type="FLOAT_MATH" value="(PI/180.0f)" desc="" />
<Define name="RAD2DEG" type="FLOAT_MATH" value="(180.0f/PI)" desc="" />
<Define name="RL_MALLOC(sz)" type="MACRO" value="malloc(sz)" desc="" />
<Define name="RL_CALLOC(n,sz)" type="MACRO" value="calloc(n,sz)" desc="" />
<Define name="RL_REALLOC(ptr,sz)" type="MACRO" value="realloc(ptr,sz)" desc="" />
<Define name="RL_FREE(ptr)" type="MACRO" value="free(ptr)" desc="" />
<Define name="CLITERAL(type)" type="MACRO" value="type" desc="" />
<Define name="RL_COLOR_TYPE" type="GUARD" value="" desc="" />
<Define name="RL_RECTANGLE_TYPE" type="GUARD" value="" desc="" />
<Define name="RL_VECTOR2_TYPE" type="GUARD" value="" desc="" />
<Define name="RL_VECTOR3_TYPE" type="GUARD" value="" desc="" />
<Define name="RL_VECTOR4_TYPE" type="GUARD" value="" desc="" />
<Define name="RL_QUATERNION_TYPE" type="GUARD" value="" desc="" />
<Define name="RL_MATRIX_TYPE" type="GUARD" value="" desc="" />
<Define name="LIGHTGRAY" type="COLOR" value="CLITERAL(Color){ 200, 200, 200, 255 }" desc="Light Gray" />
<Define name="GRAY" type="COLOR" value="CLITERAL(Color){ 130, 130, 130, 255 }" desc="Gray" />
<Define name="DARKGRAY" type="COLOR" value="CLITERAL(Color){ 80, 80, 80, 255 }" desc="Dark Gray" />
<Define name="YELLOW" type="COLOR" value="CLITERAL(Color){ 253, 249, 0, 255 }" desc="Yellow" />
<Define name="GOLD" type="COLOR" value="CLITERAL(Color){ 255, 203, 0, 255 }" desc="Gold" />
<Define name="ORANGE" type="COLOR" value="CLITERAL(Color){ 255, 161, 0, 255 }" desc="Orange" />
<Define name="PINK" type="COLOR" value="CLITERAL(Color){ 255, 109, 194, 255 }" desc="Pink" />
<Define name="RED" type="COLOR" value="CLITERAL(Color){ 230, 41, 55, 255 }" desc="Red" />
<Define name="MAROON" type="COLOR" value="CLITERAL(Color){ 190, 33, 55, 255 }" desc="Maroon" />
<Define name="GREEN" type="COLOR" value="CLITERAL(Color){ 0, 228, 48, 255 }" desc="Green" />
<Define name="LIME" type="COLOR" value="CLITERAL(Color){ 0, 158, 47, 255 }" desc="Lime" />
<Define name="DARKGREEN" type="COLOR" value="CLITERAL(Color){ 0, 117, 44, 255 }" desc="Dark Green" />
<Define name="SKYBLUE" type="COLOR" value="CLITERAL(Color){ 102, 191, 255, 255 }" desc="Sky Blue" />
<Define name="BLUE" type="COLOR" value="CLITERAL(Color){ 0, 121, 241, 255 }" desc="Blue" />
<Define name="DARKBLUE" type="COLOR" value="CLITERAL(Color){ 0, 82, 172, 255 }" desc="Dark Blue" />
<Define name="PURPLE" type="COLOR" value="CLITERAL(Color){ 200, 122, 255, 255 }" desc="Purple" />
<Define name="VIOLET" type="COLOR" value="CLITERAL(Color){ 135, 60, 190, 255 }" desc="Violet" />
<Define name="DARKPURPLE" type="COLOR" value="CLITERAL(Color){ 112, 31, 126, 255 }" desc="Dark Purple" />
<Define name="BEIGE" type="COLOR" value="CLITERAL(Color){ 211, 176, 131, 255 }" desc="Beige" />
<Define name="BROWN" type="COLOR" value="CLITERAL(Color){ 127, 106, 79, 255 }" desc="Brown" />
<Define name="DARKBROWN" type="COLOR" value="CLITERAL(Color){ 76, 63, 47, 255 }" desc="Dark Brown" />
<Define name="WHITE" type="COLOR" value="CLITERAL(Color){ 255, 255, 255, 255 }" desc="White" />
<Define name="BLACK" type="COLOR" value="CLITERAL(Color){ 0, 0, 0, 255 }" desc="Black" />
<Define name="BLANK" type="COLOR" value="CLITERAL(Color){ 0, 0, 0, 0 }" desc="Blank (Transparent)" />
<Define name="MAGENTA" type="COLOR" value="CLITERAL(Color){ 255, 0, 255, 255 }" desc="Magenta" />
<Define name="RAYWHITE" type="COLOR" value="CLITERAL(Color){ 245, 245, 245, 255 }" desc="My own White (raylib logo)" />
<Define name="RL_BOOL_TYPE" type="GUARD" value="" desc="" />
<Define name="MOUSE_LEFT_BUTTON" type="UNKNOWN" value="MOUSE_BUTTON_LEFT" desc="" />
<Define name="MOUSE_RIGHT_BUTTON" type="UNKNOWN" value="MOUSE_BUTTON_RIGHT" desc="" />
<Define name="MOUSE_MIDDLE_BUTTON" type="UNKNOWN" value="MOUSE_BUTTON_MIDDLE" desc="" />
<Define name="MATERIAL_MAP_DIFFUSE" type="UNKNOWN" value="MATERIAL_MAP_ALBEDO" desc="" />
<Define name="MATERIAL_MAP_SPECULAR" type="UNKNOWN" value="MATERIAL_MAP_METALNESS" desc="" />
<Define name="SHADER_LOC_MAP_DIFFUSE" type="UNKNOWN" value="SHADER_LOC_MAP_ALBEDO" desc="" />
<Define name="SHADER_LOC_MAP_SPECULAR" type="UNKNOWN" value="SHADER_LOC_MAP_METALNESS" desc="" />
</Defines>
<Structs count="31"> <Structs count="31">
<Struct name="Vector2" fieldCount="2" desc="Vector2, 2 components"> <Struct name="Vector2" fieldCount="2" desc="Vector2, 2 components">
<Field type="float" name="x" desc="Vector x component" /> <Field type="float" name="x" desc="Vector x component" />
@ -16,11 +70,23 @@
<Field type="float" name="z" desc="Vector z component" /> <Field type="float" name="z" desc="Vector z component" />
<Field type="float" name="w" desc="Vector w component" /> <Field type="float" name="w" desc="Vector w component" />
</Struct> </Struct>
<Struct name="Matrix" fieldCount="4" desc="Matrix, 4x4 components, column major, OpenGL style, right handed"> <Struct name="Matrix" fieldCount="16" desc="Matrix, 4x4 components, column major, OpenGL style, right handed">
<Field type="float" name="m0, m4, m8, m12" desc="Matrix first row (4 components)" /> <Field type="float" name="m0" desc="Matrix first row (4 components)" />
<Field type="float" name="m1, m5, m9, m13" desc="Matrix second row (4 components)" /> <Field type="float" name="m4" desc="Matrix first row (4 components)" />
<Field type="float" name="m2, m6, m10, m14" desc="Matrix third row (4 components)" /> <Field type="float" name="m8" desc="Matrix first row (4 components)" />
<Field type="float" name="m3, m7, m11, m15" desc="Matrix fourth row (4 components)" /> <Field type="float" name="m12" desc="Matrix first row (4 components)" />
<Field type="float" name="m1" desc="Matrix second row (4 components)" />
<Field type="float" name="m5" desc="Matrix second row (4 components)" />
<Field type="float" name="m9" desc="Matrix second row (4 components)" />
<Field type="float" name="m13" desc="Matrix second row (4 components)" />
<Field type="float" name="m2" desc="Matrix third row (4 components)" />
<Field type="float" name="m6" desc="Matrix third row (4 components)" />
<Field type="float" name="m10" desc="Matrix third row (4 components)" />
<Field type="float" name="m14" desc="Matrix third row (4 components)" />
<Field type="float" name="m3" desc="Matrix fourth row (4 components)" />
<Field type="float" name="m7" desc="Matrix fourth row (4 components)" />
<Field type="float" name="m11" desc="Matrix fourth row (4 components)" />
<Field type="float" name="m15" desc="Matrix fourth row (4 components)" />
</Struct> </Struct>
<Struct name="Color" fieldCount="4" desc="Color, 4 components, R8G8B8A8 (32bit)"> <Struct name="Color" fieldCount="4" desc="Color, 4 components, R8G8B8A8 (32bit)">
<Field type="unsigned char" name="r" desc="Color red value" /> <Field type="unsigned char" name="r" desc="Color red value" />
@ -94,7 +160,7 @@
<Field type="int" name="triangleCount" desc="Number of triangles stored (indexed or not)" /> <Field type="int" name="triangleCount" desc="Number of triangles stored (indexed or not)" />
<Field type="float *" name="vertices" desc="Vertex position (XYZ - 3 components per vertex) (shader-location = 0)" /> <Field type="float *" name="vertices" desc="Vertex position (XYZ - 3 components per vertex) (shader-location = 0)" />
<Field type="float *" name="texcoords" desc="Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)" /> <Field type="float *" name="texcoords" desc="Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)" />
<Field type="float *" name="texcoords2" desc="Vertex second texture coordinates (useful for lightmaps) (shader-location = 5)" /> <Field type="float *" name="texcoords2" desc="Vertex texture second coordinates (UV - 2 components per vertex) (shader-location = 5)" />
<Field type="float *" name="normals" desc="Vertex normals (XYZ - 3 components per vertex) (shader-location = 2)" /> <Field type="float *" name="normals" desc="Vertex normals (XYZ - 3 components per vertex) (shader-location = 2)" />
<Field type="float *" name="tangents" desc="Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4)" /> <Field type="float *" name="tangents" desc="Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4)" />
<Field type="unsigned char *" name="colors" desc="Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)" /> <Field type="unsigned char *" name="colors" desc="Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)" />
@ -118,7 +184,7 @@
<Struct name="Material" fieldCount="3" desc="Material, includes shader and maps"> <Struct name="Material" fieldCount="3" desc="Material, includes shader and maps">
<Field type="Shader" name="shader" desc="Material shader" /> <Field type="Shader" name="shader" desc="Material shader" />
<Field type="MaterialMap *" name="maps" desc="Material maps array (MAX_MATERIAL_MAPS)" /> <Field type="MaterialMap *" name="maps" desc="Material maps array (MAX_MATERIAL_MAPS)" />
<Field type="float" name="params[4]" desc="Material generic parameters (if required)" /> <Field type="float[4]" name="params" desc="Material generic parameters (if required)" />
</Struct> </Struct>
<Struct name="Transform" fieldCount="3" desc="Transform, vectex transformation data"> <Struct name="Transform" fieldCount="3" desc="Transform, vectex transformation data">
<Field type="Vector3" name="translation" desc="Translation" /> <Field type="Vector3" name="translation" desc="Translation" />
@ -126,7 +192,7 @@
<Field type="Vector3" name="scale" desc="Scale" /> <Field type="Vector3" name="scale" desc="Scale" />
</Struct> </Struct>
<Struct name="BoneInfo" fieldCount="2" desc="Bone, skeletal animation bone"> <Struct name="BoneInfo" fieldCount="2" desc="Bone, skeletal animation bone">
<Field type="char" name="name[32]" desc="Bone name" /> <Field type="char[32]" name="name" desc="Bone name" />
<Field type="int" name="parent" desc="Bone parent" /> <Field type="int" name="parent" desc="Bone parent" />
</Struct> </Struct>
<Struct name="Model" fieldCount="9" desc="Model, meshes, materials and animation data"> <Struct name="Model" fieldCount="9" desc="Model, meshes, materials and animation data">
@ -167,8 +233,9 @@
<Field type="unsigned int" name="channels" desc="Number of channels (1-mono, 2-stereo, ...)" /> <Field type="unsigned int" name="channels" desc="Number of channels (1-mono, 2-stereo, ...)" />
<Field type="void *" name="data" desc="Buffer data pointer" /> <Field type="void *" name="data" desc="Buffer data pointer" />
</Struct> </Struct>
<Struct name="AudioStream" fieldCount="4" desc="AudioStream, custom audio stream"> <Struct name="AudioStream" fieldCount="5" desc="AudioStream, custom audio stream">
<Field type="rAudioBuffer *" name="buffer" desc="Pointer to internal data used by the audio system" /> <Field type="rAudioBuffer *" name="buffer" desc="Pointer to internal data used by the audio system" />
<Field type="rAudioProcessor *" name="processor" desc="Pointer to internal data processor, useful for audio effects" />
<Field type="unsigned int" name="sampleRate" desc="Frequency (samples per second)" /> <Field type="unsigned int" name="sampleRate" desc="Frequency (samples per second)" />
<Field type="unsigned int" name="sampleSize" desc="Bit depth (bits per sample): 8, 16, 32 (24 not supported)" /> <Field type="unsigned int" name="sampleSize" desc="Bit depth (bits per sample): 8, 16, 32 (24 not supported)" />
<Field type="unsigned int" name="channels" desc="Number of channels (1-mono, 2-stereo, ...)" /> <Field type="unsigned int" name="channels" desc="Number of channels (1-mono, 2-stereo, ...)" />
@ -193,20 +260,27 @@
<Field type="float" name="eyeToScreenDistance" desc="Distance between eye and display in meters" /> <Field type="float" name="eyeToScreenDistance" desc="Distance between eye and display in meters" />
<Field type="float" name="lensSeparationDistance" desc="Lens separation distance in meters" /> <Field type="float" name="lensSeparationDistance" desc="Lens separation distance in meters" />
<Field type="float" name="interpupillaryDistance" desc="IPD (distance between pupils) in meters" /> <Field type="float" name="interpupillaryDistance" desc="IPD (distance between pupils) in meters" />
<Field type="float" name="lensDistortionValues[4]" desc="Lens distortion constant parameters" /> <Field type="float[4]" name="lensDistortionValues" desc="Lens distortion constant parameters" />
<Field type="float" name="chromaAbCorrection[4]" desc="Chromatic aberration correction parameters" /> <Field type="float[4]" name="chromaAbCorrection" desc="Chromatic aberration correction parameters" />
</Struct> </Struct>
<Struct name="VrStereoConfig" fieldCount="8" desc="VrStereoConfig, VR stereo rendering configuration for simulator"> <Struct name="VrStereoConfig" fieldCount="8" desc="VrStereoConfig, VR stereo rendering configuration for simulator">
<Field type="Matrix" name="projection[2]" desc="VR projection matrices (per eye)" /> <Field type="Matrix[2]" name="projection" desc="VR projection matrices (per eye)" />
<Field type="Matrix" name="viewOffset[2]" desc="VR view offset matrices (per eye)" /> <Field type="Matrix[2]" name="viewOffset" desc="VR view offset matrices (per eye)" />
<Field type="float" name="leftLensCenter[2]" desc="VR left lens center" /> <Field type="float[2]" name="leftLensCenter" desc="VR left lens center" />
<Field type="float" name="rightLensCenter[2]" desc="VR right lens center" /> <Field type="float[2]" name="rightLensCenter" desc="VR right lens center" />
<Field type="float" name="leftScreenCenter[2]" desc="VR left screen center" /> <Field type="float[2]" name="leftScreenCenter" desc="VR left screen center" />
<Field type="float" name="rightScreenCenter[2]" desc="VR right screen center" /> <Field type="float[2]" name="rightScreenCenter" desc="VR right screen center" />
<Field type="float" name="scale[2]" desc="VR distortion scale" /> <Field type="float[2]" name="scale" desc="VR distortion scale" />
<Field type="float" name="scaleIn[2]" desc="VR distortion scale in" /> <Field type="float[2]" name="scaleIn" desc="VR distortion scale in" />
</Struct> </Struct>
</Structs> </Structs>
<Aliases count="5">
<Alias type="Quaternion" name="Vector4" desc="Quaternion, 4 components (Vector4 alias)" />
<Alias type="Texture2D" name="Texture" desc="Texture2D, same as Texture" />
<Alias type="TextureCubemap" name="Texture" desc="TextureCubemap, same as Texture" />
<Alias type="RenderTexture2D" name="RenderTexture" desc="RenderTexture2D, same as RenderTexture" />
<Alias type="Camera" name="Camera3D" desc="Camera type fallback, defaults to Camera3D" />
</Aliases>
<Enums count="21"> <Enums count="21">
<Enum name="ConfigFlags" valueCount="14" desc="System/Window config flags"> <Enum name="ConfigFlags" valueCount="14" desc="System/Window config flags">
<Value name="FLAG_VSYNC_HINT" integer="64" desc="Set to try enabling V-Sync on GPU" /> <Value name="FLAG_VSYNC_HINT" integer="64" desc="Set to try enabling V-Sync on GPU" />
@ -543,61 +617,34 @@
<Value name="NPATCH_THREE_PATCH_HORIZONTAL" integer="2" desc="Npatch layout: 3x1 tiles" /> <Value name="NPATCH_THREE_PATCH_HORIZONTAL" integer="2" desc="Npatch layout: 3x1 tiles" />
</Enum> </Enum>
</Enums> </Enums>
<Defines count="52"> <Callbacks count="6">
<Define name="RAYLIB_H" type="GUARD" value="" desc="" /> <Callback name="TraceLogCallback" retType="void" paramCount="3" desc="Logging: Redirect trace log messages">
<Define name="RAYLIB_VERSION" type="STRING" value=""4.1-dev"" desc="" /> <Param type="int" name="logLevel" desc="" />
<Define name="RLAPI" type="UNKNOWN" value="__declspec(dllexport)" desc="// We are building the library as a Win32 shared library (.dll)" /> <Param type="const char *" name="text" desc="" />
<Define name="PI" type="FLOAT" value="3.14159265358979323846" desc="" /> <Param type="va_list" name="args" desc="" />
<Define name="DEG2RAD" type="UNKNOWN" value="(PI/180.0f)" desc="" /> </Callback>
<Define name="RAD2DEG" type="UNKNOWN" value="(180.0f/PI)" desc="" /> <Callback name="LoadFileDataCallback" retType="unsigned char *" paramCount="2" desc="FileIO: Load binary data">
<Define name="RL_MALLOC(sz)" type="MACRO" value="malloc(sz)" desc="" /> <Param type="const char *" name="fileName" desc="" />
<Define name="RL_CALLOC(n,sz)" type="MACRO" value="calloc(n,sz)" desc="" /> <Param type="unsigned int *" name="bytesRead" desc="" />
<Define name="RL_REALLOC(ptr,sz)" type="MACRO" value="realloc(ptr,sz)" desc="" /> </Callback>
<Define name="RL_FREE(ptr)" type="MACRO" value="free(ptr)" desc="" /> <Callback name="SaveFileDataCallback" retType="bool" paramCount="3" desc="FileIO: Save binary data">
<Define name="CLITERAL(type)" type="MACRO" value="type" desc="" /> <Param type="const char *" name="fileName" desc="" />
<Define name="RL_COLOR_TYPE" type="GUARD" value="" desc="" /> <Param type="void *" name="data" desc="" />
<Define name="RL_RECTANGLE_TYPE" type="GUARD" value="" desc="" /> <Param type="unsigned int" name="bytesToWrite" desc="" />
<Define name="RL_VECTOR2_TYPE" type="GUARD" value="" desc="" /> </Callback>
<Define name="RL_VECTOR3_TYPE" type="GUARD" value="" desc="" /> <Callback name="LoadFileTextCallback" retType="char *" paramCount="1" desc="FileIO: Load text data">
<Define name="RL_VECTOR4_TYPE" type="GUARD" value="" desc="" /> <Param type="const char *" name="fileName" desc="" />
<Define name="RL_QUATERNION_TYPE" type="GUARD" value="" desc="" /> </Callback>
<Define name="RL_MATRIX_TYPE" type="GUARD" value="" desc="" /> <Callback name="SaveFileTextCallback" retType="bool" paramCount="2" desc="FileIO: Save text data">
<Define name="LIGHTGRAY" type="COLOR" value="CLITERAL(Color){ 200, 200, 200, 255 }" desc="// Light Gray" /> <Param type="const char *" name="fileName" desc="" />
<Define name="GRAY" type="COLOR" value="CLITERAL(Color){ 130, 130, 130, 255 }" desc="// Gray" /> <Param type="char *" name="text" desc="" />
<Define name="DARKGRAY" type="COLOR" value="CLITERAL(Color){ 80, 80, 80, 255 }" desc="// Dark Gray" /> </Callback>
<Define name="YELLOW" type="COLOR" value="CLITERAL(Color){ 253, 249, 0, 255 }" desc="// Yellow" /> <Callback name="AudioCallback" retType="void" paramCount="2" desc="">
<Define name="GOLD" type="COLOR" value="CLITERAL(Color){ 255, 203, 0, 255 }" desc="// Gold" /> <Param type="void *" name="bufferData" desc="" />
<Define name="ORANGE" type="COLOR" value="CLITERAL(Color){ 255, 161, 0, 255 }" desc="// Orange" /> <Param type="unsigned int" name="frames" desc="" />
<Define name="PINK" type="COLOR" value="CLITERAL(Color){ 255, 109, 194, 255 }" desc="// Pink" /> </Callback>
<Define name="RED" type="COLOR" value="CLITERAL(Color){ 230, 41, 55, 255 }" desc="// Red" /> </Callbacks>
<Define name="MAROON" type="COLOR" value="CLITERAL(Color){ 190, 33, 55, 255 }" desc="// Maroon" /> <Functions count="499">
<Define name="GREEN" type="COLOR" value="CLITERAL(Color){ 0, 228, 48, 255 }" desc="// Green" />
<Define name="LIME" type="COLOR" value="CLITERAL(Color){ 0, 158, 47, 255 }" desc="// Lime" />
<Define name="DARKGREEN" type="COLOR" value="CLITERAL(Color){ 0, 117, 44, 255 }" desc="// Dark Green" />
<Define name="SKYBLUE" type="COLOR" value="CLITERAL(Color){ 102, 191, 255, 255 }" desc="// Sky Blue" />
<Define name="BLUE" type="COLOR" value="CLITERAL(Color){ 0, 121, 241, 255 }" desc="// Blue" />
<Define name="DARKBLUE" type="COLOR" value="CLITERAL(Color){ 0, 82, 172, 255 }" desc="// Dark Blue" />
<Define name="PURPLE" type="COLOR" value="CLITERAL(Color){ 200, 122, 255, 255 }" desc="// Purple" />
<Define name="VIOLET" type="COLOR" value="CLITERAL(Color){ 135, 60, 190, 255 }" desc="// Violet" />
<Define name="DARKPURPLE" type="COLOR" value="CLITERAL(Color){ 112, 31, 126, 255 }" desc="// Dark Purple" />
<Define name="BEIGE" type="COLOR" value="CLITERAL(Color){ 211, 176, 131, 255 }" desc="// Beige" />
<Define name="BROWN" type="COLOR" value="CLITERAL(Color){ 127, 106, 79, 255 }" desc="// Brown" />
<Define name="DARKBROWN" type="COLOR" value="CLITERAL(Color){ 76, 63, 47, 255 }" desc="// Dark Brown" />
<Define name="WHITE" type="COLOR" value="CLITERAL(Color){ 255, 255, 255, 255 }" desc="// White" />
<Define name="BLACK" type="COLOR" value="CLITERAL(Color){ 0, 0, 0, 255 }" desc="// Black" />
<Define name="BLANK" type="COLOR" value="CLITERAL(Color){ 0, 0, 0, 0 }" desc="// Blank (Transparent)" />
<Define name="MAGENTA" type="COLOR" value="CLITERAL(Color){ 255, 0, 255, 255 }" desc="// Magenta" />
<Define name="RAYWHITE" type="COLOR" value="CLITERAL(Color){ 245, 245, 245, 255 }" desc="// My own White (raylib logo)" />
<Define name="RL_BOOL_TYPE" type="GUARD" value="" desc="" />
<Define name="MOUSE_LEFT_BUTTON" type="UNKNOWN" value="MOUSE_BUTTON_LEFT" desc="" />
<Define name="MOUSE_RIGHT_BUTTON" type="UNKNOWN" value="MOUSE_BUTTON_RIGHT" desc="" />
<Define name="MOUSE_MIDDLE_BUTTON" type="UNKNOWN" value="MOUSE_BUTTON_MIDDLE" desc="" />
<Define name="MATERIAL_MAP_DIFFUSE" type="UNKNOWN" value="MATERIAL_MAP_ALBEDO" desc="" />
<Define name="MATERIAL_MAP_SPECULAR" type="UNKNOWN" value="MATERIAL_MAP_METALNESS" desc="" />
<Define name="SHADER_LOC_MAP_DIFFUSE" type="UNKNOWN" value="SHADER_LOC_MAP_ALBEDO" desc="" />
<Define name="SHADER_LOC_MAP_SPECULAR" type="UNKNOWN" value="SHADER_LOC_MAP_METALNESS" desc="" />
</Defines>
<Functions count="497">
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context"> <Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
<Param type="int" name="width" desc="" /> <Param type="int" name="width" desc="" />
<Param type="int" name="height" desc="" /> <Param type="int" name="height" desc="" />
@ -955,7 +1002,7 @@
</Function> </Function>
<Function name="GetApplicationDirectory" retType="const char *" paramCount="0" desc="Get the directory if the running application (uses static string)"> <Function name="GetApplicationDirectory" retType="const char *" paramCount="0" desc="Get the directory if the running application (uses static string)">
</Function> </Function>
<Function name="GetDirectoryFiles" retType="char **" paramCount="2" desc="Get filenames in a directory path (memory should be freed)"> <Function name="GetDirectoryFiles" retType="char **" paramCount="2" desc="Get filenames in a directory path (memory must be freed)">
<Param type="const char *" name="dirPath" desc="" /> <Param type="const char *" name="dirPath" desc="" />
<Param type="int *" name="count" desc="" /> <Param type="int *" name="count" desc="" />
</Function> </Function>
@ -966,7 +1013,7 @@
</Function> </Function>
<Function name="IsFileDropped" retType="bool" paramCount="0" desc="Check if a file has been dropped into window"> <Function name="IsFileDropped" retType="bool" paramCount="0" desc="Check if a file has been dropped into window">
</Function> </Function>
<Function name="GetDroppedFiles" retType="char **" paramCount="1" desc="Get dropped files names (memory should be freed)"> <Function name="GetDroppedFiles" retType="char **" paramCount="1" desc="Get dropped files names (memory must be freed)">
<Param type="int *" name="count" desc="" /> <Param type="int *" name="count" desc="" />
</Function> </Function>
<Function name="ClearDroppedFiles" retType="void" paramCount="0" desc="Clear dropped files paths buffer (free memory)"> <Function name="ClearDroppedFiles" retType="void" paramCount="0" desc="Clear dropped files paths buffer (free memory)">
@ -974,24 +1021,24 @@
<Function name="GetFileModTime" retType="long" paramCount="1" desc="Get file modification time (last write time)"> <Function name="GetFileModTime" retType="long" paramCount="1" desc="Get file modification time (last write time)">
<Param type="const char *" name="fileName" desc="" /> <Param type="const char *" name="fileName" desc="" />
</Function> </Function>
<Function name="CompressData" retType="unsigned char *" paramCount="3" desc="Compress data (DEFLATE algorithm)"> <Function name="CompressData" retType="unsigned char *" paramCount="3" desc="Compress data (DEFLATE algorithm), memory must be MemFree()">
<Param type="const unsigned char *" name="data" desc="" /> <Param type="const unsigned char *" name="data" desc="" />
<Param type="int" name="dataLength" desc="" /> <Param type="int" name="dataSize" desc="" />
<Param type="int *" name="compDataLength" desc="" /> <Param type="int *" name="compDataSize" desc="" />
</Function> </Function>
<Function name="DecompressData" retType="unsigned char *" paramCount="3" desc="Decompress data (DEFLATE algorithm)"> <Function name="DecompressData" retType="unsigned char *" paramCount="3" desc="Decompress data (DEFLATE algorithm), memory must be MemFree()">
<Param type="const unsigned char *" name="compData" desc="" /> <Param type="const unsigned char *" name="compData" desc="" />
<Param type="int" name="compDataLength" desc="" /> <Param type="int" name="compDataSize" desc="" />
<Param type="int *" name="dataLength" desc="" /> <Param type="int *" name="dataSize" desc="" />
</Function> </Function>
<Function name="EncodeDataBase64" retType="char *" paramCount="3" desc="Encode data to Base64 string"> <Function name="EncodeDataBase64" retType="char *" paramCount="3" desc="Encode data to Base64 string, memory must be MemFree()">
<Param type="const unsigned char *" name="data" desc="" /> <Param type="const unsigned char *" name="data" desc="" />
<Param type="int" name="dataLength" desc="" /> <Param type="int" name="dataSize" desc="" />
<Param type="int *" name="outputLength" desc="" /> <Param type="int *" name="outputSize" desc="" />
</Function> </Function>
<Function name="DecodeDataBase64" retType="unsigned char *" paramCount="2" desc="Decode Base64 string data"> <Function name="DecodeDataBase64" retType="unsigned char *" paramCount="2" desc="Decode Base64 string data, memory must be MemFree()">
<Param type="const unsigned char *" name="data" desc="" /> <Param type="const unsigned char *" name="data" desc="" />
<Param type="int *" name="outputLength" desc="" /> <Param type="int *" name="outputSize" desc="" />
</Function> </Function>
<Function name="SaveStorageValue" retType="bool" paramCount="2" desc="Save integer value to storage file (to defined position), returns true on success"> <Function name="SaveStorageValue" retType="bool" paramCount="2" desc="Save integer value to storage file (to defined position), returns true on success">
<Param type="unsigned int" name="position" desc="" /> <Param type="unsigned int" name="position" desc="" />
@ -2451,10 +2498,6 @@
<Param type="Ray" name="ray" desc="" /> <Param type="Ray" name="ray" desc="" />
<Param type="BoundingBox" name="box" desc="" /> <Param type="BoundingBox" name="box" desc="" />
</Function> </Function>
<Function name="GetRayCollisionModel" retType="RayCollision" paramCount="2" desc="Get collision info between ray and model">
<Param type="Ray" name="ray" desc="" />
<Param type="Model" name="model" desc="" />
</Function>
<Function name="GetRayCollisionMesh" retType="RayCollision" paramCount="3" desc="Get collision info between ray and mesh"> <Function name="GetRayCollisionMesh" retType="RayCollision" paramCount="3" desc="Get collision info between ray and mesh">
<Param type="Ray" name="ray" desc="" /> <Param type="Ray" name="ray" desc="" />
<Param type="Mesh" name="mesh" desc="" /> <Param type="Mesh" name="mesh" desc="" />
@ -2666,5 +2709,17 @@
<Function name="SetAudioStreamBufferSizeDefault" retType="void" paramCount="1" desc="Default size for new audio streams"> <Function name="SetAudioStreamBufferSizeDefault" retType="void" paramCount="1" desc="Default size for new audio streams">
<Param type="int" name="size" desc="" /> <Param type="int" name="size" desc="" />
</Function> </Function>
<Function name="SetAudioStreamCallback" retType="void" paramCount="2" desc="Audio thread callback to request new data">
<Param type="AudioStream" name="stream" desc="" />
<Param type="AudioCallback" name="callback" desc="" />
</Function>
<Function name="AttachAudioStreamProcessor" retType="void" paramCount="2" desc="">
<Param type="AudioStream" name="stream" desc="" />
<Param type="AudioCallback" name="processor" desc="" />
</Function>
<Function name="DetachAudioStreamProcessor" retType="void" paramCount="2" desc="">
<Param type="AudioStream" name="stream" desc="" />
<Param type="AudioCallback" name="processor" desc="" />
</Function>
</Functions> </Functions>
</raylibAPI> </raylibAPI>

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.11) # FetchContent is available in 3.11+ cmake_minimum_required(VERSION 3.11) # FetchContent is available in 3.11+
project(example) project(example)
# Generate compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Dependencies # Dependencies
find_package(raylib 4.0.0 QUIET) # QUIET or REQUIRED find_package(raylib 4.0.0 QUIET) # QUIET or REQUIRED
if (NOT raylib_FOUND) # If there's none, fetch and build raylib if (NOT raylib_FOUND) # If there's none, fetch and build raylib

View File

@ -11,10 +11,8 @@ To compile the example, use one of the following dependending on your build targ
Use the following to build for desktop: Use the following to build for desktop:
``` bash ``` bash
mkdir build cmake -B build
cd build cmake --build build
cmake ..
make
``` ```
### Web ### Web

View File

@ -536,9 +536,15 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI) ifeq ($(PLATFORM),PLATFORM_RPI)
LDLIBS = -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl LDLIBS = -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl
ifeq ($(RAYLIB_MODULE_AUDIO),TRUE)
LDLIBS += -latomic
endif
endif endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
LDLIBS = -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl LDLIBS = -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl
ifeq ($(RAYLIB_MODULE_AUDIO),TRUE)
LDLIBS += -latomic
endif
endif endif
ifeq ($(PLATFORM),PLATFORM_ANDROID) ifeq ($(PLATFORM),PLATFORM_ANDROID)
LDLIBS = -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lc -lm LDLIBS = -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lc -lm
@ -696,17 +702,26 @@ nxusb.o : nxusb.c nxusb.h raylib.h
raygui.o : raygui.c raygui.o : raygui.c
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) $(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)
raygui.c: raygui.c:
echo #define RAYGUI_IMPLEMENTATION > raygui.c ifeq ($(PLATFORM_SHELL), cmd)
echo #include "$(RAYLIB_MODULE_RAYGUI_PATH)/raygui.h" >> raygui.c @echo #define RAYGUI_IMPLEMENTATION > raygui.c
@echo #include "$(RAYLIB_MODULE_RAYGUI_PATH)/raygui.h" >> raygui.c
else
@echo "#define RAYGUI_IMPLEMENTATION" > raygui.c
@echo "#include \"$(RAYLIB_MODULE_RAYGUI_PATH)/raygui.h\"" >> raygui.c
endif
# Compile physac module # Compile physac module
# NOTE: physac header should be distributed with raylib.h # NOTE: physac header should be distributed with raylib.h
physac.o : physac.c physac.o : physac.c
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) $(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)
physac.c: physac.c:
ifeq ($(PLATFORM_SHELL), cmd)
@echo #define PHYSAC_IMPLEMENTATION > physac.c @echo #define PHYSAC_IMPLEMENTATION > physac.c
@echo #include "$(RAYLIB_MODULE_PHYSAC_PATH)/physac.h" >> physac.c @echo #include "$(RAYLIB_MODULE_PHYSAC_PATH)/physac.h" >> physac.c
else
@echo "#define PHYSAC_IMPLEMENTATION" > physac.c
@echo "#include \"$(RAYLIB_MODULE_PHYSAC_PATH)/physac.h\"" >> physac.c
endif
# Compile android_native_app_glue module # Compile android_native_app_glue module
android_native_app_glue.o : $(NATIVE_APP_GLUE)/android_native_app_glue.c android_native_app_glue.o : $(NATIVE_APP_GLUE)/android_native_app_glue.c
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) $(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)

View File

@ -1,89 +1,81 @@
const std = @import("std"); const std = @import("std");
pub fn Pkg(srcdir: []const u8) type { pub fn addRaylib(b: *std.build.Builder, target: std.zig.CrossTarget) *std.build.LibExeObjStep {
return struct { // Standard release options allow the person running `zig build` to select
pub fn addRaylib(b: *std.build.Builder, target: std.zig.CrossTarget) *std.build.LibExeObjStep { // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
// Standard release options allow the person running `zig build` to select const mode = b.standardReleaseOptions();
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
const mode = b.standardReleaseOptions();
const raylib_flags = &[_][]const u8{ const raylib_flags = &[_][]const u8{
"-std=gnu99", "-std=gnu99",
"-DPLATFORM_DESKTOP", "-DPLATFORM_DESKTOP",
"-DGL_SILENCE_DEPRECATION=199309L", "-DGL_SILENCE_DEPRECATION=199309L",
"-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/1891 "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/1891
};
const raylib = b.addStaticLibrary("raylib", srcdir ++ "/raylib.h");
raylib.setTarget(target);
raylib.setBuildMode(mode);
raylib.linkLibC();
raylib.addIncludeDir(srcdir ++ "/external/glfw/include");
raylib.addCSourceFiles(&.{
srcdir ++ "/raudio.c",
srcdir ++ "/rcore.c",
srcdir ++ "/rmodels.c",
srcdir ++ "/rshapes.c",
srcdir ++ "/rtext.c",
srcdir ++ "/rtextures.c",
srcdir ++ "/utils.c",
}, raylib_flags);
switch (raylib.target.toTarget().os.tag) {
.windows => {
raylib.addCSourceFiles(&.{srcdir ++ "/rglfw.c"}, raylib_flags);
raylib.linkSystemLibrary("winmm");
raylib.linkSystemLibrary("gdi32");
raylib.linkSystemLibrary("opengl32");
raylib.addIncludeDir("external/glfw/deps/mingw");
},
.linux => {
raylib.addCSourceFiles(&.{srcdir ++ "/rglfw.c"}, raylib_flags);
raylib.linkSystemLibrary("GL");
raylib.linkSystemLibrary("rt");
raylib.linkSystemLibrary("dl");
raylib.linkSystemLibrary("m");
raylib.linkSystemLibrary("X11");
},
.freebsd, .openbsd, .netbsd, .dragonfly => {
raylib.addCSourceFiles(&.{srcdir ++ "/rglfw.c"}, raylib_flags);
raylib.linkSystemLibrary("GL");
raylib.linkSystemLibrary("rt");
raylib.linkSystemLibrary("dl");
raylib.linkSystemLibrary("m");
raylib.linkSystemLibrary("X11");
raylib.linkSystemLibrary("Xrandr");
raylib.linkSystemLibrary("Xinerama");
raylib.linkSystemLibrary("Xi");
raylib.linkSystemLibrary("Xxf86vm");
raylib.linkSystemLibrary("Xcursor");
},
.macos => {
// On macos rglfw.c include Objective-C files.
const raylib_flags_extra_macos = &[_][]const u8{
"-ObjC",
};
raylib.addCSourceFiles(
&.{srcdir ++ "/rglfw.c"},
raylib_flags ++ raylib_flags_extra_macos,
);
raylib.linkFramework("Foundation");
},
else => {
@panic("Unsupported OS");
},
}
raylib.setOutputDir("./");
raylib.install();
return raylib;
}
}; };
}
const lib = Pkg("."); const raylib = b.addStaticLibrary("raylib", srcdir ++ "/raylib.h");
raylib.setTarget(target);
raylib.setBuildMode(mode);
raylib.linkLibC();
raylib.addIncludeDir(srcdir ++ "/external/glfw/include");
raylib.addCSourceFiles(&.{
srcdir ++ "/raudio.c",
srcdir ++ "/rcore.c",
srcdir ++ "/rmodels.c",
srcdir ++ "/rshapes.c",
srcdir ++ "/rtext.c",
srcdir ++ "/rtextures.c",
srcdir ++ "/utils.c",
}, raylib_flags);
switch (raylib.target.toTarget().os.tag) {
.windows => {
raylib.addCSourceFiles(&.{srcdir ++ "/rglfw.c"}, raylib_flags);
raylib.linkSystemLibrary("winmm");
raylib.linkSystemLibrary("gdi32");
raylib.linkSystemLibrary("opengl32");
raylib.addIncludeDir("external/glfw/deps/mingw");
},
.linux => {
raylib.addCSourceFiles(&.{srcdir ++ "/rglfw.c"}, raylib_flags);
raylib.linkSystemLibrary("GL");
raylib.linkSystemLibrary("rt");
raylib.linkSystemLibrary("dl");
raylib.linkSystemLibrary("m");
raylib.linkSystemLibrary("X11");
},
.freebsd, .openbsd, .netbsd, .dragonfly => {
raylib.addCSourceFiles(&.{srcdir ++ "/rglfw.c"}, raylib_flags);
raylib.linkSystemLibrary("GL");
raylib.linkSystemLibrary("rt");
raylib.linkSystemLibrary("dl");
raylib.linkSystemLibrary("m");
raylib.linkSystemLibrary("X11");
raylib.linkSystemLibrary("Xrandr");
raylib.linkSystemLibrary("Xinerama");
raylib.linkSystemLibrary("Xi");
raylib.linkSystemLibrary("Xxf86vm");
raylib.linkSystemLibrary("Xcursor");
},
.macos => {
// On macos rglfw.c include Objective-C files.
const raylib_flags_extra_macos = &[_][]const u8{
"-ObjC",
};
raylib.addCSourceFiles(
&.{srcdir ++ "/rglfw.c"},
raylib_flags ++ raylib_flags_extra_macos,
);
raylib.linkFramework("Foundation");
},
else => {
@panic("Unsupported OS");
},
}
return raylib;
}
pub fn build(b: *std.build.Builder) void { pub fn build(b: *std.build.Builder) void {
// Standard target options allows the person running `zig build` to choose // Standard target options allows the person running `zig build` to choose
@ -92,5 +84,13 @@ pub fn build(b: *std.build.Builder) void {
// for restricting supported target set are available. // for restricting supported target set are available.
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
_ = lib.addRaylib(b, target); const lib = addRaylib(b, target);
lib.setOutputDir(srcdir);
lib.install();
}
const srcdir = getSrcDir();
fn getSrcDir() []const u8 {
return std.fs.path.dirname(@src().file) orelse ".";
} }

34535
src/external/miniaudio.h vendored

File diff suppressed because it is too large Load Diff

View File

@ -101,47 +101,47 @@ extern "C" { // Prevents name mangling of functions
#endif #endif
// Linear Easing functions // Linear Easing functions
EASEDEF float EaseLinearNone(float t, float b, float c, float d) { return (c*t/d + b); } EASEDEF float EaseLinearNone(float t, float b, float c, float d) { return (c*t/d + b); } // Ease: Linear
EASEDEF float EaseLinearIn(float t, float b, float c, float d) { return (c*t/d + b); } EASEDEF float EaseLinearIn(float t, float b, float c, float d) { return (c*t/d + b); } // Ease: Linear In
EASEDEF float EaseLinearOut(float t, float b, float c, float d) { return (c*t/d + b); } EASEDEF float EaseLinearOut(float t, float b, float c, float d) { return (c*t/d + b); } // Ease: Linear Out
EASEDEF float EaseLinearInOut(float t,float b, float c, float d) { return (c*t/d + b); } EASEDEF float EaseLinearInOut(float t, float b, float c, float d) { return (c*t/d + b); } // Ease: Linear In Out
// Sine Easing functions // Sine Easing functions
EASEDEF float EaseSineIn(float t, float b, float c, float d) { return (-c*cosf(t/d*(PI/2.0f)) + c + b); } EASEDEF float EaseSineIn(float t, float b, float c, float d) { return (-c*cosf(t/d*(PI/2.0f)) + c + b); } // Ease: Sine In
EASEDEF float EaseSineOut(float t, float b, float c, float d) { return (c*sinf(t/d*(PI/2.0f)) + b); } EASEDEF float EaseSineOut(float t, float b, float c, float d) { return (c*sinf(t/d*(PI/2.0f)) + b); } // Ease: Sine Out
EASEDEF float EaseSineInOut(float t, float b, float c, float d) { return (-c/2.0f*(cosf(PI*t/d) - 1.0f) + b); } EASEDEF float EaseSineInOut(float t, float b, float c, float d) { return (-c/2.0f*(cosf(PI*t/d) - 1.0f) + b); } // Ease: Sine Out
// Circular Easing functions // Circular Easing functions
EASEDEF float EaseCircIn(float t, float b, float c, float d) { t /= d; return (-c*(sqrtf(1.0f - t*t) - 1.0f) + b); } EASEDEF float EaseCircIn(float t, float b, float c, float d) { t /= d; return (-c*(sqrtf(1.0f - t*t) - 1.0f) + b); } // Ease: Circular In
EASEDEF float EaseCircOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*sqrtf(1.0f - t*t) + b); } EASEDEF float EaseCircOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*sqrtf(1.0f - t*t) + b); } // Ease: Circular Out
EASEDEF float EaseCircInOut(float t, float b, float c, float d) EASEDEF float EaseCircInOut(float t, float b, float c, float d) // Ease: Circular In Out
{ {
if ((t/=d/2.0f) < 1.0f) return (-c/2.0f*(sqrtf(1.0f - t*t) - 1.0f) + b); if ((t/=d/2.0f) < 1.0f) return (-c/2.0f*(sqrtf(1.0f - t*t) - 1.0f) + b);
t -= 2.0f; return (c/2.0f*(sqrtf(1.0f - t*t) + 1.0f) + b); t -= 2.0f; return (c/2.0f*(sqrtf(1.0f - t*t) + 1.0f) + b);
} }
// Cubic Easing functions // Cubic Easing functions
EASEDEF float EaseCubicIn(float t, float b, float c, float d) { t /= d; return (c*t*t*t + b); } EASEDEF float EaseCubicIn(float t, float b, float c, float d) { t /= d; return (c*t*t*t + b); } // Ease: Cubic In
EASEDEF float EaseCubicOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*(t*t*t + 1.0f) + b); } EASEDEF float EaseCubicOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*(t*t*t + 1.0f) + b); } // Ease: Cubic Out
EASEDEF float EaseCubicInOut(float t, float b, float c, float d) EASEDEF float EaseCubicInOut(float t, float b, float c, float d) // Ease: Cubic In Out
{ {
if ((t/=d/2.0f) < 1.0f) return (c/2.0f*t*t*t + b); if ((t/=d/2.0f) < 1.0f) return (c/2.0f*t*t*t + b);
t -= 2.0f; return (c/2.0f*(t*t*t + 2.0f) + b); t -= 2.0f; return (c/2.0f*(t*t*t + 2.0f) + b);
} }
// Quadratic Easing functions // Quadratic Easing functions
EASEDEF float EaseQuadIn(float t, float b, float c, float d) { t /= d; return (c*t*t + b); } EASEDEF float EaseQuadIn(float t, float b, float c, float d) { t /= d; return (c*t*t + b); } // Ease: Quadratic In
EASEDEF float EaseQuadOut(float t, float b, float c, float d) { t /= d; return (-c*t*(t - 2.0f) + b); } EASEDEF float EaseQuadOut(float t, float b, float c, float d) { t /= d; return (-c*t*(t - 2.0f) + b); } // Ease: Quadratic Out
EASEDEF float EaseQuadInOut(float t, float b, float c, float d) EASEDEF float EaseQuadInOut(float t, float b, float c, float d) // Ease: Quadratic In Out
{ {
if ((t/=d/2) < 1) return (((c/2)*(t*t)) + b); if ((t/=d/2) < 1) return (((c/2)*(t*t)) + b);
return (-c/2.0f*(((t - 1.0f)*(t - 3.0f)) - 1.0f) + b); return (-c/2.0f*(((t - 1.0f)*(t - 3.0f)) - 1.0f) + b);
} }
// Exponential Easing functions // Exponential Easing functions
EASEDEF float EaseExpoIn(float t, float b, float c, float d) { return (t == 0.0f) ? b : (c*powf(2.0f, 10.0f*(t/d - 1.0f)) + b); } EASEDEF float EaseExpoIn(float t, float b, float c, float d) { return (t == 0.0f) ? b : (c*powf(2.0f, 10.0f*(t/d - 1.0f)) + b); } // Ease: Exponential In
EASEDEF float EaseExpoOut(float t, float b, float c, float d) { return (t == d) ? (b + c) : (c*(-powf(2.0f, -10.0f*t/d) + 1.0f) + b); } EASEDEF float EaseExpoOut(float t, float b, float c, float d) { return (t == d) ? (b + c) : (c*(-powf(2.0f, -10.0f*t/d) + 1.0f) + b); } // Ease: Exponential Out
EASEDEF float EaseExpoInOut(float t, float b, float c, float d) EASEDEF float EaseExpoInOut(float t, float b, float c, float d) // Ease: Exponential In Out
{ {
if (t == 0.0f) return b; if (t == 0.0f) return b;
if (t == d) return (b + c); if (t == d) return (b + c);
@ -151,21 +151,21 @@ EASEDEF float EaseExpoInOut(float t, float b, float c, float d)
} }
// Back Easing functions // Back Easing functions
EASEDEF float EaseBackIn(float t, float b, float c, float d) EASEDEF float EaseBackIn(float t, float b, float c, float d) // Ease: Back In
{ {
float s = 1.70158f; float s = 1.70158f;
float postFix = t/=d; float postFix = t/=d;
return (c*(postFix)*t*((s + 1.0f)*t - s) + b); return (c*(postFix)*t*((s + 1.0f)*t - s) + b);
} }
EASEDEF float EaseBackOut(float t, float b, float c, float d) EASEDEF float EaseBackOut(float t, float b, float c, float d) // Ease: Back Out
{ {
float s = 1.70158f; float s = 1.70158f;
t = t/d - 1.0f; t = t/d - 1.0f;
return (c*(t*t*((s + 1.0f)*t + s) + 1.0f) + b); return (c*(t*t*((s + 1.0f)*t + s) + 1.0f) + b);
} }
EASEDEF float EaseBackInOut(float t, float b, float c, float d) EASEDEF float EaseBackInOut(float t, float b, float c, float d) // Ease: Back In Out
{ {
float s = 1.70158f; float s = 1.70158f;
if ((t/=d/2.0f) < 1.0f) if ((t/=d/2.0f) < 1.0f)
@ -180,7 +180,7 @@ EASEDEF float EaseBackInOut(float t, float b, float c, float d)
} }
// Bounce Easing functions // Bounce Easing functions
EASEDEF float EaseBounceOut(float t, float b, float c, float d) EASEDEF float EaseBounceOut(float t, float b, float c, float d) // Ease: Bounce Out
{ {
if ((t/=d) < (1.0f/2.75f)) if ((t/=d) < (1.0f/2.75f))
{ {
@ -203,15 +203,15 @@ EASEDEF float EaseBounceOut(float t, float b, float c, float d)
} }
} }
EASEDEF float EaseBounceIn(float t, float b, float c, float d) { return (c - EaseBounceOut(d - t, 0.0f, c, d) + b); } EASEDEF float EaseBounceIn(float t, float b, float c, float d) { return (c - EaseBounceOut(d - t, 0.0f, c, d) + b); } // Ease: Bounce In
EASEDEF float EaseBounceInOut(float t, float b, float c, float d) EASEDEF float EaseBounceInOut(float t, float b, float c, float d) // Ease: Bounce In Out
{ {
if (t < d/2.0f) return (EaseBounceIn(t*2.0f, 0.0f, c, d)*0.5f + b); if (t < d/2.0f) return (EaseBounceIn(t*2.0f, 0.0f, c, d)*0.5f + b);
else return (EaseBounceOut(t*2.0f - d, 0.0f, c, d)*0.5f + c*0.5f + b); else return (EaseBounceOut(t*2.0f - d, 0.0f, c, d)*0.5f + c*0.5f + b);
} }
// Elastic Easing functions // Elastic Easing functions
EASEDEF float EaseElasticIn(float t, float b, float c, float d) EASEDEF float EaseElasticIn(float t, float b, float c, float d) // Ease: Elastic In
{ {
if (t == 0.0f) return b; if (t == 0.0f) return b;
if ((t/=d) == 1.0f) return (b + c); if ((t/=d) == 1.0f) return (b + c);
@ -224,7 +224,7 @@ EASEDEF float EaseElasticIn(float t, float b, float c, float d)
return (-(postFix*sinf((t*d-s)*(2.0f*PI)/p )) + b); return (-(postFix*sinf((t*d-s)*(2.0f*PI)/p )) + b);
} }
EASEDEF float EaseElasticOut(float t, float b, float c, float d) EASEDEF float EaseElasticOut(float t, float b, float c, float d) // Ease: Elastic Out
{ {
if (t == 0.0f) return b; if (t == 0.0f) return b;
if ((t/=d) == 1.0f) return (b + c); if ((t/=d) == 1.0f) return (b + c);
@ -236,7 +236,7 @@ EASEDEF float EaseElasticOut(float t, float b, float c, float d)
return (a*powf(2.0f,-10.0f*t)*sinf((t*d-s)*(2.0f*PI)/p) + c + b); return (a*powf(2.0f,-10.0f*t)*sinf((t*d-s)*(2.0f*PI)/p) + c + b);
} }
EASEDEF float EaseElasticInOut(float t, float b, float c, float d) EASEDEF float EaseElasticInOut(float t, float b, float c, float d) // Ease: Elastic In Out
{ {
if (t == 0.0f) return b; if (t == 0.0f) return b;
if ((t/=d/2.0f) == 2.0f) return (b + c); if ((t/=d/2.0f) == 2.0f) return (b + c);

View File

@ -1999,7 +1999,6 @@ bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
{ {
keyCount--; keyCount--;
text[keyCount] = '\0'; text[keyCount] = '\0';
if (keyCount < 0) keyCount = 0;
} }
} }
@ -2177,7 +2176,6 @@ bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, i
{ {
keyCount--; keyCount--;
textValue[keyCount] = '\0'; textValue[keyCount] = '\0';
if (keyCount < 0) keyCount = 0;
valueHasChanged = true; valueHasChanged = true;
} }
} }

View File

@ -247,10 +247,6 @@ typedef struct tagBITMAPINFOHEADER {
#include "external/dr_flac.h" // FLAC loading functions #include "external/dr_flac.h" // FLAC loading functions
#endif #endif
#if defined(_MSC_VER)
#undef bool
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -311,10 +307,13 @@ typedef enum {
AUDIO_BUFFER_USAGE_STREAM AUDIO_BUFFER_USAGE_STREAM
} AudioBufferUsage; } AudioBufferUsage;
// Audio buffer structure // Audio buffer struct
struct rAudioBuffer { struct rAudioBuffer {
ma_data_converter converter; // Audio data converter ma_data_converter converter; // Audio data converter
AudioCallback callback; // Audio buffer callback for buffer filling on audio threads
rAudioProcessor *processor; // Audio processor
float volume; // Audio buffer volume float volume; // Audio buffer volume
float pitch; // Audio buffer pitch float pitch; // Audio buffer pitch
float pan; // Audio buffer pan (0.0f to 1.0f) float pan; // Audio buffer pan (0.0f to 1.0f)
@ -335,6 +334,14 @@ struct rAudioBuffer {
rAudioBuffer *prev; // Previous audio buffer on the list rAudioBuffer *prev; // Previous audio buffer on the list
}; };
// Audio processor struct
// NOTE: Useful to apply effects to an AudioBuffer
struct rAudioProcessor {
AudioCallback process; // Processor callback function
rAudioProcessor *next; // Next audio processor on the list
rAudioProcessor *prev; // Previous audio processor on the list
};
#define AudioBuffer rAudioBuffer // HACK: To avoid CoreAudio (macOS) symbol collision #define AudioBuffer rAudioBuffer // HACK: To avoid CoreAudio (macOS) symbol collision
// Audio data context // Audio data context
@ -372,7 +379,7 @@ static AudioData AUDIO = { // Global AUDIO context
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Declaration // Module specific Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static void OnLog(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message); static void OnLog(void *pUserData, ma_uint32 level, const char *pMessage);
static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const void *pFramesInput, ma_uint32 frameCount); static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const void *pFramesInput, ma_uint32 frameCount);
static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer); static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer);
@ -411,7 +418,7 @@ void InitAudioDevice(void)
{ {
// Init audio context // Init audio context
ma_context_config ctxConfig = ma_context_config_init(); ma_context_config ctxConfig = ma_context_config_init();
ctxConfig.logCallback = OnLog; ma_log_callback_init(OnLog, NULL);
ma_result result = ma_context_init(NULL, 0, &ctxConfig, &AUDIO.System.context); ma_result result = ma_context_init(NULL, 0, &ctxConfig, &AUDIO.System.context);
if (result != MA_SUCCESS) if (result != MA_SUCCESS)
@ -465,8 +472,7 @@ void InitAudioDevice(void)
// Init dummy audio buffers pool for multichannel sound playing // Init dummy audio buffers pool for multichannel sound playing
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++) for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
{ {
// WARNING: An empty audio buffer is created (data = 0) // WARNING: An empty audio buffer is created (data = 0) and added to list, AudioBuffer data is filled on PlaySoundMulti()
// AudioBuffer data just points to loaded sound data
AUDIO.MultiChannel.pool[i] = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, 0, AUDIO_BUFFER_USAGE_STATIC); AUDIO.MultiChannel.pool[i] = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, 0, AUDIO_BUFFER_USAGE_STATIC);
} }
@ -492,7 +498,7 @@ void CloseAudioDevice(void)
//UnloadAudioBuffer(AUDIO.MultiChannel.pool[i]); //UnloadAudioBuffer(AUDIO.MultiChannel.pool[i]);
if (AUDIO.MultiChannel.pool[i] != NULL) if (AUDIO.MultiChannel.pool[i] != NULL)
{ {
ma_data_converter_uninit(&AUDIO.MultiChannel.pool[i]->converter); ma_data_converter_uninit(&AUDIO.MultiChannel.pool[i]->converter, NULL);
UntrackAudioBuffer(AUDIO.MultiChannel.pool[i]); UntrackAudioBuffer(AUDIO.MultiChannel.pool[i]);
//RL_FREE(buffer->data); // Already unloaded by UnloadSound() //RL_FREE(buffer->data); // Already unloaded by UnloadSound()
RL_FREE(AUDIO.MultiChannel.pool[i]); RL_FREE(AUDIO.MultiChannel.pool[i]);
@ -541,9 +547,9 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
// Audio data runs through a format converter // Audio data runs through a format converter
ma_data_converter_config converterConfig = ma_data_converter_config_init(format, AUDIO_DEVICE_FORMAT, channels, AUDIO_DEVICE_CHANNELS, sampleRate, AUDIO.System.device.sampleRate); ma_data_converter_config converterConfig = ma_data_converter_config_init(format, AUDIO_DEVICE_FORMAT, channels, AUDIO_DEVICE_CHANNELS, sampleRate, AUDIO.System.device.sampleRate);
converterConfig.resampling.allowDynamicSampleRate = true; // Pitch shifting converterConfig.allowDynamicSampleRate = true;
ma_result result = ma_data_converter_init(&converterConfig, &audioBuffer->converter); ma_result result = ma_data_converter_init(&converterConfig, NULL, &audioBuffer->converter);
if (result != MA_SUCCESS) if (result != MA_SUCCESS)
{ {
@ -557,9 +563,13 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
audioBuffer->pitch = 1.0f; audioBuffer->pitch = 1.0f;
audioBuffer->pan = 0.5f; audioBuffer->pan = 0.5f;
audioBuffer->callback = NULL;
audioBuffer->processor = NULL;
audioBuffer->playing = false; audioBuffer->playing = false;
audioBuffer->paused = false; audioBuffer->paused = false;
audioBuffer->looping = false; audioBuffer->looping = false;
audioBuffer->usage = usage; audioBuffer->usage = usage;
audioBuffer->frameCursorPos = 0; audioBuffer->frameCursorPos = 0;
audioBuffer->sizeInFrames = sizeInFrames; audioBuffer->sizeInFrames = sizeInFrames;
@ -580,7 +590,7 @@ void UnloadAudioBuffer(AudioBuffer *buffer)
{ {
if (buffer != NULL) if (buffer != NULL)
{ {
ma_data_converter_uninit(&buffer->converter); ma_data_converter_uninit(&buffer->converter, NULL);
UntrackAudioBuffer(buffer); UntrackAudioBuffer(buffer);
RL_FREE(buffer->data); RL_FREE(buffer->data);
RL_FREE(buffer); RL_FREE(buffer);
@ -654,8 +664,8 @@ void SetAudioBufferPitch(AudioBuffer *buffer, float pitch)
// Note that this changes the duration of the sound: // Note that this changes the duration of the sound:
// - higher pitches will make the sound faster // - higher pitches will make the sound faster
// - lower pitches make it slower // - lower pitches make it slower
ma_uint32 outputSampleRate = (ma_uint32)((float)buffer->converter.config.sampleRateOut/pitch); ma_uint32 outputSampleRate = (ma_uint32)((float)buffer->converter.sampleRateOut/pitch);
ma_data_converter_set_rate(&buffer->converter, buffer->converter.config.sampleRateIn, outputSampleRate); ma_data_converter_set_rate(&buffer->converter, buffer->converter.sampleRateIn, outputSampleRate);
buffer->pitch = pitch; buffer->pitch = pitch;
} }
@ -894,7 +904,7 @@ void UpdateSound(Sound sound, const void *data, int sampleCount)
StopAudioBuffer(sound.stream.buffer); StopAudioBuffer(sound.stream.buffer);
// TODO: May want to lock/unlock this since this data buffer is read at mixing time // TODO: May want to lock/unlock this since this data buffer is read at mixing time
memcpy(sound.stream.buffer->data, data, sampleCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.config.formatIn, sound.stream.buffer->converter.config.channelsIn)); memcpy(sound.stream.buffer->data, data, sampleCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.formatIn, sound.stream.buffer->converter.channelsIn));
} }
} }
@ -1068,7 +1078,8 @@ void PlaySoundMulti(Sound sound)
AUDIO.MultiChannel.pool[index]->isSubBufferProcessed[0] = false; AUDIO.MultiChannel.pool[index]->isSubBufferProcessed[0] = false;
AUDIO.MultiChannel.pool[index]->isSubBufferProcessed[1] = false; AUDIO.MultiChannel.pool[index]->isSubBufferProcessed[1] = false;
AUDIO.MultiChannel.pool[index]->sizeInFrames = sound.stream.buffer->sizeInFrames; AUDIO.MultiChannel.pool[index]->sizeInFrames = sound.stream.buffer->sizeInFrames;
AUDIO.MultiChannel.pool[index]->data = sound.stream.buffer->data;
AUDIO.MultiChannel.pool[index]->data = sound.stream.buffer->data; // Fill dummy track with data for playing
PlayAudioBuffer(AUDIO.MultiChannel.pool[index]); PlayAudioBuffer(AUDIO.MultiChannel.pool[index]);
} }
@ -1191,8 +1202,7 @@ Wave WaveCopy(Wave wave)
// NOTE: Security check in case of out-of-range // NOTE: Security check in case of out-of-range
void WaveCrop(Wave *wave, int initSample, int finalSample) void WaveCrop(Wave *wave, int initSample, int finalSample)
{ {
if ((initSample >= 0) && (initSample < finalSample) && if ((initSample >= 0) && (initSample < finalSample) && ((unsigned int)finalSample < (wave->frameCount*wave->channels)))
(finalSample > 0) && ((unsigned int)finalSample < (wave->frameCount*wave->channels)))
{ {
int sampleCount = finalSample - initSample; int sampleCount = finalSample - initSample;
@ -1503,16 +1513,14 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
jar_xm_set_max_loop_count(ctxXm, 0); // Set infinite number of loops jar_xm_set_max_loop_count(ctxXm, 0); // Set infinite number of loops
unsigned int bits = 32; unsigned int bits = 32;
if (AUDIO_DEVICE_FORMAT == ma_format_s16) if (AUDIO_DEVICE_FORMAT == ma_format_s16) bits = 16;
bits = 16; else if (AUDIO_DEVICE_FORMAT == ma_format_u8) bits = 8;
else if (AUDIO_DEVICE_FORMAT == ma_format_u8)
bits = 8;
// NOTE: Only stereo is supported for XM // NOTE: Only stereo is supported for XM
music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, bits, 2); music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, bits, 2);
music.frameCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm); // NOTE: Always 2 channels (stereo) music.frameCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm); // NOTE: Always 2 channels (stereo)
music.looping = true; // Looping enabled by default music.looping = true; // Looping enabled by default
jar_xm_reset(ctxXm); // make sure we start at the beginning of the song jar_xm_reset(ctxXm); // make sure we start at the beginning of the song
music.ctxData = ctxXm; music.ctxData = ctxXm;
musicLoaded = true; musicLoaded = true;
@ -1533,7 +1541,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
for (int i = 0; i < it; i++) newData[i] = data[i]; for (int i = 0; i < it; i++) newData[i] = data[i];
// Memory loaded version for jar_mod_load_file() // Memory loaded version for jar_mod_load_file()
if (dataSize && dataSize < 32*1024*1024) if (dataSize && (dataSize < 32*1024*1024))
{ {
ctxMod->modfilesize = dataSize; ctxMod->modfilesize = dataSize;
ctxMod->modfile = newData; ctxMod->modfile = newData;
@ -2028,22 +2036,86 @@ void SetAudioStreamBufferSizeDefault(int size)
AUDIO.Buffer.defaultSize = size; AUDIO.Buffer.defaultSize = size;
} }
// Audio thread callback to request new data
void SetAudioStreamCallback(AudioStream stream, AudioCallback callback)
{
if (stream.buffer != NULL) stream.buffer->callback = callback;
}
// Add processor to audio stream. Contrary to buffers, the order of processors is important.
// The new processor must be added at the end. As there aren't supposed to be a lot of processors attached to
// a given stream, we iterate through the list to find the end. That way we don't need a pointer to the last element.
void AttachAudioStreamProcessor(AudioStream stream, AudioCallback process)
{
ma_mutex_lock(&AUDIO.System.lock);
rAudioProcessor *processor = (rAudioProcessor *)RL_CALLOC(1, sizeof(rAudioProcessor));
processor->process = process;
rAudioProcessor *last = stream.buffer->processor;
while (last && last->next)
{
last = last->next;
}
if (last)
{
processor->prev = last;
last->next = processor;
}
else stream.buffer->processor = processor;
ma_mutex_unlock(&AUDIO.System.lock);
}
void DetachAudioStreamProcessor(AudioStream stream, AudioCallback process)
{
ma_mutex_lock(&AUDIO.System.lock);
rAudioProcessor *processor = stream.buffer->processor;
while (processor)
{
rAudioProcessor *next = processor->next;
rAudioProcessor *prev = processor->prev;
if (processor->process == process)
{
if (stream.buffer->processor == processor) stream.buffer->processor = next;
if (prev) prev->next = next;
if (next) next->prev = prev;
RL_FREE(processor);
}
processor = next;
}
ma_mutex_unlock(&AUDIO.System.lock);
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Definition // Module specific Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Log callback function // Log callback function
static void OnLog(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message) static void OnLog(void *pUserData, ma_uint32 level, const char *pMessage)
{ {
(void)pContext; TRACELOG(LOG_WARNING, "miniaudio: %s", pMessage); // All log messages from miniaudio are errors
(void)pDevice;
TRACELOG(LOG_WARNING, "miniaudio: %s", message); // All log messages from miniaudio are errors
} }
// Reads audio data from an AudioBuffer object in internal format. // Reads audio data from an AudioBuffer object in internal format.
static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer, void *framesOut, ma_uint32 frameCount) static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer, void *framesOut, ma_uint32 frameCount)
{ {
// Using audio buffer callback
if (audioBuffer->callback)
{
audioBuffer->callback(framesOut, frameCount);
audioBuffer->framesProcessed += frameCount;
return frameCount;
}
ma_uint32 subBufferSizeInFrames = (audioBuffer->sizeInFrames > 1)? audioBuffer->sizeInFrames/2 : audioBuffer->sizeInFrames; ma_uint32 subBufferSizeInFrames = (audioBuffer->sizeInFrames > 1)? audioBuffer->sizeInFrames/2 : audioBuffer->sizeInFrames;
ma_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames; ma_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames;
@ -2055,7 +2127,7 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0]; isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0];
isSubBufferProcessed[1] = audioBuffer->isSubBufferProcessed[1]; isSubBufferProcessed[1] = audioBuffer->isSubBufferProcessed[1];
ma_uint32 frameSizeInBytes = ma_get_bytes_per_frame(audioBuffer->converter.config.formatIn, audioBuffer->converter.config.channelsIn); ma_uint32 frameSizeInBytes = ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn);
// Fill out every frame until we find a buffer that's marked as processed. Then fill the remainder with 0 // Fill out every frame until we find a buffer that's marked as processed. Then fill the remainder with 0
ma_uint32 framesRead = 0; ma_uint32 framesRead = 0;
@ -2135,20 +2207,21 @@ static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, f
// detail to remember here is that we never, ever attempt to read more input data than is required for the specified number of output // detail to remember here is that we never, ever attempt to read more input data than is required for the specified number of output
// frames. This can be achieved with ma_data_converter_get_required_input_frame_count(). // frames. This can be achieved with ma_data_converter_get_required_input_frame_count().
ma_uint8 inputBuffer[4096] = { 0 }; ma_uint8 inputBuffer[4096] = { 0 };
ma_uint32 inputBufferFrameCap = sizeof(inputBuffer)/ma_get_bytes_per_frame(audioBuffer->converter.config.formatIn, audioBuffer->converter.config.channelsIn); ma_uint32 inputBufferFrameCap = sizeof(inputBuffer)/ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn);
ma_uint32 totalOutputFramesProcessed = 0; ma_uint32 totalOutputFramesProcessed = 0;
while (totalOutputFramesProcessed < frameCount) while (totalOutputFramesProcessed < frameCount)
{ {
ma_uint64 outputFramesToProcessThisIteration = frameCount - totalOutputFramesProcessed; ma_uint64 outputFramesToProcessThisIteration = frameCount - totalOutputFramesProcessed;
ma_uint64 inputFramesToProcessThisIteration = 0;
ma_uint64 inputFramesToProcessThisIteration = ma_data_converter_get_required_input_frame_count(&audioBuffer->converter, outputFramesToProcessThisIteration); ma_result result = ma_data_converter_get_required_input_frame_count(&audioBuffer->converter, outputFramesToProcessThisIteration, &inputFramesToProcessThisIteration);
if (inputFramesToProcessThisIteration > inputBufferFrameCap) if (inputFramesToProcessThisIteration > inputBufferFrameCap)
{ {
inputFramesToProcessThisIteration = inputBufferFrameCap; inputFramesToProcessThisIteration = inputBufferFrameCap;
} }
float *runningFramesOut = framesOut + (totalOutputFramesProcessed*audioBuffer->converter.config.channelsOut); float *runningFramesOut = framesOut + (totalOutputFramesProcessed*audioBuffer->converter.channelsOut);
/* At this point we can convert the data to our mixing format. */ /* At this point we can convert the data to our mixing format. */
ma_uint64 inputFramesProcessedThisIteration = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, (ma_uint32)inputFramesToProcessThisIteration); /* Safe cast. */ ma_uint64 inputFramesProcessedThisIteration = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, (ma_uint32)inputFramesToProcessThisIteration); /* Safe cast. */
@ -2217,6 +2290,14 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
float *framesOut = (float *)pFramesOut + (framesRead*AUDIO.System.device.playback.channels); float *framesOut = (float *)pFramesOut + (framesRead*AUDIO.System.device.playback.channels);
float *framesIn = tempBuffer; float *framesIn = tempBuffer;
// Apply processors chain if defined
rAudioProcessor *processor = audioBuffer->processor;
while (processor)
{
processor->process(framesIn, framesJustRead);
processor = processor->next;
}
MixAudioFrames(framesOut, framesIn, framesJustRead, audioBuffer); MixAudioFrames(framesOut, framesIn, framesJustRead, audioBuffer);
framesToRead -= framesJustRead; framesToRead -= framesJustRead;
@ -2257,41 +2338,44 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
ma_mutex_unlock(&AUDIO.System.lock); ma_mutex_unlock(&AUDIO.System.lock);
} }
// This is the main mixing function. Mixing is pretty simple in this project - it's just an accumulation. // Main mixing function, pretty simple in this project, just an accumulation
// NOTE: framesOut is both an input and an output. It will be initially filled with zeros outside of this function. // NOTE: framesOut is both an input and an output, it is initially filled with zeros outside of this function
static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer) static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer)
{ {
const float localVolume = buffer->volume; const float localVolume = buffer->volume;
const ma_uint32 channels = AUDIO.System.device.playback.channels;
const ma_uint32 nChannels = AUDIO.System.device.playback.channels; if (channels == 2) // We consider panning
if (nChannels == 2)
{ {
const float left = buffer->pan; const float left = buffer->pan;
const float right = 1.0f - left; const float right = 1.0f - left;
// fast sine approximation in [0..1] for pan law: y = 0.5f * x * (3 - x * x); // Fast sine approximation in [0..1] for pan law: y = 0.5f*x*(3 - x*x);
const float levels[2] = { localVolume*0.5f*left*(3.0f-left*left), localVolume*0.5f*right*(3.0f-right*right) }; const float levels[2] = { localVolume*0.5f*left*(3.0f - left*left), localVolume*0.5f*right*(3.0f - right*right) };
float *frameOut = framesOut; float *frameOut = framesOut;
const float *frameIn = framesIn; const float *frameIn = framesIn;
for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame)
for (ma_uint32 frame = 0; frame < frameCount; frame++)
{ {
frameOut[0] += (frameIn[0]*levels[0]); frameOut[0] += (frameIn[0]*levels[0]);
frameOut[1] += (frameIn[1]*levels[1]); frameOut[1] += (frameIn[1]*levels[1]);
frameOut += 2; frameOut += 2;
frameIn += 2; frameIn += 2;
} }
} }
else // pan is kinda meaningless else // We do not consider panning
{ {
for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame) for (ma_uint32 frame = 0; frame < frameCount; frame++)
{ {
for (ma_uint32 iChannel = 0; iChannel < nChannels; ++iChannel) for (ma_uint32 c = 0; c < channels; c++)
{ {
float *frameOut = framesOut + (iFrame * nChannels); float *frameOut = framesOut + (frame*channels);
const float *frameIn = framesIn + (iFrame * nChannels); const float *frameIn = framesIn + (frame*channels);
frameOut[iChannel] += (frameIn[iChannel] * localVolume); // Output accumulates input multiplied by volume to provided output (usually 0)
frameOut[c] += (frameIn[c]*localVolume);
} }
} }
} }

View File

@ -33,8 +33,8 @@
* *
* OPTIONAL DEPENDENCIES (included): * OPTIONAL DEPENDENCIES (included):
* [rcore] msf_gif (Miles Fogle) for GIF recording * [rcore] msf_gif (Miles Fogle) for GIF recording
* [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorythm * [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm
* [rcore] sdefl (Micha Mettke) for DEFLATE compression algorythm * [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm
* [rtextures] stb_image (Sean Barret) for images loading (BMP, TGA, PNG, JPEG, HDR...) * [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_write (Sean Barret) for image writing (BMP, TGA, PNG, JPG)
* [rtextures] stb_image_resize (Sean Barret) for image resizing algorithms * [rtextures] stb_image_resize (Sean Barret) for image resizing algorithms
@ -177,10 +177,10 @@
// Structures Definition // Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Boolean type // Boolean type
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
#include <stdbool.h> #include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool) #elif !defined(__cplusplus) && !defined(bool)
typedef enum bool { false, true } bool; typedef enum bool { false = 0, true = !false } bool;
#define RL_BOOL_TYPE #define RL_BOOL_TYPE
#endif #endif
@ -322,7 +322,7 @@ typedef struct Mesh {
// Vertex attributes data // Vertex attributes data
float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0) float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
float *texcoords2; // Vertex second texture coordinates (useful for lightmaps) (shader-location = 5) float *texcoords2; // Vertex texture second coordinates (UV - 2 components per vertex) (shader-location = 5)
float *normals; // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2) float *normals; // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
float *tangents; // Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4) float *tangents; // Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4)
unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3) unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
@ -425,11 +425,15 @@ typedef struct Wave {
void *data; // Buffer data pointer void *data; // Buffer data pointer
} Wave; } Wave;
// Opaque structs declaration
// NOTE: Actual structs are defined internally in raudio module
typedef struct rAudioBuffer rAudioBuffer; typedef struct rAudioBuffer rAudioBuffer;
typedef struct rAudioProcessor rAudioProcessor;
// AudioStream, custom audio stream // AudioStream, custom audio stream
typedef struct AudioStream { typedef struct AudioStream {
rAudioBuffer *buffer; // Pointer to internal data used by the audio system rAudioBuffer *buffer; // Pointer to internal data used by the audio system
rAudioProcessor *processor; // Pointer to internal data processor, useful for audio effects
unsigned int sampleRate; // Frequency (samples per second) unsigned int sampleRate; // Frequency (samples per second)
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported) unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
@ -945,6 +949,8 @@ RLAPI Vector2 GetWindowScaleDPI(void); // Get window
RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the primary monitor RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the primary monitor
RLAPI void SetClipboardText(const char *text); // Set clipboard text content RLAPI void SetClipboardText(const char *text); // Set clipboard text content
RLAPI const char *GetClipboardText(void); // Get clipboard text content RLAPI const char *GetClipboardText(void); // Get clipboard text 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
// Custom frame control functions // Custom frame control functions
// NOTE: Those functions are intended for advance users that want full control over the frame processing // NOTE: Those functions are intended for advance users that want full control over the frame processing
@ -1033,9 +1039,10 @@ RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
// Files management functions // Files management functions
RLAPI unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read) RLAPI unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // 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, unsigned int bytesToWrite); // Save data to file from byte array (write), returns true on success RLAPI bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write), returns true on success
RLAPI bool ExportDataAsCode(const char *data, unsigned int size, 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 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 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 bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
@ -1050,19 +1057,19 @@ RLAPI const char *GetDirectoryPath(const char *filePath); // Get full pa
RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given 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 *GetWorkingDirectory(void); // Get current working directory (uses static string)
RLAPI const char *GetApplicationDirectory(void); // Get the directory if the running application (uses static string) RLAPI const char *GetApplicationDirectory(void); // Get the directory if the running application (uses static string)
RLAPI char **GetDirectoryFiles(const char *dirPath, int *count); // Get filenames in a directory path (memory should be freed) RLAPI char **GetDirectoryFiles(const char *dirPath, int *count); // Get filenames in a directory path (memory must be freed)
RLAPI void ClearDirectoryFiles(void); // Clear directory files paths buffers (free memory) RLAPI void ClearDirectoryFiles(void); // Clear directory files paths buffers (free memory)
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
RLAPI char **GetDroppedFiles(int *count); // Get dropped files names (memory should be freed) RLAPI char **GetDroppedFiles(int *count); // Get dropped files names (memory must be freed)
RLAPI void ClearDroppedFiles(void); // Clear dropped files paths buffer (free memory) RLAPI void ClearDroppedFiles(void); // Clear dropped files paths buffer (free memory)
RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time) RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time)
// Compression/Encoding functionality // Compression/Encoding functionality
RLAPI unsigned char *CompressData(const unsigned char *data, int dataLength, int *compDataLength); // Compress data (DEFLATE algorithm) 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 compDataLength, int *dataLength); // Decompress data (DEFLATE algorithm) 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 dataLength, int *outputLength); // Encode data to Base64 string 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 *outputLength); // Decode Base64 string data RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
// Persistent storage management // Persistent storage management
RLAPI bool SaveStorageValue(unsigned int position, int value); // Save integer value to storage file (to defined position), returns true on success RLAPI bool SaveStorageValue(unsigned int position, int value); // Save integer value to storage file (to defined position), returns true on success
@ -1331,7 +1338,6 @@ RLAPI void UnloadFontData(GlyphInfo *chars, int glyphCount);
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM) RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
// Text drawing functions // Text drawing functions
RLAPI void DrawFPS(int posX, int posY); // Draw current FPS RLAPI void DrawFPS(int posX, int posY); // Draw current FPS
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
@ -1465,7 +1471,6 @@ RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2);
RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere 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 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 GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box
RLAPI RayCollision GetRayCollisionModel(Ray ray, Model model); // Get collision info between ray and model
RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh 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 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 RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad
@ -1473,6 +1478,7 @@ RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Audio Loading and Playing Functions (Module: audio) // Audio Loading and Playing Functions (Module: audio)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
typedef void (*AudioCallback)(void *bufferData, unsigned int frames);
// Audio device management functions // Audio device management functions
RLAPI void InitAudioDevice(void); // Initialize audio device and context RLAPI void InitAudioDevice(void); // Initialize audio device and context
@ -1540,6 +1546,10 @@ RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set vol
RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base 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 (0.5 is centered)
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams 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
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor);
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor);
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View File

@ -18,7 +18,7 @@
* - Functions are always self-contained, no function use another raymath function inside, * - Functions are always self-contained, no function use another raymath function inside,
* required code is directly re-implemented inside * required code is directly re-implemented inside
* - Functions input parameters are always received by value (2 unavoidable exceptions) * - Functions input parameters are always received by value (2 unavoidable exceptions)
* - Functions use always a "result" anmed variable for return * - Functions use always a "result" variable for return
* - Functions are always defined inline * - Functions are always defined inline
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience) * - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
* *
@ -77,6 +77,10 @@
#define PI 3.14159265358979323846f #define PI 3.14159265358979323846f
#endif #endif
#ifndef EPSILON
#define EPSILON 0.000001f
#endif
#ifndef DEG2RAD #ifndef DEG2RAD
#define DEG2RAD (PI/180.0f) #define DEG2RAD (PI/180.0f)
#endif #endif
@ -194,6 +198,14 @@ RMAPI float Remap(float value, float inputStart, float inputEnd, float outputSta
return result; return result;
} }
// Check whether two given floats are almost equal
RMAPI int FloatEquals(float x, float y)
{
int result = (fabsf(x - y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y))));
return result;
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition - Vector2 math // Module Functions Definition - Vector2 math
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -345,16 +357,16 @@ RMAPI Vector2 Vector2Normalize(Vector2 v)
// Transforms a Vector2 by a given Matrix // Transforms a Vector2 by a given Matrix
RMAPI Vector2 Vector2Transform(Vector2 v, Matrix mat) RMAPI Vector2 Vector2Transform(Vector2 v, Matrix mat)
{ {
Vector2 result = { 0 }; Vector2 result = { 0 };
float x = v.x; float x = v.x;
float y = v.y; float y = v.y;
float z = 0; float z = 0;
result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12;
result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13;
return result; return result;
} }
// Calculate linear interpolation between two vectors // Calculate linear interpolation between two vectors
@ -414,6 +426,62 @@ RMAPI Vector2 Vector2MoveTowards(Vector2 v, Vector2 target, float maxDistance)
return result; return result;
} }
// Invert the given vector
RMAPI Vector2 Vector2Invert(Vector2 v)
{
Vector2 result = { 1.0f/v.x, 1.0f/v.y };
return result;
}
// Clamp the components of the vector between
// min and max values specified by the given vectors
RMAPI Vector2 Vector2Clamp(Vector2 v, Vector2 min, Vector2 max)
{
Vector2 result = { 0 };
result.x = fminf(max.x, fmaxf(min.x, v.x));
result.y = fminf(max.y, fmaxf(min.y, v.y));
return result;
}
// Clamp the magnitude of the vector between two min and max values
RMAPI Vector2 Vector2ClampValue(Vector2 v, float min, float max)
{
Vector2 result = { 0 };
float length = (v.x*v.x) + (v.y*v.y);
if (length > 0.0f)
{
length = sqrtf(length);
if (length < min)
{
float scale = min/length;
result.x = v.x*scale;
result.y = v.y*scale;
}
else if (length > max)
{
float scale = max/length;
result.x = v.x*scale;
result.y = v.y*scale;
}
}
return result;
}
// Check whether two given vectors are almost equal
RMAPI int Vector2Equals(Vector2 p, Vector2 q)
{
int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y)))));
return result;
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition - Vector3 math // Module Functions Definition - Vector3 math
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -498,14 +566,14 @@ RMAPI Vector3 Vector3Perpendicular(Vector3 v)
float min = (float) fabs(v.x); float min = (float) fabs(v.x);
Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f}; Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f};
if (fabs(v.y) < min) if (fabsf(v.y) < min)
{ {
min = (float) fabs(v.y); min = (float) fabs(v.y);
Vector3 tmp = {0.0f, 1.0f, 0.0f}; Vector3 tmp = {0.0f, 1.0f, 0.0f};
cardinalAxis = tmp; cardinalAxis = tmp;
} }
if (fabs(v.z) < min) if (fabsf(v.z) < min)
{ {
Vector3 tmp = {0.0f, 0.0f, 1.0f}; Vector3 tmp = {0.0f, 0.0f, 1.0f};
cardinalAxis = tmp; cardinalAxis = tmp;
@ -851,6 +919,92 @@ RMAPI float3 Vector3ToFloatV(Vector3 v)
return buffer; return buffer;
} }
// Invert the given vector
RMAPI Vector3 Vector3Invert(Vector3 v)
{
Vector3 result = { 1.0f/v.x, 1.0f/v.y, 1.0f/v.z };
return result;
}
// Clamp the components of the vector between
// min and max values specified by the given vectors
RMAPI Vector3 Vector3Clamp(Vector3 v, Vector3 min, Vector3 max)
{
Vector3 result = { 0 };
result.x = fminf(max.x, fmaxf(min.x, v.x));
result.y = fminf(max.y, fmaxf(min.y, v.y));
result.z = fminf(max.z, fmaxf(min.z, v.z));
return result;
}
// Clamp the magnitude of the vector between two values
RMAPI Vector3 Vector3ClampValue(Vector3 v, float min, float max)
{
Vector3 result = { 0 };
float length = (v.x*v.x) + (v.y*v.y) + (v.z*v.z);
if (length > 0.0f)
{
length = sqrtf(length);
if (length < min)
{
float scale = min/length;
result.x = v.x*scale;
result.y = v.y*scale;
result.z = v.z*scale;
}
else if (length > max)
{
float scale = max/length;
result.x = v.x*scale;
result.y = v.y*scale;
result.z = v.z*scale;
}
}
return result;
}
// Check whether two given vectors are almost equal
RMAPI int Vector3Equals(Vector3 p, Vector3 q)
{
int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&
((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z)))));
return result;
}
// Compute the direction of a refracted ray where v specifies the
// normalized direction of the incoming ray, n specifies the
// normalized normal vector of the interface of two optical media,
// and r specifies the ratio of the refractive index of the medium
// from where the ray comes to the refractive index of the medium
// on the other side of the surface
RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r)
{
Vector3 result = { 0 };
float dot = v.x*n.x + v.y*n.y + v.z*n.z;
float d = 1.0f - r*r*(1.0f - dot*dot);
if (d >= 0.0f)
{
d = sqrtf(d);
v.x = r*v.x - (r*dot + d)*n.x;
v.y = r*v.y - (r*dot + d)*n.y;
v.z = r*v.z - (r*dot + d)*n.z;
result = v;
}
return result;
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition - Matrix math // Module Functions Definition - Matrix math
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -956,45 +1110,6 @@ RMAPI Matrix MatrixInvert(Matrix mat)
return result; return result;
} }
// Normalize provided matrix
RMAPI Matrix MatrixNormalize(Matrix mat)
{
Matrix result = { 0 };
// Cache the matrix values (speed optimization)
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
// MatrixDeterminant(mat)
float det = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 +
a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 +
a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 +
a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 +
a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 +
a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
result.m0 = mat.m0/det;
result.m1 = mat.m1/det;
result.m2 = mat.m2/det;
result.m3 = mat.m3/det;
result.m4 = mat.m4/det;
result.m5 = mat.m5/det;
result.m6 = mat.m6/det;
result.m7 = mat.m7/det;
result.m8 = mat.m8/det;
result.m9 = mat.m9/det;
result.m10 = mat.m10/det;
result.m11 = mat.m11/det;
result.m12 = mat.m12/det;
result.m13 = mat.m13/det;
result.m14 = mat.m14/det;
result.m15 = mat.m15/det;
return result;
}
// Get identity matrix // Get identity matrix
RMAPI Matrix MatrixIdentity(void) RMAPI Matrix MatrixIdentity(void)
{ {
@ -1516,7 +1631,7 @@ RMAPI Quaternion QuaternionInvert(Quaternion q)
float lengthSq = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w; float lengthSq = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w;
if (lengthSq != 0.0) if (lengthSq != 0.0f)
{ {
float invLength = 1.0f/lengthSq; float invLength = 1.0f/lengthSq;
@ -1550,12 +1665,10 @@ RMAPI Quaternion QuaternionScale(Quaternion q, float mul)
{ {
Quaternion result = { 0 }; Quaternion result = { 0 };
float qax = q.x, qay = q.y, qaz = q.z, qaw = q.w; result.x = q.x*mul;
result.y = q.y*mul;
result.x = qax*mul + qaw*mul + qay*mul - qaz*mul; result.z = q.z*mul;
result.y = qay*mul + qaw*mul + qaz*mul - qax*mul; result.w = q.w*mul;
result.z = qaz*mul + qaw*mul + qax*mul - qay*mul;
result.w = qaw*mul - qax*mul - qay*mul - qaz*mul;
return result; return result;
} }
@ -1619,14 +1732,14 @@ RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
cosHalfTheta = -cosHalfTheta; cosHalfTheta = -cosHalfTheta;
} }
if (fabs(cosHalfTheta) >= 1.0f) result = q1; if (fabsf(cosHalfTheta) >= 1.0f) result = q1;
else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount); else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount);
else else
{ {
float halfTheta = acosf(cosHalfTheta); float halfTheta = acosf(cosHalfTheta);
float sinHalfTheta = sqrtf(1.0f - cosHalfTheta*cosHalfTheta); float sinHalfTheta = sqrtf(1.0f - cosHalfTheta*cosHalfTheta);
if (fabs(sinHalfTheta) < 0.001f) if (fabsf(sinHalfTheta) < 0.001f)
{ {
result.x = (q1.x*0.5f + q2.x*0.5f); result.x = (q1.x*0.5f + q2.x*0.5f);
result.y = (q1.y*0.5f + q2.y*0.5f); result.y = (q1.y*0.5f + q2.y*0.5f);
@ -1792,7 +1905,7 @@ RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
// Get the rotation angle and axis for a given quaternion // Get the rotation angle and axis for a given quaternion
RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle) RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle)
{ {
if (fabs(q.w) > 1.0f) if (fabsf(q.w) > 1.0f)
{ {
// QuaternionNormalize(q); // QuaternionNormalize(q);
float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
@ -1885,4 +1998,15 @@ RMAPI Quaternion QuaternionTransform(Quaternion q, Matrix mat)
return result; return result;
} }
// Check whether two given quaternions are almost equal
RMAPI int QuaternionEquals(Quaternion p, Quaternion q)
{
int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&
((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) &&
((fabsf(p.w - q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))));
return result;
}
#endif // RAYMATH_H #endif // RAYMATH_H

View File

@ -184,7 +184,7 @@
#include <stdlib.h> // Required for: srand(), rand(), atexit() #include <stdlib.h> // Required for: srand(), rand(), atexit()
#include <stdio.h> // Required for: sprintf() [Used in OpenURL()] #include <stdio.h> // Required for: sprintf() [Used in OpenURL()]
#include <string.h> // Required for: strrchr(), strcmp(), strlen() #include <string.h> // Required for: strrchr(), strcmp(), strlen(), memset()
#include <time.h> // Required for: time() [Used in InitTimer()] #include <time.h> // Required for: time() [Used in InitTimer()]
#include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()] #include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
@ -227,7 +227,7 @@
unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#endif #endif
#endif #endif
#if defined(__linux__) || defined(__FreeBSD__) #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX #include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX
//#define GLFW_EXPOSE_NATIVE_X11 // WARNING: Exposing Xlib.h > X.h results in dup symbols for Font type //#define GLFW_EXPOSE_NATIVE_X11 // WARNING: Exposing Xlib.h > X.h results in dup symbols for Font type
@ -247,6 +247,7 @@
//#include <android/sensor.h> // Required for: Android sensors functions (accelerometer, gyroscope, light...) //#include <android/sensor.h> // Required for: Android sensors functions (accelerometer, gyroscope, light...)
#include <android/window.h> // Required for: AWINDOW_FLAG_FULLSCREEN definition and others #include <android/window.h> // Required for: AWINDOW_FLAG_FULLSCREEN definition and others
#include <android_native_app_glue.h> // Required for: android_app struct and activity management #include <android_native_app_glue.h> // Required for: android_app struct and activity management
#include <jni.h> // Required for: JNIEnv and JavaVM [Used in OpenURL()]
#include <EGL/egl.h> // Native platform windowing system interface #include <EGL/egl.h> // Native platform windowing system interface
//#include <GLES2/gl2.h> // OpenGL ES 2.0 library (not required in this module, only in rlgl) //#include <GLES2/gl2.h> // OpenGL ES 2.0 library (not required in this module, only in rlgl)
@ -411,6 +412,7 @@ typedef struct CoreData {
bool fullscreen; // Check if fullscreen mode is enabled bool fullscreen; // Check if fullscreen mode is enabled
bool shouldClose; // Check if window set for closing bool shouldClose; // Check if window set for closing
bool resizedLastFrame; // Check if window has been resized last frame bool resizedLastFrame; // Check if window has been resized last frame
bool eventWaiting; // Wait for events before ending frame
Point position; // Window position on screen (required on fullscreen toggle) Point position; // Window position on screen (required on fullscreen toggle)
Size display; // Display width and height (monitor, device-screen, LCD, ...) Size display; // Display width and height (monitor, device-screen, LCD, ...)
@ -778,11 +780,15 @@ void InitWindow(int width, int height, const char *title)
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title; if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
// Initialize required global values different than 0 // Initialize global input state
memset(&CORE.Input, 0, sizeof(CORE.Input));
CORE.Input.Keyboard.exitKey = KEY_ESCAPE; CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f }; CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW; CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
CORE.Input.Gamepad.lastButtonPressed = -1; CORE.Input.Gamepad.lastButtonPressed = -1;
#if defined(SUPPORT_EVENTS_WAITING)
CORE.Window.eventWaiting = true;
#endif
#if defined(PLATFORM_ANDROID) #if defined(PLATFORM_ANDROID)
CORE.Window.screen.width = width; CORE.Window.screen.width = width;
@ -1211,39 +1217,39 @@ bool IsWindowState(unsigned int flag)
void ToggleFullscreen(void) void ToggleFullscreen(void)
{ {
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
// NOTE: glfwSetWindowMonitor() doesn't work properly (bugs) // TODO: glfwSetWindowMonitor() doesn't work properly (bugs)
if (!CORE.Window.fullscreen) if (!CORE.Window.fullscreen)
{ {
// Store previous window position (in case we exit fullscreen) // Store previous window position (in case we exit fullscreen)
glfwGetWindowPos(CORE.Window.handle, &CORE.Window.position.x, &CORE.Window.position.y); glfwGetWindowPos(CORE.Window.handle, &CORE.Window.position.x, &CORE.Window.position.y);
int monitorCount = 0; int monitorCount = 0;
GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
int monitorIndex = GetCurrentMonitor(); int monitorIndex = GetCurrentMonitor();
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
// Use current monitor, so we correctly get the display the window is on // Use current monitor, so we correctly get the display the window is on
GLFWmonitor* monitor = monitorIndex < monitorCount ? monitors[monitorIndex] : NULL; GLFWmonitor *monitor = (monitorIndex < monitorCount)? monitors[monitorIndex] : NULL;
if (!monitor) if (monitor == NULL)
{ {
TRACELOG(LOG_WARNING, "GLFW: Failed to get monitor"); TRACELOG(LOG_WARNING, "GLFW: Failed to get monitor");
CORE.Window.fullscreen = false; // Toggle fullscreen flag CORE.Window.fullscreen = false;
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE; CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
glfwSetWindowMonitor(CORE.Window.handle, NULL, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE); glfwSetWindowMonitor(CORE.Window.handle, NULL, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
return;
} }
else
{
CORE.Window.fullscreen = true;
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
CORE.Window.fullscreen = true; // Toggle fullscreen flag glfwSetWindowMonitor(CORE.Window.handle, monitor, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
CORE.Window.flags |= FLAG_FULLSCREEN_MODE; }
glfwSetWindowMonitor(CORE.Window.handle, monitor, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
} }
else else
{ {
CORE.Window.fullscreen = false; // Toggle fullscreen flag CORE.Window.fullscreen = false;
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE; CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
glfwSetWindowMonitor(CORE.Window.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE); glfwSetWindowMonitor(CORE.Window.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
@ -1934,6 +1940,29 @@ const char *GetMonitorName(int monitor)
return ""; return "";
} }
// Set clipboard text content
void SetClipboardText(const char *text)
{
#if defined(PLATFORM_DESKTOP)
glfwSetClipboardString(CORE.Window.handle, text);
#endif
#if defined(PLATFORM_WEB)
emscripten_run_script(TextFormat("navigator.clipboard.writeText('%s')", text));
#endif
}
// Enable waiting for events on EndDrawing(), no automatic event polling
void EnableEventWaiting(void)
{
CORE.Window.eventWaiting = true;
}
// Disable waiting for events on EndDrawing(), automatic events polling
RLAPI void DisableEventWaiting(void)
{
CORE.Window.eventWaiting = false;
}
// Get clipboard text content // Get clipboard text content
// NOTE: returned string is allocated and freed by GLFW // NOTE: returned string is allocated and freed by GLFW
const char *GetClipboardText(void) const char *GetClipboardText(void)
@ -1947,16 +1976,7 @@ const char *GetClipboardText(void)
return NULL; return NULL;
} }
// Set clipboard text content
void SetClipboardText(const char *text)
{
#if defined(PLATFORM_DESKTOP)
glfwSetClipboardString(CORE.Window.handle, text);
#endif
#if defined(PLATFORM_WEB)
emscripten_run_script(TextFormat("navigator.clipboard.writeText('%s')", text));
#endif
}
// Show mouse cursor // Show mouse cursor
void ShowCursor(void) void ShowCursor(void)
@ -2066,8 +2086,9 @@ void EndDrawing(void)
{ {
// Get image data for the current frame (from backbuffer) // Get image data for the current frame (from backbuffer)
// NOTE: This process is quite slow... :( // NOTE: This process is quite slow... :(
unsigned char *screenData = rlReadScreenPixels(CORE.Window.screen.width, CORE.Window.screen.height); Vector2 scale = GetWindowScaleDPI();
msf_gif_frame(&gifState, screenData, 10, 16, CORE.Window.screen.width*4); unsigned char *screenData = rlReadScreenPixels(CORE.Window.render.width*scale.x, CORE.Window.render.height*scale.y);
msf_gif_frame(&gifState, screenData, 10, 16, CORE.Window.render.width*scale.x*4);
RL_FREE(screenData); // Free image data RL_FREE(screenData); // Free image data
} }
@ -2236,8 +2257,10 @@ void BeginTextureMode(RenderTexture2D target)
rlEnableFramebuffer(target.id); // Enable render target rlEnableFramebuffer(target.id); // Enable render target
// Set viewport to framebuffer size // Set viewport and RLGL internal framebuffer size
rlViewport(0, 0, target.texture.width, target.texture.height); rlViewport(0, 0, target.texture.width, target.texture.height);
rlSetFramebufferWidth(target.texture.width);
rlSetFramebufferHeight(target.texture.height);
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
rlLoadIdentity(); // Reset current matrix (projection) rlLoadIdentity(); // Reset current matrix (projection)
@ -2383,8 +2406,8 @@ VrStereoConfig LoadVrStereoConfig(VrDeviceInfo device)
// Fovy is normally computed with: 2*atan2f(device.vScreenSize, 2*device.eyeToScreenDistance) // Fovy is normally computed with: 2*atan2f(device.vScreenSize, 2*device.eyeToScreenDistance)
// ...but with lens distortion it is increased (see Oculus SDK Documentation) // ...but with lens distortion it is increased (see Oculus SDK Documentation)
//float fovy = 2.0f*atan2f(device.vScreenSize*0.5f*distortionScale, device.eyeToScreenDistance); // Really need distortionScale? float fovy = 2.0f*atan2f(device.vScreenSize*0.5f*distortionScale, device.eyeToScreenDistance); // Really need distortionScale?
float fovy = 2.0f*(float)atan2f(device.vScreenSize*0.5f, device.eyeToScreenDistance); // float fovy = 2.0f*(float)atan2f(device.vScreenSize*0.5f, device.eyeToScreenDistance);
// Compute camera projection matrices // Compute camera projection matrices
float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1] float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1]
@ -2710,7 +2733,7 @@ void SetTargetFPS(int fps)
if (fps < 1) CORE.Time.target = 0.0; if (fps < 1) CORE.Time.target = 0.0;
else CORE.Time.target = 1.0/(double)fps; else CORE.Time.target = 1.0/(double)fps;
TRACELOG(LOG_INFO, "TIMER: Target time per frame: %02.03f milliseconds", (float)CORE.Time.target*1000); TRACELOG(LOG_INFO, "TIMER: Target time per frame: %02.03f milliseconds", (float)CORE.Time.target*1000.0f);
} }
// Get current FPS // Get current FPS
@ -2787,8 +2810,9 @@ void SetConfigFlags(unsigned int flags)
void TakeScreenshot(const char *fileName) void TakeScreenshot(const char *fileName)
{ {
#if defined(SUPPORT_MODULE_RTEXTURES) #if defined(SUPPORT_MODULE_RTEXTURES)
unsigned char *imgData = rlReadScreenPixels(CORE.Window.render.width, CORE.Window.render.height); Vector2 scale = GetWindowScaleDPI();
Image image = { imgData, CORE.Window.render.width, CORE.Window.render.height, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; unsigned char *imgData = rlReadScreenPixels(CORE.Window.render.width*scale.x, CORE.Window.render.height*scale.y);
Image image = { imgData, CORE.Window.render.width*scale.x, CORE.Window.render.height*scale.y, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
char path[2048] = { 0 }; char path[2048] = { 0 };
strcpy(path, TextFormat("%s/%s", CORE.Storage.basePath, fileName)); strcpy(path, TextFormat("%s/%s", CORE.Storage.basePath, fileName));
@ -2943,7 +2967,7 @@ const char *GetFileName(const char *filePath)
// Get filename string without extension (uses static string) // Get filename string without extension (uses static string)
const char *GetFileNameWithoutExt(const char *filePath) const char *GetFileNameWithoutExt(const char *filePath)
{ {
#define MAX_FILENAMEWITHOUTEXT_LENGTH 128 #define MAX_FILENAMEWITHOUTEXT_LENGTH 256
static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH] = { 0 }; static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH] = { 0 };
memset(fileName, 0, MAX_FILENAMEWITHOUTEXT_LENGTH); memset(fileName, 0, MAX_FILENAMEWITHOUTEXT_LENGTH);
@ -3222,8 +3246,8 @@ long GetFileModTime(const char *fileName)
return 0; return 0;
} }
// Compress data (DEFLATE algorythm) // Compress data (DEFLATE algorithm)
unsigned char *CompressData(const unsigned char *data, int dataLength, int *compDataLength) unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize)
{ {
#define COMPRESSION_QUALITY_DEFLATE 8 #define COMPRESSION_QUALITY_DEFLATE 8
@ -3232,40 +3256,40 @@ unsigned char *CompressData(const unsigned char *data, int dataLength, int *comp
#if defined(SUPPORT_COMPRESSION_API) #if defined(SUPPORT_COMPRESSION_API)
// Compress data and generate a valid DEFLATE stream // Compress data and generate a valid DEFLATE stream
struct sdefl sdefl = { 0 }; struct sdefl sdefl = { 0 };
int bounds = sdefl_bound(dataLength); int bounds = sdefl_bound(dataSize);
compData = (unsigned char *)RL_CALLOC(bounds, 1); compData = (unsigned char *)RL_CALLOC(bounds, 1);
*compDataLength = sdeflate(&sdefl, compData, data, dataLength, COMPRESSION_QUALITY_DEFLATE); // Compression level 8, same as stbwi *compDataSize = sdeflate(&sdefl, compData, data, dataSize, COMPRESSION_QUALITY_DEFLATE); // Compression level 8, same as stbwi
TraceLog(LOG_INFO, "SYSTEM: Compress data: Original size: %i -> Comp. size: %i", dataLength, *compDataLength); TraceLog(LOG_INFO, "SYSTEM: Compress data: Original size: %i -> Comp. size: %i", dataSize, *compDataSize);
#endif #endif
return compData; return compData;
} }
// Decompress data (DEFLATE algorythm) // Decompress data (DEFLATE algorithm)
unsigned char *DecompressData(const unsigned char *compData, int compDataLength, int *dataLength) unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize)
{ {
unsigned char *data = NULL; unsigned char *data = NULL;
#if defined(SUPPORT_COMPRESSION_API) #if defined(SUPPORT_COMPRESSION_API)
// Decompress data from a valid DEFLATE stream // Decompress data from a valid DEFLATE stream
data = RL_CALLOC(MAX_DECOMPRESSION_SIZE*1024*1024, 1); data = RL_CALLOC(MAX_DECOMPRESSION_SIZE*1024*1024, 1);
int length = sinflate(data, MAX_DECOMPRESSION_SIZE, compData, compDataLength); int length = sinflate(data, MAX_DECOMPRESSION_SIZE, compData, compDataSize);
unsigned char *temp = RL_REALLOC(data, length); unsigned char *temp = RL_REALLOC(data, length);
if (temp != NULL) data = temp; if (temp != NULL) data = temp;
else TRACELOG(LOG_WARNING, "SYSTEM: Failed to re-allocate required decompression memory"); else TRACELOG(LOG_WARNING, "SYSTEM: Failed to re-allocate required decompression memory");
*dataLength = length; *dataSize = length;
TraceLog(LOG_INFO, "SYSTEM: Decompress data: Comp. size: %i -> Original size: %i", compDataLength, *dataLength); TraceLog(LOG_INFO, "SYSTEM: Decompress data: Comp. size: %i -> Original size: %i", compDataSize, *dataSize);
#endif #endif
return data; return data;
} }
// Encode data to Base64 string // Encode data to Base64 string
char *EncodeDataBase64(const unsigned char *data, int dataLength, int *outputLength) char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize)
{ {
static const unsigned char base64encodeTable[] = { static const unsigned char base64encodeTable[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
@ -3275,17 +3299,17 @@ char *EncodeDataBase64(const unsigned char *data, int dataLength, int *outputLen
static const int modTable[] = { 0, 2, 1 }; static const int modTable[] = { 0, 2, 1 };
*outputLength = 4*((dataLength + 2)/3); *outputSize = 4*((dataSize + 2)/3);
char *encodedData = RL_MALLOC(*outputLength); char *encodedData = RL_MALLOC(*outputSize);
if (encodedData == NULL) return NULL; if (encodedData == NULL) return NULL;
for (int i = 0, j = 0; i < dataLength;) for (int i = 0, j = 0; i < dataSize;)
{ {
unsigned int octetA = (i < dataLength)? (unsigned char)data[i++] : 0; unsigned int octetA = (i < dataSize)? (unsigned char)data[i++] : 0;
unsigned int octetB = (i < dataLength)? (unsigned char)data[i++] : 0; unsigned int octetB = (i < dataSize)? (unsigned char)data[i++] : 0;
unsigned int octetC = (i < dataLength)? (unsigned char)data[i++] : 0; unsigned int octetC = (i < dataSize)? (unsigned char)data[i++] : 0;
unsigned int triple = (octetA << 0x10) + (octetB << 0x08) + octetC; unsigned int triple = (octetA << 0x10) + (octetB << 0x08) + octetC;
@ -3295,13 +3319,13 @@ char *EncodeDataBase64(const unsigned char *data, int dataLength, int *outputLen
encodedData[j++] = base64encodeTable[(triple >> 0*6) & 0x3F]; encodedData[j++] = base64encodeTable[(triple >> 0*6) & 0x3F];
} }
for (int i = 0; i < modTable[dataLength%3]; i++) encodedData[*outputLength - 1 - i] = '='; // Padding character for (int i = 0; i < modTable[dataSize%3]; i++) encodedData[*outputSize - 1 - i] = '='; // Padding character
return encodedData; return encodedData;
} }
// Decode Base64 string data // Decode Base64 string data
unsigned char *DecodeDataBase64(const unsigned char *data, int *outputLength) unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
{ {
static const unsigned char base64decodeTable[] = { static const unsigned char base64decodeTable[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -3311,21 +3335,21 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputLength)
}; };
// Get output size of Base64 input data // Get output size of Base64 input data
int outLength = 0; int outSize = 0;
for (int i = 0; data[4*i] != 0; i++) for (int i = 0; data[4*i] != 0; i++)
{ {
if (data[4*i + 3] == '=') if (data[4*i + 3] == '=')
{ {
if (data[4*i + 2] == '=') outLength += 1; if (data[4*i + 2] == '=') outSize += 1;
else outLength += 2; else outSize += 2;
} }
else outLength += 3; else outSize += 3;
} }
// Allocate memory to store decoded Base64 data // Allocate memory to store decoded Base64 data
unsigned char *decodedData = (unsigned char *)RL_MALLOC(outLength); unsigned char *decodedData = (unsigned char *)RL_MALLOC(outSize);
for (int i = 0; i < outLength/3; i++) for (int i = 0; i < outSize/3; i++)
{ {
unsigned char a = base64decodeTable[(int)data[4*i]]; unsigned char a = base64decodeTable[(int)data[4*i]];
unsigned char b = base64decodeTable[(int)data[4*i + 1]]; unsigned char b = base64decodeTable[(int)data[4*i + 1]];
@ -3337,24 +3361,24 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputLength)
decodedData[3*i + 2] = (c << 6) | d; decodedData[3*i + 2] = (c << 6) | d;
} }
if (outLength%3 == 1) if (outSize%3 == 1)
{ {
int n = outLength/3; int n = outSize/3;
unsigned char a = base64decodeTable[(int)data[4*n]]; unsigned char a = base64decodeTable[(int)data[4*n]];
unsigned char b = base64decodeTable[(int)data[4*n + 1]]; unsigned char b = base64decodeTable[(int)data[4*n + 1]];
decodedData[outLength - 1] = (a << 2) | (b >> 4); decodedData[outSize - 1] = (a << 2) | (b >> 4);
} }
else if (outLength%3 == 2) else if (outSize%3 == 2)
{ {
int n = outLength/3; int n = outSize/3;
unsigned char a = base64decodeTable[(int)data[4*n]]; unsigned char a = base64decodeTable[(int)data[4*n]];
unsigned char b = base64decodeTable[(int)data[4*n + 1]]; unsigned char b = base64decodeTable[(int)data[4*n + 1]];
unsigned char c = base64decodeTable[(int)data[4*n + 2]]; unsigned char c = base64decodeTable[(int)data[4*n + 2]];
decodedData[outLength - 2] = (a << 2) | (b >> 4); decodedData[outSize - 2] = (a << 2) | (b >> 4);
decodedData[outLength - 1] = (b << 4) | (c >> 2); decodedData[outSize - 1] = (b << 4) | (c >> 2);
} }
*outputLength = outLength; *outputSize = outSize;
return decodedData; return decodedData;
} }
@ -3480,9 +3504,9 @@ void OpenURL(const char *url)
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
char *cmd = (char *)RL_CALLOC(strlen(url) + 10, sizeof(char)); char *cmd = (char *)RL_CALLOC(strlen(url) + 10, sizeof(char));
#if defined(_WIN32) #if defined(_WIN32)
sprintf(cmd, "explorer %s", url); sprintf(cmd, "explorer \"%s\"", url);
#endif #endif
#if defined(__linux__) || defined(__FreeBSD__) #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
sprintf(cmd, "xdg-open '%s'", url); // Alternatives: firefox, x-www-browser sprintf(cmd, "xdg-open '%s'", url); // Alternatives: firefox, x-www-browser
#endif #endif
#if defined(__APPLE__) #if defined(__APPLE__)
@ -3494,6 +3518,29 @@ void OpenURL(const char *url)
#endif #endif
#if defined(PLATFORM_WEB) #if defined(PLATFORM_WEB)
emscripten_run_script(TextFormat("window.open('%s', '_blank')", url)); emscripten_run_script(TextFormat("window.open('%s', '_blank')", url));
#endif
#if defined(PLATFORM_ANDROID)
JNIEnv *env = NULL;
JavaVM *vm = CORE.Android.app->activity->vm;
(*vm)->AttachCurrentThread(vm, &env, NULL);
jstring urlString = (*env)->NewStringUTF(env, url);
jclass uriClass = (*env)->FindClass(env, "android/net/Uri");
jmethodID uriParse = (*env)->GetStaticMethodID(env, uriClass, "parse", "(Ljava/lang/String;)Landroid/net/Uri;");
jobject uri = (*env)->CallStaticObjectMethod(env, uriClass, uriParse, urlString);
jclass intentClass = (*env)->FindClass(env, "android/content/Intent");
jfieldID actionViewId = (*env)->GetStaticFieldID(env, intentClass, "ACTION_VIEW", "Ljava/lang/String;");
jobject actionView = (*env)->GetStaticObjectField(env, intentClass, actionViewId);
jmethodID newIntent = (*env)->GetMethodID(env, intentClass, "<init>", "(Ljava/lang/String;Landroid/net/Uri;)V");
jobject intent = (*env)->AllocObject(env, intentClass);
(*env)->CallVoidMethod(env, intent, newIntent, actionView, uri);
jclass activityClass = (*env)->FindClass(env, "android/app/Activity");
jmethodID startActivity = (*env)->GetMethodID(env, activityClass, "startActivity", "(Landroid/content/Intent;)V");
(*env)->CallVoidMethod(env, CORE.Android.app->activity->clazz, startActivity, intent);
(*vm)->DetachCurrentThread(vm);
#endif #endif
} }
} }
@ -4848,7 +4895,7 @@ void WaitTime(float ms)
#if defined(_WIN32) #if defined(_WIN32)
Sleep((unsigned int)ms); Sleep((unsigned int)ms);
#endif #endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
struct timespec req = { 0 }; struct timespec req = { 0 };
time_t sec = (int)(ms/1000.0f); time_t sec = (int)(ms/1000.0f);
ms -= (sec*1000); ms -= (sec*1000);
@ -4867,7 +4914,7 @@ void WaitTime(float ms)
double currentTime = 0.0; double currentTime = 0.0;
// Partial busy wait loop (only a fraction of the total wait time) // Partial busy wait loop (only a fraction of the total wait time)
while ((currentTime - previousTime) < busyWait/1000.0f) currentTime = GetTime(); while ((currentTime - previousTime) < (busyWait/1000.0f)) currentTime = GetTime();
#endif #endif
#endif #endif
} }
@ -4883,53 +4930,31 @@ void SwapScreenBuffer(void)
eglSwapBuffers(CORE.Window.device, CORE.Window.surface); eglSwapBuffers(CORE.Window.device, CORE.Window.surface);
#if defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
if (!CORE.Window.gbmSurface || (-1 == CORE.Window.fd) || !CORE.Window.connector || !CORE.Window.crtc)
{ if (!CORE.Window.gbmSurface || (-1 == CORE.Window.fd) || !CORE.Window.connector || !CORE.Window.crtc) TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
abort();
}
struct gbm_bo *bo = gbm_surface_lock_front_buffer(CORE.Window.gbmSurface); struct gbm_bo *bo = gbm_surface_lock_front_buffer(CORE.Window.gbmSurface);
if (!bo) if (!bo) TRACELOG(LOG_ERROR, "DISPLAY: Failed GBM to lock front buffer");
{
TRACELOG(LOG_ERROR, "DISPLAY: Failed GBM to lock front buffer");
abort();
}
uint32_t fb = 0; uint32_t fb = 0;
int result = drmModeAddFB(CORE.Window.fd, CORE.Window.connector->modes[CORE.Window.modeIndex].hdisplay, int result = drmModeAddFB(CORE.Window.fd, CORE.Window.connector->modes[CORE.Window.modeIndex].hdisplay, CORE.Window.connector->modes[CORE.Window.modeIndex].vdisplay, 24, 32, gbm_bo_get_stride(bo), gbm_bo_get_handle(bo).u32, &fb);
CORE.Window.connector->modes[CORE.Window.modeIndex].vdisplay, 24, 32, gbm_bo_get_stride(bo), gbm_bo_get_handle(bo).u32, &fb); if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d", result);
if (0 != result)
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d", result);
abort();
}
result = drmModeSetCrtc(CORE.Window.fd, CORE.Window.crtc->crtc_id, fb, 0, 0, result = drmModeSetCrtc(CORE.Window.fd, CORE.Window.crtc->crtc_id, fb, 0, 0, &CORE.Window.connector->connector_id, 1, &CORE.Window.connector->modes[CORE.Window.modeIndex]);
&CORE.Window.connector->connector_id, 1, &CORE.Window.connector->modes[CORE.Window.modeIndex]); if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d", result);
if (0 != result)
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d", result);
abort();
}
if (CORE.Window.prevFB) if (CORE.Window.prevFB)
{ {
result = drmModeRmFB(CORE.Window.fd, CORE.Window.prevFB); result = drmModeRmFB(CORE.Window.fd, CORE.Window.prevFB);
if (0 != result) if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeRmFB() failed with result: %d", result);
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeRmFB() failed with result: %d", result);
abort();
}
} }
CORE.Window.prevFB = fb; CORE.Window.prevFB = fb;
if (CORE.Window.prevBO) if (CORE.Window.prevBO) gbm_surface_release_buffer(CORE.Window.gbmSurface, CORE.Window.prevBO);
{
gbm_surface_release_buffer(CORE.Window.gbmSurface, CORE.Window.prevBO);
}
CORE.Window.prevBO = bo; CORE.Window.prevBO = bo;
#endif // PLATFORM_DRM #endif // PLATFORM_DRM
#endif // PLATFORM_ANDROID || PLATFORM_RPI || PLATFORM_DRM || PLATFORM_NX #endif // PLATFORM_ANDROID || PLATFORM_RPI || PLATFORM_DRM || PLATFORM_NX
} }
@ -5077,8 +5102,8 @@ void PollInputEvents(void)
} }
// Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather axis) // Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather axis)
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1); CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f);
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1); CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f);
CORE.Input.Gamepad.axisCount = GLFW_GAMEPAD_AXIS_LAST + 1; CORE.Input.Gamepad.axisCount = GLFW_GAMEPAD_AXIS_LAST + 1;
} }
@ -5086,11 +5111,8 @@ void PollInputEvents(void)
CORE.Window.resizedLastFrame = false; CORE.Window.resizedLastFrame = false;
#if defined(SUPPORT_EVENTS_WAITING) if (CORE.Window.eventWaiting) glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
glfwWaitEvents(); else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks)
#else
glfwPollEvents(); // Register keyboard/mouse events (callbacks)... and window events!
#endif
#endif // PLATFORM_DESKTOP #endif // PLATFORM_DESKTOP
#if defined(PLATFORM_WEB) #if defined(PLATFORM_WEB)
@ -5514,7 +5536,8 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
gifRecording = true; gifRecording = true;
gifFrameCounter = 0; gifFrameCounter = 0;
msf_gif_begin(&gifState, CORE.Window.screen.width, CORE.Window.screen.height); Vector2 scale = GetWindowScaleDPI();
msf_gif_begin(&gifState, CORE.Window.render.width*scale.x, CORE.Window.render.height*scale.y);
screenshotCounter++; screenshotCounter++;
TRACELOG(LOG_INFO, "SYSTEM: Start animated GIF recording: %s", TextFormat("screenrec%03i.gif", screenshotCounter)); TRACELOG(LOG_INFO, "SYSTEM: Start animated GIF recording: %s", TextFormat("screenrec%03i.gif", screenshotCounter));
@ -5632,10 +5655,10 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
#endif #endif
} }
// GLFW3 Srolling Callback, runs on mouse wheel // GLFW3 Scrolling Callback, runs on mouse wheel
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset) static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset)
{ {
if (xoffset != 0.0) CORE.Input.Mouse.currentWheelMove = (float)xoffset; if (fabs(xoffset) > fabs(yoffset)) CORE.Input.Mouse.currentWheelMove = (float)xoffset;
else CORE.Input.Mouse.currentWheelMove = (float)yoffset; else CORE.Input.Mouse.currentWheelMove = (float)yoffset;
} }
@ -6227,7 +6250,8 @@ static void InitEvdevInput(void)
{ {
while ((entity = readdir(directory)) != NULL) while ((entity = readdir(directory)) != NULL)
{ {
if (strncmp("event", entity->d_name, strlen("event")) == 0) // Search for devices named "event*" if ((strncmp("event", entity->d_name, strlen("event")) == 0) || // Search for devices named "event*"
(strncmp("mouse", entity->d_name, strlen("mouse")) == 0)) // Search for devices named "mouse*"
{ {
sprintf(path, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name); sprintf(path, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
ConfigureEvdevDevice(path); // Configure the device if appropriate ConfigureEvdevDevice(path); // Configure the device if appropriate
@ -6387,7 +6411,7 @@ static void ConfigureEvdevDevice(char *device)
// Decide what to do with the device // Decide what to do with the device
//------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------
if (worker->isKeyboard && CORE.Input.Keyboard.fd == -1) if (worker->isKeyboard && (CORE.Input.Keyboard.fd == -1))
{ {
// Use the first keyboard encountered. This assumes that a device that says it's a keyboard is just a // Use the first keyboard encountered. This assumes that a device that says it's a keyboard is just a
// keyboard. The keyboard is polled synchronously, whereas other input devices are polled in separate // keyboard. The keyboard is polled synchronously, whereas other input devices are polled in separate
@ -6699,7 +6723,7 @@ static void InitGamepad(void)
{ {
sprintf(gamepadDev, "%s%i", DEFAULT_GAMEPAD_DEV, i); sprintf(gamepadDev, "%s%i", DEFAULT_GAMEPAD_DEV, i);
if ((CORE.Input.Gamepad.streamId[i] = open(gamepadDev, O_RDONLY|O_NONBLOCK)) < 0) if ((CORE.Input.Gamepad.streamId[i] = open(gamepadDev, O_RDONLY | O_NONBLOCK)) < 0)
{ {
// NOTE: Only show message for first gamepad // NOTE: Only show message for first gamepad
if (i == 0) TRACELOG(LOG_WARNING, "RPI: Failed to open Gamepad device, no gamepad available"); if (i == 0) TRACELOG(LOG_WARNING, "RPI: Failed to open Gamepad device, no gamepad available");
@ -6838,7 +6862,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode: %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh, TRACELOG(LOG_TRACE, "DISPLAY: DRM mode: %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh,
(mode->flags & DRM_MODE_FLAG_INTERLACE) ? "interlaced" : "progressive"); (mode->flags & DRM_MODE_FLAG_INTERLACE) ? "interlaced" : "progressive");
if ((mode->hdisplay < width) || (mode->vdisplay < height) || (mode->vrefresh < fps)) if ((mode->hdisplay < width) || (mode->vdisplay < height))
{ {
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode is too small"); TRACELOG(LOG_TRACE, "DISPLAY: DRM mode is too small");
continue; continue;
@ -6850,23 +6874,22 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
continue; continue;
} }
if ((mode->hdisplay >= width) && (mode->vdisplay >= height) && (mode->vrefresh >= fps)) if (nearestIndex < 0)
{ {
const int widthDiff = mode->hdisplay - width; nearestIndex = i;
const int heightDiff = mode->vdisplay - height; continue;
const int fpsDiff = mode->vrefresh - fps; }
if (nearestIndex < 0) const int widthDiff = abs(mode->hdisplay - width);
{ const int heightDiff = abs(mode->vdisplay - height);
nearestIndex = i; const int fpsDiff = abs(mode->vrefresh - fps);
continue;
}
const int nearestWidthDiff = CORE.Window.connector->modes[nearestIndex].hdisplay - width; const int nearestWidthDiff = abs(CORE.Window.connector->modes[nearestIndex].hdisplay - width);
const int nearestHeightDiff = CORE.Window.connector->modes[nearestIndex].vdisplay - height; const int nearestHeightDiff = abs(CORE.Window.connector->modes[nearestIndex].vdisplay - height);
const int nearestFpsDiff = CORE.Window.connector->modes[nearestIndex].vrefresh - fps; const int nearestFpsDiff = abs(CORE.Window.connector->modes[nearestIndex].vrefresh - fps);
if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) nearestIndex = i; if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) {
nearestIndex = i;
} }
} }
@ -6876,6 +6899,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
#if defined(SUPPORT_EVENTS_AUTOMATION) #if defined(SUPPORT_EVENTS_AUTOMATION)
// NOTE: Loading happens over AutomationEvent *events // NOTE: Loading happens over AutomationEvent *events
// TODO: This system should probably be redesigned
static void LoadAutomationEvents(const char *fileName) static void LoadAutomationEvents(const char *fileName)
{ {
//unsigned char fileId[4] = { 0 }; //unsigned char fileId[4] = { 0 };

View File

@ -62,10 +62,10 @@
// NOTE: Below types are required for GESTURES_STANDALONE usage // NOTE: Below types are required for GESTURES_STANDALONE usage
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Boolean type // Boolean type
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
#include <stdbool.h> #include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE) #elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
typedef enum bool { false, true } bool; typedef enum bool { false = 0, true = !false } bool;
#endif #endif
#if !defined(RL_VECTOR2_TYPE) #if !defined(RL_VECTOR2_TYPE)

View File

@ -358,11 +358,11 @@ typedef struct rlRenderBatch {
float currentDepth; // Current depth value for next draw float currentDepth; // Current depth value for next draw
} rlRenderBatch; } rlRenderBatch;
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
#include <stdbool.h> #include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE) #elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
// Boolean type // Boolean type
typedef enum bool { false, true } bool; typedef enum bool { false = 0, true = !false } bool;
#endif #endif
#if !defined(RL_MATRIX_TYPE) #if !defined(RL_MATRIX_TYPE)
@ -598,7 +598,9 @@ RLAPI void rlglInit(int width, int height); // Initialize rlgl (buffer
RLAPI void rlglClose(void); // De-inititialize rlgl (buffers, shaders, textures) RLAPI void rlglClose(void); // De-inititialize rlgl (buffers, shaders, textures)
RLAPI void rlLoadExtensions(void *loader); // Load OpenGL extensions (loader function required) RLAPI void rlLoadExtensions(void *loader); // Load OpenGL extensions (loader function required)
RLAPI int rlGetVersion(void); // Get current OpenGL version RLAPI int rlGetVersion(void); // Get current OpenGL version
RLAPI void rlSetFramebufferWidth(int width); // Set current framebuffer width
RLAPI int rlGetFramebufferWidth(void); // Get default framebuffer width RLAPI int rlGetFramebufferWidth(void); // Get default framebuffer width
RLAPI void rlSetFramebufferHeight(int height); // Set current framebuffer height
RLAPI int rlGetFramebufferHeight(void); // Get default framebuffer height RLAPI int rlGetFramebufferHeight(void); // Get default framebuffer height
RLAPI unsigned int rlGetTextureIdDefault(void); // Get default texture id RLAPI unsigned int rlGetTextureIdDefault(void); // Get default texture id
@ -927,8 +929,8 @@ typedef struct rlglData {
int glBlendDstFactor; // Blending destination factor int glBlendDstFactor; // Blending destination factor
int glBlendEquation; // Blending equation int glBlendEquation; // Blending equation
int framebufferWidth; // Default framebuffer width int framebufferWidth; // Current framebuffer width
int framebufferHeight; // Default framebuffer height int framebufferHeight; // Current framebuffer height
} State; // Renderer state } State; // Renderer state
struct { struct {
@ -1230,6 +1232,7 @@ void rlOrtho(double left, double right, double bottom, double top, double znear,
#endif #endif
// Set the viewport area (transformation from normalized device coordinates to window coordinates) // Set the viewport area (transformation from normalized device coordinates to window coordinates)
// NOTE: We store current viewport dimensions
void rlViewport(int x, int y, int width, int height) void rlViewport(int x, int y, int width, int height)
{ {
glViewport(x, y, width, height); glViewport(x, y, width, height);
@ -1537,7 +1540,7 @@ void rlTextureParameters(unsigned int id, int param, int value)
if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f) else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f)
{ {
TRACELOG(RL_LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, RLGL.ExtSupported.maxAnisotropyLevel); TRACELOG(RL_LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, (int)RLGL.ExtSupported.maxAnisotropyLevel);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
} }
else TRACELOG(RL_LOG_WARNING, "GL: Anisotropic filtering not supported"); else TRACELOG(RL_LOG_WARNING, "GL: Anisotropic filtering not supported");
@ -2219,6 +2222,22 @@ int rlGetVersion(void)
return glVersion; return glVersion;
} }
// Set current framebuffer width
void rlSetFramebufferWidth(int width)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
RLGL.State.framebufferWidth = width;
#endif
}
// Set current framebuffer height
void rlSetFramebufferHeight(int height)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
RLGL.State.framebufferHeight = height;
#endif
}
// Get default framebuffer width // Get default framebuffer width
int rlGetFramebufferWidth(void) int rlGetFramebufferWidth(void)
{ {
@ -2601,6 +2620,9 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
glUseProgram(0); // Unbind shader program glUseProgram(0); // Unbind shader program
} }
// Restore viewport to default measures
if (eyeCount == 2) rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
//------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------
// Reset batch buffers // Reset batch buffers
@ -3088,7 +3110,7 @@ void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if ((texIsPOT) || (RLGL.ExtSupported.texNPOT)) if ((texIsPOT) || (RLGL.ExtSupported.texNPOT))
{ {
//glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorythm: GL_FASTEST, GL_NICEST, GL_DONT_CARE //glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorithm: GL_FASTEST, GL_NICEST, GL_DONT_CARE
glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

View File

@ -3284,10 +3284,10 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota
Color color = model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color; Color color = model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color;
Color colorTint = WHITE; Color colorTint = WHITE;
colorTint.r = (unsigned char)((((float)color.r/255.0)*((float)tint.r/255.0))*255.0f); colorTint.r = (unsigned char)((((float)color.r/255.0f)*((float)tint.r/255.0f))*255.0f);
colorTint.g = (unsigned char)((((float)color.g/255.0)*((float)tint.g/255.0))*255.0f); colorTint.g = (unsigned char)((((float)color.g/255.0f)*((float)tint.g/255.0f))*255.0f);
colorTint.b = (unsigned char)((((float)color.b/255.0)*((float)tint.b/255.0))*255.0f); colorTint.b = (unsigned char)((((float)color.b/255.0f)*((float)tint.b/255.0f))*255.0f);
colorTint.a = (unsigned char)((((float)color.a/255.0)*((float)tint.a/255.0))*255.0f); colorTint.a = (unsigned char)((((float)color.a/255.0f)*((float)tint.a/255.0f))*255.0f);
model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = colorTint; model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = colorTint;
DrawMesh(model.meshes[i], model.materials[model.meshMaterial[i]], model.transform); DrawMesh(model.meshes[i], model.materials[model.meshMaterial[i]], model.transform);
@ -3640,31 +3640,12 @@ RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform)
return collision; return collision;
} }
// Get collision info between ray and model
RayCollision GetRayCollisionModel(Ray ray, Model model)
{
RayCollision collision = { 0 };
for (int m = 0; m < model.meshCount; m++)
{
RayCollision meshHitInfo = GetRayCollisionMesh(ray, model.meshes[m], model.transform);
if (meshHitInfo.hit)
{
// Save the closest hit mesh
if ((!collision.hit) || (collision.distance > meshHitInfo.distance)) collision = meshHitInfo;
}
}
return collision;
}
// Get collision info between ray and triangle // Get collision info between ray and triangle
// NOTE: The points are expected to be in counter-clockwise winding // NOTE: The points are expected to be in counter-clockwise winding
// NOTE: Based on https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm // NOTE: Based on https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3)
{ {
#define EPSILON 0.000001 // A small number #define EPSILON 0.000001f // A small number
RayCollision collision = { 0 }; RayCollision collision = { 0 };
Vector3 edge1 = { 0 }; Vector3 edge1 = { 0 };
@ -4662,7 +4643,6 @@ static Model LoadGLTF(const char *fileName)
// Load our model data: meshes and materials // Load our model data: meshes and materials
model.meshCount = primitivesCount; model.meshCount = primitivesCount;
model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh)); model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));
for (int i = 0; i < model.meshCount; i++) model.meshes[i].vboId = (unsigned int*)RL_CALLOC(MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
// NOTE: We keep an extra slot for default material, in case some mesh requires it // NOTE: We keep an extra slot for default material, in case some mesh requires it
model.materialCount = (int)data->materials_count + 1; model.materialCount = (int)data->materials_count + 1;

View File

@ -25,7 +25,7 @@
* *
* DEPENDENCIES: * DEPENDENCIES:
* stb_truetype - Load TTF file and rasterize characters data * stb_truetype - Load TTF file and rasterize characters data
* stb_rect_pack - Rectangles packing algorythms, required for font atlas generation * stb_rect_pack - Rectangles packing algorithms, required for font atlas generation
* *
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
@ -229,7 +229,7 @@ extern void LoadFontDefault(void)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Allocate space for our characters info data // Allocate space for our characters info data
// NOTE: This memory should be freed at end! --> CloseWindow() // NOTE: This memory must be freed at end! --> Done by CloseWindow()
defaultFont.glyphs = (GlyphInfo *)RL_MALLOC(defaultFont.glyphCount*sizeof(GlyphInfo)); defaultFont.glyphs = (GlyphInfo *)RL_MALLOC(defaultFont.glyphCount*sizeof(GlyphInfo));
defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.glyphCount*sizeof(Rectangle)); defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.glyphCount*sizeof(Rectangle));
@ -695,7 +695,7 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
// DEBUG: We can see padding in the generated image setting a gray background... // DEBUG: We can see padding in the generated image setting a gray background...
//for (int i = 0; i < atlas.width*atlas.height; i++) ((unsigned char *)atlas.data)[i] = 100; //for (int i = 0; i < atlas.width*atlas.height; i++) ((unsigned char *)atlas.data)[i] = 100;
if (packMethod == 0) // Use basic packing algorythm if (packMethod == 0) // Use basic packing algorithm
{ {
int offsetX = padding; int offsetX = padding;
int offsetY = padding; int offsetY = padding;
@ -746,7 +746,7 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
} }
} }
} }
else if (packMethod == 1) // Use Skyline rect packing algorythm (stb_pack_rect) else if (packMethod == 1) // Use Skyline rect packing algorithm (stb_pack_rect)
{ {
stbrp_context *context = (stbrp_context *)RL_MALLOC(sizeof(*context)); stbrp_context *context = (stbrp_context *)RL_MALLOC(sizeof(*context));
stbrp_node *nodes = (stbrp_node *)RL_MALLOC(glyphCount*sizeof(*nodes)); stbrp_node *nodes = (stbrp_node *)RL_MALLOC(glyphCount*sizeof(*nodes));
@ -992,11 +992,11 @@ bool ExportFontAsCode(Font font, const char *fileName)
// NOTE: Uses default font // NOTE: Uses default font
void DrawFPS(int posX, int posY) void DrawFPS(int posX, int posY)
{ {
Color color = LIME; // good fps Color color = LIME; // Good FPS
int fps = GetFPS(); int fps = GetFPS();
if (fps < 30 && fps >= 15) color = ORANGE; // warning FPS if ((fps < 30) && (fps >= 15)) color = ORANGE; // Warning FPS
else if (fps < 15) color = RED; // bad FPS else if (fps < 15) color = RED; // Low FPS
DrawText(TextFormat("%2i FPS", GetFPS()), posX, posY, 20, color); DrawText(TextFormat("%2i FPS", GetFPS()), posX, posY, 20, color);
} }
@ -1383,7 +1383,7 @@ const char *TextSubtext(const char *text, int position, int length)
// Replace text string // Replace text string
// REQUIRES: strlen(), strstr(), strncpy(), strcpy() // REQUIRES: strlen(), strstr(), strncpy(), strcpy()
// WARNING: Returned buffer must be freed by the user (if return != NULL) // WARNING: Allocated memory must be manually freed
char *TextReplace(char *text, const char *replace, const char *by) char *TextReplace(char *text, const char *replace, const char *by)
{ {
// Sanity checks and initialization // Sanity checks and initialization
@ -1432,7 +1432,7 @@ char *TextReplace(char *text, const char *replace, const char *by)
} }
// Insert text in a specific position, moves all text forward // Insert text in a specific position, moves all text forward
// WARNING: Allocated memory should be manually freed // WARNING: Allocated memory must be manually freed
char *TextInsert(const char *text, const char *insert, int position) char *TextInsert(const char *text, const char *insert, int position)
{ {
int textLen = TextLength(text); int textLen = TextLength(text);
@ -1616,7 +1616,7 @@ const char *TextToPascal(const char *text)
// Encode text codepoint into UTF-8 text // Encode text codepoint into UTF-8 text
// REQUIRES: memcpy() // REQUIRES: memcpy()
// WARNING: Allocated memory should be manually freed // WARNING: Allocated memory must be manually freed
char *TextCodepointsToUTF8(const int *codepoints, int length) char *TextCodepointsToUTF8(const int *codepoints, int length)
{ {
// We allocate enough memory fo fit all possible codepoints // We allocate enough memory fo fit all possible codepoints

View File

@ -37,7 +37,7 @@
* DEPENDENCIES: * DEPENDENCIES:
* stb_image - Multiple image formats loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC) * stb_image - Multiple image formats loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
* NOTE: stb_image has been slightly modified to support Android platform. * NOTE: stb_image has been slightly modified to support Android platform.
* stb_image_resize - Multiple image resize algorythms * stb_image_resize - Multiple image resize algorithms
* *
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
@ -306,10 +306,9 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
{ {
Image image = { 0 }; Image image = { 0 };
#if defined(SUPPORT_FILEFORMAT_PNG)
if ((strcmp(fileType, ".png") == 0)
#else
if ((false) if ((false)
#if defined(SUPPORT_FILEFORMAT_PNG)
|| (strcmp(fileType, ".png") == 0)
#endif #endif
#if defined(SUPPORT_FILEFORMAT_BMP) #if defined(SUPPORT_FILEFORMAT_BMP)
|| (strcmp(fileType, ".bmp") == 0) || (strcmp(fileType, ".bmp") == 0)
@ -1890,10 +1889,10 @@ void ImageColorTint(Image *image, Color color)
unsigned char b = (unsigned char)(((float)pixels[index].b/255*cB)*255.0f); unsigned char b = (unsigned char)(((float)pixels[index].b/255*cB)*255.0f);
unsigned char a = (unsigned char)(((float)pixels[index].a/255*cA)*255.0f); unsigned char a = (unsigned char)(((float)pixels[index].a/255*cA)*255.0f);
pixels[y*image->width + x].r = r; pixels[index].r = r;
pixels[y*image->width + x].g = g; pixels[index].g = g;
pixels[y*image->width + x].b = b; pixels[index].b = b;
pixels[y*image->width + x].a = a; pixels[index].a = a;
} }
} }
@ -1959,25 +1958,25 @@ void ImageColorContrast(Image *image, float contrast)
for (int x = 0; x < image->width; x++) for (int x = 0; x < image->width; x++)
{ {
float pR = (float)pixels[y*image->width + x].r/255.0f; float pR = (float)pixels[y*image->width + x].r/255.0f;
pR -= 0.5; pR -= 0.5f;
pR *= contrast; pR *= contrast;
pR += 0.5; pR += 0.5f;
pR *= 255; pR *= 255;
if (pR < 0) pR = 0; if (pR < 0) pR = 0;
if (pR > 255) pR = 255; if (pR > 255) pR = 255;
float pG = (float)pixels[y*image->width + x].g/255.0f; float pG = (float)pixels[y*image->width + x].g/255.0f;
pG -= 0.5; pG -= 0.5f;
pG *= contrast; pG *= contrast;
pG += 0.5; pG += 0.5f;
pG *= 255; pG *= 255;
if (pG < 0) pG = 0; if (pG < 0) pG = 0;
if (pG > 255) pG = 255; if (pG > 255) pG = 255;
float pB = (float)pixels[y*image->width + x].b/255.0f; float pB = (float)pixels[y*image->width + x].b/255.0f;
pB -= 0.5; pB -= 0.5f;
pB *= contrast; pB *= contrast;
pB += 0.5; pB += 0.5f;
pB *= 255; pB *= 255;
if (pB < 0) pB = 0; if (pB < 0) pB = 0;
if (pB > 255) pB = 255; if (pB > 255) pB = 255;
@ -2412,7 +2411,20 @@ Color GetImageColor(Image image, int x, int y)
// Clear image background with given color // Clear image background with given color
void ImageClearBackground(Image *dst, Color color) void ImageClearBackground(Image *dst, Color color)
{ {
for (int i = 0; i < dst->width*dst->height; ++i) ImageDrawPixel(dst, i%dst->width, i/dst->width, color); // Security check to avoid program crash
if ((dst->data == NULL) || (dst->width == 0) || (dst->height == 0)) return;
// Fill in first pixel based on image format
ImageDrawPixel(dst, 0, 0, color);
unsigned char *pSrcPixel = (unsigned char *)dst->data;
int bytesPerPixel = GetPixelDataSize(1, 1, dst->format);
// Repeat the first pixel data throughout the image
for (int i = 1; i < dst->width * dst->height; i++)
{
memcpy(pSrcPixel + i * bytesPerPixel, pSrcPixel, bytesPerPixel);
}
} }
// Draw pixel within an image // Draw pixel within an image
@ -2686,13 +2698,21 @@ void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color)
int ey = sy + (int)rec.height; int ey = sy + (int)rec.height;
int sx = (int)rec.x; int sx = (int)rec.x;
int ex = sx + (int)rec.width;
int bytesPerPixel = GetPixelDataSize(1, 1, dst->format);
for (int y = sy; y < ey; y++) for (int y = sy; y < ey; y++)
{ {
for (int x = sx; x < ex; x++) // Fill in the first pixel of the row based on image format
ImageDrawPixel(dst, sx, y, color);
int bytesOffset = ((y * dst->width) + sx) * bytesPerPixel;
unsigned char *pSrcPixel = (unsigned char *)dst->data + bytesOffset;
// Repeat the first pixel data throughout the row
for (int x = 1; x < (int)rec.width; x++)
{ {
ImageDrawPixel(dst, x, y, color); memcpy(pSrcPixel + x * bytesPerPixel, pSrcPixel, bytesPerPixel);
} }
} }
} }
@ -3472,6 +3492,8 @@ void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest,
coordD.x = (nPatchInfo.source.x + nPatchInfo.source.width)/width; coordD.x = (nPatchInfo.source.x + nPatchInfo.source.width)/width;
coordD.y = (nPatchInfo.source.y + nPatchInfo.source.height)/height; coordD.y = (nPatchInfo.source.y + nPatchInfo.source.height)/height;
rlCheckRenderBatchLimit(9 * 3 * 2); // Maxium number of verts that could happen
rlSetTexture(texture.id); rlSetTexture(texture.id);
rlPushMatrix(); rlPushMatrix();

View File

@ -148,6 +148,7 @@ void TraceLog(int logType, const char *text, ...)
strcat(buffer, text); strcat(buffer, text);
strcat(buffer, "\n"); strcat(buffer, "\n");
vprintf(buffer, args); vprintf(buffer, args);
fflush(stdout);
#endif #endif
va_end(args); va_end(args);
@ -268,6 +269,51 @@ bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
return success; return success;
} }
// Export data to code (.h), returns true on success
bool ExportDataAsCode(const char *data, unsigned int size, const char *fileName)
{
bool success = false;
#ifndef TEXT_BYTES_PER_LINE
#define TEXT_BYTES_PER_LINE 20
#endif
// NOTE: Text data buffer size is estimated considering raw data size in bytes
// and requiring 6 char bytes for every byte: "0x00, "
char *txtData = (char *)RL_CALLOC(size*6 + 2000, sizeof(char));
int byteCount = 0;
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// DataAsCode exporter v1.0 - Raw data exported as an array of bytes //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2022 Ramon Santamaria (@raysan5) //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
// Get file name from path and convert variable name to uppercase
char varFileName[256] = { 0 };
strcpy(varFileName, GetFileNameWithoutExt(fileName));
for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%i] = { ", varFileName, size);
for (int i = 0; i < size - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), data[i]);
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[size - 1]);
// NOTE: Text data size exported is determined by '\0' (NULL) character
success = SaveFileText(fileName, txtData);
RL_FREE(txtData);
if (success != 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;
}
// Load text data from file, returns a '\0' terminated string // Load text data from file, returns a '\0' terminated string
// NOTE: text chars array should be freed manually // NOTE: text chars array should be freed manually
char *LoadFileText(const char *fileName) char *LoadFileText(const char *fileName)