Merge branch 'upstream-merge'

This commit is contained in:
Luiz Pestana 2022-05-28 00:06:17 -03:00
commit 109523548e
42 changed files with 31118 additions and 9495 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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-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 |
| 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_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 |
@ -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 |
| 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-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
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 |
| 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 |
| 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/kevinw/raylib-jai |
| raylib-jai | 3.1-dev | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | https://github.com/kujukuju/raylib-jai |
| 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 |
| 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:
- [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>
[![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)
[![Packaging status](https://repology.org/badge/tiny-repos/raylib.svg)](https://repology.org/project/raylib/versions)
[![GitHub Contributors](https://img.shields.io/github/contributors/raysan5/raylib)](https://github.com/raysan5/raylib/graphs/contributors)
[![GitHub Releases Downloads](https://img.shields.io/github/downloads/raysan5/raylib/total)](https://github.com/raysan5/raylib/releases)
[![GitHub Stars](https://img.shields.io/github/stars/raysan5/raylib?style=flat&label=stars)](https://github.com/raysan5/raylib/stargazers)
[![GitHub commits since tagged version](https://img.shields.io/github/commits-since/raysan5/raylib/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)
[![Chat on Discord](https://img.shields.io/discord/426912293134270465.svg?logo=discord)](https://discord.gg/raylib)
[![GitHub stars](https://img.shields.io/github/stars/raysan5/raylib?style=social)](https://github.com/raysan5/raylib/stargazers)
[![Twitter Follow](https://img.shields.io/twitter/follow/raysan5?style=social)](https://twitter.com/raysan5)
[![Subreddit subscribers](https://img.shields.io/reddit/subreddit-subscribers/raylib?style=social)](https://www.reddit.com/r/raylib/)
[![Discord Members](https://img.shields.io/discord/426912293134270465.svg?label=Discord&logo=discord)](https://discord.gg/raylib)
[![Subreddit Subscribers](https://img.shields.io/reddit/subreddit-subscribers/raylib?label=reddit%20r%2Fraylib&logo=reddit)](https://www.reddit.com/r/raylib/)
[![Youtube Subscribers](https://img.shields.io/youtube/channel/subscribers/UC8WIBkhYb5sBNqXO1mZ7WSQ?style=flat&label=Youtube&logo=youtube)](https://www.youtube.com/c/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)
[![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))
- Tim Eilers ([@eilerstim](https://github.com/eilerstim))
- Laurentino Luna ([@catmanl](https://github.com/catmanl))
- ZimonIsHim ([@ZimonIsHim](https://github.com/ZimonIsHim))
### Past raylib GitHub Sponsors

View File

@ -44,7 +44,7 @@ elseif (${PLATFORM} MATCHES "Android")
set(PLATFORM_CPP "PLATFORM_ANDROID")
set(GRAPHICS "GRAPHICS_API_OPENGL_ES2")
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)
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")
@ -87,7 +87,9 @@ endif ()
if (${OPENGL_VERSION})
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")
elseif (${OPENGL_VERSION} MATCHES "2.1")
set(GRAPHICS "GRAPHICS_API_OPENGL_21")

View File

@ -253,6 +253,7 @@ INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external -I$(RAYLI
# Define additional directories containing required header files
ifeq ($(PLATFORM),PLATFORM_NX)
INCLUDE_PATHS += -I$(RAYLIB_PATH)/src/switch-nx
LIBDIRS := $(PORTLIBS) $(LIBNX)
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS += -ffunction-sections $(ARCH) $(foreach dir,$(LIBDIRS),-I$(dir)/include) -D__SWITCH__
@ -379,7 +380,7 @@ endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# Libraries for Raspberry Pi compiling
# 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)
LDLIBS += -lvchiq_arm -lvcos
endif
@ -387,7 +388,7 @@ endif
ifeq ($(PLATFORM),PLATFORM_DRM)
# Libraries for DRM compiling
# 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
ifeq ($(PLATFORM),PLATFORM_WEB)
# Libraries for web (HTML5) compiling

View File

@ -11,6 +11,49 @@
#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)
{
// Initialization
@ -24,11 +67,18 @@ int main(void)
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);
float timePlayed = 0.0f;
bool pause = false;
bool hasFilter = true;
bool hasDelay = true;
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
@ -55,6 +105,22 @@ int main(void)
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)
timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*400;
@ -86,6 +152,8 @@ int main(void)
CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
RL_FREE(delayBuffer); // Free delay buffer
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -20,6 +20,36 @@
#define MAX_SAMPLES 512
#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)
{
// Initialization
@ -33,9 +63,11 @@ int main(void)
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);
SetAudioStreamCallback(stream, AudioInputCallback);
// Buffer for the single cycle waveform we are synthesizing
short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES);
@ -47,6 +79,7 @@ int main(void)
// Position read in to determine next frequency
Vector2 mousePosition = { -100.0f, -100.0f };
/*
// Cycles per second (hz)
float frequency = 440.0f;
@ -55,6 +88,7 @@ int main(void)
// Cursor to read and copy the samples of the sine wave buffer
int readCursor = 0;
*/
// Computed size in samples of the sine wave
int waveLength = 1;
@ -82,7 +116,7 @@ int main(void)
SetAudioStreamPan(stream, pan);
}
// Rewrite the sine wave.
// Rewrite the sine wave
// Compute two cycles to allow the buffer padding, simplifying any modulation, resampling, etc.
if (frequency != oldFrequency)
{
@ -92,17 +126,18 @@ int main(void)
if (waveLength > MAX_SAMPLES/2) waveLength = MAX_SAMPLES/2;
if (waveLength < 1) waveLength = 1;
// Write sine wave.
// Write sine wave
for (int i = 0; i < waveLength*2; i++)
{
data[i] = (short)(sinf(((2*PI*(float)i/waveLength)))*32000);
}
// 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;
}
/*
// Refill audio stream if required
if (IsAudioStreamProcessed(stream))
{
@ -131,6 +166,7 @@ int main(void)
// Copy finished frame to audio stream
UpdateAudioStream(stream, writeBuf, MAX_SAMPLES_PER_UPDATE);
}
*/
//----------------------------------------------------------------------------------
// Draw

View File

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

View File

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

View File

@ -78,7 +78,11 @@ int main(void)
// Initialize framebuffer for stereo rendering
// 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
Camera camera = { 0 };
@ -121,8 +125,7 @@ int main(void)
BeginDrawing();
ClearBackground(RAYWHITE);
BeginShaderMode(distortion);
DrawTextureRec(target.texture, (Rectangle){ 0, 0, (float)target.texture.width,
(float)-target.texture.height }, (Vector2){ 0.0f, 0.0f }, WHITE);
DrawTexturePro(target.texture, sourceRec, destRec, (Vector2){ 0.0f, 0.0f }, 0.0f, WHITE);
EndShaderMode();
DrawFPS(10, 10);
EndDrawing();

View File

@ -121,9 +121,22 @@ int main(void)
cursorColor = ORANGE;
hitObjectName = "Box";
// Check ray collision against model
// NOTE: It considers model.transform matrix!
RayCollision meshHitInfo = GetRayCollisionModel(ray, tower);
// Check ray collision against model meshes
RayCollision meshHitInfo = { 0 };
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)
{

View File

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

View File

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

View File

@ -24,8 +24,8 @@ int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - raymarching shapes");
@ -77,9 +77,7 @@ int main(void)
// Check if screen is resized
if (IsWindowResized())
{
screenWidth = GetScreenWidth();
screenHeight = GetScreenHeight();
float resolution[2] = { (float)screenWidth, (float)screenHeight };
float resolution[2] = { (float)GetScreenWidth(), (float)GetScreenHeight() };
SetShaderValue(shader, resolutionLoc, resolution, SHADER_UNIFORM_VEC2);
}
//----------------------------------------------------------------------------------
@ -93,10 +91,10 @@ int main(void)
// We only draw a white full-screen rectangle,
// frame is generated in shader using raymarching
BeginShaderMode(shader);
DrawRectangle(0, 0, screenWidth, screenHeight, WHITE);
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), WHITE);
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();
//----------------------------------------------------------------------------------

View File

@ -41,8 +41,7 @@ int main(void)
//----------------------------------------------------------------------------------
mousePosition = GetMousePosition();
if (CheckCollisionPointRec(mousePosition, rec) &&
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 }))
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 }))
{
mouseScaleReady = true;
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) mouseScaleMode = true;
@ -56,9 +55,14 @@ int main(void)
rec.width = (mousePosition.x - rec.x);
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.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;
}
//----------------------------------------------------------------------------------

View File

@ -19,8 +19,8 @@ int main(int argc, char **argv)
{
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_RESIZABLE); // Make the window resizable
InitWindow(screenWidth, screenHeight, "raylib [textures] example - Draw part of a texture tiled");
@ -71,9 +71,6 @@ int main(int argc, char **argv)
{
// Update
//----------------------------------------------------------------------------------
screenWidth = GetScreenWidth();
screenHeight = GetScreenHeight();
// Handle mouse
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
{
@ -122,11 +119,11 @@ int main(int argc, char **argv)
ClearBackground(RAYWHITE);
// 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]);
// 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);
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/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/physac.h -o physac_api.$(EXTENSION) -f $(FORMAT) -d PHYSACDEF
./raylib_parser -i ../src/extras/raygui.h -o raygui_api.$(EXTENSION) -f $(FORMAT) -d RAYGUIAPI
./raylib_parser -i ../src/extras/rmem.h -o rmem_api.$(EXTENSION) -f $(FORMAT) -d RMEMAPI
./raylib_parser -i ../src/rlgl.h -o rlgl_api.$(EXTENSION) -f $(FORMAT) -d RLAPI
./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 -t "RAYGUI IMPLEMENTATION"
./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 -t "RLGL IMPLEMENTATION"
clean:
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" ?>
<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">
<Struct name="Vector2" fieldCount="2" desc="Vector2, 2 components">
<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="w" desc="Vector w component" />
</Struct>
<Struct name="Matrix" fieldCount="4" 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="m1, m5, m9, m13" desc="Matrix second row (4 components)" />
<Field type="float" name="m2, m6, m10, m14" desc="Matrix third row (4 components)" />
<Field type="float" name="m3, m7, m11, m15" desc="Matrix fourth row (4 components)" />
<Struct name="Matrix" fieldCount="16" desc="Matrix, 4x4 components, column major, OpenGL style, right handed">
<Field type="float" name="m0" desc="Matrix first row (4 components)" />
<Field type="float" name="m4" desc="Matrix first row (4 components)" />
<Field type="float" name="m8" desc="Matrix first 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 name="Color" fieldCount="4" desc="Color, 4 components, R8G8B8A8 (32bit)">
<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="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="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="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)" />
@ -118,7 +184,7 @@
<Struct name="Material" fieldCount="3" desc="Material, includes shader and maps">
<Field type="Shader" name="shader" desc="Material shader" />
<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 name="Transform" fieldCount="3" desc="Transform, vectex transformation data">
<Field type="Vector3" name="translation" desc="Translation" />
@ -126,7 +192,7 @@
<Field type="Vector3" name="scale" desc="Scale" />
</Struct>
<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" />
</Struct>
<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="void *" name="data" desc="Buffer data pointer" />
</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="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="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, ...)" />
@ -193,20 +260,27 @@
<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="interpupillaryDistance" desc="IPD (distance between pupils) in meters" />
<Field type="float" name="lensDistortionValues[4]" desc="Lens distortion constant parameters" />
<Field type="float" name="chromaAbCorrection[4]" desc="Chromatic aberration correction parameters" />
<Field type="float[4]" name="lensDistortionValues" desc="Lens distortion constant parameters" />
<Field type="float[4]" name="chromaAbCorrection" desc="Chromatic aberration correction parameters" />
</Struct>
<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" name="viewOffset[2]" desc="VR view offset matrices (per eye)" />
<Field type="float" name="leftLensCenter[2]" desc="VR left lens center" />
<Field type="float" name="rightLensCenter[2]" desc="VR right lens center" />
<Field type="float" name="leftScreenCenter[2]" desc="VR left screen center" />
<Field type="float" name="rightScreenCenter[2]" desc="VR right screen center" />
<Field type="float" name="scale[2]" desc="VR distortion scale" />
<Field type="float" name="scaleIn[2]" desc="VR distortion scale in" />
<Field type="Matrix[2]" name="projection" desc="VR projection matrices (per eye)" />
<Field type="Matrix[2]" name="viewOffset" desc="VR view offset matrices (per eye)" />
<Field type="float[2]" name="leftLensCenter" desc="VR left lens center" />
<Field type="float[2]" name="rightLensCenter" desc="VR right lens center" />
<Field type="float[2]" name="leftScreenCenter" desc="VR left screen center" />
<Field type="float[2]" name="rightScreenCenter" desc="VR right screen center" />
<Field type="float[2]" name="scale" desc="VR distortion scale" />
<Field type="float[2]" name="scaleIn" desc="VR distortion scale in" />
</Struct>
</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">
<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" />
@ -543,61 +617,34 @@
<Value name="NPATCH_THREE_PATCH_HORIZONTAL" integer="2" desc="Npatch layout: 3x1 tiles" />
</Enum>
</Enums>
<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="UNKNOWN" value="(PI/180.0f)" desc="" />
<Define name="RAD2DEG" type="UNKNOWN" 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>
<Functions count="497">
<Callbacks count="6">
<Callback name="TraceLogCallback" retType="void" paramCount="3" desc="Logging: Redirect trace log messages">
<Param type="int" name="logLevel" desc="" />
<Param type="const char *" name="text" desc="" />
<Param type="va_list" name="args" desc="" />
</Callback>
<Callback name="LoadFileDataCallback" retType="unsigned char *" paramCount="2" desc="FileIO: Load binary data">
<Param type="const char *" name="fileName" desc="" />
<Param type="unsigned int *" name="bytesRead" desc="" />
</Callback>
<Callback name="SaveFileDataCallback" retType="bool" paramCount="3" desc="FileIO: Save binary data">
<Param type="const char *" name="fileName" desc="" />
<Param type="void *" name="data" desc="" />
<Param type="unsigned int" name="bytesToWrite" desc="" />
</Callback>
<Callback name="LoadFileTextCallback" retType="char *" paramCount="1" desc="FileIO: Load text data">
<Param type="const char *" name="fileName" desc="" />
</Callback>
<Callback name="SaveFileTextCallback" retType="bool" paramCount="2" desc="FileIO: Save text data">
<Param type="const char *" name="fileName" desc="" />
<Param type="char *" name="text" desc="" />
</Callback>
<Callback name="AudioCallback" retType="void" paramCount="2" desc="">
<Param type="void *" name="bufferData" desc="" />
<Param type="unsigned int" name="frames" desc="" />
</Callback>
</Callbacks>
<Functions count="499">
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
<Param type="int" name="width" desc="" />
<Param type="int" name="height" desc="" />
@ -955,7 +1002,7 @@
</Function>
<Function name="GetApplicationDirectory" retType="const char *" paramCount="0" desc="Get the directory if the running application (uses static string)">
</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="int *" name="count" desc="" />
</Function>
@ -966,7 +1013,7 @@
</Function>
<Function name="IsFileDropped" retType="bool" paramCount="0" desc="Check if a file has been dropped into window">
</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="" />
</Function>
<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)">
<Param type="const char *" name="fileName" desc="" />
</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="int" name="dataLength" desc="" />
<Param type="int *" name="compDataLength" desc="" />
<Param type="int" name="dataSize" desc="" />
<Param type="int *" name="compDataSize" desc="" />
</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="int" name="compDataLength" desc="" />
<Param type="int *" name="dataLength" desc="" />
<Param type="int" name="compDataSize" desc="" />
<Param type="int *" name="dataSize" desc="" />
</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="int" name="dataLength" desc="" />
<Param type="int *" name="outputLength" desc="" />
<Param type="int" name="dataSize" desc="" />
<Param type="int *" name="outputSize" desc="" />
</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="int *" name="outputLength" desc="" />
<Param type="int *" name="outputSize" desc="" />
</Function>
<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="" />
@ -2451,10 +2498,6 @@
<Param type="Ray" name="ray" desc="" />
<Param type="BoundingBox" name="box" desc="" />
</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">
<Param type="Ray" name="ray" 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">
<Param type="int" name="size" desc="" />
</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>
</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+
project(example)
# Generate compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Dependencies
find_package(raylib 4.0.0 QUIET) # QUIET or REQUIRED
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:
``` bash
mkdir build
cd build
cmake ..
make
cmake -B build
cmake --build build
```
### Web

View File

@ -104,11 +104,11 @@ export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := -I$(RAYLIB_NX)/src $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
export INCLUDE := -I$(RAYLIB_NX)/src -I$(RAYLIB_NX)/src/switch-nx $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := -L$(RAYLIB_NX)/src $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
export LIBPATHS := -L$(RAYLIB_NX)/src -L$(RAYLIB_NX)/src/switch-nx $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(CONFIG_JSON)),)
jsons := $(wildcard *.json)

View File

@ -437,7 +437,7 @@ ifeq ($(PLATFORM),PLATFORM_NX)
LIBDIRS := $(PORTLIBS) $(LIBNX)
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIC -ftls-model=local-exec
CFLAGS += -ffunction-sections -fdata-sections $(ARCH) $(foreach dir,$(LIBDIRS),-I$(dir)/include) -D__SWITCH__
INCLUDE_PATHS = -I.
INCLUDE_PATHS = -I. -I./switch-nx
endif
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),BSD)
@ -536,9 +536,15 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
LDLIBS = -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl
ifeq ($(RAYLIB_MODULE_AUDIO),TRUE)
LDLIBS += -latomic
endif
endif
ifeq ($(PLATFORM),PLATFORM_DRM)
LDLIBS = -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl
ifeq ($(RAYLIB_MODULE_AUDIO),TRUE)
LDLIBS += -latomic
endif
endif
ifeq ($(PLATFORM),PLATFORM_ANDROID)
LDLIBS = -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lc -lm
@ -696,17 +702,26 @@ nxusb.o : nxusb.c nxusb.h raylib.h
raygui.o : raygui.c
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)
raygui.c:
echo #define RAYGUI_IMPLEMENTATION > raygui.c
echo #include "$(RAYLIB_MODULE_RAYGUI_PATH)/raygui.h" >> raygui.c
ifeq ($(PLATFORM_SHELL), cmd)
@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
# NOTE: physac header should be distributed with raylib.h
physac.o : physac.c
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)
physac.c:
ifeq ($(PLATFORM_SHELL), cmd)
@echo #define PHYSAC_IMPLEMENTATION > 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
android_native_app_glue.o : $(NATIVE_APP_GLUE)/android_native_app_glue.c
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)

View File

@ -1,8 +1,6 @@
const std = @import("std");
pub fn Pkg(srcdir: []const u8) type {
return struct {
pub fn addRaylib(b: *std.build.Builder, target: std.zig.CrossTarget) *std.build.LibExeObjStep {
pub fn addRaylib(b: *std.build.Builder, target: std.zig.CrossTarget) *std.build.LibExeObjStep {
// Standard release options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
const mode = b.standardReleaseOptions();
@ -76,15 +74,9 @@ pub fn Pkg(srcdir: []const u8) type {
},
}
raylib.setOutputDir("./");
raylib.install();
return raylib;
}
};
}
const lib = Pkg(".");
pub fn build(b: *std.build.Builder) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
@ -92,5 +84,13 @@ pub fn build(b: *std.build.Builder) void {
// for restricting supported target set are available.
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 ".";
}

33707
src/external/miniaudio.h vendored

File diff suppressed because it is too large Load Diff

233
src/external/miniaudio_sdl.h vendored Normal file
View File

@ -0,0 +1,233 @@
/******************************************************************************
SDL Backend
******************************************************************************/
struct
{
ma_uint32 deviceID;
} device_sdl;
struct
{
ma_handle hSDL;
ma_proc SDL_InitSubSystem;
ma_proc SDL_QuitSubSystem;
ma_proc SDL_GetNumAudioDevices;
ma_proc SDL_GetAudioDeviceName;
ma_proc SDL_CloseAudioDevice;
ma_proc SDL_OpenAudioDevice;
ma_proc SDL_PauseAudioDevice;
} context_sdl;
#define MA_SDL_INIT_AUDIO 0x00000010
#define MA_AUDIO_U8 0x0008
#define MA_AUDIO_S16 0x8010
#define MA_AUDIO_S32 0x8020
#define MA_AUDIO_F32 0x8120
#define MA_SDL_AUDIO_ALLOW_FREQUENCY_CHANGE 0x00000001
#define MA_SDL_AUDIO_ALLOW_FORMAT_CHANGE 0x00000002
#define MA_SDL_AUDIO_ALLOW_CHANNELS_CHANGE 0x00000004
#define MA_SDL_AUDIO_ALLOW_ANY_CHANGE (MA_SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | MA_SDL_AUDIO_ALLOW_FORMAT_CHANGE | MA_SDL_AUDIO_ALLOW_CHANNELS_CHANGE)
#include <SDL2/SDL.h>
#include <SDL2/SDL_audio.h>
typedef int (* MA_PFN_SDL_InitSubSystem)(ma_uint32 flags);
typedef void (* MA_PFN_SDL_QuitSubSystem)(ma_uint32 flags);
typedef int (* MA_PFN_SDL_GetNumAudioDevices)(int iscapture);
typedef const char* (* MA_PFN_SDL_GetAudioDeviceName)(int index, int iscapture);
typedef void (* MA_PFN_SDL_CloseAudioDevice)(SDL_AudioDeviceID dev);
typedef SDL_AudioDeviceID (* MA_PFN_SDL_OpenAudioDevice)(const char* device, int iscapture, const SDL_AudioSpec* desired, SDL_AudioSpec* obtained, int allowed_changes);
typedef void (* MA_PFN_SDL_PauseAudioDevice)(SDL_AudioDeviceID dev, int pause_on);
static SDL_AudioFormat ma_format_to_sdl(ma_format format)
{
switch (format)
{
case ma_format_unknown: return 0;
case ma_format_u8: return MA_AUDIO_U8;
case ma_format_s16: return MA_AUDIO_S16;
case ma_format_s24: return MA_AUDIO_S32; // Closest match.
case ma_format_s32: return MA_AUDIO_S32;
case ma_format_f32: return MA_AUDIO_F32;
default: return 0;
}
}
static ma_format ma_format_from_sdl(SDL_AudioFormat format)
{
switch (format)
{
case MA_AUDIO_U8: return ma_format_u8;
case MA_AUDIO_S16: return ma_format_s16;
case MA_AUDIO_S32: return ma_format_s32;
case MA_AUDIO_F32: return ma_format_f32;
default: return ma_format_unknown;
}
}
static ma_result ma_context_get_device_info__sdl(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(deviceType == ma_device_type_playback);
pDeviceInfo->isDefault = MA_TRUE;
SDL_AudioSpec desiredSpec, obtainedSpec;
MA_ZERO_OBJECT(&desiredSpec);
SDL_AudioDeviceID tempDeviceID = ((MA_PFN_SDL_OpenAudioDevice)context_sdl.SDL_OpenAudioDevice)(NULL, 0, &desiredSpec, &obtainedSpec, MA_SDL_AUDIO_ALLOW_ANY_CHANGE);
((MA_PFN_SDL_CloseAudioDevice)context_sdl.SDL_CloseAudioDevice)(tempDeviceID);
ma_format format = ma_format_from_sdl(obtainedSpec.format);
if (format == ma_format_unknown) {
format = ma_format_f32;
}
pDeviceInfo->nativeDataFormatCount = 0;
ma_device_info_add_native_data_format(pDeviceInfo, format, obtainedSpec.channels, obtainedSpec.freq, 0);
return MA_SUCCESS;
}
static ma_result ma_device_uninit__sdl(ma_device* pDevice)
{
MA_ASSERT(pDevice != NULL);
((MA_PFN_SDL_CloseAudioDevice)context_sdl.SDL_CloseAudioDevice)(device_sdl.deviceID);
return MA_SUCCESS;
}
static void ma_audio_callback__sdl(void* pUserData, ma_uint8* pBuffer, int bufferSizeInBytes)
{
ma_device* pDevice = (ma_device*)pUserData;
MA_ASSERT(pDevice != NULL);
ma_uint32 bytesPerFrame = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
ma_uint32 frameCount = (ma_uint32)bufferSizeInBytes / bytesPerFrame;
ma_device_handle_backend_data_callback(pDevice, pBuffer, NULL, frameCount);
}
static ma_result ma_device_init__sdl(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
{
MA_ASSERT(pDevice != NULL);
MA_ASSERT(pConfig != NULL);
MA_ASSERT(pConfig->deviceType == ma_device_type_playback);
if (pDescriptorPlayback->sampleRate == 0) {
pDescriptorPlayback->sampleRate = MA_DEFAULT_SAMPLE_RATE;
}
pDescriptorPlayback->periodSizeInFrames = pDescriptorPlayback->periodCount * ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
/* SDL wants the buffer size to be a power of 2 for some reason. */
if (pDescriptorPlayback->periodSizeInFrames > 32768) {
pDescriptorPlayback->periodSizeInFrames = 32768;
} else {
pDescriptorPlayback->periodSizeInFrames = ma_next_power_of_2(pDescriptorPlayback->periodSizeInFrames);
}
MA_ASSERT(pDescriptorPlayback->periodSizeInFrames <= 32768);
/* We now have enough information to set up the device. */
SDL_AudioSpec desiredSpec, obtainedSpec;
MA_ZERO_OBJECT(&desiredSpec);
desiredSpec.freq = (int)pDescriptorPlayback->sampleRate;
desiredSpec.format = ma_format_to_sdl(pDescriptorPlayback->format);
desiredSpec.channels = (ma_uint8)pDescriptorPlayback->channels;
desiredSpec.samples = (ma_uint16)pDescriptorPlayback->periodSizeInFrames;
desiredSpec.callback = ma_audio_callback__sdl;
desiredSpec.userdata = pDevice;
/* We'll fall back to f32 if we don't have an appropriate mapping between SDL and miniaudio. */
if (desiredSpec.format == ma_format_unknown) {
desiredSpec.format = MA_AUDIO_F32;
}
device_sdl.deviceID = ((MA_PFN_SDL_OpenAudioDevice)context_sdl.SDL_OpenAudioDevice)(NULL, 0, &desiredSpec, &obtainedSpec, MA_SDL_AUDIO_ALLOW_ANY_CHANGE);
/* The descriptor needs to be updated with our actual settings. */
pDescriptorPlayback->format = ma_format_from_sdl(obtainedSpec.format);
pDescriptorPlayback->channels = obtainedSpec.channels;
pDescriptorPlayback->sampleRate = (ma_uint32)obtainedSpec.freq;
ma_channel_map_init_standard(ma_standard_channel_map_default, pDescriptorPlayback->channelMap, ma_countof(pDescriptorPlayback->channelMap), pDescriptorPlayback->channels);
pDescriptorPlayback->periodSizeInFrames = obtainedSpec.samples;
pDescriptorPlayback->periodCount = 1; /* SDL doesn't use the notion of period counts, so just set to 1. */
return MA_SUCCESS;
}
static ma_result ma_device_start__sdl(ma_device* pDevice)
{
MA_ASSERT(pDevice != NULL);
((MA_PFN_SDL_PauseAudioDevice)context_sdl.SDL_PauseAudioDevice)(device_sdl.deviceID, 0);
return MA_SUCCESS;
}
static ma_result ma_device_stop__sdl(ma_device* pDevice)
{
MA_ASSERT(pDevice != NULL);
((MA_PFN_SDL_PauseAudioDevice)context_sdl.SDL_PauseAudioDevice)(device_sdl.deviceID, 1);
ma_device__set_state(pDevice, ma_device_state_stopped);
ma_stop_proc onStop = pDevice->onStop;
if (onStop) {
onStop(pDevice);
}
return MA_SUCCESS;
}
static ma_result ma_context_uninit__sdl(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
((MA_PFN_SDL_QuitSubSystem)context_sdl.SDL_QuitSubSystem)(MA_SDL_INIT_AUDIO);
return MA_SUCCESS;
}
static ma_result ma_context_init__sdl(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
MA_ASSERT(pContext != NULL);
(void)pConfig; /* Unused. */
context_sdl.SDL_InitSubSystem = (ma_proc)SDL_InitSubSystem;
context_sdl.SDL_QuitSubSystem = (ma_proc)SDL_QuitSubSystem;
context_sdl.SDL_GetNumAudioDevices = (ma_proc)SDL_GetNumAudioDevices;
context_sdl.SDL_GetAudioDeviceName = (ma_proc)SDL_GetAudioDeviceName;
context_sdl.SDL_CloseAudioDevice = (ma_proc)SDL_CloseAudioDevice;
context_sdl.SDL_OpenAudioDevice = (ma_proc)SDL_OpenAudioDevice;
context_sdl.SDL_PauseAudioDevice = (ma_proc)SDL_PauseAudioDevice;
int resultSDL = ((MA_PFN_SDL_InitSubSystem)context_sdl.SDL_InitSubSystem)(MA_SDL_INIT_AUDIO);
if (resultSDL != 0) {
return MA_ERROR;
}
pCallbacks->onContextInit = ma_context_init__sdl;
pCallbacks->onContextUninit = ma_context_uninit__sdl;
pCallbacks->onContextEnumerateDevices = NULL;
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__sdl;
pCallbacks->onDeviceInit = ma_device_init__sdl;
pCallbacks->onDeviceUninit = ma_device_uninit__sdl;
pCallbacks->onDeviceStart = ma_device_start__sdl;
pCallbacks->onDeviceStop = ma_device_stop__sdl;
pCallbacks->onDeviceRead = NULL;
pCallbacks->onDeviceWrite = NULL;
pCallbacks->onDeviceDataLoop = NULL;
return MA_SUCCESS;
}

View File

@ -101,47 +101,47 @@ extern "C" { // Prevents name mangling of functions
#endif
// Linear Easing functions
EASEDEF float EaseLinearNone(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); }
EASEDEF float EaseLinearOut(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); }
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); } // Ease: Linear In
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); } // Ease: Linear In Out
// 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 EaseSineOut(float t, float b, float c, float d) { return (c*sinf(t/d*(PI/2.0f)) + b); }
EASEDEF float EaseSineInOut(float t, float b, float c, float d) { return (-c/2.0f*(cosf(PI*t/d) - 1.0f) + 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); } // 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); } // Ease: Sine Out
// 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 EaseCircOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*sqrtf(1.0f - t*t) + b); }
EASEDEF float EaseCircInOut(float t, float b, float c, float d)
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); } // Ease: Circular Out
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);
t -= 2.0f; return (c/2.0f*(sqrtf(1.0f - t*t) + 1.0f) + b);
}
// Cubic Easing functions
EASEDEF float EaseCubicIn(float t, float b, float c, float d) { t /= d; return (c*t*t*t + 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); }
EASEDEF float EaseCubicInOut(float t, float b, float c, float d)
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); } // Ease: Cubic Out
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);
t -= 2.0f; return (c/2.0f*(t*t*t + 2.0f) + b);
}
// Quadratic Easing functions
EASEDEF float EaseQuadIn(float t, float b, float c, float d) { t /= d; return (c*t*t + b); }
EASEDEF float EaseQuadOut(float t, float b, float c, float d) { t /= d; return (-c*t*(t - 2.0f) + b); }
EASEDEF float EaseQuadInOut(float t, float b, float c, float d)
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); } // Ease: Quadratic Out
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);
return (-c/2.0f*(((t - 1.0f)*(t - 3.0f)) - 1.0f) + b);
}
// 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 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 EaseExpoInOut(float t, float b, float c, float d)
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); } // Ease: Exponential Out
EASEDEF float EaseExpoInOut(float t, float b, float c, float d) // Ease: Exponential In Out
{
if (t == 0.0f) return b;
if (t == d) return (b + c);
@ -151,21 +151,21 @@ EASEDEF float EaseExpoInOut(float t, float b, float c, float d)
}
// 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 postFix = t/=d;
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;
t = t/d - 1.0f;
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;
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
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))
{
@ -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 EaseBounceInOut(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); } // Ease: Bounce In
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);
else return (EaseBounceOut(t*2.0f - d, 0.0f, c, d)*0.5f + c*0.5f + b);
}
// 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/=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);
}
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/=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);
}
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/=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--;
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--;
textValue[keyCount] = '\0';
if (keyCount < 0) keyCount = 0;
valueHasChanged = true;
}
}

