Merge pull request #472 from JupiterRider/raylib_55

WIP: Update to raylib 5.5
This commit is contained in:
Milan Nikolic 2024-12-02 11:36:52 +01:00 committed by GitHub
commit 5d50abe7c6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
58 changed files with 12446 additions and 10777 deletions

View file

@ -66,11 +66,12 @@
#define SUPPORT_COMPRESSION_API 1 #define SUPPORT_COMPRESSION_API 1
// Support automatic generated events, loading and recording of those events when required // Support automatic generated events, loading and recording of those events when required
#define SUPPORT_AUTOMATION_EVENTS 1 #define SUPPORT_AUTOMATION_EVENTS 1
// Support custom frame control, only for advance users // Support custom frame control, only for advanced users
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents() // By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
// Enabling this flag allows manual control of the frame processes, use at your own risk // Enabling this flag allows manual control of the frame processes, use at your own risk
//#define SUPPORT_CUSTOM_FRAME_CONTROL 1 //#define SUPPORT_CUSTOM_FRAME_CONTROL 1
// rcore: Configuration values // rcore: Configuration values
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#define MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity #define MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity
@ -100,6 +101,8 @@
// Show OpenGL extensions and capabilities detailed logs on init // Show OpenGL extensions and capabilities detailed logs on init
//#define RLGL_SHOW_GL_DETAILS_INFO 1 //#define RLGL_SHOW_GL_DETAILS_INFO 1
#define RL_SUPPORT_MESH_GPU_SKINNING 1 // GPU skinning, comment if your GPU does not support more than 8 VBOs
//#define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 4096 // Default internal render batch elements limits //#define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 4096 // Default internal render batch elements limits
#define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering)
#define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture)
@ -113,12 +116,17 @@
#define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
// Default shader vertex attribute locations // Default shader vertex attribute locations
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6
#if defined(RL_SUPPORT_MESH_GPU_SKINNING)
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
#endif
// Default shader vertex attribute names to set location points // Default shader vertex attribute names to set location points
// NOTE: When a new shader is loaded, the following locations are tried to be set for convenience // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience
@ -170,7 +178,6 @@
//#define SUPPORT_FILEFORMAT_ASTC 1 //#define SUPPORT_FILEFORMAT_ASTC 1
//#define SUPPORT_FILEFORMAT_PKM 1 //#define SUPPORT_FILEFORMAT_PKM 1
//#define SUPPORT_FILEFORMAT_PVR 1 //#define SUPPORT_FILEFORMAT_PVR 1
//#define SUPPORT_FILEFORMAT_SVG 1
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi) // Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
#define SUPPORT_IMAGE_EXPORT 1 #define SUPPORT_IMAGE_EXPORT 1
@ -225,7 +232,12 @@
// rmodels: Configuration values // rmodels: Configuration values
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported #define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
#define MAX_MESH_VERTEX_BUFFERS 9 // Maximum vertex buffers (VBO) per mesh
#else
#define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh #define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh
#endif
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Module: raudio - Configuration Flags // Module: raudio - Configuration Flags
@ -261,4 +273,31 @@
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#define MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message #define MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message
// Enable partial support for clipboard image, only working on SDL3 or
// being on both Windows OS + GLFW or Windows OS + RGFW
#define SUPPORT_CLIPBOARD_IMAGE 1
#if defined(SUPPORT_CLIPBOARD_IMAGE)
#ifndef STBI_REQUIRED
#define STBI_REQUIRED
#endif
#ifndef SUPPORT_FILEFORMAT_BMP // For clipboard image on Windows
#define SUPPORT_FILEFORMAT_BMP 1
#endif
#ifndef SUPPORT_FILEFORMAT_PNG // Wayland uses png for prints, at least it was on 22 LTS ubuntu
#define SUPPORT_FILEFORMAT_PNG 1
#endif
#ifndef SUPPORT_FILEFORMAT_JPG
#define SUPPORT_FILEFORMAT_JPG 1
#endif
#ifndef SUPPORT_MODULE_RTEXTURES
#define SUPPORT_MODULE_RTEXTURES 1
#endif
#endif
#endif // CONFIG_H #endif // CONFIG_H

9160
raylib/external/RGFW.h vendored

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/** /**
* cgltf - a single-file glTF 2.0 parser written in C99. * cgltf - a single-file glTF 2.0 parser written in C99.
* *
* Version: 1.13 * Version: 1.14
* *
* Website: https://github.com/jkuhlmann/cgltf * Website: https://github.com/jkuhlmann/cgltf
* *
@ -395,6 +395,8 @@ typedef struct cgltf_texture
cgltf_sampler* sampler; cgltf_sampler* sampler;
cgltf_bool has_basisu; cgltf_bool has_basisu;
cgltf_image* basisu_image; cgltf_image* basisu_image;
cgltf_bool has_webp;
cgltf_image* webp_image;
cgltf_extras extras; cgltf_extras extras;
cgltf_size extensions_count; cgltf_size extensions_count;
cgltf_extension* extensions; cgltf_extension* extensions;
@ -1697,7 +1699,20 @@ cgltf_result cgltf_validate(cgltf_data* data)
{ {
if (data->nodes[i].weights && data->nodes[i].mesh) if (data->nodes[i].weights && data->nodes[i].mesh)
{ {
CGLTF_ASSERT_IF (data->nodes[i].mesh->primitives_count && data->nodes[i].mesh->primitives[0].targets_count != data->nodes[i].weights_count, cgltf_result_invalid_gltf); CGLTF_ASSERT_IF(data->nodes[i].mesh->primitives_count && data->nodes[i].mesh->primitives[0].targets_count != data->nodes[i].weights_count, cgltf_result_invalid_gltf);
}
if (data->nodes[i].has_mesh_gpu_instancing)
{
CGLTF_ASSERT_IF(data->nodes[i].mesh == NULL, cgltf_result_invalid_gltf);
CGLTF_ASSERT_IF(data->nodes[i].mesh_gpu_instancing.attributes_count == 0, cgltf_result_invalid_gltf);
cgltf_accessor* first = data->nodes[i].mesh_gpu_instancing.attributes[0].data;
for (cgltf_size k = 0; k < data->nodes[i].mesh_gpu_instancing.attributes_count; ++k)
{
CGLTF_ASSERT_IF(data->nodes[i].mesh_gpu_instancing.attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
}
} }
} }
@ -4538,6 +4553,34 @@ static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tok
} }
} }
} }
else if (cgltf_json_strcmp(tokens + i, json_chunk, "EXT_texture_webp") == 0)
{
out_texture->has_webp = 1;
++i;
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
int num_properties = tokens[i].size;
++i;
for (int t = 0; t < num_properties; ++t)
{
CGLTF_CHECK_KEY(tokens[i]);
if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
{
++i;
out_texture->webp_image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
++i;
}
else
{
i = cgltf_skip_json(tokens, i + 1);
}
if (i < 0)
{
return i;
}
}
}
else else
{ {
i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture->extensions[out_texture->extensions_count++])); i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture->extensions[out_texture->extensions_count++]));
@ -6548,6 +6591,7 @@ static int cgltf_fixup_pointers(cgltf_data* data)
{ {
CGLTF_PTRFIXUP(data->textures[i].image, data->images, data->images_count); CGLTF_PTRFIXUP(data->textures[i].image, data->images, data->images_count);
CGLTF_PTRFIXUP(data->textures[i].basisu_image, data->images, data->images_count); CGLTF_PTRFIXUP(data->textures[i].basisu_image, data->images, data->images_count);
CGLTF_PTRFIXUP(data->textures[i].webp_image, data->images, data->images_count);
CGLTF_PTRFIXUP(data->textures[i].sampler, data->samplers, data->samplers_count); CGLTF_PTRFIXUP(data->textures[i].sampler, data->samplers, data->samplers_count);
} }

View file

@ -1,6 +1,6 @@
/* /*
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file. MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_mp3 - v0.6.38 - 2023-11-02 dr_mp3 - v0.6.39 - 2024-02-27
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
@ -95,7 +95,7 @@ extern "C" {
#define DRMP3_VERSION_MAJOR 0 #define DRMP3_VERSION_MAJOR 0
#define DRMP3_VERSION_MINOR 6 #define DRMP3_VERSION_MINOR 6
#define DRMP3_VERSION_REVISION 38 #define DRMP3_VERSION_REVISION 39
#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION) #define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
#include <stddef.h> /* For size_t. */ #include <stddef.h> /* For size_t. */
@ -1985,8 +1985,8 @@ static drmp3_int16 drmp3d_scale_pcm(float sample)
s32 -= (s32 < 0); s32 -= (s32 < 0);
s = (drmp3_int16)drmp3_clip_int16_arm(s32); s = (drmp3_int16)drmp3_clip_int16_arm(s32);
#else #else
if (sample >= 32766.5) return (drmp3_int16) 32767; if (sample >= 32766.5f) return (drmp3_int16) 32767;
if (sample <= -32767.5) return (drmp3_int16)-32768; if (sample <= -32767.5f) return (drmp3_int16)-32768;
s = (drmp3_int16)(sample + .5f); s = (drmp3_int16)(sample + .5f);
s -= (s < 0); /* away from zero, to be compliant */ s -= (s < 0); /* away from zero, to be compliant */
#endif #endif
@ -2404,9 +2404,9 @@ DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num
for(; i < num_samples; i++) for(; i < num_samples; i++)
{ {
float sample = in[i] * 32768.0f; float sample = in[i] * 32768.0f;
if (sample >= 32766.5) if (sample >= 32766.5f)
out[i] = (drmp3_int16) 32767; out[i] = (drmp3_int16) 32767;
else if (sample <= -32767.5) else if (sample <= -32767.5f)
out[i] = (drmp3_int16)-32768; out[i] = (drmp3_int16)-32768;
else else
{ {
@ -4495,6 +4495,9 @@ counts rather than sample counts.
/* /*
REVISION HISTORY REVISION HISTORY
================ ================
v0.6.39 - 2024-02-27
- Fix a Wdouble-promotion warning.
v0.6.38 - 2023-11-02 v0.6.38 - 2023-11-02
- Fix build for ARMv6-M. - Fix build for ARMv6-M.

View file

@ -1,6 +1,6 @@
/* /*
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file. WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_wav - v0.13.13 - 2023-11-02 dr_wav - v0.13.16 - 2024-02-27
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
@ -147,7 +147,7 @@ extern "C" {
#define DRWAV_VERSION_MAJOR 0 #define DRWAV_VERSION_MAJOR 0
#define DRWAV_VERSION_MINOR 13 #define DRWAV_VERSION_MINOR 13
#define DRWAV_VERSION_REVISION 13 #define DRWAV_VERSION_REVISION 16
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION) #define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
#include <stddef.h> /* For size_t. */ #include <stddef.h> /* For size_t. */
@ -3075,7 +3075,13 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx) { if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx) {
if (drwav_bytes_to_u32_ex(chunkSizeBytes, pWav->container) < 36) { if (drwav_bytes_to_u32_ex(chunkSizeBytes, pWav->container) < 36) {
return DRWAV_FALSE; /* Chunk size should always be at least 36 bytes. */ /*
I've had a report of a WAV file failing to load when the size of the WAVE chunk is not encoded
and is instead just set to 0. I'm going to relax the validation here to allow these files to
load. Considering the chunk size isn't actually used this should be safe. With this change my
test suite still passes.
*/
/*return DRWAV_FALSE;*/ /* Chunk size should always be at least 36 bytes. */
} }
} else if (pWav->container == drwav_container_rf64) { } else if (pWav->container == drwav_container_rf64) {
if (drwav_bytes_to_u32_le(chunkSizeBytes) != 0xFFFFFFFF) { if (drwav_bytes_to_u32_le(chunkSizeBytes) != 0xFFFFFFFF) {
@ -3554,10 +3560,7 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
/* Getting here means it's not a chunk that we care about internally, but might need to be handled as metadata by the caller. */ /* Getting here means it's not a chunk that we care about internally, but might need to be handled as metadata by the caller. */
if (isProcessingMetadata) { if (isProcessingMetadata) {
drwav_uint64 metadataBytesRead; drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
metadataBytesRead = drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
DRWAV_ASSERT(metadataBytesRead <= header.sizeInBytes);
/* Go back to the start of the chunk so we can normalize the position of the cursor. */ /* Go back to the start of the chunk so we can normalize the position of the cursor. */
if (drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData) == DRWAV_FALSE) { if (drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData) == DRWAV_FALSE) {
@ -7830,7 +7833,7 @@ DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t samp
} }
for (i = 0; i < sampleCount; ++i) { for (i = 0; i < sampleCount; ++i) {
*pOut++ = (drwav_int32)(2147483648.0 * pIn[i]); *pOut++ = (drwav_int32)(2147483648.0f * pIn[i]);
} }
} }
@ -8347,6 +8350,15 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
/* /*
REVISION HISTORY REVISION HISTORY
================ ================
v0.13.16 - 2024-02-27
- Fix a Wdouble-promotion warning.
v0.13.15 - 2024-01-23
- Relax some unnecessary validation that prevented some files from loading.
v0.13.14 - 2023-12-02
- Fix a warning about an unused variable.
v0.13.13 - 2023-11-02 v0.13.13 - 2023-11-02
- Fix a warning when compiling with Clang. - Fix a warning when compiling with Clang.

View file

@ -1,7 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.4 macOS - www.glfw.org // GLFW 3.4 macOS (modified for raylib) - www.glfw.org; www.raylib.com
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -175,7 +176,7 @@ static void createMenuBar(void)
// Create key code translation tables // Create key code translation tables
// //
static void createKeyTables(void) static void createKeyTablesCocoa(void)
{ {
memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes)); memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes)); memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
@ -618,7 +619,7 @@ int _glfwInitCocoa(void)
name:NSTextInputContextKeyboardSelectionDidChangeNotification name:NSTextInputContextKeyboardSelectionDidChangeNotification
object:nil]; object:nil];
createKeyTables(); createKeyTablesCocoa();
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); _glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
if (!_glfw.ns.eventSource) if (!_glfw.ns.eventSource)

View file

@ -1,8 +1,9 @@
//======================================================================== //========================================================================
// GLFW 3.4 macOS - www.glfw.org // GLFW 3.4 macOS (modified for raylib) - www.glfw.org; www.raylib.com
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages

View file

@ -111,7 +111,7 @@ static void updateCursorMode(_GLFWwindow* window)
// Make the specified window and its video mode active on its monitor // Make the specified window and its video mode active on its monitor
// //
static void acquireMonitor(_GLFWwindow* window) static void acquireMonitorCocoa(_GLFWwindow* window)
{ {
_glfwSetVideoModeCocoa(window->monitor, &window->videoMode); _glfwSetVideoModeCocoa(window->monitor, &window->videoMode);
const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID); const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
@ -127,7 +127,7 @@ static void acquireMonitor(_GLFWwindow* window)
// Remove the window and restore the original video mode // Remove the window and restore the original video mode
// //
static void releaseMonitor(_GLFWwindow* window) static void releaseMonitorCocoa(_GLFWwindow* window)
{ {
if (window->monitor->window != window) if (window->monitor->window != window)
return; return;
@ -158,7 +158,7 @@ static int translateFlags(NSUInteger flags)
// Translates a macOS keycode to a GLFW keycode // Translates a macOS keycode to a GLFW keycode
// //
static int translateKey(unsigned int key) static int translateKeyCocoa(unsigned int key)
{ {
if (key >= sizeof(_glfw.ns.keycodes) / sizeof(_glfw.ns.keycodes[0])) if (key >= sizeof(_glfw.ns.keycodes) / sizeof(_glfw.ns.keycodes[0]))
return GLFW_KEY_UNKNOWN; return GLFW_KEY_UNKNOWN;
@ -277,7 +277,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidMiniaturize:(NSNotification *)notification - (void)windowDidMiniaturize:(NSNotification *)notification
{ {
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitorCocoa(window);
_glfwInputWindowIconify(window, GLFW_TRUE); _glfwInputWindowIconify(window, GLFW_TRUE);
} }
@ -285,7 +285,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidDeminiaturize:(NSNotification *)notification - (void)windowDidDeminiaturize:(NSNotification *)notification
{ {
if (window->monitor) if (window->monitor)
acquireMonitor(window); acquireMonitorCocoa(window);
_glfwInputWindowIconify(window, GLFW_FALSE); _glfwInputWindowIconify(window, GLFW_FALSE);
} }
@ -561,7 +561,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)keyDown:(NSEvent *)event - (void)keyDown:(NSEvent *)event
{ {
const int key = translateKey([event keyCode]); const int key = translateKeyCocoa([event keyCode]);
const int mods = translateFlags([event modifierFlags]); const int mods = translateFlags([event modifierFlags]);
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods); _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
@ -574,7 +574,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
int action; int action;
const unsigned int modifierFlags = const unsigned int modifierFlags =
[event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
const int key = translateKey([event keyCode]); const int key = translateKeyCocoa([event keyCode]);
const int mods = translateFlags(modifierFlags); const int mods = translateFlags(modifierFlags);
const NSUInteger keyFlag = translateKeyToModifierFlag(key); const NSUInteger keyFlag = translateKeyToModifierFlag(key);
@ -593,7 +593,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)keyUp:(NSEvent *)event - (void)keyUp:(NSEvent *)event
{ {
const int key = translateKey([event keyCode]); const int key = translateKeyCocoa([event keyCode]);
const int mods = translateFlags([event modifierFlags]); const int mods = translateFlags([event modifierFlags]);
_glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods); _glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods);
} }
@ -966,7 +966,7 @@ GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window,
{ {
_glfwShowWindowCocoa(window); _glfwShowWindowCocoa(window);
_glfwFocusWindowCocoa(window); _glfwFocusWindowCocoa(window);
acquireMonitor(window); acquireMonitorCocoa(window);
if (wndconfig->centerCursor) if (wndconfig->centerCursor)
_glfwCenterCursorInContentArea(window); _glfwCenterCursorInContentArea(window);
@ -996,7 +996,7 @@ void _glfwDestroyWindowCocoa(_GLFWwindow* window)
[window->ns.object orderOut:nil]; [window->ns.object orderOut:nil];
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitorCocoa(window);
if (window->context.destroy) if (window->context.destroy)
window->context.destroy(window); window->context.destroy(window);
@ -1083,7 +1083,7 @@ void _glfwSetWindowSizeCocoa(_GLFWwindow* window, int width, int height)
if (window->monitor) if (window->monitor)
{ {
if (window->monitor->window == window) if (window->monitor->window == window)
acquireMonitor(window); acquireMonitorCocoa(window);
} }
else else
{ {
@ -1252,7 +1252,7 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
if (monitor) if (monitor)
{ {
if (monitor->window == window) if (monitor->window == window)
acquireMonitor(window); acquireMonitorCocoa(window);
} }
else else
{ {
@ -1270,7 +1270,7 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
} }
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitorCocoa(window);
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
@ -1308,7 +1308,7 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
[window->ns.object setLevel:NSMainMenuWindowLevel + 1]; [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
[window->ns.object setHasShadow:NO]; [window->ns.object setHasShadow:NO];
acquireMonitor(window); acquireMonitorCocoa(window);
} }
else else
{ {

View file

@ -996,6 +996,7 @@ const char* _glfwDefaultMappings[] =
"03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,", "03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,",
"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux,",
#endif // GLFW_BUILD_LINUX_JOYSTICK #endif // GLFW_BUILD_LINUX_JOYSTICK
}; };

82
raylib/external/glfw/src/mappings.h.in vendored Normal file
View file

@ -0,0 +1,82 @@
//========================================================================
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
// As mappings.h.in, this file is used by CMake to produce the mappings.h
// header file. If you are adding a GLFW specific gamepad mapping, this is
// where to put it.
//========================================================================
// As mappings.h, this provides all pre-defined gamepad mappings, including
// all available in SDL_GameControllerDB. Do not edit this file. Any gamepad
// mappings not specific to GLFW should be submitted to SDL_GameControllerDB.
// This file can be re-generated from mappings.h.in and the upstream
// gamecontrollerdb.txt with the 'update_mappings' CMake target.
//========================================================================
// All gamepad mappings not labeled GLFW are copied from the
// SDL_GameControllerDB project under the following license:
//
// Simple DirectMedia Layer
// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the
// use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
const char* _glfwDefaultMappings[] =
{
#if defined(_GLFW_WIN32)
@GLFW_WIN32_MAPPINGS@
"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
#endif // _GLFW_WIN32
#if defined(_GLFW_COCOA)
@GLFW_COCOA_MAPPINGS@
#endif // _GLFW_COCOA
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
@GLFW_LINUX_MAPPINGS@
#endif // GLFW_BUILD_LINUX_JOYSTICK
};

View file

@ -1,8 +1,9 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.4 (modified for raylib) - www.glfw.org; www.raylib.com
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -59,12 +60,12 @@ static void fitToMonitor(_GLFWwindow* window)
window->null.height = mode.height; window->null.height = mode.height;
} }
static void acquireMonitor(_GLFWwindow* window) static void acquireMonitorNull(_GLFWwindow* window)
{ {
_glfwInputMonitorWindow(window->monitor, window); _glfwInputMonitorWindow(window->monitor, window);
} }
static void releaseMonitor(_GLFWwindow* window) static void releaseMonitorNull(_GLFWwindow* window)
{ {
if (window->monitor->window != window) if (window->monitor->window != window)
return; return;
@ -147,7 +148,7 @@ GLFWbool _glfwCreateWindowNull(_GLFWwindow* window,
{ {
_glfwShowWindowNull(window); _glfwShowWindowNull(window);
_glfwFocusWindowNull(window); _glfwFocusWindowNull(window);
acquireMonitor(window); acquireMonitorNull(window);
if (wndconfig->centerCursor) if (wndconfig->centerCursor)
_glfwCenterCursorInContentArea(window); _glfwCenterCursorInContentArea(window);
@ -168,7 +169,7 @@ GLFWbool _glfwCreateWindowNull(_GLFWwindow* window,
void _glfwDestroyWindowNull(_GLFWwindow* window) void _glfwDestroyWindowNull(_GLFWwindow* window)
{ {
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitorNull(window);
if (_glfw.null.focusedWindow == window) if (_glfw.null.focusedWindow == window)
_glfw.null.focusedWindow = NULL; _glfw.null.focusedWindow = NULL;
@ -203,14 +204,14 @@ void _glfwSetWindowMonitorNull(_GLFWwindow* window,
} }
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitorNull(window);
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
if (window->monitor) if (window->monitor)
{ {
window->null.visible = GLFW_TRUE; window->null.visible = GLFW_TRUE;
acquireMonitor(window); acquireMonitorNull(window);
fitToMonitor(window); fitToMonitor(window);
} }
else else
@ -340,7 +341,7 @@ void _glfwIconifyWindowNull(_GLFWwindow* window)
_glfwInputWindowIconify(window, GLFW_TRUE); _glfwInputWindowIconify(window, GLFW_TRUE);
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitorNull(window);
} }
} }
@ -352,7 +353,7 @@ void _glfwRestoreWindowNull(_GLFWwindow* window)
_glfwInputWindowIconify(window, GLFW_FALSE); _glfwInputWindowIconify(window, GLFW_FALSE);
if (window->monitor) if (window->monitor)
acquireMonitor(window); acquireMonitorNull(window);
} }
else if (window->null.maximized) else if (window->null.maximized)
{ {

View file

@ -1,8 +1,9 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.4 (modified for raylib) - www.glfw.org; www.raylib.com
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -74,15 +75,6 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)
return GLFW_FALSE; return GLFW_FALSE;
} }
// Only allow the Null platform if specifically requested
if (desiredID == GLFW_PLATFORM_NULL)
return _glfwConnectNull(desiredID, platform);
else if (count == 0)
{
_glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "This binary only supports the Null platform");
return GLFW_FALSE;
}
#if defined(_GLFW_WAYLAND) && defined(_GLFW_X11) #if defined(_GLFW_WAYLAND) && defined(_GLFW_X11)
if (desiredID == GLFW_ANY_PLATFORM) if (desiredID == GLFW_ANY_PLATFORM)
{ {

View file

@ -1,8 +1,9 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 - www.glfw.org // GLFW 3.4 Win32 (modified for raylib) - www.glfw.org; www.raylib.com
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -195,7 +196,7 @@ static void freeLibraries(void)
// Create key code translation tables // Create key code translation tables
// //
static void createKeyTables(void) static void createKeyTablesWin32(void)
{ {
int scancode; int scancode;
@ -685,7 +686,7 @@ int _glfwInitWin32(void)
if (!loadLibraries()) if (!loadLibraries())
return GLFW_FALSE; return GLFW_FALSE;
createKeyTables(); createKeyTablesWin32();
_glfwUpdateKeyNamesWin32(); _glfwUpdateKeyNamesWin32();
if (_glfwIsWindows10Version1703OrGreaterWin32()) if (_glfwIsWindows10Version1703OrGreaterWin32())

View file

@ -1,8 +1,9 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 - www.glfw.org // GLFW 3.4 Win32 (modified for raylib) - www.glfw.org; www.raylib.com
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -439,7 +440,7 @@ static void fitToMonitor(_GLFWwindow* window)
// Make the specified window and its video mode active on its monitor // Make the specified window and its video mode active on its monitor
// //
static void acquireMonitor(_GLFWwindow* window) static void acquireMonitorWin32(_GLFWwindow* window)
{ {
if (!_glfw.win32.acquiredMonitorCount) if (!_glfw.win32.acquiredMonitorCount)
{ {
@ -460,7 +461,7 @@ static void acquireMonitor(_GLFWwindow* window)
// Remove the window and restore the original video mode // Remove the window and restore the original video mode
// //
static void releaseMonitor(_GLFWwindow* window) static void releaseMonitorWin32(_GLFWwindow* window)
{ {
if (window->monitor->window != window) if (window->monitor->window != window)
return; return;
@ -470,7 +471,7 @@ static void releaseMonitor(_GLFWwindow* window)
{ {
SetThreadExecutionState(ES_CONTINUOUS); SetThreadExecutionState(ES_CONTINUOUS);
// HACK: Restore mouse trail length saved in acquireMonitor // HACK: Restore mouse trail length saved in acquireMonitorWin32
SystemParametersInfoW(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0); SystemParametersInfoW(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
} }
@ -1050,10 +1051,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
if (window->monitor && window->win32.iconified != iconified) if (window->monitor && window->win32.iconified != iconified)
{ {
if (iconified) if (iconified)
releaseMonitor(window); releaseMonitorWin32(window);
else else
{ {
acquireMonitor(window); acquireMonitorWin32(window);
fitToMonitor(window); fitToMonitor(window);
} }
} }
@ -1534,7 +1535,7 @@ GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
{ {
_glfwShowWindowWin32(window); _glfwShowWindowWin32(window);
_glfwFocusWindowWin32(window); _glfwFocusWindowWin32(window);
acquireMonitor(window); acquireMonitorWin32(window);
fitToMonitor(window); fitToMonitor(window);
if (wndconfig->centerCursor) if (wndconfig->centerCursor)
@ -1556,7 +1557,7 @@ GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
void _glfwDestroyWindowWin32(_GLFWwindow* window) void _glfwDestroyWindowWin32(_GLFWwindow* window)
{ {
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitorWin32(window);
if (window->context.destroy) if (window->context.destroy)
window->context.destroy(window); window->context.destroy(window);
@ -1677,7 +1678,7 @@ void _glfwSetWindowSizeWin32(_GLFWwindow* window, int width, int height)
{ {
if (window->monitor->window == window) if (window->monitor->window == window)
{ {
acquireMonitor(window); acquireMonitorWin32(window);
fitToMonitor(window); fitToMonitor(window);
} }
} }
@ -1849,7 +1850,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
{ {
if (monitor->window == window) if (monitor->window == window)
{ {
acquireMonitor(window); acquireMonitorWin32(window);
fitToMonitor(window); fitToMonitor(window);
} }
} }
@ -1879,7 +1880,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
} }
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitorWin32(window);
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
@ -1897,7 +1898,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
flags |= SWP_FRAMECHANGED; flags |= SWP_FRAMECHANGED;
} }
acquireMonitor(window); acquireMonitorWin32(window);
GetMonitorInfoW(window->monitor->win32.handle, &mi); GetMonitorInfoW(window->monitor->win32.handle, &mi);
SetWindowPos(window->win32.handle, HWND_TOPMOST, SetWindowPos(window->win32.handle, HWND_TOPMOST,

View file

@ -1,7 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.4 Wayland - www.glfw.org // GLFW 3.4 Wayland (modified for raylib) - www.glfw.org; www.raylib.com
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -257,7 +258,7 @@ static const struct wl_callback_listener libdecorReadyListener =
// Create key code translation tables // Create key code translation tables
// //
static void createKeyTablesWL(void) static void createKeyTablesWayland(void)
{ {
memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes)); memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes)); memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
@ -821,7 +822,7 @@ int _glfwInitWayland(void)
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display); _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL); wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
createKeyTablesWL(); createKeyTablesWayland();
_glfw.wl.xkb.context = xkb_context_new(0); _glfw.wl.xkb.context = xkb_context_new(0);
if (!_glfw.wl.xkb.context) if (!_glfw.wl.xkb.context)

View file

@ -1,7 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.4 Wayland - www.glfw.org // GLFW 3.4 Wayland (modified for raylib) - www.glfw.org; www.raylib.com
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -498,7 +499,7 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
// Make the specified window and its video mode active on its monitor // Make the specified window and its video mode active on its monitor
// //
static void acquireMonitorWL(_GLFWwindow* window) static void acquireMonitorWayland(_GLFWwindow* window)
{ {
if (window->wl.libdecor.frame) if (window->wl.libdecor.frame)
{ {
@ -519,7 +520,7 @@ static void acquireMonitorWL(_GLFWwindow* window)
// Remove the window and restore the original video mode // Remove the window and restore the original video mode
// //
static void releaseMonitorWL(_GLFWwindow* window) static void releaseMonitorWayland(_GLFWwindow* window)
{ {
if (window->wl.libdecor.frame) if (window->wl.libdecor.frame)
libdecor_frame_unset_fullscreen(window->wl.libdecor.frame); libdecor_frame_unset_fullscreen(window->wl.libdecor.frame);
@ -1156,7 +1157,7 @@ static GLFWbool flushDisplay(void)
return GLFW_TRUE; return GLFW_TRUE;
} }
static int translateKeyWL(uint32_t scancode) static int translateKeyWayland(uint32_t scancode)
{ {
if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0])) if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
return _glfw.wl.keycodes[scancode]; return _glfw.wl.keycodes[scancode];
@ -1270,7 +1271,7 @@ static void handleEvents(double* timeout)
for (uint64_t i = 0; i < repeats; i++) for (uint64_t i = 0; i < repeats; i++)
{ {
_glfwInputKey(_glfw.wl.keyboardFocus, _glfwInputKey(_glfw.wl.keyboardFocus,
translateKeyWL(_glfw.wl.keyRepeatScancode), translateKeyWayland(_glfw.wl.keyRepeatScancode),
_glfw.wl.keyRepeatScancode, _glfw.wl.keyRepeatScancode,
GLFW_PRESS, GLFW_PRESS,
_glfw.wl.xkb.modifiers); _glfw.wl.xkb.modifiers);
@ -1773,7 +1774,7 @@ static void keyboardHandleKey(void* userData,
if (!window) if (!window)
return; return;
const int key = translateKeyWL(scancode); const int key = translateKeyWayland(scancode);
const int action = const int action =
state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE; state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
@ -2509,12 +2510,12 @@ void _glfwSetWindowMonitorWayland(_GLFWwindow* window,
} }
if (window->monitor) if (window->monitor)
releaseMonitorWL(window); releaseMonitorWayland(window);
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
if (window->monitor) if (window->monitor)
acquireMonitorWL(window); acquireMonitorWayland(window);
else else
_glfwSetWindowSizeWayland(window, width, height); _glfwSetWindowSizeWayland(window, width, height);
} }

View file

@ -1,8 +1,9 @@
//======================================================================== //========================================================================
// GLFW 3.4 X11 - www.glfw.org // GLFW 3.4 X11 (modified for raylib) - www.glfw.org; www.raylib.com
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -210,7 +211,7 @@ static int translateKeySyms(const KeySym* keysyms, int width)
// Create key code translation tables // Create key code translation tables
// //
static void createKeyTables(void) static void createKeyTablesX11(void)
{ {
int scancodeMin, scancodeMax; int scancodeMin, scancodeMax;
@ -908,7 +909,7 @@ static GLFWbool initExtensions(void)
// Update the key code LUT // Update the key code LUT
// FIXME: We should listen to XkbMapNotify events to track changes to // FIXME: We should listen to XkbMapNotify events to track changes to
// the keyboard mapping. // the keyboard mapping.
createKeyTables(); createKeyTablesX11();
// String format atoms // String format atoms
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);

View file

@ -1,8 +1,9 @@
//======================================================================== //========================================================================
// GLFW 3.4 X11 - www.glfw.org // GLFW 3.4 X11 (modified for raylib) - www.glfw.org; www.raylib.com
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -235,9 +236,9 @@ static int translateState(int state)
// Translates an X11 key code to a GLFW key token // Translates an X11 key code to a GLFW key token
// //
static int translateKey(int scancode) static int translateKeyX11(int scancode)
{ {
// Use the pre-filled LUT (see createKeyTables() in x11_init.c) // Use the pre-filled LUT (see createKeyTablesX11() in x11_init.c)
if (scancode < 0 || scancode > 255) if (scancode < 0 || scancode > 255)
return GLFW_KEY_UNKNOWN; return GLFW_KEY_UNKNOWN;
@ -1081,7 +1082,7 @@ static const char* getSelectionString(Atom selection)
// Make the specified window and its video mode active on its monitor // Make the specified window and its video mode active on its monitor
// //
static void acquireMonitor(_GLFWwindow* window) static void acquireMonitorX11(_GLFWwindow* window)
{ {
if (_glfw.x11.saver.count == 0) if (_glfw.x11.saver.count == 0)
{ {
@ -1120,7 +1121,7 @@ static void acquireMonitor(_GLFWwindow* window)
// Remove the window and restore the original video mode // Remove the window and restore the original video mode
// //
static void releaseMonitor(_GLFWwindow* window) static void releaseMonitorX11(_GLFWwindow* window)
{ {
if (window->monitor->window != window) if (window->monitor->window != window)
return; return;
@ -1242,7 +1243,7 @@ static void processEvent(XEvent *event)
case KeyPress: case KeyPress:
{ {
const int key = translateKey(keycode); const int key = translateKeyX11(keycode);
const int mods = translateState(event->xkey.state); const int mods = translateState(event->xkey.state);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
@ -1314,7 +1315,7 @@ static void processEvent(XEvent *event)
case KeyRelease: case KeyRelease:
{ {
const int key = translateKey(keycode); const int key = translateKeyX11(keycode);
const int mods = translateState(event->xkey.state); const int mods = translateState(event->xkey.state);
if (!_glfw.x11.xkb.detectable) if (!_glfw.x11.xkb.detectable)
@ -1806,9 +1807,9 @@ static void processEvent(XEvent *event)
if (window->monitor) if (window->monitor)
{ {
if (iconified) if (iconified)
releaseMonitor(window); releaseMonitorX11(window);
else else
acquireMonitor(window); acquireMonitorX11(window);
} }
window->x11.iconified = iconified; window->x11.iconified = iconified;
@ -2025,7 +2026,7 @@ GLFWbool _glfwCreateWindowX11(_GLFWwindow* window,
{ {
_glfwShowWindowX11(window); _glfwShowWindowX11(window);
updateWindowMode(window); updateWindowMode(window);
acquireMonitor(window); acquireMonitorX11(window);
if (wndconfig->centerCursor) if (wndconfig->centerCursor)
_glfwCenterCursorInContentArea(window); _glfwCenterCursorInContentArea(window);
@ -2050,7 +2051,7 @@ void _glfwDestroyWindowX11(_GLFWwindow* window)
enableCursor(window); enableCursor(window);
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitorX11(window);
if (window->x11.ic) if (window->x11.ic)
{ {
@ -2206,7 +2207,7 @@ void _glfwSetWindowSizeX11(_GLFWwindow* window, int width, int height)
if (window->monitor) if (window->monitor)
{ {
if (window->monitor->window == window) if (window->monitor->window == window)
acquireMonitor(window); acquireMonitorX11(window);
} }
else else
{ {
@ -2477,7 +2478,7 @@ void _glfwSetWindowMonitorX11(_GLFWwindow* window,
if (monitor) if (monitor)
{ {
if (monitor->window == window) if (monitor->window == window)
acquireMonitor(window); acquireMonitorX11(window);
} }
else else
{ {
@ -2496,7 +2497,7 @@ void _glfwSetWindowMonitorX11(_GLFWwindow* window,
{ {
_glfwSetWindowDecoratedX11(window, window->decorated); _glfwSetWindowDecoratedX11(window, window->decorated);
_glfwSetWindowFloatingX11(window, window->floating); _glfwSetWindowFloatingX11(window, window->floating);
releaseMonitor(window); releaseMonitorX11(window);
} }
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
@ -2511,7 +2512,7 @@ void _glfwSetWindowMonitorX11(_GLFWwindow* window,
} }
updateWindowMode(window); updateWindowMode(window);
acquireMonitor(window); acquireMonitorX11(window);
} }
else else
{ {

View file

@ -1208,7 +1208,7 @@ static void jar_xm_tone_portamento(jar_xm_context_t* ctx, jar_xm_channel_context
} }
static void jar_xm_pitch_slide(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch, float period_offset) { static void jar_xm_pitch_slide(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch, float period_offset) {
/* Don't ask about the 4.f coefficient. I found mention of it nowhere. Found by ear. */ /* Don't ask about the 4.f coefficient. I found mention of it nowhere. Found by ear. */
if(ctx->module.frequency_type == jar_xm_LINEAR_FREQUENCIES) {period_offset *= 4.f; } if(ctx->module.frequency_type == jar_xm_LINEAR_FREQUENCIES) {period_offset *= 4.f; }
ch->period += period_offset; ch->period += period_offset;
jar_xm_CLAMP_DOWN(ch->period); jar_xm_CLAMP_DOWN(ch->period);
@ -1511,7 +1511,7 @@ static void jar_xm_handle_note_and_instrument(jar_xm_context_t* ctx, jar_xm_chan
jar_xm_volume_slide(ch, ch->fine_volume_slide_param); jar_xm_volume_slide(ch, ch->fine_volume_slide_param);
break; break;
case 0xD: /* EDy: Note delay */ case 0xD: /* EDy: Note delay */
/* XXX: figure this out better. EDx triggers the note even when there no note and no instrument. But ED0 acts like like a ghost note, EDx (x 0) does not. */ /* XXX: figure this out better. EDx triggers the note even when there no note and no instrument. But ED0 acts like like a ghost note, EDx (x != 0) does not. */
if(s->note == 0 && s->instrument == 0) { if(s->note == 0 && s->instrument == 0) {
unsigned int flags = jar_xm_TRIGGER_KEEP_VOLUME; unsigned int flags = jar_xm_TRIGGER_KEEP_VOLUME;
if(ch->current->effect_param & 0x0F) { if(ch->current->effect_param & 0x0F) {
@ -1799,7 +1799,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) {
if(ch->current->effect_param > 0) { if(ch->current->effect_param > 0) {
char arp_offset = ctx->tempo % 3; char arp_offset = ctx->tempo % 3;
switch(arp_offset) { switch(arp_offset) {
case 2: /* 0 -> x -> 0 -> y -> x -> */ case 2: /* 0 -> x -> 0 -> y -> x -> ... */
if(ctx->current_tick == 1) { if(ctx->current_tick == 1) {
ch->arp_in_progress = true; ch->arp_in_progress = true;
ch->arp_note_offset = ch->current->effect_param >> 4; ch->arp_note_offset = ch->current->effect_param >> 4;
@ -1807,7 +1807,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) {
break; break;
} }
/* No break here, this is intended */ /* No break here, this is intended */
case 1: /* 0 -> 0 -> y -> x -> */ case 1: /* 0 -> 0 -> y -> x -> ... */
if(ctx->current_tick == 0) { if(ctx->current_tick == 0) {
ch->arp_in_progress = false; ch->arp_in_progress = false;
ch->arp_note_offset = 0; ch->arp_note_offset = 0;
@ -1815,7 +1815,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) {
break; break;
} }
/* No break here, this is intended */ /* No break here, this is intended */
case 0: /* 0 -> y -> x -> */ case 0: /* 0 -> y -> x -> ... */
jar_xm_arpeggio(ctx, ch, ch->current->effect_param, ctx->current_tick - arp_offset); jar_xm_arpeggio(ctx, ch, ch->current->effect_param, ctx->current_tick - arp_offset);
default: default:
break; break;

View file

@ -21473,7 +21473,9 @@ static ma_result ma_context_get_MMDevice__wasapi(ma_context* pContext, ma_device
MA_ASSERT(pContext != NULL); MA_ASSERT(pContext != NULL);
MA_ASSERT(ppMMDevice != NULL); MA_ASSERT(ppMMDevice != NULL);
ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE);
hr = ma_CoCreateInstance(pContext, &MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator); hr = ma_CoCreateInstance(pContext, &MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
ma_CoUninitialize(pContext);
if (FAILED(hr)) { if (FAILED(hr)) {
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create IMMDeviceEnumerator.\n"); ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create IMMDeviceEnumerator.\n");
return ma_result_from_HRESULT(hr); return ma_result_from_HRESULT(hr);
@ -36076,9 +36078,15 @@ static ma_result ma_context_get_device_info_from_fd__audio4(ma_context* pContext
ma_uint32 channels; ma_uint32 channels;
ma_uint32 sampleRate; ma_uint32 sampleRate;
#ifdef __NetBSD__
if (ioctl(fd, AUDIO_GETFORMAT, &fdInfo) < 0) {
return MA_ERROR;
}
#else
if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) { if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) {
return MA_ERROR; return MA_ERROR;
} }
#endif
if (deviceType == ma_device_type_playback) { if (deviceType == ma_device_type_playback) {
channels = fdInfo.play.channels; channels = fdInfo.play.channels;
@ -36356,7 +36364,11 @@ static ma_result ma_device_init_fd__audio4(ma_device* pDevice, const ma_device_c
/* We're using a default device. Get the info from the /dev/audioctl file instead of /dev/audio. */ /* We're using a default device. Get the info from the /dev/audioctl file instead of /dev/audio. */
int fdctl = open(pDefaultDeviceCtlNames[iDefaultDevice], fdFlags, 0); int fdctl = open(pDefaultDeviceCtlNames[iDefaultDevice], fdFlags, 0);
if (fdctl != -1) { if (fdctl != -1) {
#ifdef __NetBSD__
fdInfoResult = ioctl(fdctl, AUDIO_GETFORMAT, &fdInfo);
#else
fdInfoResult = ioctl(fdctl, AUDIO_GETINFO, &fdInfo); fdInfoResult = ioctl(fdctl, AUDIO_GETINFO, &fdInfo);
#endif
close(fdctl); close(fdctl);
} }
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1130,7 +1130,7 @@ static par_shapes__rule* par_shapes__pick_rule(const char* name,
total += rule->weight; total += rule->weight;
} }
} }
float r = (float) rand() / RAND_MAX; float r = (float) rand() / (float) RAND_MAX;
float t = 0; float t = 0;
for (int i = 0; i < nrules; i++) { for (int i = 0; i < nrules; i++) {
rule = rules + i; rule = rules + i;

92
raylib/external/qoa.h vendored
View file

@ -366,22 +366,7 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
), bytes, &p); ), bytes, &p);
for (int c = 0; c < channels; c++) { for (unsigned int c = 0; c < channels; c++) {
/* If the weights have grown too large, reset them to 0. This may happen
with certain high-frequency sounds. This is a last resort and will
introduce quite a bit of noise, but should at least prevent pops/clicks */
int weights_sum =
qoa->lms[c].weights[0] * qoa->lms[c].weights[0] +
qoa->lms[c].weights[1] * qoa->lms[c].weights[1] +
qoa->lms[c].weights[2] * qoa->lms[c].weights[2] +
qoa->lms[c].weights[3] * qoa->lms[c].weights[3];
if (weights_sum > 0x2fffffff) {
qoa->lms[c].weights[0] = 0;
qoa->lms[c].weights[1] = 0;
qoa->lms[c].weights[2] = 0;
qoa->lms[c].weights[3] = 0;
}
/* Write the current LMS state */ /* Write the current LMS state */
qoa_uint64_t weights = 0; qoa_uint64_t weights = 0;
qoa_uint64_t history = 0; qoa_uint64_t history = 0;
@ -395,9 +380,9 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
/* We encode all samples with the channels interleaved on a slice level. /* We encode all samples with the channels interleaved on a slice level.
E.g. for stereo: (ch-0, slice 0), (ch 1, slice 0), (ch 0, slice 1), ...*/ E.g. for stereo: (ch-0, slice 0), (ch 1, slice 0), (ch 0, slice 1), ...*/
for (int sample_index = 0; sample_index < frame_len; sample_index += QOA_SLICE_LEN) { for (unsigned int sample_index = 0; sample_index < frame_len; sample_index += QOA_SLICE_LEN) {
for (int c = 0; c < channels; c++) { for (unsigned int c = 0; c < channels; c++) {
int slice_len = qoa_clamp(QOA_SLICE_LEN, 0, frame_len - sample_index); int slice_len = qoa_clamp(QOA_SLICE_LEN, 0, frame_len - sample_index);
int slice_start = sample_index * channels + c; int slice_start = sample_index * channels + c;
int slice_end = (sample_index + slice_len) * channels + c; int slice_end = (sample_index + slice_len) * channels + c;
@ -405,10 +390,13 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
/* Brute for search for the best scalefactor. Just go through all /* Brute for search for the best scalefactor. Just go through all
16 scalefactors, encode all samples for the current slice and 16 scalefactors, encode all samples for the current slice and
meassure the total squared error. */ meassure the total squared error. */
qoa_uint64_t best_error = -1; qoa_uint64_t best_rank = -1;
qoa_uint64_t best_slice; #ifdef QOA_RECORD_TOTAL_ERROR
qoa_uint64_t best_error = -1;
#endif
qoa_uint64_t best_slice = 0;
qoa_lms_t best_lms; qoa_lms_t best_lms;
int best_scalefactor; int best_scalefactor = 0;
for (int sfi = 0; sfi < 16; sfi++) { for (int sfi = 0; sfi < 16; sfi++) {
/* There is a strong correlation between the scalefactors of /* There is a strong correlation between the scalefactors of
@ -421,7 +409,10 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
state when encoding. */ state when encoding. */
qoa_lms_t lms = qoa->lms[c]; qoa_lms_t lms = qoa->lms[c];
qoa_uint64_t slice = scalefactor; qoa_uint64_t slice = scalefactor;
qoa_uint64_t current_error = 0; qoa_uint64_t current_rank = 0;
#ifdef QOA_RECORD_TOTAL_ERROR
qoa_uint64_t current_error = 0;
#endif
for (int si = slice_start; si < slice_end; si += channels) { for (int si = slice_start; si < slice_end; si += channels) {
int sample = sample_data[si]; int sample = sample_data[si];
@ -434,9 +425,27 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
int dequantized = qoa_dequant_tab[scalefactor][quantized]; int dequantized = qoa_dequant_tab[scalefactor][quantized];
int reconstructed = qoa_clamp_s16(predicted + dequantized); int reconstructed = qoa_clamp_s16(predicted + dequantized);
/* If the weights have grown too large, we introduce a penalty
here. This prevents pops/clicks in certain problem cases */
int weights_penalty = ((
lms.weights[0] * lms.weights[0] +
lms.weights[1] * lms.weights[1] +
lms.weights[2] * lms.weights[2] +
lms.weights[3] * lms.weights[3]
) >> 18) - 0x8ff;
if (weights_penalty < 0) {
weights_penalty = 0;
}
long long error = (sample - reconstructed); long long error = (sample - reconstructed);
current_error += error * error; qoa_uint64_t error_sq = error * error;
if (current_error > best_error) {
current_rank += error_sq + weights_penalty * weights_penalty;
#ifdef QOA_RECORD_TOTAL_ERROR
current_error += error_sq;
#endif
if (current_rank > best_rank) {
break; break;
} }
@ -444,8 +453,11 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
slice = (slice << 3) | quantized; slice = (slice << 3) | quantized;
} }
if (current_error < best_error) { if (current_rank < best_rank) {
best_error = current_error; best_rank = current_rank;
#ifdef QOA_RECORD_TOTAL_ERROR
best_error = current_error;
#endif
best_slice = slice; best_slice = slice;
best_lms = lms; best_lms = lms;
best_scalefactor = scalefactor; best_scalefactor = scalefactor;
@ -490,7 +502,7 @@ void *qoa_encode(const short *sample_data, qoa_desc *qoa, unsigned int *out_len)
unsigned char *bytes = QOA_MALLOC(encoded_size); unsigned char *bytes = QOA_MALLOC(encoded_size);
for (int c = 0; c < qoa->channels; c++) { for (unsigned int c = 0; c < qoa->channels; c++) {
/* Set the initial LMS weights to {0, 0, -1, 2}. This helps with the /* Set the initial LMS weights to {0, 0, -1, 2}. This helps with the
prediction of the first few ms of a file. */ prediction of the first few ms of a file. */
qoa->lms[c].weights[0] = 0; qoa->lms[c].weights[0] = 0;
@ -513,7 +525,7 @@ void *qoa_encode(const short *sample_data, qoa_desc *qoa, unsigned int *out_len)
#endif #endif
int frame_len = QOA_FRAME_LEN; int frame_len = QOA_FRAME_LEN;
for (int sample_index = 0; sample_index < qoa->samples; sample_index += frame_len) { for (unsigned int sample_index = 0; sample_index < qoa->samples; sample_index += frame_len) {
frame_len = qoa_clamp(QOA_FRAME_LEN, 0, qoa->samples - sample_index); frame_len = qoa_clamp(QOA_FRAME_LEN, 0, qoa->samples - sample_index);
const short *frame_samples = sample_data + sample_index * qoa->channels; const short *frame_samples = sample_data + sample_index * qoa->channels;
unsigned int frame_size = qoa_encode_frame(frame_samples, qoa, frame_len, bytes + p); unsigned int frame_size = qoa_encode_frame(frame_samples, qoa, frame_len, bytes + p);
@ -576,14 +588,14 @@ unsigned int qoa_decode_frame(const unsigned char *bytes, unsigned int size, qoa
/* Read and verify the frame header */ /* Read and verify the frame header */
qoa_uint64_t frame_header = qoa_read_u64(bytes, &p); qoa_uint64_t frame_header = qoa_read_u64(bytes, &p);
int channels = (frame_header >> 56) & 0x0000ff; unsigned int channels = (frame_header >> 56) & 0x0000ff;
int samplerate = (frame_header >> 32) & 0xffffff; unsigned int samplerate = (frame_header >> 32) & 0xffffff;
int samples = (frame_header >> 16) & 0x00ffff; unsigned int samples = (frame_header >> 16) & 0x00ffff;
int frame_size = (frame_header ) & 0x00ffff; unsigned int frame_size = (frame_header ) & 0x00ffff;
int data_size = frame_size - 8 - QOA_LMS_LEN * 4 * channels; unsigned int data_size = frame_size - 8 - QOA_LMS_LEN * 4 * channels;
int num_slices = data_size / 8; unsigned int num_slices = data_size / 8;
int max_total_samples = num_slices * QOA_SLICE_LEN; unsigned int max_total_samples = num_slices * QOA_SLICE_LEN;
if ( if (
channels != qoa->channels || channels != qoa->channels ||
@ -596,7 +608,7 @@ unsigned int qoa_decode_frame(const unsigned char *bytes, unsigned int size, qoa
/* Read the LMS state: 4 x 2 bytes history, 4 x 2 bytes weights per channel */ /* Read the LMS state: 4 x 2 bytes history, 4 x 2 bytes weights per channel */
for (int c = 0; c < channels; c++) { for (unsigned int c = 0; c < channels; c++) {
qoa_uint64_t history = qoa_read_u64(bytes, &p); qoa_uint64_t history = qoa_read_u64(bytes, &p);
qoa_uint64_t weights = qoa_read_u64(bytes, &p); qoa_uint64_t weights = qoa_read_u64(bytes, &p);
for (int i = 0; i < QOA_LMS_LEN; i++) { for (int i = 0; i < QOA_LMS_LEN; i++) {
@ -609,17 +621,19 @@ unsigned int qoa_decode_frame(const unsigned char *bytes, unsigned int size, qoa
/* Decode all slices for all channels in this frame */ /* Decode all slices for all channels in this frame */
for (int sample_index = 0; sample_index < samples; sample_index += QOA_SLICE_LEN) { for (unsigned int sample_index = 0; sample_index < samples; sample_index += QOA_SLICE_LEN) {
for (int c = 0; c < channels; c++) { for (unsigned int c = 0; c < channels; c++) {
qoa_uint64_t slice = qoa_read_u64(bytes, &p); qoa_uint64_t slice = qoa_read_u64(bytes, &p);
int scalefactor = (slice >> 60) & 0xf; int scalefactor = (slice >> 60) & 0xf;
slice <<= 4;
int slice_start = sample_index * channels + c; int slice_start = sample_index * channels + c;
int slice_end = qoa_clamp(sample_index + QOA_SLICE_LEN, 0, samples) * channels + c; int slice_end = qoa_clamp(sample_index + QOA_SLICE_LEN, 0, samples) * channels + c;
for (int si = slice_start; si < slice_end; si += channels) { for (int si = slice_start; si < slice_end; si += channels) {
int predicted = qoa_lms_predict(&qoa->lms[c]); int predicted = qoa_lms_predict(&qoa->lms[c]);
int quantized = (slice >> 57) & 0x7; int quantized = (slice >> 61) & 0x7;
int dequantized = qoa_dequant_tab[scalefactor][quantized]; int dequantized = qoa_dequant_tab[scalefactor][quantized];
int reconstructed = qoa_clamp_s16(predicted + dequantized); int reconstructed = qoa_clamp_s16(predicted + dequantized);

View file

@ -171,6 +171,10 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
*width = header->width; *width = header->width;
*height = header->height; *height = header->height;
if (*width % 4 != 0) LOG("WARNING: IMAGE: DDS file width must be multiple of 4. Image will not display correctly");
if (*height % 4 != 0) LOG("WARNING: IMAGE: DDS file height must be multiple of 4. Image will not display correctly");
image_pixel_size = header->width*header->height; image_pixel_size = header->width*header->height;
if (header->mipmap_count == 0) *mips = 1; // Parameter not used if (header->mipmap_count == 0) *mips = 1; // Parameter not used
@ -181,6 +185,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
if (header->ddspf.flags == 0x40) // No alpha channel if (header->ddspf.flags == 0x40) // No alpha channel
{ {
int data_size = image_pixel_size*sizeof(unsigned short); int data_size = image_pixel_size*sizeof(unsigned short);
if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size); image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size); memcpy(image_data, file_data_ptr, data_size);
@ -192,6 +197,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
if (header->ddspf.a_bit_mask == 0x8000) // 1bit alpha if (header->ddspf.a_bit_mask == 0x8000) // 1bit alpha
{ {
int data_size = image_pixel_size*sizeof(unsigned short); int data_size = image_pixel_size*sizeof(unsigned short);
if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size); image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size); memcpy(image_data, file_data_ptr, data_size);
@ -211,6 +217,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
else if (header->ddspf.a_bit_mask == 0xf000) // 4bit alpha else if (header->ddspf.a_bit_mask == 0xf000) // 4bit alpha
{ {
int data_size = image_pixel_size*sizeof(unsigned short); int data_size = image_pixel_size*sizeof(unsigned short);
if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size); image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size); memcpy(image_data, file_data_ptr, data_size);
@ -232,6 +239,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
else if ((header->ddspf.flags == 0x40) && (header->ddspf.rgb_bit_count == 24)) // DDS_RGB, no compressed else if ((header->ddspf.flags == 0x40) && (header->ddspf.rgb_bit_count == 24)) // DDS_RGB, no compressed
{ {
int data_size = image_pixel_size*3*sizeof(unsigned char); int data_size = image_pixel_size*3*sizeof(unsigned char);
if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size); image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size); memcpy(image_data, file_data_ptr, data_size);
@ -241,6 +249,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
else if ((header->ddspf.flags == 0x41) && (header->ddspf.rgb_bit_count == 32)) // DDS_RGBA, no compressed else if ((header->ddspf.flags == 0x41) && (header->ddspf.rgb_bit_count == 32)) // DDS_RGBA, no compressed
{ {
int data_size = image_pixel_size*4*sizeof(unsigned char); int data_size = image_pixel_size*4*sizeof(unsigned char);
if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size); image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size); memcpy(image_data, file_data_ptr, data_size);
@ -261,9 +270,11 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
} }
else if (((header->ddspf.flags == 0x04) || (header->ddspf.flags == 0x05)) && (header->ddspf.fourcc > 0)) // Compressed else if (((header->ddspf.flags == 0x04) || (header->ddspf.flags == 0x05)) && (header->ddspf.fourcc > 0)) // Compressed
{ {
// NOTE: This forces only 1 mipmap to be loaded which is not really correct but it works int data_size = 0;
int data_size = (header->pitch_or_linear_size < file_size - 0x80) ? header->pitch_or_linear_size : file_size - 0x80;
*mips = 1; // Calculate data size, including all mipmaps
if (header->mipmap_count > 1) data_size = header->pitch_or_linear_size + header->pitch_or_linear_size / 3;
else data_size = header->pitch_or_linear_size;
image_data = RL_MALLOC(data_size*sizeof(unsigned char)); image_data = RL_MALLOC(data_size*sizeof(unsigned char));

View file

@ -1,4 +1,4 @@
/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb /* stb_image - v2.30 - public domain image loader - http://nothings.org/stb
no warranty implied; use at your own risk no warranty implied; use at your own risk
Do this: Do this:
@ -48,6 +48,8 @@ LICENSE
RECENT REVISION HISTORY: RECENT REVISION HISTORY:
2.30 (2024-05-31) avoid erroneous gcc warning
2.29 (2023-05-xx) optimizations
2.28 (2023-01-29) many error fixes, security errors, just tons of stuff 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff
2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
2.26 (2020-07-13) many minor fixes 2.26 (2020-07-13) many minor fixes
@ -1072,8 +1074,8 @@ static int stbi__addints_valid(int a, int b)
return a <= INT_MAX - b; return a <= INT_MAX - b;
} }
// returns 1 if the product of two signed shorts is valid, 0 on overflow. // returns 1 if the product of two ints fits in a signed short, 0 on overflow.
static int stbi__mul2shorts_valid(short a, short b) static int stbi__mul2shorts_valid(int a, int b)
{ {
if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow
if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid
@ -3384,13 +3386,13 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
return 1; return 1;
} }
static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
{ {
// some JPEGs have junk at end, skip over it but if we find what looks // some JPEGs have junk at end, skip over it but if we find what looks
// like a valid marker, resume there // like a valid marker, resume there
while (!stbi__at_eof(j->s)) { while (!stbi__at_eof(j->s)) {
int x = stbi__get8(j->s); stbi_uc x = stbi__get8(j->s);
while (x == 255) { // might be a marker while (x == 0xff) { // might be a marker
if (stbi__at_eof(j->s)) return STBI__MARKER_none; if (stbi__at_eof(j->s)) return STBI__MARKER_none;
x = stbi__get8(j->s); x = stbi__get8(j->s);
if (x != 0x00 && x != 0xff) { if (x != 0x00 && x != 0xff) {
@ -4176,6 +4178,7 @@ typedef struct
{ {
stbi_uc *zbuffer, *zbuffer_end; stbi_uc *zbuffer, *zbuffer_end;
int num_bits; int num_bits;
int hit_zeof_once;
stbi__uint32 code_buffer; stbi__uint32 code_buffer;
char *zout; char *zout;
@ -4242,9 +4245,20 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
int b,s; int b,s;
if (a->num_bits < 16) { if (a->num_bits < 16) {
if (stbi__zeof(a)) { if (stbi__zeof(a)) {
return -1; /* report error for unexpected end of data. */ if (!a->hit_zeof_once) {
// This is the first time we hit eof, insert 16 extra padding btis
// to allow us to keep going; if we actually consume any of them
// though, that is invalid data. This is caught later.
a->hit_zeof_once = 1;
a->num_bits += 16; // add 16 implicit zero bits
} else {
// We already inserted our extra 16 padding bits and are again
// out, this stream is actually prematurely terminated.
return -1;
}
} else {
stbi__fill_bits(a);
} }
stbi__fill_bits(a);
} }
b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
if (b) { if (b) {
@ -4309,6 +4323,13 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
int len,dist; int len,dist;
if (z == 256) { if (z == 256) {
a->zout = zout; a->zout = zout;
if (a->hit_zeof_once && a->num_bits < 16) {
// The first time we hit zeof, we inserted 16 extra zero bits into our bit
// buffer so the decoder can just do its speculative decoding. But if we
// actually consumed any of those bits (which is the case when num_bits < 16),
// the stream actually read past the end so it is malformed.
return stbi__err("unexpected end","Corrupt PNG");
}
return 1; return 1;
} }
if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data
@ -4320,7 +4341,7 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
dist = stbi__zdist_base[z]; dist = stbi__zdist_base[z];
if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
if (zout + len > a->zout_end) { if (len > a->zout_end - zout) {
if (!stbi__zexpand(a, zout, len)) return 0; if (!stbi__zexpand(a, zout, len)) return 0;
zout = a->zout; zout = a->zout;
} }
@ -4464,6 +4485,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
if (!stbi__parse_zlib_header(a)) return 0; if (!stbi__parse_zlib_header(a)) return 0;
a->num_bits = 0; a->num_bits = 0;
a->code_buffer = 0; a->code_buffer = 0;
a->hit_zeof_once = 0;
do { do {
final = stbi__zreceive(a,1); final = stbi__zreceive(a,1);
type = stbi__zreceive(a,2); type = stbi__zreceive(a,2);
@ -4619,9 +4641,8 @@ enum {
STBI__F_up=2, STBI__F_up=2,
STBI__F_avg=3, STBI__F_avg=3,
STBI__F_paeth=4, STBI__F_paeth=4,
// synthetic filters used for first scanline to avoid needing a dummy row of 0s // synthetic filter used for first scanline to avoid needing a dummy row of 0s
STBI__F_avg_first, STBI__F_avg_first
STBI__F_paeth_first
}; };
static stbi_uc first_row_filter[5] = static stbi_uc first_row_filter[5] =
@ -4630,29 +4651,56 @@ static stbi_uc first_row_filter[5] =
STBI__F_sub, STBI__F_sub,
STBI__F_none, STBI__F_none,
STBI__F_avg_first, STBI__F_avg_first,
STBI__F_paeth_first STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub
}; };
static int stbi__paeth(int a, int b, int c) static int stbi__paeth(int a, int b, int c)
{ {
int p = a + b - c; // This formulation looks very different from the reference in the PNG spec, but is
int pa = abs(p-a); // actually equivalent and has favorable data dependencies and admits straightforward
int pb = abs(p-b); // generation of branch-free code, which helps performance significantly.
int pc = abs(p-c); int thresh = c*3 - (a + b);
if (pa <= pb && pa <= pc) return a; int lo = a < b ? a : b;
if (pb <= pc) return b; int hi = a < b ? b : a;
return c; int t0 = (hi <= thresh) ? lo : c;
int t1 = (thresh <= lo) ? hi : t0;
return t1;
} }
static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
// adds an extra all-255 alpha channel
// dest == src is legal
// img_n must be 1 or 3
static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n)
{
int i;
// must process data backwards since we allow dest==src
if (img_n == 1) {
for (i=x-1; i >= 0; --i) {
dest[i*2+1] = 255;
dest[i*2+0] = src[i];
}
} else {
STBI_ASSERT(img_n == 3);
for (i=x-1; i >= 0; --i) {
dest[i*4+3] = 255;
dest[i*4+2] = src[i*3+2];
dest[i*4+1] = src[i*3+1];
dest[i*4+0] = src[i*3+0];
}
}
}
// create the png data from post-deflated data // create the png data from post-deflated data
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
{ {
int bytes = (depth == 16? 2 : 1); int bytes = (depth == 16 ? 2 : 1);
stbi__context *s = a->s; stbi__context *s = a->s;
stbi__uint32 i,j,stride = x*out_n*bytes; stbi__uint32 i,j,stride = x*out_n*bytes;
stbi__uint32 img_len, img_width_bytes; stbi__uint32 img_len, img_width_bytes;
stbi_uc *filter_buf;
int all_ok = 1;
int k; int k;
int img_n = s->img_n; // copy it into a local for later int img_n = s->img_n; // copy it into a local for later
@ -4664,8 +4712,11 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
if (!a->out) return stbi__err("outofmem", "Out of memory"); if (!a->out) return stbi__err("outofmem", "Out of memory");
// note: error exits here don't need to clean up a->out individually,
// stbi__do_png always does on error.
if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
img_width_bytes = (((img_n * x * depth) + 7) >> 3); img_width_bytes = (((img_n * x * depth) + 7) >> 3);
if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG");
img_len = (img_width_bytes + 1) * y; img_len = (img_width_bytes + 1) * y;
// we used to check for exact match between raw_len and img_len on non-interlaced PNGs, // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
@ -4673,189 +4724,137 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
// so just check for raw_len < img_len always. // so just check for raw_len < img_len always.
if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
// Allocate two scan lines worth of filter workspace buffer.
filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0);
if (!filter_buf) return stbi__err("outofmem", "Out of memory");
// Filtering for low-bit-depth images
if (depth < 8) {
filter_bytes = 1;
width = img_width_bytes;
}
for (j=0; j < y; ++j) { for (j=0; j < y; ++j) {
stbi_uc *cur = a->out + stride*j; // cur/prior filter buffers alternate
stbi_uc *prior; stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes;
stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes;
stbi_uc *dest = a->out + stride*j;
int nk = width * filter_bytes;
int filter = *raw++; int filter = *raw++;
if (filter > 4) // check filter type
return stbi__err("invalid filter","Corrupt PNG"); if (filter > 4) {
all_ok = stbi__err("invalid filter","Corrupt PNG");
if (depth < 8) { break;
if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG");
cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
filter_bytes = 1;
width = img_width_bytes;
} }
prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
// if first row, use special filter that doesn't sample previous row // if first row, use special filter that doesn't sample previous row
if (j == 0) filter = first_row_filter[filter]; if (j == 0) filter = first_row_filter[filter];
// handle first byte explicitly // perform actual filtering
for (k=0; k < filter_bytes; ++k) { switch (filter) {
switch (filter) { case STBI__F_none:
case STBI__F_none : cur[k] = raw[k]; break; memcpy(cur, raw, nk);
case STBI__F_sub : cur[k] = raw[k]; break; break;
case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; case STBI__F_sub:
case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; memcpy(cur, raw, filter_bytes);
case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; for (k = filter_bytes; k < nk; ++k)
case STBI__F_avg_first : cur[k] = raw[k]; break; cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]);
case STBI__F_paeth_first: cur[k] = raw[k]; break; break;
} case STBI__F_up:
for (k = 0; k < nk; ++k)
cur[k] = STBI__BYTECAST(raw[k] + prior[k]);
break;
case STBI__F_avg:
for (k = 0; k < filter_bytes; ++k)
cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1));
for (k = filter_bytes; k < nk; ++k)
cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1));
break;
case STBI__F_paeth:
for (k = 0; k < filter_bytes; ++k)
cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0)
for (k = filter_bytes; k < nk; ++k)
cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes]));
break;
case STBI__F_avg_first:
memcpy(cur, raw, filter_bytes);
for (k = filter_bytes; k < nk; ++k)
cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1));
break;
} }
if (depth == 8) { raw += nk;
if (img_n != out_n)
cur[img_n] = 255; // first pixel
raw += img_n;
cur += out_n;
prior += out_n;
} else if (depth == 16) {
if (img_n != out_n) {
cur[filter_bytes] = 255; // first pixel top byte
cur[filter_bytes+1] = 255; // first pixel bottom byte
}
raw += filter_bytes;
cur += output_bytes;
prior += output_bytes;
} else {
raw += 1;
cur += 1;
prior += 1;
}
// this is a little gross, so that we don't switch per-pixel or per-component // expand decoded bits in cur to dest, also adding an extra alpha channel if desired
if (depth < 8 || img_n == out_n) { if (depth < 8) {
int nk = (width - 1)*filter_bytes;
#define STBI__CASE(f) \
case f: \
for (k=0; k < nk; ++k)
switch (filter) {
// "none" filter turns into a memcpy here; make that explicit.
case STBI__F_none: memcpy(cur, raw, nk); break;
STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
}
#undef STBI__CASE
raw += nk;
} else {
STBI_ASSERT(img_n+1 == out_n);
#define STBI__CASE(f) \
case f: \
for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
for (k=0; k < filter_bytes; ++k)
switch (filter) {
STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break;
STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
}
#undef STBI__CASE
// the loop above sets the high byte of the pixels' alpha, but for
// 16 bit png files we also need the low byte set. we'll do that here.
if (depth == 16) {
cur = a->out + stride*j; // start at the beginning of the row again
for (i=0; i < x; ++i,cur+=output_bytes) {
cur[filter_bytes+1] = 255;
}
}
}
}
// we make a separate pass to expand bits to pixels; for performance,
// this could run two scanlines behind the above code, so it won't
// intefere with filtering but will still be in the cache.
if (depth < 8) {
for (j=0; j < y; ++j) {
stbi_uc *cur = a->out + stride*j;
stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes;
// unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
// png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
stbi_uc *in = cur;
stbi_uc *out = dest;
stbi_uc inb = 0;
stbi__uint32 nsmp = x*img_n;
// note that the final byte might overshoot and write more data than desired. // expand bits to bytes first
// we can allocate enough data that this never writes out of memory, but it
// could also overwrite the next scanline. can it overwrite non-empty data
// on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
// so we need to explicitly clamp the final ones
if (depth == 4) { if (depth == 4) {
for (k=x*img_n; k >= 2; k-=2, ++in) { for (i=0; i < nsmp; ++i) {
*cur++ = scale * ((*in >> 4) ); if ((i & 1) == 0) inb = *in++;
*cur++ = scale * ((*in ) & 0x0f); *out++ = scale * (inb >> 4);
inb <<= 4;
} }
if (k > 0) *cur++ = scale * ((*in >> 4) );
} else if (depth == 2) { } else if (depth == 2) {
for (k=x*img_n; k >= 4; k-=4, ++in) { for (i=0; i < nsmp; ++i) {
*cur++ = scale * ((*in >> 6) ); if ((i & 3) == 0) inb = *in++;
*cur++ = scale * ((*in >> 4) & 0x03); *out++ = scale * (inb >> 6);
*cur++ = scale * ((*in >> 2) & 0x03); inb <<= 2;
*cur++ = scale * ((*in ) & 0x03);
} }
if (k > 0) *cur++ = scale * ((*in >> 6) ); } else {
if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); STBI_ASSERT(depth == 1);
if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); for (i=0; i < nsmp; ++i) {
} else if (depth == 1) { if ((i & 7) == 0) inb = *in++;
for (k=x*img_n; k >= 8; k-=8, ++in) { *out++ = scale * (inb >> 7);
*cur++ = scale * ((*in >> 7) ); inb <<= 1;
*cur++ = scale * ((*in >> 6) & 0x01);
*cur++ = scale * ((*in >> 5) & 0x01);
*cur++ = scale * ((*in >> 4) & 0x01);
*cur++ = scale * ((*in >> 3) & 0x01);
*cur++ = scale * ((*in >> 2) & 0x01);
*cur++ = scale * ((*in >> 1) & 0x01);
*cur++ = scale * ((*in ) & 0x01);
} }
if (k > 0) *cur++ = scale * ((*in >> 7) );
if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
} }
if (img_n != out_n) {
int q; // insert alpha=255 values if desired
// insert alpha = 255 if (img_n != out_n)
cur = a->out + stride*j; stbi__create_png_alpha_expand8(dest, dest, x, img_n);
} else if (depth == 8) {
if (img_n == out_n)
memcpy(dest, cur, x*img_n);
else
stbi__create_png_alpha_expand8(dest, cur, x, img_n);
} else if (depth == 16) {
// convert the image data from big-endian to platform-native
stbi__uint16 *dest16 = (stbi__uint16*)dest;
stbi__uint32 nsmp = x*img_n;
if (img_n == out_n) {
for (i = 0; i < nsmp; ++i, ++dest16, cur += 2)
*dest16 = (cur[0] << 8) | cur[1];
} else {
STBI_ASSERT(img_n+1 == out_n);
if (img_n == 1) { if (img_n == 1) {
for (q=x-1; q >= 0; --q) { for (i = 0; i < x; ++i, dest16 += 2, cur += 2) {
cur[q*2+1] = 255; dest16[0] = (cur[0] << 8) | cur[1];
cur[q*2+0] = cur[q]; dest16[1] = 0xffff;
} }
} else { } else {
STBI_ASSERT(img_n == 3); STBI_ASSERT(img_n == 3);
for (q=x-1; q >= 0; --q) { for (i = 0; i < x; ++i, dest16 += 4, cur += 6) {
cur[q*4+3] = 255; dest16[0] = (cur[0] << 8) | cur[1];
cur[q*4+2] = cur[q*3+2]; dest16[1] = (cur[2] << 8) | cur[3];
cur[q*4+1] = cur[q*3+1]; dest16[2] = (cur[4] << 8) | cur[5];
cur[q*4+0] = cur[q*3+0]; dest16[3] = 0xffff;
} }
} }
} }
} }
} else if (depth == 16) {
// force the image data from big-endian to platform-native.
// this is done in a separate pass due to the decoding relying
// on the data being untouched, but could probably be done
// per-line during decode if care is taken.
stbi_uc *cur = a->out;
stbi__uint16 *cur16 = (stbi__uint16*)cur;
for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
*cur16 = (cur[0] << 8) | cur[1];
}
} }
STBI_FREE(filter_buf);
if (!all_ok) return 0;
return 1; return 1;
} }
@ -5161,9 +5160,11 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
// non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now.
if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } if (scan == STBI__SCAN_header) { ++s->img_n; return 1; }
if (z->depth == 16) { if (z->depth == 16) {
for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning
tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
} else { } else {
for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger for (k = 0; k < s->img_n && k < 3; ++k)
tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
} }
} }
break; break;

File diff suppressed because it is too large Load diff

View file

@ -54,7 +54,7 @@
// Hou Qiming Derek Vinyard // Hou Qiming Derek Vinyard
// Rob Loach Cort Stratton // Rob Loach Cort Stratton
// Kenney Phillis Jr. Brian Costabile // Kenney Phillis Jr. Brian Costabile
// Ken Voskuil (kaesve) // Ken Voskuil (kaesve) Yakov Galka
// //
// VERSION HISTORY // VERSION HISTORY
// //
@ -4604,6 +4604,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
scale_y = -scale_y; scale_y = -scale_y;
{ {
// distance from singular values (in the same units as the pixel grid)
const float eps = 1./1024, eps2 = eps*eps;
int x,y,i,j; int x,y,i,j;
float *precompute; float *precompute;
stbtt_vertex *verts; stbtt_vertex *verts;
@ -4616,15 +4618,15 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; precompute[i] = (dist < eps) ? 0.0f : 1.0f / dist;
} else if (verts[i].type == STBTT_vcurve) { } else if (verts[i].type == STBTT_vcurve) {
float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
float len2 = bx*bx + by*by; float len2 = bx*bx + by*by;
if (len2 != 0.0f) if (len2 >= eps2)
precompute[i] = 1.0f / (bx*bx + by*by); precompute[i] = 1.0f / len2;
else else
precompute[i] = 0.0f; precompute[i] = 0.0f;
} else } else
@ -4689,8 +4691,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
float a = 3*(ax*bx + ay*by); float a = 3*(ax*bx + ay*by);
float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
float c = mx*ax+my*ay; float c = mx*ax+my*ay;
if (a == 0.0) { // if a is 0, it's linear if (STBTT_fabs(a) < eps2) { // if a is 0, it's linear
if (b != 0.0) { if (STBTT_fabs(b) >= eps2) {
res[num++] = -c/b; res[num++] = -c/b;
} }
} else { } else {

374
raylib/external/win32_clipboard.h vendored Normal file
View file

@ -0,0 +1,374 @@
#if !defined(_WIN32)
# error "This module is only made for Windows OS"
#endif
#ifndef WIN32_CLIPBOARD_
#define WIN32_CLIPBOARD_
unsigned char* Win32GetClipboardImageData(int* width, int* height, unsigned long long int *dataSize);
#endif // WIN32_CLIPBOARD_
#ifdef WIN32_CLIPBOARD_IMPLEMENTATION
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
// NOTE: These search for architecture is taken from "Windows.h", and it's necessary if we really don't wanna import windows.h
// and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. <minwindef.h>) can cause problems is these are not defined.
#if !defined(_X86_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_IX86)
#define _X86_
#if !defined(_CHPE_X86_ARM64_) && defined(_M_HYBRID)
#define _CHPE_X86_ARM64_
#endif
#endif
#if !defined(_AMD64_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && (defined(_M_AMD64) || defined(_M_ARM64EC))
#define _AMD64_
#endif
#if !defined(_ARM_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_ARM)
#define _ARM_
#endif
#if !defined(_ARM64_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64EC_) && defined(_M_ARM64)
#define _ARM64_
#endif
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_ARM64EC)
#define _ARM64EC_
#endif
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_M68K)
#define _68K_
#endif
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_MPPC)
#define _MPPC_
#endif
#if !defined(_IA64_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_M_IX86) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_IA64)
#define _IA64_
#endif
#define WIN32_LEAN_AND_MEAN
// #include <sdkddkver.h>
// #include <windows.h>
// #include <winuser.h>
#include <minwindef.h>
// #include <minwinbase.h>
#ifndef WINAPI
#if defined(_ARM_)
#define WINAPI
#else
#define WINAPI __stdcall
#endif
#endif
#ifndef WINAPI
#if defined(_ARM_)
#define WINAPI
#else
#define WINAPI __stdcall
#endif
#endif
#ifndef WINBASEAPI
#ifndef _KERNEL32_
#define WINBASEAPI DECLSPEC_IMPORT
#else
#define WINBASEAPI
#endif
#endif
#ifndef WINUSERAPI
#ifndef _USER32_
#define WINUSERAPI __declspec (dllimport)
#else
#define WINUSERAPI
#endif
#endif
typedef int WINBOOL;
// typedef HANDLE HGLOBAL;
#ifndef HWND
#define HWND void*
#endif
#if !defined(_WINUSER_) || !defined(WINUSER_ALREADY_INCLUDED)
WINUSERAPI WINBOOL WINAPI OpenClipboard(HWND hWndNewOwner);
WINUSERAPI WINBOOL WINAPI CloseClipboard(VOID);
WINUSERAPI DWORD WINAPI GetClipboardSequenceNumber(VOID);
WINUSERAPI HWND WINAPI GetClipboardOwner(VOID);
WINUSERAPI HWND WINAPI SetClipboardViewer(HWND hWndNewViewer);
WINUSERAPI HWND WINAPI GetClipboardViewer(VOID);
WINUSERAPI WINBOOL WINAPI ChangeClipboardChain(HWND hWndRemove, HWND hWndNewNext);
WINUSERAPI HANDLE WINAPI SetClipboardData(UINT uFormat, HANDLE hMem);
WINUSERAPI HANDLE WINAPI GetClipboardData(UINT uFormat);
WINUSERAPI UINT WINAPI RegisterClipboardFormatA(LPCSTR lpszFormat);
WINUSERAPI UINT WINAPI RegisterClipboardFormatW(LPCWSTR lpszFormat);
WINUSERAPI int WINAPI CountClipboardFormats(VOID);
WINUSERAPI UINT WINAPI EnumClipboardFormats(UINT format);
WINUSERAPI int WINAPI GetClipboardFormatNameA(UINT format, LPSTR lpszFormatName, int cchMaxCount);
WINUSERAPI int WINAPI GetClipboardFormatNameW(UINT format, LPWSTR lpszFormatName, int cchMaxCount);
WINUSERAPI WINBOOL WINAPI EmptyClipboard(VOID);
WINUSERAPI WINBOOL WINAPI IsClipboardFormatAvailable(UINT format);
WINUSERAPI int WINAPI GetPriorityClipboardFormat(UINT *paFormatPriorityList, int cFormats);
WINUSERAPI HWND WINAPI GetOpenClipboardWindow(VOID);
#endif
#ifndef HGLOBAL
#define HGLOBAL void*
#endif
#if !defined(_WINBASE_) || !defined(WINBASE_ALREADY_INCLUDED)
WINBASEAPI SIZE_T WINAPI GlobalSize (HGLOBAL hMem);
WINBASEAPI LPVOID WINAPI GlobalLock (HGLOBAL hMem);
WINBASEAPI WINBOOL WINAPI GlobalUnlock (HGLOBAL hMem);
#endif
#if !defined(_WINGDI_) || !defined(WINGDI_ALREADY_INCLUDED)
#ifndef BITMAPINFOHEADER_ALREADY_DEFINED
#define BITMAPINFOHEADER_ALREADY_DEFINED
// Does this header need to be packed ? by the windowps header it doesnt seem to be
#pragma pack(push, 1)
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER,*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER;
#pragma pack(pop)
#endif
#ifndef BITMAPFILEHEADER_ALREADY_DEFINED
#define BITMAPFILEHEADER_ALREADY_DEFINED
#pragma pack(push, 1)
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;
#pragma pack(pop)
#endif
#ifndef RGBQUAD_ALREADY_DEFINED
#define RGBQUAD_ALREADY_DEFINED
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD, *LPRGBQUAD;
#endif
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/4e588f70-bd92-4a6f-b77f-35d0feaf7a57
#define BI_RGB 0x0000
#define BI_RLE8 0x0001
#define BI_RLE4 0x0002
#define BI_BITFIELDS 0x0003
#define BI_JPEG 0x0004
#define BI_PNG 0x0005
#define BI_CMYK 0x000B
#define BI_CMYKRLE8 0x000C
#define BI_CMYKRLE4 0x000D
#endif
// https://learn.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats
#define CF_DIB 8
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setsystemcursor
// #define OCR_NORMAL 32512 // Normal select
// #define OCR_IBEAM 32513 // Text select
// #define OCR_WAIT 32514 // Busy
// #define OCR_CROSS 32515 // Precision select
// #define OCR_UP 32516 // Alternate select
// #define OCR_SIZENWSE 32642 // Diagonal resize 1
// #define OCR_SIZENESW 32643 // Diagonal resize 2
// #define OCR_SIZEWE 32644 // Horizontal resize
// #define OCR_SIZENS 32645 // Vertical resize
// #define OCR_SIZEALL 32646 // Move
// #define OCR_NO 32648 // Unavailable
// #define OCR_HAND 32649 // Link select
// #define OCR_APPSTARTING 32650 //
//----------------------------------------------------------------------------------
// Module Internal Functions Declaration
//----------------------------------------------------------------------------------
static BOOL OpenClipboardRetrying(HWND handle); // Open clipboard with a number of retries
static int GetPixelDataOffset(BITMAPINFOHEADER bih);
unsigned char* Win32GetClipboardImageData(int* width, int* height, unsigned long long int *dataSize)
{
HWND win = NULL; // Get from somewhere but is doesnt seem to matter
const char* msgString = "";
int severity = LOG_INFO;
BYTE* bmpData = NULL;
if (!OpenClipboardRetrying(win)) {
severity = LOG_ERROR;
msgString = "Couldn't open clipboard";
goto end;
}
HGLOBAL clipHandle = (HGLOBAL)GetClipboardData(CF_DIB);
if (!clipHandle) {
severity = LOG_ERROR;
msgString = "Clipboard data is not an Image";
goto close;
}
BITMAPINFOHEADER *bmpInfoHeader = (BITMAPINFOHEADER *)GlobalLock(clipHandle);
if (!bmpInfoHeader) {
// Mapping from HGLOBAL to our local *address space* failed
severity = LOG_ERROR;
msgString = "Clipboard data failed to be locked";
goto unlock;
}
*width = bmpInfoHeader->biWidth;
*height = bmpInfoHeader->biHeight;
SIZE_T clipDataSize = GlobalSize(clipHandle);
if (clipDataSize < sizeof(BITMAPINFOHEADER)) {
// Format CF_DIB needs space for BITMAPINFOHEADER struct.
msgString = "Clipboard has Malformed data";
severity = LOG_ERROR;
goto unlock;
}
// Denotes where the pixel data starts from the bmpInfoHeader pointer
int pixelOffset = GetPixelDataOffset(*bmpInfoHeader);
//--------------------------------------------------------------------------------//
//
// The rest of the section is about create the bytes for a correct BMP file
// Then we copy the data and to a pointer
//
//--------------------------------------------------------------------------------//
BITMAPFILEHEADER bmpFileHeader = {0};
SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize;
*dataSize = bmpFileSize;
bmpFileHeader.bfType = 0x4D42; //https://stackoverflow.com/questions/601430/multibyte-character-constants-and-bitmap-file-header-type-constants#601536
bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine
bmpFileHeader.bfOffBits = sizeof(bmpFileHeader) + pixelOffset;
//
// Each process has a default heap provided by the system
// Memory objects allocated by GlobalAlloc and LocalAlloc are in private,
// committed pages with read/write access that cannot be accessed by other processes.
//
// This may be wrong since we might be allocating in a DLL and freeing from another module, the main application
// that may cause heap corruption. We could create a FreeImage function
//
bmpData = malloc(sizeof(bmpFileHeader) + clipDataSize);
// First we add the header for a bmp file
memcpy(bmpData, &bmpFileHeader, sizeof(bmpFileHeader));
// Then we add the header for the bmp itself + the pixel data
memcpy(bmpData + sizeof(bmpFileHeader), bmpInfoHeader, clipDataSize);
msgString = "Clipboad image acquired successfully";
unlock:
GlobalUnlock(clipHandle);
close:
CloseClipboard();
end:
TRACELOG(severity, msgString);
return bmpData;
}
static BOOL OpenClipboardRetrying(HWND hWnd)
{
static const int maxTries = 20;
static const int sleepTimeMS = 60;
for (int _ = 0; _ < maxTries; ++_)
{
// Might be being hold by another process
// Or yourself forgot to CloseClipboard
if (OpenClipboard(hWnd)) {
return true;
}
Sleep(sleepTimeMS);
}
return false;
}
// Based off of researching microsoft docs and reponses from this question https://stackoverflow.com/questions/30552255/how-to-read-a-bitmap-from-the-windows-clipboard#30552856
// https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader
// Get the byte offset where does the pixels data start (from a packed DIB)
static int GetPixelDataOffset(BITMAPINFOHEADER bih)
{
int offset = 0;
const unsigned int rgbaSize = sizeof(RGBQUAD);
// biSize Specifies the number of bytes required by the structure
// We expect to always be 40 because it should be packed
if (40 == bih.biSize && 40 == sizeof(BITMAPINFOHEADER))
{
//
// biBitCount Specifies the number of bits per pixel.
// Might exist some bit masks *after* the header and *before* the pixel offset
// we're looking, but only if we have more than
// 8 bits per pixel, so we need to ajust for that
//
if (bih.biBitCount > 8)
{
// if bih.biCompression is RBG we should NOT offset more
if (bih.biCompression == BI_BITFIELDS)
{
offset += 3 * rgbaSize;
} else if (bih.biCompression == 6 /* BI_ALPHABITFIELDS */)
{
// Not widely supported, but valid.
offset += 4 * rgbaSize;
}
}
}
//
// biClrUsed Specifies the number of color indices in the color table that are actually used by the bitmap.
// If this value is zero, the bitmap uses the maximum number of colors
// corresponding to the value of the biBitCount member for the compression mode specified by biCompression.
// If biClrUsed is nonzero and the biBitCount member is less than 16
// the biClrUsed member specifies the actual number of colors
//
if (bih.biClrUsed > 0) {
offset += bih.biClrUsed * rgbaSize;
} else {
if (bih.biBitCount < 16)
{
offset = offset + (rgbaSize << bih.biBitCount);
}
}
return bih.biSize + offset;
}
#endif // WIN32_CLIPBOARD_IMPLEMENTATION
// EOF

View file

@ -74,14 +74,14 @@ typedef struct {
// Global Variables Definition // Global Variables Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
extern CoreData CORE; // Global CORE state context extern CoreData CORE; // Global CORE state context
extern bool isGpuReady; // Flag to note GPU has been initialized successfully
static PlatformData platform = { 0 }; // Platform specific data static PlatformData platform = { 0 }; // Platform specific data
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Local Variables Definition // Local Variables Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#define KEYCODE_MAP_SIZE 162 #define KEYCODE_MAP_SIZE 162
static const KeyboardKey KeycodeMap[KEYCODE_MAP_SIZE] = { static const KeyboardKey mapKeycode[KEYCODE_MAP_SIZE] = {
KEY_NULL, // AKEYCODE_UNKNOWN KEY_NULL, // AKEYCODE_UNKNOWN
0, // AKEYCODE_SOFT_LEFT 0, // AKEYCODE_SOFT_LEFT
0, // AKEYCODE_SOFT_RIGHT 0, // AKEYCODE_SOFT_RIGHT
@ -283,14 +283,15 @@ void android_main(struct android_app *app)
// Request to end the native activity // Request to end the native activity
ANativeActivity_finish(app->activity); ANativeActivity_finish(app->activity);
// Android ALooper_pollAll() variables // Android ALooper_pollOnce() variables
int pollResult = 0; int pollResult = 0;
int pollEvents = 0; int pollEvents = 0;
// Waiting for application events before complete finishing // Waiting for application events before complete finishing
while (!app->destroyRequested) while (!app->destroyRequested)
{ {
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void **)&platform.source)) >= 0) // Poll all events until we reach return value TIMEOUT, meaning no events left to process
while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, (void **)&platform.source)) > ALOOPER_POLL_TIMEOUT)
{ {
if (platform.source != NULL) platform.source->process(app, platform.source); if (platform.source != NULL) platform.source->process(app, platform.source);
} }
@ -616,7 +617,7 @@ int SetGamepadMappings(const char *mappings)
} }
// Set gamepad vibration // Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{ {
TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform"); TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform");
} }
@ -634,6 +635,13 @@ void SetMouseCursor(int cursor)
TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform"); TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform");
} }
// Get physical key name.
const char *GetKeyName(int key)
{
TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");
return "";
}
// Register all input events // Register all input events
void PollInputEvents(void) void PollInputEvents(void)
{ {
@ -662,7 +670,7 @@ void PollInputEvents(void)
CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k]; CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
} }
} }
// Register previous touch states // Register previous touch states
for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i]; for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
@ -677,27 +685,27 @@ void PollInputEvents(void)
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
} }
// Android ALooper_pollAll() variables // Android ALooper_pollOnce() variables
int pollResult = 0; int pollResult = 0;
int pollEvents = 0; int pollEvents = 0;
// Poll Events (registered events) // Poll Events (registered events) until we reach TIMEOUT which indicates there are no events left to poll
// NOTE: Activity is paused if not enabled (platform.appEnabled) // NOTE: Activity is paused if not enabled (platform.appEnabled)
while ((pollResult = ALooper_pollAll(platform.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&platform.source)) >= 0) while ((pollResult = ALooper_pollOnce(platform.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT)
{ {
// Process this event // Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source); if (platform.source != NULL) platform.source->process(platform.app, platform.source);
// NOTE: Never close window, native activity is controlled by the system! // NOTE: Allow closing the window in case a configuration change happened.
// The android_main function should be allowed to return to its caller in order for the
// Android OS to relaunch the activity.
if (platform.app->destroyRequested != 0) if (platform.app->destroyRequested != 0)
{ {
//CORE.Window.shouldClose = true; CORE.Window.shouldClose = true;
//ANativeActivity_finish(platform.app->activity);
} }
} }
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -762,20 +770,20 @@ int InitPlatform(void)
TRACELOG(LOG_INFO, "PLATFORM: ANDROID: Initialized successfully"); TRACELOG(LOG_INFO, "PLATFORM: ANDROID: Initialized successfully");
// Android ALooper_pollAll() variables // Android ALooper_pollOnce() variables
int pollResult = 0; int pollResult = 0;
int pollEvents = 0; int pollEvents = 0;
// Wait for window to be initialized (display and context) // Wait for window to be initialized (display and context)
while (!CORE.Window.ready) while (!CORE.Window.ready)
{ {
// Process events loop // Process events until we reach TIMEOUT, which indicates no more events queued.
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&platform.source)) >= 0) while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT)
{ {
// Process this event // Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source); if (platform.source != NULL) platform.source->process(platform.app, platform.source);
// NOTE: Never close window, native activity is controlled by the system! // NOTE: It's highly likely destroyRequested will never be non-zero at the start of the activity lifecycle.
//if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true; //if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true;
} }
} }
@ -806,6 +814,12 @@ void ClosePlatform(void)
eglTerminate(platform.device); eglTerminate(platform.device);
platform.device = EGL_NO_DISPLAY; platform.device = EGL_NO_DISPLAY;
} }
// NOTE: Reset global state in case the activity is being relaunched.
if (platform.app->destroyRequested != 0) {
CORE = (CoreData){0};
platform = (PlatformData){0};
}
} }
// Initialize display device and framebuffer // Initialize display device and framebuffer
@ -976,6 +990,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Initialize OpenGL context (states and resources) // Initialize OpenGL context (states and resources)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
isGpuReady = true;
// Setup default viewport // Setup default viewport
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height // NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
@ -1135,9 +1150,9 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_RIGHT_Y] = AMotionEvent_getAxisValue( CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_RIGHT_Y] = AMotionEvent_getAxisValue(
event, AMOTION_EVENT_AXIS_RZ, 0); event, AMOTION_EVENT_AXIS_RZ, 0);
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_LEFT_TRIGGER] = AMotionEvent_getAxisValue( CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_LEFT_TRIGGER] = AMotionEvent_getAxisValue(
event, AMOTION_EVENT_AXIS_BRAKE, 0) * 2.0f - 1.0f; event, AMOTION_EVENT_AXIS_BRAKE, 0)*2.0f - 1.0f;
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_RIGHT_TRIGGER] = AMotionEvent_getAxisValue( CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_RIGHT_TRIGGER] = AMotionEvent_getAxisValue(
event, AMOTION_EVENT_AXIS_GAS, 0) * 2.0f - 1.0f; event, AMOTION_EVENT_AXIS_GAS, 0)*2.0f - 1.0f;
// dpad is reported as an axis on android // dpad is reported as an axis on android
float dpadX = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_X, 0); float dpadX = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_X, 0);
@ -1203,7 +1218,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
return 1; // Handled gamepad button return 1; // Handled gamepad button
} }
KeyboardKey key = (keycode > 0 && keycode < KEYCODE_MAP_SIZE) ? KeycodeMap[keycode] : KEY_NULL; KeyboardKey key = (keycode > 0 && keycode < KEYCODE_MAP_SIZE)? mapKeycode[keycode] : KEY_NULL;
if (key != KEY_NULL) if (key != KEY_NULL)
{ {
// Save current key and its state // Save current key and its state
@ -1254,10 +1269,10 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
CORE.Input.Touch.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) }; CORE.Input.Touch.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) };
// Normalize CORE.Input.Touch.position[i] for CORE.Window.screen.width and CORE.Window.screen.height // Normalize CORE.Input.Touch.position[i] for CORE.Window.screen.width and CORE.Window.screen.height
float widthRatio = (float)(CORE.Window.screen.width + CORE.Window.renderOffset.x) / (float)CORE.Window.display.width; float widthRatio = (float)(CORE.Window.screen.width + CORE.Window.renderOffset.x)/(float)CORE.Window.display.width;
float heightRatio = (float)(CORE.Window.screen.height + CORE.Window.renderOffset.y) / (float)CORE.Window.display.height; float heightRatio = (float)(CORE.Window.screen.height + CORE.Window.renderOffset.y)/(float)CORE.Window.display.height;
CORE.Input.Touch.position[i].x = CORE.Input.Touch.position[i].x * widthRatio - (float)CORE.Window.renderOffset.x / 2; CORE.Input.Touch.position[i].x = CORE.Input.Touch.position[i].x*widthRatio - (float)CORE.Window.renderOffset.x/2;
CORE.Input.Touch.position[i].y = CORE.Input.Touch.position[i].y * heightRatio - (float)CORE.Window.renderOffset.y / 2; CORE.Input.Touch.position[i].y = CORE.Input.Touch.position[i].y*heightRatio - (float)CORE.Window.renderOffset.y/2;
} }
int32_t action = AMotionEvent_getAction(event); int32_t action = AMotionEvent_getAction(event);

View file

@ -58,6 +58,7 @@
#if defined(_WIN32) #if defined(_WIN32)
typedef void *PVOID; typedef void *PVOID;
typedef PVOID HANDLE; typedef PVOID HANDLE;
#include "../external/win32_clipboard.h"
typedef HANDLE HWND; typedef HANDLE HWND;
#define GLFW_EXPOSE_NATIVE_WIN32 #define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_NATIVE_INCLUDE_NONE // To avoid some symbols re-definition in windows.h #define GLFW_NATIVE_INCLUDE_NONE // To avoid some symbols re-definition in windows.h
@ -65,8 +66,9 @@
#if defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP) #if defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
// NOTE: Those functions require linking with winmm library // NOTE: Those functions require linking with winmm library
unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod); //#pragma warning(disable: 4273)
unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); __declspec(dllimport) unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
//#pragma warning(default: 4273)
#endif #endif
#endif #endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
@ -109,6 +111,7 @@ static void ErrorCallback(int error, const char *description);
// Window callbacks events // Window callbacks events
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
static void WindowPosCallback(GLFWwindow* window, int x, int y); // GLFW3 WindowPos Callback, runs when window is moved
static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored
static void WindowMaximizeCallback(GLFWwindow* window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized static void WindowMaximizeCallback(GLFWwindow* window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized
static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus
@ -147,7 +150,7 @@ void ToggleFullscreen(void)
if (!CORE.Window.fullscreen) if (!CORE.Window.fullscreen)
{ {
// Store previous window position (in case we exit fullscreen) // Store previous window position (in case we exit fullscreen)
glfwGetWindowPos(platform.handle, &CORE.Window.position.x, &CORE.Window.position.y); CORE.Window.previousPosition = CORE.Window.position;
int monitorCount = 0; int monitorCount = 0;
int monitorIndex = GetCurrentMonitor(); int monitorIndex = GetCurrentMonitor();
@ -179,7 +182,11 @@ void ToggleFullscreen(void)
CORE.Window.fullscreen = false; CORE.Window.fullscreen = false;
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE; CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE); glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.previousPosition.x, CORE.Window.previousPosition.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
// we update the window position right away
CORE.Window.position.x = CORE.Window.previousPosition.x;
CORE.Window.position.y = CORE.Window.previousPosition.y;
} }
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS) // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
@ -190,11 +197,11 @@ void ToggleFullscreen(void)
// Toggle borderless windowed mode // Toggle borderless windowed mode
void ToggleBorderlessWindowed(void) void ToggleBorderlessWindowed(void)
{ {
// Leave fullscreen before attempting to set borderless windowed mode and get screen position from it // Leave fullscreen before attempting to set borderless windowed mode
bool wasOnFullscreen = false; bool wasOnFullscreen = false;
if (CORE.Window.fullscreen) if (CORE.Window.fullscreen)
{ {
CORE.Window.previousPosition = CORE.Window.position; // fullscreen already saves the previous position so it does not need to be set here again
ToggleFullscreen(); ToggleFullscreen();
wasOnFullscreen = true; wasOnFullscreen = true;
} }
@ -213,7 +220,7 @@ void ToggleBorderlessWindowed(void)
{ {
// Store screen position and size // Store screen position and size
// NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here // NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here
if (!wasOnFullscreen) glfwGetWindowPos(platform.handle, &CORE.Window.previousPosition.x, &CORE.Window.previousPosition.y); if (!wasOnFullscreen) CORE.Window.previousPosition = CORE.Window.position;
CORE.Window.previousScreen = CORE.Window.screen; CORE.Window.previousScreen = CORE.Window.screen;
// Set undecorated and topmost modes and flags // Set undecorated and topmost modes and flags
@ -255,6 +262,9 @@ void ToggleBorderlessWindowed(void)
glfwFocusWindow(platform.handle); glfwFocusWindow(platform.handle);
CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE; CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE;
CORE.Window.position.x = CORE.Window.previousPosition.x;
CORE.Window.position.y = CORE.Window.previousPosition.y;
} }
} }
else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor"); else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");
@ -592,6 +602,9 @@ void SetWindowTitle(const char *title)
// Set window position on screen (windowed mode) // Set window position on screen (windowed mode)
void SetWindowPosition(int x, int y) void SetWindowPosition(int x, int y)
{ {
// Update CORE.Window.position as well
CORE.Window.position.x = x;
CORE.Window.position.y = y;
glfwSetWindowPos(platform.handle, x, y); glfwSetWindowPos(platform.handle, x, y);
} }
@ -614,8 +627,9 @@ void SetWindowMonitor(int monitor)
{ {
TRACELOG(LOG_INFO, "GLFW: Selected monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor])); TRACELOG(LOG_INFO, "GLFW: Selected monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));
const int screenWidth = CORE.Window.screen.width; // Here the render width has to be used again in case high dpi flag is enabled
const int screenHeight = CORE.Window.screen.height; const int screenWidth = CORE.Window.render.width;
const int screenHeight = CORE.Window.render.height;
int monitorWorkareaX = 0; int monitorWorkareaX = 0;
int monitorWorkareaY = 0; int monitorWorkareaY = 0;
int monitorWorkareaWidth = 0; int monitorWorkareaWidth = 0;
@ -666,6 +680,9 @@ void SetWindowMaxSize(int width, int height)
// Set window dimensions // Set window dimensions
void SetWindowSize(int width, int height) void SetWindowSize(int width, int height)
{ {
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
glfwSetWindowSize(platform.handle, width, height); glfwSetWindowSize(platform.handle, width, height);
} }
@ -950,6 +967,33 @@ const char *GetClipboardText(void)
return glfwGetClipboardString(platform.handle); return glfwGetClipboardString(platform.handle);
} }
#if defined(SUPPORT_CLIPBOARD_IMAGE)
// Get clipboard image
Image GetClipboardImage(void)
{
Image image = {0};
unsigned long long int dataSize = 0;
void* fileData = NULL;
#ifdef _WIN32
int width, height;
fileData = (void*)Win32GetClipboardImageData(&width, &height, &dataSize);
#else
TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_GLFW doesn't implement `GetClipboardImage` for this OS");
#endif
if (fileData == NULL)
{
TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data.");
}
else
{
image = LoadImageFromMemory(".bmp", fileData, (int)dataSize);
}
return image;
}
#endif // SUPPORT_CLIPBOARD_IMAGE
// Show mouse cursor // Show mouse cursor
void ShowCursor(void) void ShowCursor(void)
{ {
@ -1045,7 +1089,7 @@ int SetGamepadMappings(const char *mappings)
} }
// Set gamepad vibration // Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{ {
TRACELOG(LOG_WARNING, "GamepadSetVibration() not available on target platform"); TRACELOG(LOG_WARNING, "GamepadSetVibration() not available on target platform");
} }
@ -1072,6 +1116,12 @@ void SetMouseCursor(int cursor)
} }
} }
// Get physical key name.
const char *GetKeyName(int key)
{
return glfwGetKeyName(key, glfwGetKeyScancode(key));
}
// Register all input events // Register all input events
void PollInputEvents(void) void PollInputEvents(void)
{ {
@ -1144,7 +1194,7 @@ void PollInputEvents(void)
const unsigned char *buttons = state.buttons; const unsigned char *buttons = state.buttons;
for (int k = 0; (buttons != NULL) && (k < GLFW_GAMEPAD_BUTTON_DPAD_LEFT + 1) && (k < MAX_GAMEPAD_BUTTONS); k++) for (int k = 0; (buttons != NULL) && (k < MAX_GAMEPAD_BUTTONS); k++)
{ {
int button = -1; // GamepadButton enum values assigned int button = -1; // GamepadButton enum values assigned
@ -1186,7 +1236,7 @@ void PollInputEvents(void)
// Get current axis state // Get current axis state
const float *axes = state.axes; const float *axes = state.axes;
for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1) && (k < MAX_GAMEPAD_AXIS); k++) for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1); k++)
{ {
CORE.Input.Gamepad.axisState[i][k] = axes[k]; CORE.Input.Gamepad.axisState[i][k] = axes[k];
} }
@ -1213,7 +1263,6 @@ void PollInputEvents(void)
glfwSetWindowShouldClose(platform.handle, GLFW_FALSE); glfwSetWindowShouldClose(platform.handle, GLFW_FALSE);
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -1266,6 +1315,11 @@ int InitPlatform(void)
//glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // OpenGL API to use. Alternative: GLFW_OPENGL_ES_API //glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // OpenGL API to use. Alternative: GLFW_OPENGL_ES_API
//glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers //glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers
// Disable GlFW auto iconify behaviour
// Auto Iconify automatically minimizes (iconifies) the window if the window loses focus
// additionally auto iconify restores the hardware resolution of the monitor if the window that loses focus is a fullscreen window
glfwWindowHint(GLFW_AUTO_ICONIFY, 0);
// Check window creation flags // Check window creation flags
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) CORE.Window.fullscreen = true; if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) CORE.Window.fullscreen = true;
@ -1421,7 +1475,7 @@ int InitPlatform(void)
} }
} }
TRACELOG(LOG_WARNING, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height); TRACELOG(LOG_INFO, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
// NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example, // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example,
// for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3), // for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3),
@ -1443,15 +1497,7 @@ int InitPlatform(void)
else else
{ {
// No-fullscreen window creation // No-fullscreen window creation
bool wantWindowedFullscreen = (CORE.Window.screen.height == 0) && (CORE.Window.screen.width == 0); bool requestWindowedFullscreen = (CORE.Window.screen.height == 0) && (CORE.Window.screen.width == 0);
// If we are windowed fullscreen, ensures that window does not minimize when focus is lost.
// This hinting code will not work if the user already specified the correct monitor dimensions;
// at this point we don't know the monitor's dimensions. (Though, how did the user then?)
if (wantWindowedFullscreen)
{
glfwWindowHint(GLFW_AUTO_ICONIFY, 0);
}
// Default to at least one pixel in size, as creation with a zero dimension is not allowed. // Default to at least one pixel in size, as creation with a zero dimension is not allowed.
int creationWidth = CORE.Window.screen.width != 0 ? CORE.Window.screen.width : 1; int creationWidth = CORE.Window.screen.width != 0 ? CORE.Window.screen.width : 1;
@ -1471,11 +1517,7 @@ int InitPlatform(void)
monitor = monitors[monitorIndex]; monitor = monitors[monitorIndex];
SetDimensionsFromMonitor(monitor); SetDimensionsFromMonitor(monitor);
TRACELOG(LOG_INFO, "wantWindowed: %d, size: %dx%d", wantWindowedFullscreen, CORE.Window.screen.width, CORE.Window.screen.height); if (requestWindowedFullscreen) glfwSetWindowSize(platform.handle, CORE.Window.screen.width, CORE.Window.screen.height);
if (wantWindowedFullscreen)
{
glfwSetWindowSize(platform.handle, CORE.Window.screen.width, CORE.Window.screen.height);
}
} }
else else
{ {
@ -1567,11 +1609,16 @@ int InitPlatform(void)
int monitorHeight = 0; int monitorHeight = 0;
glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight); glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight);
int posX = monitorX + (monitorWidth - (int)CORE.Window.screen.width)/2; // Here CORE.Window.render.width/height should be used instead of CORE.Window.screen.width/height to center the window correctly when the high dpi flag is enabled.
int posY = monitorY + (monitorHeight - (int)CORE.Window.screen.height)/2; int posX = monitorX + (monitorWidth - (int)CORE.Window.render.width)/2;
int posY = monitorY + (monitorHeight - (int)CORE.Window.render.height)/2;
if (posX < monitorX) posX = monitorX; if (posX < monitorX) posX = monitorX;
if (posY < monitorY) posY = monitorY; if (posY < monitorY) posY = monitorY;
SetWindowPosition(posX, posY); SetWindowPosition(posX, posY);
// Update CORE.Window.position here so it is correct from the start
CORE.Window.position.x = posX;
CORE.Window.position.y = posY;
} }
// Load OpenGL extensions // Load OpenGL extensions
@ -1583,6 +1630,7 @@ int InitPlatform(void)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Set window callback events // Set window callback events
glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default! glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default!
glfwSetWindowPosCallback(platform.handle, WindowPosCallback);
glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback); glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback);
glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback); glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);
glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback); glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);
@ -1621,18 +1669,23 @@ int InitPlatform(void)
CORE.Storage.basePath = GetWorkingDirectory(); CORE.Storage.basePath = GetWorkingDirectory();
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
char* glfwPlatform = ""; #if defined(__NetBSD__)
// Workaround for NetBSD
char *glfwPlatform = "X11";
#else
char *glfwPlatform = "";
switch (glfwGetPlatform()) switch (glfwGetPlatform())
{ {
case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break; case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break;
case GLFW_PLATFORM_COCOA: glfwPlatform = "Cocoa"; break; case GLFW_PLATFORM_COCOA: glfwPlatform = "Cocoa"; break;
case GLFW_PLATFORM_WAYLAND: glfwPlatform = "Wayland"; break; case GLFW_PLATFORM_WAYLAND: glfwPlatform = "Wayland"; break;
case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break; case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break;
case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break; case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break;
default: break;
} }
#endif
TRACELOG(LOG_INFO, "GLFW platform: %s", glfwPlatform); TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW - %s): Initialized successfully", glfwPlatform);
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW): Initialized successfully");
return 0; return 0;
} }
@ -1668,27 +1721,18 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
if (IsWindowFullscreen()) return; if (IsWindowFullscreen()) return;
// Set current screen size // Set current screen size
#if defined(__APPLE__)
CORE.Window.screen.width = width; CORE.Window.screen.width = width;
CORE.Window.screen.height = height; CORE.Window.screen.height = height;
#else
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
{
Vector2 windowScaleDPI = GetWindowScaleDPI();
CORE.Window.screen.width = (unsigned int)(width/windowScaleDPI.x);
CORE.Window.screen.height = (unsigned int)(height/windowScaleDPI.y);
}
else
{
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
}
#endif
// NOTE: Postprocessing texture is not scaled to new size // NOTE: Postprocessing texture is not scaled to new size
} }
static void WindowPosCallback(GLFWwindow* window, int x, int y)
{
// Set current window position
CORE.Window.position.x = x;
CORE.Window.position.y = y;
}
static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley) static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley)
{ {
CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f); CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f);
@ -1882,4 +1926,8 @@ static void JoystickCallback(int jid, int event)
} }
} }
#ifdef _WIN32
# define WIN32_CLIPBOARD_IMPLEMENTATION
# include "../external/win32_clipboard.h"
#endif
// EOF // EOF

File diff suppressed because it is too large Load diff

View file

@ -23,7 +23,7 @@
* Custom flag for rcore on target platform -not used- * Custom flag for rcore on target platform -not used-
* *
* DEPENDENCIES: * DEPENDENCIES:
* - SDL 2 (main library): Windowing and inputs management * - SDL 2 or SLD 3 (main library): Windowing and inputs management
* - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs) * - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs)
* *
* *
@ -48,6 +48,10 @@
* *
**********************************************************************************************/ **********************************************************************************************/
#ifndef SDL_ENABLE_OLD_NAMES
#define SDL_ENABLE_OLD_NAMES // Just in case we're on SDL3, we need some in-between compatibily
#endif
#include "SDL.h" // SDL base library (window/rendered, input, timing... functionality) #include "SDL.h" // SDL base library (window/rendered, input, timing... functionality)
#if defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_ES2)
@ -57,6 +61,20 @@
#include "SDL_opengl.h" // SDL OpenGL functionality (if required, instead of internal renderer) #include "SDL_opengl.h" // SDL OpenGL functionality (if required, instead of internal renderer)
#endif #endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#ifndef MAX_CLIPBOARD_BUFFER_LENGTH
#define MAX_CLIPBOARD_BUFFER_LENGTH 1024 // Size of the clipboard buffer used on GetClipboardText()
#endif
#if ((defined(SDL_MAJOR_VERSION) && SDL_MAJOR_VERSION == 3) && (defined(SDL_MINOR_VERSION) && SDL_MINOR_VERSION >= 1))
#ifndef PLATFORM_DESKTOP_SDL3
#define PLATFORM_DESKTOP_SDL3
#endif
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -64,7 +82,7 @@ typedef struct {
SDL_Window *window; SDL_Window *window;
SDL_GLContext glContext; SDL_GLContext glContext;
SDL_Joystick *gamepad[MAX_GAMEPADS]; SDL_GameController *gamepad[MAX_GAMEPADS];
SDL_Cursor *cursor; SDL_Cursor *cursor;
bool cursorRelative; bool cursorRelative;
} PlatformData; } PlatformData;
@ -80,7 +98,7 @@ static PlatformData platform = { 0 }; // Platform specific data
// Local Variables Definition // Local Variables Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#define SCANCODE_MAPPED_NUM 232 #define SCANCODE_MAPPED_NUM 232
static const KeyboardKey ScancodeToKey[SCANCODE_MAPPED_NUM] = { static const KeyboardKey mapScancodeToKey[SCANCODE_MAPPED_NUM] = {
KEY_NULL, // SDL_SCANCODE_UNKNOWN KEY_NULL, // SDL_SCANCODE_UNKNOWN
0, 0,
0, 0,
@ -220,6 +238,190 @@ static const int CursorsLUT[] = {
//SDL_SYSTEM_CURSOR_WAITARROW, // No equivalent implemented on MouseCursor enum on raylib.h //SDL_SYSTEM_CURSOR_WAITARROW, // No equivalent implemented on MouseCursor enum on raylib.h
}; };
// SDL3 Migration Layer made to avoid `ifdefs` inside functions when we can.
#ifdef PLATFORM_DESKTOP_SDL3
// SDL3 Migration:
// SDL_WINDOW_FULLSCREEN_DESKTOP has been removed,
// and you can call SDL_GetWindowFullscreenMode()
// to see whether an exclusive fullscreen mode will be used
// or the borderless fullscreen desktop mode will be used
#define SDL_WINDOW_FULLSCREEN_DESKTOP SDL_WINDOW_FULLSCREEN
#define SDL_IGNORE false
#define SDL_DISABLE false
#define SDL_ENABLE true
// SDL3 Migration: SDL_INIT_TIMER - no longer needed before calling SDL_AddTimer()
#define SDL_INIT_TIMER 0x0 // It's a flag, so no problem in setting it to zero if we use in a bitor (|)
// SDL3 Migration: The SDL_WINDOW_SHOWN flag has been removed. Windows are shown by default and can be created hidden by using the SDL_WINDOW_HIDDEN flag.
#define SDL_WINDOW_SHOWN 0x0 // It's a flag, so no problem in setting it to zero if we use in a bitor (|)
//
// SDL3 Migration: Renamed
// IMPORTANT:
// Might need to call SDL_CleanupEvent somewhere see :https://github.com/libsdl-org/SDL/issues/3540#issuecomment-1793449852
//
#define SDL_DROPFILE SDL_EVENT_DROP_FILE
const char* SDL_GameControllerNameForIndex(int joystickIndex)
{
// NOTE: SDL3 uses the IDs itself (SDL_JoystickID) instead of SDL2 joystick_index
const char* name = NULL;
int numJoysticks = 0;
SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks);
if (joysticks) {
if (joystickIndex < numJoysticks) {
SDL_JoystickID instance_id = joysticks[joystickIndex];
name = SDL_GetGamepadNameForID(instance_id);
}
SDL_free(joysticks);
}
return name;
}
int SDL_GetNumVideoDisplays(void)
{
int monitorCount = 0;
SDL_DisplayID *displays = SDL_GetDisplays(&monitorCount);
// Safe because If `mem` is NULL, SDL_free does nothing.
SDL_free(displays);
return monitorCount;
}
// SLD3 Migration:
// To emulate SDL2 this function should return `SDL_DISABLE` or `SDL_ENABLE`
// representing the *processing state* of the event before this function makes any changes to it.
Uint8 SDL_EventState(Uint32 type, int state) {
Uint8 stateBefore = SDL_EventEnabled(type);
switch (state)
{
case SDL_DISABLE: SDL_SetEventEnabled(type, false); break;
case SDL_ENABLE: SDL_SetEventEnabled(type, true); break;
default: TRACELOG(LOG_WARNING, "Event sate: unknow type");
}
return stateBefore;
}
void SDL_GetCurrentDisplayMode_Adapter(SDL_DisplayID displayID, SDL_DisplayMode* mode)
{
const SDL_DisplayMode* currMode = SDL_GetCurrentDisplayMode(displayID);
if (currMode == NULL)
{
TRACELOG(LOG_WARNING, "No current display mode");
}
else
{
*mode = *currMode;
}
}
// SDL3 Migration: Renamed
#define SDL_GetCurrentDisplayMode SDL_GetCurrentDisplayMode_Adapter
SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
{
return SDL_CreateSurface(width, height, SDL_GetPixelFormatForMasks(depth, Rmask, Gmask, Bmask, Amask));
}
// SDL3 Migration:
// SDL_GetDisplayDPI() -
// not reliable across platforms, approximately replaced by multiplying
// SDL_GetWindowDisplayScale() times 160 on iPhone and Android, and 96 on other platforms.
// returns 0 on success or a negative error code on failure
int SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi) {
float dpi = SDL_GetWindowDisplayScale(platform.window) * 96.0;
if (ddpi != NULL) *ddpi = dpi;
if (hdpi != NULL) *hdpi = dpi;
if (vdpi != NULL) *vdpi = dpi;
return 0;
}
SDL_Surface *SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, Uint32 format)
{
return SDL_CreateSurface(width, height, format);
}
SDL_Surface *SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
{
return SDL_CreateSurfaceFrom(width, height, SDL_GetPixelFormatForMasks(depth, Rmask, Gmask, Bmask, Amask), pixels, pitch);
}
SDL_Surface *SDL_CreateRGBSurfaceWithFormatFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 format)
{
return SDL_CreateSurfaceFrom(width, height, format, pixels, pitch);
}
int SDL_NumJoysticks(void)
{
int numJoysticks;
SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks);
SDL_free(joysticks);
return numJoysticks;
}
// SDL_SetRelativeMouseMode
// returns 0 on success or a negative error code on failure
// If relative mode is not supported, this returns -1.
int SDL_SetRelativeMouseMode_Adapter(SDL_bool enabled)
{
//
// SDL_SetWindowRelativeMouseMode(SDL_Window *window, bool enabled)
// \returns true on success or false on failure; call SDL_GetError() for more
//
if (SDL_SetWindowRelativeMouseMode(platform.window, enabled))
{
return 0; // success
}
else
{
return -1; // failure
}
}
#define SDL_SetRelativeMouseMode SDL_SetRelativeMouseMode_Adapter
bool SDL_GetRelativeMouseMode_Adapter(void)
{
return SDL_GetWindowRelativeMouseMode(platform.window);
}
#define SDL_GetRelativeMouseMode SDL_GetRelativeMouseMode_Adapter
int SDL_GetNumTouchFingers(SDL_TouchID touchID)
{
// SDL_Finger **SDL_GetTouchFingers(SDL_TouchID touchID, int *count)
int count = 0;
SDL_Finger **fingers = SDL_GetTouchFingers(touchID, &count);
SDL_free(fingers);
return count;
}
#else // We're on SDL2
// Since SDL2 doesn't have this function we leave a stub
// SDL_GetClipboardData function is available since SDL 3.1.3. (e.g. SDL3)
void* SDL_GetClipboardData(const char *mime_type, size_t *size) {
TRACELOG(LOG_WARNING, "Getting clipboard data that is not text is only available in SDL3");
// We could possibly implement it ourselves in this case for some easier platforms
return NULL;
}
#endif // PLATFORM_DESKTOP_SDL3
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Declaration // Module Internal Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -249,7 +451,12 @@ void ToggleFullscreen(void)
{ {
const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays(); const int monitorCount = SDL_GetNumVideoDisplays();
#ifdef PLATFORM_DESKTOP_SDL3 // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if ((monitor > 0) && (monitor <= monitorCount))
#else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < monitorCount))
#endif
{ {
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0)
{ {
@ -272,7 +479,11 @@ void ToggleBorderlessWindowed(void)
{ {
const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays(); const int monitorCount = SDL_GetNumVideoDisplays();
#ifdef PLATFORM_DESKTOP_SDL3 // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if ((monitor > 0) && (monitor <= monitorCount))
#else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < monitorCount))
#endif
{ {
if ((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0) if ((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0)
{ {
@ -321,7 +532,11 @@ void SetWindowState(unsigned int flags)
{ {
const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays(); const int monitorCount = SDL_GetNumVideoDisplays();
#ifdef PLATFORM_DESKTOP_SDL3 // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if ((monitor > 0) && (monitor <= monitorCount))
#else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < monitorCount))
#endif
{ {
SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN); SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN);
CORE.Window.fullscreen = true; CORE.Window.fullscreen = true;
@ -380,7 +595,11 @@ void SetWindowState(unsigned int flags)
{ {
const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays(); const int monitorCount = SDL_GetNumVideoDisplays();
#ifdef PLATFORM_DESKTOP_SDL3 // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if ((monitor > 0) && (monitor <= monitorCount))
#else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < monitorCount))
#endif
{ {
SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN_DESKTOP); SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN_DESKTOP);
} }
@ -476,9 +695,9 @@ void ClearWindowState(unsigned int flags)
// Set icon for window // Set icon for window
void SetWindowIcon(Image image) void SetWindowIcon(Image image)
{ {
SDL_Surface* iconSurface = NULL; SDL_Surface *iconSurface = NULL;
Uint32 rmask, gmask, bmask, amask; unsigned int rmask = 0, gmask = 0, bmask = 0, amask = 0;
int depth = 0; // Depth in bits int depth = 0; // Depth in bits
int pitch = 0; // Pixel spacing (pitch) in bytes int pitch = 0; // Pixel spacing (pitch) in bytes
@ -492,72 +711,67 @@ void SetWindowIcon(Image image)
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
rmask = 0xFF, gmask = 0xFF00; rmask = 0xFF, gmask = 0xFF00;
bmask = 0, amask = 0; bmask = 0, amask = 0;
depth = 16, pitch = image.width * 2; depth = 16, pitch = image.width*2;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R5G6B5: case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
rmask = 0xF800, gmask = 0x07E0; rmask = 0xF800, gmask = 0x07E0;
bmask = 0x001F, amask = 0; bmask = 0x001F, amask = 0;
depth = 16, pitch = image.width * 2; depth = 16, pitch = image.width*2;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // Uses BGR for 24-bit case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // Uses BGR for 24-bit
rmask = 0x0000FF, gmask = 0x00FF00; rmask = 0x0000FF, gmask = 0x00FF00;
bmask = 0xFF0000, amask = 0; bmask = 0xFF0000, amask = 0;
depth = 24, pitch = image.width * 3; depth = 24, pitch = image.width*3;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
rmask = 0xF800, gmask = 0x07C0; rmask = 0xF800, gmask = 0x07C0;
bmask = 0x003E, amask = 0x0001; bmask = 0x003E, amask = 0x0001;
depth = 16, pitch = image.width * 2; depth = 16, pitch = image.width*2;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
rmask = 0xF000, gmask = 0x0F00; rmask = 0xF000, gmask = 0x0F00;
bmask = 0x00F0, amask = 0x000F; bmask = 0x00F0, amask = 0x000F;
depth = 16, pitch = image.width * 2; depth = 16, pitch = image.width*2;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
rmask = 0xFF000000, gmask = 0x00FF0000; rmask = 0xFF000000, gmask = 0x00FF0000;
bmask = 0x0000FF00, amask = 0x000000FF; bmask = 0x0000FF00, amask = 0x000000FF;
depth = 32, pitch = image.width * 4; depth = 32, pitch = image.width*4;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R32: case PIXELFORMAT_UNCOMPRESSED_R32:
rmask = 0xFFFFFFFF, gmask = 0; rmask = 0xFFFFFFFF, gmask = 0;
bmask = 0, amask = 0; bmask = 0, amask = 0;
depth = 32, pitch = image.width * 4; depth = 32, pitch = image.width*4;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R32G32B32: case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF; rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
bmask = 0xFFFFFFFF, amask = 0; bmask = 0xFFFFFFFF, amask = 0;
depth = 96, pitch = image.width * 12; depth = 96, pitch = image.width*12;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF; rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
bmask = 0xFFFFFFFF, amask = 0xFFFFFFFF; bmask = 0xFFFFFFFF, amask = 0xFFFFFFFF;
depth = 128, pitch = image.width * 16; depth = 128, pitch = image.width*16;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R16: case PIXELFORMAT_UNCOMPRESSED_R16:
rmask = 0xFFFF, gmask = 0; rmask = 0xFFFF, gmask = 0;
bmask = 0, amask = 0; bmask = 0, amask = 0;
depth = 16, pitch = image.width * 2; depth = 16, pitch = image.width*2;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R16G16B16: case PIXELFORMAT_UNCOMPRESSED_R16G16B16:
rmask = 0xFFFF, gmask = 0xFFFF; rmask = 0xFFFF, gmask = 0xFFFF;
bmask = 0xFFFF, amask = 0; bmask = 0xFFFF, amask = 0;
depth = 48, pitch = image.width * 6; depth = 48, pitch = image.width*6;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:
rmask = 0xFFFF, gmask = 0xFFFF; rmask = 0xFFFF, gmask = 0xFFFF;
bmask = 0xFFFF, amask = 0xFFFF; bmask = 0xFFFF, amask = 0xFFFF;
depth = 64, pitch = image.width * 8; depth = 64, pitch = image.width*8;
break; break;
default: default: return; // Compressed formats are not supported
// Compressed formats are not supported
return;
} }
iconSurface = SDL_CreateRGBSurfaceFrom( iconSurface = SDL_CreateRGBSurfaceFrom( image.data, image.width, image.height, depth, pitch, rmask, gmask, bmask, amask );
image.data, image.width, image.height, depth, pitch,
rmask, gmask, bmask, amask
);
if (iconSurface) if (iconSurface)
{ {
@ -599,12 +813,16 @@ void SetWindowMonitor(int monitor)
// 1. SDL started supporting moving exclusive fullscreen windows between displays on SDL3, // 1. SDL started supporting moving exclusive fullscreen windows between displays on SDL3,
// see commit https://github.com/libsdl-org/SDL/commit/3f5ef7dd422057edbcf3e736107e34be4b75d9ba // see commit https://github.com/libsdl-org/SDL/commit/3f5ef7dd422057edbcf3e736107e34be4b75d9ba
// 2. A workaround for SDL2 is leaving fullscreen, moving the window, then entering full screen again. // 2. A workaround for SDL2 is leaving fullscreen, moving the window, then entering full screen again.
const bool wasFullscreen = ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) ? true : false; const bool wasFullscreen = ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0)? true : false;
const int screenWidth = CORE.Window.screen.width; const int screenWidth = CORE.Window.screen.width;
const int screenHeight = CORE.Window.screen.height; const int screenHeight = CORE.Window.screen.height;
SDL_Rect usableBounds; SDL_Rect usableBounds;
#ifdef PLATFORM_DESKTOP_SDL3 // Different style for success checking
if (SDL_GetDisplayUsableBounds(monitor, &usableBounds))
#else
if (SDL_GetDisplayUsableBounds(monitor, &usableBounds) == 0) if (SDL_GetDisplayUsableBounds(monitor, &usableBounds) == 0)
#endif
{ {
if (wasFullscreen == 1) ToggleFullscreen(); // Leave fullscreen. if (wasFullscreen == 1) ToggleFullscreen(); // Leave fullscreen.
@ -702,6 +920,7 @@ int GetCurrentMonitor(void)
{ {
int currentMonitor = 0; int currentMonitor = 0;
// Be aware that this returns an ID in SDL3 and a Index in SDL2
currentMonitor = SDL_GetWindowDisplayIndex(platform.window); currentMonitor = SDL_GetWindowDisplayIndex(platform.window);
return currentMonitor; return currentMonitor;
@ -714,7 +933,11 @@ Vector2 GetMonitorPosition(int monitor)
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < monitorCount))
{ {
SDL_Rect displayBounds; SDL_Rect displayBounds;
#ifdef PLATFORM_DESKTOP_SDL3
if (SDL_GetDisplayUsableBounds(monitor, &displayBounds))
#else
if (SDL_GetDisplayUsableBounds(monitor, &displayBounds) == 0) if (SDL_GetDisplayUsableBounds(monitor, &displayBounds) == 0)
#endif
{ {
return (Vector2){ (float)displayBounds.x, (float)displayBounds.y }; return (Vector2){ (float)displayBounds.x, (float)displayBounds.y };
} }
@ -842,10 +1065,16 @@ Vector2 GetWindowScaleDPI(void)
{ {
Vector2 scale = { 1.0f, 1.0f }; Vector2 scale = { 1.0f, 1.0f };
#ifndef PLATFORM_DESKTOP_SDL3
// NOTE: SDL_GetWindowDisplayScale was only added on SDL3 // NOTE: SDL_GetWindowDisplayScale was only added on SDL3
// see https://wiki.libsdl.org/SDL3/SDL_GetWindowDisplayScale // see https://wiki.libsdl.org/SDL3/SDL_GetWindowDisplayScale
// TODO: Implement the window scale factor calculation manually. // TODO: Implement the window scale factor calculation manually.
TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform"); TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform");
#else
scale.x = SDL_GetWindowDisplayScale(platform.window);
scale.y = scale.x;
TRACELOG(LOG_INFO, "WindowScaleDPI is %f", scale.x);
#endif
return scale; return scale;
} }
@ -857,25 +1086,86 @@ void SetClipboardText(const char *text)
} }
// Get clipboard text content // Get clipboard text content
// NOTE: returned string must be freed with SDL_free()
const char *GetClipboardText(void) const char *GetClipboardText(void)
{ {
return SDL_GetClipboardText(); static char buffer[MAX_CLIPBOARD_BUFFER_LENGTH] = { 0 };
char *clipboard = SDL_GetClipboardText();
int clipboardSize = snprintf(buffer, sizeof(buffer), "%s", clipboard);
if (clipboardSize >= MAX_CLIPBOARD_BUFFER_LENGTH)
{
char *truncate = buffer + MAX_CLIPBOARD_BUFFER_LENGTH - 4;
sprintf(truncate, "...");
}
SDL_free(clipboard);
return buffer;
} }
#if defined(SUPPORT_CLIPBOARD_IMAGE)
// Get clipboard image
Image GetClipboardImage(void)
{
// Let's hope compiler put these arrays in static memory
const char *image_formats[] = {
"image/bmp",
"image/png",
"image/jpg",
"image/tiff",
};
const char *image_extensions[] = {
".bmp",
".png",
".jpg",
".tiff",
};
Image image = {0};
size_t dataSize = 0;
void *fileData = NULL;
for (int i = 0; i < SDL_arraysize(image_formats); ++i)
{
// NOTE: This pointer should be free with SDL_free() at some point.
fileData = SDL_GetClipboardData(image_formats[i], &dataSize);
if (fileData) {
image = LoadImageFromMemory(image_extensions[i], fileData, dataSize);
if (IsImageValid(image))
{
TRACELOG(LOG_INFO, "Clipboard image: Got image from clipboard as a `%s` successfully", image_extensions[i]);
return image;
}
}
}
TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data. %s", SDL_GetError());
return image;
}
#endif
// Show mouse cursor // Show mouse cursor
void ShowCursor(void) void ShowCursor(void)
{ {
#ifdef PLATFORM_DESKTOP_SDL3
SDL_ShowCursor();
#else
SDL_ShowCursor(SDL_ENABLE); SDL_ShowCursor(SDL_ENABLE);
#endif
CORE.Input.Mouse.cursorHidden = false; CORE.Input.Mouse.cursorHidden = false;
} }
// Hides mouse cursor // Hides mouse cursor
void HideCursor(void) void HideCursor(void)
{ {
#ifdef PLATFORM_DESKTOP_SDL3
SDL_HideCursor();
#else
SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
#endif
CORE.Input.Mouse.cursorHidden = true; CORE.Input.Mouse.cursorHidden = true;
} }
@ -883,7 +1173,13 @@ void HideCursor(void)
void EnableCursor(void) void EnableCursor(void)
{ {
SDL_SetRelativeMouseMode(SDL_FALSE); SDL_SetRelativeMouseMode(SDL_FALSE);
#ifdef PLATFORM_DESKTOP_SDL3
// SDL_ShowCursor() has been split into three functions: SDL_ShowCursor(), SDL_HideCursor(), and SDL_CursorVisible()
SDL_ShowCursor();
#else
SDL_ShowCursor(SDL_ENABLE); SDL_ShowCursor(SDL_ENABLE);
#endif
platform.cursorRelative = false; platform.cursorRelative = false;
CORE.Input.Mouse.cursorHidden = false; CORE.Input.Mouse.cursorHidden = false;
@ -939,17 +1235,17 @@ int SetGamepadMappings(const char *mappings)
} }
// Set gamepad vibration // Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{ {
//Limit input values to between 0.0f and 1.0f if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (duration > 0.0f))
leftMotor = (0.0f > leftMotor) ? 0.0f : leftMotor;
rightMotor = (0.0f > rightMotor) ? 0.0f : rightMotor;
leftMotor = (1.0f < leftMotor) ? 1.0f : leftMotor;
rightMotor = (1.0f < rightMotor) ? 1.0f : rightMotor;
if (IsGamepadAvailable(gamepad))
{ {
SDL_JoystickRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(MAX_GAMEPAD_VIBRATION_TIME*1000.0f)); if (leftMotor < 0.0f) leftMotor = 0.0f;
if (leftMotor > 1.0f) leftMotor = 1.0f;
if (rightMotor < 0.0f) rightMotor = 0.0f;
if (rightMotor > 1.0f) rightMotor = 1.0f;
if (duration > MAX_GAMEPAD_VIBRATION_TIME) duration = MAX_GAMEPAD_VIBRATION_TIME;
SDL_GameControllerRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(duration*1000.0f));
} }
} }
@ -971,8 +1267,30 @@ void SetMouseCursor(int cursor)
CORE.Input.Mouse.cursor = cursor; CORE.Input.Mouse.cursor = cursor;
} }
// Get physical key name.
const char *GetKeyName(int key)
{
return SDL_GetKeyName(key);
}
static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event) static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event)
{ {
#ifdef PLATFORM_DESKTOP_SDL3 // SDL3
int count = 0;
SDL_Finger **fingers = SDL_GetTouchFingers(event.touchID, &count);
CORE.Input.Touch.pointCount = count;
for (int i = 0; i < CORE.Input.Touch.pointCount; i++)
{
SDL_Finger *finger = fingers[i];
CORE.Input.Touch.pointId[i] = finger->id;
CORE.Input.Touch.position[i].x = finger->x*CORE.Window.screen.width;
CORE.Input.Touch.position[i].y = finger->y*CORE.Window.screen.height;
CORE.Input.Touch.currentTouchState[i] = 1;
}
SDL_free(fingers);
#else // SDL2
CORE.Input.Touch.pointCount = SDL_GetNumTouchFingers(event.touchId); CORE.Input.Touch.pointCount = SDL_GetNumTouchFingers(event.touchId);
for (int i = 0; i < CORE.Input.Touch.pointCount; i++) for (int i = 0; i < CORE.Input.Touch.pointCount; i++)
@ -983,6 +1301,7 @@ static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event)
CORE.Input.Touch.position[i].y = finger->y*CORE.Window.screen.height; CORE.Input.Touch.position[i].y = finger->y*CORE.Window.screen.height;
CORE.Input.Touch.currentTouchState[i] = 1; CORE.Input.Touch.currentTouchState[i] = 1;
} }
#endif
for (int i = CORE.Input.Touch.pointCount; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.currentTouchState[i] = 0; for (int i = CORE.Input.Touch.pointCount; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.currentTouchState[i] = 0;
} }
@ -1074,16 +1393,26 @@ void PollInputEvents(void)
CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *)); CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *));
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
#ifdef PLATFORM_DESKTOP_SDL3
// const char *data; /**< The text for SDL_EVENT_DROP_TEXT and the file name for SDL_EVENT_DROP_FILE, NULL for other events */
// Event memory is now managed by SDL, so you should not free the data in SDL_EVENT_DROP_FILE, and if you want to hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events, you should make a copy of it. SDL_TEXTINPUTEVENT_TEXT_SIZE is no longer necessary and has been removed.
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data);
#else
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file); strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file);
SDL_free(event.drop.file); SDL_free(event.drop.file);
#endif
CORE.Window.dropFileCount++; CORE.Window.dropFileCount++;
} }
else if (CORE.Window.dropFileCount < 1024) else if (CORE.Window.dropFileCount < 1024)
{ {
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
#ifdef PLATFORM_DESKTOP_SDL3
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data);
#else
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file); strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file);
SDL_free(event.drop.file); SDL_free(event.drop.file);
#endif
CORE.Window.dropFileCount++; CORE.Window.dropFileCount++;
} }
@ -1092,10 +1421,18 @@ void PollInputEvents(void)
} break; } break;
// Window events are also polled (Minimized, maximized, close...) // Window events are also polled (Minimized, maximized, close...)
#ifndef PLATFORM_DESKTOP_SDL3
// SDL3 states:
// The SDL_WINDOWEVENT_* events have been moved to top level events,
// and SDL_WINDOWEVENT has been removed.
// In general, handling this change just means checking for the individual events instead of first checking for SDL_WINDOWEVENT
// and then checking for window events. You can compare the event >= SDL_EVENT_WINDOW_FIRST and <= SDL_EVENT_WINDOW_LAST if you need to see whether it's a window event.
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
{ {
switch (event.window.event) switch (event.window.event)
{ {
#endif
case SDL_WINDOWEVENT_RESIZED: case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_SIZE_CHANGED: case SDL_WINDOWEVENT_SIZE_CHANGED:
{ {
@ -1123,16 +1460,26 @@ void PollInputEvents(void)
case SDL_WINDOWEVENT_FOCUS_GAINED: case SDL_WINDOWEVENT_FOCUS_GAINED:
case SDL_WINDOWEVENT_MAXIMIZED: case SDL_WINDOWEVENT_MAXIMIZED:
case SDL_WINDOWEVENT_RESTORED: case SDL_WINDOWEVENT_RESTORED:
#ifdef PLATFORM_DESKTOP_SDL3
break;
#else
default: break; default: break;
} }
} break; } break;
#endif
// Keyboard events // Keyboard events
case SDL_KEYDOWN: case SDL_KEYDOWN:
{ {
#ifdef PLATFORM_DESKTOP_SDL3
// SDL3 Migration: The following structures have been removed: * SDL_Keysym
KeyboardKey key = ConvertScancodeToKey(event.key.scancode);
#else
KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode); KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode);
#endif
if (key != KEY_NULL) { if (key != KEY_NULL)
{
// If key was up, add it to the key pressed queue // If key was up, add it to the key pressed queue
if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE)) if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE))
{ {
@ -1154,7 +1501,12 @@ void PollInputEvents(void)
case SDL_KEYUP: case SDL_KEYUP:
{ {
#ifdef PLATFORM_DESKTOP_SDL3
KeyboardKey key = ConvertScancodeToKey(event.key.scancode);
#else
KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode); KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode);
#endif
if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0; if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0;
} break; } break;
@ -1249,15 +1601,15 @@ void PollInputEvents(void)
if (!CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS)) if (!CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS))
{ {
platform.gamepad[jid] = SDL_JoystickOpen(jid); platform.gamepad[jid] = SDL_GameControllerOpen(jid);
if (platform.gamepad[jid]) if (platform.gamepad[jid])
{ {
CORE.Input.Gamepad.ready[jid] = true; CORE.Input.Gamepad.ready[jid] = true;
CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(platform.gamepad[jid]); CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[jid]));
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
strncpy(CORE.Input.Gamepad.name[jid], SDL_JoystickName(platform.gamepad[jid]), 63); strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), 63);
CORE.Input.Gamepad.name[jid][63] = '\0'; CORE.Input.Gamepad.name[jid][63] = '\0';
} }
else else
@ -1270,15 +1622,15 @@ void PollInputEvents(void)
{ {
int jid = event.jdevice.which; int jid = event.jdevice.which;
if (jid == SDL_JoystickInstanceID(platform.gamepad[jid])) if (jid == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[jid])))
{ {
SDL_JoystickClose(platform.gamepad[jid]); SDL_GameControllerClose(platform.gamepad[jid]);
platform.gamepad[jid] = SDL_JoystickOpen(0); platform.gamepad[jid] = SDL_GameControllerOpen(0);
CORE.Input.Gamepad.ready[jid] = false; CORE.Input.Gamepad.ready[jid] = false;
memset(CORE.Input.Gamepad.name[jid], 0, 64); memset(CORE.Input.Gamepad.name[jid], 0, 64);
} }
} break; } break;
case SDL_JOYBUTTONDOWN: case SDL_CONTROLLERBUTTONDOWN:
{ {
int button = -1; int button = -1;
@ -1312,7 +1664,7 @@ void PollInputEvents(void)
CORE.Input.Gamepad.lastButtonPressed = button; CORE.Input.Gamepad.lastButtonPressed = button;
} }
} break; } break;
case SDL_JOYBUTTONUP: case SDL_CONTROLLERBUTTONUP:
{ {
int button = -1; int button = -1;
@ -1346,7 +1698,7 @@ void PollInputEvents(void)
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
} }
} break; } break;
case SDL_JOYAXISMOTION: case SDL_CONTROLLERAXISMOTION:
{ {
int axis = -1; int axis = -1;
@ -1364,13 +1716,13 @@ void PollInputEvents(void)
if (axis >= 0) if (axis >= 0)
{ {
// SDL axis value range is -32768 to 32767, we normalize it to RayLib's -1.0 to 1.0f range // SDL axis value range is -32768 to 32767, we normalize it to RayLib's -1.0 to 1.0f range
float value = event.jaxis.value / (float) 32767; float value = event.jaxis.value/(float)32767;
CORE.Input.Gamepad.axisState[event.jaxis.which][axis] = value; CORE.Input.Gamepad.axisState[event.jaxis.which][axis] = value;
// Register button state for triggers in addition to their axes // Register button state for triggers in addition to their axes
if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER)) if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))
{ {
int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER) ? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2; int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
int pressed = (value > 0.1f); int pressed = (value > 0.1f);
CORE.Input.Gamepad.currentButtonState[event.jaxis.which][button] = pressed; CORE.Input.Gamepad.currentButtonState[event.jaxis.which][button] = pressed;
if (pressed) CORE.Input.Gamepad.lastButtonPressed = button; if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
@ -1499,11 +1851,6 @@ int InitPlatform(void)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
} }
if (CORE.Window.flags & FLAG_VSYNC_HINT)
{
SDL_GL_SetSwapInterval(1);
}
if (CORE.Window.flags & FLAG_MSAA_4X_HINT) if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
{ {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
@ -1511,7 +1858,11 @@ int InitPlatform(void)
} }
// Init window // Init window
#ifdef PLATFORM_DESKTOP_SDL3
platform.window = SDL_CreateWindow(CORE.Window.title, CORE.Window.screen.width, CORE.Window.screen.height, flags);
#else
platform.window = SDL_CreateWindow(CORE.Window.title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, CORE.Window.screen.width, CORE.Window.screen.height, flags); platform.window = SDL_CreateWindow(CORE.Window.title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, CORE.Window.screen.width, CORE.Window.screen.height, flags);
#endif
// Init OpenGL context // Init OpenGL context
platform.glContext = SDL_GL_CreateContext(platform.window); platform.glContext = SDL_GL_CreateContext(platform.window);
@ -1537,6 +1888,9 @@ int InitPlatform(void)
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
if (CORE.Window.flags & FLAG_VSYNC_HINT) SDL_GL_SetSwapInterval(1);
else SDL_GL_SetSwapInterval(0);
} }
else else
{ {
@ -1554,14 +1908,15 @@ int InitPlatform(void)
// Initialize gamepads // Initialize gamepads
for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++) for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++)
{ {
platform.gamepad[i] = SDL_JoystickOpen(i); platform.gamepad[i] = SDL_GameControllerOpen(i);
if (platform.gamepad[i]) if (platform.gamepad[i])
{ {
CORE.Input.Gamepad.ready[i] = true; CORE.Input.Gamepad.ready[i] = true;
CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(platform.gamepad[i]); CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[i]));
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
strncpy(CORE.Input.Gamepad.name[i], SDL_JoystickName(platform.gamepad[i]), 63); strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), 63);
CORE.Input.Gamepad.name[i][63] = '\0'; CORE.Input.Gamepad.name[i][63] = '\0';
} }
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError()); else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
@ -1581,16 +1936,22 @@ int InitPlatform(void)
CORE.Time.previous = GetTime(); // Get time as double CORE.Time.previous = GetTime(); // Get time as double
#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP) #if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)
SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "1"); // SDL equivalent of timeBeginPeriod() and timeEndPeriod() SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "1"); // SDL equivalent of timeBeginPeriod() and timeEndPeriod()
#endif #endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Initialize storage system // Initialize storage system
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
CORE.Storage.basePath = GetWorkingDirectory(); // Define base path for storage // Define base path for storage
CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory();
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
#ifdef PLATFORM_DESKTOP_SDL3
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL3): Initialized successfully");
#else
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully"); TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully");
#endif
return 0; return 0;
} }
@ -1609,8 +1970,9 @@ static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode)
{ {
if (sdlScancode >= 0 && sdlScancode < SCANCODE_MAPPED_NUM) if (sdlScancode >= 0 && sdlScancode < SCANCODE_MAPPED_NUM)
{ {
return ScancodeToKey[sdlScancode]; return mapScancodeToKey[sdlScancode];
} }
return KEY_NULL; // No equivalent key in Raylib return KEY_NULL; // No equivalent key in Raylib
} }
// EOF // EOF

View file

@ -207,7 +207,7 @@ static const short linuxToRaylibMap[KEYMAP_SIZE] = {
[BTN_TL] = GAMEPAD_BUTTON_LEFT_TRIGGER_1, [BTN_TL] = GAMEPAD_BUTTON_LEFT_TRIGGER_1,
[BTN_TL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2, [BTN_TL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2,
[BTN_TR] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1, [BTN_TR] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1,
[BTN_TR2] GAMEPAD_BUTTON_RIGHT_TRIGGER_2, [BTN_TR2] = GAMEPAD_BUTTON_RIGHT_TRIGGER_2,
[BTN_SELECT] = GAMEPAD_BUTTON_MIDDLE_LEFT, [BTN_SELECT] = GAMEPAD_BUTTON_MIDDLE_LEFT,
[BTN_MODE] = GAMEPAD_BUTTON_MIDDLE, [BTN_MODE] = GAMEPAD_BUTTON_MIDDLE,
[BTN_START] = GAMEPAD_BUTTON_MIDDLE_RIGHT, [BTN_START] = GAMEPAD_BUTTON_MIDDLE_RIGHT,
@ -399,7 +399,7 @@ int GetMonitorWidth(int monitor)
{ {
width = platform.connector->modes[platform.modeIndex].hdisplay; width = platform.connector->modes[platform.modeIndex].hdisplay;
} }
return width; return width;
} }
@ -416,7 +416,7 @@ int GetMonitorHeight(int monitor)
{ {
height = platform.connector->modes[platform.modeIndex].vdisplay; height = platform.connector->modes[platform.modeIndex].vdisplay;
} }
return height; return height;
} }
@ -480,7 +480,7 @@ const char *GetMonitorName(int monitor)
{ {
name = platform.connector->modes[platform.modeIndex].name; name = platform.connector->modes[platform.modeIndex].name;
} }
return name; return name;
} }
@ -611,7 +611,7 @@ int SetGamepadMappings(const char *mappings)
} }
// Set gamepad vibration // Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{ {
TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform"); TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform");
} }
@ -629,6 +629,13 @@ void SetMouseCursor(int cursor)
TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform"); TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform");
} }
// Get physical key name.
const char *GetKeyName(int key)
{
TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");
return "";
}
// Register all input events // Register all input events
void PollInputEvents(void) void PollInputEvents(void)
{ {
@ -758,7 +765,9 @@ int InitPlatform(void)
drmModeConnector *con = drmModeGetConnector(platform.fd, res->connectors[i]); drmModeConnector *con = drmModeGetConnector(platform.fd, res->connectors[i]);
TRACELOG(LOG_TRACE, "DISPLAY: Connector modes detected: %i", con->count_modes); TRACELOG(LOG_TRACE, "DISPLAY: Connector modes detected: %i", con->count_modes);
if ((con->connection == DRM_MODE_CONNECTED) && (con->encoder_id)) // In certain cases the status of the conneciton is reported as UKNOWN, but it is still connected.
// This might be a hardware or software limitation like on Raspberry Pi Zero with composite output.
if (((con->connection == DRM_MODE_CONNECTED) || (con->connection == DRM_MODE_UNKNOWNCONNECTION)) && (con->encoder_id))
{ {
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode connected"); TRACELOG(LOG_TRACE, "DISPLAY: DRM mode connected");
platform.connector = con; platform.connector = con;
@ -1029,7 +1038,7 @@ int InitPlatform(void)
// If graphic device is no properly initialized, we end program // If graphic device is no properly initialized, we end program
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; } if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor()) / 2 - CORE.Window.screen.width / 2, GetMonitorHeight(GetCurrentMonitor()) / 2 - CORE.Window.screen.height / 2); else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
// Set some default window flags // Set some default window flags
CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN; // false CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN; // false
@ -1137,7 +1146,8 @@ void ClosePlatform(void)
// Close the evdev devices // Close the evdev devices
if (platform.mouseFd != -1) { if (platform.mouseFd != -1)
{
close(platform.mouseFd); close(platform.mouseFd);
platform.mouseFd = -1; platform.mouseFd = -1;
} }
@ -1471,7 +1481,6 @@ static void ConfigureEvdevDevice(char *device)
TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true; TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;
} }
if (TEST_BIT(evBits, EV_KEY)) if (TEST_BIT(evBits, EV_KEY))
{ {
// The first 32 keys as defined in input-event-codes.h are pretty much // The first 32 keys as defined in input-event-codes.h are pretty much
@ -1614,7 +1623,7 @@ static void PollKeyboardEvents(void)
} }
} }
TRACELOG(LOG_DEBUG, "INPUT: KEY_%s Keycode(linux): %4i KeyCode(raylib): %4i", (event.value == 0) ? "UP " : "DOWN", event.code, keycode); TRACELOG(LOG_DEBUG, "INPUT: KEY_%s Keycode(linux): %4i KeyCode(raylib): %4i", (event.value == 0)? "UP " : "DOWN", event.code, keycode);
} }
} }
} }
@ -1641,7 +1650,7 @@ static void PollGamepadEvents(void)
{ {
short keycodeRaylib = linuxToRaylibMap[event.code]; short keycodeRaylib = linuxToRaylibMap[event.code];
TRACELOG(LOG_DEBUG, "INPUT: Gamepad %2i: KEY_%s Keycode(linux): %4i Keycode(raylib): %4i", i, (event.value == 0) ? "UP " : "DOWN", event.code, keycodeRaylib); TRACELOG(LOG_DEBUG, "INPUT: Gamepad %2i: KEY_%s Keycode(linux): %4i Keycode(raylib): %4i", i, (event.value == 0)? "UP" : "DOWN", event.code, keycodeRaylib);
if ((keycodeRaylib != 0) && (keycodeRaylib < MAX_GAMEPAD_BUTTONS)) if ((keycodeRaylib != 0) && (keycodeRaylib < MAX_GAMEPAD_BUTTONS))
{ {
@ -1666,7 +1675,7 @@ static void PollGamepadEvents(void)
int range = platform.gamepadAbsAxisRange[i][event.code][1]; int range = platform.gamepadAbsAxisRange[i][event.code][1];
// NOTE: Scaling of event.value to get values between -1..1 // NOTE: Scaling of event.value to get values between -1..1
CORE.Input.Gamepad.axisState[i][axisRaylib] = (2 * (float)(event.value - min) / range) - 1; CORE.Input.Gamepad.axisState[i][axisRaylib] = (2*(float)(event.value - min)/range) - 1;
} }
} }
} }
@ -1925,9 +1934,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
const int nearestHeightDiff = abs(platform.connector->modes[nearestIndex].vdisplay - height); const int nearestHeightDiff = abs(platform.connector->modes[nearestIndex].vdisplay - height);
const int nearestFpsDiff = abs(platform.connector->modes[nearestIndex].vrefresh - fps); const int nearestFpsDiff = abs(platform.connector->modes[nearestIndex].vrefresh - fps);
if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) { if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) nearestIndex = i;
nearestIndex = i;
}
} }
return nearestIndex; return nearestIndex;

View file

@ -14,7 +14,7 @@ import (
const ( const (
libname = "raylib.dll" libname = "raylib.dll"
requiredVersion = "5.0" requiredVersion = "5.5"
) )
var wvsprintfA uintptr var wvsprintfA uintptr

View file

@ -895,8 +895,8 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
return wave; return wave;
} }
// Checks if wave data is ready // Checks if wave data is valid (data loaded and parameters)
bool IsWaveReady(Wave wave) bool IsWaveValid(Wave wave)
{ {
bool result = false; bool result = false;
@ -996,8 +996,8 @@ Sound LoadSoundAlias(Sound source)
} }
// Checks if a sound is ready // Checks if a sound is valid (data loaded and buffers initialized)
bool IsSoundReady(Sound sound) bool IsSoundValid(Sound sound)
{ {
bool result = false; bool result = false;
@ -1277,20 +1277,21 @@ Wave WaveCopy(Wave wave)
return newWave; return newWave;
} }
// Crop a wave to defined samples range // Crop a wave to defined frames range
// NOTE: Security check in case of out-of-range // NOTE: Security check in case of out-of-range
void WaveCrop(Wave *wave, int initSample, int finalSample) void WaveCrop(Wave *wave, int initFrame, int finalFrame)
{ {
if ((initSample >= 0) && (initSample < finalSample) && ((unsigned int)finalSample < (wave->frameCount*wave->channels))) if ((initFrame >= 0) && (initFrame < finalFrame) && ((unsigned int)finalFrame <= wave->frameCount))
{ {
int sampleCount = finalSample - initSample; int frameCount = finalFrame - initFrame;
void *data = RL_MALLOC(sampleCount*wave->sampleSize/8); void *data = RL_MALLOC(frameCount*wave->channels*wave->sampleSize/8);
memcpy(data, (unsigned char *)wave->data + (initSample*wave->channels*wave->sampleSize/8), sampleCount*wave->sampleSize/8); memcpy(data, (unsigned char *)wave->data + (initFrame*wave->channels*wave->sampleSize/8), frameCount*wave->channels*wave->sampleSize/8);
RL_FREE(wave->data); RL_FREE(wave->data);
wave->data = data; wave->data = data;
wave->frameCount = (unsigned int)frameCount;
} }
else TRACELOG(LOG_WARNING, "WAVE: Crop range out of bounds"); else TRACELOG(LOG_WARNING, "WAVE: Crop range out of bounds");
} }
@ -1306,8 +1307,8 @@ float *LoadWaveSamples(Wave wave)
for (unsigned int i = 0; i < wave.frameCount*wave.channels; i++) for (unsigned int i = 0; i < wave.frameCount*wave.channels; i++)
{ {
if (wave.sampleSize == 8) samples[i] = (float)(((unsigned char *)wave.data)[i] - 127)/256.0f; if (wave.sampleSize == 8) samples[i] = (float)(((unsigned char *)wave.data)[i] - 128)/128.0f;
else if (wave.sampleSize == 16) samples[i] = (float)(((short *)wave.data)[i])/32767.0f; else if (wave.sampleSize == 16) samples[i] = (float)(((short *)wave.data)[i])/32768.0f;
else if (wave.sampleSize == 32) samples[i] = ((float *)wave.data)[i]; else if (wave.sampleSize == 32) samples[i] = ((float *)wave.data)[i];
} }
@ -1351,7 +1352,6 @@ Music LoadMusicStream(const char *fileName)
} }
else else
{ {
drwav_uninit(ctxWav);
RL_FREE(ctxWav); RL_FREE(ctxWav);
} }
} }
@ -1431,7 +1431,9 @@ Music LoadMusicStream(const char *fileName)
{ {
music.ctxType = MUSIC_AUDIO_FLAC; music.ctxType = MUSIC_AUDIO_FLAC;
music.ctxData = ctxFlac; music.ctxData = ctxFlac;
music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels); int sampleSize = ctxFlac->bitsPerSample;
if (ctxFlac->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
music.stream = LoadAudioStream(ctxFlac->sampleRate, sampleSize, ctxFlac->channels);
music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount; music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
music.looping = true; // Looping enabled by default music.looping = true; // Looping enabled by default
musicLoaded = true; musicLoaded = true;
@ -1465,7 +1467,7 @@ Music LoadMusicStream(const char *fileName)
jar_xm_reset(ctxXm); // Make sure we start at the beginning of the song jar_xm_reset(ctxXm); // Make sure we start at the beginning of the song
musicLoaded = true; musicLoaded = true;
} }
else else
{ {
jar_xm_free_context(ctxXm); jar_xm_free_context(ctxXm);
} }
@ -1551,7 +1553,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0)) else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0))
{ {
// Open ogg audio stream // Open ogg audio stream
stb_vorbis* ctxOgg = stb_vorbis_open_memory((const unsigned char*)data, dataSize, NULL, NULL); stb_vorbis* ctxOgg = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL);
if (ctxOgg != NULL) if (ctxOgg != NULL)
{ {
@ -1567,7 +1569,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
music.looping = true; // Looping enabled by default music.looping = true; // Looping enabled by default
musicLoaded = true; musicLoaded = true;
} }
else else
{ {
stb_vorbis_close(ctxOgg); stb_vorbis_close(ctxOgg);
} }
@ -1627,7 +1629,9 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
{ {
music.ctxType = MUSIC_AUDIO_FLAC; music.ctxType = MUSIC_AUDIO_FLAC;
music.ctxData = ctxFlac; music.ctxData = ctxFlac;
music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels); int sampleSize = ctxFlac->bitsPerSample;
if (ctxFlac->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
music.stream = LoadAudioStream(ctxFlac->sampleRate, sampleSize, ctxFlac->channels);
music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount; music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
music.looping = true; // Looping enabled by default music.looping = true; // Looping enabled by default
musicLoaded = true; musicLoaded = true;
@ -1725,8 +1729,8 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
return music; return music;
} }
// Checks if a music stream is ready // Checks if a music stream is valid (context and buffers initialized)
bool IsMusicReady(Music music) bool IsMusicValid(Music music)
{ {
return ((music.ctxData != NULL) && // Validate context loaded return ((music.ctxData != NULL) && // Validate context loaded
(music.frameCount > 0) && // Validate audio frame count (music.frameCount > 0) && // Validate audio frame count
@ -2118,8 +2122,8 @@ AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
return stream; return stream;
} }
// Checks if an audio stream is ready // Checks if an audio stream is valid (buffers initialized)
bool IsAudioStreamReady(AudioStream stream) bool IsAudioStreamValid(AudioStream stream)
{ {
return ((stream.buffer != NULL) && // Validate stream buffer return ((stream.buffer != NULL) && // Validate stream buffer
(stream.sampleRate > 0) && // Validate sample rate is supported (stream.sampleRate > 0) && // Validate sample rate is supported

View file

@ -176,10 +176,10 @@ func LoadWaveFromMemory(fileType string, fileData []byte, dataSize int32) Wave {
return v return v
} }
// IsWaveReady - Checks if wave data is ready // IsWaveValid - Checks if wave data is valid (data loaded and parameters)
func IsWaveReady(wave Wave) bool { func IsWaveValid(wave Wave) bool {
cwave := wave.cptr() cwave := wave.cptr()
ret := C.IsWaveReady(*cwave) ret := C.IsWaveValid(*cwave)
v := bool(ret) v := bool(ret)
return v return v
} }
@ -209,10 +209,10 @@ func LoadSoundAlias(source Sound) Sound {
return v return v
} }
// IsSoundReady - Checks if a sound is ready // IsSoundValid - Checks if a sound is valid (data loaded and buffers initialized)
func IsSoundReady(sound Sound) bool { func IsSoundValid(sound Sound) bool {
csound := sound.cptr() csound := sound.cptr()
ret := C.IsSoundReady(*csound) ret := C.IsSoundValid(*csound)
v := bool(ret) v := bool(ret)
return v return v
} }
@ -315,12 +315,12 @@ func WaveCopy(wave Wave) Wave {
return v return v
} }
// WaveCrop - Crop a wave to defined samples range // WaveCrop - Crop a wave to defined frames range
func WaveCrop(wave Wave, initSample int32, finalSample int32) { func WaveCrop(wave Wave, initFrame int32, finalFrame int32) {
cwave := wave.cptr() cwave := wave.cptr()
cinitSample := (C.int)(initSample) cinitFrame := (C.int)(initFrame)
cfinalSample := (C.int)(finalSample) cfinalFrame := (C.int)(finalFrame)
C.WaveCrop(cwave, cinitSample, cfinalSample) C.WaveCrop(cwave, cinitFrame, cfinalFrame)
} }
// LoadWaveSamples - Get samples data from wave as a floats array // LoadWaveSamples - Get samples data from wave as a floats array
@ -356,10 +356,10 @@ func LoadMusicStreamFromMemory(fileType string, fileData []byte, dataSize int32)
return v return v
} }
// IsMusicReady - Checks if a music stream is ready // IsMusicValid - Checks if a music stream is valid (context and buffers initialized)
func IsMusicReady(music Music) bool { func IsMusicValid(music Music) bool {
cmusic := *(*C.Music)(unsafe.Pointer(&music)) cmusic := *(*C.Music)(unsafe.Pointer(&music))
ret := C.IsMusicReady(cmusic) ret := C.IsMusicValid(cmusic)
v := bool(ret) v := bool(ret)
return v return v
} }
@ -462,10 +462,10 @@ func LoadAudioStream(sampleRate uint32, sampleSize uint32, channels uint32) Audi
return v return v
} }
// IsAudioStreamReady - Checks if an audio stream is ready // IsAudioStreamValid - Checks if an audio stream is valid (buffers initialized)
func IsAudioStreamReady(stream AudioStream) bool { func IsAudioStreamValid(stream AudioStream) bool {
cstream := stream.cptr() cstream := stream.cptr()
ret := C.IsAudioStreamReady(*cstream) ret := C.IsAudioStreamValid(*cstream)
v := bool(ret) v := bool(ret)
return v return v
} }

View file

@ -364,7 +364,7 @@ const (
// Android keys // Android keys
KeyBack = 4 KeyBack = 4
KeyMenu = 82 KeyMenu = 5
KeyVolumeUp = 24 KeyVolumeUp = 24
KeyVolumeDown = 25 KeyVolumeDown = 25
@ -411,12 +411,12 @@ const (
GamepadButtonLeftFaceDown // Gamepad left DPAD down button GamepadButtonLeftFaceDown // Gamepad left DPAD down button
GamepadButtonLeftFaceLeft // Gamepad left DPAD left button GamepadButtonLeftFaceLeft // Gamepad left DPAD left button
GamepadButtonRightFaceUp // Gamepad right button up (i.e. PS3: Triangle, Xbox: Y) GamepadButtonRightFaceUp // Gamepad right button up (i.e. PS3: Triangle, Xbox: Y)
GamepadButtonRightFaceRight // Gamepad right button right (i.e. PS3: Square, Xbox: X) GamepadButtonRightFaceRight // Gamepad right button right (i.e. PS3: Circle, Xbox: B)
GamepadButtonRightFaceDown // Gamepad right button down (i.e. PS3: Cross, Xbox: A) GamepadButtonRightFaceDown // Gamepad right button down (i.e. PS3: Cross, Xbox: A)
GamepadButtonRightFaceLeft // Gamepad right button left (i.e. PS3: Circle, Xbox: B) GamepadButtonRightFaceLeft // Gamepad right button left (i.e. PS3: Square, Xbox: X)
GamepadButtonLeftTrigger1 // Gamepad top/back trigger left (first), it could be a trailing button GamepadButtonLeftTrigger1 // Gamepad top/back trigger left (first), it could be a trailing button
GamepadButtonLeftTrigger2 // Gamepad top/back trigger left (second), it could be a trailing button GamepadButtonLeftTrigger2 // Gamepad top/back trigger left (second), it could be a trailing button
GamepadButtonRightTrigger1 // Gamepad top/back trigger right (one), it could be a trailing button GamepadButtonRightTrigger1 // Gamepad top/back trigger right (first), it could be a trailing button
GamepadButtonRightTrigger2 // Gamepad top/back trigger right (second), it could be a trailing button GamepadButtonRightTrigger2 // Gamepad top/back trigger right (second), it could be a trailing button
GamepadButtonMiddleLeft // Gamepad center buttons, left one (i.e. PS3: Select) GamepadButtonMiddleLeft // Gamepad center buttons, left one (i.e. PS3: Select)
GamepadButtonMiddle // Gamepad center buttons, middle one (i.e. PS3: PS, Xbox: XBOX) GamepadButtonMiddle // Gamepad center buttons, middle one (i.e. PS3: PS, Xbox: XBOX)
@ -729,14 +729,31 @@ type ShaderUniformDataType int32
// ShaderUniformDataType enumeration // ShaderUniformDataType enumeration
const ( const (
// Shader uniform type: float
ShaderUniformFloat ShaderUniformDataType = iota ShaderUniformFloat ShaderUniformDataType = iota
// Shader uniform type: vec2 (2 float)
ShaderUniformVec2 ShaderUniformVec2
// Shader uniform type: vec3 (3 float)
ShaderUniformVec3 ShaderUniformVec3
// Shader uniform type: vec4 (4 float)
ShaderUniformVec4 ShaderUniformVec4
// Shader uniform type: int
ShaderUniformInt ShaderUniformInt
// Shader uniform type: ivec2 (2 int)
ShaderUniformIvec2 ShaderUniformIvec2
// Shader uniform type: ivec2 (3 int)
ShaderUniformIvec3 ShaderUniformIvec3
// Shader uniform type: ivec2 (4 int)
ShaderUniformIvec4 ShaderUniformIvec4
// Shader uniform type: unsigned int
ShaderUniformUint
// Shader uniform type: uivec2 (2 unsigned int)
ShaderUniformUivec2
// Shader uniform type: uivec3 (3 unsigned int)
ShaderUniformUivec3
// Shader uniform type: uivec4 (4 unsigned int)
ShaderUniformUivec4
// Shader uniform type: sampler2d
ShaderUniformSampler2d ShaderUniformSampler2d
) )
@ -795,6 +812,10 @@ type Mesh struct {
BoneIds *int32 BoneIds *int32
// BoneWeights // BoneWeights
BoneWeights *float32 BoneWeights *float32
// Bones animated transformation matrices
BoneMatrices *Matrix
// Number of bones
BoneCount int32
// OpenGL Vertex Array Object id // OpenGL Vertex Array Object id
VaoID uint32 VaoID uint32
// OpenGL Vertex Buffer Objects id (7 types of vertex data) // OpenGL Vertex Buffer Objects id (7 types of vertex data)
@ -1093,7 +1114,6 @@ const (
CubemapLayoutLineHorizontal // Layout is defined by a horizontal line with faces CubemapLayoutLineHorizontal // Layout is defined by a horizontal line with faces
CubemapLayoutCrossThreeByFour // Layout is defined by a 3x4 cross with cubemap faces CubemapLayoutCrossThreeByFour // Layout is defined by a 3x4 cross with cubemap faces
CubemapLayoutCrossFourByThree // Layout is defined by a 4x3 cross with cubemap faces CubemapLayoutCrossFourByThree // Layout is defined by a 4x3 cross with cubemap faces
CubemapLayoutPanorama // Layout is defined by a panorama image (equirrectangular map)
) )
// Image type, bpp always RGBA (32bit) // Image type, bpp always RGBA (32bit)
@ -1217,7 +1237,6 @@ type VrDeviceInfo struct {
VResolution int32 // Vertical resolution in pixels VResolution int32 // Vertical resolution in pixels
HScreenSize float32 // Horizontal size in meters HScreenSize float32 // Horizontal size in meters
VScreenSize float32 // Vertical size in meters VScreenSize float32 // Vertical size in meters
VScreenCenter float32 // Screen center in meters
EyeToScreenDistance float32 // Distance between eye and display in meters EyeToScreenDistance float32 // Distance between eye and display in meters
LensSeparationDistance float32 // Lens separation distance in meters LensSeparationDistance float32 // Lens separation distance in meters
InterpupillaryDistance float32 // IPD (distance between pupils) in meters InterpupillaryDistance float32 // IPD (distance between pupils) in meters

View file

@ -1,22 +1,22 @@
/********************************************************************************************** /**********************************************************************************************
* *
* raylib v5.1-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) * raylib v5.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
* *
* FEATURES: * FEATURES:
* - NO external dependencies, all required libraries included with raylib * - NO external dependencies, all required libraries included with raylib
* - Multiplatform: Windows, Linux, FreeBSD, OpenBSD, NetBSD, DragonFly, * - Multiplatform: Windows, Linux, FreeBSD, OpenBSD, NetBSD, DragonFly,
* MacOS, Haiku, Android, Raspberry Pi, DRM native, HTML5. * MacOS, Haiku, Android, Raspberry Pi, DRM native, HTML5.
* - Written in plain C code (C99) in PascalCase/camelCase notation * - Written in plain C code (C99) in PascalCase/camelCase notation
* - Hardware accelerated with OpenGL (1.1, 2.1, 3.3, 4.3 or ES2 - choose at compile) * - Hardware accelerated with OpenGL (1.1, 2.1, 3.3, 4.3, ES2, ES3 - choose at compile)
* - Unique OpenGL abstraction layer (usable as standalone module): [rlgl] * - Unique OpenGL abstraction layer (usable as standalone module): [rlgl]
* - Multiple Fonts formats supported (TTF, XNA fonts, AngelCode fonts) * - Multiple Fonts formats supported (TTF, OTF, FNT, BDF, Sprite fonts)
* - Outstanding texture formats support, including compressed formats (DXT, ETC, ASTC) * - Outstanding texture formats support, including compressed formats (DXT, ETC, ASTC)
* - Full 3d support for 3d Shapes, Models, Billboards, Heightmaps and more! * - Full 3d support for 3d Shapes, Models, Billboards, Heightmaps and more!
* - Flexible Materials system, supporting classic maps and PBR maps * - Flexible Materials system, supporting classic maps and PBR maps
* - Animated 3D models supported (skeletal bones animation) (IQM) * - Animated 3D models supported (skeletal bones animation) (IQM, M3D, GLTF)
* - Shaders support, including Model shaders and Postprocessing shaders * - Shaders support, including Model shaders and Postprocessing shaders
* - Powerful math module for Vector, Matrix and Quaternion operations: [raymath] * - Powerful math module for Vector, Matrix and Quaternion operations: [raymath]
* - Audio loading and playing with streaming support (WAV, OGG, MP3, FLAC, XM, MOD) * - Audio loading and playing with streaming support (WAV, OGG, MP3, FLAC, QOA, XM, MOD)
* - VR stereo rendering with configurable HMD device parameters * - VR stereo rendering with configurable HMD device parameters
* - Bindings to multiple programming languages available! * - Bindings to multiple programming languages available!
* *
@ -27,29 +27,35 @@
* - One default RenderBatch is loaded on rlglInit()->rlLoadRenderBatch() [rlgl] (OpenGL 3.3 or ES2) * - One default RenderBatch is loaded on rlglInit()->rlLoadRenderBatch() [rlgl] (OpenGL 3.3 or ES2)
* *
* DEPENDENCIES (included): * DEPENDENCIES (included):
* [rcore] rglfw (Camilla Löwy - github.com/glfw/glfw) for window/context management and input (PLATFORM_DESKTOP) * [rcore][GLFW] rglfw (Camilla Löwy - github.com/glfw/glfw) for window/context management and input
* [rlgl] glad (David Herberth - github.com/Dav1dde/glad) for OpenGL 3.3 extensions loading (PLATFORM_DESKTOP) * [rcore][RGFW] rgfw (ColleagueRiley - github.com/ColleagueRiley/RGFW) for window/context management and input
* [rlgl] glad/glad_gles2 (David Herberth - github.com/Dav1dde/glad) for OpenGL 3.3 extensions loading
* [raudio] miniaudio (David Reid - github.com/mackron/miniaudio) for audio device/context management * [raudio] miniaudio (David Reid - github.com/mackron/miniaudio) for audio device/context management
* *
* OPTIONAL DEPENDENCIES (included): * OPTIONAL DEPENDENCIES (included):
* [rcore] msf_gif (Miles Fogle) for GIF recording * [rcore] msf_gif (Miles Fogle) for GIF recording
* [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm * [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm
* [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm * [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm
* [rcore] rprand (Ramon Snatamaria) for pseudo-random numbers generation
* [rtextures] qoi (Dominic Szablewski - https://phoboslab.org) for QOI image manage
* [rtextures] stb_image (Sean Barret) for images loading (BMP, TGA, PNG, JPEG, HDR...) * [rtextures] stb_image (Sean Barret) for images loading (BMP, TGA, PNG, JPEG, HDR...)
* [rtextures] stb_image_write (Sean Barret) for image writing (BMP, TGA, PNG, JPG) * [rtextures] stb_image_write (Sean Barret) for image writing (BMP, TGA, PNG, JPG)
* [rtextures] stb_image_resize (Sean Barret) for image resizing algorithms * [rtextures] stb_image_resize2 (Sean Barret) for image resizing algorithms
* [rtextures] stb_perlin (Sean Barret) for Perlin Noise image generation
* [rtext] stb_truetype (Sean Barret) for ttf fonts loading * [rtext] stb_truetype (Sean Barret) for ttf fonts loading
* [rtext] stb_rect_pack (Sean Barret) for rectangles packing * [rtext] stb_rect_pack (Sean Barret) for rectangles packing
* [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation * [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation
* [rmodels] tinyobj_loader_c (Syoyo Fujita) for models loading (OBJ, MTL) * [rmodels] tinyobj_loader_c (Syoyo Fujita) for models loading (OBJ, MTL)
* [rmodels] cgltf (Johannes Kuhlmann) for models loading (glTF) * [rmodels] cgltf (Johannes Kuhlmann) for models loading (glTF)
* [rmodels] Model3D (bzt) for models loading (M3D, https://bztsrc.gitlab.io/model3d) * [rmodels] m3d (bzt) for models loading (M3D, https://bztsrc.gitlab.io/model3d)
* [rmodels] vox_loader (Johann Nadalutti) for models loading (VOX)
* [raudio] dr_wav (David Reid) for WAV audio file loading * [raudio] dr_wav (David Reid) for WAV audio file loading
* [raudio] dr_flac (David Reid) for FLAC audio file loading * [raudio] dr_flac (David Reid) for FLAC audio file loading
* [raudio] dr_mp3 (David Reid) for MP3 audio file loading * [raudio] dr_mp3 (David Reid) for MP3 audio file loading
* [raudio] stb_vorbis (Sean Barret) for OGG audio loading * [raudio] stb_vorbis (Sean Barret) for OGG audio loading
* [raudio] jar_xm (Joshua Reisenauer) for XM audio module loading * [raudio] jar_xm (Joshua Reisenauer) for XM audio module loading
* [raudio] jar_mod (Joshua Reisenauer) for MOD audio module loading * [raudio] jar_mod (Joshua Reisenauer) for MOD audio module loading
* [raudio] qoa (Dominic Szablewski - https://phoboslab.org) for QOA audio manage
* *
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
@ -82,9 +88,9 @@
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback #include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
#define RAYLIB_VERSION_MAJOR 5 #define RAYLIB_VERSION_MAJOR 5
#define RAYLIB_VERSION_MINOR 1 #define RAYLIB_VERSION_MINOR 5
#define RAYLIB_VERSION_PATCH 0 #define RAYLIB_VERSION_PATCH 0
#define RAYLIB_VERSION "5.1-dev" #define RAYLIB_VERSION "5.5"
// Function specifiers in case library is build/used as a shared library // Function specifiers in case library is build/used as a shared library
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
@ -352,8 +358,10 @@ typedef struct Mesh {
// Animation vertex data // Animation vertex data
float *animVertices; // Animated vertex positions (after bones transformations) float *animVertices; // Animated vertex positions (after bones transformations)
float *animNormals; // Animated normals (after bones transformations) float *animNormals; // Animated normals (after bones transformations)
unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)
float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)
Matrix *boneMatrices; // Bones animated transformation matrices
int boneCount; // Number of bones
// OpenGL identifiers // OpenGL identifiers
unsigned int vaoId; // OpenGL Vertex Array Object id unsigned int vaoId; // OpenGL Vertex Array Object id
@ -421,7 +429,7 @@ typedef struct ModelAnimation {
// Ray, ray for raycasting // Ray, ray for raycasting
typedef struct Ray { typedef struct Ray {
Vector3 position; // Ray position (origin) Vector3 position; // Ray position (origin)
Vector3 direction; // Ray direction Vector3 direction; // Ray direction (normalized)
} Ray; } Ray;
// RayCollision, ray hit information // RayCollision, ray hit information
@ -790,7 +798,10 @@ typedef enum {
SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap
SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance
SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter
SHADER_LOC_MAP_BRDF // Shader location: sampler2d texture: brdf SHADER_LOC_MAP_BRDF, // Shader location: sampler2d texture: brdf
SHADER_LOC_VERTEX_BONEIDS, // Shader location: vertex attribute: boneIds
SHADER_LOC_VERTEX_BONEWEIGHTS, // Shader location: vertex attribute: boneWeights
SHADER_LOC_BONE_MATRICES // Shader location: array of matrices uniform: boneMatrices
} ShaderLocationIndex; } ShaderLocationIndex;
#define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO #define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO
@ -872,8 +883,7 @@ typedef enum {
CUBEMAP_LAYOUT_LINE_VERTICAL, // Layout is defined by a vertical line with faces CUBEMAP_LAYOUT_LINE_VERTICAL, // Layout is defined by a vertical line with faces
CUBEMAP_LAYOUT_LINE_HORIZONTAL, // Layout is defined by a horizontal line with faces CUBEMAP_LAYOUT_LINE_HORIZONTAL, // Layout is defined by a horizontal line with faces
CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR, // Layout is defined by a 3x4 cross with cubemap faces CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR, // Layout is defined by a 3x4 cross with cubemap faces
CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE, // Layout is defined by a 4x3 cross with cubemap faces CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE // Layout is defined by a 4x3 cross with cubemap faces
CUBEMAP_LAYOUT_PANORAMA // Layout is defined by a panorama image (equirrectangular map)
} CubemapLayout; } CubemapLayout;
// Font type, defines generation method // Font type, defines generation method
@ -934,7 +944,7 @@ typedef enum {
} NPatchLayout; } NPatchLayout;
// Callbacks to hook some internal functions // Callbacks to hook some internal functions
// WARNING: These callbacks are intended for advance users // WARNING: These callbacks are intended for advanced users
typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data
@ -960,36 +970,36 @@ RLAPI void CloseWindow(void); // Close windo
RLAPI bool WindowShouldClose(void); // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked) RLAPI bool WindowShouldClose(void); // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)
RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully
RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen
RLAPI bool IsWindowHidden(void); // Check if window is currently hidden (only PLATFORM_DESKTOP) RLAPI bool IsWindowHidden(void); // Check if window is currently hidden
RLAPI bool IsWindowMinimized(void); // Check if window is currently minimized (only PLATFORM_DESKTOP) RLAPI bool IsWindowMinimized(void); // Check if window is currently minimized
RLAPI bool IsWindowMaximized(void); // Check if window is currently maximized (only PLATFORM_DESKTOP) RLAPI bool IsWindowMaximized(void); // Check if window is currently maximized
RLAPI bool IsWindowFocused(void); // Check if window is currently focused (only PLATFORM_DESKTOP) RLAPI bool IsWindowFocused(void); // Check if window is currently focused
RLAPI bool IsWindowResized(void); // Check if window has been resized last frame RLAPI bool IsWindowResized(void); // Check if window has been resized last frame
RLAPI bool IsWindowState(unsigned int flag); // Check if one specific window flag is enabled RLAPI bool IsWindowState(unsigned int flag); // Check if one specific window flag is enabled
RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP) RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags
RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags
RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP) RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed, resizes monitor to match window resolution
RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed (only PLATFORM_DESKTOP) RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed, resizes window to match monitor resolution
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP) RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable
RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP) RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable
RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP) RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized
RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP) RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit)
RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP) RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit)
RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP and PLATFORM_WEB) RLAPI void SetWindowTitle(const char *title); // Set title for window
RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP) RLAPI void SetWindowPosition(int x, int y); // Set window position on screen
RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window
RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE) RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
RLAPI void SetWindowMaxSize(int width, int height); // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE) RLAPI void SetWindowMaxSize(int width, int height); // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE)
RLAPI void SetWindowSize(int width, int height); // Set window dimensions RLAPI void SetWindowSize(int width, int height); // Set window dimensions
RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP) RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f]
RLAPI void SetWindowFocused(void); // Set window focused (only PLATFORM_DESKTOP) RLAPI void SetWindowFocused(void); // Set window focused
RLAPI void *GetWindowHandle(void); // Get native window handle RLAPI void *GetWindowHandle(void); // Get native window handle
RLAPI int GetScreenWidth(void); // Get current screen width RLAPI int GetScreenWidth(void); // Get current screen width
RLAPI int GetScreenHeight(void); // Get current screen height RLAPI int GetScreenHeight(void); // Get current screen height
RLAPI int GetRenderWidth(void); // Get current render width (it considers HiDPI) RLAPI int GetRenderWidth(void); // Get current render width (it considers HiDPI)
RLAPI int GetRenderHeight(void); // Get current render height (it considers HiDPI) RLAPI int GetRenderHeight(void); // Get current render height (it considers HiDPI)
RLAPI int GetMonitorCount(void); // Get number of connected monitors RLAPI int GetMonitorCount(void); // Get number of connected monitors
RLAPI int GetCurrentMonitor(void); // Get current connected monitor RLAPI int GetCurrentMonitor(void); // Get current monitor where window is placed
RLAPI Vector2 GetMonitorPosition(int monitor); // Get specified monitor position RLAPI Vector2 GetMonitorPosition(int monitor); // Get specified monitor position
RLAPI int GetMonitorWidth(int monitor); // Get specified monitor width (current video mode used by monitor) RLAPI int GetMonitorWidth(int monitor); // Get specified monitor width (current video mode used by monitor)
RLAPI int GetMonitorHeight(int monitor); // Get specified monitor height (current video mode used by monitor) RLAPI int GetMonitorHeight(int monitor); // Get specified monitor height (current video mode used by monitor)
@ -1001,6 +1011,7 @@ RLAPI Vector2 GetWindowScaleDPI(void); // Get window
RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor
RLAPI void SetClipboardText(const char *text); // Set clipboard text content RLAPI void SetClipboardText(const char *text); // Set clipboard text content
RLAPI const char *GetClipboardText(void); // Get clipboard text content RLAPI const char *GetClipboardText(void); // Get clipboard text content
RLAPI Image GetClipboardImage(void); // Get clipboard image content
RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling 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 RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
@ -1039,7 +1050,7 @@ RLAPI void UnloadVrStereoConfig(VrStereoConfig config); // Unload VR s
// NOTE: Shader functionality is not available on OpenGL 1.1 // NOTE: Shader functionality is not available on OpenGL 1.1
RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
RLAPI bool IsShaderReady(Shader shader); // Check if a shader is ready RLAPI bool IsShaderValid(Shader shader); // Check if a shader is valid (loaded on GPU)
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location
RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value
@ -1066,7 +1077,7 @@ RLAPI double GetTime(void); // Get elapsed
RLAPI int GetFPS(void); // Get current FPS RLAPI int GetFPS(void); // Get current FPS
// Custom frame control functions // Custom frame control functions
// NOTE: Those functions are intended for advance users that want full control over the frame processing // NOTE: Those functions are intended for advanced users that want full control over the frame processing
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents() // By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL // To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing) RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
@ -1093,7 +1104,7 @@ RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal me
RLAPI void MemFree(void *ptr); // Internal memory free RLAPI void MemFree(void *ptr); // Internal memory free
// Set custom callbacks // Set custom callbacks
// WARNING: Callbacks setup is intended for advance users // WARNING: Callbacks setup is intended for advanced users
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader
RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver
@ -1122,10 +1133,12 @@ RLAPI const char *GetDirectoryPath(const char *filePath); // Get full pa
RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string)
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string) RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string) RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string)
RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
@ -1137,10 +1150,14 @@ RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree() RLAPI 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 char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree() RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code
RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes)
RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes)
// Automation events functionality // Automation events functionality
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file
RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file
RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to
RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording
@ -1154,7 +1171,7 @@ RLAPI void PlayAutomationEvent(AutomationEvent event);
// Input-related functions: keyboard // Input-related functions: keyboard
RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again (Only PLATFORM_DESKTOP) RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again
RLAPI bool IsKeyDown(int key); // Check if a key is being pressed RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
@ -1173,7 +1190,7 @@ RLAPI int GetGamepadButtonPressed(void);
RLAPI int GetGamepadAxisCount(int gamepad); // Get gamepad axis count for a gamepad RLAPI int GetGamepadAxisCount(int gamepad); // Get gamepad axis count for a gamepad
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get axis movement value for a gamepad axis RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get axis movement value for a gamepad axis
RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB) RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB)
RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor); // Set gamepad vibration for both motors RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration); // Set gamepad vibration for both motors (duration in seconds)
// Input-related functions: mouse // Input-related functions: mouse
RLAPI bool IsMouseButtonPressed(int button); // Check if a mouse button has been pressed once RLAPI bool IsMouseButtonPressed(int button); // Check if a mouse button has been pressed once
@ -1204,7 +1221,7 @@ RLAPI int GetTouchPointCount(void); // Get number of t
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
RLAPI int GetGestureDetected(void); // Get latest detected gesture RLAPI int GetGestureDetected(void); // Get latest detected gesture
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
RLAPI float GetGestureDragAngle(void); // Get gesture drag angle RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
@ -1227,17 +1244,17 @@ RLAPI Texture2D GetShapesTexture(void); // Get t
RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing
// Basic shapes drawing functions // Basic shapes drawing functions
RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care]
RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel (Vector version) RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel using geometry (Vector version) [Can be slow, use with care]
RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line
RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines) RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines)
RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads) RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads)
RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines) RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines)
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); // Draw a gradient-filled circle
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version) RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version) RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
@ -1249,9 +1266,9 @@ RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color)
RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version) RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version)
RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle
RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters
RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a vertical-gradient-filled rectangle RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle
RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a horizontal-gradient-filled rectangle RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle
RLAPI void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // Draw a gradient-filled rectangle with custom vertex colors RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight); // Draw a gradient-filled rectangle with custom vertex colors
RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters
RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges
@ -1259,18 +1276,18 @@ RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segment
RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline
RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)
RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!) RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!)
RLAPI void DrawTriangleFan(Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center) RLAPI void DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)
RLAPI void DrawTriangleStrip(Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points RLAPI void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version) RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides
RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters
// Splines drawing functions // Splines drawing functions
RLAPI void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points
RLAPI void DrawSplineBasis(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points
RLAPI void DrawSplineCatmullRom(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points RLAPI void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points
RLAPI void DrawSplineBezierQuadratic(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] RLAPI void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
RLAPI void DrawSplineBezierCubic(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] RLAPI void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
RLAPI void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color); // Draw spline segment: Linear, 2 points RLAPI void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color); // Draw spline segment: Linear, 2 points
RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: B-Spline, 4 points RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: B-Spline, 4 points
RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points
@ -1288,12 +1305,13 @@ RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vect
RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles
RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles
RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle
RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created betweeen two points [p1] and [p2]
RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle
RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle
RLAPI bool CheckCollisionPointPoly(Vector2 point, Vector2 *points, int pointCount); // Check if point is within a polygon described by array of vertices
RLAPI bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint); // Check the collision between two lines defined by two points each, returns collision point by reference
RLAPI bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold); // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] RLAPI bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold); // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
RLAPI bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount); // Check if point is within a polygon described by array of vertices
RLAPI bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint); // Check the collision between two lines defined by two points each, returns collision point by reference
RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // Get collision rectangle for two rectangles collision RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // Get collision rectangle for two rectangles collision
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -1304,13 +1322,12 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);
// NOTE: These functions do not require GPU access // NOTE: These functions do not require GPU access
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM) RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data) RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png' RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot) RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot)
RLAPI bool IsImageReady(Image image); // Check if an image is ready RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM) RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
@ -1330,6 +1347,7 @@ RLAPI Image GenImageText(int width, int height, const char *text);
// Image manipulation functions // Image manipulation functions
RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations) RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations)
RLAPI Image ImageFromImage(Image image, Rectangle rec); // Create an image from another image piece RLAPI Image ImageFromImage(Image image, Rectangle rec); // Create an image from another image piece
RLAPI Image ImageFromChannel(Image image, int selectedChannel); // Create an image from a selected channel of another image (GRAYSCALE)
RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font) RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font)
RLAPI Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint); // Create an image from text (custom sprite font) RLAPI Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint); // Create an image from text (custom sprite font)
RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format
@ -1340,10 +1358,10 @@ RLAPI void ImageAlphaClear(Image *image, Color color, float threshold);
RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel
RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation
RLAPI void ImageKernelConvolution(Image *image, float* kernel, int kernelSize); // Apply Custom Square image convolution kernel RLAPI void ImageKernelConvolution(Image *image, const float *kernel, int kernelSize); // Apply custom square convolution kernel to image
RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm) RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm)
RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm) RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm)
RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color
RLAPI void ImageMipmaps(Image *image); // Compute all mipmap levels for a provided image RLAPI void ImageMipmaps(Image *image); // Compute all mipmap levels for a provided image
RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering) RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
RLAPI void ImageFlipVertical(Image *image); // Flip image vertically RLAPI void ImageFlipVertical(Image *image); // Flip image vertically
@ -1371,6 +1389,7 @@ RLAPI void ImageDrawPixel(Image *dst, int posX, int posY, Color color);
RLAPI void ImageDrawPixelV(Image *dst, Vector2 position, Color color); // Draw pixel within an image (Vector version) RLAPI void ImageDrawPixelV(Image *dst, Vector2 position, Color color); // Draw pixel within an image (Vector version)
RLAPI void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw line within an image RLAPI void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw line within an image
RLAPI void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color); // Draw line within an image (Vector version) RLAPI void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color); // Draw line within an image (Vector version)
RLAPI void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color); // Draw a line defining thickness within an image
RLAPI void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color); // Draw a filled circle within an image RLAPI void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color); // Draw a filled circle within an image
RLAPI void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color); // Draw a filled circle within an image (Vector version) RLAPI void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color); // Draw a filled circle within an image (Vector version)
RLAPI void ImageDrawCircleLines(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle outline within an image RLAPI void ImageDrawCircleLines(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle outline within an image
@ -1379,6 +1398,11 @@ RLAPI void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int hei
RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version) RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version)
RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image
RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image
RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image
RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image
RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image
RLAPI void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center)
RLAPI void ImageDrawTriangleStrip(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image
RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source) RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source)
RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination) RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination)
RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination) RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination)
@ -1389,9 +1413,9 @@ RLAPI Texture2D LoadTexture(const char *fileName);
RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data
RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported
RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer) RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer)
RLAPI bool IsTextureReady(Texture2D texture); // Check if a texture is ready RLAPI bool IsTextureValid(Texture2D texture); // Check if a texture is valid (loaded in GPU)
RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM) RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
RLAPI bool IsRenderTextureReady(RenderTexture2D target); // Check if a render texture is ready RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if a render texture is valid (loaded in GPU)
RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM) RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM)
RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data
RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data
@ -1422,6 +1446,7 @@ RLAPI Color ColorBrightness(Color color, float factor); // G
RLAPI Color ColorContrast(Color color, float contrast); // Get color with contrast correction, contrast values between -1.0f and 1.0f RLAPI Color ColorContrast(Color color, float contrast); // Get color with contrast correction, contrast values between -1.0f and 1.0f
RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint
RLAPI Color ColorLerp(Color color1, Color color2, float factor); // Get color lerp interpolation between two colors, factor [0.0f..1.0f]
RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value
RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format
RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer
@ -1434,10 +1459,10 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
// Font loading/unloading functions // Font loading/unloading functions
RLAPI Font GetFontDefault(void); // Get the default Font RLAPI Font GetFontDefault(void); // Get the default Font
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style) RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
RLAPI bool IsFontReady(Font font); // Check if a font is ready RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM) RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
@ -1487,6 +1512,9 @@ RLAPI int TextFindIndex(const char *text, const char *find);
RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string
RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string
RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
RLAPI const char *TextToSnake(const char *text); // Get Snake case notation version of provided string
RLAPI const char *TextToCamel(const char *text); // Get Camel case notation version of provided string
RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported) RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported)
RLAPI float TextToFloat(const char *text); // Get float value from text (negative values not supported) RLAPI float TextToFloat(const char *text); // Get float value from text (negative values not supported)
@ -1499,7 +1527,7 @@ RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color);
RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line
RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space
RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)
RLAPI void DrawTriangleStrip3D(Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points RLAPI void DrawTriangleStrip3D(const Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points
RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube
RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version) RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version)
RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires
@ -1524,7 +1552,7 @@ RLAPI void DrawGrid(int slices, float spacing);
// Model management functions // Model management functions
RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials) RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials)
RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material) RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material)
RLAPI bool IsModelReady(Model model); // Check if a model is ready RLAPI bool IsModelValid(Model model); // Check if a model is valid (loaded in GPU, VAO/VBOs)
RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM) RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM)
RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes) RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes)
@ -1533,8 +1561,10 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint);
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint); // Draw a billboard texture RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation
@ -1565,14 +1595,15 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize);
// Material loading/unloading functions // Material loading/unloading functions
RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file
RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
RLAPI bool IsMaterialReady(Material material); // Check if a material is ready RLAPI bool IsMaterialValid(Material material); // Check if a material is valid (shader assigned, map textures loaded in GPU)
RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM)
RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture); // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture); // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
// Model animations loading/unloading functions // Model animations loading/unloading functions
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose (CPU)
RLAPI void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (GPU skinning)
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
@ -1602,11 +1633,11 @@ RLAPI float GetMasterVolume(void); // Get mas
// Wave/Sound loading/unloading functions // Wave/Sound loading/unloading functions
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav' RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready RLAPI bool IsWaveValid(Wave wave); // Checks if wave data is valid (data loaded and parameters)
RLAPI Sound LoadSound(const char *fileName); // Load sound from file RLAPI Sound LoadSound(const char *fileName); // Load sound from file
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data
RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready RLAPI bool IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized)
RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
RLAPI void UnloadWave(Wave wave); // Unload wave data RLAPI void UnloadWave(Wave wave); // Unload wave data
RLAPI void UnloadSound(Sound sound); // Unload sound RLAPI void UnloadSound(Sound sound); // Unload sound
@ -1624,7 +1655,7 @@ RLAPI void SetSoundVolume(Sound sound, float volume); // Set vol
RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level) RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (0.5 is center) RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (0.5 is center)
RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave
RLAPI void WaveCrop(Wave *wave, int initSample, int finalSample); // Crop a wave to defined samples range RLAPI void WaveCrop(Wave *wave, int initFrame, int finalFrame); // Crop a wave to defined frames range
RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format
RLAPI float *LoadWaveSamples(Wave wave); // Load samples data from wave as a 32bit float data array RLAPI float *LoadWaveSamples(Wave wave); // Load samples data from wave as a 32bit float data array
RLAPI void UnloadWaveSamples(float *samples); // Unload samples data loaded with LoadWaveSamples() RLAPI void UnloadWaveSamples(float *samples); // Unload samples data loaded with LoadWaveSamples()
@ -1632,7 +1663,7 @@ RLAPI void UnloadWaveSamples(float *samples); // Unload
// Music management functions // Music management functions
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
RLAPI bool IsMusicReady(Music music); // Checks if a music stream is ready RLAPI bool IsMusicValid(Music music); // Checks if a music stream is valid (context and buffers initialized)
RLAPI void UnloadMusicStream(Music music); // Unload music stream RLAPI void UnloadMusicStream(Music music); // Unload music stream
RLAPI void PlayMusicStream(Music music); // Start music playing RLAPI void PlayMusicStream(Music music); // Start music playing
RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing
@ -1649,7 +1680,7 @@ RLAPI float GetMusicTimePlayed(Music music); // Get cur
// AudioStream management functions // AudioStream management functions
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data) RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
RLAPI bool IsAudioStreamReady(AudioStream stream); // Checks if an audio stream is ready RLAPI bool IsAudioStreamValid(AudioStream stream); // Checks if an audio stream is valid (buffers initialized)
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill

View file

@ -65,6 +65,7 @@ var getWindowScaleDPI func() uintptr
var getMonitorName func(monitor int32) string var getMonitorName func(monitor int32) string
var setClipboardText func(text string) var setClipboardText func(text string)
var getClipboardText func() string var getClipboardText func() string
var getClipboardImage func(img uintptr)
var enableEventWaiting func() var enableEventWaiting func()
var disableEventWaiting func() var disableEventWaiting func()
var showCursor func() var showCursor func()
@ -94,7 +95,7 @@ var loadVrStereoConfig func(config uintptr, device uintptr)
var unloadVrStereoConfig func(config uintptr) var unloadVrStereoConfig func(config uintptr)
var loadShader func(shader uintptr, vsFileName uintptr, fsFileName uintptr) var loadShader func(shader uintptr, vsFileName uintptr, fsFileName uintptr)
var loadShaderFromMemory func(shader uintptr, vsCode uintptr, fsCode uintptr) var loadShaderFromMemory func(shader uintptr, vsCode uintptr, fsCode uintptr)
var isShaderReady func(shader uintptr) bool var isShaderValid func(shader uintptr) bool
var getShaderLocation func(shader uintptr, uniformName string) int32 var getShaderLocation func(shader uintptr, uniformName string) int32
var getShaderLocationAttrib func(shader uintptr, attribName string) int32 var getShaderLocationAttrib func(shader uintptr, attribName string) int32
var setShaderValue func(shader uintptr, locIndex int32, value []float32, uniformType int32) var setShaderValue func(shader uintptr, locIndex int32, value []float32, uniformType int32)
@ -102,7 +103,8 @@ var setShaderValueV func(shader uintptr, locIndex int32, value []float32, unifor
var setShaderValueMatrix func(shader uintptr, locIndex int32, mat uintptr) var setShaderValueMatrix func(shader uintptr, locIndex int32, mat uintptr)
var setShaderValueTexture func(shader uintptr, locIndex int32, texture uintptr) var setShaderValueTexture func(shader uintptr, locIndex int32, texture uintptr)
var unloadShader func(shader uintptr) var unloadShader func(shader uintptr)
var getMouseRay func(ray uintptr, mousePosition uintptr, camera uintptr) var getScreenToWorldRay func(ray uintptr, position uintptr, camera uintptr)
var getScreenToWorldRayEx func(ray uintptr, position uintptr, camera uintptr, width, height int32)
var getCameraMatrix func(mat uintptr, camera uintptr) var getCameraMatrix func(mat uintptr, camera uintptr)
var getCameraMatrix2D func(mat uintptr, camera uintptr) var getCameraMatrix2D func(mat uintptr, camera uintptr)
var getWorldToScreen func(position uintptr, camera uintptr) uintptr var getWorldToScreen func(position uintptr, camera uintptr) uintptr
@ -158,6 +160,7 @@ var getGamepadButtonPressed func() int32
var getGamepadAxisCount func(gamepad int32) int32 var getGamepadAxisCount func(gamepad int32) int32
var getGamepadAxisMovement func(gamepad int32, axis int32) float32 var getGamepadAxisMovement func(gamepad int32, axis int32) float32
var setGamepadMappings func(mappings string) int32 var setGamepadMappings func(mappings string) int32
var setGamepadVibration func(gamepad int32, leftMotor, rightMotor, duration float32)
var isMouseButtonPressed func(button int32) bool var isMouseButtonPressed func(button int32) bool
var isMouseButtonDown func(button int32) bool var isMouseButtonDown func(button int32) bool
var isMouseButtonReleased func(button int32) bool var isMouseButtonReleased func(button int32) bool
@ -186,6 +189,8 @@ var getGestureDragAngle func() float32
var getGesturePinchVector func() uintptr var getGesturePinchVector func() uintptr
var getGesturePinchAngle func() float32 var getGesturePinchAngle func() float32
var setShapesTexture func(texture uintptr, source uintptr) var setShapesTexture func(texture uintptr, source uintptr)
var getShapesTexture func(texture uintptr)
var getShapesTextureRectangle func(rec uintptr)
var drawPixel func(posX int32, posY int32, col uintptr) var drawPixel func(posX int32, posY int32, col uintptr)
var drawPixelV func(position uintptr, col uintptr) var drawPixelV func(position uintptr, col uintptr)
var drawLine func(startPosX int32, startPosY int32, endPosX int32, endPosY int32, col uintptr) var drawLine func(startPosX int32, startPosY int32, endPosX int32, endPosY int32, col uintptr)
@ -196,7 +201,7 @@ var drawLineBezier func(startPos uintptr, endPos uintptr, thick float32, col uin
var drawCircle func(centerX int32, centerY int32, radius float32, col uintptr) var drawCircle func(centerX int32, centerY int32, radius float32, col uintptr)
var drawCircleSector func(center uintptr, radius float32, startAngle float32, endAngle float32, segments int32, col uintptr) var drawCircleSector func(center uintptr, radius float32, startAngle float32, endAngle float32, segments int32, col uintptr)
var drawCircleSectorLines func(center uintptr, radius float32, startAngle float32, endAngle float32, segments int32, col uintptr) var drawCircleSectorLines func(center uintptr, radius float32, startAngle float32, endAngle float32, segments int32, col uintptr)
var drawCircleGradient func(centerX int32, centerY int32, radius float32, color1 uintptr, color2 uintptr) var drawCircleGradient func(centerX int32, centerY int32, radius float32, inner uintptr, outer uintptr)
var drawCircleV func(center uintptr, radius float32, col uintptr) var drawCircleV func(center uintptr, radius float32, col uintptr)
var drawCircleLines func(centerX int32, centerY int32, radius float32, col uintptr) var drawCircleLines func(centerX int32, centerY int32, radius float32, col uintptr)
var drawCircleLinesV func(center uintptr, radius float32, col uintptr) var drawCircleLinesV func(center uintptr, radius float32, col uintptr)
@ -208,13 +213,14 @@ var drawRectangle func(posX int32, posY int32, width int32, height int32, col ui
var drawRectangleV func(position uintptr, size uintptr, col uintptr) var drawRectangleV func(position uintptr, size uintptr, col uintptr)
var drawRectangleRec func(rec uintptr, col uintptr) var drawRectangleRec func(rec uintptr, col uintptr)
var drawRectanglePro func(rec uintptr, origin uintptr, rotation float32, col uintptr) var drawRectanglePro func(rec uintptr, origin uintptr, rotation float32, col uintptr)
var drawRectangleGradientV func(posX int32, posY int32, width int32, height int32, color1 uintptr, color2 uintptr) var drawRectangleGradientV func(posX int32, posY int32, width int32, height int32, top uintptr, bottom uintptr)
var drawRectangleGradientH func(posX int32, posY int32, width int32, height int32, color1 uintptr, color2 uintptr) var drawRectangleGradientH func(posX int32, posY int32, width int32, height int32, left uintptr, right uintptr)
var drawRectangleGradientEx func(rec uintptr, col1 uintptr, col2 uintptr, col3 uintptr, col4 uintptr) var drawRectangleGradientEx func(rec uintptr, topLeft uintptr, bottomLeft uintptr, topRight uintptr, bottomRight uintptr)
var drawRectangleLines func(posX int32, posY int32, width int32, height int32, col uintptr) var drawRectangleLines func(posX int32, posY int32, width int32, height int32, col uintptr)
var drawRectangleLinesEx func(rec uintptr, lineThick float32, col uintptr) var drawRectangleLinesEx func(rec uintptr, lineThick float32, col uintptr)
var drawRectangleRounded func(rec uintptr, roundness float32, segments int32, col uintptr) var drawRectangleRounded func(rec uintptr, roundness float32, segments int32, col uintptr)
var drawRectangleRoundedLines func(rec uintptr, roundness float32, segments int32, lineThick float32, col uintptr) var drawRectangleRoundedLines func(rec uintptr, roundness float32, segments int32, col uintptr)
var drawRectangleRoundedLinesEx func(rec uintptr, roundness float32, segments int32, lineThick float32, col uintptr)
var drawTriangle func(v1 uintptr, v2 uintptr, v3 uintptr, col uintptr) var drawTriangle func(v1 uintptr, v2 uintptr, v3 uintptr, col uintptr)
var drawTriangleLines func(v1 uintptr, v2 uintptr, v3 uintptr, col uintptr) var drawTriangleLines func(v1 uintptr, v2 uintptr, v3 uintptr, col uintptr)
var drawTriangleFan func(points *Vector2, pointCount int32, col uintptr) var drawTriangleFan func(points *Vector2, pointCount int32, col uintptr)
@ -240,6 +246,7 @@ var getSplinePointBezierCubic func(p1 uintptr, c2 uintptr, c3 uintptr, p4 uintpt
var checkCollisionRecs func(rec1 uintptr, rec2 uintptr) bool var checkCollisionRecs func(rec1 uintptr, rec2 uintptr) bool
var checkCollisionCircles func(center1 uintptr, radius1 float32, center2 uintptr, radius2 float32) bool var checkCollisionCircles func(center1 uintptr, radius1 float32, center2 uintptr, radius2 float32) bool
var checkCollisionCircleRec func(center uintptr, radius float32, rec uintptr) bool var checkCollisionCircleRec func(center uintptr, radius float32, rec uintptr) bool
var checkCollisionCircleLine func(center uintptr, radius float32, p1, p2 uintptr) bool
var checkCollisionPointRec func(point uintptr, rec uintptr) bool var checkCollisionPointRec func(point uintptr, rec uintptr) bool
var checkCollisionPointCircle func(point uintptr, center uintptr, radius float32) bool var checkCollisionPointCircle func(point uintptr, center uintptr, radius float32) bool
var checkCollisionPointTriangle func(point uintptr, p1 uintptr, p2 uintptr, p3 uintptr) bool var checkCollisionPointTriangle func(point uintptr, p1 uintptr, p2 uintptr, p3 uintptr) bool
@ -249,12 +256,12 @@ var checkCollisionPointLine func(point uintptr, p1 uintptr, p2 uintptr, threshol
var getCollisionRec func(rec uintptr, rec1 uintptr, rec2 uintptr) var getCollisionRec func(rec uintptr, rec1 uintptr, rec2 uintptr)
var loadImage func(img uintptr, fileName string) var loadImage func(img uintptr, fileName string)
var loadImageRaw func(img uintptr, fileName string, width int32, height int32, format int32, headerSize int32) var loadImageRaw func(img uintptr, fileName string, width int32, height int32, format int32, headerSize int32)
var loadImageSvg func(img uintptr, fileNameOrString string, width int32, height int32) var loadImageAnim func(img uintptr, fileName string, frames *int32)
var loadImageAnim func(img uintptr, fileName string, frames []int32) var loadImageAnimFromMemory func(img uintptr, fileType string, fileData []byte, dataSize int32, frames *int32)
var loadImageFromMemory func(img uintptr, fileType string, fileData []byte, dataSize int32) var loadImageFromMemory func(img uintptr, fileType string, fileData []byte, dataSize int32)
var loadImageFromTexture func(img uintptr, texture uintptr) var loadImageFromTexture func(img uintptr, texture uintptr)
var loadImageFromScreen func(img uintptr) var loadImageFromScreen func(img uintptr)
var isImageReady func(image uintptr) bool var isImageValid func(image uintptr) bool
var unloadImage func(image uintptr) var unloadImage func(image uintptr)
var exportImage func(image uintptr, fileName string) bool var exportImage func(image uintptr, fileName string) bool
var exportImageToMemory func(image uintptr, fileType string, fileSize *int32) *byte var exportImageToMemory func(image uintptr, fileType string, fileSize *int32) *byte
@ -269,6 +276,7 @@ var genImageCellular func(image uintptr, width int32, height int32, tileSize int
var genImageText func(image uintptr, width int32, height int32, text string) var genImageText func(image uintptr, width int32, height int32, text string)
var imageCopy func(retImage uintptr, image uintptr) var imageCopy func(retImage uintptr, image uintptr)
var imageFromImage func(retImage uintptr, image uintptr, rec uintptr) var imageFromImage func(retImage uintptr, image uintptr, rec uintptr)
var imageFromChannel func(retImage uintptr, image uintptr, selectedChannel int32)
var imageText func(retImage uintptr, text string, fontSize int32, col uintptr) var imageText func(retImage uintptr, text string, fontSize int32, col uintptr)
var imageTextEx func(retImage uintptr, font uintptr, text string, fontSize float32, spacing float32, tint uintptr) var imageTextEx func(retImage uintptr, font uintptr, text string, fontSize float32, spacing float32, tint uintptr)
var imageFormat func(image *Image, newFormat int32) var imageFormat func(image *Image, newFormat int32)
@ -279,6 +287,7 @@ var imageAlphaClear func(image *Image, col uintptr, threshold float32)
var imageAlphaMask func(image *Image, alphaMask uintptr) var imageAlphaMask func(image *Image, alphaMask uintptr)
var imageAlphaPremultiply func(image *Image) var imageAlphaPremultiply func(image *Image)
var imageBlurGaussian func(image *Image, blurSize int32) var imageBlurGaussian func(image *Image, blurSize int32)
var imageKernelConvolution func(image *Image, kernel []float32, kernelSize int32)
var imageResize func(image *Image, newWidth int32, newHeight int32) var imageResize func(image *Image, newWidth int32, newHeight int32)
var imageResizeNN func(image *Image, newWidth int32, newHeight int32) var imageResizeNN func(image *Image, newWidth int32, newHeight int32)
var imageResizeCanvas func(image *Image, newWidth int32, newHeight int32, offsetX int32, offsetY int32, fill uintptr) var imageResizeCanvas func(image *Image, newWidth int32, newHeight int32, offsetX int32, offsetY int32, fill uintptr)
@ -306,6 +315,7 @@ var imageDrawPixel func(dst *Image, posX int32, posY int32, col uintptr)
var imageDrawPixelV func(dst *Image, position uintptr, col uintptr) var imageDrawPixelV func(dst *Image, position uintptr, col uintptr)
var imageDrawLine func(dst *Image, startPosX int32, startPosY int32, endPosX int32, endPosY int32, col uintptr) var imageDrawLine func(dst *Image, startPosX int32, startPosY int32, endPosX int32, endPosY int32, col uintptr)
var imageDrawLineV func(dst *Image, start uintptr, end uintptr, col uintptr) var imageDrawLineV func(dst *Image, start uintptr, end uintptr, col uintptr)
var imageDrawLineEx func(dst *Image, start uintptr, end uintptr, thick int32, col uintptr)
var imageDrawCircle func(dst *Image, centerX int32, centerY int32, radius int32, col uintptr) var imageDrawCircle func(dst *Image, centerX int32, centerY int32, radius int32, col uintptr)
var imageDrawCircleV func(dst *Image, center uintptr, radius int32, col uintptr) var imageDrawCircleV func(dst *Image, center uintptr, radius int32, col uintptr)
var imageDrawCircleLines func(dst *Image, centerX int32, centerY int32, radius int32, col uintptr) var imageDrawCircleLines func(dst *Image, centerX int32, centerY int32, radius int32, col uintptr)
@ -314,6 +324,11 @@ var imageDrawRectangle func(dst *Image, posX int32, posY int32, width int32, hei
var imageDrawRectangleV func(dst *Image, position uintptr, size uintptr, col uintptr) var imageDrawRectangleV func(dst *Image, position uintptr, size uintptr, col uintptr)
var imageDrawRectangleRec func(dst *Image, rec uintptr, col uintptr) var imageDrawRectangleRec func(dst *Image, rec uintptr, col uintptr)
var imageDrawRectangleLines func(dst *Image, rec uintptr, thick int32, col uintptr) var imageDrawRectangleLines func(dst *Image, rec uintptr, thick int32, col uintptr)
var imageDrawTriangle func(dst *Image, v1, v2, v3 uintptr, col uintptr)
var imageDrawTriangleEx func(dst *Image, v1, v2, v3 uintptr, c1, c2, c3 uintptr)
var imageDrawTriangleLines func(dst *Image, v1, v2, v3 uintptr, col uintptr)
var imageDrawTriangleFan func(dst *Image, points *Vector2, pointCount int32, col uintptr)
var imageDrawTriangleStrip func(dst *Image, points *Vector2, pointCount int32, col uintptr)
var imageDraw func(dst *Image, src uintptr, srcRec uintptr, dstRec uintptr, tint uintptr) var imageDraw func(dst *Image, src uintptr, srcRec uintptr, dstRec uintptr, tint uintptr)
var imageDrawText func(dst *Image, text string, posX int32, posY int32, fontSize int32, col uintptr) var imageDrawText func(dst *Image, text string, posX int32, posY int32, fontSize int32, col uintptr)
var imageDrawTextEx func(dst *Image, font uintptr, text string, position uintptr, fontSize float32, spacing float32, tint uintptr) var imageDrawTextEx func(dst *Image, font uintptr, text string, position uintptr, fontSize float32, spacing float32, tint uintptr)
@ -321,9 +336,9 @@ var loadTexture func(texture uintptr, fileName string)
var loadTextureFromImage func(texture uintptr, image uintptr) var loadTextureFromImage func(texture uintptr, image uintptr)
var loadTextureCubemap func(texture uintptr, image uintptr, layout int32) var loadTextureCubemap func(texture uintptr, image uintptr, layout int32)
var loadRenderTexture func(texture uintptr, width int32, height int32) var loadRenderTexture func(texture uintptr, width int32, height int32)
var isTextureReady func(texture uintptr) bool var isTextureValid func(texture uintptr) bool
var unloadTexture func(texture uintptr) var unloadTexture func(texture uintptr)
var isRenderTextureReady func(target uintptr) bool var isRenderTextureValid func(target uintptr) bool
var unloadRenderTexture func(target uintptr) var unloadRenderTexture func(target uintptr)
var updateTexture func(texture uintptr, pixels *color.RGBA) var updateTexture func(texture uintptr, pixels *color.RGBA)
var updateTextureRec func(texture uintptr, rec uintptr, pixels *color.RGBA) var updateTextureRec func(texture uintptr, rec uintptr, pixels *color.RGBA)
@ -347,6 +362,7 @@ var colorBrightness func(col uintptr, factor float32) uintptr
var colorContrast func(col uintptr, contrast float32) uintptr var colorContrast func(col uintptr, contrast float32) uintptr
var colorAlpha func(col uintptr, alpha float32) uintptr var colorAlpha func(col uintptr, alpha float32) uintptr
var colorAlphaBlend func(dst uintptr, src uintptr, tint uintptr) uintptr var colorAlphaBlend func(dst uintptr, src uintptr, tint uintptr) uintptr
var colorLerp func(col1, col2 uintptr, factor float32) uintptr
var getColor func(hexValue uint32) uintptr var getColor func(hexValue uint32) uintptr
var getPixelColor func(srcPtr unsafe.Pointer, format int32) uintptr var getPixelColor func(srcPtr unsafe.Pointer, format int32) uintptr
var setPixelColor func(dstPtr unsafe.Pointer, col uintptr, format int32) var setPixelColor func(dstPtr unsafe.Pointer, col uintptr, format int32)
@ -356,7 +372,7 @@ var loadFont func(font uintptr, fileName string)
var loadFontEx func(font uintptr, fileName string, fontSize int32, codepoints []int32, codepointCount int32) var loadFontEx func(font uintptr, fileName string, fontSize int32, codepoints []int32, codepointCount int32)
var loadFontFromImage func(font uintptr, image uintptr, key uintptr, firstChar int32) var loadFontFromImage func(font uintptr, image uintptr, key uintptr, firstChar int32)
var loadFontFromMemory func(font uintptr, fileType string, fileData []byte, dataSize int32, fontSize int32, codepoints []int32, codepointCount int32) var loadFontFromMemory func(font uintptr, fileType string, fileData []byte, dataSize int32, fontSize int32, codepoints []int32, codepointCount int32)
var isFontReady func(font uintptr) bool var isFontValid func(font uintptr) bool
var loadFontData func(fileData []byte, dataSize int32, fontSize int32, codepoints []int32, codepointCount int32, _type int32) *GlyphInfo var loadFontData func(fileData []byte, dataSize int32, fontSize int32, codepoints []int32, codepointCount int32, _type int32) *GlyphInfo
var genImageFontAtlas func(image uintptr, glyphs *GlyphInfo, glyphRecs []*Rectangle, glyphCount int32, fontSize int32, padding int32, packMethod int32) var genImageFontAtlas func(image uintptr, glyphs *GlyphInfo, glyphRecs []*Rectangle, glyphCount int32, fontSize int32, padding int32, packMethod int32)
var unloadFontData func(glyphs *GlyphInfo, glyphCount int32) var unloadFontData func(glyphs *GlyphInfo, glyphCount int32)
@ -396,15 +412,17 @@ var drawRay func(ray uintptr, col uintptr)
var drawGrid func(slices int32, spacing float32) var drawGrid func(slices int32, spacing float32)
var loadModel func(model uintptr, fileName string) var loadModel func(model uintptr, fileName string)
var loadModelFromMesh func(model uintptr, mesh uintptr) var loadModelFromMesh func(model uintptr, mesh uintptr)
var isModelReady func(model uintptr) bool var isModelValid func(model uintptr) bool
var unloadModel func(model uintptr) var unloadModel func(model uintptr)
var getModelBoundingBox func(boundingBox uintptr, model uintptr) var getModelBoundingBox func(boundingBox uintptr, model uintptr)
var drawModel func(model uintptr, position uintptr, scale float32, tint uintptr) var drawModel func(model uintptr, position uintptr, scale float32, tint uintptr)
var drawModelEx func(model uintptr, position uintptr, rotationAxis uintptr, rotationAngle float32, scale uintptr, tint uintptr) var drawModelEx func(model uintptr, position uintptr, rotationAxis uintptr, rotationAngle float32, scale uintptr, tint uintptr)
var drawModelWires func(model uintptr, position uintptr, scale float32, tint uintptr) var drawModelWires func(model uintptr, position uintptr, scale float32, tint uintptr)
var drawModelWiresEx func(model uintptr, position uintptr, rotationAxis uintptr, rotationAngle float32, scale uintptr, tint uintptr) var drawModelWiresEx func(model uintptr, position uintptr, rotationAxis uintptr, rotationAngle float32, scale uintptr, tint uintptr)
var drawModelPoints func(model uintptr, position uintptr, scale float32, tint uintptr)
var drawModelPointsEx func(model uintptr, position uintptr, rotationAxis uintptr, rotationAngle float32, scale uintptr, tint uintptr)
var drawBoundingBox func(box uintptr, col uintptr) var drawBoundingBox func(box uintptr, col uintptr)
var drawBillboard func(camera uintptr, texture uintptr, position uintptr, size float32, tint uintptr) var drawBillboard func(camera uintptr, texture uintptr, position uintptr, scale float32, tint uintptr)
var drawBillboardRec func(camera uintptr, texture uintptr, source uintptr, position uintptr, size uintptr, tint uintptr) var drawBillboardRec func(camera uintptr, texture uintptr, source uintptr, position uintptr, size uintptr, tint uintptr)
var drawBillboardPro func(camera uintptr, texture uintptr, source uintptr, position uintptr, up uintptr, size uintptr, origin uintptr, rotation float32, tint uintptr) var drawBillboardPro func(camera uintptr, texture uintptr, source uintptr, position uintptr, up uintptr, size uintptr, origin uintptr, rotation float32, tint uintptr)
var uploadMesh func(mesh *Mesh, dynamic bool) var uploadMesh func(mesh *Mesh, dynamic bool)
@ -428,12 +446,13 @@ var genMeshHeightmap func(mesh uintptr, heightmap uintptr, size uintptr)
var genMeshCubicmap func(mesh uintptr, cubicmap uintptr, cubeSize uintptr) var genMeshCubicmap func(mesh uintptr, cubicmap uintptr, cubeSize uintptr)
var loadMaterials func(fileName string, materialCount *int32) *Material var loadMaterials func(fileName string, materialCount *int32) *Material
var loadMaterialDefault func(material uintptr) var loadMaterialDefault func(material uintptr)
var isMaterialReady func(material uintptr) bool var isMaterialValid func(material uintptr) bool
var unloadMaterial func(material uintptr) var unloadMaterial func(material uintptr)
var setMaterialTexture func(material *Material, mapType int32, texture uintptr) var setMaterialTexture func(material *Material, mapType int32, texture uintptr)
var setModelMeshMaterial func(model *Model, meshId int32, materialId int32) var setModelMeshMaterial func(model *Model, meshId int32, materialId int32)
var loadModelAnimations func(fileName string, animCount *int32) *ModelAnimation var loadModelAnimations func(fileName string, animCount *int32) *ModelAnimation
var updateModelAnimation func(model uintptr, anim uintptr, frame int32) var updateModelAnimation func(model uintptr, anim uintptr, frame int32)
var updateModelAnimationBones func(model uintptr, anim uintptr, frame int32)
var unloadModelAnimation func(anim uintptr) var unloadModelAnimation func(anim uintptr)
var unloadModelAnimations func(animations *ModelAnimation, animCount int32) var unloadModelAnimations func(animations *ModelAnimation, animCount int32)
var isModelAnimationValid func(model uintptr, anim uintptr) bool var isModelAnimationValid func(model uintptr, anim uintptr) bool
@ -452,11 +471,11 @@ var setMasterVolume func(volume float32)
var getMasterVolume func() float32 var getMasterVolume func() float32
var loadWave func(wave uintptr, fileName string) var loadWave func(wave uintptr, fileName string)
var loadWaveFromMemory func(wave uintptr, fileType string, fileData []byte, dataSize int32) var loadWaveFromMemory func(wave uintptr, fileType string, fileData []byte, dataSize int32)
var isWaveReady func(wave uintptr) bool var isWaveValid func(wave uintptr) bool
var loadSound func(sound uintptr, fileName string) var loadSound func(sound uintptr, fileName string)
var loadSoundFromWave func(sound uintptr, wave uintptr) var loadSoundFromWave func(sound uintptr, wave uintptr)
var loadSoundAlias func(sound uintptr, source uintptr) var loadSoundAlias func(sound uintptr, source uintptr)
var isSoundReady func(sound uintptr) bool var isSoundValid func(sound uintptr) bool
var updateSound func(sound uintptr, data []byte, sampleCount int32) var updateSound func(sound uintptr, data []byte, sampleCount int32)
var unloadWave func(wave uintptr) var unloadWave func(wave uintptr)
var unloadSound func(sound uintptr) var unloadSound func(sound uintptr)
@ -471,13 +490,13 @@ var setSoundVolume func(sound uintptr, volume float32)
var setSoundPitch func(sound uintptr, pitch float32) var setSoundPitch func(sound uintptr, pitch float32)
var setSoundPan func(sound uintptr, pan float32) var setSoundPan func(sound uintptr, pan float32)
var waveCopy func(copy uintptr, wave uintptr) var waveCopy func(copy uintptr, wave uintptr)
var waveCrop func(wave *Wave, initSample int32, finalSample int32) var waveCrop func(wave *Wave, initFrame int32, finalFrame int32)
var waveFormat func(wave *Wave, sampleRate int32, sampleSize int32, channels int32) var waveFormat func(wave *Wave, sampleRate int32, sampleSize int32, channels int32)
var loadWaveSamples func(wave uintptr) *float32 var loadWaveSamples func(wave uintptr) *float32
var unloadWaveSamples func(samples []float32) var unloadWaveSamples func(samples []float32)
var loadMusicStream func(music uintptr, fileName string) var loadMusicStream func(music uintptr, fileName string)
var loadMusicStreamFromMemory func(sound uintptr, fileType string, data []byte, dataSize int32) var loadMusicStreamFromMemory func(sound uintptr, fileType string, data []byte, dataSize int32)
var isMusicReady func(music uintptr) bool var isMusicValid func(music uintptr) bool
var unloadMusicStream func(music uintptr) var unloadMusicStream func(music uintptr)
var playMusicStream func(music uintptr) var playMusicStream func(music uintptr)
var isMusicStreamPlaying func(music uintptr) bool var isMusicStreamPlaying func(music uintptr) bool
@ -492,7 +511,7 @@ var setMusicPan func(music uintptr, pan float32)
var getMusicTimeLength func(music uintptr) float32 var getMusicTimeLength func(music uintptr) float32
var getMusicTimePlayed func(music uintptr) float32 var getMusicTimePlayed func(music uintptr) float32
var loadAudioStream func(audioStream uintptr, sampleRate uint32, sampleSize uint32, channels uint32) var loadAudioStream func(audioStream uintptr, sampleRate uint32, sampleSize uint32, channels uint32)
var isAudioStreamReady func(stream uintptr) bool var isAudioStreamValid func(stream uintptr) bool
var unloadAudioStream func(stream uintptr) var unloadAudioStream func(stream uintptr)
var updateAudioStream func(stream uintptr, data []float32, frameCount int32) var updateAudioStream func(stream uintptr, data []float32, frameCount int32)
var isAudioStreamProcessed func(stream uintptr) bool var isAudioStreamProcessed func(stream uintptr) bool
@ -562,6 +581,7 @@ func init() {
purego.RegisterLibFunc(&getMonitorName, raylibDll, "GetMonitorName") purego.RegisterLibFunc(&getMonitorName, raylibDll, "GetMonitorName")
purego.RegisterLibFunc(&setClipboardText, raylibDll, "SetClipboardText") purego.RegisterLibFunc(&setClipboardText, raylibDll, "SetClipboardText")
purego.RegisterLibFunc(&getClipboardText, raylibDll, "GetClipboardText") purego.RegisterLibFunc(&getClipboardText, raylibDll, "GetClipboardText")
purego.RegisterLibFunc(&getClipboardImage, raylibDll, "GetClipboardImage")
purego.RegisterLibFunc(&enableEventWaiting, raylibDll, "EnableEventWaiting") purego.RegisterLibFunc(&enableEventWaiting, raylibDll, "EnableEventWaiting")
purego.RegisterLibFunc(&disableEventWaiting, raylibDll, "DisableEventWaiting") purego.RegisterLibFunc(&disableEventWaiting, raylibDll, "DisableEventWaiting")
purego.RegisterLibFunc(&showCursor, raylibDll, "ShowCursor") purego.RegisterLibFunc(&showCursor, raylibDll, "ShowCursor")
@ -591,7 +611,7 @@ func init() {
purego.RegisterLibFunc(&unloadVrStereoConfig, raylibDll, "UnloadVrStereoConfig") purego.RegisterLibFunc(&unloadVrStereoConfig, raylibDll, "UnloadVrStereoConfig")
purego.RegisterLibFunc(&loadShader, raylibDll, "LoadShader") purego.RegisterLibFunc(&loadShader, raylibDll, "LoadShader")
purego.RegisterLibFunc(&loadShaderFromMemory, raylibDll, "LoadShaderFromMemory") purego.RegisterLibFunc(&loadShaderFromMemory, raylibDll, "LoadShaderFromMemory")
purego.RegisterLibFunc(&isShaderReady, raylibDll, "IsShaderReady") purego.RegisterLibFunc(&isShaderValid, raylibDll, "IsShaderValid")
purego.RegisterLibFunc(&getShaderLocation, raylibDll, "GetShaderLocation") purego.RegisterLibFunc(&getShaderLocation, raylibDll, "GetShaderLocation")
purego.RegisterLibFunc(&getShaderLocationAttrib, raylibDll, "GetShaderLocationAttrib") purego.RegisterLibFunc(&getShaderLocationAttrib, raylibDll, "GetShaderLocationAttrib")
purego.RegisterLibFunc(&setShaderValue, raylibDll, "SetShaderValue") purego.RegisterLibFunc(&setShaderValue, raylibDll, "SetShaderValue")
@ -599,7 +619,8 @@ func init() {
purego.RegisterLibFunc(&setShaderValueMatrix, raylibDll, "SetShaderValueMatrix") purego.RegisterLibFunc(&setShaderValueMatrix, raylibDll, "SetShaderValueMatrix")
purego.RegisterLibFunc(&setShaderValueTexture, raylibDll, "SetShaderValueTexture") purego.RegisterLibFunc(&setShaderValueTexture, raylibDll, "SetShaderValueTexture")
purego.RegisterLibFunc(&unloadShader, raylibDll, "UnloadShader") purego.RegisterLibFunc(&unloadShader, raylibDll, "UnloadShader")
purego.RegisterLibFunc(&getMouseRay, raylibDll, "GetMouseRay") purego.RegisterLibFunc(&getScreenToWorldRay, raylibDll, "GetScreenToWorldRay")
purego.RegisterLibFunc(&getScreenToWorldRayEx, raylibDll, "GetScreenToWorldRayEx")
purego.RegisterLibFunc(&getCameraMatrix, raylibDll, "GetCameraMatrix") purego.RegisterLibFunc(&getCameraMatrix, raylibDll, "GetCameraMatrix")
purego.RegisterLibFunc(&getCameraMatrix2D, raylibDll, "GetCameraMatrix2D") purego.RegisterLibFunc(&getCameraMatrix2D, raylibDll, "GetCameraMatrix2D")
purego.RegisterLibFunc(&getWorldToScreen, raylibDll, "GetWorldToScreen") purego.RegisterLibFunc(&getWorldToScreen, raylibDll, "GetWorldToScreen")
@ -655,6 +676,7 @@ func init() {
purego.RegisterLibFunc(&getGamepadAxisCount, raylibDll, "GetGamepadAxisCount") purego.RegisterLibFunc(&getGamepadAxisCount, raylibDll, "GetGamepadAxisCount")
purego.RegisterLibFunc(&getGamepadAxisMovement, raylibDll, "GetGamepadAxisMovement") purego.RegisterLibFunc(&getGamepadAxisMovement, raylibDll, "GetGamepadAxisMovement")
purego.RegisterLibFunc(&setGamepadMappings, raylibDll, "SetGamepadMappings") purego.RegisterLibFunc(&setGamepadMappings, raylibDll, "SetGamepadMappings")
purego.RegisterLibFunc(&setGamepadVibration, raylibDll, "SetGamepadVibration")
purego.RegisterLibFunc(&isMouseButtonPressed, raylibDll, "IsMouseButtonPressed") purego.RegisterLibFunc(&isMouseButtonPressed, raylibDll, "IsMouseButtonPressed")
purego.RegisterLibFunc(&isMouseButtonDown, raylibDll, "IsMouseButtonDown") purego.RegisterLibFunc(&isMouseButtonDown, raylibDll, "IsMouseButtonDown")
purego.RegisterLibFunc(&isMouseButtonReleased, raylibDll, "IsMouseButtonReleased") purego.RegisterLibFunc(&isMouseButtonReleased, raylibDll, "IsMouseButtonReleased")
@ -683,6 +705,8 @@ func init() {
purego.RegisterLibFunc(&getGesturePinchVector, raylibDll, "GetGesturePinchVector") purego.RegisterLibFunc(&getGesturePinchVector, raylibDll, "GetGesturePinchVector")
purego.RegisterLibFunc(&getGesturePinchAngle, raylibDll, "GetGesturePinchAngle") purego.RegisterLibFunc(&getGesturePinchAngle, raylibDll, "GetGesturePinchAngle")
purego.RegisterLibFunc(&setShapesTexture, raylibDll, "SetShapesTexture") purego.RegisterLibFunc(&setShapesTexture, raylibDll, "SetShapesTexture")
purego.RegisterLibFunc(&getShapesTexture, raylibDll, "GetShapesTexture")
purego.RegisterLibFunc(&getShapesTextureRectangle, raylibDll, "GetShapesTextureRectangle")
purego.RegisterLibFunc(&drawPixel, raylibDll, "DrawPixel") purego.RegisterLibFunc(&drawPixel, raylibDll, "DrawPixel")
purego.RegisterLibFunc(&drawPixelV, raylibDll, "DrawPixelV") purego.RegisterLibFunc(&drawPixelV, raylibDll, "DrawPixelV")
purego.RegisterLibFunc(&drawLine, raylibDll, "DrawLine") purego.RegisterLibFunc(&drawLine, raylibDll, "DrawLine")
@ -712,6 +736,7 @@ func init() {
purego.RegisterLibFunc(&drawRectangleLinesEx, raylibDll, "DrawRectangleLinesEx") purego.RegisterLibFunc(&drawRectangleLinesEx, raylibDll, "DrawRectangleLinesEx")
purego.RegisterLibFunc(&drawRectangleRounded, raylibDll, "DrawRectangleRounded") purego.RegisterLibFunc(&drawRectangleRounded, raylibDll, "DrawRectangleRounded")
purego.RegisterLibFunc(&drawRectangleRoundedLines, raylibDll, "DrawRectangleRoundedLines") purego.RegisterLibFunc(&drawRectangleRoundedLines, raylibDll, "DrawRectangleRoundedLines")
purego.RegisterLibFunc(&drawRectangleRoundedLinesEx, raylibDll, "DrawRectangleRoundedLinesEx")
purego.RegisterLibFunc(&drawTriangle, raylibDll, "DrawTriangle") purego.RegisterLibFunc(&drawTriangle, raylibDll, "DrawTriangle")
purego.RegisterLibFunc(&drawTriangleLines, raylibDll, "DrawTriangleLines") purego.RegisterLibFunc(&drawTriangleLines, raylibDll, "DrawTriangleLines")
purego.RegisterLibFunc(&drawTriangleFan, raylibDll, "DrawTriangleFan") purego.RegisterLibFunc(&drawTriangleFan, raylibDll, "DrawTriangleFan")
@ -737,6 +762,7 @@ func init() {
purego.RegisterLibFunc(&checkCollisionRecs, raylibDll, "CheckCollisionRecs") purego.RegisterLibFunc(&checkCollisionRecs, raylibDll, "CheckCollisionRecs")
purego.RegisterLibFunc(&checkCollisionCircles, raylibDll, "CheckCollisionCircles") purego.RegisterLibFunc(&checkCollisionCircles, raylibDll, "CheckCollisionCircles")
purego.RegisterLibFunc(&checkCollisionCircleRec, raylibDll, "CheckCollisionCircleRec") purego.RegisterLibFunc(&checkCollisionCircleRec, raylibDll, "CheckCollisionCircleRec")
purego.RegisterLibFunc(&checkCollisionCircleLine, raylibDll, "CheckCollisionCircleLine")
purego.RegisterLibFunc(&checkCollisionPointRec, raylibDll, "CheckCollisionPointRec") purego.RegisterLibFunc(&checkCollisionPointRec, raylibDll, "CheckCollisionPointRec")
purego.RegisterLibFunc(&checkCollisionPointCircle, raylibDll, "CheckCollisionPointCircle") purego.RegisterLibFunc(&checkCollisionPointCircle, raylibDll, "CheckCollisionPointCircle")
purego.RegisterLibFunc(&checkCollisionPointTriangle, raylibDll, "CheckCollisionPointTriangle") purego.RegisterLibFunc(&checkCollisionPointTriangle, raylibDll, "CheckCollisionPointTriangle")
@ -746,12 +772,12 @@ func init() {
purego.RegisterLibFunc(&getCollisionRec, raylibDll, "GetCollisionRec") purego.RegisterLibFunc(&getCollisionRec, raylibDll, "GetCollisionRec")
purego.RegisterLibFunc(&loadImage, raylibDll, "LoadImage") purego.RegisterLibFunc(&loadImage, raylibDll, "LoadImage")
purego.RegisterLibFunc(&loadImageRaw, raylibDll, "LoadImageRaw") purego.RegisterLibFunc(&loadImageRaw, raylibDll, "LoadImageRaw")
purego.RegisterLibFunc(&loadImageSvg, raylibDll, "LoadImageSvg")
purego.RegisterLibFunc(&loadImageAnim, raylibDll, "LoadImageAnim") purego.RegisterLibFunc(&loadImageAnim, raylibDll, "LoadImageAnim")
purego.RegisterLibFunc(&loadImageAnimFromMemory, raylibDll, "LoadImageAnimFromMemory")
purego.RegisterLibFunc(&loadImageFromMemory, raylibDll, "LoadImageFromMemory") purego.RegisterLibFunc(&loadImageFromMemory, raylibDll, "LoadImageFromMemory")
purego.RegisterLibFunc(&loadImageFromTexture, raylibDll, "LoadImageFromTexture") purego.RegisterLibFunc(&loadImageFromTexture, raylibDll, "LoadImageFromTexture")
purego.RegisterLibFunc(&loadImageFromScreen, raylibDll, "LoadImageFromScreen") purego.RegisterLibFunc(&loadImageFromScreen, raylibDll, "LoadImageFromScreen")
purego.RegisterLibFunc(&isImageReady, raylibDll, "IsImageReady") purego.RegisterLibFunc(&isImageValid, raylibDll, "IsImageValid")
purego.RegisterLibFunc(&unloadImage, raylibDll, "UnloadImage") purego.RegisterLibFunc(&unloadImage, raylibDll, "UnloadImage")
purego.RegisterLibFunc(&exportImage, raylibDll, "ExportImage") purego.RegisterLibFunc(&exportImage, raylibDll, "ExportImage")
purego.RegisterLibFunc(&exportImageToMemory, raylibDll, "ExportImageToMemory") purego.RegisterLibFunc(&exportImageToMemory, raylibDll, "ExportImageToMemory")
@ -766,6 +792,7 @@ func init() {
purego.RegisterLibFunc(&genImageText, raylibDll, "GenImageText") purego.RegisterLibFunc(&genImageText, raylibDll, "GenImageText")
purego.RegisterLibFunc(&imageCopy, raylibDll, "ImageCopy") purego.RegisterLibFunc(&imageCopy, raylibDll, "ImageCopy")
purego.RegisterLibFunc(&imageFromImage, raylibDll, "ImageFromImage") purego.RegisterLibFunc(&imageFromImage, raylibDll, "ImageFromImage")
purego.RegisterLibFunc(&imageFromChannel, raylibDll, "ImageFromChannel")
purego.RegisterLibFunc(&imageText, raylibDll, "ImageText") purego.RegisterLibFunc(&imageText, raylibDll, "ImageText")
purego.RegisterLibFunc(&imageTextEx, raylibDll, "ImageTextEx") purego.RegisterLibFunc(&imageTextEx, raylibDll, "ImageTextEx")
purego.RegisterLibFunc(&imageFormat, raylibDll, "ImageFormat") purego.RegisterLibFunc(&imageFormat, raylibDll, "ImageFormat")
@ -776,6 +803,7 @@ func init() {
purego.RegisterLibFunc(&imageAlphaMask, raylibDll, "ImageAlphaMask") purego.RegisterLibFunc(&imageAlphaMask, raylibDll, "ImageAlphaMask")
purego.RegisterLibFunc(&imageAlphaPremultiply, raylibDll, "ImageAlphaPremultiply") purego.RegisterLibFunc(&imageAlphaPremultiply, raylibDll, "ImageAlphaPremultiply")
purego.RegisterLibFunc(&imageBlurGaussian, raylibDll, "ImageBlurGaussian") purego.RegisterLibFunc(&imageBlurGaussian, raylibDll, "ImageBlurGaussian")
purego.RegisterLibFunc(&imageKernelConvolution, raylibDll, "ImageKernelConvolution")
purego.RegisterLibFunc(&imageResize, raylibDll, "ImageResize") purego.RegisterLibFunc(&imageResize, raylibDll, "ImageResize")
purego.RegisterLibFunc(&imageResizeNN, raylibDll, "ImageResizeNN") purego.RegisterLibFunc(&imageResizeNN, raylibDll, "ImageResizeNN")
purego.RegisterLibFunc(&imageResizeCanvas, raylibDll, "ImageResizeCanvas") purego.RegisterLibFunc(&imageResizeCanvas, raylibDll, "ImageResizeCanvas")
@ -803,6 +831,7 @@ func init() {
purego.RegisterLibFunc(&imageDrawPixelV, raylibDll, "ImageDrawPixelV") purego.RegisterLibFunc(&imageDrawPixelV, raylibDll, "ImageDrawPixelV")
purego.RegisterLibFunc(&imageDrawLine, raylibDll, "ImageDrawLine") purego.RegisterLibFunc(&imageDrawLine, raylibDll, "ImageDrawLine")
purego.RegisterLibFunc(&imageDrawLineV, raylibDll, "ImageDrawLineV") purego.RegisterLibFunc(&imageDrawLineV, raylibDll, "ImageDrawLineV")
purego.RegisterLibFunc(&imageDrawLineEx, raylibDll, "ImageDrawLineEx")
purego.RegisterLibFunc(&imageDrawCircle, raylibDll, "ImageDrawCircle") purego.RegisterLibFunc(&imageDrawCircle, raylibDll, "ImageDrawCircle")
purego.RegisterLibFunc(&imageDrawCircleV, raylibDll, "ImageDrawCircleV") purego.RegisterLibFunc(&imageDrawCircleV, raylibDll, "ImageDrawCircleV")
purego.RegisterLibFunc(&imageDrawCircleLines, raylibDll, "ImageDrawCircleLines") purego.RegisterLibFunc(&imageDrawCircleLines, raylibDll, "ImageDrawCircleLines")
@ -811,6 +840,11 @@ func init() {
purego.RegisterLibFunc(&imageDrawRectangleV, raylibDll, "ImageDrawRectangleV") purego.RegisterLibFunc(&imageDrawRectangleV, raylibDll, "ImageDrawRectangleV")
purego.RegisterLibFunc(&imageDrawRectangleRec, raylibDll, "ImageDrawRectangleRec") purego.RegisterLibFunc(&imageDrawRectangleRec, raylibDll, "ImageDrawRectangleRec")
purego.RegisterLibFunc(&imageDrawRectangleLines, raylibDll, "ImageDrawRectangleLines") purego.RegisterLibFunc(&imageDrawRectangleLines, raylibDll, "ImageDrawRectangleLines")
purego.RegisterLibFunc(&imageDrawTriangle, raylibDll, "ImageDrawTriangle")
purego.RegisterLibFunc(&imageDrawTriangleEx, raylibDll, "ImageDrawTriangleEx")
purego.RegisterLibFunc(&imageDrawTriangleLines, raylibDll, "ImageDrawTriangleLines")
purego.RegisterLibFunc(&imageDrawTriangleFan, raylibDll, "ImageDrawTriangleFan")
purego.RegisterLibFunc(&imageDrawTriangleStrip, raylibDll, "ImageDrawTriangleStrip")
purego.RegisterLibFunc(&imageDraw, raylibDll, "ImageDraw") purego.RegisterLibFunc(&imageDraw, raylibDll, "ImageDraw")
purego.RegisterLibFunc(&imageDrawText, raylibDll, "ImageDrawText") purego.RegisterLibFunc(&imageDrawText, raylibDll, "ImageDrawText")
purego.RegisterLibFunc(&imageDrawTextEx, raylibDll, "ImageDrawTextEx") purego.RegisterLibFunc(&imageDrawTextEx, raylibDll, "ImageDrawTextEx")
@ -818,9 +852,9 @@ func init() {
purego.RegisterLibFunc(&loadTextureFromImage, raylibDll, "LoadTextureFromImage") purego.RegisterLibFunc(&loadTextureFromImage, raylibDll, "LoadTextureFromImage")
purego.RegisterLibFunc(&loadTextureCubemap, raylibDll, "LoadTextureCubemap") purego.RegisterLibFunc(&loadTextureCubemap, raylibDll, "LoadTextureCubemap")
purego.RegisterLibFunc(&loadRenderTexture, raylibDll, "LoadRenderTexture") purego.RegisterLibFunc(&loadRenderTexture, raylibDll, "LoadRenderTexture")
purego.RegisterLibFunc(&isTextureReady, raylibDll, "IsTextureReady") purego.RegisterLibFunc(&isTextureValid, raylibDll, "IsTextureValid")
purego.RegisterLibFunc(&unloadTexture, raylibDll, "UnloadTexture") purego.RegisterLibFunc(&unloadTexture, raylibDll, "UnloadTexture")
purego.RegisterLibFunc(&isRenderTextureReady, raylibDll, "IsRenderTextureReady") purego.RegisterLibFunc(&isRenderTextureValid, raylibDll, "IsRenderTextureValid")
purego.RegisterLibFunc(&unloadRenderTexture, raylibDll, "UnloadRenderTexture") purego.RegisterLibFunc(&unloadRenderTexture, raylibDll, "UnloadRenderTexture")
purego.RegisterLibFunc(&updateTexture, raylibDll, "UpdateTexture") purego.RegisterLibFunc(&updateTexture, raylibDll, "UpdateTexture")
purego.RegisterLibFunc(&updateTextureRec, raylibDll, "UpdateTextureRec") purego.RegisterLibFunc(&updateTextureRec, raylibDll, "UpdateTextureRec")
@ -844,6 +878,7 @@ func init() {
purego.RegisterLibFunc(&colorContrast, raylibDll, "ColorContrast") purego.RegisterLibFunc(&colorContrast, raylibDll, "ColorContrast")
purego.RegisterLibFunc(&colorAlpha, raylibDll, "ColorAlpha") purego.RegisterLibFunc(&colorAlpha, raylibDll, "ColorAlpha")
purego.RegisterLibFunc(&colorAlphaBlend, raylibDll, "ColorAlphaBlend") purego.RegisterLibFunc(&colorAlphaBlend, raylibDll, "ColorAlphaBlend")
purego.RegisterLibFunc(&colorLerp, raylibDll, "ColorLerp")
purego.RegisterLibFunc(&getColor, raylibDll, "GetColor") purego.RegisterLibFunc(&getColor, raylibDll, "GetColor")
purego.RegisterLibFunc(&getPixelColor, raylibDll, "GetPixelColor") purego.RegisterLibFunc(&getPixelColor, raylibDll, "GetPixelColor")
purego.RegisterLibFunc(&setPixelColor, raylibDll, "SetPixelColor") purego.RegisterLibFunc(&setPixelColor, raylibDll, "SetPixelColor")
@ -853,7 +888,7 @@ func init() {
purego.RegisterLibFunc(&loadFontEx, raylibDll, "LoadFontEx") purego.RegisterLibFunc(&loadFontEx, raylibDll, "LoadFontEx")
purego.RegisterLibFunc(&loadFontFromImage, raylibDll, "LoadFontFromImage") purego.RegisterLibFunc(&loadFontFromImage, raylibDll, "LoadFontFromImage")
purego.RegisterLibFunc(&loadFontFromMemory, raylibDll, "LoadFontFromMemory") purego.RegisterLibFunc(&loadFontFromMemory, raylibDll, "LoadFontFromMemory")
purego.RegisterLibFunc(&isFontReady, raylibDll, "IsFontReady") purego.RegisterLibFunc(&isFontValid, raylibDll, "IsFontValid")
purego.RegisterLibFunc(&loadFontData, raylibDll, "LoadFontData") purego.RegisterLibFunc(&loadFontData, raylibDll, "LoadFontData")
purego.RegisterLibFunc(&genImageFontAtlas, raylibDll, "GenImageFontAtlas") purego.RegisterLibFunc(&genImageFontAtlas, raylibDll, "GenImageFontAtlas")
purego.RegisterLibFunc(&unloadFontData, raylibDll, "UnloadFontData") purego.RegisterLibFunc(&unloadFontData, raylibDll, "UnloadFontData")
@ -893,13 +928,15 @@ func init() {
purego.RegisterLibFunc(&drawGrid, raylibDll, "DrawGrid") purego.RegisterLibFunc(&drawGrid, raylibDll, "DrawGrid")
purego.RegisterLibFunc(&loadModel, raylibDll, "LoadModel") purego.RegisterLibFunc(&loadModel, raylibDll, "LoadModel")
purego.RegisterLibFunc(&loadModelFromMesh, raylibDll, "LoadModelFromMesh") purego.RegisterLibFunc(&loadModelFromMesh, raylibDll, "LoadModelFromMesh")
purego.RegisterLibFunc(&isModelReady, raylibDll, "IsModelReady") purego.RegisterLibFunc(&isModelValid, raylibDll, "IsModelValid")
purego.RegisterLibFunc(&unloadModel, raylibDll, "UnloadModel") purego.RegisterLibFunc(&unloadModel, raylibDll, "UnloadModel")
purego.RegisterLibFunc(&getModelBoundingBox, raylibDll, "GetModelBoundingBox") purego.RegisterLibFunc(&getModelBoundingBox, raylibDll, "GetModelBoundingBox")
purego.RegisterLibFunc(&drawModel, raylibDll, "DrawModel") purego.RegisterLibFunc(&drawModel, raylibDll, "DrawModel")
purego.RegisterLibFunc(&drawModelEx, raylibDll, "DrawModelEx") purego.RegisterLibFunc(&drawModelEx, raylibDll, "DrawModelEx")
purego.RegisterLibFunc(&drawModelWires, raylibDll, "DrawModelWires") purego.RegisterLibFunc(&drawModelWires, raylibDll, "DrawModelWires")
purego.RegisterLibFunc(&drawModelWiresEx, raylibDll, "DrawModelWiresEx") purego.RegisterLibFunc(&drawModelWiresEx, raylibDll, "DrawModelWiresEx")
purego.RegisterLibFunc(&drawModelPoints, raylibDll, "DrawModelPoints")
purego.RegisterLibFunc(&drawModelPointsEx, raylibDll, "DrawModelPointsEx")
purego.RegisterLibFunc(&drawBoundingBox, raylibDll, "DrawBoundingBox") purego.RegisterLibFunc(&drawBoundingBox, raylibDll, "DrawBoundingBox")
purego.RegisterLibFunc(&drawBillboard, raylibDll, "DrawBillboard") purego.RegisterLibFunc(&drawBillboard, raylibDll, "DrawBillboard")
purego.RegisterLibFunc(&drawBillboardRec, raylibDll, "DrawBillboardRec") purego.RegisterLibFunc(&drawBillboardRec, raylibDll, "DrawBillboardRec")
@ -925,12 +962,13 @@ func init() {
purego.RegisterLibFunc(&genMeshCubicmap, raylibDll, "GenMeshCubicmap") purego.RegisterLibFunc(&genMeshCubicmap, raylibDll, "GenMeshCubicmap")
purego.RegisterLibFunc(&loadMaterials, raylibDll, "LoadMaterials") purego.RegisterLibFunc(&loadMaterials, raylibDll, "LoadMaterials")
purego.RegisterLibFunc(&loadMaterialDefault, raylibDll, "LoadMaterialDefault") purego.RegisterLibFunc(&loadMaterialDefault, raylibDll, "LoadMaterialDefault")
purego.RegisterLibFunc(&isMaterialReady, raylibDll, "IsMaterialReady") purego.RegisterLibFunc(&isMaterialValid, raylibDll, "IsMaterialValid")
purego.RegisterLibFunc(&unloadMaterial, raylibDll, "UnloadMaterial") purego.RegisterLibFunc(&unloadMaterial, raylibDll, "UnloadMaterial")
purego.RegisterLibFunc(&setMaterialTexture, raylibDll, "SetMaterialTexture") purego.RegisterLibFunc(&setMaterialTexture, raylibDll, "SetMaterialTexture")
purego.RegisterLibFunc(&setModelMeshMaterial, raylibDll, "SetModelMeshMaterial") purego.RegisterLibFunc(&setModelMeshMaterial, raylibDll, "SetModelMeshMaterial")
purego.RegisterLibFunc(&loadModelAnimations, raylibDll, "LoadModelAnimations") purego.RegisterLibFunc(&loadModelAnimations, raylibDll, "LoadModelAnimations")
purego.RegisterLibFunc(&updateModelAnimation, raylibDll, "UpdateModelAnimation") purego.RegisterLibFunc(&updateModelAnimation, raylibDll, "UpdateModelAnimation")
purego.RegisterLibFunc(&updateModelAnimationBones, raylibDll, "UpdateModelAnimationBones")
purego.RegisterLibFunc(&unloadModelAnimation, raylibDll, "UnloadModelAnimation") purego.RegisterLibFunc(&unloadModelAnimation, raylibDll, "UnloadModelAnimation")
purego.RegisterLibFunc(&unloadModelAnimations, raylibDll, "UnloadModelAnimations") purego.RegisterLibFunc(&unloadModelAnimations, raylibDll, "UnloadModelAnimations")
purego.RegisterLibFunc(&isModelAnimationValid, raylibDll, "IsModelAnimationValid") purego.RegisterLibFunc(&isModelAnimationValid, raylibDll, "IsModelAnimationValid")
@ -949,11 +987,11 @@ func init() {
purego.RegisterLibFunc(&getMasterVolume, raylibDll, "GetMasterVolume") purego.RegisterLibFunc(&getMasterVolume, raylibDll, "GetMasterVolume")
purego.RegisterLibFunc(&loadWave, raylibDll, "LoadWave") purego.RegisterLibFunc(&loadWave, raylibDll, "LoadWave")
purego.RegisterLibFunc(&loadWaveFromMemory, raylibDll, "LoadWaveFromMemory") purego.RegisterLibFunc(&loadWaveFromMemory, raylibDll, "LoadWaveFromMemory")
purego.RegisterLibFunc(&isWaveReady, raylibDll, "IsWaveReady") purego.RegisterLibFunc(&isWaveValid, raylibDll, "IsWaveValid")
purego.RegisterLibFunc(&loadSound, raylibDll, "LoadSound") purego.RegisterLibFunc(&loadSound, raylibDll, "LoadSound")
purego.RegisterLibFunc(&loadSoundFromWave, raylibDll, "LoadSoundFromWave") purego.RegisterLibFunc(&loadSoundFromWave, raylibDll, "LoadSoundFromWave")
purego.RegisterLibFunc(&loadSoundAlias, raylibDll, "LoadSoundAlias") purego.RegisterLibFunc(&loadSoundAlias, raylibDll, "LoadSoundAlias")
purego.RegisterLibFunc(&isSoundReady, raylibDll, "IsSoundReady") purego.RegisterLibFunc(&isSoundValid, raylibDll, "IsSoundValid")
purego.RegisterLibFunc(&updateSound, raylibDll, "UpdateSound") purego.RegisterLibFunc(&updateSound, raylibDll, "UpdateSound")
purego.RegisterLibFunc(&unloadWave, raylibDll, "UnloadWave") purego.RegisterLibFunc(&unloadWave, raylibDll, "UnloadWave")
purego.RegisterLibFunc(&unloadSound, raylibDll, "UnloadSound") purego.RegisterLibFunc(&unloadSound, raylibDll, "UnloadSound")
@ -974,7 +1012,7 @@ func init() {
purego.RegisterLibFunc(&unloadWaveSamples, raylibDll, "UnloadWaveSamples") purego.RegisterLibFunc(&unloadWaveSamples, raylibDll, "UnloadWaveSamples")
purego.RegisterLibFunc(&loadMusicStream, raylibDll, "LoadMusicStream") purego.RegisterLibFunc(&loadMusicStream, raylibDll, "LoadMusicStream")
purego.RegisterLibFunc(&loadMusicStreamFromMemory, raylibDll, "LoadMusicStreamFromMemory") purego.RegisterLibFunc(&loadMusicStreamFromMemory, raylibDll, "LoadMusicStreamFromMemory")
purego.RegisterLibFunc(&isMusicReady, raylibDll, "IsMusicReady") purego.RegisterLibFunc(&isMusicValid, raylibDll, "IsMusicValid")
purego.RegisterLibFunc(&unloadMusicStream, raylibDll, "UnloadMusicStream") purego.RegisterLibFunc(&unloadMusicStream, raylibDll, "UnloadMusicStream")
purego.RegisterLibFunc(&playMusicStream, raylibDll, "PlayMusicStream") purego.RegisterLibFunc(&playMusicStream, raylibDll, "PlayMusicStream")
purego.RegisterLibFunc(&isMusicStreamPlaying, raylibDll, "IsMusicStreamPlaying") purego.RegisterLibFunc(&isMusicStreamPlaying, raylibDll, "IsMusicStreamPlaying")
@ -989,7 +1027,7 @@ func init() {
purego.RegisterLibFunc(&getMusicTimeLength, raylibDll, "GetMusicTimeLength") purego.RegisterLibFunc(&getMusicTimeLength, raylibDll, "GetMusicTimeLength")
purego.RegisterLibFunc(&getMusicTimePlayed, raylibDll, "GetMusicTimePlayed") purego.RegisterLibFunc(&getMusicTimePlayed, raylibDll, "GetMusicTimePlayed")
purego.RegisterLibFunc(&loadAudioStream, raylibDll, "LoadAudioStream") purego.RegisterLibFunc(&loadAudioStream, raylibDll, "LoadAudioStream")
purego.RegisterLibFunc(&isAudioStreamReady, raylibDll, "IsAudioStreamReady") purego.RegisterLibFunc(&isAudioStreamValid, raylibDll, "IsAudioStreamValid")
purego.RegisterLibFunc(&unloadAudioStream, raylibDll, "UnloadAudioStream") purego.RegisterLibFunc(&unloadAudioStream, raylibDll, "UnloadAudioStream")
purego.RegisterLibFunc(&updateAudioStream, raylibDll, "UpdateAudioStream") purego.RegisterLibFunc(&updateAudioStream, raylibDll, "UpdateAudioStream")
purego.RegisterLibFunc(&isAudioStreamProcessed, raylibDll, "IsAudioStreamProcessed") purego.RegisterLibFunc(&isAudioStreamProcessed, raylibDll, "IsAudioStreamProcessed")
@ -1179,7 +1217,7 @@ func GetMonitorCount() int {
return int(getMonitorCount()) return int(getMonitorCount())
} }
// GetCurrentMonitor - Get current connected monitor // GetCurrentMonitor - Get current monitor where window is placed
func GetCurrentMonitor() int { func GetCurrentMonitor() int {
return int(getCurrentMonitor()) return int(getCurrentMonitor())
} }
@ -1242,6 +1280,15 @@ func GetClipboardText() string {
return getClipboardText() return getClipboardText()
} }
// GetClipboardImage - Get clipboard image content
//
// Only works with SDL3 backend or Windows with RGFW/GLFW
func GetClipboardImage() Image {
var img Image
getClipboardImage(uintptr(unsafe.Pointer(&img)))
return img
}
// EnableEventWaiting - Enable waiting for events on EndDrawing(), no automatic event polling // EnableEventWaiting - Enable waiting for events on EndDrawing(), no automatic event polling
func EnableEventWaiting() { func EnableEventWaiting() {
enableEventWaiting() enableEventWaiting()
@ -1423,9 +1470,9 @@ func LoadShaderFromMemory(vsCode string, fsCode string) Shader {
return shader return shader
} }
// IsShaderReady - Check if a shader is ready // IsShaderValid - Check if a shader is valid (loaded on GPU)
func IsShaderReady(shader Shader) bool { func IsShaderValid(shader Shader) bool {
return isShaderReady(uintptr(unsafe.Pointer(&shader))) return isShaderValid(uintptr(unsafe.Pointer(&shader)))
} }
// GetShaderLocation - Get shader uniform location // GetShaderLocation - Get shader uniform location
@ -1464,9 +1511,23 @@ func UnloadShader(shader Shader) {
} }
// GetMouseRay - Get a ray trace from mouse position // GetMouseRay - Get a ray trace from mouse position
//
// Deprecated: Use [GetScreenToWorldRay] instead.
func GetMouseRay(mousePosition Vector2, camera Camera) Ray { func GetMouseRay(mousePosition Vector2, camera Camera) Ray {
return GetScreenToWorldRay(mousePosition, camera)
}
// GetScreenToWorldRay - Get a ray trace from screen position (i.e mouse)
func GetScreenToWorldRay(position Vector2, camera Camera) Ray {
var ray Ray var ray Ray
getMouseRay(uintptr(unsafe.Pointer(&ray)), *(*uintptr)(unsafe.Pointer(&mousePosition)), uintptr(unsafe.Pointer(&camera))) getScreenToWorldRay(uintptr(unsafe.Pointer(&ray)), *(*uintptr)(unsafe.Pointer(&position)), uintptr(unsafe.Pointer(&camera)))
return ray
}
// GetScreenToWorldRayEx - Get a ray trace from screen position (i.e mouse) in a viewport
func GetScreenToWorldRayEx(position Vector2, camera Camera, width, height int32) Ray {
var ray Ray
getScreenToWorldRayEx(uintptr(unsafe.Pointer(&ray)), *(*uintptr)(unsafe.Pointer(&position)), uintptr(unsafe.Pointer(&camera)), width, height)
return ray return ray
} }
@ -1791,6 +1852,11 @@ func SetGamepadMappings(mappings string) int32 {
return setGamepadMappings(mappings) return setGamepadMappings(mappings)
} }
// SetGamepadVibration - Set gamepad vibration for both motors (duration in seconds)
func SetGamepadVibration(gamepad int32, leftMotor, rightMotor, duration float32) {
setGamepadVibration(gamepad, leftMotor, rightMotor, duration)
}
// IsMouseButtonPressed - Check if a mouse button has been pressed once // IsMouseButtonPressed - Check if a mouse button has been pressed once
func IsMouseButtonPressed(button MouseButton) bool { func IsMouseButtonPressed(button MouseButton) bool {
return isMouseButtonPressed(int32(button)) return isMouseButtonPressed(int32(button))
@ -1937,6 +2003,20 @@ func SetShapesTexture(texture Texture2D, source Rectangle) {
setShapesTexture(uintptr(unsafe.Pointer(&texture)), uintptr(unsafe.Pointer(&source))) setShapesTexture(uintptr(unsafe.Pointer(&texture)), uintptr(unsafe.Pointer(&source)))
} }
// GetShapesTexture - Get texture that is used for shapes drawing
func GetShapesTexture() Texture2D {
var texture Texture2D
getShapesTexture(uintptr(unsafe.Pointer(&texture)))
return texture
}
// GetShapesTextureRectangle - Get texture source rectangle that is used for shapes drawing
func GetShapesTextureRectangle() Rectangle {
var rec Rectangle
getShapesTextureRectangle(uintptr(unsafe.Pointer(&rec)))
return rec
}
// DrawPixel - Draw a pixel // DrawPixel - Draw a pixel
func DrawPixel(posX int32, posY int32, col color.RGBA) { func DrawPixel(posX int32, posY int32, col color.RGBA) {
drawPixel(posX, posY, *(*uintptr)(unsafe.Pointer(&col))) drawPixel(posX, posY, *(*uintptr)(unsafe.Pointer(&col)))
@ -1989,8 +2069,8 @@ func DrawCircleSectorLines(center Vector2, radius float32, startAngle float32, e
} }
// DrawCircleGradient - Draw a gradient-filled circle // DrawCircleGradient - Draw a gradient-filled circle
func DrawCircleGradient(centerX int32, centerY int32, radius float32, color1 color.RGBA, color2 color.RGBA) { func DrawCircleGradient(centerX int32, centerY int32, radius float32, inner color.RGBA, outer color.RGBA) {
drawCircleGradient(centerX, centerY, radius, *(*uintptr)(unsafe.Pointer(&color1)), *(*uintptr)(unsafe.Pointer(&color2))) drawCircleGradient(centerX, centerY, radius, *(*uintptr)(unsafe.Pointer(&inner)), *(*uintptr)(unsafe.Pointer(&outer)))
} }
// DrawCircleV - Draw a color-filled circle (Vector version) // DrawCircleV - Draw a color-filled circle (Vector version)
@ -2049,18 +2129,18 @@ func DrawRectanglePro(rec Rectangle, origin Vector2, rotation float32, col color
} }
// DrawRectangleGradientV - Draw a vertical-gradient-filled rectangle // DrawRectangleGradientV - Draw a vertical-gradient-filled rectangle
func DrawRectangleGradientV(posX int32, posY int32, width int32, height int32, color1 color.RGBA, color2 color.RGBA) { func DrawRectangleGradientV(posX int32, posY int32, width int32, height int32, top color.RGBA, bottom color.RGBA) {
drawRectangleGradientV(posX, posY, width, height, *(*uintptr)(unsafe.Pointer(&color1)), *(*uintptr)(unsafe.Pointer(&color2))) drawRectangleGradientV(posX, posY, width, height, *(*uintptr)(unsafe.Pointer(&top)), *(*uintptr)(unsafe.Pointer(&bottom)))
} }
// DrawRectangleGradientH - Draw a horizontal-gradient-filled rectangle // DrawRectangleGradientH - Draw a horizontal-gradient-filled rectangle
func DrawRectangleGradientH(posX int32, posY int32, width int32, height int32, color1 color.RGBA, color2 color.RGBA) { func DrawRectangleGradientH(posX int32, posY int32, width int32, height int32, left color.RGBA, right color.RGBA) {
drawRectangleGradientH(posX, posY, width, height, *(*uintptr)(unsafe.Pointer(&color1)), *(*uintptr)(unsafe.Pointer(&color2))) drawRectangleGradientH(posX, posY, width, height, *(*uintptr)(unsafe.Pointer(&left)), *(*uintptr)(unsafe.Pointer(&right)))
} }
// DrawRectangleGradientEx - Draw a gradient-filled rectangle with custom vertex colors // DrawRectangleGradientEx - Draw a gradient-filled rectangle with custom vertex colors
func DrawRectangleGradientEx(rec Rectangle, col1 color.RGBA, col2 color.RGBA, col3 color.RGBA, col4 color.RGBA) { func DrawRectangleGradientEx(rec Rectangle, topLeft color.RGBA, bottomLeft color.RGBA, topRight color.RGBA, bottomRight color.RGBA) {
drawRectangleGradientEx(uintptr(unsafe.Pointer(&rec)), *(*uintptr)(unsafe.Pointer(&col1)), *(*uintptr)(unsafe.Pointer(&col2)), *(*uintptr)(unsafe.Pointer(&col3)), *(*uintptr)(unsafe.Pointer(&col4))) drawRectangleGradientEx(uintptr(unsafe.Pointer(&rec)), *(*uintptr)(unsafe.Pointer(&topLeft)), *(*uintptr)(unsafe.Pointer(&bottomLeft)), *(*uintptr)(unsafe.Pointer(&topRight)), *(*uintptr)(unsafe.Pointer(&bottomRight)))
} }
// DrawRectangleLines - Draw rectangle outline // DrawRectangleLines - Draw rectangle outline
@ -2078,9 +2158,14 @@ func DrawRectangleRounded(rec Rectangle, roundness float32, segments int32, col
drawRectangleRounded(uintptr(unsafe.Pointer(&rec)), roundness, segments, *(*uintptr)(unsafe.Pointer(&col))) drawRectangleRounded(uintptr(unsafe.Pointer(&rec)), roundness, segments, *(*uintptr)(unsafe.Pointer(&col)))
} }
// DrawRectangleRoundedLines - Draw rectangle with rounded edges outline // DrawRectangleRoundedLines - Draw rectangle lines with rounded edges
func DrawRectangleRoundedLines(rec Rectangle, roundness float32, segments float32, lineThick float32, col color.RGBA) { func DrawRectangleRoundedLines(rec Rectangle, roundness float32, segments int32, col color.RGBA) {
drawRectangleRoundedLines(uintptr(unsafe.Pointer(&rec)), roundness, int32(segments), lineThick, *(*uintptr)(unsafe.Pointer(&col))) drawRectangleRoundedLines(uintptr(unsafe.Pointer(&rec)), roundness, segments, *(*uintptr)(unsafe.Pointer(&col)))
}
// DrawRectangleRoundedLinesEx - Draw rectangle with rounded edges outline
func DrawRectangleRoundedLinesEx(rec Rectangle, roundness float32, segments int32, lineThick float32, col color.RGBA) {
drawRectangleRoundedLinesEx(uintptr(unsafe.Pointer(&rec)), roundness, segments, lineThick, *(*uintptr)(unsafe.Pointer(&col)))
} }
// DrawTriangle - Draw a color-filled triangle (vertex in counter-clockwise order!) // DrawTriangle - Draw a color-filled triangle (vertex in counter-clockwise order!)
@ -2220,6 +2305,11 @@ func CheckCollisionCircleRec(center Vector2, radius float32, rec Rectangle) bool
return checkCollisionCircleRec(*(*uintptr)(unsafe.Pointer(&center)), radius, uintptr(unsafe.Pointer(&rec))) return checkCollisionCircleRec(*(*uintptr)(unsafe.Pointer(&center)), radius, uintptr(unsafe.Pointer(&rec)))
} }
// CheckCollisionCircleLine - Check if circle collides with a line created betweeen two points [p1] and [p2]
func CheckCollisionCircleLine(center Vector2, radius float32, p1, p2 Vector2) bool {
return checkCollisionCircleLine(*(*uintptr)(unsafe.Pointer(&center)), radius, *(*uintptr)(unsafe.Pointer(&p1)), *(*uintptr)(unsafe.Pointer(&p2)))
}
// CheckCollisionPointRec - Check if point is inside rectangle // CheckCollisionPointRec - Check if point is inside rectangle
func CheckCollisionPointRec(point Vector2, rec Rectangle) bool { func CheckCollisionPointRec(point Vector2, rec Rectangle) bool {
return checkCollisionPointRec(*(*uintptr)(unsafe.Pointer(&point)), uintptr(unsafe.Pointer(&rec))) return checkCollisionPointRec(*(*uintptr)(unsafe.Pointer(&point)), uintptr(unsafe.Pointer(&rec)))
@ -2272,17 +2362,17 @@ func LoadImageRaw(fileName string, width int32, height int32, format PixelFormat
return &img return &img
} }
// LoadImageSvg - Load image from SVG file data or string with specified size // LoadImageAnim - Load image sequence from file (frames appended to image.data)
func LoadImageSvg(fileNameOrString string, width int32, height int32) *Image { func LoadImageAnim(fileName string, frames *int32) *Image {
var img Image var img Image
loadImageSvg(uintptr(unsafe.Pointer(&img)), fileNameOrString, width, height) loadImageAnim(uintptr(unsafe.Pointer(&img)), fileName, frames)
return &img return &img
} }
// LoadImageAnim - Load image sequence from file (frames appended to image.data) // LoadImageAnimFromMemory - Load image sequence from memory buffer
func LoadImageAnim(fileName string, frames []int32) *Image { func LoadImageAnimFromMemory(fileType string, fileData []byte, dataSize int32, frames *int32) *Image {
var img Image var img Image
loadImageAnim(uintptr(unsafe.Pointer(&img)), fileName, frames) loadImageAnimFromMemory(uintptr(unsafe.Pointer(&img)), fileType, fileData, dataSize, frames)
return &img return &img
} }
@ -2307,9 +2397,9 @@ func LoadImageFromScreen() *Image {
return &img return &img
} }
// IsImageReady - Check if an image is ready // IsImageValid - Check if an image is valid (data and parameters)
func IsImageReady(image *Image) bool { func IsImageValid(image *Image) bool {
return isImageReady(uintptr(unsafe.Pointer(image))) return isImageValid(uintptr(unsafe.Pointer(image)))
} }
// UnloadImage - Unload image from CPU memory (RAM) // UnloadImage - Unload image from CPU memory (RAM)
@ -2406,6 +2496,13 @@ func ImageFromImage(image Image, rec Rectangle) Image {
return retImage return retImage
} }
// ImageFromChannel - Create an image from a selected channel of another image (GRAYSCALE)
func ImageFromChannel(image Image, selectedChannel int32) Image {
var retImage Image
imageFromChannel(uintptr(unsafe.Pointer(&retImage)), uintptr(unsafe.Pointer(&image)), selectedChannel)
return retImage
}
// ImageText - Create an image from text (default font) // ImageText - Create an image from text (default font)
func ImageText(text string, fontSize int32, col color.RGBA) Image { func ImageText(text string, fontSize int32, col color.RGBA) Image {
var retImage Image var retImage Image
@ -2460,6 +2557,11 @@ func ImageBlurGaussian(image *Image, blurSize int32) {
imageBlurGaussian(image, blurSize) imageBlurGaussian(image, blurSize)
} }
// ImageKernelConvolution - Apply custom square convolution kernel to image
func ImageKernelConvolution(image *Image, kernel []float32) {
imageKernelConvolution(image, kernel, int32(len(kernel)))
}
// ImageResize - Resize image (Bicubic scaling algorithm) // ImageResize - Resize image (Bicubic scaling algorithm)
func ImageResize(image *Image, newWidth int32, newHeight int32) { func ImageResize(image *Image, newWidth int32, newHeight int32) {
imageResize(image, newWidth, newHeight) imageResize(image, newWidth, newHeight)
@ -2601,10 +2703,15 @@ func ImageDrawLine(dst *Image, startPosX int32, startPosY int32, endPosX int32,
} }
// ImageDrawLineV - Draw line within an image (Vector version) // ImageDrawLineV - Draw line within an image (Vector version)
func ImageDrawLineV(dst *Image, start Vector2, end Vector2, col color.RGBA) { func ImageDrawLineV(dst *Image, start, end Vector2, col color.RGBA) {
imageDrawLineV(dst, *(*uintptr)(unsafe.Pointer(&start)), *(*uintptr)(unsafe.Pointer(&end)), *(*uintptr)(unsafe.Pointer(&col))) imageDrawLineV(dst, *(*uintptr)(unsafe.Pointer(&start)), *(*uintptr)(unsafe.Pointer(&end)), *(*uintptr)(unsafe.Pointer(&col)))
} }
// ImageDrawLineEx - Draw a line defining thickness within an image
func ImageDrawLineEx(dst *Image, start, end Vector2, thick int32, col color.RGBA) {
imageDrawLineEx(dst, *(*uintptr)(unsafe.Pointer(&start)), *(*uintptr)(unsafe.Pointer(&end)), thick, *(*uintptr)(unsafe.Pointer(&col)))
}
// ImageDrawCircle - Draw a filled circle within an image // ImageDrawCircle - Draw a filled circle within an image
func ImageDrawCircle(dst *Image, centerX int32, centerY int32, radius int32, col color.RGBA) { func ImageDrawCircle(dst *Image, centerX int32, centerY int32, radius int32, col color.RGBA) {
imageDrawCircle(dst, centerX, centerY, radius, *(*uintptr)(unsafe.Pointer(&col))) imageDrawCircle(dst, centerX, centerY, radius, *(*uintptr)(unsafe.Pointer(&col)))
@ -2645,6 +2752,33 @@ func ImageDrawRectangleLines(dst *Image, rec Rectangle, thick int, col color.RGB
imageDrawRectangleLines(dst, uintptr(unsafe.Pointer(&rec)), int32(thick), *(*uintptr)(unsafe.Pointer(&col))) imageDrawRectangleLines(dst, uintptr(unsafe.Pointer(&rec)), int32(thick), *(*uintptr)(unsafe.Pointer(&col)))
} }
// ImageDrawTriangle - Draw triangle within an image
func ImageDrawTriangle(dst *Image, v1, v2, v3 Vector2, col color.RGBA) {
imageDrawTriangle(dst, *(*uintptr)(unsafe.Pointer(&v1)), *(*uintptr)(unsafe.Pointer(&v2)), *(*uintptr)(unsafe.Pointer(&v3)), *(*uintptr)(unsafe.Pointer(&col)))
}
// ImageDrawTriangleEx - Draw triangle with interpolated colors within an image
func ImageDrawTriangleEx(dst *Image, v1, v2, v3 Vector2, c1, c2, c3 color.RGBA) {
imageDrawTriangleEx(dst, *(*uintptr)(unsafe.Pointer(&v1)), *(*uintptr)(unsafe.Pointer(&v2)), *(*uintptr)(unsafe.Pointer(&v3)), *(*uintptr)(unsafe.Pointer(&c1)), *(*uintptr)(unsafe.Pointer(&c2)), *(*uintptr)(unsafe.Pointer(&c3)))
}
// ImageDrawTriangleLines - Draw triangle outline within an image
func ImageDrawTriangleLines(dst *Image, v1, v2, v3 Vector2, col color.RGBA) {
imageDrawTriangleLines(dst, *(*uintptr)(unsafe.Pointer(&v1)), *(*uintptr)(unsafe.Pointer(&v2)), *(*uintptr)(unsafe.Pointer(&v3)), *(*uintptr)(unsafe.Pointer(&col)))
}
// ImageDrawTriangleFan - Draw a triangle fan defined by points within an image (first vertex is the center)
func ImageDrawTriangleFan(dst *Image, points []Vector2, col color.RGBA) {
pointCount := int32(len(points))
imageDrawTriangleFan(dst, (unsafe.SliceData(points)), pointCount, *(*uintptr)(unsafe.Pointer(&col)))
}
// ImageDrawTriangleStrip - Draw a triangle strip defined by points within an image
func ImageDrawTriangleStrip(dst *Image, points []Vector2, col color.RGBA) {
pointCount := int32(len(points))
imageDrawTriangleStrip(dst, (unsafe.SliceData(points)), pointCount, *(*uintptr)(unsafe.Pointer(&col)))
}
// ImageDraw - Draw a source image within a destination image (tint applied to source) // ImageDraw - Draw a source image within a destination image (tint applied to source)
func ImageDraw(dst *Image, src *Image, srcRec Rectangle, dstRec Rectangle, tint color.RGBA) { func ImageDraw(dst *Image, src *Image, srcRec Rectangle, dstRec Rectangle, tint color.RGBA) {
imageDraw(dst, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(&srcRec)), uintptr(unsafe.Pointer(&dstRec)), *(*uintptr)(unsafe.Pointer(&tint))) imageDraw(dst, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(&srcRec)), uintptr(unsafe.Pointer(&dstRec)), *(*uintptr)(unsafe.Pointer(&tint)))
@ -2689,9 +2823,9 @@ func LoadRenderTexture(width int32, height int32) RenderTexture2D {
return texture return texture
} }
// IsTextureReady - Check if a texture is ready // IsTextureValid - Check if a texture is valid (loaded in GPU)
func IsTextureReady(texture Texture2D) bool { func IsTextureValid(texture Texture2D) bool {
return isTextureReady(uintptr(unsafe.Pointer(&texture))) return isTextureValid(uintptr(unsafe.Pointer(&texture)))
} }
// UnloadTexture - Unload texture from GPU memory (VRAM) // UnloadTexture - Unload texture from GPU memory (VRAM)
@ -2699,9 +2833,9 @@ func UnloadTexture(texture Texture2D) {
unloadTexture(uintptr(unsafe.Pointer(&texture))) unloadTexture(uintptr(unsafe.Pointer(&texture)))
} }
// IsRenderTextureReady - Check if a render texture is ready // IsRenderTextureValid - Check if a render texture is valid (loaded in GPU)
func IsRenderTextureReady(target RenderTexture2D) bool { func IsRenderTextureValid(target RenderTexture2D) bool {
return isRenderTextureReady(uintptr(unsafe.Pointer(&target))) return isRenderTextureValid(uintptr(unsafe.Pointer(&target)))
} }
// UnloadRenderTexture - Unload render texture from GPU memory (VRAM) // UnloadRenderTexture - Unload render texture from GPU memory (VRAM)
@ -2770,7 +2904,7 @@ func Fade(col color.RGBA, alpha float32) color.RGBA {
return *(*color.RGBA)(unsafe.Pointer(&ret)) return *(*color.RGBA)(unsafe.Pointer(&ret))
} }
// ColorToInt - Get hexadecimal value for a Color // ColorToInt - Get hexadecimal value for a Color (0xRRGGBBAA)
func ColorToInt(col color.RGBA) int32 { func ColorToInt(col color.RGBA) int32 {
return colorToInt(*(*uintptr)(unsafe.Pointer(&col))) return colorToInt(*(*uintptr)(unsafe.Pointer(&col)))
} }
@ -2831,6 +2965,12 @@ func ColorAlphaBlend(dst color.RGBA, src color.RGBA, tint color.RGBA) color.RGBA
return *(*color.RGBA)(unsafe.Pointer(&ret)) return *(*color.RGBA)(unsafe.Pointer(&ret))
} }
// ColorLerp - Get color lerp interpolation between two colors, factor [0.0f..1.0f]
func ColorLerp(col1, col2 color.RGBA, factor float32) color.RGBA {
ret := colorLerp(*(*uintptr)(unsafe.Pointer(&col1)), *(*uintptr)(unsafe.Pointer(&col2)), factor)
return *(*color.RGBA)(unsafe.Pointer(&ret))
}
// GetColor - Get Color structure from hexadecimal value // GetColor - Get Color structure from hexadecimal value
func GetColor(hexValue uint) color.RGBA { func GetColor(hexValue uint) color.RGBA {
ret := getColor(uint32(hexValue)) ret := getColor(uint32(hexValue))
@ -2894,9 +3034,9 @@ func LoadFontFromMemory(fileType string, fileData []byte, fontSize int32, codepo
return font return font
} }
// IsFontReady - Check if a font is ready // IsFontValid - Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
func IsFontReady(font Font) bool { func IsFontValid(font Font) bool {
return isFontReady(uintptr(unsafe.Pointer(&font))) return isFontValid(uintptr(unsafe.Pointer(&font)))
} }
// LoadFontData - Load font data for further use // LoadFontData - Load font data for further use
@ -3115,9 +3255,9 @@ func LoadModelFromMesh(mesh Mesh) Model {
return model return model
} }
// IsModelReady - Check if a model is ready // IsModelValid - Check if a model is valid (loaded in GPU, VAO/VBOs)
func IsModelReady(model Model) bool { func IsModelValid(model Model) bool {
return isModelReady(uintptr(unsafe.Pointer(&model))) return isModelValid(uintptr(unsafe.Pointer(&model)))
} }
// UnloadModel - Unload model (including meshes) from memory (RAM and/or VRAM) // UnloadModel - Unload model (including meshes) from memory (RAM and/or VRAM)
@ -3152,14 +3292,24 @@ func DrawModelWiresEx(model Model, position Vector3, rotationAxis Vector3, rotat
drawModelWiresEx(uintptr(unsafe.Pointer(&model)), uintptr(unsafe.Pointer(&position)), uintptr(unsafe.Pointer(&rotationAxis)), rotationAngle, uintptr(unsafe.Pointer(&scale)), *(*uintptr)(unsafe.Pointer(&tint))) drawModelWiresEx(uintptr(unsafe.Pointer(&model)), uintptr(unsafe.Pointer(&position)), uintptr(unsafe.Pointer(&rotationAxis)), rotationAngle, uintptr(unsafe.Pointer(&scale)), *(*uintptr)(unsafe.Pointer(&tint)))
} }
// DrawModelPoints - Draw a model as points
func DrawModelPoints(model Model, position Vector3, scale float32, tint color.RGBA) {
drawModelPoints(uintptr(unsafe.Pointer(&model)), uintptr(unsafe.Pointer(&position)), scale, *(*uintptr)(unsafe.Pointer(&tint)))
}
// DrawModelPointsEx - Draw a model as points with extended parameters
func DrawModelPointsEx(model Model, position Vector3, rotationAxis Vector3, rotationAngle float32, scale Vector3, tint color.RGBA) {
drawModelPointsEx(uintptr(unsafe.Pointer(&model)), uintptr(unsafe.Pointer(&position)), uintptr(unsafe.Pointer(&rotationAxis)), rotationAngle, uintptr(unsafe.Pointer(&scale)), *(*uintptr)(unsafe.Pointer(&tint)))
}
// DrawBoundingBox - Draw bounding box (wires) // DrawBoundingBox - Draw bounding box (wires)
func DrawBoundingBox(box BoundingBox, col color.RGBA) { func DrawBoundingBox(box BoundingBox, col color.RGBA) {
drawBoundingBox(uintptr(unsafe.Pointer(&box)), *(*uintptr)(unsafe.Pointer(&col))) drawBoundingBox(uintptr(unsafe.Pointer(&box)), *(*uintptr)(unsafe.Pointer(&col)))
} }
// DrawBillboard - Draw a billboard texture // DrawBillboard - Draw a billboard texture
func DrawBillboard(camera Camera, texture Texture2D, position Vector3, size float32, tint color.RGBA) { func DrawBillboard(camera Camera, texture Texture2D, position Vector3, scale float32, tint color.RGBA) {
drawBillboard(uintptr(unsafe.Pointer(&camera)), uintptr(unsafe.Pointer(&texture)), uintptr(unsafe.Pointer(&position)), size, *(*uintptr)(unsafe.Pointer(&tint))) drawBillboard(uintptr(unsafe.Pointer(&camera)), uintptr(unsafe.Pointer(&texture)), uintptr(unsafe.Pointer(&position)), scale, *(*uintptr)(unsafe.Pointer(&tint)))
} }
// DrawBillboardRec - Draw a billboard texture defined by source // DrawBillboardRec - Draw a billboard texture defined by source
@ -3306,9 +3456,9 @@ func LoadMaterialDefault() Material {
return material return material
} }
// IsMaterialReady - Check if a material is ready // IsMaterialValid - Check if a material is valid (shader assigned, map textures loaded in GPU)
func IsMaterialReady(material Material) bool { func IsMaterialValid(material Material) bool {
return isMaterialReady(uintptr(unsafe.Pointer(&material))) return isMaterialValid(uintptr(unsafe.Pointer(&material)))
} }
// UnloadMaterial - Unload material from GPU memory (VRAM) // UnloadMaterial - Unload material from GPU memory (VRAM)
@ -3333,11 +3483,16 @@ func LoadModelAnimations(fileName string) []ModelAnimation {
return unsafe.Slice(ret, animCount) return unsafe.Slice(ret, animCount)
} }
// UpdateModelAnimation - Update model animation pose // UpdateModelAnimation - Update model animation pose (CPU)
func UpdateModelAnimation(model Model, anim ModelAnimation, frame int32) { func UpdateModelAnimation(model Model, anim ModelAnimation, frame int32) {
updateModelAnimation(uintptr(unsafe.Pointer(&model)), uintptr(unsafe.Pointer(&anim)), frame) updateModelAnimation(uintptr(unsafe.Pointer(&model)), uintptr(unsafe.Pointer(&anim)), frame)
} }
// UpdateModelAnimationBones - Update model animation mesh bone matrices (GPU skinning)
func UpdateModelAnimationBones(model Model, anim ModelAnimation, frame int32) {
updateModelAnimationBones(uintptr(unsafe.Pointer(&model)), uintptr(unsafe.Pointer(&anim)), frame)
}
// UnloadModelAnimation - Unload animation data // UnloadModelAnimation - Unload animation data
func UnloadModelAnimation(anim ModelAnimation) { func UnloadModelAnimation(anim ModelAnimation) {
unloadModelAnimation(uintptr(unsafe.Pointer(&anim))) unloadModelAnimation(uintptr(unsafe.Pointer(&anim)))
@ -3443,9 +3598,9 @@ func LoadWaveFromMemory(fileType string, fileData []byte, dataSize int32) Wave {
return wave return wave
} }
// IsWaveReady - Checks if wave data is ready // IsWaveValid - Checks if wave data is valid (data loaded and parameters)
func IsWaveReady(wave Wave) bool { func IsWaveValid(wave Wave) bool {
return isWaveReady(uintptr(unsafe.Pointer(&wave))) return isWaveValid(uintptr(unsafe.Pointer(&wave)))
} }
// LoadSound - Load sound from file // LoadSound - Load sound from file
@ -3469,9 +3624,9 @@ func LoadSoundAlias(source Sound) Sound {
return sound return sound
} }
// IsSoundReady - Checks if a sound is ready // IsSoundValid - Checks if a sound is valid (data loaded and buffers initialized)
func IsSoundReady(sound Sound) bool { func IsSoundValid(sound Sound) bool {
return isSoundReady(uintptr(unsafe.Pointer(&sound))) return isSoundValid(uintptr(unsafe.Pointer(&sound)))
} }
// UpdateSound - Update sound buffer with new data // UpdateSound - Update sound buffer with new data
@ -3546,9 +3701,9 @@ func WaveCopy(wave Wave) Wave {
return copy return copy
} }
// WaveCrop - Crop a wave to defined samples range // WaveCrop - Crop a wave to defined frames range
func WaveCrop(wave *Wave, initSample int32, finalSample int32) { func WaveCrop(wave *Wave, initFrame int32, finalFrame int32) {
waveCrop(wave, initSample, finalSample) waveCrop(wave, initFrame, finalFrame)
} }
// WaveFormat - Convert wave data to desired format // WaveFormat - Convert wave data to desired format
@ -3581,9 +3736,9 @@ func LoadMusicStreamFromMemory(fileType string, data []byte, dataSize int32) Mus
return music return music
} }
// IsMusicReady - Checks if a music stream is ready // IsMusicValid - Checks if a music stream is valid (context and buffers initialized)
func IsMusicReady(music Music) bool { func IsMusicValid(music Music) bool {
return isMusicReady(uintptr(unsafe.Pointer(&music))) return isMusicValid(uintptr(unsafe.Pointer(&music)))
} }
// UnloadMusicStream - Unload music stream // UnloadMusicStream - Unload music stream
@ -3658,9 +3813,9 @@ func LoadAudioStream(sampleRate uint32, sampleSize uint32, channels uint32) Audi
return audioStream return audioStream
} }
// IsAudioStreamReady - Checks if an audio stream is ready // IsAudioStreamValid - Checks if an audio stream is valid (buffers initialized)
func IsAudioStreamReady(stream AudioStream) bool { func IsAudioStreamValid(stream AudioStream) bool {
return isAudioStreamReady(uintptr(unsafe.Pointer(&stream))) return isAudioStreamValid(uintptr(unsafe.Pointer(&stream)))
} }
// UnloadAudioStream - Unload audio stream and free memory // UnloadAudioStream - Unload audio stream and free memory

View file

@ -1,6 +1,6 @@
/********************************************************************************************** /**********************************************************************************************
* *
* raymath v1.5 - Math functions to work with Vector2, Vector3, Matrix and Quaternions * raymath v2.0 - Math functions to work with Vector2, Vector3, Matrix and Quaternions
* *
* CONVENTIONS: * CONVENTIONS:
* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all * - Matrix structure is defined as row-major (memory layout) but parameters naming AND all
@ -12,7 +12,7 @@
* - Functions are always self-contained, no function use another raymath function inside, * - Functions are always self-contained, no function use another raymath function inside,
* required code is directly re-implemented inside * required code is directly re-implemented inside
* - Functions input parameters are always received by value (2 unavoidable exceptions) * - Functions input parameters are always received by value (2 unavoidable exceptions)
* - Functions use always a "result" variable for return * - Functions use always a "result" variable for return (except C++ operators)
* - Functions are always defined inline * - Functions are always defined inline
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience) * - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
* - No compound literals used to make sure libray is compatible with C++ * - No compound literals used to make sure libray is compatible with C++
@ -27,6 +27,8 @@
* Define static inline functions code, so #include header suffices for use. * Define static inline functions code, so #include header suffices for use.
* This may use up lots of memory. * This may use up lots of memory.
* *
* #define RAYMATH_DISABLE_CPP_OPERATORS
* Disables C++ operator overloads for raymath types.
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
@ -77,6 +79,7 @@
#endif #endif
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -174,7 +177,7 @@ typedef struct float16 {
// Clamp float value // Clamp float value
RMAPI float Clamp(float value, float min, float max) RMAPI float Clamp(float value, float min, float max)
{ {
float result = (value < min) ? min : value; float result = (value < min)? min : value;
if (result > max) result = max; if (result > max) result = max;
@ -961,12 +964,12 @@ RMAPI Vector3 Vector3CubicHermite(Vector3 v1, Vector3 tangent1, Vector3 v2, Vect
{ {
Vector3 result = { 0 }; Vector3 result = { 0 };
float amountPow2 = amount * amount; float amountPow2 = amount*amount;
float amountPow3 = amount * amount * amount; float amountPow3 = amount*amount*amount;
result.x = (2 * amountPow3 - 3 * amountPow2 + 1) * v1.x + (amountPow3 - 2 * amountPow2 + amount) * tangent1.x + (-2 * amountPow3 + 3 * amountPow2) * v2.x + (amountPow3 - amountPow2) * tangent2.x; result.x = (2*amountPow3 - 3*amountPow2 + 1)*v1.x + (amountPow3 - 2*amountPow2 + amount)*tangent1.x + (-2*amountPow3 + 3*amountPow2)*v2.x + (amountPow3 - amountPow2)*tangent2.x;
result.y = (2 * amountPow3 - 3 * amountPow2 + 1) * v1.y + (amountPow3 - 2 * amountPow2 + amount) * tangent1.y + (-2 * amountPow3 + 3 * amountPow2) * v2.y + (amountPow3 - amountPow2) * tangent2.y; result.y = (2*amountPow3 - 3*amountPow2 + 1)*v1.y + (amountPow3 - 2*amountPow2 + amount)*tangent1.y + (-2*amountPow3 + 3*amountPow2)*v2.y + (amountPow3 - amountPow2)*tangent2.y;
result.z = (2 * amountPow3 - 3 * amountPow2 + 1) * v1.z + (amountPow3 - 2 * amountPow2 + amount) * tangent1.z + (-2 * amountPow3 + 3 * amountPow2) * v2.z + (amountPow3 - amountPow2) * tangent2.z; result.z = (2*amountPow3 - 3*amountPow2 + 1)*v1.z + (amountPow3 - 2*amountPow2 + amount)*tangent1.z + (-2*amountPow3 + 3*amountPow2)*v2.z + (amountPow3 - amountPow2)*tangent2.z;
return result; return result;
} }
@ -1836,32 +1839,32 @@ RMAPI Matrix MatrixScale(float x, float y, float z)
} }
// Get perspective projection matrix // Get perspective projection matrix
RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far) RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top, double nearPlane, double farPlane)
{ {
Matrix result = { 0 }; Matrix result = { 0 };
float rl = (float)(right - left); float rl = (float)(right - left);
float tb = (float)(top - bottom); float tb = (float)(top - bottom);
float fn = (float)(far - near); float fn = (float)(farPlane - nearPlane);
result.m0 = ((float)near*2.0f)/rl; result.m0 = ((float)nearPlane*2.0f)/rl;
result.m1 = 0.0f; result.m1 = 0.0f;
result.m2 = 0.0f; result.m2 = 0.0f;
result.m3 = 0.0f; result.m3 = 0.0f;
result.m4 = 0.0f; result.m4 = 0.0f;
result.m5 = ((float)near*2.0f)/tb; result.m5 = ((float)nearPlane*2.0f)/tb;
result.m6 = 0.0f; result.m6 = 0.0f;
result.m7 = 0.0f; result.m7 = 0.0f;
result.m8 = ((float)right + (float)left)/rl; result.m8 = ((float)right + (float)left)/rl;
result.m9 = ((float)top + (float)bottom)/tb; result.m9 = ((float)top + (float)bottom)/tb;
result.m10 = -((float)far + (float)near)/fn; result.m10 = -((float)farPlane + (float)nearPlane)/fn;
result.m11 = -1.0f; result.m11 = -1.0f;
result.m12 = 0.0f; result.m12 = 0.0f;
result.m13 = 0.0f; result.m13 = 0.0f;
result.m14 = -((float)far*(float)near*2.0f)/fn; result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/fn;
result.m15 = 0.0f; result.m15 = 0.0f;
return result; return result;
@ -2217,12 +2220,12 @@ RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
// as described in the GLTF 2.0 specification: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic // as described in the GLTF 2.0 specification: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic
RMAPI Quaternion QuaternionCubicHermiteSpline(Quaternion q1, Quaternion outTangent1, Quaternion q2, Quaternion inTangent2, float t) RMAPI Quaternion QuaternionCubicHermiteSpline(Quaternion q1, Quaternion outTangent1, Quaternion q2, Quaternion inTangent2, float t)
{ {
float t2 = t * t; float t2 = t*t;
float t3 = t2 * t; float t3 = t2*t;
float h00 = 2 * t3 - 3 * t2 + 1; float h00 = 2*t3 - 3*t2 + 1;
float h10 = t3 - 2 * t2 + t; float h10 = t3 - 2*t2 + t;
float h01 = -2 * t3 + 3 * t2; float h01 = -2*t3 + 3*t2;
float h11 = t3 - t2; float h11 = t3 - t2;
Quaternion p0 = QuaternionScale(q1, h00); Quaternion p0 = QuaternionScale(q1, h00);
Quaternion m0 = QuaternionScale(outTangent1, h10); Quaternion m0 = QuaternionScale(outTangent1, h10);
@ -2566,7 +2569,13 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio
if (!FloatEquals(det, 0)) if (!FloatEquals(det, 0))
{ {
clone.m0 /= s.x; clone.m0 /= s.x;
clone.m4 /= s.x;
clone.m8 /= s.x;
clone.m1 /= s.y;
clone.m5 /= s.y; clone.m5 /= s.y;
clone.m9 /= s.y;
clone.m2 /= s.z;
clone.m6 /= s.z;
clone.m10 /= s.z; clone.m10 /= s.z;
// Extract rotation // Extract rotation
@ -2579,4 +2588,354 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio
} }
} }
#if defined(__cplusplus) && !defined(RAYMATH_DISABLE_CPP_OPERATORS)
// Optional C++ math operators
//-------------------------------------------------------------------------------
// Vector2 operators
static constexpr Vector2 Vector2Zeros = { 0, 0 };
static constexpr Vector2 Vector2Ones = { 1, 1 };
static constexpr Vector2 Vector2UnitX = { 1, 0 };
static constexpr Vector2 Vector2UnitY = { 0, 1 };
inline Vector2 operator + (const Vector2& lhs, const Vector2& rhs)
{
return Vector2Add(lhs, rhs);
}
inline const Vector2& operator += (Vector2& lhs, const Vector2& rhs)
{
lhs = Vector2Add(lhs, rhs);
return lhs;
}
inline Vector2 operator - (const Vector2& lhs, const Vector2& rhs)
{
return Vector2Subtract(lhs, rhs);
}
inline const Vector2& operator -= (Vector2& lhs, const Vector2& rhs)
{
lhs = Vector2Subtract(lhs, rhs);
return lhs;
}
inline Vector2 operator * (const Vector2& lhs, const float& rhs)
{
return Vector2Scale(lhs, rhs);
}
inline const Vector2& operator *= (Vector2& lhs, const float& rhs)
{
lhs = Vector2Scale(lhs, rhs);
return lhs;
}
inline Vector2 operator * (const Vector2& lhs, const Vector2& rhs)
{
return Vector2Multiply(lhs, rhs);
}
inline const Vector2& operator *= (Vector2& lhs, const Vector2& rhs)
{
lhs = Vector2Multiply(lhs, rhs);
return lhs;
}
inline Vector2 operator * (const Vector2& lhs, const Matrix& rhs)
{
return Vector2Transform(lhs, rhs);
}
inline const Vector2& operator -= (Vector2& lhs, const Matrix& rhs)
{
lhs = Vector2Transform(lhs, rhs);
return lhs;
}
inline Vector2 operator / (const Vector2& lhs, const float& rhs)
{
return Vector2Scale(lhs, 1.0f / rhs);
}
inline const Vector2& operator /= (Vector2& lhs, const float& rhs)
{
lhs = Vector2Scale(lhs, rhs);
return lhs;
}
inline Vector2 operator / (const Vector2& lhs, const Vector2& rhs)
{
return Vector2Divide(lhs, rhs);
}
inline const Vector2& operator /= (Vector2& lhs, const Vector2& rhs)
{
lhs = Vector2Divide(lhs, rhs);
return lhs;
}
inline bool operator == (const Vector2& lhs, const Vector2& rhs)
{
return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y);
}
inline bool operator != (const Vector2& lhs, const Vector2& rhs)
{
return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y);
}
// Vector3 operators
static constexpr Vector3 Vector3Zeros = { 0, 0, 0 };
static constexpr Vector3 Vector3Ones = { 1, 1, 1 };
static constexpr Vector3 Vector3UnitX = { 1, 0, 0 };
static constexpr Vector3 Vector3UnitY = { 0, 1, 0 };
static constexpr Vector3 Vector3UnitZ = { 0, 0, 1 };
inline Vector3 operator + (const Vector3& lhs, const Vector3& rhs)
{
return Vector3Add(lhs, rhs);
}
inline const Vector3& operator += (Vector3& lhs, const Vector3& rhs)
{
lhs = Vector3Add(lhs, rhs);
return lhs;
}
inline Vector3 operator - (const Vector3& lhs, const Vector3& rhs)
{
return Vector3Subtract(lhs, rhs);
}
inline const Vector3& operator -= (Vector3& lhs, const Vector3& rhs)
{
lhs = Vector3Subtract(lhs, rhs);
return lhs;
}
inline Vector3 operator * (const Vector3& lhs, const float& rhs)
{
return Vector3Scale(lhs, rhs);
}
inline const Vector3& operator *= (Vector3& lhs, const float& rhs)
{
lhs = Vector3Scale(lhs, rhs);
return lhs;
}
inline Vector3 operator * (const Vector3& lhs, const Vector3& rhs)
{
return Vector3Multiply(lhs, rhs);
}
inline const Vector3& operator *= (Vector3& lhs, const Vector3& rhs)
{
lhs = Vector3Multiply(lhs, rhs);
return lhs;
}
inline Vector3 operator * (const Vector3& lhs, const Matrix& rhs)
{
return Vector3Transform(lhs, rhs);
}
inline const Vector3& operator -= (Vector3& lhs, const Matrix& rhs)
{
lhs = Vector3Transform(lhs, rhs);
return lhs;
}
inline Vector3 operator / (const Vector3& lhs, const float& rhs)
{
return Vector3Scale(lhs, 1.0f / rhs);
}
inline const Vector3& operator /= (Vector3& lhs, const float& rhs)
{
lhs = Vector3Scale(lhs, rhs);
return lhs;
}
inline Vector3 operator / (const Vector3& lhs, const Vector3& rhs)
{
return Vector3Divide(lhs, rhs);
}
inline const Vector3& operator /= (Vector3& lhs, const Vector3& rhs)
{
lhs = Vector3Divide(lhs, rhs);
return lhs;
}
inline bool operator == (const Vector3& lhs, const Vector3& rhs)
{
return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z);
}
inline bool operator != (const Vector3& lhs, const Vector3& rhs)
{
return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z);
}
// Vector4 operators
static constexpr Vector4 Vector4Zeros = { 0, 0, 0, 0 };
static constexpr Vector4 Vector4Ones = { 1, 1, 1, 1 };
static constexpr Vector4 Vector4UnitX = { 1, 0, 0, 0 };
static constexpr Vector4 Vector4UnitY = { 0, 1, 0, 0 };
static constexpr Vector4 Vector4UnitZ = { 0, 0, 1, 0 };
static constexpr Vector4 Vector4UnitW = { 0, 0, 0, 1 };
inline Vector4 operator + (const Vector4& lhs, const Vector4& rhs)
{
return Vector4Add(lhs, rhs);
}
inline const Vector4& operator += (Vector4& lhs, const Vector4& rhs)
{
lhs = Vector4Add(lhs, rhs);
return lhs;
}
inline Vector4 operator - (const Vector4& lhs, const Vector4& rhs)
{
return Vector4Subtract(lhs, rhs);
}
inline const Vector4& operator -= (Vector4& lhs, const Vector4& rhs)
{
lhs = Vector4Subtract(lhs, rhs);
return lhs;
}
inline Vector4 operator * (const Vector4& lhs, const float& rhs)
{
return Vector4Scale(lhs, rhs);
}
inline const Vector4& operator *= (Vector4& lhs, const float& rhs)
{
lhs = Vector4Scale(lhs, rhs);
return lhs;
}
inline Vector4 operator * (const Vector4& lhs, const Vector4& rhs)
{
return Vector4Multiply(lhs, rhs);
}
inline const Vector4& operator *= (Vector4& lhs, const Vector4& rhs)
{
lhs = Vector4Multiply(lhs, rhs);
return lhs;
}
inline Vector4 operator / (const Vector4& lhs, const float& rhs)
{
return Vector4Scale(lhs, 1.0f / rhs);
}
inline const Vector4& operator /= (Vector4& lhs, const float& rhs)
{
lhs = Vector4Scale(lhs, rhs);
return lhs;
}
inline Vector4 operator / (const Vector4& lhs, const Vector4& rhs)
{
return Vector4Divide(lhs, rhs);
}
inline const Vector4& operator /= (Vector4& lhs, const Vector4& rhs)
{
lhs = Vector4Divide(lhs, rhs);
return lhs;
}
inline bool operator == (const Vector4& lhs, const Vector4& rhs)
{
return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z) && FloatEquals(lhs.w, rhs.w);
}
inline bool operator != (const Vector4& lhs, const Vector4& rhs)
{
return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z) || !FloatEquals(lhs.w, rhs.w);
}
// Quaternion operators
static constexpr Quaternion QuaternionZeros = { 0, 0, 0, 0 };
static constexpr Quaternion QuaternionOnes = { 1, 1, 1, 1 };
static constexpr Quaternion QuaternionUnitX = { 0, 0, 0, 1 };
inline Quaternion operator + (const Quaternion& lhs, const float& rhs)
{
return QuaternionAddValue(lhs, rhs);
}
inline const Quaternion& operator += (Quaternion& lhs, const float& rhs)
{
lhs = QuaternionAddValue(lhs, rhs);
return lhs;
}
inline Quaternion operator - (const Quaternion& lhs, const float& rhs)
{
return QuaternionSubtractValue(lhs, rhs);
}
inline const Quaternion& operator -= (Quaternion& lhs, const float& rhs)
{
lhs = QuaternionSubtractValue(lhs, rhs);
return lhs;
}
inline Quaternion operator * (const Quaternion& lhs, const Matrix& rhs)
{
return QuaternionTransform(lhs, rhs);
}
inline const Quaternion& operator *= (Quaternion& lhs, const Matrix& rhs)
{
lhs = QuaternionTransform(lhs, rhs);
return lhs;
}
// Matrix operators
inline Matrix operator + (const Matrix& lhs, const Matrix& rhs)
{
return MatrixAdd(lhs, rhs);
}
inline const Matrix& operator += (Matrix& lhs, const Matrix& rhs)
{
lhs = MatrixAdd(lhs, rhs);
return lhs;
}
inline Matrix operator - (const Matrix& lhs, const Matrix& rhs)
{
return MatrixSubtract(lhs, rhs);
}
inline const Matrix& operator -= (Matrix& lhs, const Matrix& rhs)
{
lhs = MatrixSubtract(lhs, rhs);
return lhs;
}
inline Matrix operator * (const Matrix& lhs, const Matrix& rhs)
{
return MatrixMultiply(lhs, rhs);
}
inline const Matrix& operator *= (Matrix& lhs, const Matrix& rhs)
{
lhs = MatrixMultiply(lhs, rhs);
return lhs;
}
//-------------------------------------------------------------------------------
#endif // C++ operators
#endif // RAYMATH_H #endif // RAYMATH_H

View file

@ -162,7 +162,6 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
#endif // RCAMERA_H #endif // RCAMERA_H
/*********************************************************************************** /***********************************************************************************
* *
* CAMERA IMPLEMENTATION * CAMERA IMPLEMENTATION
@ -196,12 +195,12 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#define CAMERA_MOVE_SPEED 0.09f #define CAMERA_MOVE_SPEED 5.4f // Units per second
#define CAMERA_ROTATION_SPEED 0.03f #define CAMERA_ROTATION_SPEED 0.03f
#define CAMERA_PAN_SPEED 0.2f #define CAMERA_PAN_SPEED 0.2f
// Camera mouse movement sensitivity // Camera mouse movement sensitivity
#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate #define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f
// Camera orbital speed in CAMERA_ORBITAL mode // Camera orbital speed in CAMERA_ORBITAL mode
#define CAMERA_ORBITAL_SPEED 0.5f // Radians per second #define CAMERA_ORBITAL_SPEED 0.5f // Radians per second
@ -444,11 +443,17 @@ void UpdateCamera(Camera *camera, int mode)
bool lockView = ((mode == CAMERA_FREE) || (mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); bool lockView = ((mode == CAMERA_FREE) || (mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
bool rotateUp = false; bool rotateUp = false;
// Camera speeds based on frame time
float cameraMoveSpeed = CAMERA_MOVE_SPEED*GetFrameTime();
float cameraRotationSpeed = CAMERA_ROTATION_SPEED*GetFrameTime();
float cameraPanSpeed = CAMERA_PAN_SPEED*GetFrameTime();
float cameraOrbitalSpeed = CAMERA_ORBITAL_SPEED*GetFrameTime();
if (mode == CAMERA_CUSTOM) {} if (mode == CAMERA_CUSTOM) {}
else if (mode == CAMERA_ORBITAL) else if (mode == CAMERA_ORBITAL)
{ {
// Orbital can just orbit // Orbital can just orbit
Matrix rotation = MatrixRotate(GetCameraUp(camera), CAMERA_ORBITAL_SPEED*GetFrameTime()); Matrix rotation = MatrixRotate(GetCameraUp(camera), cameraOrbitalSpeed);
Vector3 view = Vector3Subtract(camera->position, camera->target); Vector3 view = Vector3Subtract(camera->position, camera->target);
view = Vector3Transform(view, rotation); view = Vector3Transform(view, rotation);
camera->position = Vector3Add(camera->target, view); camera->position = Vector3Add(camera->target, view);
@ -456,22 +461,22 @@ void UpdateCamera(Camera *camera, int mode)
else else
{ {
// Camera rotation // Camera rotation
if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp);
if (IsKeyDown(KEY_UP)) CameraPitch(camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); if (IsKeyDown(KEY_UP)) CameraPitch(camera, cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp);
if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget); if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -cameraRotationSpeed, rotateAroundTarget);
if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, CAMERA_ROTATION_SPEED, rotateAroundTarget); if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, cameraRotationSpeed, rotateAroundTarget);
if (IsKeyDown(KEY_Q)) CameraRoll(camera, -CAMERA_ROTATION_SPEED); if (IsKeyDown(KEY_Q)) CameraRoll(camera, -cameraRotationSpeed);
if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED); if (IsKeyDown(KEY_E)) CameraRoll(camera, cameraRotationSpeed);
// Camera movement // Camera movement
// Camera pan (for CAMERA_FREE) // Camera pan (for CAMERA_FREE)
if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE))) if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)))
{ {
const Vector2 mouseDelta = GetMouseDelta(); const Vector2 mouseDelta = GetMouseDelta();
if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane); if (mouseDelta.x > 0.0f) CameraMoveRight(camera, cameraPanSpeed, moveInWorldPlane);
if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane); if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -cameraPanSpeed, moveInWorldPlane);
if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED); if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -cameraPanSpeed);
if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED); if (mouseDelta.y < 0.0f) CameraMoveUp(camera, cameraPanSpeed);
} }
else else
{ {
@ -481,28 +486,28 @@ void UpdateCamera(Camera *camera, int mode)
} }
// Keyboard support // Keyboard support
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); if (IsKeyDown(KEY_W)) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane);
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane);
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane);
if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); if (IsKeyDown(KEY_D)) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane);
// Gamepad movement // Gamepad movement
if (IsGamepadAvailable(0)) if (IsGamepadAvailable(0))
{ {
// Gamepad controller support // Gamepad controller support
CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane);
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane);
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane);
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane);
} }
if (mode == CAMERA_FREE) if (mode == CAMERA_FREE)
{ {
if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED); if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, cameraMoveSpeed);
if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED); if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -cameraMoveSpeed);
} }
} }

View file

@ -3,7 +3,7 @@
* rcore - Window/display management, Graphic device/context management and input management * rcore - Window/display management, Graphic device/context management and input management
* *
* PLATFORMS SUPPORTED: * PLATFORMS SUPPORTED:
* > PLATFORM_DESKTOP (GLFW backend): * > PLATFORM_DESKTOP_GLFW (GLFW backend):
* - Windows (Win32, Win64) * - Windows (Win32, Win64)
* - Linux (X11/Wayland desktop mode) * - Linux (X11/Wayland desktop mode)
* - macOS/OSX (x64, arm64) * - macOS/OSX (x64, arm64)
@ -161,10 +161,14 @@
__declspec(dllimport) unsigned long __stdcall GetModuleFileNameA(void *hModule, void *lpFilename, unsigned long nSize); __declspec(dllimport) unsigned long __stdcall GetModuleFileNameA(void *hModule, void *lpFilename, unsigned long nSize);
__declspec(dllimport) unsigned long __stdcall GetModuleFileNameW(void *hModule, void *lpFilename, unsigned long nSize); __declspec(dllimport) unsigned long __stdcall GetModuleFileNameW(void *hModule, void *lpFilename, unsigned long nSize);
__declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, void *widestr, int cchwide, void *str, int cbmb, void *defchar, int *used_default); __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, void *widestr, int cchwide, void *str, int cbmb, void *defchar, int *used_default);
unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod); __declspec(dllimport) unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);
unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); __declspec(dllimport) unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#elif defined(__linux__) #elif defined(__linux__)
#include <unistd.h> #include <unistd.h>
#elif defined(__FreeBSD__)
#include <sys/types.h>
#include <sys/sysctl.h>
#include <unistd.h>
#elif defined(__APPLE__) #elif defined(__APPLE__)
#include <sys/syslimits.h> #include <sys/syslimits.h>
#include <mach-o/dyld.h> #include <mach-o/dyld.h>
@ -187,14 +191,16 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#endif #endif
#if defined(_WIN32) #if defined(_WIN32)
#include <direct.h> // Required for: _getch(), _chdir() #include <io.h> // Required for: _access() [Used in FileExists()]
#include <direct.h> // Required for: _getch(), _chdir(), _mkdir()
#define GETCWD _getcwd // NOTE: MSDN recommends not to use getcwd(), chdir() #define GETCWD _getcwd // NOTE: MSDN recommends not to use getcwd(), chdir()
#define CHDIR _chdir #define CHDIR _chdir
#include <io.h> // Required for: _access() [Used in FileExists()] #define MKDIR(dir) _mkdir(dir)
#else #else
#include <unistd.h> // Required for: getch(), chdir() (POSIX), access() #include <unistd.h> // Required for: getch(), chdir(), mkdir(), access()
#define GETCWD getcwd #define GETCWD getcwd
#define CHDIR chdir #define CHDIR chdir
#define MKDIR(dir) mkdir(dir, 0777)
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -247,6 +253,10 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record #define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
#endif #endif
#ifndef DIRECTORY_FILTER_TAG
#define DIRECTORY_FILTER_TAG "DIR" // Name tag used to request directory inclusion on directory scan
#endif // NOTE: Used in ScanDirectoryFiles(), ScanDirectoryFilesRecursively() and LoadDirectoryFilesEx()
// Flags operation macros // Flags operation macros
#define FLAG_SET(n, f) ((n) |= (f)) #define FLAG_SET(n, f) ((n) |= (f))
#define FLAG_CLEAR(n, f) ((n) &= ~(f)) #define FLAG_CLEAR(n, f) ((n) &= ~(f))
@ -360,16 +370,21 @@ typedef struct CoreData {
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
RLAPI const char *raylib_version = RAYLIB_VERSION; // raylib version exported symbol, required for some bindings RLAPI const char *raylib_version = RAYLIB_VERSION; // raylib version exported symbol, required for some bindings
CoreData CORE = { 0 }; // Global CORE state context CoreData CORE = { 0 }; // Global CORE state context
// Flag to note GPU acceleration is available,
// referenced from other modules to support GPU data loading
// NOTE: Useful to allow Texture, RenderTexture, Font.texture, Mesh.vaoId/vboId, Shader loading
bool isGpuReady = false;
#if defined(SUPPORT_SCREEN_CAPTURE) #if defined(SUPPORT_SCREEN_CAPTURE)
static int screenshotCounter = 0; // Screenshots counter static int screenshotCounter = 0; // Screenshots counter
#endif #endif
#if defined(SUPPORT_GIF_RECORDING) #if defined(SUPPORT_GIF_RECORDING)
unsigned int gifFrameCounter = 0; // GIF frames counter static unsigned int gifFrameCounter = 0; // GIF frames counter
bool gifRecording = false; // GIF recording state static bool gifRecording = false; // GIF recording state
MsfGifState gifState = { 0 }; // MSGIF context state static MsfGifState gifState = { 0 }; // MSGIF context state
#endif #endif
#if defined(SUPPORT_AUTOMATION_EVENTS) #if defined(SUPPORT_AUTOMATION_EVENTS)
@ -493,9 +508,36 @@ void __stdcall Sleep(unsigned long msTimeout); // Required for: Wai
const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
#endif // !SUPPORT_MODULE_RTEXT #endif // !SUPPORT_MODULE_RTEXT
// Include platform-specific submodules
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#include "platforms/rcore_desktop.c" #define PLATFORM_DESKTOP_GLFW
#endif
// We're using `#pragma message` because `#warning` is not adopted by MSVC.
#if defined(SUPPORT_CLIPBOARD_IMAGE)
#if !defined(SUPPORT_MODULE_RTEXTURES)
#pragma message ("Warning: Enabling SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly")
#endif
// It's nice to have support Bitmap on Linux as well, but not as necessary as Windows
#if !defined(SUPPORT_FILEFORMAT_BMP) && defined(_WIN32)
#pragma message ("Warning: Enabling SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_FILEFORMAT_BMP, specially on Windows")
#endif
// From what I've tested applications on Wayland saves images on clipboard as PNG.
#if (!defined(SUPPORT_FILEFORMAT_PNG) || !defined(SUPPORT_FILEFORMAT_JPG)) && !defined(_WIN32)
#pragma message ("Warning: Getting image from the clipboard might not work without SUPPORT_FILEFORMAT_PNG or SUPPORT_FILEFORMAT_JPG")
#endif
// Not needed because `rtexture.c` will automatically defined STBI_REQUIRED when any SUPPORT_FILEFORMAT_* is defined.
// #if !defined(STBI_REQUIRED)
// #pragma message ("Warning: "STBI_REQUIRED is not defined, that means we can't load images from clipbard"
// #endif
#endif // SUPPORT_CLIPBOARD_IMAGE
// Include platform-specific submodules
#if defined(PLATFORM_DESKTOP_GLFW)
#include "platforms/rcore_desktop_glfw.c"
#elif defined(PLATFORM_DESKTOP_SDL) #elif defined(PLATFORM_DESKTOP_SDL)
#include "platforms/rcore_desktop_sdl.c" #include "platforms/rcore_desktop_sdl.c"
#elif defined(PLATFORM_DESKTOP_RGFW) #elif defined(PLATFORM_DESKTOP_RGFW)
@ -559,15 +601,16 @@ const char *TextFormat(const char *text, ...); // Formatting of tex
//void DisableCursor(void) //void DisableCursor(void)
// Initialize window and OpenGL context // Initialize window and OpenGL context
// NOTE: data parameter could be used to pass any kind of required data to the initialization
void InitWindow(int width, int height, const char *title) void InitWindow(int width, int height, const char *title)
{ {
TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION); TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP_GLFW)
TRACELOG(LOG_INFO, "Platform backend: DESKTOP (GLFW)"); TRACELOG(LOG_INFO, "Platform backend: DESKTOP (GLFW)");
#elif defined(PLATFORM_DESKTOP_SDL) #elif defined(PLATFORM_DESKTOP_SDL)
TRACELOG(LOG_INFO, "Platform backend: DESKTOP (SDL)"); TRACELOG(LOG_INFO, "Platform backend: DESKTOP (SDL)");
#elif defined(PLATFORM_DESKTOP_RGFW)
TRACELOG(LOG_INFO, "Platform backend: DESKTOP (RGFW)");
#elif defined(PLATFORM_WEB) #elif defined(PLATFORM_WEB)
TRACELOG(LOG_INFO, "Platform backend: WEB (HTML5)"); TRACELOG(LOG_INFO, "Platform backend: WEB (HTML5)");
#elif defined(PLATFORM_DRM) #elif defined(PLATFORM_DRM)
@ -631,28 +674,31 @@ void InitWindow(int width, int height, const char *title)
// Initialize rlgl default data (buffers and shaders) // Initialize rlgl default data (buffers and shaders)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
isGpuReady = true; // Flag to note GPU has been initialized successfully
// Setup default viewport // Setup default viewport
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT) #if defined(SUPPORT_MODULE_RTEXT)
// Load default font #if defined(SUPPORT_DEFAULT_FONT)
// WARNING: External function: Module required: rtext // Load default font
LoadFontDefault(); // WARNING: External function: Module required: rtext
#if defined(SUPPORT_MODULE_RSHAPES) LoadFontDefault();
// Set font white rectangle for shapes drawing, so shapes and text can be batched together #if defined(SUPPORT_MODULE_RSHAPES)
// WARNING: rshapes module is required, if not available, default internal white rectangle is used // Set font white rectangle for shapes drawing, so shapes and text can be batched together
Rectangle rec = GetFontDefault().recs[95]; // WARNING: rshapes module is required, if not available, default internal white rectangle is used
if (CORE.Window.flags & FLAG_MSAA_4X_HINT) Rectangle rec = GetFontDefault().recs[95];
{ if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
// NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering {
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 }); // NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering
} SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });
else }
{ else
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding {
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding
} SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });
}
#endif
#endif #endif
#else #else
#if defined(SUPPORT_MODULE_RSHAPES) #if defined(SUPPORT_MODULE_RSHAPES)
@ -662,21 +708,14 @@ void InitWindow(int width, int height, const char *title)
SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }); // WARNING: Module required: rshapes SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }); // WARNING: Module required: rshapes
#endif #endif
#endif #endif
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
{
// Set default font texture filter for HighDPI (blurry)
// RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_LINEAR);
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR);
}
#endif
CORE.Time.frameCounter = 0; CORE.Time.frameCounter = 0;
CORE.Window.shouldClose = false; CORE.Window.shouldClose = false;
// Initialize random seed // Initialize random seed
SetRandomSeed((unsigned int)time(NULL)); SetRandomSeed((unsigned int)time(NULL));
TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", GetWorkingDirectory());
} }
// Close window and unload OpenGL context // Close window and unload OpenGL context
@ -856,7 +895,7 @@ void EndDrawing(void)
#ifndef GIF_RECORD_FRAMERATE #ifndef GIF_RECORD_FRAMERATE
#define GIF_RECORD_FRAMERATE 10 #define GIF_RECORD_FRAMERATE 10
#endif #endif
gifFrameCounter += GetFrameTime()*1000; gifFrameCounter += (unsigned int)(GetFrameTime()*1000);
// NOTE: We record one gif frame depending on the desired gif framerate // NOTE: We record one gif frame depending on the desired gif framerate
if (gifFrameCounter > 1000/GIF_RECORD_FRAMERATE) if (gifFrameCounter > 1000/GIF_RECORD_FRAMERATE)
@ -1288,6 +1327,8 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
// vertex color location = 3 // vertex color location = 3
// vertex tangent location = 4 // vertex tangent location = 4
// vertex texcoord2 location = 5 // vertex texcoord2 location = 5
// vertex boneIds location = 6
// vertex boneWeights location = 7
// NOTE: If any location is not found, loc point becomes -1 // NOTE: If any location is not found, loc point becomes -1
@ -1303,6 +1344,8 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
shader.locs[SHADER_LOC_VERTEX_NORMAL] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL); shader.locs[SHADER_LOC_VERTEX_NORMAL] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL);
shader.locs[SHADER_LOC_VERTEX_TANGENT] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); shader.locs[SHADER_LOC_VERTEX_TANGENT] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
shader.locs[SHADER_LOC_VERTEX_BONEIDS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);
shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS);
// Get handles to GLSL uniform locations (vertex shader) // Get handles to GLSL uniform locations (vertex shader)
shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP); shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP);
@ -1310,6 +1353,7 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
shader.locs[SHADER_LOC_MATRIX_PROJECTION] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION); shader.locs[SHADER_LOC_MATRIX_PROJECTION] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION);
shader.locs[SHADER_LOC_MATRIX_MODEL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL); shader.locs[SHADER_LOC_MATRIX_MODEL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL);
shader.locs[SHADER_LOC_MATRIX_NORMAL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL); shader.locs[SHADER_LOC_MATRIX_NORMAL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL);
shader.locs[SHADER_LOC_BONE_MATRICES] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES);
// Get handles to GLSL uniform locations (fragment shader) // Get handles to GLSL uniform locations (fragment shader)
shader.locs[SHADER_LOC_COLOR_DIFFUSE] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR); shader.locs[SHADER_LOC_COLOR_DIFFUSE] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR);
@ -1321,10 +1365,10 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
return shader; return shader;
} }
// Check if a shader is ready // Check if a shader is valid (loaded on GPU)
bool IsShaderReady(Shader shader) bool IsShaderValid(Shader shader)
{ {
return ((shader.id > 0) && // Validate shader id (loaded successfully) return ((shader.id > 0) && // Validate shader id (GPU loaded successfully)
(shader.locs != NULL)); // Validate memory has been allocated for default shader locations (shader.locs != NULL)); // Validate memory has been allocated for default shader locations
// The following locations are tried to be set automatically (locs[i] >= 0), // The following locations are tried to be set automatically (locs[i] >= 0),
@ -2154,6 +2198,28 @@ const char *GetApplicationDirectory(void)
appDir[0] = '.'; appDir[0] = '.';
appDir[1] = '/'; appDir[1] = '/';
} }
#elif defined(__FreeBSD__)
size_t size = sizeof(appDir);
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
if (sysctl(mib, 4, appDir, &size, NULL, 0) == 0)
{
int len = strlen(appDir);
for (int i = len; i >= 0; --i)
{
if (appDir[i] == '/')
{
appDir[i + 1] = '\0';
break;
}
}
}
else
{
appDir[0] = '.';
appDir[1] = '/';
}
#endif #endif
return appDir; return appDir;
@ -2225,6 +2291,40 @@ void UnloadDirectoryFiles(FilePathList files)
RL_FREE(files.paths); RL_FREE(files.paths);
} }
// Create directories (including full path requested), returns 0 on success
int MakeDirectory(const char *dirPath)
{
if ((dirPath == NULL) || (dirPath[0] == '\0')) return 1; // Path is not valid
if (DirectoryExists(dirPath)) return 0; // Path already exists (is valid)
// Copy path string to avoid modifying original
int len = (int)strlen(dirPath) + 1;
char *pathcpy = (char *)RL_CALLOC(len, 1);
memcpy(pathcpy, dirPath, len);
// Iterate over pathcpy, create each subdirectory as needed
for (int i = 0; (i < len) && (pathcpy[i] != '\0'); i++)
{
if (pathcpy[i] == ':') i++;
else
{
if ((pathcpy[i] == '\\') || (pathcpy[i] == '/'))
{
pathcpy[i] = '\0';
if (!DirectoryExists(pathcpy)) MKDIR(pathcpy);
pathcpy[i] = '/';
}
}
}
// Create final directory
if (!DirectoryExists(pathcpy)) MKDIR(pathcpy);
RL_FREE(pathcpy);
return 0;
}
// Change working directory, returns true on success // Change working directory, returns true on success
bool ChangeDirectory(const char *dir) bool ChangeDirectory(const char *dir)
{ {
@ -2244,6 +2344,64 @@ bool IsPathFile(const char *path)
return S_ISREG(result.st_mode); return S_ISREG(result.st_mode);
} }
// Check if fileName is valid for the platform/OS
bool IsFileNameValid(const char *fileName)
{
bool valid = true;
if ((fileName != NULL) && (fileName[0] != '\0'))
{
int length = (int)strlen(fileName);
bool allPeriods = true;
for (int i = 0; i < length; i++)
{
// Check invalid characters
if ((fileName[i] == '<') ||
(fileName[i] == '>') ||
(fileName[i] == ':') ||
(fileName[i] == '\"') ||
(fileName[i] == '/') ||
(fileName[i] == '\\') ||
(fileName[i] == '|') ||
(fileName[i] == '?') ||
(fileName[i] == '*')) { valid = false; break; }
// Check non-glyph characters
if ((unsigned char)fileName[i] < 32) { valid = false; break; }
// TODO: Check trailing periods/spaces?
// Check if filename is not all periods
if (fileName[i] != '.') allPeriods = false;
}
if (allPeriods) valid = false;
/*
if (valid)
{
// Check invalid DOS names
if (length >= 3)
{
if (((fileName[0] == 'C') && (fileName[1] == 'O') && (fileName[2] == 'N')) || // CON
((fileName[0] == 'P') && (fileName[1] == 'R') && (fileName[2] == 'N')) || // PRN
((fileName[0] == 'A') && (fileName[1] == 'U') && (fileName[2] == 'X')) || // AUX
((fileName[0] == 'N') && (fileName[1] == 'U') && (fileName[2] == 'L'))) valid = false; // NUL
}
if (length >= 4)
{
if (((fileName[0] == 'C') && (fileName[1] == 'O') && (fileName[2] == 'M') && ((fileName[3] >= '0') && (fileName[3] <= '9'))) || // COM0-9
((fileName[0] == 'L') && (fileName[1] == 'P') && (fileName[2] == 'T') && ((fileName[3] >= '0') && (fileName[3] <= '9')))) valid = false; // LPT0-9
}
}
*/
}
return valid;
}
// Check if a file has been dropped into window // Check if a file has been dropped into window
bool IsFileDropped(void) bool IsFileDropped(void)
{ {
@ -2442,6 +2600,265 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
return decodedData; return decodedData;
} }
// Compute CRC32 hash code
unsigned int ComputeCRC32(unsigned char *data, int dataSize)
{
static unsigned int crcTable[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
unsigned int crc = ~0u;
for (int i = 0; i < dataSize; i++) crc = (crc >> 8) ^ crcTable[data[i] ^ (crc & 0xff)];
return ~crc;
}
// Compute MD5 hash code
// NOTE: Returns a static int[4] array (16 bytes)
unsigned int *ComputeMD5(unsigned char *data, int dataSize)
{
#define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
static unsigned int hash[4] = { 0 }; // Hash to be returned
// WARNING: All variables are unsigned 32 bit and wrap modulo 2^32 when calculating
// NOTE: r specifies the per-round shift amounts
unsigned int r[] = {
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
};
// Using binary integer part of the sines of integers (in radians) as constants
unsigned int k[] = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
};
hash[0] = 0x67452301;
hash[1] = 0xefcdab89;
hash[2] = 0x98badcfe;
hash[3] = 0x10325476;
// Pre-processing: adding a single 1 bit
// Append '1' bit to message
// NOTE: The input bytes are considered as bits strings,
// where the first bit is the most significant bit of the byte
// Pre-processing: padding with zeros
// Append '0' bit until message length in bit 448 (mod 512)
// Append length mod (2 pow 64) to message
int newDataSize = ((((dataSize + 8)/64) + 1)*64) - 8;
unsigned char *msg = RL_CALLOC(newDataSize + 64, 1); // Initialize with '0' bits, allocating 64 extra bytes
memcpy(msg, data, dataSize);
msg[dataSize] = 128; // Write the '1' bit
unsigned int bitsLen = 8*dataSize;
memcpy(msg + newDataSize, &bitsLen, 4); // Append the len in bits at the end of the buffer
// Process the message in successive 512-bit chunks for each 512-bit chunk of message
for (int offset = 0; offset < newDataSize; offset += (512/8))
{
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
unsigned int *w = (unsigned int *)(msg + offset);
// Initialize hash value for this chunk
unsigned int a = hash[0];
unsigned int b = hash[1];
unsigned int c = hash[2];
unsigned int d = hash[3];
for (int i = 0; i < 64; i++)
{
unsigned int f = 0;
unsigned int g = 0;
if (i < 16)
{
f = (b & c) | ((~b) & d);
g = i;
}
else if (i < 32)
{
f = (d & b) | ((~d) & c);
g = (5*i + 1)%16;
}
else if (i < 48)
{
f = b ^ c ^ d;
g = (3*i + 5)%16;
}
else
{
f = c ^ (b | (~d));
g = (7*i)%16;
}
unsigned int temp = d;
d = c;
c = b;
b = b + ROTATE_LEFT((a + f + k[i] + w[g]), r[i]);
a = temp;
}
// Add chunk's hash to result so far
hash[0] += a;
hash[1] += b;
hash[2] += c;
hash[3] += d;
}
RL_FREE(msg);
return hash;
}
// Compute SHA-1 hash code
// NOTE: Returns a static int[5] array (20 bytes)
unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
#define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
static unsigned int hash[5] = { 0 }; // Hash to be returned
// Initialize hash values
hash[0] = 0x67452301;
hash[1] = 0xEFCDAB89;
hash[2] = 0x98BADCFE;
hash[3] = 0x10325476;
hash[4] = 0xC3D2E1F0;
// Pre-processing: adding a single 1 bit
// Append '1' bit to message
// NOTE: The input bytes are considered as bits strings,
// where the first bit is the most significant bit of the byte
// Pre-processing: padding with zeros
// Append '0' bit until message length in bit 448 (mod 512)
// Append length mod (2 pow 64) to message
int newDataSize = ((((dataSize + 8)/64) + 1)*64);
unsigned char *msg = RL_CALLOC(newDataSize, 1); // Initialize with '0' bits
memcpy(msg, data, dataSize);
msg[dataSize] = 128; // Write the '1' bit
unsigned int bitsLen = 8*dataSize;
msg[newDataSize-1] = bitsLen;
// Process the message in successive 512-bit chunks
for (int offset = 0; offset < newDataSize; offset += (512/8))
{
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
unsigned int w[80] = {0};
for (int i = 0; i < 16; i++) {
w[i] = (msg[offset + (i * 4) + 0] << 24) |
(msg[offset + (i * 4) + 1] << 16) |
(msg[offset + (i * 4) + 2] << 8) |
(msg[offset + (i * 4) + 3]);
}
// Message schedule: extend the sixteen 32-bit words into eighty 32-bit words:
for (int i = 16; i < 80; ++i) {
w[i] = ROTATE_LEFT(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);
}
// Initialize hash value for this chunk
unsigned int a = hash[0];
unsigned int b = hash[1];
unsigned int c = hash[2];
unsigned int d = hash[3];
unsigned int e = hash[4];
for (int i = 0; i < 80; i++)
{
unsigned int f = 0;
unsigned int k = 0;
if (i < 20) {
f = (b & c) | ((~b) & d);
k = 0x5A827999;
} else if (i < 40) {
f = b ^ c ^ d;
k = 0x6ED9EBA1;
} else if (i < 60) {
f = (b & c) | (b & d) | (c & d);
k = 0x8F1BBCDC;
} else {
f = b ^ c ^ d;
k = 0xCA62C1D6;
}
unsigned int temp = ROTATE_LEFT(a, 5) + f + e + k + w[i];
e = d;
d = c;
c = ROTATE_LEFT(b, 30);
b = a;
a = temp;
}
// Add this chunk's hash to result so far
hash[0] += a;
hash[1] += b;
hash[2] += c;
hash[3] += d;
hash[4] += e;
}
free(msg);
return hash;
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition: Automation Events Recording and Playing // Module Functions Definition: Automation Events Recording and Playing
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -2649,8 +3066,8 @@ void PlayAutomationEvent(AutomationEvent event)
} break; } break;
case INPUT_MOUSE_WHEEL_MOTION: // param[0]: x delta, param[1]: y delta case INPUT_MOUSE_WHEEL_MOTION: // param[0]: x delta, param[1]: y delta
{ {
CORE.Input.Mouse.currentWheelMove.x = (float)event.params[0]; break; CORE.Input.Mouse.currentWheelMove.x = (float)event.params[0];
CORE.Input.Mouse.currentWheelMove.y = (float)event.params[1]; break; CORE.Input.Mouse.currentWheelMove.y = (float)event.params[1];
} break; } break;
case INPUT_TOUCH_UP: CORE.Input.Touch.currentTouchState[event.params[0]] = false; break; // param[0]: id case INPUT_TOUCH_UP: CORE.Input.Touch.currentTouchState[event.params[0]] = false; break; // param[0]: id
case INPUT_TOUCH_DOWN: CORE.Input.Touch.currentTouchState[event.params[0]] = true; break; // param[0]: id case INPUT_TOUCH_DOWN: CORE.Input.Touch.currentTouchState[event.params[0]] = true; break; // param[0]: id
@ -2687,6 +3104,8 @@ void PlayAutomationEvent(AutomationEvent event)
case ACTION_SETTARGETFPS: SetTargetFPS(event.params[0]); break; case ACTION_SETTARGETFPS: SetTargetFPS(event.params[0]); break;
default: break; default: break;
} }
TRACELOG(LOG_INFO, "AUTOMATION PLAY: Frame: %i | Event type: %i | Event parameters: %i, %i, %i", event.frame, event.type, event.params[0], event.params[1], event.params[2]);
} }
#endif #endif
} }
@ -2894,10 +3313,13 @@ int GetGamepadAxisCount(int gamepad)
// Get axis movement vector for a gamepad // Get axis movement vector for a gamepad
float GetGamepadAxisMovement(int gamepad, int axis) float GetGamepadAxisMovement(int gamepad, int axis)
{ {
float value = 0; float value = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f;
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS) && if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS)) {
(fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]) > 0.1f)) value = CORE.Input.Gamepad.axisState[gamepad][axis]; // 0.1f = GAMEPAD_AXIS_MINIMUM_DRIFT/DELTA float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]);
if (movement > value) value = CORE.Input.Gamepad.axisState[gamepad][axis];
}
return value; return value;
} }
@ -3242,10 +3664,21 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
if (filter != NULL) if (filter != NULL)
{ {
if (IsFileExtension(path, filter)) if (IsPathFile(path))
{ {
strcpy(files->paths[files->count], path); if (IsFileExtension(path, filter))
files->count++; {
strcpy(files->paths[files->count], path);
files->count++;
}
}
else
{
if (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0)
{
strcpy(files->paths[files->count], path);
files->count++;
}
} }
} }
else else
@ -3305,7 +3738,22 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi
break; break;
} }
} }
else ScanDirectoryFilesRecursively(path, files, filter); else
{
if ((filter != NULL) && (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0))
{
strcpy(files->paths[files->count], path);
files->count++;
}
if (files->count >= files->capacity)
{
TRACELOG(LOG_WARNING, "FILEIO: Maximum filepath scan capacity reached (%i files)", files->capacity);
break;
}
ScanDirectoryFilesRecursively(path, files, filter);
}
} }
} }
@ -3418,7 +3866,7 @@ static void RecordAutomationEvent(void)
currentEventList->events[currentEventList->count].frame = CORE.Time.frameCounter; currentEventList->events[currentEventList->count].frame = CORE.Time.frameCounter;
currentEventList->events[currentEventList->count].type = INPUT_MOUSE_WHEEL_MOTION; currentEventList->events[currentEventList->count].type = INPUT_MOUSE_WHEEL_MOTION;
currentEventList->events[currentEventList->count].params[0] = (int)CORE.Input.Mouse.currentWheelMove.x; currentEventList->events[currentEventList->count].params[0] = (int)CORE.Input.Mouse.currentWheelMove.x;
currentEventList->events[currentEventList->count].params[1] = (int)CORE.Input.Mouse.currentWheelMove.y;; currentEventList->events[currentEventList->count].params[1] = (int)CORE.Input.Mouse.currentWheelMove.y;
currentEventList->events[currentEventList->count].params[2] = 0; currentEventList->events[currentEventList->count].params[2] = 0;
TRACELOG(LOG_INFO, "AUTOMATION: Frame: %i | Event type: INPUT_MOUSE_WHEEL_MOTION | Event parameters: %i, %i, %i", currentEventList->events[currentEventList->count].frame, currentEventList->events[currentEventList->count].params[0], currentEventList->events[currentEventList->count].params[1], currentEventList->events[currentEventList->count].params[2]); TRACELOG(LOG_INFO, "AUTOMATION: Frame: %i | Event type: INPUT_MOUSE_WHEEL_MOTION | Event parameters: %i, %i, %i", currentEventList->events[currentEventList->count].frame, currentEventList->events[currentEventList->count].params[0], currentEventList->events[currentEventList->count].params[1], currentEventList->events[currentEventList->count].params[2]);
@ -3541,7 +3989,8 @@ static void RecordAutomationEvent(void)
for (int axis = 0; axis < MAX_GAMEPAD_AXIS; axis++) for (int axis = 0; axis < MAX_GAMEPAD_AXIS; axis++)
{ {
// Event type: INPUT_GAMEPAD_AXIS_MOTION // Event type: INPUT_GAMEPAD_AXIS_MOTION
if (CORE.Input.Gamepad.axisState[gamepad][axis] > 0.1f) float defaultMovement = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f;
if (GetGamepadAxisMovement(gamepad, axis) != defaultMovement)
{ {
currentEventList->events[currentEventList->count].frame = CORE.Time.frameCounter; currentEventList->events[currentEventList->count].frame = CORE.Time.frameCounter;
currentEventList->events[currentEventList->count].type = INPUT_GAMEPAD_AXIS_MOTION; currentEventList->events[currentEventList->count].type = INPUT_GAMEPAD_AXIS_MOTION;

View file

@ -338,7 +338,7 @@ func GetMonitorCount() int {
return v return v
} }
// GetCurrentMonitor - Get current connected monitor // GetCurrentMonitor - Get current monitor where window is placed
func GetCurrentMonitor() int { func GetCurrentMonitor() int {
ret := C.GetCurrentMonitor() ret := C.GetCurrentMonitor()
v := (int)(ret) v := (int)(ret)
@ -429,6 +429,15 @@ func GetClipboardText() string {
return v return v
} }
// GetClipboardImage - Get clipboard image content
//
// Only works with SDL3 backend or Windows with GLFW/RGFW
func GetClipboardImage() Image {
ret := C.GetClipboardImage()
v := newImageFromPointer(unsafe.Pointer(&ret))
return *v
}
// EnableEventWaiting - Enable waiting for events on EndDrawing(), no automatic event polling // EnableEventWaiting - Enable waiting for events on EndDrawing(), no automatic event polling
func EnableEventWaiting() { func EnableEventWaiting() {
C.EnableEventWaiting() C.EnableEventWaiting()
@ -546,10 +555,10 @@ func LoadShaderFromMemory(vsCode string, fsCode string) Shader {
return v return v
} }
// IsShaderReady - Check if a shader is ready // IsShaderValid - Check if a shader is valid (loaded on GPU)
func IsShaderReady(shader Shader) bool { func IsShaderValid(shader Shader) bool {
cshader := shader.cptr() cshader := shader.cptr()
ret := C.IsShaderReady(*cshader) ret := C.IsShaderValid(*cshader)
v := bool(ret) v := bool(ret)
return v return v
} }
@ -617,11 +626,29 @@ func UnloadShader(shader Shader) {
C.UnloadShader(*cshader) C.UnloadShader(*cshader)
} }
// GetMouseRay - Returns a ray trace from mouse position // GetMouseRay - Get a ray trace from mouse position
//
// Deprecated: Use [GetScreenToWorldRay] instead.
func GetMouseRay(mousePosition Vector2, camera Camera) Ray { func GetMouseRay(mousePosition Vector2, camera Camera) Ray {
cmousePosition := mousePosition.cptr() return GetScreenToWorldRay(mousePosition, camera)
}
// GetScreenToWorldRay - Get a ray trace from screen position (i.e mouse)
func GetScreenToWorldRay(position Vector2, camera Camera) Ray {
cposition := position.cptr()
ccamera := camera.cptr() ccamera := camera.cptr()
ret := C.GetMouseRay(*cmousePosition, *ccamera) ret := C.GetScreenToWorldRay(*cposition, *ccamera)
v := newRayFromPointer(unsafe.Pointer(&ret))
return v
}
// GetScreenToWorldRayEx - Get a ray trace from screen position (i.e mouse) in a viewport
func GetScreenToWorldRayEx(position Vector2, camera Camera, width, height int32) Ray {
cposition := position.cptr()
ccamera := camera.cptr()
cwidth := (C.int)(width)
cheight := (C.int)(height)
ret := C.GetScreenToWorldRayEx(*cposition, *ccamera, cwidth, cheight)
v := newRayFromPointer(unsafe.Pointer(&ret)) v := newRayFromPointer(unsafe.Pointer(&ret))
return v return v
} }
@ -738,7 +765,7 @@ func Fade(col color.RGBA, alpha float32) color.RGBA {
return v return v
} }
// ColorToInt - Returns hexadecimal value for a Color // ColorToInt - Get hexadecimal value for a Color (0xRRGGBBAA)
func ColorToInt(col color.RGBA) int32 { func ColorToInt(col color.RGBA) int32 {
ccolor := colorCptr(col) ccolor := colorCptr(col)
ret := C.ColorToInt(*ccolor) ret := C.ColorToInt(*ccolor)
@ -826,6 +853,15 @@ func ColorAlphaBlend(src, dst, tint color.RGBA) color.RGBA {
return v return v
} }
// ColorLerp - Get color lerp interpolation between two colors, factor [0.0f..1.0f]
func ColorLerp(col1, col2 color.RGBA, factor float32) color.RGBA {
ccol1 := colorCptr(col1)
ccol2 := colorCptr(col2)
ret := C.ColorLerp(*ccol1, *ccol2, C.float(factor))
v := newColorFromPointer(unsafe.Pointer(&ret))
return v
}
// GetColor - Returns a Color struct from hexadecimal value // GetColor - Returns a Color struct from hexadecimal value
func GetColor(hexValue uint) color.RGBA { func GetColor(hexValue uint) color.RGBA {
chexValue := (C.uint)(hexValue) chexValue := (C.uint)(hexValue)
@ -1081,6 +1117,11 @@ func SetGamepadMappings(mappings string) int32 {
return v return v
} }
// SetGamepadVibration - Set gamepad vibration for both motors (duration in seconds)
func SetGamepadVibration(gamepad int32, leftMotor, rightMotor, duration float32) {
C.SetGamepadVibration(C.int(gamepad), C.float(leftMotor), C.float(rightMotor), C.float(duration))
}
// IsMouseButtonPressed - Detect if a mouse button has been pressed once // IsMouseButtonPressed - Detect if a mouse button has been pressed once
func IsMouseButtonPressed(button MouseButton) bool { func IsMouseButtonPressed(button MouseButton) bool {
cbutton := (C.int)(button) cbutton := (C.int)(button)

View file

@ -434,7 +434,7 @@ int GetGestureDetected(void)
return (GESTURES.enabledFlags & GESTURES.current); return (GESTURES.enabledFlags & GESTURES.current);
} }
// Hold time measured in ms // Hold time measured in seconds
float GetGestureHoldDuration(void) float GetGestureHoldDuration(void)
{ {
// NOTE: time is calculated on current gesture HOLD // NOTE: time is calculated on current gesture HOLD
@ -517,7 +517,7 @@ static double rgGetCurrentTime(void)
#if defined(_WIN32) #if defined(_WIN32)
unsigned long long int clockFrequency, currentTime; unsigned long long int clockFrequency, currentTime;
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation! QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
QueryPerformanceCounter(&currentTime); QueryPerformanceCounter(&currentTime);
time = (double)currentTime/clockFrequency; // Time in seconds time = (double)currentTime/clockFrequency; // Time in seconds

View file

@ -54,13 +54,14 @@ const (
// VertexBuffer - Dynamic vertex buffers (position + texcoords + colors + indices arrays) // VertexBuffer - Dynamic vertex buffers (position + texcoords + colors + indices arrays)
type VertexBuffer struct { type VertexBuffer struct {
ElementCount int32 ElementCount int32 // Number of elements in the buffer (QUADS)
Vertices *float32 Vertices *float32 // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
Texcoords *float32 Texcoords *float32 // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
Colors *uint8 Normals *float32 // Vertex normal (XYZ - 3 components per vertex) (shader-location = 2)
Indices *uint32 Colors *uint8 // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
VaoId uint32 Indices *uint32 // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
VboId [4]uint32 VaoId uint32 // OpenGL Vertex Array Object id
VboId [5]uint32 // OpenGL Vertex Buffer Objects id (5 types of vertex data)
} }
// DrawCall - Draw call type // DrawCall - Draw call type

View file

@ -8,17 +8,17 @@
* *
* ADDITIONAL NOTES: * ADDITIONAL NOTES:
* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are * When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are
* initialized on rlglInit() to accumulate vertex data. * initialized on rlglInit() to accumulate vertex data
* *
* When an internal state change is required all the stored vertex data is renderer in batch, * When an internal state change is required all the stored vertex data is renderer in batch,
* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch. * additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch
* *
* Some resources are also loaded for convenience, here the complete list: * Some resources are also loaded for convenience, here the complete list:
* - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data * - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data
* - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8 * - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8
* - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs) * - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs)
* *
* Internal buffer (and resources) must be manually unloaded calling rlglClose(). * Internal buffer (and resources) must be manually unloaded calling rlglClose()
* *
* CONFIGURATION: * CONFIGURATION:
* #define GRAPHICS_API_OPENGL_11 * #define GRAPHICS_API_OPENGL_11
@ -32,9 +32,9 @@
* required by any other module, use rlGetVersion() to check it * required by any other module, use rlGetVersion() to check it
* *
* #define RLGL_IMPLEMENTATION * #define RLGL_IMPLEMENTATION
* Generates the implementation of the library into the included file. * Generates the implementation of the library into the included file
* If not defined, the library is in header only mode and can be included in other headers * If not defined, the library is in header only mode and can be included in other headers
* or source files without problems. But only ONE file should hold the implementation. * or source files without problems. But only ONE file should hold the implementation
* *
* #define RLGL_RENDER_TEXTURES_HINT * #define RLGL_RENDER_TEXTURES_HINT
* Enable framebuffer objects (fbo) support (enabled by default) * Enable framebuffer objects (fbo) support (enabled by default)
@ -68,12 +68,15 @@
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR * #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT * #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 * #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))) * #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)))
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) * #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices
* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
@ -324,22 +327,33 @@
// Default shader vertex attribute locations // Default shader vertex attribute locations
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
#endif #endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1
#endif #endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2
#endif #endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3
#endif #endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4
#endif #endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6
#endif
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
#endif
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -527,6 +541,10 @@ typedef enum {
RL_SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int) RL_SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int)
RL_SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int) RL_SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int)
RL_SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int) RL_SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int)
RL_SHADER_UNIFORM_UINT, // Shader uniform type: unsigned int
RL_SHADER_UNIFORM_UIVEC2, // Shader uniform type: uivec2 (2 unsigned int)
RL_SHADER_UNIFORM_UIVEC3, // Shader uniform type: uivec3 (3 unsigned int)
RL_SHADER_UNIFORM_UIVEC4, // Shader uniform type: uivec4 (4 unsigned int)
RL_SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d RL_SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d
} rlShaderUniformDataType; } rlShaderUniformDataType;
@ -590,9 +608,9 @@ RLAPI void rlMultMatrixf(const float *matf); // Multiply the current
RLAPI void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar); RLAPI void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar);
RLAPI void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar); RLAPI void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar);
RLAPI void rlViewport(int x, int y, int width, int height); // Set the viewport area RLAPI void rlViewport(int x, int y, int width, int height); // Set the viewport area
RLAPI void rlSetClipPlanes(double near, double far); // Set clip planes distances RLAPI void rlSetClipPlanes(double nearPlane, double farPlane); // Set clip planes distances
RLAPI double rlGetCullDistanceNear(); // Get cull plane distance near RLAPI double rlGetCullDistanceNear(void); // Get cull plane distance near
RLAPI double rlGetCullDistanceFar(); // Get cull plane distance far RLAPI double rlGetCullDistanceFar(void); // Get cull plane distance far
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Functions Declaration - Vertex level operations // Functions Declaration - Vertex level operations
@ -665,7 +683,7 @@ RLAPI void rlDisableScissorTest(void); // Disable scissor test
RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test
RLAPI void rlEnableWireMode(void); // Enable wire mode RLAPI void rlEnableWireMode(void); // Enable wire mode
RLAPI void rlEnablePointMode(void); // Enable point mode RLAPI void rlEnablePointMode(void); // Enable point mode
RLAPI void rlDisableWireMode(void); // Disable wire mode ( and point ) maybe rename RLAPI void rlDisableWireMode(void); // Disable wire (and point) mode
RLAPI void rlSetLineWidth(float width); // Set the line drawing width RLAPI void rlSetLineWidth(float width); // Set the line drawing width
RLAPI float rlGetLineWidth(void); // Get the line drawing width RLAPI float rlGetLineWidth(void); // Get the line drawing width
RLAPI void rlEnableSmoothLines(void); // Enable line aliasing RLAPI void rlEnableSmoothLines(void); // Enable line aliasing
@ -731,7 +749,7 @@ RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, const void
// Textures management // Textures management
RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture data RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture data
RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo) RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo)
RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format); // Load texture cubemap data RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount); // Load texture cubemap data
RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update texture with new data on GPU RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update texture with new data on GPU
RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats
RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format
@ -755,6 +773,7 @@ RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName);
RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute
RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform
RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix
RLAPI void rlSetUniformMatrices(int locIndex, const Matrix *mat, int count); // Set shader value matrices
RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler
RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations) RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations)
@ -844,9 +863,9 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2ext.h> // OpenGL ES 2.0 extensions library #include <GLES2/gl2ext.h> // OpenGL ES 2.0 extensions library
#elif defined(GRAPHICS_API_OPENGL_ES2) #elif defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: OpenGL ES 2.0 can be enabled on PLATFORM_DESKTOP, // NOTE: OpenGL ES 2.0 can be enabled on Desktop platforms,
// in that case, functions are loaded from a custom glad for OpenGL ES 2.0 // in that case, functions are loaded from a custom glad for OpenGL ES 2.0
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL)
#define GLAD_GLES2_IMPLEMENTATION #define GLAD_GLES2_IMPLEMENTATION
#include "external/glad_gles2.h" #include "external/glad_gles2.h"
#else #else
@ -973,6 +992,12 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2
#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2
#endif #endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS
#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
#endif
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP
#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
@ -992,6 +1017,9 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR
#define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
#endif #endif
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES
#define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices
#endif
#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 #ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0
#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
#endif #endif
@ -1371,10 +1399,10 @@ void rlViewport(int x, int y, int width, int height)
} }
// Set clip planes distances // Set clip planes distances
void rlSetClipPlanes(double near, double far) void rlSetClipPlanes(double nearPlane, double farPlane)
{ {
rlCullDistanceNear = near; rlCullDistanceNear = nearPlane;
rlCullDistanceFar = far; rlCullDistanceFar = farPlane;
} }
// Get cull plane distance near // Get cull plane distance near
@ -1406,7 +1434,7 @@ void rlBegin(int mode)
} }
} }
void rlEnd() { glEnd(); } void rlEnd(void) { glEnd(); }
void rlVertex2i(int x, int y) { glVertex2i(x, y); } void rlVertex2i(int x, int y) { glVertex2i(x, y); }
void rlVertex2f(float x, float y) { glVertex2f(x, y); } void rlVertex2f(float x, float y) { glVertex2f(x, y); }
void rlVertex3f(float x, float y, float z) { glVertex3f(x, y, z); } void rlVertex3f(float x, float y, float z) { glVertex3f(x, y, z); }
@ -1475,8 +1503,8 @@ void rlVertex3f(float x, float y, float z)
tz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z + RLGL.State.transform.m14; tz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z + RLGL.State.transform.m14;
} }
// WARNING: We can't break primitives when launching a new batch. // WARNING: We can't break primitives when launching a new batch
// RL_LINES comes in pairs, RL_TRIANGLES come in groups of 3 vertices and RL_QUADS come in groups of 4 vertices. // RL_LINES comes in pairs, RL_TRIANGLES come in groups of 3 vertices and RL_QUADS come in groups of 4 vertices
// We must check current draw.mode when a new vertex is required and finish the batch only if the draw.mode draw.vertexCount is %2, %3 or %4 // We must check current draw.mode when a new vertex is required and finish the batch only if the draw.mode draw.vertexCount is %2, %3 or %4
if (RLGL.State.vertexCounter > (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4 - 4)) if (RLGL.State.vertexCounter > (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4 - 4))
{ {
@ -1560,7 +1588,7 @@ void rlNormal3f(float x, float y, float z)
float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz); float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz);
if (length != 0.0f) if (length != 0.0f)
{ {
float ilength = 1.0f / length; float ilength = 1.0f/length;
normalx *= ilength; normalx *= ilength;
normaly *= ilength; normaly *= ilength;
normalz *= ilength; normalz *= ilength;
@ -1948,6 +1976,7 @@ void rlEnableWireMode(void)
#endif #endif
} }
// Enable point mode
void rlEnablePointMode(void) void rlEnablePointMode(void)
{ {
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
@ -1956,6 +1985,7 @@ void rlEnablePointMode(void)
glEnable(GL_PROGRAM_POINT_SIZE); glEnable(GL_PROGRAM_POINT_SIZE);
#endif #endif
} }
// Disable wire mode // Disable wire mode
void rlDisableWireMode(void) void rlDisableWireMode(void)
{ {
@ -2038,7 +2068,7 @@ void rlClearScreenBuffers(void)
} }
// Check and log OpenGL error codes // Check and log OpenGL error codes
void rlCheckErrors() void rlCheckErrors(void)
{ {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
int check = 1; int check = 1;
@ -2390,7 +2420,7 @@ void rlLoadExtensions(void *loader)
#elif defined(GRAPHICS_API_OPENGL_ES2) #elif defined(GRAPHICS_API_OPENGL_ES2)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL)
// TODO: Support GLAD loader for OpenGL ES 3.0 // TODO: Support GLAD loader for OpenGL ES 3.0
if (gladLoadGLES2((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL ES2.0 functions"); if (gladLoadGLES2((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL ES2.0 functions");
else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES 2.0 loaded successfully"); else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES 2.0 loaded successfully");
@ -2442,25 +2472,47 @@ void rlLoadExtensions(void *loader)
} }
// Check instanced rendering support // Check instanced rendering support
if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // Web ANGLE if (strstr(extList[i], (const char*)"instanced_arrays") != NULL) // Broad check for instanced_arrays
{ {
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE"); // Specific check
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE"); if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // ANGLE
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE"); {
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE");
if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE");
} glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE");
else }
{ else if (strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0) // EXT
if ((strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0) && // Standard EXT
(strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0))
{ {
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT"); glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT"); glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT");
if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
} }
else if (strcmp(extList[i], (const char *)"GL_NV_instanced_arrays") == 0) // NVIDIA GLES
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorNV");
}
// The feature will only be marked as supported if the elements from GL_XXX_instanced_arrays are present
if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
}
else if (strstr(extList[i], (const char *)"draw_instanced") != NULL)
{
// GL_ANGLE_draw_instanced doesn't exist
if (strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0)
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT");
}
else if (strcmp(extList[i], (const char*)"GL_NV_draw_instanced") == 0)
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV");
}
// But the functions will at least be loaded if only GL_XX_EXT_draw_instanced exist
if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
} }
// Check NPOT textures support // Check NPOT textures support
@ -2881,11 +2933,11 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors); glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer
// NOTE: glMapBuffer() causes sync issue. // NOTE: glMapBuffer() causes sync issue
// If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job. // If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job
// To avoid waiting (idle), you can call first glBufferData() with NULL pointer before glMapBuffer(). // To avoid waiting (idle), you can call first glBufferData() with NULL pointer before glMapBuffer()
// If you do that, the previous data in PBO will be discarded and glMapBuffer() returns a new // If you do that, the previous data in PBO will be discarded and glMapBuffer() returns a new
// allocated pointer immediately even if GPU is still working with the previous data. // allocated pointer immediately even if GPU is still working with the previous data
// Another option: map the buffer object into client's memory // Another option: map the buffer object into client's memory
// Probably this code could be moved somewhere else... // Probably this code could be moved somewhere else...
@ -2938,7 +2990,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
} }
// WARNING: For the following setup of the view, model, and normal matrices, it is expected that // WARNING: For the following setup of the view, model, and normal matrices, it is expected that
// transformations and rendering occur between rlPushMatrix and rlPopMatrix. // transformations and rendering occur between rlPushMatrix() and rlPopMatrix()
if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_VIEW] != -1) if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_VIEW] != -1)
{ {
@ -3008,15 +3060,15 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount); if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount);
else else
{ {
#if defined(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_33)
// We need to define the number of indices to be processed: elementCount*6 // We need to define the number of indices to be processed: elementCount*6
// NOTE: The final parameter tells the GPU the offset in bytes from the // NOTE: The final parameter tells the GPU the offset in bytes from the
// start of the index buffer to the location of the first index to process // start of the index buffer to the location of the first index to process
glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint))); glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint)));
#endif #endif
#if defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_ES2)
glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(vertexOffset/4*6*sizeof(GLushort))); glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(vertexOffset/4*6*sizeof(GLushort)));
#endif #endif
} }
vertexOffset += (batch->draws[i].vertexCount + batch->draws[i].vertexAlignment); vertexOffset += (batch->draws[i].vertexCount + batch->draws[i].vertexAlignment);
@ -3334,11 +3386,17 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
// Load texture cubemap // Load texture cubemap
// NOTE: Cubemap data is expected to be 6 images in a single data array (one after the other), // NOTE: Cubemap data is expected to be 6 images in a single data array (one after the other),
// expected the following convention: +X, -X, +Y, -Y, +Z, -Z // expected the following convention: +X, -X, +Y, -Y, +Z, -Z
unsigned int rlLoadTextureCubemap(const void *data, int size, int format) unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount)
{ {
unsigned int id = 0; unsigned int id = 0;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
int mipSize = size;
// NOTE: Added pointer math separately from function to avoid UBSAN complaining
unsigned char *dataPtr = NULL;
if (data != NULL) dataPtr = (unsigned char *)data;
unsigned int dataSize = rlGetPixelDataSize(size, size, format); unsigned int dataSize = rlGetPixelDataSize(size, size, format);
glGenTextures(1, &id); glGenTextures(1, &id);
@ -3349,24 +3407,28 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format)
if (glInternalFormat != 0) if (glInternalFormat != 0)
{ {
// Load cubemap faces // Load cubemap faces/mipmaps
for (unsigned int i = 0; i < 6; i++) for (int i = 0; i < 6*mipmapCount; i++)
{ {
int mipmapLevel = i/6;
int face = i%6;
if (data == NULL) if (data == NULL)
{ {
if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)
{ {
if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32) if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) ||
|| (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16)) (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32) ||
TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) ||
else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, NULL); (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16)) TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported");
else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, glFormat, glType, NULL);
} }
else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format"); else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format");
} }
else else
{ {
if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, (unsigned char *)data + i*dataSize); if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, glFormat, glType, (unsigned char *)dataPtr + face*dataSize);
else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, dataSize, (unsigned char *)data + i*dataSize); else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, dataSize, (unsigned char *)dataPtr + face*dataSize);
} }
#if defined(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_33)
@ -3385,11 +3447,23 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format)
glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
} }
#endif #endif
if (face == 5)
{
mipSize /= 2;
if (data != NULL) dataPtr += dataSize*6; // Increment data pointer to next mipmap
// Security check for NPOT textures
if (mipSize < 1) mipSize = 1;
dataSize = rlGetPixelDataSize(mipSize, mipSize, format);
}
} }
} }
// Set cubemap texture sampling parameters // Set cubemap texture sampling parameters
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); if (mipmapCount > 1) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
else glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@ -3548,8 +3622,8 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
//glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
//glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format); //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
// NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding. // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding
// Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting. // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting
// GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.) // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
// GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.) // GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
@ -3570,7 +3644,7 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
#if defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_ES2)
// glGetTexImage() is not available on OpenGL ES 2.0 // glGetTexImage() is not available on OpenGL ES 2.0
// Texture width and height are required on OpenGL ES 2.0. There is no way to get it from texture id. // Texture width and height are required on OpenGL ES 2.0, there is no way to get it from texture id
// Two possible Options: // Two possible Options:
// 1 - Bind texture to color fbo attachment and glReadPixels() // 1 - Bind texture to color fbo attachment and glReadPixels()
// 2 - Create an fbo, activate it, render quad with texture, glReadPixels() // 2 - Create an fbo, activate it, render quad with texture, glReadPixels()
@ -3736,7 +3810,7 @@ void rlUnloadFramebuffer(unsigned int id)
else if (depthType == GL_TEXTURE) glDeleteTextures(1, &depthIdU); else if (depthType == GL_TEXTURE) glDeleteTextures(1, &depthIdU);
// NOTE: If a texture object is deleted while its image is attached to the *currently bound* framebuffer, // NOTE: If a texture object is deleted while its image is attached to the *currently bound* framebuffer,
// the texture image is automatically detached from the currently bound framebuffer. // the texture image is automatically detached from the currently bound framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &id); glDeleteFramebuffers(1, &id);
@ -3945,7 +4019,9 @@ void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool norma
// Additional types (depends on OpenGL version or extensions): // Additional types (depends on OpenGL version or extensions):
// - GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, GL_FIXED, // - GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, GL_FIXED,
// - GL_INT_2_10_10_10_REV, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_10F_11F_11F_REV // - GL_INT_2_10_10_10_REV, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_10F_11F_11F_REV
glVertexAttribPointer(index, compSize, type, normalized, stride, (void *)offset);
size_t offsetNative = offset;
glVertexAttribPointer(index, compSize, type, normalized, stride, (void *)offsetNative);
#endif #endif
} }
@ -3992,18 +4068,18 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
unsigned int fragmentShaderId = 0; unsigned int fragmentShaderId = 0;
// Compile vertex shader (if provided) // Compile vertex shader (if provided)
// NOTE: If not vertex shader is provided, use default one
if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER); if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER);
// In case no vertex shader was provided or compilation failed, we use default vertex shader else vertexShaderId = RLGL.State.defaultVShaderId;
if (vertexShaderId == 0) vertexShaderId = RLGL.State.defaultVShaderId;
// Compile fragment shader (if provided) // Compile fragment shader (if provided)
// NOTE: If not vertex shader is provided, use default one
if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER); if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);
// In case no fragment shader was provided or compilation failed, we use default fragment shader else fragmentShaderId = RLGL.State.defaultFShaderId;
if (fragmentShaderId == 0) fragmentShaderId = RLGL.State.defaultFShaderId;
// In case vertex and fragment shader are the default ones, no need to recompile, we can just assign the default shader program id // In case vertex and fragment shader are the default ones, no need to recompile, we can just assign the default shader program id
if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId; if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId;
else else if ((vertexShaderId > 0) && (fragmentShaderId > 0))
{ {
// One of or both shader are new, we need to compile a new shader program // One of or both shader are new, we need to compile a new shader program
id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId); id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId);
@ -4081,6 +4157,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
//case GL_GEOMETRY_SHADER: //case GL_GEOMETRY_SHADER:
#if defined(GRAPHICS_API_OPENGL_43) #if defined(GRAPHICS_API_OPENGL_43)
case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile compute shader code", shader); break; case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile compute shader code", shader); break;
#elif defined(GRAPHICS_API_OPENGL_33)
case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break;
#endif #endif
default: break; default: break;
} }
@ -4096,6 +4174,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log); TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log);
RL_FREE(log); RL_FREE(log);
} }
shader = 0;
} }
else else
{ {
@ -4106,6 +4186,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
//case GL_GEOMETRY_SHADER: //case GL_GEOMETRY_SHADER:
#if defined(GRAPHICS_API_OPENGL_43) #if defined(GRAPHICS_API_OPENGL_43)
case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader compiled successfully", shader); break; case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader compiled successfully", shader); break;
#elif defined(GRAPHICS_API_OPENGL_33)
case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break;
#endif #endif
default: break; default: break;
} }
@ -4135,6 +4217,11 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS);
#endif
// NOTE: If some attrib name is no found on the shader, it locations becomes -1 // NOTE: If some attrib name is no found on the shader, it locations becomes -1
glLinkProgram(program); glLinkProgram(program);
@ -4166,7 +4253,7 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
else else
{ {
// Get the size of compiled shader program (not available on OpenGL ES 2.0) // Get the size of compiled shader program (not available on OpenGL ES 2.0)
// NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero. // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero
//GLint binarySize = 0; //GLint binarySize = 0;
//glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize); //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);
@ -4226,8 +4313,16 @@ void rlSetUniform(int locIndex, const void *value, int uniformType, int count)
case RL_SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break;
case RL_SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break;
case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break;
#if !defined(GRAPHICS_API_OPENGL_ES2)
case RL_SHADER_UNIFORM_UINT: glUniform1uiv(locIndex, count, (unsigned int *)value); break;
case RL_SHADER_UNIFORM_UIVEC2: glUniform2uiv(locIndex, count, (unsigned int *)value); break;
case RL_SHADER_UNIFORM_UIVEC3: glUniform3uiv(locIndex, count, (unsigned int *)value); break;
case RL_SHADER_UNIFORM_UIVEC4: glUniform4uiv(locIndex, count, (unsigned int *)value); break;
#endif
case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break;
default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized"); default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized");
// TODO: Support glUniform1uiv(), glUniform2uiv(), glUniform3uiv(), glUniform4uiv()
} }
#endif #endif
} }
@ -4261,6 +4356,18 @@ void rlSetUniformMatrix(int locIndex, Matrix mat)
#endif #endif
} }
// Set shader value uniform matrix
void rlSetUniformMatrices(int locIndex, const Matrix *matrices, int count)
{
#if defined(GRAPHICS_API_OPENGL_33)
glUniformMatrix4fv(locIndex, count, true, (const float *)matrices);
#elif defined(GRAPHICS_API_OPENGL_ES2)
// WARNING: WebGL does not support Matrix transpose ("true" parameter)
// REF: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniformMatrix
glUniformMatrix4fv(locIndex, count, false, (const float *)matrices);
#endif
}
// Set shader value uniform sampler // Set shader value uniform sampler
void rlSetUniformSampler(int locIndex, unsigned int textureId) void rlSetUniformSampler(int locIndex, unsigned int textureId)
{ {
@ -4340,12 +4447,14 @@ unsigned int rlLoadComputeShaderProgram(unsigned int shaderId)
else else
{ {
// Get the size of compiled shader program (not available on OpenGL ES 2.0) // Get the size of compiled shader program (not available on OpenGL ES 2.0)
// NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero. // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero
//GLint binarySize = 0; //GLint binarySize = 0;
//glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize); //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);
TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", program); TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", program);
} }
#else
TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43");
#endif #endif
return program; return program;
@ -4370,6 +4479,8 @@ unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHi
glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY); glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY);
if (data == NULL) glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); // Clear buffer data to 0 if (data == NULL) glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); // Clear buffer data to 0
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
#else
TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43");
#endif #endif
return ssbo; return ssbo;
@ -4380,7 +4491,10 @@ void rlUnloadShaderBuffer(unsigned int ssboId)
{ {
#if defined(GRAPHICS_API_OPENGL_43) #if defined(GRAPHICS_API_OPENGL_43)
glDeleteBuffers(1, &ssboId); glDeleteBuffers(1, &ssboId);
#else
TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43");
#endif #endif
} }
// Update SSBO buffer data // Update SSBO buffer data
@ -4395,14 +4509,14 @@ void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSi
// Get SSBO buffer size // Get SSBO buffer size
unsigned int rlGetShaderBufferSize(unsigned int id) unsigned int rlGetShaderBufferSize(unsigned int id)
{ {
long long size = 0;
#if defined(GRAPHICS_API_OPENGL_43) #if defined(GRAPHICS_API_OPENGL_43)
GLint64 size = 0;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id); glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
glGetInteger64v(GL_SHADER_STORAGE_BUFFER_SIZE, &size); glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size);
#endif
return (size > 0)? (unsigned int)size : 0; return (size > 0)? (unsigned int)size : 0;
#else
return 0;
#endif
} }
// Read SSBO buffer data (GPU->CPU) // Read SSBO buffer data (GPU->CPU)
@ -4440,6 +4554,8 @@ void rlBindImageTexture(unsigned int id, unsigned int index, int format, bool re
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
glBindImageTexture(index, id, 0, 0, 0, readonly? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat); glBindImageTexture(index, id, 0, 0, 0, readonly? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat);
#else
TRACELOG(RL_LOG_WARNING, "TEXTURE: Image texture binding not enabled. Define GRAPHICS_API_OPENGL_43");
#endif #endif
} }
@ -4518,7 +4634,7 @@ Matrix rlGetMatrixTransform(void)
} }
// Get internal projection matrix for stereo render (selected eye) // Get internal projection matrix for stereo render (selected eye)
RLAPI Matrix rlGetMatrixProjectionStereo(int eye) Matrix rlGetMatrixProjectionStereo(int eye)
{ {
Matrix mat = rlMatrixIdentity(); Matrix mat = rlMatrixIdentity();
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@ -4528,7 +4644,7 @@ RLAPI Matrix rlGetMatrixProjectionStereo(int eye)
} }
// Get internal view offset matrix for stereo render (selected eye) // Get internal view offset matrix for stereo render (selected eye)
RLAPI Matrix rlGetMatrixViewOffsetStereo(int eye) Matrix rlGetMatrixViewOffsetStereo(int eye)
{ {
Matrix mat = rlMatrixIdentity(); Matrix mat = rlMatrixIdentity();
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@ -4754,7 +4870,16 @@ static void rlLoadShaderDefault(void)
"out vec2 fragTexCoord; \n" "out vec2 fragTexCoord; \n"
"out vec4 fragColor; \n" "out vec4 fragColor; \n"
#endif #endif
#if defined(GRAPHICS_API_OPENGL_ES2)
#if defined(GRAPHICS_API_OPENGL_ES3)
"#version 300 es \n"
"precision mediump float; \n" // Precision required for OpenGL ES3 (WebGL 2) (on some browsers)
"in vec3 vertexPosition; \n"
"in vec2 vertexTexCoord; \n"
"in vec4 vertexColor; \n"
"out vec2 fragTexCoord; \n"
"out vec4 fragColor; \n"
#elif defined(GRAPHICS_API_OPENGL_ES2)
"#version 100 \n" "#version 100 \n"
"precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) (on some browsers) "precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) (on some browsers)
"attribute vec3 vertexPosition; \n" "attribute vec3 vertexPosition; \n"
@ -4763,6 +4888,7 @@ static void rlLoadShaderDefault(void)
"varying vec2 fragTexCoord; \n" "varying vec2 fragTexCoord; \n"
"varying vec4 fragColor; \n" "varying vec4 fragColor; \n"
#endif #endif
"uniform mat4 mvp; \n" "uniform mat4 mvp; \n"
"void main() \n" "void main() \n"
"{ \n" "{ \n"
@ -4797,7 +4923,21 @@ static void rlLoadShaderDefault(void)
" finalColor = texelColor*colDiffuse*fragColor; \n" " finalColor = texelColor*colDiffuse*fragColor; \n"
"} \n"; "} \n";
#endif #endif
#if defined(GRAPHICS_API_OPENGL_ES2)
#if defined(GRAPHICS_API_OPENGL_ES3)
"#version 300 es \n"
"precision mediump float; \n" // Precision required for OpenGL ES3 (WebGL 2)
"in vec2 fragTexCoord; \n"
"in vec4 fragColor; \n"
"out vec4 finalColor; \n"
"uniform sampler2D texture0; \n"
"uniform vec4 colDiffuse; \n"
"void main() \n"
"{ \n"
" vec4 texelColor = texture(texture0, fragTexCoord); \n"
" finalColor = texelColor*colDiffuse*fragColor; \n"
"} \n";
#elif defined(GRAPHICS_API_OPENGL_ES2)
"#version 100 \n" "#version 100 \n"
"precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) "precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL)
"varying vec2 fragTexCoord; \n" "varying vec2 fragTexCoord; \n"
@ -4828,7 +4968,7 @@ static void rlLoadShaderDefault(void)
RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
// Set default shader locations: uniform locations // Set default shader locations: uniform locations
RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP); RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP);
RLGL.State.defaultShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR); RLGL.State.defaultShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR);
RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0); RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0);
} }
@ -4967,7 +5107,8 @@ static int rlGetPixelDataSize(int width, int height, int format)
default: break; default: break;
} }
dataSize = width*height*bpp/8; // Total data size in bytes double bytesPerPixel = (double)bpp/8.0;
dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
// Most compressed formats works on 4x4 blocks, // Most compressed formats works on 4x4 blocks,
// if texture is smaller, minimum dataSize is 8 or 16 // if texture is smaller, minimum dataSize is 8 or 16

View file

@ -127,6 +127,23 @@ func Viewport(x int32, y int32, width int32, height int32) {
C.rlViewport(cx, cy, cwidth, cheight) C.rlViewport(cx, cy, cwidth, cheight)
} }
// SetClipPlanes - Set clip planes distances
func SetClipPlanes(nearPlane, farPlane float64) {
C.rlSetClipPlanes(C.double(nearPlane), C.double(farPlane))
}
// GetCullDistanceNear - Get cull plane distance near
func GetCullDistanceNear() float64 {
ret := C.rlGetCullDistanceNear()
return float64(ret)
}
// GetCullDistanceFar - Get cull plane distance far
func GetCullDistanceFar() float64 {
ret := C.rlGetCullDistanceFar()
return float64(ret)
}
// Begin - Initialize drawing mode (how to organize vertex) // Begin - Initialize drawing mode (how to organize vertex)
func Begin(mode int32) { func Begin(mode int32) {
cmode := C.int(mode) cmode := C.int(mode)
@ -312,12 +329,27 @@ func DisableFramebuffer() {
C.rlDisableFramebuffer() C.rlDisableFramebuffer()
} }
// GetActiveFramebuffer - Get the currently active render texture (fbo), 0 for default framebuffer
func GetActiveFramebuffer() uint32 {
return uint32(C.rlGetActiveFramebuffer())
}
// ActiveDrawBuffers - Activate multiple draw color buffers // ActiveDrawBuffers - Activate multiple draw color buffers
func ActiveDrawBuffers(count int32) { func ActiveDrawBuffers(count int32) {
ccount := C.int(count) ccount := C.int(count)
C.rlActiveDrawBuffers(ccount) C.rlActiveDrawBuffers(ccount)
} }
// BlitFramebuffer - Blit active framebuffer to main framebuffer
func BlitFramebuffer(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask int32) {
C.rlBlitFramebuffer(C.int(srcX), C.int(srcY), C.int(srcWidth), C.int(srcHeight), C.int(dstX), C.int(dstY), C.int(dstWidth), C.int(dstHeight), C.int(bufferMask))
}
// BindFramebuffer - Bind framebuffer (FBO)
func BindFramebuffer(target, framebuffer uint32) {
C.rlBindFramebuffer(C.uint(target), C.uint(framebuffer))
}
// EnableColorBlend - Enable color blending // EnableColorBlend - Enable color blending
func EnableColorBlend() { func EnableColorBlend() {
C.rlEnableColorBlend() C.rlEnableColorBlend()
@ -358,6 +390,11 @@ func DisableBackfaceCulling() {
C.rlDisableBackfaceCulling() C.rlDisableBackfaceCulling()
} }
// ColorMask - Color mask control
func ColorMask(r, g, b, a bool) {
C.rlColorMask(C.bool(r), C.bool(g), C.bool(b), C.bool(a))
}
// SetCullFace - Set face culling mode // SetCullFace - Set face culling mode
func SetCullFace(mode int32) { func SetCullFace(mode int32) {
cmode := C.int(mode) cmode := C.int(mode)
@ -592,7 +629,7 @@ func LoadTextureDepth(width, height int32, useRenderBuffer bool) {
} }
// LoadFramebuffer - Load an empty framebuffer // LoadFramebuffer - Load an empty framebuffer
func LoadFramebuffer(width int32, height int32) uint32 { func LoadFramebuffer() uint32 {
return uint32(C.rlLoadFramebuffer()) return uint32(C.rlLoadFramebuffer())
} }
@ -664,6 +701,23 @@ func GetLocationAttrib(shaderId uint32, attribName string) int32 {
return int32(C.rlGetLocationAttrib(cshaderId, cattribName)) return int32(C.rlGetLocationAttrib(cshaderId, cattribName))
} }
// SetUniform - Set shader value uniform
func SetUniform(locIndex int32, value []float32, uniformType int32) {
C.rlSetUniform(C.int(locIndex), unsafe.Pointer(unsafe.SliceData(value)), C.int(uniformType), C.int((len(value))))
}
// SetUniformMatrix - Set shader value matrix
func SetUniformMatrix(locIndex int32, mat Matrix) {
cmat := (*C.Matrix)(unsafe.Pointer(&mat))
C.rlSetUniformMatrix(C.int(locIndex), *cmat)
}
// SetUniformMatrices - Set shader value matrices
func SetUniformMatrices(locIndex int32, mat []Matrix) {
cmat := (*C.Matrix)(unsafe.Pointer(unsafe.SliceData(mat)))
C.rlSetUniformMatrices(C.int(locIndex), cmat, C.int(len(mat)))
}
// SetUniformSampler - Set shader value sampler // SetUniformSampler - Set shader value sampler
func SetUniformSampler(locIndex int32, textureId uint32) { func SetUniformSampler(locIndex int32, textureId uint32) {
clocIndex := C.int(locIndex) clocIndex := C.int(locIndex)

View file

@ -20,6 +20,9 @@ var rlMultMatrixf func(matf *float32)
var rlFrustum func(left float64, right float64, bottom float64, top float64, znear float64, zfar float64) var rlFrustum func(left float64, right float64, bottom float64, top float64, znear float64, zfar float64)
var rlOrtho func(left float64, right float64, bottom float64, top float64, znear float64, zfar float64) var rlOrtho func(left float64, right float64, bottom float64, top float64, znear float64, zfar float64)
var rlViewport func(x int32, y int32, width int32, height int32) var rlViewport func(x int32, y int32, width int32, height int32)
var rlSetClipPlanes func(float64, float64)
var rlGetCullDistanceNear func() float64
var rlGetCullDistanceFar func() float64
var rlBegin func(mode int32) var rlBegin func(mode int32)
var rlEnd func() var rlEnd func()
var rlVertex2i func(x int32, y int32) var rlVertex2i func(x int32, y int32)
@ -49,7 +52,10 @@ var rlEnableShader func(id uint32)
var rlDisableShader func() var rlDisableShader func()
var rlEnableFramebuffer func(id uint32) var rlEnableFramebuffer func(id uint32)
var rlDisableFramebuffer func() var rlDisableFramebuffer func()
var rlGetActiveFramebuffer func() uint32
var rlActiveDrawBuffers func(count int32) var rlActiveDrawBuffers func(count int32)
var rlBlitFramebuffer func(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask int32)
var rlBindFramebuffer func(target, framebuffer uint32)
var rlEnableColorBlend func() var rlEnableColorBlend func()
var rlDisableColorBlend func() var rlDisableColorBlend func()
var rlEnableDepthTest func() var rlEnableDepthTest func()
@ -58,6 +64,7 @@ var rlEnableDepthMask func()
var rlDisableDepthMask func() var rlDisableDepthMask func()
var rlEnableBackfaceCulling func() var rlEnableBackfaceCulling func()
var rlDisableBackfaceCulling func() var rlDisableBackfaceCulling func()
var rlColorMask func(r, g, b, a bool)
var rlSetCullFace func(mode int32) var rlSetCullFace func(mode int32)
var rlEnableScissorTest func() var rlEnableScissorTest func()
var rlDisableScissorTest func() var rlDisableScissorTest func()
@ -98,7 +105,7 @@ var rlLoadVertexArray func() uint32
var rlUnloadVertexBuffer func(vboId uint32) var rlUnloadVertexBuffer func(vboId uint32)
var rlSetVertexAttributeDivisor func(index uint32, divisor int32) var rlSetVertexAttributeDivisor func(index uint32, divisor int32)
var rlLoadTextureDepth func(width int32, height int32, useRenderBuffer bool) uint32 var rlLoadTextureDepth func(width int32, height int32, useRenderBuffer bool) uint32
var rlLoadFramebuffer func(width int32, height int32) uint32 var rlLoadFramebuffer func() uint32
var rlFramebufferAttach func(fboId uint32, texId uint32, attachType int32, texType int32, mipLevel int32) var rlFramebufferAttach func(fboId uint32, texId uint32, attachType int32, texType int32, mipLevel int32)
var rlFramebufferComplete func(id uint32) bool var rlFramebufferComplete func(id uint32) bool
var rlUnloadFramebuffer func(id uint32) var rlUnloadFramebuffer func(id uint32)
@ -108,6 +115,9 @@ var rlLoadShaderProgram func(vShaderId uint32, fShaderId uint32) uint32
var rlUnloadShaderProgram func(id uint32) var rlUnloadShaderProgram func(id uint32)
var rlGetLocationUniform func(shaderId uint32, uniformName string) int32 var rlGetLocationUniform func(shaderId uint32, uniformName string) int32
var rlGetLocationAttrib func(shaderId uint32, attribName string) int32 var rlGetLocationAttrib func(shaderId uint32, attribName string) int32
var rlSetUniform func(locIndex int32, value unsafe.Pointer, uniformType, count int32)
var rlSetUniformMatrix func(locIndex int32, mat uintptr)
var rlSetUniformMatrices func(locIndex int32, mat *Matrix, count int32)
var rlSetUniformSampler func(locIndex int32, textureId uint32) var rlSetUniformSampler func(locIndex int32, textureId uint32)
var rlLoadComputeShaderProgram func(shaderID uint32) uint32 var rlLoadComputeShaderProgram func(shaderID uint32) uint32
var rlComputeShaderDispatch func(groupX uint32, groupY uint32, groupZ uint32) var rlComputeShaderDispatch func(groupX uint32, groupY uint32, groupZ uint32)
@ -143,6 +153,9 @@ func initRlglPurego() {
purego.RegisterLibFunc(&rlFrustum, raylibDll, "rlFrustum") purego.RegisterLibFunc(&rlFrustum, raylibDll, "rlFrustum")
purego.RegisterLibFunc(&rlOrtho, raylibDll, "rlOrtho") purego.RegisterLibFunc(&rlOrtho, raylibDll, "rlOrtho")
purego.RegisterLibFunc(&rlViewport, raylibDll, "rlViewport") purego.RegisterLibFunc(&rlViewport, raylibDll, "rlViewport")
purego.RegisterLibFunc(&rlSetClipPlanes, raylibDll, "rlSetClipPlanes")
purego.RegisterLibFunc(&rlGetCullDistanceNear, raylibDll, "rlGetCullDistanceNear")
purego.RegisterLibFunc(&rlGetCullDistanceFar, raylibDll, "rlGetCullDistanceFar")
purego.RegisterLibFunc(&rlBegin, raylibDll, "rlBegin") purego.RegisterLibFunc(&rlBegin, raylibDll, "rlBegin")
purego.RegisterLibFunc(&rlEnd, raylibDll, "rlEnd") purego.RegisterLibFunc(&rlEnd, raylibDll, "rlEnd")
purego.RegisterLibFunc(&rlVertex2i, raylibDll, "rlVertex2i") purego.RegisterLibFunc(&rlVertex2i, raylibDll, "rlVertex2i")
@ -172,7 +185,10 @@ func initRlglPurego() {
purego.RegisterLibFunc(&rlDisableShader, raylibDll, "rlDisableShader") purego.RegisterLibFunc(&rlDisableShader, raylibDll, "rlDisableShader")
purego.RegisterLibFunc(&rlEnableFramebuffer, raylibDll, "rlEnableFramebuffer") purego.RegisterLibFunc(&rlEnableFramebuffer, raylibDll, "rlEnableFramebuffer")
purego.RegisterLibFunc(&rlDisableFramebuffer, raylibDll, "rlDisableFramebuffer") purego.RegisterLibFunc(&rlDisableFramebuffer, raylibDll, "rlDisableFramebuffer")
purego.RegisterLibFunc(&rlGetActiveFramebuffer, raylibDll, "rlGetActiveFramebuffer")
purego.RegisterLibFunc(&rlActiveDrawBuffers, raylibDll, "rlActiveDrawBuffers") purego.RegisterLibFunc(&rlActiveDrawBuffers, raylibDll, "rlActiveDrawBuffers")
purego.RegisterLibFunc(&rlBlitFramebuffer, raylibDll, "rlBlitFramebuffer")
purego.RegisterLibFunc(&rlBindFramebuffer, raylibDll, "rlBindFramebuffer")
purego.RegisterLibFunc(&rlEnableColorBlend, raylibDll, "rlEnableColorBlend") purego.RegisterLibFunc(&rlEnableColorBlend, raylibDll, "rlEnableColorBlend")
purego.RegisterLibFunc(&rlDisableColorBlend, raylibDll, "rlDisableColorBlend") purego.RegisterLibFunc(&rlDisableColorBlend, raylibDll, "rlDisableColorBlend")
purego.RegisterLibFunc(&rlEnableDepthTest, raylibDll, "rlEnableDepthTest") purego.RegisterLibFunc(&rlEnableDepthTest, raylibDll, "rlEnableDepthTest")
@ -181,6 +197,7 @@ func initRlglPurego() {
purego.RegisterLibFunc(&rlDisableDepthMask, raylibDll, "rlDisableDepthMask") purego.RegisterLibFunc(&rlDisableDepthMask, raylibDll, "rlDisableDepthMask")
purego.RegisterLibFunc(&rlEnableBackfaceCulling, raylibDll, "rlEnableBackfaceCulling") purego.RegisterLibFunc(&rlEnableBackfaceCulling, raylibDll, "rlEnableBackfaceCulling")
purego.RegisterLibFunc(&rlDisableBackfaceCulling, raylibDll, "rlDisableBackfaceCulling") purego.RegisterLibFunc(&rlDisableBackfaceCulling, raylibDll, "rlDisableBackfaceCulling")
purego.RegisterLibFunc(&rlColorMask, raylibDll, "rlColorMask")
purego.RegisterLibFunc(&rlSetCullFace, raylibDll, "rlSetCullFace") purego.RegisterLibFunc(&rlSetCullFace, raylibDll, "rlSetCullFace")
purego.RegisterLibFunc(&rlEnableScissorTest, raylibDll, "rlEnableScissorTest") purego.RegisterLibFunc(&rlEnableScissorTest, raylibDll, "rlEnableScissorTest")
purego.RegisterLibFunc(&rlDisableScissorTest, raylibDll, "rlDisableScissorTest") purego.RegisterLibFunc(&rlDisableScissorTest, raylibDll, "rlDisableScissorTest")
@ -231,6 +248,9 @@ func initRlglPurego() {
purego.RegisterLibFunc(&rlUnloadShaderProgram, raylibDll, "rlUnloadShaderProgram") purego.RegisterLibFunc(&rlUnloadShaderProgram, raylibDll, "rlUnloadShaderProgram")
purego.RegisterLibFunc(&rlGetLocationUniform, raylibDll, "rlGetLocationUniform") purego.RegisterLibFunc(&rlGetLocationUniform, raylibDll, "rlGetLocationUniform")
purego.RegisterLibFunc(&rlGetLocationAttrib, raylibDll, "rlGetLocationAttrib") purego.RegisterLibFunc(&rlGetLocationAttrib, raylibDll, "rlGetLocationAttrib")
purego.RegisterLibFunc(&rlSetUniform, raylibDll, "rlSetUniform")
purego.RegisterLibFunc(&rlSetUniformMatrix, raylibDll, "rlSetUniformMatrix")
purego.RegisterLibFunc(&rlSetUniformMatrices, raylibDll, "rlSetUniformMatrices")
purego.RegisterLibFunc(&rlSetUniformSampler, raylibDll, "rlSetUniformSampler") purego.RegisterLibFunc(&rlSetUniformSampler, raylibDll, "rlSetUniformSampler")
purego.RegisterLibFunc(&rlLoadComputeShaderProgram, raylibDll, "rlLoadComputeShaderProgram") purego.RegisterLibFunc(&rlLoadComputeShaderProgram, raylibDll, "rlLoadComputeShaderProgram")
purego.RegisterLibFunc(&rlComputeShaderDispatch, raylibDll, "rlComputeShaderDispatch") purego.RegisterLibFunc(&rlComputeShaderDispatch, raylibDll, "rlComputeShaderDispatch")
@ -321,6 +341,21 @@ func Viewport(x int32, y int32, width int32, height int32) {
rlViewport(x, y, width, height) rlViewport(x, y, width, height)
} }
// SetClipPlanes - Set clip planes distances
func SetClipPlanes(nearPlane, farPlane float64) {
rlSetClipPlanes(nearPlane, farPlane)
}
// GetCullDistanceNear - Get cull plane distance near
func GetCullDistanceNear() float64 {
return rlGetCullDistanceNear()
}
// GetCullDistanceFar - Get cull plane distance far
func GetCullDistanceFar() float64 {
return rlGetCullDistanceFar()
}
// Begin - Initialize drawing mode (how to organize vertex) // Begin - Initialize drawing mode (how to organize vertex)
func Begin(mode int32) { func Begin(mode int32) {
rlBegin(mode) rlBegin(mode)
@ -466,11 +501,26 @@ func DisableFramebuffer() {
rlDisableFramebuffer() rlDisableFramebuffer()
} }
// GetActiveFramebuffer - Get the currently active render texture (fbo), 0 for default framebuffer
func GetActiveFramebuffer() uint32 {
return rlGetActiveFramebuffer()
}
// ActiveDrawBuffers - Activate multiple draw color buffers // ActiveDrawBuffers - Activate multiple draw color buffers
func ActiveDrawBuffers(count int32) { func ActiveDrawBuffers(count int32) {
rlActiveDrawBuffers(count) rlActiveDrawBuffers(count)
} }
// BlitFramebuffer - Blit active framebuffer to main framebuffer
func BlitFramebuffer(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask int32) {
rlBlitFramebuffer(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask)
}
// BindFramebuffer - Bind framebuffer (FBO)
func BindFramebuffer(target, framebuffer uint32) {
rlBindFramebuffer(target, framebuffer)
}
// EnableColorBlend - Enable color blending // EnableColorBlend - Enable color blending
func EnableColorBlend() { func EnableColorBlend() {
rlEnableColorBlend() rlEnableColorBlend()
@ -511,6 +561,11 @@ func DisableBackfaceCulling() {
rlDisableBackfaceCulling() rlDisableBackfaceCulling()
} }
// ColorMask - Color mask control
func ColorMask(r, g, b, a bool) {
rlColorMask(r, g, b, a)
}
// SetCullFace - Set face culling mode // SetCullFace - Set face culling mode
func SetCullFace(mode int32) { func SetCullFace(mode int32) {
rlSetCullFace(mode) rlSetCullFace(mode)
@ -714,8 +769,8 @@ func LoadTextureDepth(width, height int32, useRenderBuffer bool) {
} }
// LoadFramebuffer - Load an empty framebuffer // LoadFramebuffer - Load an empty framebuffer
func LoadFramebuffer(width int32, height int32) uint32 { func LoadFramebuffer() uint32 {
return rlLoadFramebuffer(width, height) return rlLoadFramebuffer()
} }
// FramebufferAttach - Attach texture/renderbuffer to a framebuffer // FramebufferAttach - Attach texture/renderbuffer to a framebuffer
@ -763,6 +818,21 @@ func GetLocationAttrib(shaderId uint32, attribName string) int32 {
return rlGetLocationAttrib(shaderId, attribName) return rlGetLocationAttrib(shaderId, attribName)
} }
// SetUniform - Set shader value uniform
func SetUniform(locIndex int32, value []float32, uniformType int32) {
rlSetUniform(locIndex, unsafe.Pointer(unsafe.SliceData(value)), uniformType, int32(len(value)))
}
// SetUniformMatrix - Set shader value matrix
func SetUniformMatrix(locIndex int32, mat Matrix) {
rlSetUniformMatrix(locIndex, uintptr(unsafe.Pointer(&mat)))
}
// SetUniformMatrices - Set shader value matrices
func SetUniformMatrices(locIndex int32, mat []Matrix) {
rlSetUniformMatrices(locIndex, unsafe.SliceData(mat), int32(len(mat)))
}
// SetUniformSampler - Set shader value sampler // SetUniformSampler - Set shader value sampler
func SetUniformSampler(locIndex int32, textureId uint32) { func SetUniformSampler(locIndex int32, textureId uint32) {
rlSetUniformSampler(locIndex, textureId) rlSetUniformSampler(locIndex, textureId)

File diff suppressed because it is too large Load diff

View file

@ -269,10 +269,10 @@ func LoadModelFromMesh(data Mesh) Model {
return v return v
} }
// IsModelReady - Check if a model is ready // IsModelValid - Check if a model is valid (loaded in GPU, VAO/VBOs)
func IsModelReady(model Model) bool { func IsModelValid(model Model) bool {
cmodel := model.cptr() cmodel := model.cptr()
ret := C.IsModelReady(*cmodel) ret := C.IsModelValid(*cmodel)
v := bool(ret) v := bool(ret)
return v return v
} }
@ -331,6 +331,26 @@ func DrawModelWiresEx(model Model, position Vector3, rotationAxis Vector3, rotat
C.DrawModelWiresEx(*cmodel, *cposition, *crotationAxis, crotationAngle, *cscale, *ctint) C.DrawModelWiresEx(*cmodel, *cposition, *crotationAxis, crotationAngle, *cscale, *ctint)
} }
// DrawModelPoints - Draw a model as points
func DrawModelPoints(model Model, position Vector3, scale float32, tint color.RGBA) {
cmodel := model.cptr()
cposition := position.cptr()
cscale := (C.float)(scale)
ctint := colorCptr(tint)
C.DrawModelPoints(*cmodel, *cposition, cscale, *ctint)
}
// DrawModelPointsEx - Draw a model as points with extended parameters
func DrawModelPointsEx(model Model, position Vector3, rotationAxis Vector3, rotationAngle float32, scale Vector3, tint color.RGBA) {
cmodel := model.cptr()
cposition := position.cptr()
crotationAxis := rotationAxis.cptr()
crotationAngle := (C.float)(rotationAngle)
cscale := scale.cptr()
ctint := colorCptr(tint)
C.DrawModelPointsEx(*cmodel, *cposition, *crotationAxis, crotationAngle, *cscale, *ctint)
}
// DrawBoundingBox - Draw bounding box (wires) // DrawBoundingBox - Draw bounding box (wires)
func DrawBoundingBox(box BoundingBox, col color.RGBA) { func DrawBoundingBox(box BoundingBox, col color.RGBA) {
cbox := box.cptr() cbox := box.cptr()
@ -339,13 +359,13 @@ func DrawBoundingBox(box BoundingBox, col color.RGBA) {
} }
// DrawBillboard - Draw a billboard texture // DrawBillboard - Draw a billboard texture
func DrawBillboard(camera Camera, texture Texture2D, center Vector3, size float32, tint color.RGBA) { func DrawBillboard(camera Camera, texture Texture2D, center Vector3, scale float32, tint color.RGBA) {
ccamera := camera.cptr() ccamera := camera.cptr()
ctexture := texture.cptr() ctexture := texture.cptr()
ccenter := center.cptr() ccenter := center.cptr()
csize := (C.float)(size) cscale := (C.float)(scale)
ctint := colorCptr(tint) ctint := colorCptr(tint)
C.DrawBillboard(*ccamera, *ctexture, *ccenter, csize, *ctint) C.DrawBillboard(*ccamera, *ctexture, *ccenter, cscale, *ctint)
} }
// DrawBillboardRec - Draw a billboard texture defined by sourceRec // DrawBillboardRec - Draw a billboard texture defined by sourceRec
@ -545,10 +565,10 @@ func LoadMaterialDefault() Material {
return v return v
} }
// IsMaterialReady - Check if a material is ready // IsMaterialValid - Check if a material is valid (shader assigned, map textures loaded in GPU)
func IsMaterialReady(material Material) bool { func IsMaterialValid(material Material) bool {
cmaterial := material.cptr() cmaterial := material.cptr()
ret := C.IsMaterialReady(*cmaterial) ret := C.IsMaterialValid(*cmaterial)
v := bool(ret) v := bool(ret)
return v return v
} }
@ -585,7 +605,7 @@ func LoadModelAnimations(fileName string) []ModelAnimation {
return v return v
} }
// UpdateModelAnimation - Update model animation pose // UpdateModelAnimation - Update model animation pose (CPU)
func UpdateModelAnimation(model Model, anim ModelAnimation, frame int32) { func UpdateModelAnimation(model Model, anim ModelAnimation, frame int32) {
cmodel := model.cptr() cmodel := model.cptr()
canim := anim.cptr() canim := anim.cptr()
@ -593,6 +613,14 @@ func UpdateModelAnimation(model Model, anim ModelAnimation, frame int32) {
C.UpdateModelAnimation(*cmodel, *canim, cframe) C.UpdateModelAnimation(*cmodel, *canim, cframe)
} }
// UpdateModelAnimationBones - Update model animation mesh bone matrices (GPU skinning)
func UpdateModelAnimationBones(model Model, anim ModelAnimation, frame int32) {
cmodel := model.cptr()
canim := anim.cptr()
cframe := (C.int)(frame)
C.UpdateModelAnimationBones(*cmodel, *canim, cframe)
}
// UnloadModelAnimation - Unload animation data // UnloadModelAnimation - Unload animation data
func UnloadModelAnimation(anim ModelAnimation) { func UnloadModelAnimation(anim ModelAnimation) {
canim := anim.cptr() canim := anim.cptr()

View file

@ -79,8 +79,8 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global Variables Definition // Global Variables Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (white pixel loaded by rlgl) static Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (white pixel loaded by rlgl)
Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing static Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Declaration // Module specific Functions Declaration
@ -126,7 +126,7 @@ Rectangle GetShapesTextureRectangle(void)
// Draw a pixel // Draw a pixel
void DrawPixel(int posX, int posY, Color color) void DrawPixel(int posX, int posY, Color color)
{ {
DrawPixelV((Vector2){ (float)posX, (float)posY }, color); DrawPixelV((Vector2){ (float)posX, (float)posY }, color);
} }
// Draw a pixel (Vector version) // Draw a pixel (Vector version)
@ -178,9 +178,8 @@ void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color colo
{ {
rlBegin(RL_LINES); rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
// WARNING: Adding 0.5f offset to "center" point on selected pixel rlVertex2f((float)startPosX, (float)startPosY);
rlVertex2f((float)startPosX + 0.5f, (float)startPosY + 0.5f); rlVertex2f((float)endPosX, (float)endPosY);
rlVertex2f((float)endPosX + 0.5f, (float)endPosY + 0.5f);
rlEnd(); rlEnd();
} }
@ -189,14 +188,13 @@ void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
{ {
rlBegin(RL_LINES); rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
// WARNING: Adding 0.5f offset to "center" point on selected pixel rlVertex2f(startPos.x, startPos.y);
rlVertex2f(startPos.x + 0.5f, startPos.y + 0.5f); rlVertex2f(endPos.x, endPos.y);
rlVertex2f(endPos.x + 0.5f, endPos.y + 0.5f);
rlEnd(); rlEnd();
} }
// Draw lines sequuence (using gl lines) // Draw lines sequuence (using gl lines)
void DrawLineStrip(Vector2 *points, int pointCount, Color color) void DrawLineStrip(const Vector2 *points, int pointCount, Color color)
{ {
if (pointCount < 2) return; // Security check if (pointCount < 2) return; // Security check
@ -339,7 +337,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
} }
// NOTE: In case number of segments is odd, we add one last piece to the cake // NOTE: In case number of segments is odd, we add one last piece to the cake
if (((unsigned int)segments%2) == 1) if ((((unsigned int)segments)%2) == 1)
{ {
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
@ -432,17 +430,16 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float
} }
// Draw a gradient-filled circle // Draw a gradient-filled circle
// NOTE: Gradient goes from center (color1) to border (color2) void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer)
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
{ {
rlBegin(RL_TRIANGLES); rlBegin(RL_TRIANGLES);
for (int i = 0; i < 360; i += 10) for (int i = 0; i < 360; i += 10)
{ {
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlColor4ub(inner.r, inner.g, inner.b, inner.a);
rlVertex2f((float)centerX, (float)centerY); rlVertex2f((float)centerX, (float)centerY);
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlColor4ub(outer.r, outer.g, outer.b, outer.a);
rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius); rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius);
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlColor4ub(outer.r, outer.g, outer.b, outer.a);
rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius); rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius);
} }
rlEnd(); rlEnd();
@ -763,22 +760,19 @@ void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color
} }
// Draw a vertical-gradient-filled rectangle // Draw a vertical-gradient-filled rectangle
// NOTE: Gradient goes from bottom (color1) to top (color2) void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom)
void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
{ {
DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color2, color2, color1); DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, top, bottom, bottom, top);
} }
// Draw a horizontal-gradient-filled rectangle // Draw a horizontal-gradient-filled rectangle
// NOTE: Gradient goes from bottom (color1) to top (color2) void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right)
void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2)
{ {
DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color1, color2, color2); DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, left, left, right, right);
} }
// Draw a gradient-filled rectangle // Draw a gradient-filled rectangle
// NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight)
void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
{ {
rlSetTexture(GetShapesTexture().id); rlSetTexture(GetShapesTexture().id);
Rectangle shapeRect = GetShapesTextureRectangle(); Rectangle shapeRect = GetShapesTextureRectangle();
@ -787,19 +781,19 @@ void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3,
rlNormal3f(0.0f, 0.0f, 1.0f); rlNormal3f(0.0f, 0.0f, 1.0f);
// NOTE: Default raylib font character 95 is a white square // NOTE: Default raylib font character 95 is a white square
rlColor4ub(col1.r, col1.g, col1.b, col1.a); rlColor4ub(topLeft.r, topLeft.g, topLeft.b, topLeft.a);
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
rlVertex2f(rec.x, rec.y); rlVertex2f(rec.x, rec.y);
rlColor4ub(col2.r, col2.g, col2.b, col2.a); rlColor4ub(bottomLeft.r, bottomLeft.g, bottomLeft.b, bottomLeft.a);
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
rlVertex2f(rec.x, rec.y + rec.height); rlVertex2f(rec.x, rec.y + rec.height);
rlColor4ub(col3.r, col3.g, col3.b, col3.a); rlColor4ub(topRight.r, topRight.g, topRight.b, topRight.a);
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
rlVertex2f(rec.x + rec.width, rec.y + rec.height); rlVertex2f(rec.x + rec.width, rec.y + rec.height);
rlColor4ub(col4.r, col4.g, col4.b, col4.a); rlColor4ub(bottomRight.r, bottomRight.g, bottomRight.b, bottomRight.a);
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
rlVertex2f(rec.x + rec.width, rec.y); rlVertex2f(rec.x + rec.width, rec.y);
rlEnd(); rlEnd();
@ -813,6 +807,30 @@ void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3,
// but it solves another issue: https://github.com/raysan5/raylib/issues/3884 // but it solves another issue: https://github.com/raysan5/raylib/issues/3884
void DrawRectangleLines(int posX, int posY, int width, int height, Color color) void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
{ {
Matrix mat = rlGetMatrixModelview();
float zoomFactor = 0.5f/mat.m0;
rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2f((float)posX - zoomFactor, (float)posY);
rlVertex2f((float)posX + (float)width + zoomFactor, (float)posY);
rlVertex2f((float)posX + (float)width, (float)posY - zoomFactor);
rlVertex2f((float)posX + (float)width, (float)posY + (float)height + zoomFactor);
rlVertex2f((float)posX + (float)width + zoomFactor, (float)posY + (float)height);
rlVertex2f((float)posX - zoomFactor, (float)posY + (float)height);
rlVertex2f((float)posX, (float)posY + (float)height + zoomFactor);
rlVertex2f((float)posX, (float)posY - zoomFactor);
rlEnd();
/*
// Previous implementation, it has issues... but it does not require view matrix...
#if defined(SUPPORT_QUADS_DRAW_MODE)
DrawRectangle(posX, posY, width, 1, color);
DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, color);
DrawRectangle(posX, posY + height - 1, width, 1, color);
DrawRectangle(posX, posY + 1, 1, height - 2, color);
#else
rlBegin(RL_LINES); rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2f((float)posX, (float)posY); rlVertex2f((float)posX, (float)posY);
@ -827,6 +845,8 @@ void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
rlVertex2f((float)posX + 1, (float)posY + (float)height); rlVertex2f((float)posX + 1, (float)posY + (float)height);
rlVertex2f((float)posX + 1, (float)posY + 1); rlVertex2f((float)posX + 1, (float)posY + 1);
rlEnd(); rlEnd();
//#endif
*/
} }
// Draw rectangle outline with extended parameters // Draw rectangle outline with extended parameters
@ -834,8 +854,8 @@ void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color)
{ {
if ((lineThick > rec.width) || (lineThick > rec.height)) if ((lineThick > rec.width) || (lineThick > rec.height))
{ {
if (rec.width > rec.height) lineThick = rec.height/2; if (rec.width >= rec.height) lineThick = rec.height/2;
else if (rec.width < rec.height) lineThick = rec.width/2; else if (rec.width <= rec.height) lineThick = rec.width/2;
} }
// When rec = { x, y, 8.0f, 6.0f } and lineThick = 2, the following // When rec = { x, y, 8.0f, 6.0f } and lineThick = 2, the following
@ -1385,7 +1405,7 @@ void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
// Draw a triangle fan defined by points // Draw a triangle fan defined by points
// NOTE: First vertex provided is the center, shared by all triangles // NOTE: First vertex provided is the center, shared by all triangles
// By default, following vertex should be provided in counter-clockwise order // By default, following vertex should be provided in counter-clockwise order
void DrawTriangleFan(Vector2 *points, int pointCount, Color color) void DrawTriangleFan(const Vector2 *points, int pointCount, Color color)
{ {
if (pointCount >= 3) if (pointCount >= 3)
{ {
@ -1416,7 +1436,7 @@ void DrawTriangleFan(Vector2 *points, int pointCount, Color color)
// Draw a triangle strip defined by points // Draw a triangle strip defined by points
// NOTE: Every new vertex connects with previous two // NOTE: Every new vertex connects with previous two
void DrawTriangleStrip(Vector2 *points, int pointCount, Color color) void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color)
{ {
if (pointCount >= 3) if (pointCount >= 3)
{ {
@ -1570,7 +1590,7 @@ void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, fl
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw spline: linear, minimum 2 points // Draw spline: linear, minimum 2 points
void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color) void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color)
{ {
if (pointCount < 2) return; if (pointCount < 2) return;
@ -1656,7 +1676,7 @@ void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color)
prevNormal = normal; prevNormal = normal;
} }
#else // !SUPPORT_SPLINE_MITTERS #else // !SUPPORT_SPLINE_MITERS
Vector2 delta = { 0 }; Vector2 delta = { 0 };
float length = 0.0f; float length = 0.0f;
@ -1687,7 +1707,7 @@ void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color)
} }
// Draw spline: B-Spline, minimum 4 points // Draw spline: B-Spline, minimum 4 points
void DrawSplineBasis(Vector2 *points, int pointCount, float thick, Color color) void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color)
{ {
if (pointCount < 4) return; if (pointCount < 4) return;
@ -1759,11 +1779,12 @@ void DrawSplineBasis(Vector2 *points, int pointCount, float thick, Color color)
DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color); DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
} }
DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap // Cap circle drawing at the end of every segment
DrawCircleV(currentPoint, thick/2.0f, color);
} }
// Draw spline: Catmull-Rom, minimum 4 points // Draw spline: Catmull-Rom, minimum 4 points
void DrawSplineCatmullRom(Vector2 *points, int pointCount, float thick, Color color) void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color)
{ {
if (pointCount < 4) return; if (pointCount < 4) return;
@ -1825,28 +1846,31 @@ void DrawSplineCatmullRom(Vector2 *points, int pointCount, float thick, Color co
DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color); DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
} }
DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap // Cap circle drawing at the end of every segment
DrawCircleV(currentPoint, thick/2.0f, color);
} }
// Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
void DrawSplineBezierQuadratic(Vector2 *points, int pointCount, float thick, Color color) void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color)
{ {
if (pointCount < 3) return; if (pointCount >= 3)
for (int i = 0; i < pointCount - 2; i++)
{ {
DrawSplineSegmentBezierQuadratic(points[i], points[i + 1], points[i + 2], thick, color); for (int i = 0; i < pointCount - 2; i += 2) DrawSplineSegmentBezierQuadratic(points[i], points[i + 1], points[i + 2], thick, color);
// Cap circle drawing at the end of every segment
//for (int i = 2; i < pointCount - 2; i += 2) DrawCircleV(points[i], thick/2.0f, color);
} }
} }
// Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
void DrawSplineBezierCubic(Vector2 *points, int pointCount, float thick, Color color) void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color)
{ {
if (pointCount < 4) return; if (pointCount >= 4)
for (int i = 0; i < pointCount - 3; i++)
{ {
DrawSplineSegmentBezierCubic(points[i], points[i + 1], points[i + 2], points[i + 3], thick, color); for (int i = 0; i < pointCount - 3; i += 3) DrawSplineSegmentBezierCubic(points[i], points[i + 1], points[i + 2], points[i + 3], thick, color);
// Cap circle drawing at the end of every segment
//for (int i = 3; i < pointCount - 3; i += 3) DrawCircleV(points[i], thick/2.0f, color);
} }
} }
@ -2170,7 +2194,9 @@ bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius)
{ {
bool collision = false; bool collision = false;
collision = CheckCollisionCircles(point, 0, center, radius); float distanceSquared = (point.x - center.x)*(point.x - center.x) + (point.y - center.y)*(point.y - center.y);
if (distanceSquared <= radius*radius) collision = true;
return collision; return collision;
} }
@ -2195,7 +2221,7 @@ bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2
// Check if point is within a polygon described by array of vertices // Check if point is within a polygon described by array of vertices
// NOTE: Based on http://jeffreythompson.org/collision-detection/poly-point.php // NOTE: Based on http://jeffreythompson.org/collision-detection/poly-point.php
bool CheckCollisionPointPoly(Vector2 point, Vector2 *points, int pointCount) bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount)
{ {
bool inside = false; bool inside = false;
@ -2233,9 +2259,10 @@ bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, floa
float dx = center2.x - center1.x; // X distance between centers float dx = center2.x - center1.x; // X distance between centers
float dy = center2.y - center1.y; // Y distance between centers float dy = center2.y - center1.y; // Y distance between centers
float distance = sqrtf(dx*dx + dy*dy); // Distance between centers float distanceSquared = dx*dx + dy*dy; // Distance between centers squared
float radiusSum = radius1 + radius2;
if (distance <= (radius1 + radius2)) collision = true; collision = (distanceSquared <= (radiusSum*radiusSum));
return collision; return collision;
} }
@ -2315,6 +2342,30 @@ bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshol
return collision; return collision;
} }
// Check if circle collides with a line created betweeen two points [p1] and [p2]
RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2)
{
float dx = p1.x - p2.x;
float dy = p1.y - p2.y;
if ((fabsf(dx) + fabsf(dy)) <= FLT_EPSILON)
{
return CheckCollisionCircles(p1, 0, center, radius);
}
float lengthSQ = ((dx*dx) + (dy*dy));
float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ);
if (dotProduct > 1.0f) dotProduct = 1.0f;
else if (dotProduct < 0.0f) dotProduct = 0.0f;
float dx2 = (p1.x - (dotProduct*(dx))) - center.x;
float dy2 = (p1.y - (dotProduct*(dy))) - center.y;
float distanceSQ = ((dx2*dx2) + (dy2*dy2));
return (distanceSQ <= radius*radius);
}
// Get collision rectangle for two rectangles collision // Get collision rectangle for two rectangles collision
Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2) Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
{ {

View file

@ -17,6 +17,20 @@ func SetShapesTexture(texture Texture2D, source Rectangle) {
C.SetShapesTexture(*ctexture, *csource) C.SetShapesTexture(*ctexture, *csource)
} }
// GetShapesTexture - Get texture that is used for shapes drawing
func GetShapesTexture() Texture2D {
ret := C.GetShapesTexture()
v := newTexture2DFromPointer(unsafe.Pointer(&ret))
return v
}
// GetShapesTextureRectangle - Get texture source rectangle that is used for shapes drawing
func GetShapesTextureRectangle() Rectangle {
ret := C.GetShapesTextureRectangle()
v := newRectangleFromPointer(unsafe.Pointer(&ret))
return v
}
// DrawPixel - Draw a pixel // DrawPixel - Draw a pixel
func DrawPixel(posX, posY int32, col color.RGBA) { func DrawPixel(posX, posY int32, col color.RGBA) {
cposX := (C.int)(posX) cposX := (C.int)(posX)
@ -108,13 +122,13 @@ func DrawCircleSectorLines(center Vector2, radius, startAngle, endAngle float32,
} }
// DrawCircleGradient - Draw a gradient-filled circle // DrawCircleGradient - Draw a gradient-filled circle
func DrawCircleGradient(centerX, centerY int32, radius float32, col1, col2 color.RGBA) { func DrawCircleGradient(centerX, centerY int32, radius float32, inner, outer color.RGBA) {
ccenterX := (C.int)(centerX) ccenterX := (C.int)(centerX)
ccenterY := (C.int)(centerY) ccenterY := (C.int)(centerY)
cradius := (C.float)(radius) cradius := (C.float)(radius)
ccolor1 := colorCptr(col1) cinner := colorCptr(inner)
ccolor2 := colorCptr(col2) couter := colorCptr(outer)
C.DrawCircleGradient(ccenterX, ccenterY, cradius, *ccolor1, *ccolor2) C.DrawCircleGradient(ccenterX, ccenterY, cradius, *cinner, *couter)
} }
// DrawCircleV - Draw a color-filled circle (Vector version) // DrawCircleV - Draw a color-filled circle (Vector version)
@ -221,35 +235,35 @@ func DrawRectanglePro(rec Rectangle, origin Vector2, rotation float32, col color
} }
// DrawRectangleGradientV - Draw a vertical-gradient-filled rectangle // DrawRectangleGradientV - Draw a vertical-gradient-filled rectangle
func DrawRectangleGradientV(posX, posY, width, height int32, col1, col2 color.RGBA) { func DrawRectangleGradientV(posX, posY, width, height int32, top, bottom color.RGBA) {
cposX := (C.int)(posX) cposX := (C.int)(posX)
cposY := (C.int)(posY) cposY := (C.int)(posY)
cwidth := (C.int)(width) cwidth := (C.int)(width)
cheight := (C.int)(height) cheight := (C.int)(height)
ccolor1 := colorCptr(col1) ctop := colorCptr(top)
ccolor2 := colorCptr(col2) cbottom := colorCptr(bottom)
C.DrawRectangleGradientV(cposX, cposY, cwidth, cheight, *ccolor1, *ccolor2) C.DrawRectangleGradientV(cposX, cposY, cwidth, cheight, *ctop, *cbottom)
} }
// DrawRectangleGradientH - Draw a horizontal-gradient-filled rectangle // DrawRectangleGradientH - Draw a horizontal-gradient-filled rectangle
func DrawRectangleGradientH(posX, posY, width, height int32, col1, col2 color.RGBA) { func DrawRectangleGradientH(posX, posY, width, height int32, left, right color.RGBA) {
cposX := (C.int)(posX) cposX := (C.int)(posX)
cposY := (C.int)(posY) cposY := (C.int)(posY)
cwidth := (C.int)(width) cwidth := (C.int)(width)
cheight := (C.int)(height) cheight := (C.int)(height)
ccolor1 := colorCptr(col1) cleft := colorCptr(left)
ccolor2 := colorCptr(col2) cright := colorCptr(right)
C.DrawRectangleGradientH(cposX, cposY, cwidth, cheight, *ccolor1, *ccolor2) C.DrawRectangleGradientH(cposX, cposY, cwidth, cheight, *cleft, *cright)
} }
// DrawRectangleGradientEx - Draw a gradient-filled rectangle with custom vertex colors // DrawRectangleGradientEx - Draw a gradient-filled rectangle with custom vertex colors
func DrawRectangleGradientEx(rec Rectangle, col1, col2, col3, col4 color.RGBA) { func DrawRectangleGradientEx(rec Rectangle, topLeft, bottomLeft, topRight, bottomRight color.RGBA) {
crec := rec.cptr() crec := rec.cptr()
ccolor1 := colorCptr(col1) ctopLeft := colorCptr(topLeft)
ccolor2 := colorCptr(col2) cbottomLeft := colorCptr(bottomLeft)
ccolor3 := colorCptr(col3) ctopRight := colorCptr(topRight)
ccolor4 := colorCptr(col4) cbottomRight := colorCptr(bottomRight)
C.DrawRectangleGradientEx(*crec, *ccolor1, *ccolor2, *ccolor3, *ccolor4) C.DrawRectangleGradientEx(*crec, *ctopLeft, *cbottomLeft, *ctopRight, *cbottomRight)
} }
// DrawRectangleLines - Draw rectangle outline // DrawRectangleLines - Draw rectangle outline
@ -279,8 +293,8 @@ func DrawRectangleRounded(rec Rectangle, roundness float32, segments int32, col
C.DrawRectangleRounded(*crec, croundness, csegments, *ccolor) C.DrawRectangleRounded(*crec, croundness, csegments, *ccolor)
} }
// DrawRectangleRoundedLines - Draw rectangle with rounded edges outline // DrawRectangleRoundedLines - Draw rectangle lines with rounded edges
func DrawRectangleRoundedLines(rec Rectangle, roundness float32, segments, lineThick float32, col color.RGBA) { func DrawRectangleRoundedLines(rec Rectangle, roundness float32, segments int32, col color.RGBA) {
crec := rec.cptr() crec := rec.cptr()
croundness := (C.float)(roundness) croundness := (C.float)(roundness)
csegments := (C.int)(segments) csegments := (C.int)(segments)
@ -288,6 +302,16 @@ func DrawRectangleRoundedLines(rec Rectangle, roundness float32, segments, lineT
C.DrawRectangleRoundedLines(*crec, croundness, csegments, *ccolor) C.DrawRectangleRoundedLines(*crec, croundness, csegments, *ccolor)
} }
// DrawRectangleRoundedLinesEx - Draw rectangle with rounded edges outline
func DrawRectangleRoundedLinesEx(rec Rectangle, roundness float32, segments int32, lineThick float32, col color.RGBA) {
crec := rec.cptr()
croundness := (C.float)(roundness)
csegments := (C.int)(segments)
clineThick := (C.float)(lineThick)
ccolor := colorCptr(col)
C.DrawRectangleRoundedLinesEx(*crec, croundness, csegments, clineThick, *ccolor)
}
// DrawTriangle - Draw a color-filled triangle // DrawTriangle - Draw a color-filled triangle
func DrawTriangle(v1, v2, v3 Vector2, col color.RGBA) { func DrawTriangle(v1, v2, v3 Vector2, col color.RGBA) {
cv1 := v1.cptr() cv1 := v1.cptr()
@ -537,6 +561,17 @@ func CheckCollisionCircleRec(center Vector2, radius float32, rec Rectangle) bool
return v return v
} }
// CheckCollisionCircleLine - Check if circle collides with a line created betweeen two points [p1] and [p2]
func CheckCollisionCircleLine(center Vector2, radius float32, p1, p2 Vector2) bool {
ccenter := center.cptr()
cradius := (C.float)(radius)
cp1 := p1.cptr()
cp2 := p2.cptr()
ret := C.CheckCollisionCircleLine(*ccenter, cradius, *cp1, *cp2)
v := bool(ret)
return v
}
// CheckCollisionPointRec - Check if point is inside rectangle // CheckCollisionPointRec - Check if point is inside rectangle
func CheckCollisionPointRec(point Vector2, rec Rectangle) bool { func CheckCollisionPointRec(point Vector2, rec Rectangle) bool {
cpoint := point.cptr() cpoint := point.cptr()

View file

@ -124,6 +124,7 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global variables // Global variables
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
extern bool isGpuReady;
#if defined(SUPPORT_DEFAULT_FONT) #if defined(SUPPORT_DEFAULT_FONT)
// Default font provided by raylib // Default font provided by raylib
// NOTE: Default font is loaded on InitWindow() and disposed on CloseWindow() [module: core] // NOTE: Default font is loaded on InitWindow() and disposed on CloseWindow() [module: core]
@ -252,15 +253,15 @@ extern void LoadFontDefault(void)
counter++; counter++;
} }
defaultFont.texture = LoadTextureFromImage(imFont); if (isGpuReady) defaultFont.texture = LoadTextureFromImage(imFont);
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount // Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Allocate space for our characters info data // Allocate space for our characters info data
// NOTE: This memory must be freed at end! --> Done by CloseWindow() // NOTE: This memory must be freed at end! --> Done by CloseWindow()
defaultFont.glyphs = (GlyphInfo *)RL_MALLOC(defaultFont.glyphCount*sizeof(GlyphInfo)); defaultFont.glyphs = (GlyphInfo *)RL_CALLOC(defaultFont.glyphCount, sizeof(GlyphInfo));
defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.glyphCount*sizeof(Rectangle)); defaultFont.recs = (Rectangle *)RL_CALLOC(defaultFont.glyphCount, sizeof(Rectangle));
int currentLine = 0; int currentLine = 0;
int currentPosX = charsDivisor; int currentPosX = charsDivisor;
@ -308,7 +309,7 @@ extern void LoadFontDefault(void)
extern void UnloadFontDefault(void) extern void UnloadFontDefault(void)
{ {
for (int i = 0; i < defaultFont.glyphCount; i++) UnloadImage(defaultFont.glyphs[i].image); for (int i = 0; i < defaultFont.glyphCount; i++) UnloadImage(defaultFont.glyphs[i].image);
UnloadTexture(defaultFont.texture); if (isGpuReady) UnloadTexture(defaultFont.texture);
RL_FREE(defaultFont.glyphs); RL_FREE(defaultFont.glyphs);
RL_FREE(defaultFont.recs); RL_FREE(defaultFont.recs);
} }
@ -362,15 +363,14 @@ Font LoadFont(const char *fileName)
UnloadImage(image); UnloadImage(image);
} }
if (font.texture.id == 0) if (isGpuReady)
{ {
TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName); if (font.texture.id == 0) TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName);
font = GetFontDefault(); else
} {
else SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default, we set point filter (the best performance)
{ TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS);
SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default, we set point filter (the best performance) }
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS);
} }
return font; return font;
@ -394,7 +394,6 @@ Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepoi
UnloadFileData(fileData); UnloadFileData(fileData);
} }
else font = GetFontDefault();
return font; return font;
} }
@ -492,7 +491,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
}; };
// Set font with all data parsed from image // Set font with all data parsed from image
font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture if (isGpuReady) font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
font.glyphCount = index; font.glyphCount = index;
font.glyphPadding = 0; font.glyphPadding = 0;
@ -561,7 +560,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING; font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0); Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0);
font.texture = LoadTextureFromImage(atlas); if (isGpuReady) font.texture = LoadTextureFromImage(atlas);
// Update glyphs[i].image to use alpha, required to be used on ImageDrawText() // Update glyphs[i].image to use alpha, required to be used on ImageDrawText()
for (int i = 0; i < font.glyphCount; i++) for (int i = 0; i < font.glyphCount; i++)
@ -582,17 +581,16 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
return font; return font;
} }
// Check if a font is ready // Check if a font is valid (font data loaded)
bool IsFontReady(Font font) // WARNING: GPU texture not checked
bool IsFontValid(Font font)
{ {
return ((font.texture.id > 0) && // Validate OpenGL id fot font texture atlas return ((font.baseSize > 0) && // Validate font size
(font.baseSize > 0) && // Validate font size
(font.glyphCount > 0) && // Validate font contains some glyph (font.glyphCount > 0) && // Validate font contains some glyph
(font.recs != NULL) && // Validate font recs defining glyphs on texture atlas (font.recs != NULL) && // Validate font recs defining glyphs on texture atlas
(font.glyphs != NULL)); // Validate glyph data is loaded (font.glyphs != NULL)); // Validate glyph data is loaded
// NOTE: Further validations could be done to verify if recs count and glyphs count // NOTE: Further validations could be done to verify if recs and glyphs contain valid data (glyphs values, metrics...)
// match glyphCount and to verify that data contained is valid (glyphs values, metrics...)
} }
// Load font data for further use // Load font data for further use
@ -679,6 +677,8 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL); stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor); chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor);
if (chh > fontSize) TRACELOG(LOG_WARNING, "FONT: Character [0x%08x] size is bigger than expected font size", ch);
// Load characters images // Load characters images
chars[i].image.width = chw; chars[i].image.width = chw;
chars[i].image.height = chh; chars[i].image.height = chh;
@ -951,7 +951,7 @@ void UnloadFont(Font font)
if (font.texture.id != GetFontDefault().texture.id) if (font.texture.id != GetFontDefault().texture.id)
{ {
UnloadFontData(font.glyphs, font.glyphCount); UnloadFontData(font.glyphs, font.glyphCount);
UnloadTexture(font.texture); if (isGpuReady) UnloadTexture(font.texture);
RL_FREE(font.recs); RL_FREE(font.recs);
TRACELOGD("FONT: Unloaded font data from RAM and VRAM"); TRACELOGD("FONT: Unloaded font data from RAM and VRAM");
@ -1035,7 +1035,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
// Save font recs data // Save font recs data
byteCount += sprintf(txtData + byteCount, "// Font characters rectangles data\n"); byteCount += sprintf(txtData + byteCount, "// Font characters rectangles data\n");
byteCount += sprintf(txtData + byteCount, "static const Rectangle fontRecs_%s[%i] = {\n", fileNamePascal, font.glyphCount); byteCount += sprintf(txtData + byteCount, "static Rectangle fontRecs_%s[%i] = {\n", fileNamePascal, font.glyphCount);
for (int i = 0; i < font.glyphCount; i++) for (int i = 0; i < font.glyphCount; i++)
{ {
byteCount += sprintf(txtData + byteCount, " { %1.0f, %1.0f, %1.0f , %1.0f },\n", font.recs[i].x, font.recs[i].y, font.recs[i].width, font.recs[i].height); byteCount += sprintf(txtData + byteCount, " { %1.0f, %1.0f, %1.0f , %1.0f },\n", font.recs[i].x, font.recs[i].y, font.recs[i].width, font.recs[i].height);
@ -1047,7 +1047,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
// it could be generated from image and recs // it could be generated from image and recs
byteCount += sprintf(txtData + byteCount, "// Font glyphs info data\n"); byteCount += sprintf(txtData + byteCount, "// Font glyphs info data\n");
byteCount += sprintf(txtData + byteCount, "// NOTE: No glyphs.image data provided\n"); byteCount += sprintf(txtData + byteCount, "// NOTE: No glyphs.image data provided\n");
byteCount += sprintf(txtData + byteCount, "static const GlyphInfo fontGlyphs_%s[%i] = {\n", fileNamePascal, font.glyphCount); byteCount += sprintf(txtData + byteCount, "static GlyphInfo fontGlyphs_%s[%i] = {\n", fileNamePascal, font.glyphCount);
for (int i = 0; i < font.glyphCount; i++) for (int i = 0; i < font.glyphCount; i++)
{ {
byteCount += sprintf(txtData + byteCount, " { %i, %i, %i, %i, { 0 }},\n", font.glyphs[i].value, font.glyphs[i].offsetX, font.glyphs[i].offsetY, font.glyphs[i].advanceX); byteCount += sprintf(txtData + byteCount, " { %i, %i, %i, %i, { 0 }},\n", font.glyphs[i].value, font.glyphs[i].offsetX, font.glyphs[i].offsetY, font.glyphs[i].advanceX);
@ -1071,7 +1071,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
byteCount += sprintf(txtData + byteCount, " Image imFont = { fontImageData_%s, %i, %i, 1, %i };\n\n", styleName, image.width, image.height, image.format); byteCount += sprintf(txtData + byteCount, " Image imFont = { fontImageData_%s, %i, %i, 1, %i };\n\n", styleName, image.width, image.height, image.format);
#endif #endif
byteCount += sprintf(txtData + byteCount, " // Load texture from image\n"); byteCount += sprintf(txtData + byteCount, " // Load texture from image\n");
byteCount += sprintf(txtData + byteCount, " font.texture = LoadTextureFromImage(imFont);\n"); byteCount += sprintf(txtData + byteCount, " if (isGpuReady) font.texture = LoadTextureFromImage(imFont);\n");
#if defined(SUPPORT_COMPRESSED_FONT_ATLAS) #if defined(SUPPORT_COMPRESSED_FONT_ATLAS)
byteCount += sprintf(txtData + byteCount, " UnloadImage(imFont); // Uncompressed data can be unloaded from memory\n\n"); byteCount += sprintf(txtData + byteCount, " UnloadImage(imFont); // Uncompressed data can be unloaded from memory\n\n");
#endif #endif
@ -1282,7 +1282,8 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
{ {
Vector2 textSize = { 0 }; Vector2 textSize = { 0 };
if ((font.texture.id == 0) || (text == NULL)) return textSize; // Security check if ((isGpuReady && (font.texture.id == 0)) ||
(text == NULL) || (text[0] == '\0')) return textSize; // Security check
int size = TextLength(text); // Get size in bytes of text int size = TextLength(text); // Get size in bytes of text
int tempByteCounter = 0; // Used to count longer text line num chars int tempByteCounter = 0; // Used to count longer text line num chars
@ -1301,15 +1302,15 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
{ {
byteCounter++; byteCounter++;
int next = 0; int codepointByteCount = 0;
letter = GetCodepointNext(&text[i], &next); letter = GetCodepointNext(&text[i], &codepointByteCount);
index = GetGlyphIndex(font, letter); index = GetGlyphIndex(font, letter);
i += next; i += codepointByteCount;
if (letter != '\n') if (letter != '\n')
{ {
if (font.glyphs[index].advanceX != 0) textWidth += font.glyphs[index].advanceX; if (font.glyphs[index].advanceX > 0) textWidth += font.glyphs[index].advanceX;
else textWidth += (font.recs[index].width + font.glyphs[index].offsetX); else textWidth += (font.recs[index].width + font.glyphs[index].offsetX);
} }
else else
@ -1472,8 +1473,7 @@ float TextToFloat(const char *text)
int i = 0; int i = 0;
for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0'); for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0');
if (text[i++] != '.') value *= sign; if (text[i++] == '.')
else
{ {
float divisor = 10.0f; float divisor = 10.0f;
for (; ((text[i] >= '0') && (text[i] <= '9')); i++) for (; ((text[i] >= '0') && (text[i] <= '9')); i++)
@ -1483,7 +1483,7 @@ float TextToFloat(const char *text)
} }
} }
return value; return value*sign;
} }
#if defined(SUPPORT_TEXT_MANIPULATION) #if defined(SUPPORT_TEXT_MANIPULATION)
@ -1577,7 +1577,7 @@ char *TextReplace(const char *text, const char *replace, const char *by)
byLen = TextLength(by); byLen = TextLength(by);
// Count the number of replacements needed // Count the number of replacements needed
insertPoint = (char*)text; insertPoint = (char *)text;
for (count = 0; (temp = strstr(insertPoint, replace)); count++) insertPoint = temp + replaceLen; for (count = 0; (temp = strstr(insertPoint, replace)); count++) insertPoint = temp + replaceLen;
// Allocate returning string and point temp to it // Allocate returning string and point temp to it
@ -1786,6 +1786,62 @@ const char *TextToPascal(const char *text)
return buffer; return buffer;
} }
// Get snake case notation version of provided string
// WARNING: Limited functionality, only basic characters set
const char *TextToSnake(const char *text)
{
static char buffer[MAX_TEXT_BUFFER_LENGTH] = {0};
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
if (text != NULL)
{
// Check for next separator to upper case another character
for (int i = 0, j = 0; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[j] != '\0'); i++, j++)
{
if ((text[j] >= 'A') && (text[j] <= 'Z'))
{
if (i >= 1)
{
buffer[i] = '_';
i++;
}
buffer[i] = text[j] + 32;
}
else buffer[i] = text[j];
}
}
return buffer;
}
// Get Camel case notation version of provided string
// WARNING: Limited functionality, only basic characters set
const char *TextToCamel(const char *text)
{
static char buffer[MAX_TEXT_BUFFER_LENGTH] = {0};
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
if (text != NULL)
{
// Lower case first character
if ((text[0] >= 'A') && (text[0] <= 'Z')) buffer[0] = text[0] + 32;
else buffer[0] = text[0];
// Check for next separator to upper case another character
for (int i = 1, j = 1; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[j] != '\0'); i++, j++)
{
if (text[j] != '_') buffer[i] = text[j];
else
{
j++;
if ((text[j] >= 'a') && (text[j] <= 'z')) buffer[i] = text[j] - 32;
}
}
}
return buffer;
}
// Encode text codepoint into UTF-8 text // Encode text codepoint into UTF-8 text
// REQUIRES: memcpy() // REQUIRES: memcpy()
// WARNING: Allocated memory must be manually freed // WARNING: Allocated memory must be manually freed
@ -1836,8 +1892,7 @@ int *LoadCodepoints(const char *text, int *count)
} }
// Re-allocate buffer to the actual number of codepoints loaded // Re-allocate buffer to the actual number of codepoints loaded
int *temp = (int *)RL_REALLOC(codepoints, codepointCount*sizeof(int)); codepoints = (int *)RL_REALLOC(codepoints, codepointCount*sizeof(int));
if (temp != NULL) codepoints = temp;
*count = codepointCount; *count = codepointCount;
@ -1875,7 +1930,8 @@ int GetCodepointCount(const char *text)
const char *CodepointToUTF8(int codepoint, int *utf8Size) const char *CodepointToUTF8(int codepoint, int *utf8Size)
{ {
static char utf8[6] = { 0 }; static char utf8[6] = { 0 };
int size = 0; // Byte size of codepoint memset(utf8, 0, 6); // Clear static array
int size = 0; // Byte size of codepoint
if (codepoint <= 0x7f) if (codepoint <= 0x7f)
{ {
@ -2208,7 +2264,7 @@ static Font LoadBMFont(const char *fileName)
RL_FREE(imFonts); RL_FREE(imFonts);
font.texture = LoadTextureFromImage(fullFont); if (isGpuReady) font.texture = LoadTextureFromImage(fullFont);
// Fill font characters info data // Fill font characters info data
font.baseSize = fontSize; font.baseSize = fontSize;
@ -2240,13 +2296,17 @@ static Font LoadBMFont(const char *fileName)
// Fill character image data from full font data // Fill character image data from full font data
font.glyphs[i].image = ImageFromImage(fullFont, font.recs[i]); font.glyphs[i].image = ImageFromImage(fullFont, font.recs[i]);
} }
else TRACELOG(LOG_WARNING, "FONT: [%s] Some characters data not correctly provided", fileName); else
{
font.glyphs[i].image = GenImageColor((int)font.recs[i].width, (int)font.recs[i].height, BLACK);
TRACELOG(LOG_WARNING, "FONT: [%s] Some characters data not correctly provided", fileName);
}
} }
UnloadImage(fullFont); UnloadImage(fullFont);
UnloadFileText(fileText); UnloadFileText(fileText);
if (font.texture.id == 0) if (isGpuReady && (font.texture.id == 0))
{ {
UnloadFont(font); UnloadFont(font);
font = GetFontDefault(); font = GetFontDefault();
@ -2285,7 +2345,7 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
int readBytes = 0; // Data bytes read (line) int readBytes = 0; // Data bytes read (line)
int readVars = 0; // Variables filled by sscanf() int readVars = 0; // Variables filled by sscanf()
const char *fileText = (const char*)fileData; const char *fileText = (const char *)fileData;
const char *fileTextPtr = fileText; const char *fileTextPtr = fileText;
bool fontMalformed = false; // Is the font malformed bool fontMalformed = false; // Is the font malformed

View file

@ -92,10 +92,10 @@ func LoadFontFromMemory(fileType string, fileData []byte, fontSize int32, codepo
return v return v
} }
// IsFontReady - Check if a font is ready // IsFontValid - Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
func IsFontReady(font Font) bool { func IsFontValid(font Font) bool {
cfont := font.cptr() cfont := font.cptr()
ret := C.IsFontReady(*cfont) ret := C.IsFontValid(*cfont)
v := bool(ret) v := bool(ret)
return v return v
} }

File diff suppressed because it is too large Load diff

View file

@ -103,17 +103,6 @@ func LoadImageRaw(fileName string, width, height int32, format PixelFormat, head
return v return v
} }
// LoadImageSvg - Load image from SVG file data or string with specified size
func LoadImageSvg(fileNameOrString string, width, height int32) *Image {
cfileNameOrString := C.CString(fileNameOrString)
defer C.free(unsafe.Pointer(cfileNameOrString))
cwidth := (C.int)(width)
cheight := (C.int)(height)
ret := C.LoadImageSvg(cfileNameOrString, cwidth, cheight)
v := newImageFromPointer(unsafe.Pointer(&ret))
return v
}
// LoadImageAnim - Load image sequence from file (frames appended to image.data) // LoadImageAnim - Load image sequence from file (frames appended to image.data)
func LoadImageAnim(fileName string, frames *int32) *Image { func LoadImageAnim(fileName string, frames *int32) *Image {
cfileName := C.CString(fileName) cfileName := C.CString(fileName)
@ -124,6 +113,18 @@ func LoadImageAnim(fileName string, frames *int32) *Image {
return v return v
} }
// LoadImageAnimFromMemory - Load image sequence from memory buffer
func LoadImageAnimFromMemory(fileType string, fileData []byte, dataSize int32, frames *int32) *Image {
cfileType := C.CString(fileType)
defer C.free(unsafe.Pointer(cfileType))
cfileData := (*C.uchar)(unsafe.Pointer(&fileData[0]))
cdataSize := (C.int)(dataSize)
cframes := (*C.int)(frames)
ret := C.LoadImageAnimFromMemory(cfileType, cfileData, cdataSize, cframes)
v := newImageFromPointer(unsafe.Pointer(&ret))
return v
}
// LoadImageFromMemory - Load image from memory buffer, fileType refers to extension: i.e. ".png" // LoadImageFromMemory - Load image from memory buffer, fileType refers to extension: i.e. ".png"
func LoadImageFromMemory(fileType string, fileData []byte, dataSize int32) *Image { func LoadImageFromMemory(fileType string, fileData []byte, dataSize int32) *Image {
cfileType := C.CString(fileType) cfileType := C.CString(fileType)
@ -150,10 +151,10 @@ func LoadImageFromScreen() *Image {
return v return v
} }
// IsImageReady - Check if an image is ready // IsImageValid - Check if an image is valid (data and parameters)
func IsImageReady(image *Image) bool { func IsImageValid(image *Image) bool {
cimage := image.cptr() cimage := image.cptr()
ret := C.IsImageReady(*cimage) ret := C.IsImageValid(*cimage)
v := bool(ret) v := bool(ret)
return v return v
} }
@ -199,10 +200,10 @@ func UnloadImage(image *Image) {
C.UnloadImage(*cimage) C.UnloadImage(*cimage)
} }
// IsTextureReady - Check if a texture is ready // IsTextureValid - Check if a texture is valid (loaded in GPU)
func IsTextureReady(texture Texture2D) bool { func IsTextureValid(texture Texture2D) bool {
ctexture := texture.cptr() ctexture := texture.cptr()
ret := C.IsTextureReady(*ctexture) ret := C.IsTextureValid(*ctexture)
v := bool(ret) v := bool(ret)
return v return v
} }
@ -213,10 +214,10 @@ func UnloadTexture(texture Texture2D) {
C.UnloadTexture(*ctexture) C.UnloadTexture(*ctexture)
} }
// IsRenderTextureReady - Check if a render texture is ready // IsRenderTextureValid - Check if a render texture is valid (loaded in GPU)
func IsRenderTextureReady(target RenderTexture2D) bool { func IsRenderTextureValid(target RenderTexture2D) bool {
ctarget := target.cptr() ctarget := target.cptr()
ret := C.IsRenderTextureReady(*ctarget) ret := C.IsRenderTextureValid(*ctarget)
v := bool(ret) v := bool(ret)
return v return v
} }
@ -291,6 +292,15 @@ func ImageFromImage(image Image, rec Rectangle) Image {
return *v return *v
} }
// ImageFromChannel - Create an image from a selected channel of another image (GRAYSCALE)
func ImageFromChannel(image Image, selectedChannel int32) Image {
cimage := image.cptr()
cselectedChannel := C.int(selectedChannel)
ret := C.ImageFromChannel(*cimage, cselectedChannel)
v := newImageFromPointer(unsafe.Pointer(&ret))
return *v
}
// ImageText - Create an image from text (default font) // ImageText - Create an image from text (default font)
func ImageText(text string, fontSize int32, col color.RGBA) *Image { func ImageText(text string, fontSize int32, col color.RGBA) *Image {
ctext := C.CString(text) ctext := C.CString(text)
@ -371,6 +381,13 @@ func ImageBlurGaussian(image *Image, blurSize int32) {
C.ImageBlurGaussian(cimage, cblurSize) C.ImageBlurGaussian(cimage, cblurSize)
} }
// ImageKernelConvolution - Apply custom square convolution kernel to image
func ImageKernelConvolution(image *Image, kernel []float32) {
cimage := image.cptr()
ckernel := (*C.float)(unsafe.Pointer(&kernel[0]))
C.ImageKernelConvolution(cimage, ckernel, C.int(len(kernel)))
}
// ImageResize - Resize an image (bilinear filtering) // ImageResize - Resize an image (bilinear filtering)
func ImageResize(image *Image, newWidth, newHeight int32) { func ImageResize(image *Image, newWidth, newHeight int32) {
cimage := image.cptr() cimage := image.cptr()
@ -534,6 +551,16 @@ func ImageDrawLineV(dst *Image, start, end Vector2, col color.RGBA) {
C.ImageDrawLineV(cdst, *cstart, *cend, *ccolor) C.ImageDrawLineV(cdst, *cstart, *cend, *ccolor)
} }
// ImageDrawLineEx - Draw a line defining thickness within an image
func ImageDrawLineEx(dst *Image, start, end Vector2, thick int32, col color.RGBA) {
cdst := dst.cptr()
cstart := start.cptr()
cend := end.cptr()
cthick := C.int(thick)
ccolor := colorCptr(col)
C.ImageDrawLineEx(cdst, *cstart, *cend, cthick, *ccolor)
}
// ImageDrawCircle - Draw a filled circle within an image // ImageDrawCircle - Draw a filled circle within an image
func ImageDrawCircle(dst *Image, centerX, centerY, radius int32, col color.RGBA) { func ImageDrawCircle(dst *Image, centerX, centerY, radius int32, col color.RGBA) {
cdst := dst.cptr() cdst := dst.cptr()
@ -618,6 +645,56 @@ func ImageDrawRectangleLines(dst *Image, rec Rectangle, thick int, col color.RGB
C.ImageDrawRectangleLines(cdst, *crec, cthick, *ccolor) C.ImageDrawRectangleLines(cdst, *crec, cthick, *ccolor)
} }
// ImageDrawTriangle - Draw triangle within an image
func ImageDrawTriangle(dst *Image, v1, v2, v3 Vector2, col color.RGBA) {
cdst := dst.cptr()
cv1 := v1.cptr()
cv2 := v2.cptr()
cv3 := v3.cptr()
ccol := colorCptr(col)
C.ImageDrawTriangle(cdst, *cv1, *cv2, *cv3, *ccol)
}
// ImageDrawTriangleEx - Draw triangle with interpolated colors within an image
func ImageDrawTriangleEx(dst *Image, v1, v2, v3 Vector2, c1, c2, c3 color.RGBA) {
cdst := dst.cptr()
cv1 := v1.cptr()
cv2 := v2.cptr()
cv3 := v3.cptr()
cc1 := colorCptr(c1)
cc2 := colorCptr(c2)
cc3 := colorCptr(c3)
C.ImageDrawTriangleEx(cdst, *cv1, *cv2, *cv3, *cc1, *cc2, *cc3)
}
// ImageDrawTriangleLines - Draw triangle outline within an image
func ImageDrawTriangleLines(dst *Image, v1, v2, v3 Vector2, col color.RGBA) {
cdst := dst.cptr()
cv1 := v1.cptr()
cv2 := v2.cptr()
cv3 := v3.cptr()
ccol := colorCptr(col)
C.ImageDrawTriangleLines(cdst, *cv1, *cv2, *cv3, *ccol)
}
// ImageDrawTriangleFan - Draw a triangle fan defined by points within an image (first vertex is the center)
func ImageDrawTriangleFan(dst *Image, points []Vector2, col color.RGBA) {
cdst := dst.cptr()
cpoints := (*C.Vector2)(unsafe.Pointer(&points[0]))
pointCount := C.int(len(points))
ccol := colorCptr(col)
C.ImageDrawTriangleFan(cdst, cpoints, pointCount, *ccol)
}
// ImageDrawTriangleStrip - Draw a triangle strip defined by points within an image
func ImageDrawTriangleStrip(dst *Image, points []Vector2, col color.RGBA) {
cdst := dst.cptr()
cpoints := (*C.Vector2)(unsafe.Pointer(&points[0]))
pointCount := C.int(len(points))
ccol := colorCptr(col)
C.ImageDrawTriangleStrip(cdst, cpoints, pointCount, *ccol)
}
// ImageDrawRectangleRec - Draw rectangle within an image // ImageDrawRectangleRec - Draw rectangle within an image
func ImageDrawRectangleRec(dst *Image, rec Rectangle, col color.RGBA) { func ImageDrawRectangleRec(dst *Image, rec Rectangle, col color.RGBA) {
cdst := dst.cptr() cdst := dst.cptr()

View file

@ -76,7 +76,6 @@ void SetSaveFileDataCallback(SaveFileDataCallback callback) { saveFileData = cal
void SetLoadFileTextCallback(LoadFileTextCallback callback) { loadFileText = callback; } // Set custom file text loader void SetLoadFileTextCallback(LoadFileTextCallback callback) { loadFileText = callback; } // Set custom file text loader
void SetSaveFileTextCallback(SaveFileTextCallback callback) { saveFileText = callback; } // Set custom file text saver void SetSaveFileTextCallback(SaveFileTextCallback callback) { saveFileText = callback; } // Set custom file text saver
#if defined(PLATFORM_ANDROID) #if defined(PLATFORM_ANDROID)
static AAssetManager *assetManager = NULL; // Android assets manager pointer static AAssetManager *assetManager = NULL; // Android assets manager pointer
static const char *internalDataPath = NULL; // Android internal data path static const char *internalDataPath = NULL; // Android internal data path