View File

@ -163,6 +163,11 @@ typedef struct tagBITMAPINFOHEADER {
#define MA_MALLOC RL_MALLOC
#define MA_FREE RL_FREE
#if defined(PLATFORM_NX)
#define MA_ENABLE_ONLY_SPECIFIC_BACKENDS
#define MA_ENABLE_CUSTOM
#endif
#define MA_NO_JACK
#define MA_NO_WAV
#define MA_NO_FLAC
@ -170,6 +175,9 @@ typedef struct tagBITMAPINFOHEADER {
#define MINIAUDIO_IMPLEMENTATION
//#define MA_DEBUG_OUTPUT
#include "external/miniaudio.h" // Audio device initialization and management
#if defined(PLATFORM_NX)
#include "external/miniaudio_sdl.h"
#endif
#undef PlaySound // Win32 API: windows.h > mmsystem.h defines PlaySound macro
#include <stdlib.h> // Required for: malloc(), free()
@ -247,10 +255,6 @@ typedef struct tagBITMAPINFOHEADER {
#include "external/dr_flac.h" // FLAC loading functions
#endif
#if defined(_MSC_VER)
#undef bool
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@ -311,10 +315,13 @@ typedef enum {
AUDIO_BUFFER_USAGE_STREAM
} AudioBufferUsage;
// Audio buffer structure
// Audio buffer struct
struct rAudioBuffer {
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 pitch; // Audio buffer pitch
float pan; // Audio buffer pan (0.0f to 1.0f)
@ -335,6 +342,14 @@ struct rAudioBuffer {
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
// Audio data context
@ -372,7 +387,7 @@ static AudioData AUDIO = { // Global AUDIO context
//----------------------------------------------------------------------------------
// 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 MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer);
@ -411,9 +426,17 @@ void InitAudioDevice(void)
{
// Init audio context
ma_context_config ctxConfig = ma_context_config_init();
ctxConfig.logCallback = OnLog;
ma_log_callback_init(OnLog, NULL);
#if defined(PLATFORM_NX)
ma_backend backends[] = {
ma_backend_custom
};
ctxConfig.custom.onContextInit = ma_context_init__sdl;
ma_result result = ma_context_init(backends, sizeof(backends)/sizeof(backends[0]), &ctxConfig, &AUDIO.System.context);
#else
ma_result result = ma_context_init(NULL, 0, &ctxConfig, &AUDIO.System.context);
#endif
if (result != MA_SUCCESS)
{
TRACELOG(LOG_WARNING, "AUDIO: Failed to initialize context");
@ -465,8 +488,7 @@ void InitAudioDevice(void)
// Init dummy audio buffers pool for multichannel sound playing
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
{
// WARNING: An empty audio buffer is created (data = 0)
// AudioBuffer data just points to loaded sound data
// WARNING: An empty audio buffer is created (data = 0) and added to list, AudioBuffer data is filled on PlaySoundMulti()
AUDIO.MultiChannel.pool[i] = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, 0, AUDIO_BUFFER_USAGE_STATIC);
}
@ -492,7 +514,7 @@ void CloseAudioDevice(void)
//UnloadAudioBuffer(AUDIO.MultiChannel.pool[i]);
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]);
//RL_FREE(buffer->data); // Already unloaded by UnloadSound()
RL_FREE(AUDIO.MultiChannel.pool[i]);
@ -541,9 +563,9 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
// 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);
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)
{
@ -557,9 +579,13 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
audioBuffer->pitch = 1.0f;
audioBuffer->pan = 0.5f;
audioBuffer->callback = NULL;
audioBuffer->processor = NULL;
audioBuffer->playing = false;
audioBuffer->paused = false;
audioBuffer->looping = false;
audioBuffer->usage = usage;
audioBuffer->frameCursorPos = 0;
audioBuffer->sizeInFrames = sizeInFrames;
@ -580,7 +606,7 @@ void UnloadAudioBuffer(AudioBuffer *buffer)
{
if (buffer != NULL)
{
ma_data_converter_uninit(&buffer->converter);
ma_data_converter_uninit(&buffer->converter, NULL);
UntrackAudioBuffer(buffer);
RL_FREE(buffer->data);
RL_FREE(buffer);
@ -654,8 +680,8 @@ void SetAudioBufferPitch(AudioBuffer *buffer, float pitch)
// Note that this changes the duration of the sound:
// - higher pitches will make the sound faster
// - lower pitches make it slower
ma_uint32 outputSampleRate = (ma_uint32)((float)buffer->converter.config.sampleRateOut/pitch);
ma_data_converter_set_rate(&buffer->converter, buffer->converter.config.sampleRateIn, outputSampleRate);
ma_uint32 outputSampleRate = (ma_uint32)((float)buffer->converter.sampleRateOut/pitch);
ma_data_converter_set_rate(&buffer->converter, buffer->converter.sampleRateIn, outputSampleRate);
buffer->pitch = pitch;
}
@ -894,7 +920,7 @@ void UpdateSound(Sound sound, const void *data, int sampleCount)
StopAudioBuffer(sound.stream.buffer);
// 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 +1094,8 @@ void PlaySoundMulti(Sound sound)
AUDIO.MultiChannel.pool[index]->isSubBufferProcessed[0] = false;
AUDIO.MultiChannel.pool[index]->isSubBufferProcessed[1] = false;
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]);
}
@ -1191,8 +1218,7 @@ Wave WaveCopy(Wave wave)
// NOTE: Security check in case of out-of-range
void WaveCrop(Wave *wave, int initSample, int finalSample)
{
if ((initSample >= 0) && (initSample < finalSample) &&
(finalSample > 0) && ((unsigned int)finalSample < (wave->frameCount*wave->channels)))
if ((initSample >= 0) && (initSample < finalSample) && ((unsigned int)finalSample < (wave->frameCount*wave->channels)))
{
int sampleCount = finalSample - initSample;
@ -1503,10 +1529,8 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
jar_xm_set_max_loop_count(ctxXm, 0); // Set infinite number of loops
unsigned int bits = 32;
if (AUDIO_DEVICE_FORMAT == ma_format_s16)
bits = 16;
else if (AUDIO_DEVICE_FORMAT == ma_format_u8)
bits = 8;
if (AUDIO_DEVICE_FORMAT == ma_format_s16) bits = 16;
else if (AUDIO_DEVICE_FORMAT == ma_format_u8) bits = 8;
// NOTE: Only stereo is supported for XM
music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, bits, 2);
@ -1533,7 +1557,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
for (int i = 0; i < it; i++) newData[i] = data[i];
// Memory loaded version for jar_mod_load_file()
if (dataSize && dataSize < 32*1024*1024)
if (dataSize && (dataSize < 32*1024*1024))
{
ctxMod->modfilesize = dataSize;
ctxMod->modfile = newData;
@ -2028,22 +2052,86 @@ void SetAudioStreamBufferSizeDefault(int 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
//----------------------------------------------------------------------------------
// 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;
(void)pDevice;
TRACELOG(LOG_WARNING, "miniaudio: %s", message); // All log messages from miniaudio are errors
TRACELOG(LOG_WARNING, "miniaudio: %s", pMessage); // All log messages from miniaudio are errors
}
// Reads audio data from an AudioBuffer object in internal format.
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 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames;
@ -2055,7 +2143,7 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0];
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
ma_uint32 framesRead = 0;
@ -2135,20 +2223,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
// frames. This can be achieved with ma_data_converter_get_required_input_frame_count().
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;
while (totalOutputFramesProcessed < frameCount)
{
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)
{
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. */
ma_uint64 inputFramesProcessedThisIteration = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, (ma_uint32)inputFramesToProcessThisIteration); /* Safe cast. */
@ -2217,6 +2306,14 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
float *framesOut = (float *)pFramesOut + (framesRead*AUDIO.System.device.playback.channels);
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);
framesToRead -= framesJustRead;
@ -2257,41 +2354,44 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
ma_mutex_unlock(&AUDIO.System.lock);
}
// This is the main mixing function. Mixing is pretty simple in this project - it's just an accumulation.
// NOTE: framesOut is both an input and an output. It will be initially filled with zeros outside of this function.
// Main mixing function, pretty simple in this project, just an accumulation
// 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)
{
const float localVolume = buffer->volume;
const ma_uint32 channels = AUDIO.System.device.playback.channels;
const ma_uint32 nChannels = AUDIO.System.device.playback.channels;
if (nChannels == 2)
if (channels == 2) // We consider panning
{
const float left = buffer->pan;
const float right = 1.0f - left;
// 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) };
// 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) };
float *frameOut = framesOut;
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[1] += (frameIn[1]*levels[1]);
frameOut += 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);
const float *frameIn = framesIn + (iFrame * nChannels);
float *frameOut = framesOut + (frame*channels);
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):
* [rcore] msf_gif (Miles Fogle) for GIF recording
* [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorythm
* [rcore] sdefl (Micha Mettke) for DEFLATE compression algorythm
* [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm
* [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm
* [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_resize (Sean Barret) for image resizing algorithms
@ -177,10 +177,10 @@
// Structures Definition
//----------------------------------------------------------------------------------
// Boolean type
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
#include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool)
typedef enum bool { false, true } bool;
typedef enum bool { false = 0, true = !false } bool;
#define RL_BOOL_TYPE
#endif
@ -322,7 +322,7 @@ typedef struct Mesh {
// Vertex attributes data
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 *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 *tangents; // Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4)
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
} Wave;
// Opaque structs declaration
// NOTE: Actual structs are defined internally in raudio module
typedef struct rAudioBuffer rAudioBuffer;
typedef struct rAudioProcessor rAudioProcessor;
// AudioStream, custom audio stream
typedef struct AudioStream {
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 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 void SetClipboardText(const char *text); // Set 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
// NOTE: Those functions are intended for advance users that want full control over the frame processing
@ -1036,6 +1042,7 @@ RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom
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 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 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
@ -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 *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 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 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 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 long GetFileModTime(const char *fileName); // Get file modification time (last write time)
// Compression/Encoding functionality
RLAPI unsigned char *CompressData(const unsigned char *data, int dataLength, int *compDataLength); // Compress data (DEFLATE algorithm)
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataLength, int *dataLength); // Decompress data (DEFLATE algorithm)
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataLength, int *outputLength); // Encode data to Base64 string
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputLength); // Decode Base64 string data
RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize); // Compress data (DEFLATE algorithm), memory must be MemFree()
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree()
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
// Persistent storage management
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 bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
// Text drawing functions
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)
@ -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 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 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 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
@ -1473,6 +1478,7 @@ RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3
//------------------------------------------------------------------------------------
// Audio Loading and Playing Functions (Module: audio)
//------------------------------------------------------------------------------------
typedef void (*AudioCallback)(void *bufferData, unsigned int frames);
// Audio device management functions
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 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 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)
}

View File

@ -18,7 +18,7 @@
* - Functions are always self-contained, no function use another raymath function inside,
* required code is directly re-implemented inside
* - 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
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
*
@ -77,6 +77,10 @@
#define PI 3.14159265358979323846f
#endif
#ifndef EPSILON
#define EPSILON 0.000001f
#endif
#ifndef DEG2RAD
#define DEG2RAD (PI/180.0f)
#endif
@ -194,6 +198,14 @@ RMAPI float Remap(float value, float inputStart, float inputEnd, float outputSta
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
//----------------------------------------------------------------------------------
@ -414,6 +426,62 @@ RMAPI Vector2 Vector2MoveTowards(Vector2 v, Vector2 target, float maxDistance)
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
//----------------------------------------------------------------------------------
@ -498,14 +566,14 @@ RMAPI Vector3 Vector3Perpendicular(Vector3 v)
float min = (float) fabs(v.x);
Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f};
if (fabs(v.y) < min)
if (fabsf(v.y) < min)
{
min = (float) fabs(v.y);
Vector3 tmp = {0.0f, 1.0f, 0.0f};
cardinalAxis = tmp;
}
if (fabs(v.z) < min)
if (fabsf(v.z) < min)
{
Vector3 tmp = {0.0f, 0.0f, 1.0f};
cardinalAxis = tmp;
@ -851,6 +919,92 @@ RMAPI float3 Vector3ToFloatV(Vector3 v)
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
//----------------------------------------------------------------------------------
@ -956,45 +1110,6 @@ RMAPI Matrix MatrixInvert(Matrix mat)
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
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;
if (lengthSq != 0.0)
if (lengthSq != 0.0f)
{
float invLength = 1.0f/lengthSq;
@ -1550,12 +1665,10 @@ RMAPI Quaternion QuaternionScale(Quaternion q, float mul)
{
Quaternion result = { 0 };
float qax = q.x, qay = q.y, qaz = q.z, qaw = q.w;
result.x = qax*mul + qaw*mul + qay*mul - qaz*mul;
result.y = qay*mul + qaw*mul + qaz*mul - qax*mul;
result.z = qaz*mul + qaw*mul + qax*mul - qay*mul;
result.w = qaw*mul - qax*mul - qay*mul - qaz*mul;
result.x = q.x*mul;
result.y = q.y*mul;
result.z = q.z*mul;
result.w = q.w*mul;
return result;
}
@ -1619,14 +1732,14 @@ RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
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
{
float halfTheta = acosf(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.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
RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle)
{
if (fabs(q.w) > 1.0f)
if (fabsf(q.w) > 1.0f)
{
// QuaternionNormalize(q);
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;
}
// 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

View File

@ -184,7 +184,7 @@
#include <stdlib.h> // Required for: srand(), rand(), atexit()
#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 <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
@ -227,7 +227,7 @@
unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#endif
#endif
#if defined(__linux__) || defined(__FreeBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#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
@ -247,6 +247,7 @@
//#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_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 <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 shouldClose; // Check if window set for closing
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)
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;
// 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.Mouse.scale = (Vector2){ 1.0f, 1.0f };
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
CORE.Input.Gamepad.lastButtonPressed = -1;
#if defined(SUPPORT_EVENTS_WAITING)
CORE.Window.eventWaiting = true;
#endif
#if defined(PLATFORM_ANDROID)
CORE.Window.screen.width = width;
@ -1211,39 +1217,39 @@ bool IsWindowState(unsigned int flag)
void ToggleFullscreen(void)
{
#if defined(PLATFORM_DESKTOP)
// NOTE: glfwSetWindowMonitor() doesn't work properly (bugs)
// TODO: glfwSetWindowMonitor() doesn't work properly (bugs)
if (!CORE.Window.fullscreen)
{
// Store previous window position (in case we exit fullscreen)
glfwGetWindowPos(CORE.Window.handle, &CORE.Window.position.x, &CORE.Window.position.y);
int monitorCount = 0;
GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
int monitorIndex = GetCurrentMonitor();
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
// 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");
CORE.Window.fullscreen = false; // Toggle fullscreen flag
CORE.Window.fullscreen = false;
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
glfwSetWindowMonitor(CORE.Window.handle, NULL, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
return;
}
CORE.Window.fullscreen = true; // Toggle fullscreen flag
else
{
CORE.Window.fullscreen = true;
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
{
CORE.Window.fullscreen = false; // Toggle fullscreen flag
CORE.Window.fullscreen = false;
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);
@ -1934,6 +1940,29 @@ const char *GetMonitorName(int monitor)
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
// NOTE: returned string is allocated and freed by GLFW
const char *GetClipboardText(void)
@ -1947,16 +1976,7 @@ const char *GetClipboardText(void)
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
void ShowCursor(void)
@ -2066,8 +2086,9 @@ void EndDrawing(void)
{
// Get image data for the current frame (from backbuffer)
// NOTE: This process is quite slow... :(
unsigned char *screenData = rlReadScreenPixels(CORE.Window.screen.width, CORE.Window.screen.height);
msf_gif_frame(&gifState, screenData, 10, 16, CORE.Window.screen.width*4);
Vector2 scale = GetWindowScaleDPI();
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
}
@ -2236,8 +2257,10 @@ void BeginTextureMode(RenderTexture2D 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);
rlSetFramebufferWidth(target.texture.width);
rlSetFramebufferHeight(target.texture.height);
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
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)
// ...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*(float)atan2f(device.vScreenSize*0.5f, device.eyeToScreenDistance);
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);
// Compute camera projection matrices
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;
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
@ -2787,8 +2810,9 @@ void SetConfigFlags(unsigned int flags)
void TakeScreenshot(const char *fileName)
{
#if defined(SUPPORT_MODULE_RTEXTURES)
unsigned char *imgData = rlReadScreenPixels(CORE.Window.render.width, CORE.Window.render.height);
Image image = { imgData, CORE.Window.render.width, CORE.Window.render.height, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
Vector2 scale = GetWindowScaleDPI();
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 };
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)
const char *GetFileNameWithoutExt(const char *filePath)
{
#define MAX_FILENAMEWITHOUTEXT_LENGTH 128
#define MAX_FILENAMEWITHOUTEXT_LENGTH 256
static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH] = { 0 };
memset(fileName, 0, MAX_FILENAMEWITHOUTEXT_LENGTH);
@ -3222,8 +3246,8 @@ long GetFileModTime(const char *fileName)
return 0;
}
// Compress data (DEFLATE algorythm)
unsigned char *CompressData(const unsigned char *data, int dataLength, int *compDataLength)
// Compress data (DEFLATE algorithm)
unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize)
{
#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)
// Compress data and generate a valid DEFLATE stream
struct sdefl sdefl = { 0 };
int bounds = sdefl_bound(dataLength);
int bounds = sdefl_bound(dataSize);
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
return compData;
}
// Decompress data (DEFLATE algorythm)
unsigned char *DecompressData(const unsigned char *compData, int compDataLength, int *dataLength)
// Decompress data (DEFLATE algorithm)
unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize)
{
unsigned char *data = NULL;
#if defined(SUPPORT_COMPRESSION_API)
// Decompress data from a valid DEFLATE stream
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);
if (temp != NULL) data = temp;
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
return data;
}
// 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[] = {
'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 };
*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;
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 octetB = (i < dataLength)? (unsigned char)data[i++] : 0;
unsigned int octetC = (i < dataLength)? (unsigned char)data[i++] : 0;
unsigned int octetA = (i < dataSize)? (unsigned char)data[i++] : 0;
unsigned int octetB = (i < dataSize)? (unsigned char)data[i++] : 0;
unsigned int octetC = (i < dataSize)? (unsigned char)data[i++] : 0;
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];
}
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;
}
// 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[] = {
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
int outLength = 0;
int outSize = 0;
for (int i = 0; data[4*i] != 0; i++)
{
if (data[4*i + 3] == '=')
{
if (data[4*i + 2] == '=') outLength += 1;
else outLength += 2;
if (data[4*i + 2] == '=') outSize += 1;
else outSize += 2;
}
else outLength += 3;
else outSize += 3;
}
// 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 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;
}
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 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 b = base64decodeTable[(int)data[4*n + 1]];
unsigned char c = base64decodeTable[(int)data[4*n + 2]];
decodedData[outLength - 2] = (a << 2) | (b >> 4);
decodedData[outLength - 1] = (b << 4) | (c >> 2);
decodedData[outSize - 2] = (a << 2) | (b >> 4);
decodedData[outSize - 1] = (b << 4) | (c >> 2);
}
*outputLength = outLength;
*outputSize = outSize;
return decodedData;
}
@ -3480,9 +3504,9 @@ void OpenURL(const char *url)
#if defined(PLATFORM_DESKTOP)
char *cmd = (char *)RL_CALLOC(strlen(url) + 10, sizeof(char));
#if defined(_WIN32)
sprintf(cmd, "explorer %s", url);
sprintf(cmd, "explorer \"%s\"", url);
#endif
#if defined(__linux__) || defined(__FreeBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
sprintf(cmd, "xdg-open '%s'", url); // Alternatives: firefox, x-www-browser
#endif
#if defined(__APPLE__)
@ -3494,6 +3518,29 @@ void OpenURL(const char *url)
#endif
#if defined(PLATFORM_WEB)
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
}
}
@ -4848,7 +4895,7 @@ void WaitTime(float ms)
#if defined(_WIN32)
Sleep((unsigned int)ms);
#endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
struct timespec req = { 0 };
time_t sec = (int)(ms/1000.0f);
ms -= (sec*1000);
@ -4867,7 +4914,7 @@ void WaitTime(float ms)
double currentTime = 0.0;
// 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
}
@ -4883,53 +4930,31 @@ void SwapScreenBuffer(void)
eglSwapBuffers(CORE.Window.device, CORE.Window.surface);
#if defined(PLATFORM_DRM)
if (!CORE.Window.gbmSurface || (-1 == CORE.Window.fd) || !CORE.Window.connector || !CORE.Window.crtc)
{
TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
abort();
}
if (!CORE.Window.gbmSurface || (-1 == CORE.Window.fd) || !CORE.Window.connector || !CORE.Window.crtc) TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
struct gbm_bo *bo = gbm_surface_lock_front_buffer(CORE.Window.gbmSurface);
if (!bo)
{
TRACELOG(LOG_ERROR, "DISPLAY: Failed GBM to lock front buffer");
abort();
}
if (!bo) TRACELOG(LOG_ERROR, "DISPLAY: Failed GBM to lock front buffer");
uint32_t fb = 0;
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);
if (0 != result)
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d", result);
abort();
}
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);
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d", result);
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]);
if (0 != result)
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d", result);
abort();
}
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]);
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d", result);
if (CORE.Window.prevFB)
{
result = drmModeRmFB(CORE.Window.fd, CORE.Window.prevFB);
if (0 != result)
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeRmFB() failed with result: %d", result);
abort();
}
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeRmFB() failed with result: %d", result);
}
CORE.Window.prevFB = fb;
if (CORE.Window.prevBO)
{
gbm_surface_release_buffer(CORE.Window.gbmSurface, CORE.Window.prevBO);
}
if (CORE.Window.prevBO) gbm_surface_release_buffer(CORE.Window.gbmSurface, CORE.Window.prevBO);
CORE.Window.prevBO = bo;
#endif // PLATFORM_DRM
#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)
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_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_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.1f);
CORE.Input.Gamepad.axisCount = GLFW_GAMEPAD_AXIS_LAST + 1;
}
@ -5086,11 +5111,8 @@ void PollInputEvents(void)
CORE.Window.resizedLastFrame = false;
#if defined(SUPPORT_EVENTS_WAITING)
glfwWaitEvents();
#else
glfwPollEvents(); // Register keyboard/mouse events (callbacks)... and window events!
#endif
if (CORE.Window.eventWaiting) glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks)
#endif // PLATFORM_DESKTOP
#if defined(PLATFORM_WEB)
@ -5514,7 +5536,8 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
gifRecording = true;
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++;
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
}
// GLFW3 Srolling Callback, runs on mouse wheel
// GLFW3 Scrolling Callback, runs on mouse wheel
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;
}
@ -6227,7 +6250,8 @@ static void InitEvdevInput(void)
{
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);
ConfigureEvdevDevice(path); // Configure the device if appropriate
@ -6387,7 +6411,7 @@ static void ConfigureEvdevDevice(char *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
// 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);
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
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,
(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");
continue;
@ -6850,23 +6874,22 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
continue;
}
if ((mode->hdisplay >= width) && (mode->vdisplay >= height) && (mode->vrefresh >= fps))
{
const int widthDiff = mode->hdisplay - width;
const int heightDiff = mode->vdisplay - height;
const int fpsDiff = mode->vrefresh - fps;
if (nearestIndex < 0)
{
nearestIndex = i;
continue;
}
const int nearestWidthDiff = CORE.Window.connector->modes[nearestIndex].hdisplay - width;
const int nearestHeightDiff = CORE.Window.connector->modes[nearestIndex].vdisplay - height;
const int nearestFpsDiff = CORE.Window.connector->modes[nearestIndex].vrefresh - fps;
const int widthDiff = abs(mode->hdisplay - width);
const int heightDiff = abs(mode->vdisplay - height);
const int fpsDiff = abs(mode->vrefresh - fps);
if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) nearestIndex = i;
const int nearestWidthDiff = abs(CORE.Window.connector->modes[nearestIndex].hdisplay - width);
const int nearestHeightDiff = abs(CORE.Window.connector->modes[nearestIndex].vdisplay - height);
const int nearestFpsDiff = abs(CORE.Window.connector->modes[nearestIndex].vrefresh - fps);
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)
// NOTE: Loading happens over AutomationEvent *events
// TODO: This system should probably be redesigned
static void LoadAutomationEvents(const char *fileName)
{
//unsigned char fileId[4] = { 0 };

View File

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

View File

@ -358,11 +358,11 @@ typedef struct rlRenderBatch {
float currentDepth; // Current depth value for next draw
} rlRenderBatch;
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
#include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
// Boolean type
typedef enum bool { false, true } bool;
typedef enum bool { false = 0, true = !false } bool;
#endif
#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 rlLoadExtensions(void *loader); // Load OpenGL extensions (loader function required)
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 void rlSetFramebufferHeight(int height); // Set current framebuffer height
RLAPI int rlGetFramebufferHeight(void); // Get default framebuffer height
RLAPI unsigned int rlGetTextureIdDefault(void); // Get default texture id
@ -927,8 +929,8 @@ typedef struct rlglData {
int glBlendDstFactor; // Blending destination factor
int glBlendEquation; // Blending equation
int framebufferWidth; // Default framebuffer width
int framebufferHeight; // Default framebuffer height
int framebufferWidth; // Current framebuffer width
int framebufferHeight; // Current framebuffer height
} State; // Renderer state
struct {
@ -1230,6 +1232,7 @@ void rlOrtho(double left, double right, double bottom, double top, double znear,
#endif
// 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)
{
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);
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);
}
else TRACELOG(RL_LOG_WARNING, "GL: Anisotropic filtering not supported");
@ -2219,6 +2222,22 @@ int rlGetVersion(void)
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
int rlGetFramebufferWidth(void)
{
@ -2601,6 +2620,9 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
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
@ -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 ((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
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 colorTint = WHITE;
colorTint.r = (unsigned char)((((float)color.r/255.0)*((float)tint.r/255.0))*255.0f);
colorTint.g = (unsigned char)((((float)color.g/255.0)*((float)tint.g/255.0))*255.0f);
colorTint.b = (unsigned char)((((float)color.b/255.0)*((float)tint.b/255.0))*255.0f);
colorTint.a = (unsigned char)((((float)color.a/255.0)*((float)tint.a/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.0f)*((float)tint.g/255.0f))*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.0f)*((float)tint.a/255.0f))*255.0f);
model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = colorTint;
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;
}
// 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
// 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
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 };
Vector3 edge1 = { 0 };
@ -4662,7 +4643,6 @@ static Model LoadGLTF(const char *fileName)
// Load our model data: meshes and materials
model.meshCount = primitivesCount;
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
model.materialCount = (int)data->materials_count + 1;

View File

@ -25,7 +25,7 @@
*
* DEPENDENCIES:
* 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
@ -229,7 +229,7 @@ extern void LoadFontDefault(void)
//------------------------------------------------------------------------------
// 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.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...
//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 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_node *nodes = (stbrp_node *)RL_MALLOC(glyphCount*sizeof(*nodes));
@ -992,11 +992,11 @@ bool ExportFontAsCode(Font font, const char *fileName)
// NOTE: Uses default font
void DrawFPS(int posX, int posY)
{
Color color = LIME; // good fps
Color color = LIME; // Good FPS
int fps = GetFPS();
if (fps < 30 && fps >= 15) color = ORANGE; // warning FPS
else if (fps < 15) color = RED; // bad FPS
if ((fps < 30) && (fps >= 15)) color = ORANGE; // Warning FPS
else if (fps < 15) color = RED; // Low FPS
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
// 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)
{
// 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
// WARNING: Allocated memory should be manually freed
// WARNING: Allocated memory must be manually freed
char *TextInsert(const char *text, const char *insert, int position)
{
int textLen = TextLength(text);
@ -1616,7 +1616,7 @@ const char *TextToPascal(const char *text)
// Encode text codepoint into UTF-8 text
// REQUIRES: memcpy()
// WARNING: Allocated memory should be manually freed
// WARNING: Allocated memory must be manually freed
char *TextCodepointsToUTF8(const int *codepoints, int length)
{
// We allocate enough memory fo fit all possible codepoints

View File

@ -37,7 +37,7 @@
* DEPENDENCIES:
* stb_image - Multiple image formats loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
* 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
@ -306,10 +306,9 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
{
Image image = { 0 };
#if defined(SUPPORT_FILEFORMAT_PNG)
if ((strcmp(fileType, ".png") == 0)
#else
if ((false)
#if defined(SUPPORT_FILEFORMAT_PNG)
|| (strcmp(fileType, ".png") == 0)
#endif
#if defined(SUPPORT_FILEFORMAT_BMP)
|| (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 a = (unsigned char)(((float)pixels[index].a/255*cA)*255.0f);
pixels[y*image->width + x].r = r;
pixels[y*image->width + x].g = g;
pixels[y*image->width + x].b = b;
pixels[y*image->width + x].a = a;
pixels[index].r = r;
pixels[index].g = g;
pixels[index].b = b;
pixels[index].a = a;
}
}
@ -1959,25 +1958,25 @@ void ImageColorContrast(Image *image, float contrast)
for (int x = 0; x < image->width; x++)
{
float pR = (float)pixels[y*image->width + x].r/255.0f;
pR -= 0.5;
pR -= 0.5f;
pR *= contrast;
pR += 0.5;
pR += 0.5f;
pR *= 255;
if (pR < 0) pR = 0;
if (pR > 255) pR = 255;
float pG = (float)pixels[y*image->width + x].g/255.0f;
pG -= 0.5;
pG -= 0.5f;
pG *= contrast;
pG += 0.5;
pG += 0.5f;
pG *= 255;
if (pG < 0) pG = 0;
if (pG > 255) pG = 255;
float pB = (float)pixels[y*image->width + x].b/255.0f;
pB -= 0.5;
pB -= 0.5f;
pB *= contrast;
pB += 0.5;
pB += 0.5f;
pB *= 255;
if (pB < 0) pB = 0;
if (pB > 255) pB = 255;
@ -2412,7 +2411,20 @@ Color GetImageColor(Image image, int x, int y)
// Clear image background with given 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
@ -2686,13 +2698,21 @@ void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color)
int ey = sy + (int)rec.height;
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 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.y = (nPatchInfo.source.y + nPatchInfo.source.height)/height;
rlCheckRenderBatchLimit(9 * 3 * 2); // Maxium number of verts that could happen
rlSetTexture(texture.id);
rlPushMatrix();

21
src/switch-nx/dlfcn.h Normal file
View File

@ -0,0 +1,21 @@
/*
Required file to make miniaudio.h compile to Switch
*/
#define RTLD_LAZY 0x00001
#define RTLD_NOW 0x00002
#define RTLD_BINDING_MASK 0x3
#define RTLD_NOLOAD 0x00004
#define RTLD_DEEPBIND 0x00008
#define RTLD_GLOBAL 0x00100
#define RTLD_LOCAL 0
#define RTLD_NODELETE 0x01000
void *dlopen(const char *, int);
void *dlsym(void *, const char *);
int dlclose(void *);
char *dlerror(void);
int pthread_attr_setschedpolicy(pthread_attr_t *, int) { return 0; }
int sched_get_priority_max(int policy) { return 0; }
int sched_get_priority_min(int policy) { return 0; }

View File

@ -148,6 +148,7 @@ void TraceLog(int logType, const char *text, ...)
strcat(buffer, text);
strcat(buffer, "\n");
vprintf(buffer, args);
fflush(stdout);
#endif
va_end(args);
@ -268,6 +269,51 @@ bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
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
// NOTE: text chars array should be freed manually
char *LoadFileText(const char *fileName)