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
// Support automatic generated events, loading and recording of those events when required
#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()
// Enabling this flag allows manual control of the frame processes, use at your own risk
//#define SUPPORT_CUSTOM_FRAME_CONTROL 1
// rcore: Configuration values
//------------------------------------------------------------------------------------
#define MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity
@ -100,6 +101,8 @@
// Show OpenGL extensions and capabilities detailed logs on init
//#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_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)
@ -113,12 +116,17 @@
#define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
// Default shader vertex attribute locations
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4
#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
// 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_PKM 1
//#define SUPPORT_FILEFORMAT_PVR 1
//#define SUPPORT_FILEFORMAT_SVG 1
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
#define SUPPORT_IMAGE_EXPORT 1
@ -225,7 +232,12 @@
// rmodels: Configuration values
//------------------------------------------------------------------------------------
#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
#endif
//------------------------------------------------------------------------------------
// Module: raudio - Configuration Flags
@ -261,4 +273,31 @@
//------------------------------------------------------------------------------------
#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

9052
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.
*
* Version: 1.13
* Version: 1.14
*
* Website: https://github.com/jkuhlmann/cgltf
*
@ -395,6 +395,8 @@ typedef struct cgltf_texture
cgltf_sampler* sampler;
cgltf_bool has_basisu;
cgltf_image* basisu_image;
cgltf_bool has_webp;
cgltf_image* webp_image;
cgltf_extras extras;
cgltf_size extensions_count;
cgltf_extension* extensions;
@ -1697,7 +1699,20 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
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
{
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].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);
}

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.
dr_mp3 - v0.6.38 - 2023-11-02
dr_mp3 - v0.6.39 - 2024-02-27
David Reid - mackron@gmail.com
@ -95,7 +95,7 @@ extern "C" {
#define DRMP3_VERSION_MAJOR 0
#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)
#include <stddef.h> /* For size_t. */
@ -1985,8 +1985,8 @@ static drmp3_int16 drmp3d_scale_pcm(float sample)
s32 -= (s32 < 0);
s = (drmp3_int16)drmp3_clip_int16_arm(s32);
#else
if (sample >= 32766.5) return (drmp3_int16) 32767;
if (sample <= -32767.5) return (drmp3_int16)-32768;
if (sample >= 32766.5f) return (drmp3_int16) 32767;
if (sample <= -32767.5f) return (drmp3_int16)-32768;
s = (drmp3_int16)(sample + .5f);
s -= (s < 0); /* away from zero, to be compliant */
#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++)
{
float sample = in[i] * 32768.0f;
if (sample >= 32766.5)
if (sample >= 32766.5f)
out[i] = (drmp3_int16) 32767;
else if (sample <= -32767.5)
else if (sample <= -32767.5f)
out[i] = (drmp3_int16)-32768;
else
{
@ -4495,6 +4495,9 @@ counts rather than sample counts.
/*
REVISION HISTORY
================
v0.6.39 - 2024-02-27
- Fix a Wdouble-promotion warning.
v0.6.38 - 2023-11-02
- 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.
dr_wav - v0.13.13 - 2023-11-02
dr_wav - v0.13.16 - 2024-02-27
David Reid - mackron@gmail.com
@ -147,7 +147,7 @@ extern "C" {
#define DRWAV_VERSION_MAJOR 0
#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)
#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 (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) {
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. */
if (isProcessingMetadata) {
drwav_uint64 metadataBytesRead;
metadataBytesRead = drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
DRWAV_ASSERT(metadataBytesRead <= header.sizeInBytes);
drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
/* 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) {
@ -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) {
*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
================
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
- 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) 2024 M374LX <wilsalx@gmail.com>
//
// This software is provided 'as-is', without any express or implied
// 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
//
static void createKeyTables(void)
static void createKeyTablesCocoa(void)
{
memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
@ -618,7 +619,7 @@ int _glfwInitCocoa(void)
name:NSTextInputContextKeyboardSelectionDidChangeNotification
object:nil];
createKeyTables();
createKeyTablesCocoa();
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
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) 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
// 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
//
static void acquireMonitor(_GLFWwindow* window)
static void acquireMonitorCocoa(_GLFWwindow* window)
{
_glfwSetVideoModeCocoa(window->monitor, &window->videoMode);
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
//
static void releaseMonitor(_GLFWwindow* window)
static void releaseMonitorCocoa(_GLFWwindow* window)
{
if (window->monitor->window != window)
return;
@ -158,7 +158,7 @@ static int translateFlags(NSUInteger flags)
// 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]))
return GLFW_KEY_UNKNOWN;
@ -277,7 +277,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidMiniaturize:(NSNotification *)notification
{
if (window->monitor)
releaseMonitor(window);
releaseMonitorCocoa(window);
_glfwInputWindowIconify(window, GLFW_TRUE);
}
@ -285,7 +285,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidDeminiaturize:(NSNotification *)notification
{
if (window->monitor)
acquireMonitor(window);
acquireMonitorCocoa(window);
_glfwInputWindowIconify(window, GLFW_FALSE);
}
@ -561,7 +561,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)keyDown:(NSEvent *)event
{
const int key = translateKey([event keyCode]);
const int key = translateKeyCocoa([event keyCode]);
const int mods = translateFlags([event modifierFlags]);
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
@ -574,7 +574,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
int action;
const unsigned int modifierFlags =
[event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
const int key = translateKey([event keyCode]);
const int key = translateKeyCocoa([event keyCode]);
const int mods = translateFlags(modifierFlags);
const NSUInteger keyFlag = translateKeyToModifierFlag(key);
@ -593,7 +593,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)keyUp:(NSEvent *)event
{
const int key = translateKey([event keyCode]);
const int key = translateKeyCocoa([event keyCode]);
const int mods = translateFlags([event modifierFlags]);
_glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods);
}
@ -966,7 +966,7 @@ GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window,
{
_glfwShowWindowCocoa(window);
_glfwFocusWindowCocoa(window);
acquireMonitor(window);
acquireMonitorCocoa(window);
if (wndconfig->centerCursor)
_glfwCenterCursorInContentArea(window);
@ -996,7 +996,7 @@ void _glfwDestroyWindowCocoa(_GLFWwindow* window)
[window->ns.object orderOut:nil];
if (window->monitor)
releaseMonitor(window);
releaseMonitorCocoa(window);
if (window->context.destroy)
window->context.destroy(window);
@ -1083,7 +1083,7 @@ void _glfwSetWindowSizeCocoa(_GLFWwindow* window, int width, int height)
if (window->monitor)
{
if (window->monitor->window == window)
acquireMonitor(window);
acquireMonitorCocoa(window);
}
else
{
@ -1252,7 +1252,7 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
if (monitor)
{
if (monitor->window == window)
acquireMonitor(window);
acquireMonitorCocoa(window);
}
else
{
@ -1270,7 +1270,7 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
}
if (window->monitor)
releaseMonitor(window);
releaseMonitorCocoa(window);
_glfwInputWindowMonitor(window, monitor);
@ -1308,7 +1308,7 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
[window->ns.object setHasShadow:NO];
acquireMonitor(window);
acquireMonitorCocoa(window);
}
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,",
"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,",
"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
};

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-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
// 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;
}
static void acquireMonitor(_GLFWwindow* window)
static void acquireMonitorNull(_GLFWwindow* window)
{
_glfwInputMonitorWindow(window->monitor, window);
}
static void releaseMonitor(_GLFWwindow* window)
static void releaseMonitorNull(_GLFWwindow* window)
{
if (window->monitor->window != window)
return;
@ -147,7 +148,7 @@ GLFWbool _glfwCreateWindowNull(_GLFWwindow* window,
{
_glfwShowWindowNull(window);
_glfwFocusWindowNull(window);
acquireMonitor(window);
acquireMonitorNull(window);
if (wndconfig->centerCursor)
_glfwCenterCursorInContentArea(window);
@ -168,7 +169,7 @@ GLFWbool _glfwCreateWindowNull(_GLFWwindow* window,
void _glfwDestroyWindowNull(_GLFWwindow* window)
{
if (window->monitor)
releaseMonitor(window);
releaseMonitorNull(window);
if (_glfw.null.focusedWindow == window)
_glfw.null.focusedWindow = NULL;
@ -203,14 +204,14 @@ void _glfwSetWindowMonitorNull(_GLFWwindow* window,
}
if (window->monitor)
releaseMonitor(window);
releaseMonitorNull(window);
_glfwInputWindowMonitor(window, monitor);
if (window->monitor)
{
window->null.visible = GLFW_TRUE;
acquireMonitor(window);
acquireMonitorNull(window);
fitToMonitor(window);
}
else
@ -340,7 +341,7 @@ void _glfwIconifyWindowNull(_GLFWwindow* window)
_glfwInputWindowIconify(window, GLFW_TRUE);
if (window->monitor)
releaseMonitor(window);
releaseMonitorNull(window);
}
}
@ -352,7 +353,7 @@ void _glfwRestoreWindowNull(_GLFWwindow* window)
_glfwInputWindowIconify(window, GLFW_FALSE);
if (window->monitor)
acquireMonitor(window);
acquireMonitorNull(window);
}
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) 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
// 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;
}
// 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 (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) 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
// 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
//
static void createKeyTables(void)
static void createKeyTablesWin32(void)
{
int scancode;
@ -685,7 +686,7 @@ int _glfwInitWin32(void)
if (!loadLibraries())
return GLFW_FALSE;
createKeyTables();
createKeyTablesWin32();
_glfwUpdateKeyNamesWin32();
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) 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
// 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
//
static void acquireMonitor(_GLFWwindow* window)
static void acquireMonitorWin32(_GLFWwindow* window)
{
if (!_glfw.win32.acquiredMonitorCount)
{
@ -460,7 +461,7 @@ static void acquireMonitor(_GLFWwindow* window)
// Remove the window and restore the original video mode
//
static void releaseMonitor(_GLFWwindow* window)
static void releaseMonitorWin32(_GLFWwindow* window)
{
if (window->monitor->window != window)
return;
@ -470,7 +471,7 @@ static void releaseMonitor(_GLFWwindow* window)
{
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);
}
@ -1050,10 +1051,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
if (window->monitor && window->win32.iconified != iconified)
{
if (iconified)
releaseMonitor(window);
releaseMonitorWin32(window);
else
{
acquireMonitor(window);
acquireMonitorWin32(window);
fitToMonitor(window);
}
}
@ -1534,7 +1535,7 @@ GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
{
_glfwShowWindowWin32(window);
_glfwFocusWindowWin32(window);
acquireMonitor(window);
acquireMonitorWin32(window);
fitToMonitor(window);
if (wndconfig->centerCursor)
@ -1556,7 +1557,7 @@ GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
void _glfwDestroyWindowWin32(_GLFWwindow* window)
{
if (window->monitor)
releaseMonitor(window);
releaseMonitorWin32(window);
if (window->context.destroy)
window->context.destroy(window);
@ -1677,7 +1678,7 @@ void _glfwSetWindowSizeWin32(_GLFWwindow* window, int width, int height)
{
if (window->monitor->window == window)
{
acquireMonitor(window);
acquireMonitorWin32(window);
fitToMonitor(window);
}
}
@ -1849,7 +1850,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
{
if (monitor->window == window)
{
acquireMonitor(window);
acquireMonitorWin32(window);
fitToMonitor(window);
}
}
@ -1879,7 +1880,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
}
if (window->monitor)
releaseMonitor(window);
releaseMonitorWin32(window);
_glfwInputWindowMonitor(window, monitor);
@ -1897,7 +1898,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
flags |= SWP_FRAMECHANGED;
}
acquireMonitor(window);
acquireMonitorWin32(window);
GetMonitorInfoW(window->monitor->win32.handle, &mi);
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) 2024 M374LX <wilsalx@gmail.com>
//
// This software is provided 'as-is', without any express or implied
// 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
//
static void createKeyTablesWL(void)
static void createKeyTablesWayland(void)
{
memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
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);
wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
createKeyTablesWL();
createKeyTablesWayland();
_glfw.wl.xkb.context = xkb_context_new(0);
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) 2024 M374LX <wilsalx@gmail.com>
//
// This software is provided 'as-is', without any express or implied
// 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
//
static void acquireMonitorWL(_GLFWwindow* window)
static void acquireMonitorWayland(_GLFWwindow* window)
{
if (window->wl.libdecor.frame)
{
@ -519,7 +520,7 @@ static void acquireMonitorWL(_GLFWwindow* window)
// Remove the window and restore the original video mode
//
static void releaseMonitorWL(_GLFWwindow* window)
static void releaseMonitorWayland(_GLFWwindow* window)
{
if (window->wl.libdecor.frame)
libdecor_frame_unset_fullscreen(window->wl.libdecor.frame);
@ -1156,7 +1157,7 @@ static GLFWbool flushDisplay(void)
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]))
return _glfw.wl.keycodes[scancode];
@ -1270,7 +1271,7 @@ static void handleEvents(double* timeout)
for (uint64_t i = 0; i < repeats; i++)
{
_glfwInputKey(_glfw.wl.keyboardFocus,
translateKeyWL(_glfw.wl.keyRepeatScancode),
translateKeyWayland(_glfw.wl.keyRepeatScancode),
_glfw.wl.keyRepeatScancode,
GLFW_PRESS,
_glfw.wl.xkb.modifiers);
@ -1773,7 +1774,7 @@ static void keyboardHandleKey(void* userData,
if (!window)
return;
const int key = translateKeyWL(scancode);
const int key = translateKeyWayland(scancode);
const int action =
state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
@ -2509,12 +2510,12 @@ void _glfwSetWindowMonitorWayland(_GLFWwindow* window,
}
if (window->monitor)
releaseMonitorWL(window);
releaseMonitorWayland(window);
_glfwInputWindowMonitor(window, monitor);
if (window->monitor)
acquireMonitorWL(window);
acquireMonitorWayland(window);
else
_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) 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
// 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
//
static void createKeyTables(void)
static void createKeyTablesX11(void)
{
int scancodeMin, scancodeMax;
@ -908,7 +909,7 @@ static GLFWbool initExtensions(void)
// Update the key code LUT
// FIXME: We should listen to XkbMapNotify events to track changes to
// the keyboard mapping.
createKeyTables();
createKeyTablesX11();
// String format atoms
_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) 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
// 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
//
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)
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
//
static void acquireMonitor(_GLFWwindow* window)
static void acquireMonitorX11(_GLFWwindow* window)
{
if (_glfw.x11.saver.count == 0)
{
@ -1120,7 +1121,7 @@ static void acquireMonitor(_GLFWwindow* window)
// Remove the window and restore the original video mode
//
static void releaseMonitor(_GLFWwindow* window)
static void releaseMonitorX11(_GLFWwindow* window)
{
if (window->monitor->window != window)
return;
@ -1242,7 +1243,7 @@ static void processEvent(XEvent *event)
case KeyPress:
{
const int key = translateKey(keycode);
const int key = translateKeyX11(keycode);
const int mods = translateState(event->xkey.state);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
@ -1314,7 +1315,7 @@ static void processEvent(XEvent *event)
case KeyRelease:
{
const int key = translateKey(keycode);
const int key = translateKeyX11(keycode);
const int mods = translateState(event->xkey.state);
if (!_glfw.x11.xkb.detectable)
@ -1806,9 +1807,9 @@ static void processEvent(XEvent *event)
if (window->monitor)
{
if (iconified)
releaseMonitor(window);
releaseMonitorX11(window);
else
acquireMonitor(window);
acquireMonitorX11(window);
}
window->x11.iconified = iconified;
@ -2025,7 +2026,7 @@ GLFWbool _glfwCreateWindowX11(_GLFWwindow* window,
{
_glfwShowWindowX11(window);
updateWindowMode(window);
acquireMonitor(window);
acquireMonitorX11(window);
if (wndconfig->centerCursor)
_glfwCenterCursorInContentArea(window);
@ -2050,7 +2051,7 @@ void _glfwDestroyWindowX11(_GLFWwindow* window)
enableCursor(window);
if (window->monitor)
releaseMonitor(window);
releaseMonitorX11(window);
if (window->x11.ic)
{
@ -2206,7 +2207,7 @@ void _glfwSetWindowSizeX11(_GLFWwindow* window, int width, int height)
if (window->monitor)
{
if (window->monitor->window == window)
acquireMonitor(window);
acquireMonitorX11(window);
}
else
{
@ -2477,7 +2478,7 @@ void _glfwSetWindowMonitorX11(_GLFWwindow* window,
if (monitor)
{
if (monitor->window == window)
acquireMonitor(window);
acquireMonitorX11(window);
}
else
{
@ -2496,7 +2497,7 @@ void _glfwSetWindowMonitorX11(_GLFWwindow* window,
{
_glfwSetWindowDecoratedX11(window, window->decorated);
_glfwSetWindowFloatingX11(window, window->floating);
releaseMonitor(window);
releaseMonitorX11(window);
}
_glfwInputWindowMonitor(window, monitor);
@ -2511,7 +2512,7 @@ void _glfwSetWindowMonitorX11(_GLFWwindow* window,
}
updateWindowMode(window);
acquireMonitor(window);
acquireMonitorX11(window);
}
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) {
/* 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; }
ch->period += period_offset;
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);
break;
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) {
unsigned int flags = jar_xm_TRIGGER_KEEP_VOLUME;
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) {
char arp_offset = ctx->tempo % 3;
switch(arp_offset) {
case 2: /* 0 -> x -> 0 -> y -> x -> */
case 2: /* 0 -> x -> 0 -> y -> x -> ... */
if(ctx->current_tick == 1) {
ch->arp_in_progress = true;
ch->arp_note_offset = ch->current->effect_param >> 4;
@ -1807,7 +1807,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) {
break;
}
/* No break here, this is intended */
case 1: /* 0 -> 0 -> y -> x -> */
case 1: /* 0 -> 0 -> y -> x -> ... */
if(ctx->current_tick == 0) {
ch->arp_in_progress = false;
ch->arp_note_offset = 0;
@ -1815,7 +1815,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) {
break;
}
/* 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);
default:
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(ppMMDevice != NULL);
ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE);
hr = ma_CoCreateInstance(pContext, &MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
ma_CoUninitialize(pContext);
if (FAILED(hr)) {
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create IMMDeviceEnumerator.\n");
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 sampleRate;
#ifdef __NetBSD__
if (ioctl(fd, AUDIO_GETFORMAT, &fdInfo) < 0) {
return MA_ERROR;
}
#else
if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) {
return MA_ERROR;
}
#endif
if (deviceType == ma_device_type_playback) {
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. */
int fdctl = open(pDefaultDeviceCtlNames[iDefaultDevice], fdFlags, 0);
if (fdctl != -1) {
#ifdef __NetBSD__
fdInfoResult = ioctl(fdctl, AUDIO_GETFORMAT, &fdInfo);
#else
fdInfoResult = ioctl(fdctl, AUDIO_GETINFO, &fdInfo);
#endif
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;
}
}
float r = (float) rand() / RAND_MAX;
float r = (float) rand() / (float) RAND_MAX;
float t = 0;
for (int i = 0; i < nrules; 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);
for (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;
}
for (unsigned int c = 0; c < channels; c++) {
/* Write the current LMS state */
qoa_uint64_t weights = 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.
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_start = sample_index * 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
16 scalefactors, encode all samples for the current slice and
meassure the total squared error. */
qoa_uint64_t best_error = -1;
qoa_uint64_t best_slice;
qoa_uint64_t best_rank = -1;
#ifdef QOA_RECORD_TOTAL_ERROR
qoa_uint64_t best_error = -1;
#endif
qoa_uint64_t best_slice = 0;
qoa_lms_t best_lms;
int best_scalefactor;
int best_scalefactor = 0;
for (int sfi = 0; sfi < 16; sfi++) {
/* 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. */
qoa_lms_t lms = qoa->lms[c];
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) {
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 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);
current_error += error * error;
if (current_error > best_error) {
qoa_uint64_t error_sq = error * 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;
}
@ -444,8 +453,11 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
slice = (slice << 3) | quantized;
}
if (current_error < best_error) {
best_error = current_error;
if (current_rank < best_rank) {
best_rank = current_rank;
#ifdef QOA_RECORD_TOTAL_ERROR
best_error = current_error;
#endif
best_slice = slice;
best_lms = lms;
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);
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
prediction of the first few ms of a file. */
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
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);
const short *frame_samples = sample_data + sample_index * qoa->channels;
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 */
qoa_uint64_t frame_header = qoa_read_u64(bytes, &p);
int channels = (frame_header >> 56) & 0x0000ff;
int samplerate = (frame_header >> 32) & 0xffffff;
int samples = (frame_header >> 16) & 0x00ffff;
int frame_size = (frame_header ) & 0x00ffff;
unsigned int channels = (frame_header >> 56) & 0x0000ff;
unsigned int samplerate = (frame_header >> 32) & 0xffffff;
unsigned int samples = (frame_header >> 16) & 0x00ffff;
unsigned int frame_size = (frame_header ) & 0x00ffff;
int data_size = frame_size - 8 - QOA_LMS_LEN * 4 * channels;
int num_slices = data_size / 8;
int max_total_samples = num_slices * QOA_SLICE_LEN;
unsigned int data_size = frame_size - 8 - QOA_LMS_LEN * 4 * channels;
unsigned int num_slices = data_size / 8;
unsigned int max_total_samples = num_slices * QOA_SLICE_LEN;
if (
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 */
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 weights = qoa_read_u64(bytes, &p);
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 */
for (int sample_index = 0; sample_index < samples; sample_index += QOA_SLICE_LEN) {
for (int c = 0; c < channels; c++) {
for (unsigned int sample_index = 0; sample_index < samples; sample_index += QOA_SLICE_LEN) {
for (unsigned int c = 0; c < channels; c++) {
qoa_uint64_t slice = qoa_read_u64(bytes, &p);
int scalefactor = (slice >> 60) & 0xf;
slice <<= 4;
int slice_start = sample_index * 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) {
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 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;
*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;
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
{
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);
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
{
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);
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
{
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);
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
{
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);
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
{
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);
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
{
// NOTE: This forces only 1 mipmap to be loaded which is not really correct but it works
int data_size = (header->pitch_or_linear_size < file_size - 0x80) ? header->pitch_or_linear_size : file_size - 0x80;
*mips = 1;
int data_size = 0;
// 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));

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
Do this:
@ -48,6 +48,8 @@ LICENSE
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.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug 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;
}
// returns 1 if the product of two signed shorts is valid, 0 on overflow.
static int stbi__mul2shorts_valid(short a, short b)
// returns 1 if the product of two ints fits in a signed short, 0 on overflow.
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 ((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;
}
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
// like a valid marker, resume there
while (!stbi__at_eof(j->s)) {
int x = stbi__get8(j->s);
while (x == 255) { // might be a marker
stbi_uc x = stbi__get8(j->s);
while (x == 0xff) { // might be a marker
if (stbi__at_eof(j->s)) return STBI__MARKER_none;
x = stbi__get8(j->s);
if (x != 0x00 && x != 0xff) {
@ -4176,6 +4178,7 @@ typedef struct
{
stbi_uc *zbuffer, *zbuffer_end;
int num_bits;
int hit_zeof_once;
stbi__uint32 code_buffer;
char *zout;
@ -4242,9 +4245,20 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
int b,s;
if (a->num_bits < 16) {
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];
if (b) {
@ -4309,6 +4323,13 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
int len,dist;
if (z == 256) {
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;
}
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];
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 + len > a->zout_end) {
if (len > a->zout_end - zout) {
if (!stbi__zexpand(a, zout, len)) return 0;
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;
a->num_bits = 0;
a->code_buffer = 0;
a->hit_zeof_once = 0;
do {
final = stbi__zreceive(a,1);
type = stbi__zreceive(a,2);
@ -4619,9 +4641,8 @@ enum {
STBI__F_up=2,
STBI__F_avg=3,
STBI__F_paeth=4,
// synthetic filters used for first scanline to avoid needing a dummy row of 0s
STBI__F_avg_first,
STBI__F_paeth_first
// synthetic filter used for first scanline to avoid needing a dummy row of 0s
STBI__F_avg_first
};
static stbi_uc first_row_filter[5] =
@ -4630,29 +4651,56 @@ static stbi_uc first_row_filter[5] =
STBI__F_sub,
STBI__F_none,
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)
{
int p = a + b - c;
int pa = abs(p-a);
int pb = abs(p-b);
int pc = abs(p-c);
if (pa <= pb && pa <= pc) return a;
if (pb <= pc) return b;
return c;
// This formulation looks very different from the reference in the PNG spec, but is
// actually equivalent and has favorable data dependencies and admits straightforward
// generation of branch-free code, which helps performance significantly.
int thresh = c*3 - (a + b);
int lo = a < b ? a : b;
int hi = a < b ? b : a;
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 };
// 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
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__uint32 i,j,stride = x*out_n*bytes;
stbi__uint32 img_len, img_width_bytes;
stbi_uc *filter_buf;
int all_ok = 1;
int k;
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
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");
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;
// 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.
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) {
stbi_uc *cur = a->out + stride*j;
stbi_uc *prior;
// cur/prior filter buffers alternate
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++;
if (filter > 4)
return stbi__err("invalid filter","Corrupt PNG");
if (depth < 8) {
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;
// check filter type
if (filter > 4) {
all_ok = stbi__err("invalid filter","Corrupt PNG");
break;
}
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 (j == 0) filter = first_row_filter[filter];
// handle first byte explicitly
for (k=0; k < filter_bytes; ++k) {
switch (filter) {
case STBI__F_none : cur[k] = raw[k]; break;
case STBI__F_sub : cur[k] = raw[k]; break;
case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break;
case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break;
case STBI__F_avg_first : cur[k] = raw[k]; break;
case STBI__F_paeth_first: cur[k] = raw[k]; break;
}
// perform actual filtering
switch (filter) {
case STBI__F_none:
memcpy(cur, raw, nk);
break;
case STBI__F_sub:
memcpy(cur, raw, filter_bytes);
for (k = filter_bytes; k < nk; ++k)
cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]);
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) {
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;
}
raw += nk;
// this is a little gross, so that we don't switch per-pixel or per-component
if (depth < 8 || img_n == out_n) {
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
// expand decoded bits in cur to dest, also adding an extra alpha channel if desired
if (depth < 8) {
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.
// 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
// expand bits to bytes first
if (depth == 4) {
for (k=x*img_n; k >= 2; k-=2, ++in) {
*cur++ = scale * ((*in >> 4) );
*cur++ = scale * ((*in ) & 0x0f);
for (i=0; i < nsmp; ++i) {
if ((i & 1) == 0) inb = *in++;
*out++ = scale * (inb >> 4);
inb <<= 4;
}
if (k > 0) *cur++ = scale * ((*in >> 4) );
} else if (depth == 2) {
for (k=x*img_n; k >= 4; k-=4, ++in) {
*cur++ = scale * ((*in >> 6) );
*cur++ = scale * ((*in >> 4) & 0x03);
*cur++ = scale * ((*in >> 2) & 0x03);
*cur++ = scale * ((*in ) & 0x03);
for (i=0; i < nsmp; ++i) {
if ((i & 3) == 0) inb = *in++;
*out++ = scale * (inb >> 6);
inb <<= 2;
}
if (k > 0) *cur++ = scale * ((*in >> 6) );
if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
} else if (depth == 1) {
for (k=x*img_n; k >= 8; k-=8, ++in) {
*cur++ = scale * ((*in >> 7) );
*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);
} else {
STBI_ASSERT(depth == 1);
for (i=0; i < nsmp; ++i) {
if ((i & 7) == 0) inb = *in++;
*out++ = scale * (inb >> 7);
inb <<= 1;
}
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
cur = a->out + stride*j;
// insert alpha=255 values if desired
if (img_n != out_n)
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) {
for (q=x-1; q >= 0; --q) {
cur[q*2+1] = 255;
cur[q*2+0] = cur[q];
for (i = 0; i < x; ++i, dest16 += 2, cur += 2) {
dest16[0] = (cur[0] << 8) | cur[1];
dest16[1] = 0xffff;
}
} else {
STBI_ASSERT(img_n == 3);
for (q=x-1; q >= 0; --q) {
cur[q*4+3] = 255;
cur[q*4+2] = cur[q*3+2];
cur[q*4+1] = cur[q*3+1];
cur[q*4+0] = cur[q*3+0];
for (i = 0; i < x; ++i, dest16 += 4, cur += 6) {
dest16[0] = (cur[0] << 8) | cur[1];
dest16[1] = (cur[2] << 8) | cur[3];
dest16[2] = (cur[4] << 8) | cur[5];
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;
}
@ -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.
if (scan == STBI__SCAN_header) { ++s->img_n; return 1; }
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 {
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;

File diff suppressed because it is too large Load diff

View file

@ -54,7 +54,7 @@
// Hou Qiming Derek Vinyard
// Rob Loach Cort Stratton
// Kenney Phillis Jr. Brian Costabile
// Ken Voskuil (kaesve)
// Ken Voskuil (kaesve) Yakov Galka
//
// VERSION HISTORY
//
@ -4604,6 +4604,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
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;
float *precompute;
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 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));
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) {
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 x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
float len2 = bx*bx + by*by;
if (len2 != 0.0f)
precompute[i] = 1.0f / (bx*bx + by*by);
if (len2 >= eps2)
precompute[i] = 1.0f / len2;
else
precompute[i] = 0.0f;
} 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 b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
float c = mx*ax+my*ay;
if (a == 0.0) { // if a is 0, it's linear
if (b != 0.0) {
if (STBTT_fabs(a) < eps2) { // if a is 0, it's linear
if (STBTT_fabs(b) >= eps2) {
res[num++] = -c/b;
}
} 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
//----------------------------------------------------------------------------------
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
//----------------------------------------------------------------------------------
// Local Variables Definition
//----------------------------------------------------------------------------------
#define KEYCODE_MAP_SIZE 162
static const KeyboardKey KeycodeMap[KEYCODE_MAP_SIZE] = {
static const KeyboardKey mapKeycode[KEYCODE_MAP_SIZE] = {
KEY_NULL, // AKEYCODE_UNKNOWN
0, // AKEYCODE_SOFT_LEFT
0, // AKEYCODE_SOFT_RIGHT
@ -283,14 +283,15 @@ void android_main(struct android_app *app)
// Request to end the native activity
ANativeActivity_finish(app->activity);
// Android ALooper_pollAll() variables
// Android ALooper_pollOnce() variables
int pollResult = 0;
int pollEvents = 0;
// Waiting for application events before complete finishing
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);
}
@ -616,7 +617,7 @@ int SetGamepadMappings(const char *mappings)
}
// 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");
}
@ -634,6 +635,13 @@ void SetMouseCursor(int cursor)
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
void PollInputEvents(void)
{
@ -677,27 +685,27 @@ void PollInputEvents(void)
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
}
// Android ALooper_pollAll() variables
// Android ALooper_pollOnce() variables
int pollResult = 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)
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
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)
{
//CORE.Window.shouldClose = true;
//ANativeActivity_finish(platform.app->activity);
CORE.Window.shouldClose = true;
}
}
}
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
@ -762,20 +770,20 @@ int InitPlatform(void)
TRACELOG(LOG_INFO, "PLATFORM: ANDROID: Initialized successfully");
// Android ALooper_pollAll() variables
// Android ALooper_pollOnce() variables
int pollResult = 0;
int pollEvents = 0;
// Wait for window to be initialized (display and context)
while (!CORE.Window.ready)
{
// Process events loop
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&platform.source)) >= 0)
// Process events until we reach TIMEOUT, which indicates no more events queued.
while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT)
{
// Process this event
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;
}
}
@ -806,6 +814,12 @@ void ClosePlatform(void)
eglTerminate(platform.device);
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
@ -976,6 +990,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Initialize OpenGL context (states and resources)
// 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);
isGpuReady = true;
// Setup default viewport
// 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(
event, AMOTION_EVENT_AXIS_RZ, 0);
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(
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
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
}
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)
{
// 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) };
// 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 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].y = CORE.Input.Touch.position[i].y * heightRatio - (float)CORE.Window.renderOffset.y / 2;
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;
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;
}
int32_t action = AMotionEvent_getAction(event);

View file

@ -58,6 +58,7 @@
#if defined(_WIN32)
typedef void *PVOID;
typedef PVOID HANDLE;
#include "../external/win32_clipboard.h"
typedef HANDLE HWND;
#define GLFW_EXPOSE_NATIVE_WIN32
#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)
// NOTE: Those functions require linking with winmm library
unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);
unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
//#pragma warning(disable: 4273)
__declspec(dllimport) unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
//#pragma warning(default: 4273)
#endif
#endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
@ -109,6 +111,7 @@ static void ErrorCallback(int error, const char *description);
// Window callbacks events
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 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
@ -147,7 +150,7 @@ void ToggleFullscreen(void)
if (!CORE.Window.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 monitorIndex = GetCurrentMonitor();
@ -179,7 +182,11 @@ void ToggleFullscreen(void)
CORE.Window.fullscreen = false;
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)
@ -190,11 +197,11 @@ void ToggleFullscreen(void)
// Toggle borderless windowed mode
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;
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();
wasOnFullscreen = true;
}
@ -213,7 +220,7 @@ void ToggleBorderlessWindowed(void)
{
// Store screen position and size
// 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;
// Set undecorated and topmost modes and flags
@ -255,6 +262,9 @@ void ToggleBorderlessWindowed(void)
glfwFocusWindow(platform.handle);
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");
@ -592,6 +602,9 @@ void SetWindowTitle(const char *title)
// Set window position on screen (windowed mode)
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);
}
@ -614,8 +627,9 @@ void SetWindowMonitor(int monitor)
{
TRACELOG(LOG_INFO, "GLFW: Selected monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));
const int screenWidth = CORE.Window.screen.width;
const int screenHeight = CORE.Window.screen.height;
// Here the render width has to be used again in case high dpi flag is enabled
const int screenWidth = CORE.Window.render.width;
const int screenHeight = CORE.Window.render.height;
int monitorWorkareaX = 0;
int monitorWorkareaY = 0;
int monitorWorkareaWidth = 0;
@ -666,6 +680,9 @@ void SetWindowMaxSize(int width, int height)
// Set window dimensions
void SetWindowSize(int width, int height)
{
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
glfwSetWindowSize(platform.handle, width, height);
}
@ -950,6 +967,33 @@ const char *GetClipboardText(void)
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
void ShowCursor(void)
{
@ -1045,7 +1089,7 @@ int SetGamepadMappings(const char *mappings)
}
// 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");
}
@ -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
void PollInputEvents(void)
{
@ -1144,7 +1194,7 @@ void PollInputEvents(void)
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
@ -1186,7 +1236,7 @@ void PollInputEvents(void)
// Get current axis state
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];
}
@ -1213,7 +1263,6 @@ void PollInputEvents(void)
glfwSetWindowShouldClose(platform.handle, GLFW_FALSE);
}
//----------------------------------------------------------------------------------
// 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_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
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,
// for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3),
@ -1443,15 +1497,7 @@ int InitPlatform(void)
else
{
// No-fullscreen window creation
bool wantWindowedFullscreen = (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);
}
bool requestWindowedFullscreen = (CORE.Window.screen.height == 0) && (CORE.Window.screen.width == 0);
// 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;
@ -1471,11 +1517,7 @@ int InitPlatform(void)
monitor = monitors[monitorIndex];
SetDimensionsFromMonitor(monitor);
TRACELOG(LOG_INFO, "wantWindowed: %d, size: %dx%d", wantWindowedFullscreen, CORE.Window.screen.width, CORE.Window.screen.height);
if (wantWindowedFullscreen)
{
glfwSetWindowSize(platform.handle, CORE.Window.screen.width, CORE.Window.screen.height);
}
if (requestWindowedFullscreen) glfwSetWindowSize(platform.handle, CORE.Window.screen.width, CORE.Window.screen.height);
}
else
{
@ -1567,11 +1609,16 @@ int InitPlatform(void)
int monitorHeight = 0;
glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight);
int posX = monitorX + (monitorWidth - (int)CORE.Window.screen.width)/2;
int posY = monitorY + (monitorHeight - (int)CORE.Window.screen.height)/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 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 (posY < monitorY) posY = monitorY;
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
@ -1583,6 +1630,7 @@ int InitPlatform(void)
//----------------------------------------------------------------------------
// Set window callback events
glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default!
glfwSetWindowPosCallback(platform.handle, WindowPosCallback);
glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback);
glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);
glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);
@ -1621,18 +1669,23 @@ int InitPlatform(void)
CORE.Storage.basePath = GetWorkingDirectory();
//----------------------------------------------------------------------------
char* glfwPlatform = "";
#if defined(__NetBSD__)
// Workaround for NetBSD
char *glfwPlatform = "X11";
#else
char *glfwPlatform = "";
switch (glfwGetPlatform())
{
case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break;
case GLFW_PLATFORM_COCOA: glfwPlatform = "Cocoa"; break;
case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break;
case GLFW_PLATFORM_COCOA: glfwPlatform = "Cocoa"; break;
case GLFW_PLATFORM_WAYLAND: glfwPlatform = "Wayland"; break;
case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break;
case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break;
case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break;
case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break;
default: break;
}
#endif
TRACELOG(LOG_INFO, "GLFW platform: %s", glfwPlatform);
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW): Initialized successfully");
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW - %s): Initialized successfully", glfwPlatform);
return 0;
}
@ -1668,27 +1721,18 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
if (IsWindowFullscreen()) return;
// Set current screen size
#if defined(__APPLE__)
CORE.Window.screen.width = width;
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
}
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)
{
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

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-
*
* 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)
*
*
@ -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)
#if defined(GRAPHICS_API_OPENGL_ES2)
@ -57,6 +61,20 @@
#include "SDL_opengl.h" // SDL OpenGL functionality (if required, instead of internal renderer)
#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
//----------------------------------------------------------------------------------
@ -64,7 +82,7 @@ typedef struct {
SDL_Window *window;
SDL_GLContext glContext;
SDL_Joystick *gamepad[MAX_GAMEPADS];
SDL_GameController *gamepad[MAX_GAMEPADS];
SDL_Cursor *cursor;
bool cursorRelative;
} PlatformData;
@ -80,7 +98,7 @@ static PlatformData platform = { 0 }; // Platform specific data
// Local Variables Definition
//----------------------------------------------------------------------------------
#define SCANCODE_MAPPED_NUM 232
static const KeyboardKey ScancodeToKey[SCANCODE_MAPPED_NUM] = {
static const KeyboardKey mapScancodeToKey[SCANCODE_MAPPED_NUM] = {
KEY_NULL, // SDL_SCANCODE_UNKNOWN
0,
0,
@ -220,6 +238,190 @@ static const int CursorsLUT[] = {
//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
//----------------------------------------------------------------------------------
@ -249,7 +451,12 @@ void ToggleFullscreen(void)
{
const int monitor = SDL_GetWindowDisplayIndex(platform.window);
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))
#endif
{
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0)
{
@ -272,7 +479,11 @@ void ToggleBorderlessWindowed(void)
{
const int monitor = SDL_GetWindowDisplayIndex(platform.window);
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))
#endif
{
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 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))
#endif
{
SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN);
CORE.Window.fullscreen = true;
@ -380,7 +595,11 @@ void SetWindowState(unsigned int flags)
{
const int monitor = SDL_GetWindowDisplayIndex(platform.window);
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))
#endif
{
SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN_DESKTOP);
}
@ -476,9 +695,9 @@ void ClearWindowState(unsigned int flags)
// Set icon for window
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 pitch = 0; // Pixel spacing (pitch) in bytes
@ -492,72 +711,67 @@ void SetWindowIcon(Image image)
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
rmask = 0xFF, gmask = 0xFF00;
bmask = 0, amask = 0;
depth = 16, pitch = image.width * 2;
depth = 16, pitch = image.width*2;
break;
case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
rmask = 0xF800, gmask = 0x07E0;
bmask = 0x001F, amask = 0;
depth = 16, pitch = image.width * 2;
depth = 16, pitch = image.width*2;
break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // Uses BGR for 24-bit
rmask = 0x0000FF, gmask = 0x00FF00;
bmask = 0xFF0000, amask = 0;
depth = 24, pitch = image.width * 3;
depth = 24, pitch = image.width*3;
break;
case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
rmask = 0xF800, gmask = 0x07C0;
bmask = 0x003E, amask = 0x0001;
depth = 16, pitch = image.width * 2;
depth = 16, pitch = image.width*2;
break;
case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
rmask = 0xF000, gmask = 0x0F00;
bmask = 0x00F0, amask = 0x000F;
depth = 16, pitch = image.width * 2;
depth = 16, pitch = image.width*2;
break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
rmask = 0xFF000000, gmask = 0x00FF0000;
bmask = 0x0000FF00, amask = 0x000000FF;
depth = 32, pitch = image.width * 4;
depth = 32, pitch = image.width*4;
break;
case PIXELFORMAT_UNCOMPRESSED_R32:
rmask = 0xFFFFFFFF, gmask = 0;
bmask = 0, amask = 0;
depth = 32, pitch = image.width * 4;
depth = 32, pitch = image.width*4;
break;
case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
bmask = 0xFFFFFFFF, amask = 0;
depth = 96, pitch = image.width * 12;
depth = 96, pitch = image.width*12;
break;
case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
bmask = 0xFFFFFFFF, amask = 0xFFFFFFFF;
depth = 128, pitch = image.width * 16;
depth = 128, pitch = image.width*16;
break;
case PIXELFORMAT_UNCOMPRESSED_R16:
rmask = 0xFFFF, gmask = 0;
bmask = 0, amask = 0;
depth = 16, pitch = image.width * 2;
depth = 16, pitch = image.width*2;
break;
case PIXELFORMAT_UNCOMPRESSED_R16G16B16:
rmask = 0xFFFF, gmask = 0xFFFF;
bmask = 0xFFFF, amask = 0;
depth = 48, pitch = image.width * 6;
depth = 48, pitch = image.width*6;
break;
case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:
rmask = 0xFFFF, gmask = 0xFFFF;
bmask = 0xFFFF, amask = 0xFFFF;
depth = 64, pitch = image.width * 8;
depth = 64, pitch = image.width*8;
break;
default:
// Compressed formats are not supported
return;
default: return; // Compressed formats are not supported
}
iconSurface = SDL_CreateRGBSurfaceFrom(
image.data, image.width, image.height, depth, pitch,
rmask, gmask, bmask, amask
);
iconSurface = SDL_CreateRGBSurfaceFrom( image.data, image.width, image.height, depth, pitch, rmask, gmask, bmask, amask );
if (iconSurface)
{
@ -599,12 +813,16 @@ void SetWindowMonitor(int monitor)
// 1. SDL started supporting moving exclusive fullscreen windows between displays on SDL3,
// 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.
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 screenHeight = CORE.Window.screen.height;
SDL_Rect usableBounds;
#ifdef PLATFORM_DESKTOP_SDL3 // Different style for success checking
if (SDL_GetDisplayUsableBounds(monitor, &usableBounds))
#else
if (SDL_GetDisplayUsableBounds(monitor, &usableBounds) == 0)
#endif
{
if (wasFullscreen == 1) ToggleFullscreen(); // Leave fullscreen.
@ -702,6 +920,7 @@ int GetCurrentMonitor(void)
{
int currentMonitor = 0;
// Be aware that this returns an ID in SDL3 and a Index in SDL2
currentMonitor = SDL_GetWindowDisplayIndex(platform.window);
return currentMonitor;
@ -714,7 +933,11 @@ Vector2 GetMonitorPosition(int monitor)
if ((monitor >= 0) && (monitor < monitorCount))
{
SDL_Rect displayBounds;
#ifdef PLATFORM_DESKTOP_SDL3
if (SDL_GetDisplayUsableBounds(monitor, &displayBounds))
#else
if (SDL_GetDisplayUsableBounds(monitor, &displayBounds) == 0)
#endif
{
return (Vector2){ (float)displayBounds.x, (float)displayBounds.y };
}
@ -842,10 +1065,16 @@ Vector2 GetWindowScaleDPI(void)
{
Vector2 scale = { 1.0f, 1.0f };
#ifndef PLATFORM_DESKTOP_SDL3
// NOTE: SDL_GetWindowDisplayScale was only added on SDL3
// see https://wiki.libsdl.org/SDL3/SDL_GetWindowDisplayScale
// TODO: Implement the window scale factor calculation manually.
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;
}
@ -857,25 +1086,86 @@ void SetClipboardText(const char *text)
}
// Get clipboard text content
// NOTE: returned string must be freed with SDL_free()
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
void ShowCursor(void)
{
#ifdef PLATFORM_DESKTOP_SDL3
SDL_ShowCursor();
#else
SDL_ShowCursor(SDL_ENABLE);
#endif
CORE.Input.Mouse.cursorHidden = false;
}
// Hides mouse cursor
void HideCursor(void)
{
#ifdef PLATFORM_DESKTOP_SDL3
SDL_HideCursor();
#else
SDL_ShowCursor(SDL_DISABLE);
#endif
CORE.Input.Mouse.cursorHidden = true;
}
@ -883,7 +1173,13 @@ void HideCursor(void)
void EnableCursor(void)
{
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);
#endif
platform.cursorRelative = false;
CORE.Input.Mouse.cursorHidden = false;
@ -939,17 +1235,17 @@ int SetGamepadMappings(const char *mappings)
}
// 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
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))
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (duration > 0.0f))
{
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;
}
// Get physical key name.
const char *GetKeyName(int key)
{
return SDL_GetKeyName(key);
}
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);
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.currentTouchState[i] = 1;
}
#endif
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[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);
SDL_free(event.drop.file);
#endif
CORE.Window.dropFileCount++;
}
else if (CORE.Window.dropFileCount < 1024)
{
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);
SDL_free(event.drop.file);
#endif
CORE.Window.dropFileCount++;
}
@ -1092,10 +1421,18 @@ void PollInputEvents(void)
} break;
// 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:
{
switch (event.window.event)
{
#endif
case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_SIZE_CHANGED:
{
@ -1123,16 +1460,26 @@ void PollInputEvents(void)
case SDL_WINDOWEVENT_FOCUS_GAINED:
case SDL_WINDOWEVENT_MAXIMIZED:
case SDL_WINDOWEVENT_RESTORED:
#ifdef PLATFORM_DESKTOP_SDL3
break;
#else
default: break;
}
} break;
#endif
// Keyboard events
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);
#endif
if (key != KEY_NULL) {
if (key != KEY_NULL)
{
// 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))
{
@ -1154,7 +1501,12 @@ void PollInputEvents(void)
case SDL_KEYUP:
{
#ifdef PLATFORM_DESKTOP_SDL3
KeyboardKey key = ConvertScancodeToKey(event.key.scancode);
#else
KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode);
#endif
if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0;
} break;
@ -1249,15 +1601,15 @@ void PollInputEvents(void)
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])
{
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_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';
}
else
@ -1270,15 +1622,15 @@ void PollInputEvents(void)
{
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]);
platform.gamepad[jid] = SDL_JoystickOpen(0);
SDL_GameControllerClose(platform.gamepad[jid]);
platform.gamepad[jid] = SDL_GameControllerOpen(0);
CORE.Input.Gamepad.ready[jid] = false;
memset(CORE.Input.Gamepad.name[jid], 0, 64);
}
} break;
case SDL_JOYBUTTONDOWN:
case SDL_CONTROLLERBUTTONDOWN:
{
int button = -1;
@ -1312,7 +1664,7 @@ void PollInputEvents(void)
CORE.Input.Gamepad.lastButtonPressed = button;
}
} break;
case SDL_JOYBUTTONUP:
case SDL_CONTROLLERBUTTONUP:
{
int button = -1;
@ -1346,7 +1698,7 @@ void PollInputEvents(void)
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
}
} break;
case SDL_JOYAXISMOTION:
case SDL_CONTROLLERAXISMOTION:
{
int axis = -1;
@ -1364,13 +1716,13 @@ void PollInputEvents(void)
if (axis >= 0)
{
// 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;
// Register button state for triggers in addition to their axes
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);
CORE.Input.Gamepad.currentButtonState[event.jaxis.which][button] = pressed;
if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
@ -1499,11 +1851,6 @@ int InitPlatform(void)
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)
{
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
@ -1511,7 +1858,11 @@ int InitPlatform(void)
}
// 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);
#endif
// Init OpenGL context
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, " > 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);
if (CORE.Window.flags & FLAG_VSYNC_HINT) SDL_GL_SetSwapInterval(1);
else SDL_GL_SetSwapInterval(0);
}
else
{
@ -1554,14 +1908,15 @@ int InitPlatform(void)
// Initialize gamepads
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])
{
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_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';
}
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
#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
//----------------------------------------------------------------------------
// 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");
#endif
return 0;
}
@ -1609,8 +1970,9 @@ static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode)
{
if (sdlScancode >= 0 && sdlScancode < SCANCODE_MAPPED_NUM)
{
return ScancodeToKey[sdlScancode];
return mapScancodeToKey[sdlScancode];
}
return KEY_NULL; // No equivalent key in Raylib
}
// EOF

View file

@ -207,7 +207,7 @@ static const short linuxToRaylibMap[KEYMAP_SIZE] = {
[BTN_TL] = GAMEPAD_BUTTON_LEFT_TRIGGER_1,
[BTN_TL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2,
[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_MODE] = GAMEPAD_BUTTON_MIDDLE,
[BTN_START] = GAMEPAD_BUTTON_MIDDLE_RIGHT,
@ -611,7 +611,7 @@ int SetGamepadMappings(const char *mappings)
}
// 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");
}
@ -629,6 +629,13 @@ void SetMouseCursor(int cursor)
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
void PollInputEvents(void)
{
@ -758,7 +765,9 @@ int InitPlatform(void)
drmModeConnector *con = drmModeGetConnector(platform.fd, res->connectors[i]);
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");
platform.connector = con;
@ -1029,7 +1038,7 @@ int InitPlatform(void)
// 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; }
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
CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN; // false
@ -1137,7 +1146,8 @@ void ClosePlatform(void)
// Close the evdev devices
if (platform.mouseFd != -1) {
if (platform.mouseFd != -1)
{
close(platform.mouseFd);
platform.mouseFd = -1;
}
@ -1471,7 +1481,6 @@ static void ConfigureEvdevDevice(char *device)
TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;
}
if (TEST_BIT(evBits, EV_KEY))
{
// 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];
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))
{
@ -1666,7 +1675,7 @@ static void PollGamepadEvents(void)
int range = platform.gamepadAbsAxisRange[i][event.code][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 nearestFpsDiff = abs(platform.connector->modes[nearestIndex].vrefresh - fps);
if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) {
nearestIndex = i;
}
if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) nearestIndex = i;
}
return nearestIndex;

View file

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

View file

@ -895,8 +895,8 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
return wave;
}
// Checks if wave data is ready
bool IsWaveReady(Wave wave)
// Checks if wave data is valid (data loaded and parameters)
bool IsWaveValid(Wave wave)
{
bool result = false;
@ -996,8 +996,8 @@ Sound LoadSoundAlias(Sound source)
}
// Checks if a sound is ready
bool IsSoundReady(Sound sound)
// Checks if a sound is valid (data loaded and buffers initialized)
bool IsSoundValid(Sound sound)
{
bool result = false;
@ -1277,20 +1277,21 @@ Wave WaveCopy(Wave wave)
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
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);
wave->data = data;
wave->frameCount = (unsigned int)frameCount;
}
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++)
{
if (wave.sampleSize == 8) samples[i] = (float)(((unsigned char *)wave.data)[i] - 127)/256.0f;
else if (wave.sampleSize == 16) samples[i] = (float)(((short *)wave.data)[i])/32767.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])/32768.0f;
else if (wave.sampleSize == 32) samples[i] = ((float *)wave.data)[i];
}
@ -1351,7 +1352,6 @@ Music LoadMusicStream(const char *fileName)
}
else
{
drwav_uninit(ctxWav);
RL_FREE(ctxWav);
}
}
@ -1431,7 +1431,9 @@ Music LoadMusicStream(const char *fileName)
{
music.ctxType = MUSIC_AUDIO_FLAC;
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.looping = true; // Looping enabled by default
musicLoaded = true;
@ -1551,7 +1553,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0))
{
// 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)
{
@ -1627,7 +1629,9 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
{
music.ctxType = MUSIC_AUDIO_FLAC;
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.looping = true; // Looping enabled by default
musicLoaded = true;
@ -1725,8 +1729,8 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
return music;
}
// Checks if a music stream is ready
bool IsMusicReady(Music music)
// Checks if a music stream is valid (context and buffers initialized)
bool IsMusicValid(Music music)
{
return ((music.ctxData != NULL) && // Validate context loaded
(music.frameCount > 0) && // Validate audio frame count
@ -2118,8 +2122,8 @@ AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
return stream;
}
// Checks if an audio stream is ready
bool IsAudioStreamReady(AudioStream stream)
// Checks if an audio stream is valid (buffers initialized)
bool IsAudioStreamValid(AudioStream stream)
{
return ((stream.buffer != NULL) && // Validate stream buffer
(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
}
// IsWaveReady - Checks if wave data is ready
func IsWaveReady(wave Wave) bool {
// IsWaveValid - Checks if wave data is valid (data loaded and parameters)
func IsWaveValid(wave Wave) bool {
cwave := wave.cptr()
ret := C.IsWaveReady(*cwave)
ret := C.IsWaveValid(*cwave)
v := bool(ret)
return v
}
@ -209,10 +209,10 @@ func LoadSoundAlias(source Sound) Sound {
return v
}
// IsSoundReady - Checks if a sound is ready
func IsSoundReady(sound Sound) bool {
// IsSoundValid - Checks if a sound is valid (data loaded and buffers initialized)
func IsSoundValid(sound Sound) bool {
csound := sound.cptr()
ret := C.IsSoundReady(*csound)
ret := C.IsSoundValid(*csound)
v := bool(ret)
return v
}
@ -315,12 +315,12 @@ func WaveCopy(wave Wave) Wave {
return v
}
// WaveCrop - Crop a wave to defined samples range
func WaveCrop(wave Wave, initSample int32, finalSample int32) {
// WaveCrop - Crop a wave to defined frames range
func WaveCrop(wave Wave, initFrame int32, finalFrame int32) {
cwave := wave.cptr()
cinitSample := (C.int)(initSample)
cfinalSample := (C.int)(finalSample)
C.WaveCrop(cwave, cinitSample, cfinalSample)
cinitFrame := (C.int)(initFrame)
cfinalFrame := (C.int)(finalFrame)
C.WaveCrop(cwave, cinitFrame, cfinalFrame)
}
// LoadWaveSamples - Get samples data from wave as a floats array
@ -356,10 +356,10 @@ func LoadMusicStreamFromMemory(fileType string, fileData []byte, dataSize int32)
return v
}
// IsMusicReady - Checks if a music stream is ready
func IsMusicReady(music Music) bool {
// IsMusicValid - Checks if a music stream is valid (context and buffers initialized)
func IsMusicValid(music Music) bool {
cmusic := *(*C.Music)(unsafe.Pointer(&music))
ret := C.IsMusicReady(cmusic)
ret := C.IsMusicValid(cmusic)
v := bool(ret)
return v
}
@ -462,10 +462,10 @@ func LoadAudioStream(sampleRate uint32, sampleSize uint32, channels uint32) Audi
return v
}
// IsAudioStreamReady - Checks if an audio stream is ready
func IsAudioStreamReady(stream AudioStream) bool {
// IsAudioStreamValid - Checks if an audio stream is valid (buffers initialized)
func IsAudioStreamValid(stream AudioStream) bool {
cstream := stream.cptr()
ret := C.IsAudioStreamReady(*cstream)
ret := C.IsAudioStreamValid(*cstream)
v := bool(ret)
return v
}

View file

@ -364,7 +364,7 @@ const (
// Android keys
KeyBack = 4
KeyMenu = 82
KeyMenu = 5
KeyVolumeUp = 24
KeyVolumeDown = 25
@ -411,12 +411,12 @@ const (
GamepadButtonLeftFaceDown // Gamepad left DPAD down button
GamepadButtonLeftFaceLeft // Gamepad left DPAD left button
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)
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
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
GamepadButtonMiddleLeft // Gamepad center buttons, left one (i.e. PS3: Select)
GamepadButtonMiddle // Gamepad center buttons, middle one (i.e. PS3: PS, Xbox: XBOX)
@ -729,14 +729,31 @@ type ShaderUniformDataType int32
// ShaderUniformDataType enumeration
const (
// Shader uniform type: float
ShaderUniformFloat ShaderUniformDataType = iota
// Shader uniform type: vec2 (2 float)
ShaderUniformVec2
// Shader uniform type: vec3 (3 float)
ShaderUniformVec3
// Shader uniform type: vec4 (4 float)
ShaderUniformVec4
// Shader uniform type: int
ShaderUniformInt
// Shader uniform type: ivec2 (2 int)
ShaderUniformIvec2
// Shader uniform type: ivec2 (3 int)
ShaderUniformIvec3
// Shader uniform type: ivec2 (4 int)
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
)
@ -795,6 +812,10 @@ type Mesh struct {
BoneIds *int32
// BoneWeights
BoneWeights *float32
// Bones animated transformation matrices
BoneMatrices *Matrix
// Number of bones
BoneCount int32
// OpenGL Vertex Array Object id
VaoID uint32
// 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
CubemapLayoutCrossThreeByFour // Layout is defined by a 3x4 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)
@ -1217,7 +1237,6 @@ type VrDeviceInfo struct {
VResolution int32 // Vertical resolution in pixels
HScreenSize float32 // Horizontal size in meters
VScreenSize float32 // Vertical size in meters
VScreenCenter float32 // Screen center in meters
EyeToScreenDistance float32 // Distance between eye and display in meters
LensSeparationDistance float32 // Lens separation distance 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:
* - NO external dependencies, all required libraries included with raylib
* - Multiplatform: Windows, Linux, FreeBSD, OpenBSD, NetBSD, DragonFly,
* MacOS, Haiku, Android, Raspberry Pi, DRM native, HTML5.
* - 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]
* - 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)
* - Full 3d support for 3d Shapes, Models, Billboards, Heightmaps and more!
* - 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
* - 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
* - Bindings to multiple programming languages available!
*
@ -27,29 +27,35 @@
* - One default RenderBatch is loaded on rlglInit()->rlLoadRenderBatch() [rlgl] (OpenGL 3.3 or ES2)
*
* DEPENDENCIES (included):
* [rcore] rglfw (Camilla Löwy - github.com/glfw/glfw) for window/context management and input (PLATFORM_DESKTOP)
* [rlgl] glad (David Herberth - github.com/Dav1dde/glad) for OpenGL 3.3 extensions loading (PLATFORM_DESKTOP)
* [rcore][GLFW] rglfw (Camilla Löwy - github.com/glfw/glfw) for window/context management and input
* [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
*
* OPTIONAL DEPENDENCIES (included):
* [rcore] msf_gif (Miles Fogle) for GIF recording
* [rcore] sinfl (Micha Mettke) for DEFLATE decompression 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_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_rect_pack (Sean Barret) for rectangles packing
* [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation
* [rmodels] tinyobj_loader_c (Syoyo Fujita) for models loading (OBJ, MTL)
* [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_flac (David Reid) for FLAC audio file loading
* [raudio] dr_mp3 (David Reid) for MP3 audio file loading
* [raudio] stb_vorbis (Sean Barret) for OGG audio loading
* [raudio] jar_xm (Joshua Reisenauer) for XM 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
@ -82,9 +88,9 @@
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
#define RAYLIB_VERSION_MAJOR 5
#define RAYLIB_VERSION_MINOR 1
#define RAYLIB_VERSION_MINOR 5
#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
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
@ -352,8 +358,10 @@ typedef struct Mesh {
// Animation vertex data
float *animVertices; // Animated vertex positions (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)
float *boneWeights; // Vertex bone weight, 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) (shader-location = 7)
Matrix *boneMatrices; // Bones animated transformation matrices
int boneCount; // Number of bones
// OpenGL identifiers
unsigned int vaoId; // OpenGL Vertex Array Object id
@ -421,7 +429,7 @@ typedef struct ModelAnimation {
// Ray, ray for raycasting
typedef struct Ray {
Vector3 position; // Ray position (origin)
Vector3 direction; // Ray direction
Vector3 direction; // Ray direction (normalized)
} Ray;
// RayCollision, ray hit information
@ -790,7 +798,10 @@ typedef enum {
SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap
SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance
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;
#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_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_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)
CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE // Layout is defined by a 4x3 cross with cubemap faces
} CubemapLayout;
// Font type, defines generation method
@ -934,7 +944,7 @@ typedef enum {
} NPatchLayout;
// 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 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
@ -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 IsWindowReady(void); // Check if window has been initialized successfully
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 IsWindowMinimized(void); // Check if window is currently minimized (only PLATFORM_DESKTOP)
RLAPI bool IsWindowMaximized(void); // Check if window is currently maximized (only PLATFORM_DESKTOP)
RLAPI bool IsWindowFocused(void); // Check if window is currently focused (only PLATFORM_DESKTOP)
RLAPI bool IsWindowHidden(void); // Check if window is currently hidden
RLAPI bool IsWindowMinimized(void); // Check if window is currently minimized
RLAPI bool IsWindowMaximized(void); // Check if window is currently maximized
RLAPI bool IsWindowFocused(void); // Check if window is currently focused
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 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 ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)
RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed (only PLATFORM_DESKTOP)
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP)
RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP)
RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP)
RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP)
RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP and PLATFORM_WEB)
RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (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, resizes window to match monitor resolution
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable
RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable
RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized
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)
RLAPI void SetWindowTitle(const char *title); // Set title for window
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 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 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 SetWindowFocused(void); // Set window focused (only PLATFORM_DESKTOP)
RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f]
RLAPI void SetWindowFocused(void); // Set window focused
RLAPI void *GetWindowHandle(void); // Get native window handle
RLAPI int GetScreenWidth(void); // Get current screen width
RLAPI int GetScreenHeight(void); // Get current screen height
RLAPI int GetRenderWidth(void); // Get current render width (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 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 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)
@ -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 void SetClipboardText(const char *text); // Set 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 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
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 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 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
@ -1066,7 +1077,7 @@ RLAPI double GetTime(void); // Get elapsed
RLAPI int GetFPS(void); // Get current FPS
// 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()
// 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)
@ -1093,7 +1104,7 @@ RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal me
RLAPI void MemFree(void *ptr); // Internal memory free
// 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 SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader
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 *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 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 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 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 bool IsFileDropped(void); // Check if a file has been dropped into window
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 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 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
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 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
@ -1154,7 +1171,7 @@ RLAPI void PlayAutomationEvent(AutomationEvent event);
// Input-related functions: keyboard
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 IsKeyReleased(int key); // Check if a key has been released once
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 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 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
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 bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
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 float GetGestureDragAngle(void); // Get gesture drag angle
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
// Basic shapes drawing functions
RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel
RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel (Vector version)
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 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 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 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 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 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 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)
@ -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 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 DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2);// 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 DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // Draw a gradient-filled rectangle with custom vertex colors
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 left, Color right); // Draw a horizontal-gradient-filled rectangle
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 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
@ -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 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 DrawTriangleFan(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 DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)
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 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
// Splines drawing functions
RLAPI void DrawSplineLinear(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 DrawSplineCatmullRom(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 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 DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points
RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, 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(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(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 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
@ -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 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 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 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 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 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
//------------------------------------------------------------------------------------
@ -1304,13 +1322,12 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);
// NOTE: These functions do not require GPU access
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 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 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 LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
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 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
@ -1330,6 +1347,7 @@ RLAPI Image GenImageText(int width, int height, const char *text);
// Image manipulation functions
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 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 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
@ -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 ImageAlphaPremultiply(Image *image); // Premultiply alpha channel
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 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 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
@ -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 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 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 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
@ -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 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 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 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)
@ -1389,9 +1413,9 @@ RLAPI Texture2D LoadTexture(const char *fileName);
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 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 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 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
@ -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 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 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 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
@ -1434,10 +1459,10 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
// Font loading/unloading functions
RLAPI Font GetFontDefault(void); // Get the default Font
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 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 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)
@ -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 *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 *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 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 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 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 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
@ -1524,7 +1552,7 @@ RLAPI void DrawGrid(int slices, float spacing);
// Model management functions
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 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 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 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 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 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 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
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 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 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
// Model animations loading/unloading functions
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 UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
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
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 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 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 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 UnloadWave(Wave wave); // Unload wave data
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 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 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 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()
@ -1632,7 +1663,7 @@ RLAPI void UnloadWaveSamples(float *samples); // Unload
// Music management functions
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 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 PlayMusicStream(Music music); // Start music 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
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 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

View file

@ -65,6 +65,7 @@ var getWindowScaleDPI func() uintptr
var getMonitorName func(monitor int32) string
var setClipboardText func(text string)
var getClipboardText func() string
var getClipboardImage func(img uintptr)
var enableEventWaiting func()
var disableEventWaiting func()
var showCursor func()
@ -94,7 +95,7 @@ var loadVrStereoConfig func(config uintptr, device uintptr)
var unloadVrStereoConfig func(config uintptr)
var loadShader func(shader uintptr, vsFileName uintptr, fsFileName 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 getShaderLocationAttrib func(shader uintptr, attribName string) 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 setShaderValueTexture func(shader uintptr, locIndex int32, texture 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 getCameraMatrix2D func(mat uintptr, camera uintptr)
var getWorldToScreen func(position uintptr, camera uintptr) uintptr
@ -158,6 +160,7 @@ var getGamepadButtonPressed func() int32
var getGamepadAxisCount func(gamepad int32) int32
var getGamepadAxisMovement func(gamepad int32, axis int32) float32
var setGamepadMappings func(mappings string) int32
var setGamepadVibration func(gamepad int32, leftMotor, rightMotor, duration float32)
var isMouseButtonPressed func(button int32) bool
var isMouseButtonDown func(button int32) bool
var isMouseButtonReleased func(button int32) bool
@ -186,6 +189,8 @@ var getGestureDragAngle func() float32
var getGesturePinchVector func() uintptr
var getGesturePinchAngle func() float32
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 drawPixelV func(position uintptr, 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 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 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 drawCircleLines func(centerX int32, centerY int32, 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 drawRectangleRec func(rec uintptr, 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 drawRectangleGradientH func(posX int32, posY int32, width int32, height int32, color1 uintptr, color2 uintptr)
var drawRectangleGradientEx func(rec uintptr, col1 uintptr, col2 uintptr, col3 uintptr, col4 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, left uintptr, right 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 drawRectangleLinesEx func(rec uintptr, lineThick float32, 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 drawTriangleLines func(v1 uintptr, v2 uintptr, v3 uintptr, 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 checkCollisionCircles func(center1 uintptr, radius1 float32, center2 uintptr, radius2 float32) 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 checkCollisionPointCircle func(point uintptr, center uintptr, radius float32) 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 loadImage func(img uintptr, fileName string)
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 loadImageFromTexture func(img uintptr, texture uintptr)
var loadImageFromScreen func(img uintptr)
var isImageReady func(image uintptr) bool
var isImageValid func(image uintptr) bool
var unloadImage func(image uintptr)
var exportImage func(image uintptr, fileName string) bool
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 imageCopy func(retImage uintptr, image 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 imageTextEx func(retImage uintptr, font uintptr, text string, fontSize float32, spacing float32, tint uintptr)
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 imageAlphaPremultiply func(image *Image)
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 imageResizeNN func(image *Image, newWidth int32, newHeight int32)
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 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 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 imageDrawCircleV func(dst *Image, center uintptr, 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 imageDrawRectangleRec func(dst *Image, rec uintptr, 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 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)
@ -321,9 +336,9 @@ var loadTexture func(texture uintptr, fileName string)
var loadTextureFromImage func(texture uintptr, image uintptr)
var loadTextureCubemap func(texture uintptr, image uintptr, layout 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 isRenderTextureReady func(target uintptr) bool
var isRenderTextureValid func(target uintptr) bool
var unloadRenderTexture func(target uintptr)
var updateTexture func(texture 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 colorAlpha func(col uintptr, alpha float32) 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 getPixelColor func(srcPtr unsafe.Pointer, format int32) uintptr
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 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 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 genImageFontAtlas func(image uintptr, glyphs *GlyphInfo, glyphRecs []*Rectangle, glyphCount int32, fontSize int32, padding int32, packMethod 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 loadModel func(model uintptr, fileName string)
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 getModelBoundingBox func(boundingBox uintptr, model 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 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 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 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 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)
@ -428,12 +446,13 @@ var genMeshHeightmap func(mesh uintptr, heightmap uintptr, size uintptr)
var genMeshCubicmap func(mesh uintptr, cubicmap uintptr, cubeSize uintptr)
var loadMaterials func(fileName string, materialCount *int32) *Material
var loadMaterialDefault func(material uintptr)
var isMaterialReady func(material uintptr) bool
var isMaterialValid func(material uintptr) bool
var unloadMaterial func(material uintptr)
var setMaterialTexture func(material *Material, mapType int32, texture uintptr)
var setModelMeshMaterial func(model *Model, meshId int32, materialId int32)
var loadModelAnimations func(fileName string, animCount *int32) *ModelAnimation
var updateModelAnimation func(model uintptr, anim uintptr, frame int32)
var updateModelAnimationBones func(model uintptr, anim uintptr, frame int32)
var unloadModelAnimation func(anim uintptr)
var unloadModelAnimations func(animations *ModelAnimation, animCount int32)
var isModelAnimationValid func(model uintptr, anim uintptr) bool
@ -452,11 +471,11 @@ var setMasterVolume func(volume float32)
var getMasterVolume func() float32
var loadWave func(wave uintptr, fileName string)
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 loadSoundFromWave func(sound uintptr, wave 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 unloadWave func(wave 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 setSoundPan func(sound uintptr, pan float32)
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 loadWaveSamples func(wave uintptr) *float32
var unloadWaveSamples func(samples []float32)
var loadMusicStream func(music uintptr, fileName string)
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 playMusicStream func(music uintptr)
var isMusicStreamPlaying func(music uintptr) bool
@ -492,7 +511,7 @@ var setMusicPan func(music uintptr, pan float32)
var getMusicTimeLength func(music uintptr) float32
var getMusicTimePlayed func(music uintptr) float32
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 updateAudioStream func(stream uintptr, data []float32, frameCount int32)
var isAudioStreamProcessed func(stream uintptr) bool
@ -562,6 +581,7 @@ func init() {
purego.RegisterLibFunc(&getMonitorName, raylibDll, "GetMonitorName")
purego.RegisterLibFunc(&setClipboardText, raylibDll, "SetClipboardText")
purego.RegisterLibFunc(&getClipboardText, raylibDll, "GetClipboardText")
purego.RegisterLibFunc(&getClipboardImage, raylibDll, "GetClipboardImage")
purego.RegisterLibFunc(&enableEventWaiting, raylibDll, "EnableEventWaiting")
purego.RegisterLibFunc(&disableEventWaiting, raylibDll, "DisableEventWaiting")
purego.RegisterLibFunc(&showCursor, raylibDll, "ShowCursor")
@ -591,7 +611,7 @@ func init() {
purego.RegisterLibFunc(&unloadVrStereoConfig, raylibDll, "UnloadVrStereoConfig")
purego.RegisterLibFunc(&loadShader, raylibDll, "LoadShader")
purego.RegisterLibFunc(&loadShaderFromMemory, raylibDll, "LoadShaderFromMemory")
purego.RegisterLibFunc(&isShaderReady, raylibDll, "IsShaderReady")
purego.RegisterLibFunc(&isShaderValid, raylibDll, "IsShaderValid")
purego.RegisterLibFunc(&getShaderLocation, raylibDll, "GetShaderLocation")
purego.RegisterLibFunc(&getShaderLocationAttrib, raylibDll, "GetShaderLocationAttrib")
purego.RegisterLibFunc(&setShaderValue, raylibDll, "SetShaderValue")
@ -599,7 +619,8 @@ func init() {
purego.RegisterLibFunc(&setShaderValueMatrix, raylibDll, "SetShaderValueMatrix")
purego.RegisterLibFunc(&setShaderValueTexture, raylibDll, "SetShaderValueTexture")
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(&getCameraMatrix2D, raylibDll, "GetCameraMatrix2D")
purego.RegisterLibFunc(&getWorldToScreen, raylibDll, "GetWorldToScreen")
@ -655,6 +676,7 @@ func init() {
purego.RegisterLibFunc(&getGamepadAxisCount, raylibDll, "GetGamepadAxisCount")
purego.RegisterLibFunc(&getGamepadAxisMovement, raylibDll, "GetGamepadAxisMovement")
purego.RegisterLibFunc(&setGamepadMappings, raylibDll, "SetGamepadMappings")
purego.RegisterLibFunc(&setGamepadVibration, raylibDll, "SetGamepadVibration")
purego.RegisterLibFunc(&isMouseButtonPressed, raylibDll, "IsMouseButtonPressed")
purego.RegisterLibFunc(&isMouseButtonDown, raylibDll, "IsMouseButtonDown")
purego.RegisterLibFunc(&isMouseButtonReleased, raylibDll, "IsMouseButtonReleased")
@ -683,6 +705,8 @@ func init() {
purego.RegisterLibFunc(&getGesturePinchVector, raylibDll, "GetGesturePinchVector")
purego.RegisterLibFunc(&getGesturePinchAngle, raylibDll, "GetGesturePinchAngle")
purego.RegisterLibFunc(&setShapesTexture, raylibDll, "SetShapesTexture")
purego.RegisterLibFunc(&getShapesTexture, raylibDll, "GetShapesTexture")
purego.RegisterLibFunc(&getShapesTextureRectangle, raylibDll, "GetShapesTextureRectangle")
purego.RegisterLibFunc(&drawPixel, raylibDll, "DrawPixel")
purego.RegisterLibFunc(&drawPixelV, raylibDll, "DrawPixelV")
purego.RegisterLibFunc(&drawLine, raylibDll, "DrawLine")
@ -712,6 +736,7 @@ func init() {
purego.RegisterLibFunc(&drawRectangleLinesEx, raylibDll, "DrawRectangleLinesEx")
purego.RegisterLibFunc(&drawRectangleRounded, raylibDll, "DrawRectangleRounded")
purego.RegisterLibFunc(&drawRectangleRoundedLines, raylibDll, "DrawRectangleRoundedLines")
purego.RegisterLibFunc(&drawRectangleRoundedLinesEx, raylibDll, "DrawRectangleRoundedLinesEx")
purego.RegisterLibFunc(&drawTriangle, raylibDll, "DrawTriangle")
purego.RegisterLibFunc(&drawTriangleLines, raylibDll, "DrawTriangleLines")
purego.RegisterLibFunc(&drawTriangleFan, raylibDll, "DrawTriangleFan")
@ -737,6 +762,7 @@ func init() {
purego.RegisterLibFunc(&checkCollisionRecs, raylibDll, "CheckCollisionRecs")
purego.RegisterLibFunc(&checkCollisionCircles, raylibDll, "CheckCollisionCircles")
purego.RegisterLibFunc(&checkCollisionCircleRec, raylibDll, "CheckCollisionCircleRec")
purego.RegisterLibFunc(&checkCollisionCircleLine, raylibDll, "CheckCollisionCircleLine")
purego.RegisterLibFunc(&checkCollisionPointRec, raylibDll, "CheckCollisionPointRec")
purego.RegisterLibFunc(&checkCollisionPointCircle, raylibDll, "CheckCollisionPointCircle")
purego.RegisterLibFunc(&checkCollisionPointTriangle, raylibDll, "CheckCollisionPointTriangle")
@ -746,12 +772,12 @@ func init() {
purego.RegisterLibFunc(&getCollisionRec, raylibDll, "GetCollisionRec")
purego.RegisterLibFunc(&loadImage, raylibDll, "LoadImage")
purego.RegisterLibFunc(&loadImageRaw, raylibDll, "LoadImageRaw")
purego.RegisterLibFunc(&loadImageSvg, raylibDll, "LoadImageSvg")
purego.RegisterLibFunc(&loadImageAnim, raylibDll, "LoadImageAnim")
purego.RegisterLibFunc(&loadImageAnimFromMemory, raylibDll, "LoadImageAnimFromMemory")
purego.RegisterLibFunc(&loadImageFromMemory, raylibDll, "LoadImageFromMemory")
purego.RegisterLibFunc(&loadImageFromTexture, raylibDll, "LoadImageFromTexture")
purego.RegisterLibFunc(&loadImageFromScreen, raylibDll, "LoadImageFromScreen")
purego.RegisterLibFunc(&isImageReady, raylibDll, "IsImageReady")
purego.RegisterLibFunc(&isImageValid, raylibDll, "IsImageValid")
purego.RegisterLibFunc(&unloadImage, raylibDll, "UnloadImage")
purego.RegisterLibFunc(&exportImage, raylibDll, "ExportImage")
purego.RegisterLibFunc(&exportImageToMemory, raylibDll, "ExportImageToMemory")
@ -766,6 +792,7 @@ func init() {
purego.RegisterLibFunc(&genImageText, raylibDll, "GenImageText")
purego.RegisterLibFunc(&imageCopy, raylibDll, "ImageCopy")
purego.RegisterLibFunc(&imageFromImage, raylibDll, "ImageFromImage")
purego.RegisterLibFunc(&imageFromChannel, raylibDll, "ImageFromChannel")
purego.RegisterLibFunc(&imageText, raylibDll, "ImageText")
purego.RegisterLibFunc(&imageTextEx, raylibDll, "ImageTextEx")
purego.RegisterLibFunc(&imageFormat, raylibDll, "ImageFormat")
@ -776,6 +803,7 @@ func init() {
purego.RegisterLibFunc(&imageAlphaMask, raylibDll, "ImageAlphaMask")
purego.RegisterLibFunc(&imageAlphaPremultiply, raylibDll, "ImageAlphaPremultiply")
purego.RegisterLibFunc(&imageBlurGaussian, raylibDll, "ImageBlurGaussian")
purego.RegisterLibFunc(&imageKernelConvolution, raylibDll, "ImageKernelConvolution")
purego.RegisterLibFunc(&imageResize, raylibDll, "ImageResize")
purego.RegisterLibFunc(&imageResizeNN, raylibDll, "ImageResizeNN")
purego.RegisterLibFunc(&imageResizeCanvas, raylibDll, "ImageResizeCanvas")
@ -803,6 +831,7 @@ func init() {
purego.RegisterLibFunc(&imageDrawPixelV, raylibDll, "ImageDrawPixelV")
purego.RegisterLibFunc(&imageDrawLine, raylibDll, "ImageDrawLine")
purego.RegisterLibFunc(&imageDrawLineV, raylibDll, "ImageDrawLineV")
purego.RegisterLibFunc(&imageDrawLineEx, raylibDll, "ImageDrawLineEx")
purego.RegisterLibFunc(&imageDrawCircle, raylibDll, "ImageDrawCircle")
purego.RegisterLibFunc(&imageDrawCircleV, raylibDll, "ImageDrawCircleV")
purego.RegisterLibFunc(&imageDrawCircleLines, raylibDll, "ImageDrawCircleLines")
@ -811,6 +840,11 @@ func init() {
purego.RegisterLibFunc(&imageDrawRectangleV, raylibDll, "ImageDrawRectangleV")
purego.RegisterLibFunc(&imageDrawRectangleRec, raylibDll, "ImageDrawRectangleRec")
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(&imageDrawText, raylibDll, "ImageDrawText")
purego.RegisterLibFunc(&imageDrawTextEx, raylibDll, "ImageDrawTextEx")
@ -818,9 +852,9 @@ func init() {
purego.RegisterLibFunc(&loadTextureFromImage, raylibDll, "LoadTextureFromImage")
purego.RegisterLibFunc(&loadTextureCubemap, raylibDll, "LoadTextureCubemap")
purego.RegisterLibFunc(&loadRenderTexture, raylibDll, "LoadRenderTexture")
purego.RegisterLibFunc(&isTextureReady, raylibDll, "IsTextureReady")
purego.RegisterLibFunc(&isTextureValid, raylibDll, "IsTextureValid")
purego.RegisterLibFunc(&unloadTexture, raylibDll, "UnloadTexture")
purego.RegisterLibFunc(&isRenderTextureReady, raylibDll, "IsRenderTextureReady")
purego.RegisterLibFunc(&isRenderTextureValid, raylibDll, "IsRenderTextureValid")
purego.RegisterLibFunc(&unloadRenderTexture, raylibDll, "UnloadRenderTexture")
purego.RegisterLibFunc(&updateTexture, raylibDll, "UpdateTexture")
purego.RegisterLibFunc(&updateTextureRec, raylibDll, "UpdateTextureRec")
@ -844,6 +878,7 @@ func init() {
purego.RegisterLibFunc(&colorContrast, raylibDll, "ColorContrast")
purego.RegisterLibFunc(&colorAlpha, raylibDll, "ColorAlpha")
purego.RegisterLibFunc(&colorAlphaBlend, raylibDll, "ColorAlphaBlend")
purego.RegisterLibFunc(&colorLerp, raylibDll, "ColorLerp")
purego.RegisterLibFunc(&getColor, raylibDll, "GetColor")
purego.RegisterLibFunc(&getPixelColor, raylibDll, "GetPixelColor")
purego.RegisterLibFunc(&setPixelColor, raylibDll, "SetPixelColor")
@ -853,7 +888,7 @@ func init() {
purego.RegisterLibFunc(&loadFontEx, raylibDll, "LoadFontEx")
purego.RegisterLibFunc(&loadFontFromImage, raylibDll, "LoadFontFromImage")
purego.RegisterLibFunc(&loadFontFromMemory, raylibDll, "LoadFontFromMemory")
purego.RegisterLibFunc(&isFontReady, raylibDll, "IsFontReady")
purego.RegisterLibFunc(&isFontValid, raylibDll, "IsFontValid")
purego.RegisterLibFunc(&loadFontData, raylibDll, "LoadFontData")
purego.RegisterLibFunc(&genImageFontAtlas, raylibDll, "GenImageFontAtlas")
purego.RegisterLibFunc(&unloadFontData, raylibDll, "UnloadFontData")
@ -893,13 +928,15 @@ func init() {
purego.RegisterLibFunc(&drawGrid, raylibDll, "DrawGrid")
purego.RegisterLibFunc(&loadModel, raylibDll, "LoadModel")
purego.RegisterLibFunc(&loadModelFromMesh, raylibDll, "LoadModelFromMesh")
purego.RegisterLibFunc(&isModelReady, raylibDll, "IsModelReady")
purego.RegisterLibFunc(&isModelValid, raylibDll, "IsModelValid")
purego.RegisterLibFunc(&unloadModel, raylibDll, "UnloadModel")
purego.RegisterLibFunc(&getModelBoundingBox, raylibDll, "GetModelBoundingBox")
purego.RegisterLibFunc(&drawModel, raylibDll, "DrawModel")
purego.RegisterLibFunc(&drawModelEx, raylibDll, "DrawModelEx")
purego.RegisterLibFunc(&drawModelWires, raylibDll, "DrawModelWires")
purego.RegisterLibFunc(&drawModelWiresEx, raylibDll, "DrawModelWiresEx")
purego.RegisterLibFunc(&drawModelPoints, raylibDll, "DrawModelPoints")
purego.RegisterLibFunc(&drawModelPointsEx, raylibDll, "DrawModelPointsEx")
purego.RegisterLibFunc(&drawBoundingBox, raylibDll, "DrawBoundingBox")
purego.RegisterLibFunc(&drawBillboard, raylibDll, "DrawBillboard")
purego.RegisterLibFunc(&drawBillboardRec, raylibDll, "DrawBillboardRec")
@ -925,12 +962,13 @@ func init() {
purego.RegisterLibFunc(&genMeshCubicmap, raylibDll, "GenMeshCubicmap")
purego.RegisterLibFunc(&loadMaterials, raylibDll, "LoadMaterials")
purego.RegisterLibFunc(&loadMaterialDefault, raylibDll, "LoadMaterialDefault")
purego.RegisterLibFunc(&isMaterialReady, raylibDll, "IsMaterialReady")
purego.RegisterLibFunc(&isMaterialValid, raylibDll, "IsMaterialValid")
purego.RegisterLibFunc(&unloadMaterial, raylibDll, "UnloadMaterial")
purego.RegisterLibFunc(&setMaterialTexture, raylibDll, "SetMaterialTexture")
purego.RegisterLibFunc(&setModelMeshMaterial, raylibDll, "SetModelMeshMaterial")
purego.RegisterLibFunc(&loadModelAnimations, raylibDll, "LoadModelAnimations")
purego.RegisterLibFunc(&updateModelAnimation, raylibDll, "UpdateModelAnimation")
purego.RegisterLibFunc(&updateModelAnimationBones, raylibDll, "UpdateModelAnimationBones")
purego.RegisterLibFunc(&unloadModelAnimation, raylibDll, "UnloadModelAnimation")
purego.RegisterLibFunc(&unloadModelAnimations, raylibDll, "UnloadModelAnimations")
purego.RegisterLibFunc(&isModelAnimationValid, raylibDll, "IsModelAnimationValid")
@ -949,11 +987,11 @@ func init() {
purego.RegisterLibFunc(&getMasterVolume, raylibDll, "GetMasterVolume")
purego.RegisterLibFunc(&loadWave, raylibDll, "LoadWave")
purego.RegisterLibFunc(&loadWaveFromMemory, raylibDll, "LoadWaveFromMemory")
purego.RegisterLibFunc(&isWaveReady, raylibDll, "IsWaveReady")
purego.RegisterLibFunc(&isWaveValid, raylibDll, "IsWaveValid")
purego.RegisterLibFunc(&loadSound, raylibDll, "LoadSound")
purego.RegisterLibFunc(&loadSoundFromWave, raylibDll, "LoadSoundFromWave")
purego.RegisterLibFunc(&loadSoundAlias, raylibDll, "LoadSoundAlias")
purego.RegisterLibFunc(&isSoundReady, raylibDll, "IsSoundReady")
purego.RegisterLibFunc(&isSoundValid, raylibDll, "IsSoundValid")
purego.RegisterLibFunc(&updateSound, raylibDll, "UpdateSound")
purego.RegisterLibFunc(&unloadWave, raylibDll, "UnloadWave")
purego.RegisterLibFunc(&unloadSound, raylibDll, "UnloadSound")
@ -974,7 +1012,7 @@ func init() {
purego.RegisterLibFunc(&unloadWaveSamples, raylibDll, "UnloadWaveSamples")
purego.RegisterLibFunc(&loadMusicStream, raylibDll, "LoadMusicStream")
purego.RegisterLibFunc(&loadMusicStreamFromMemory, raylibDll, "LoadMusicStreamFromMemory")
purego.RegisterLibFunc(&isMusicReady, raylibDll, "IsMusicReady")
purego.RegisterLibFunc(&isMusicValid, raylibDll, "IsMusicValid")
purego.RegisterLibFunc(&unloadMusicStream, raylibDll, "UnloadMusicStream")
purego.RegisterLibFunc(&playMusicStream, raylibDll, "PlayMusicStream")
purego.RegisterLibFunc(&isMusicStreamPlaying, raylibDll, "IsMusicStreamPlaying")
@ -989,7 +1027,7 @@ func init() {
purego.RegisterLibFunc(&getMusicTimeLength, raylibDll, "GetMusicTimeLength")
purego.RegisterLibFunc(&getMusicTimePlayed, raylibDll, "GetMusicTimePlayed")
purego.RegisterLibFunc(&loadAudioStream, raylibDll, "LoadAudioStream")
purego.RegisterLibFunc(&isAudioStreamReady, raylibDll, "IsAudioStreamReady")
purego.RegisterLibFunc(&isAudioStreamValid, raylibDll, "IsAudioStreamValid")
purego.RegisterLibFunc(&unloadAudioStream, raylibDll, "UnloadAudioStream")
purego.RegisterLibFunc(&updateAudioStream, raylibDll, "UpdateAudioStream")
purego.RegisterLibFunc(&isAudioStreamProcessed, raylibDll, "IsAudioStreamProcessed")
@ -1179,7 +1217,7 @@ func GetMonitorCount() int {
return int(getMonitorCount())
}
// GetCurrentMonitor - Get current connected monitor
// GetCurrentMonitor - Get current monitor where window is placed
func GetCurrentMonitor() int {
return int(getCurrentMonitor())
}
@ -1242,6 +1280,15 @@ func GetClipboardText() string {
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
func EnableEventWaiting() {
enableEventWaiting()
@ -1423,9 +1470,9 @@ func LoadShaderFromMemory(vsCode string, fsCode string) Shader {
return shader
}
// IsShaderReady - Check if a shader is ready
func IsShaderReady(shader Shader) bool {
return isShaderReady(uintptr(unsafe.Pointer(&shader)))
// IsShaderValid - Check if a shader is valid (loaded on GPU)
func IsShaderValid(shader Shader) bool {
return isShaderValid(uintptr(unsafe.Pointer(&shader)))
}
// GetShaderLocation - Get shader uniform location
@ -1464,9 +1511,23 @@ func UnloadShader(shader Shader) {
}
// GetMouseRay - Get a ray trace from mouse position
//
// Deprecated: Use [GetScreenToWorldRay] instead.
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
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
}
@ -1791,6 +1852,11 @@ func SetGamepadMappings(mappings string) int32 {
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
func IsMouseButtonPressed(button MouseButton) bool {
return isMouseButtonPressed(int32(button))
@ -1937,6 +2003,20 @@ func SetShapesTexture(texture Texture2D, source Rectangle) {
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
func DrawPixel(posX int32, posY int32, col color.RGBA) {
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
func DrawCircleGradient(centerX int32, centerY int32, radius float32, color1 color.RGBA, color2 color.RGBA) {
drawCircleGradient(centerX, centerY, radius, *(*uintptr)(unsafe.Pointer(&color1)), *(*uintptr)(unsafe.Pointer(&color2)))
func DrawCircleGradient(centerX int32, centerY int32, radius float32, inner color.RGBA, outer color.RGBA) {
drawCircleGradient(centerX, centerY, radius, *(*uintptr)(unsafe.Pointer(&inner)), *(*uintptr)(unsafe.Pointer(&outer)))
}
// 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
func DrawRectangleGradientV(posX int32, posY int32, width int32, height int32, color1 color.RGBA, color2 color.RGBA) {
drawRectangleGradientV(posX, posY, width, height, *(*uintptr)(unsafe.Pointer(&color1)), *(*uintptr)(unsafe.Pointer(&color2)))
func DrawRectangleGradientV(posX int32, posY int32, width int32, height int32, top color.RGBA, bottom color.RGBA) {
drawRectangleGradientV(posX, posY, width, height, *(*uintptr)(unsafe.Pointer(&top)), *(*uintptr)(unsafe.Pointer(&bottom)))
}
// DrawRectangleGradientH - Draw a horizontal-gradient-filled rectangle
func DrawRectangleGradientH(posX int32, posY int32, width int32, height int32, color1 color.RGBA, color2 color.RGBA) {
drawRectangleGradientH(posX, posY, width, height, *(*uintptr)(unsafe.Pointer(&color1)), *(*uintptr)(unsafe.Pointer(&color2)))
func DrawRectangleGradientH(posX int32, posY int32, width int32, height int32, left color.RGBA, right color.RGBA) {
drawRectangleGradientH(posX, posY, width, height, *(*uintptr)(unsafe.Pointer(&left)), *(*uintptr)(unsafe.Pointer(&right)))
}
// 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) {
drawRectangleGradientEx(uintptr(unsafe.Pointer(&rec)), *(*uintptr)(unsafe.Pointer(&col1)), *(*uintptr)(unsafe.Pointer(&col2)), *(*uintptr)(unsafe.Pointer(&col3)), *(*uintptr)(unsafe.Pointer(&col4)))
func DrawRectangleGradientEx(rec Rectangle, topLeft color.RGBA, bottomLeft color.RGBA, topRight color.RGBA, bottomRight color.RGBA) {
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
@ -2078,9 +2158,14 @@ func DrawRectangleRounded(rec Rectangle, roundness float32, segments int32, col
drawRectangleRounded(uintptr(unsafe.Pointer(&rec)), roundness, segments, *(*uintptr)(unsafe.Pointer(&col)))
}
// DrawRectangleRoundedLines - Draw rectangle with rounded edges outline
func DrawRectangleRoundedLines(rec Rectangle, roundness float32, segments float32, lineThick float32, col color.RGBA) {
drawRectangleRoundedLines(uintptr(unsafe.Pointer(&rec)), roundness, int32(segments), lineThick, *(*uintptr)(unsafe.Pointer(&col)))
// DrawRectangleRoundedLines - Draw rectangle lines with rounded edges
func DrawRectangleRoundedLines(rec Rectangle, roundness float32, segments int32, col color.RGBA) {
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!)
@ -2220,6 +2305,11 @@ func CheckCollisionCircleRec(center Vector2, radius float32, rec Rectangle) bool
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
func CheckCollisionPointRec(point Vector2, rec Rectangle) bool {
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
}
// LoadImageSvg - Load image from SVG file data or string with specified size
func LoadImageSvg(fileNameOrString string, width int32, height int32) *Image {
// LoadImageAnim - Load image sequence from file (frames appended to image.data)
func LoadImageAnim(fileName string, frames *int32) *Image {
var img Image
loadImageSvg(uintptr(unsafe.Pointer(&img)), fileNameOrString, width, height)
loadImageAnim(uintptr(unsafe.Pointer(&img)), fileName, frames)
return &img
}
// LoadImageAnim - Load image sequence from file (frames appended to image.data)
func LoadImageAnim(fileName string, frames []int32) *Image {
// LoadImageAnimFromMemory - Load image sequence from memory buffer
func LoadImageAnimFromMemory(fileType string, fileData []byte, dataSize int32, frames *int32) *Image {
var img Image
loadImageAnim(uintptr(unsafe.Pointer(&img)), fileName, frames)
loadImageAnimFromMemory(uintptr(unsafe.Pointer(&img)), fileType, fileData, dataSize, frames)
return &img
}
@ -2307,9 +2397,9 @@ func LoadImageFromScreen() *Image {
return &img
}
// IsImageReady - Check if an image is ready
func IsImageReady(image *Image) bool {
return isImageReady(uintptr(unsafe.Pointer(image)))
// IsImageValid - Check if an image is valid (data and parameters)
func IsImageValid(image *Image) bool {
return isImageValid(uintptr(unsafe.Pointer(image)))
}
// UnloadImage - Unload image from CPU memory (RAM)
@ -2406,6 +2496,13 @@ func ImageFromImage(image Image, rec Rectangle) Image {
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)
func ImageText(text string, fontSize int32, col color.RGBA) Image {
var retImage Image
@ -2460,6 +2557,11 @@ func ImageBlurGaussian(image *Image, blurSize int32) {
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)
func ImageResize(image *Image, newWidth int32, newHeight int32) {
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)
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)))
}
// 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
func ImageDrawCircle(dst *Image, centerX int32, centerY int32, radius int32, col color.RGBA) {
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)))
}
// 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)
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)))
@ -2689,9 +2823,9 @@ func LoadRenderTexture(width int32, height int32) RenderTexture2D {
return texture
}
// IsTextureReady - Check if a texture is ready
func IsTextureReady(texture Texture2D) bool {
return isTextureReady(uintptr(unsafe.Pointer(&texture)))
// IsTextureValid - Check if a texture is valid (loaded in GPU)
func IsTextureValid(texture Texture2D) bool {
return isTextureValid(uintptr(unsafe.Pointer(&texture)))
}
// UnloadTexture - Unload texture from GPU memory (VRAM)
@ -2699,9 +2833,9 @@ func UnloadTexture(texture Texture2D) {
unloadTexture(uintptr(unsafe.Pointer(&texture)))
}
// IsRenderTextureReady - Check if a render texture is ready
func IsRenderTextureReady(target RenderTexture2D) bool {
return isRenderTextureReady(uintptr(unsafe.Pointer(&target)))
// IsRenderTextureValid - Check if a render texture is valid (loaded in GPU)
func IsRenderTextureValid(target RenderTexture2D) bool {
return isRenderTextureValid(uintptr(unsafe.Pointer(&target)))
}
// 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))
}
// ColorToInt - Get hexadecimal value for a Color
// ColorToInt - Get hexadecimal value for a Color (0xRRGGBBAA)
func ColorToInt(col color.RGBA) int32 {
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))
}
// 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
func GetColor(hexValue uint) color.RGBA {
ret := getColor(uint32(hexValue))
@ -2894,9 +3034,9 @@ func LoadFontFromMemory(fileType string, fileData []byte, fontSize int32, codepo
return font
}
// IsFontReady - Check if a font is ready
func IsFontReady(font Font) bool {
return isFontReady(uintptr(unsafe.Pointer(&font)))
// IsFontValid - Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
func IsFontValid(font Font) bool {
return isFontValid(uintptr(unsafe.Pointer(&font)))
}
// LoadFontData - Load font data for further use
@ -3115,9 +3255,9 @@ func LoadModelFromMesh(mesh Mesh) Model {
return model
}
// IsModelReady - Check if a model is ready
func IsModelReady(model Model) bool {
return isModelReady(uintptr(unsafe.Pointer(&model)))
// IsModelValid - Check if a model is valid (loaded in GPU, VAO/VBOs)
func IsModelValid(model Model) bool {
return isModelValid(uintptr(unsafe.Pointer(&model)))
}
// 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)))
}
// 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)
func DrawBoundingBox(box BoundingBox, col color.RGBA) {
drawBoundingBox(uintptr(unsafe.Pointer(&box)), *(*uintptr)(unsafe.Pointer(&col)))
}
// DrawBillboard - Draw a billboard texture
func DrawBillboard(camera Camera, texture Texture2D, position Vector3, size float32, tint color.RGBA) {
drawBillboard(uintptr(unsafe.Pointer(&camera)), uintptr(unsafe.Pointer(&texture)), uintptr(unsafe.Pointer(&position)), size, *(*uintptr)(unsafe.Pointer(&tint)))
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)), scale, *(*uintptr)(unsafe.Pointer(&tint)))
}
// DrawBillboardRec - Draw a billboard texture defined by source
@ -3306,9 +3456,9 @@ func LoadMaterialDefault() Material {
return material
}
// IsMaterialReady - Check if a material is ready
func IsMaterialReady(material Material) bool {
return isMaterialReady(uintptr(unsafe.Pointer(&material)))
// IsMaterialValid - Check if a material is valid (shader assigned, map textures loaded in GPU)
func IsMaterialValid(material Material) bool {
return isMaterialValid(uintptr(unsafe.Pointer(&material)))
}
// UnloadMaterial - Unload material from GPU memory (VRAM)
@ -3333,11 +3483,16 @@ func LoadModelAnimations(fileName string) []ModelAnimation {
return unsafe.Slice(ret, animCount)
}
// UpdateModelAnimation - Update model animation pose
// UpdateModelAnimation - Update model animation pose (CPU)
func UpdateModelAnimation(model Model, anim ModelAnimation, frame int32) {
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
func UnloadModelAnimation(anim ModelAnimation) {
unloadModelAnimation(uintptr(unsafe.Pointer(&anim)))
@ -3443,9 +3598,9 @@ func LoadWaveFromMemory(fileType string, fileData []byte, dataSize int32) Wave {
return wave
}
// IsWaveReady - Checks if wave data is ready
func IsWaveReady(wave Wave) bool {
return isWaveReady(uintptr(unsafe.Pointer(&wave)))
// IsWaveValid - Checks if wave data is valid (data loaded and parameters)
func IsWaveValid(wave Wave) bool {
return isWaveValid(uintptr(unsafe.Pointer(&wave)))
}
// LoadSound - Load sound from file
@ -3469,9 +3624,9 @@ func LoadSoundAlias(source Sound) Sound {
return sound
}
// IsSoundReady - Checks if a sound is ready
func IsSoundReady(sound Sound) bool {
return isSoundReady(uintptr(unsafe.Pointer(&sound)))
// IsSoundValid - Checks if a sound is valid (data loaded and buffers initialized)
func IsSoundValid(sound Sound) bool {
return isSoundValid(uintptr(unsafe.Pointer(&sound)))
}
// UpdateSound - Update sound buffer with new data
@ -3546,9 +3701,9 @@ func WaveCopy(wave Wave) Wave {
return copy
}
// WaveCrop - Crop a wave to defined samples range
func WaveCrop(wave *Wave, initSample int32, finalSample int32) {
waveCrop(wave, initSample, finalSample)
// WaveCrop - Crop a wave to defined frames range
func WaveCrop(wave *Wave, initFrame int32, finalFrame int32) {
waveCrop(wave, initFrame, finalFrame)
}
// WaveFormat - Convert wave data to desired format
@ -3581,9 +3736,9 @@ func LoadMusicStreamFromMemory(fileType string, data []byte, dataSize int32) Mus
return music
}
// IsMusicReady - Checks if a music stream is ready
func IsMusicReady(music Music) bool {
return isMusicReady(uintptr(unsafe.Pointer(&music)))
// IsMusicValid - Checks if a music stream is valid (context and buffers initialized)
func IsMusicValid(music Music) bool {
return isMusicValid(uintptr(unsafe.Pointer(&music)))
}
// UnloadMusicStream - Unload music stream
@ -3658,9 +3813,9 @@ func LoadAudioStream(sampleRate uint32, sampleSize uint32, channels uint32) Audi
return audioStream
}
// IsAudioStreamReady - Checks if an audio stream is ready
func IsAudioStreamReady(stream AudioStream) bool {
return isAudioStreamReady(uintptr(unsafe.Pointer(&stream)))
// IsAudioStreamValid - Checks if an audio stream is valid (buffers initialized)
func IsAudioStreamValid(stream AudioStream) bool {
return isAudioStreamValid(uintptr(unsafe.Pointer(&stream)))
}
// 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:
* - 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,
* required code is directly re-implemented inside
* - 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
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
* - 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.
* This may use up lots of memory.
*
* #define RAYMATH_DISABLE_CPP_OPERATORS
* Disables C++ operator overloads for raymath types.
*
* LICENSE: zlib/libpng
*
@ -77,6 +79,7 @@
#endif
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@ -174,7 +177,7 @@ typedef struct float16 {
// Clamp float value
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;
@ -961,12 +964,12 @@ RMAPI Vector3 Vector3CubicHermite(Vector3 v1, Vector3 tangent1, Vector3 v2, Vect
{
Vector3 result = { 0 };
float amountPow2 = amount * amount;
float amountPow3 = amount * amount * amount;
float amountPow2 = 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.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.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.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;
}
@ -1836,32 +1839,32 @@ RMAPI Matrix MatrixScale(float x, float y, float z)
}
// 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 };
float rl = (float)(right - left);
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.m2 = 0.0f;
result.m3 = 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.m7 = 0.0f;
result.m8 = ((float)right + (float)left)/rl;
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.m12 = 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;
return result;
@ -2217,11 +2220,11 @@ 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
RMAPI Quaternion QuaternionCubicHermiteSpline(Quaternion q1, Quaternion outTangent1, Quaternion q2, Quaternion inTangent2, float t)
{
float t2 = t * t;
float t3 = t2 * t;
float h00 = 2 * t3 - 3 * t2 + 1;
float h10 = t3 - 2 * t2 + t;
float h01 = -2 * t3 + 3 * t2;
float t2 = t*t;
float t3 = t2*t;
float h00 = 2*t3 - 3*t2 + 1;
float h10 = t3 - 2*t2 + t;
float h01 = -2*t3 + 3*t2;
float h11 = t3 - t2;
Quaternion p0 = QuaternionScale(q1, h00);
@ -2566,7 +2569,13 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio
if (!FloatEquals(det, 0))
{
clone.m0 /= s.x;
clone.m4 /= s.x;
clone.m8 /= s.x;
clone.m1 /= s.y;
clone.m5 /= s.y;
clone.m9 /= s.y;
clone.m2 /= s.z;
clone.m6 /= s.z;
clone.m10 /= s.z;
// 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

View file

@ -162,7 +162,6 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
#endif // RCAMERA_H
/***********************************************************************************
*
* CAMERA IMPLEMENTATION
@ -196,12 +195,12 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
//----------------------------------------------------------------------------------
// 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_PAN_SPEED 0.2f
// 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
#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 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) {}
else if (mode == CAMERA_ORBITAL)
{
// 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);
view = Vector3Transform(view, rotation);
camera->position = Vector3Add(camera->target, view);
@ -456,22 +461,22 @@ void UpdateCamera(Camera *camera, int mode)
else
{
// Camera rotation
if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp);
if (IsKeyDown(KEY_UP)) CameraPitch(camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp);
if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget);
if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, CAMERA_ROTATION_SPEED, rotateAroundTarget);
if (IsKeyDown(KEY_Q)) CameraRoll(camera, -CAMERA_ROTATION_SPEED);
if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED);
if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp);
if (IsKeyDown(KEY_UP)) CameraPitch(camera, cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp);
if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -cameraRotationSpeed, rotateAroundTarget);
if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, cameraRotationSpeed, rotateAroundTarget);
if (IsKeyDown(KEY_Q)) CameraRoll(camera, -cameraRotationSpeed);
if (IsKeyDown(KEY_E)) CameraRoll(camera, cameraRotationSpeed);
// Camera movement
// Camera pan (for CAMERA_FREE)
if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)))
{
const Vector2 mouseDelta = GetMouseDelta();
if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane);
if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane);
if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED);
if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED);
if (mouseDelta.x > 0.0f) CameraMoveRight(camera, cameraPanSpeed, moveInWorldPlane);
if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -cameraPanSpeed, moveInWorldPlane);
if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -cameraPanSpeed);
if (mouseDelta.y < 0.0f) CameraMoveUp(camera, cameraPanSpeed);
}
else
{
@ -481,28 +486,28 @@ void UpdateCamera(Camera *camera, int mode)
}
// Keyboard support
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane);
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane);
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane);
if (IsKeyDown(KEY_D)) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane);
// Gamepad movement
if (IsGamepadAvailable(0))
{
// Gamepad controller support
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);
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);
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(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, -cameraMoveSpeed, 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, cameraMoveSpeed, moveInWorldPlane);
}
if (mode == CAMERA_FREE)
{
if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED);
if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED);
if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, cameraMoveSpeed);
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
*
* PLATFORMS SUPPORTED:
* > PLATFORM_DESKTOP (GLFW backend):
* > PLATFORM_DESKTOP_GLFW (GLFW backend):
* - Windows (Win32, Win64)
* - Linux (X11/Wayland desktop mode)
* - 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 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);
unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);
unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
__declspec(dllimport) unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);
__declspec(dllimport) unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#elif defined(__linux__)
#include <unistd.h>
#elif defined(__FreeBSD__)
#include <sys/types.h>
#include <sys/sysctl.h>
#include <unistd.h>
#elif defined(__APPLE__)
#include <sys/syslimits.h>
#include <mach-o/dyld.h>
@ -187,14 +191,16 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#endif
#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 CHDIR _chdir
#include <io.h> // Required for: _access() [Used in FileExists()]
#define MKDIR(dir) _mkdir(dir)
#else
#include <unistd.h> // Required for: getch(), chdir() (POSIX), access()
#include <unistd.h> // Required for: getch(), chdir(), mkdir(), access()
#define GETCWD getcwd
#define CHDIR chdir
#define MKDIR(dir) mkdir(dir, 0777)
#endif
//----------------------------------------------------------------------------------
@ -247,6 +253,10 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
#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
#define FLAG_SET(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
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)
static int screenshotCounter = 0; // Screenshots counter
static int screenshotCounter = 0; // Screenshots counter
#endif
#if defined(SUPPORT_GIF_RECORDING)
unsigned int gifFrameCounter = 0; // GIF frames counter
bool gifRecording = false; // GIF recording state
MsfGifState gifState = { 0 }; // MSGIF context state
static unsigned int gifFrameCounter = 0; // GIF frames counter
static bool gifRecording = false; // GIF recording state
static MsfGifState gifState = { 0 }; // MSGIF context state
#endif
#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'
#endif // !SUPPORT_MODULE_RTEXT
// Include platform-specific submodules
#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)
#include "platforms/rcore_desktop_sdl.c"
#elif defined(PLATFORM_DESKTOP_RGFW)
@ -559,15 +601,16 @@ const char *TextFormat(const char *text, ...); // Formatting of tex
//void DisableCursor(void)
// 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)
{
TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);
#if defined(PLATFORM_DESKTOP)
#if defined(PLATFORM_DESKTOP_GLFW)
TRACELOG(LOG_INFO, "Platform backend: DESKTOP (GLFW)");
#elif defined(PLATFORM_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)
TRACELOG(LOG_INFO, "Platform backend: WEB (HTML5)");
#elif defined(PLATFORM_DRM)
@ -631,28 +674,31 @@ void InitWindow(int width, int height, const char *title)
// 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
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
isGpuReady = true; // Flag to note GPU has been initialized successfully
// Setup default viewport
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Load default font
// WARNING: External function: Module required: rtext
LoadFontDefault();
#if defined(SUPPORT_MODULE_RSHAPES)
// Set font white rectangle for shapes drawing, so shapes and text can be batched together
// WARNING: rshapes module is required, if not available, default internal white rectangle is used
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 });
}
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 });
}
#if defined(SUPPORT_MODULE_RTEXT)
#if defined(SUPPORT_DEFAULT_FONT)
// Load default font
// WARNING: External function: Module required: rtext
LoadFontDefault();
#if defined(SUPPORT_MODULE_RSHAPES)
// Set font white rectangle for shapes drawing, so shapes and text can be batched together
// WARNING: rshapes module is required, if not available, default internal white rectangle is used
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 });
}
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 });
}
#endif
#endif
#else
#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
#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.Window.shouldClose = false;
// Initialize random seed
SetRandomSeed((unsigned int)time(NULL));
TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", GetWorkingDirectory());
}
// Close window and unload OpenGL context
@ -856,7 +895,7 @@ void EndDrawing(void)
#ifndef GIF_RECORD_FRAMERATE
#define GIF_RECORD_FRAMERATE 10
#endif
gifFrameCounter += GetFrameTime()*1000;
gifFrameCounter += (unsigned int)(GetFrameTime()*1000);
// NOTE: We record one gif frame depending on the desired gif framerate
if (gifFrameCounter > 1000/GIF_RECORD_FRAMERATE)
@ -1288,6 +1327,8 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
// vertex color location = 3
// vertex tangent location = 4
// vertex texcoord2 location = 5
// vertex boneIds location = 6
// vertex boneWeights location = 7
// 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_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_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)
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_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_BONE_MATRICES] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES);
// Get handles to GLSL uniform locations (fragment shader)
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;
}
// Check if a shader is ready
bool IsShaderReady(Shader shader)
// Check if a shader is valid (loaded on GPU)
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
// The following locations are tried to be set automatically (locs[i] >= 0),
@ -2154,6 +2198,28 @@ const char *GetApplicationDirectory(void)
appDir[0] = '.';
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
return appDir;
@ -2225,6 +2291,40 @@ void UnloadDirectoryFiles(FilePathList files)
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
bool ChangeDirectory(const char *dir)
{
@ -2244,6 +2344,64 @@ bool IsPathFile(const char *path)
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
bool IsFileDropped(void)
{
@ -2442,6 +2600,265 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
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
//----------------------------------------------------------------------------------
@ -2649,8 +3066,8 @@ void PlayAutomationEvent(AutomationEvent event)
} break;
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.y = (float)event.params[1]; break;
CORE.Input.Mouse.currentWheelMove.x = (float)event.params[0];
CORE.Input.Mouse.currentWheelMove.y = (float)event.params[1];
} break;
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
@ -2687,6 +3104,8 @@ void PlayAutomationEvent(AutomationEvent event)
case ACTION_SETTARGETFPS: SetTargetFPS(event.params[0]); 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
}
@ -2894,10 +3313,13 @@ int GetGamepadAxisCount(int gamepad)
// Get axis movement vector for a gamepad
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) &&
(fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]) > 0.1f)) value = CORE.Input.Gamepad.axisState[gamepad][axis]; // 0.1f = GAMEPAD_AXIS_MINIMUM_DRIFT/DELTA
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS)) {
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;
}
@ -3242,10 +3664,21 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
if (filter != NULL)
{
if (IsFileExtension(path, filter))
if (IsPathFile(path))
{
strcpy(files->paths[files->count], path);
files->count++;
if (IsFileExtension(path, filter))
{
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
@ -3305,7 +3738,22 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi
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].type = INPUT_MOUSE_WHEEL_MOTION;
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;
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++)
{
// 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].type = INPUT_GAMEPAD_AXIS_MOTION;

View file

@ -338,7 +338,7 @@ func GetMonitorCount() int {
return v
}
// GetCurrentMonitor - Get current connected monitor
// GetCurrentMonitor - Get current monitor where window is placed
func GetCurrentMonitor() int {
ret := C.GetCurrentMonitor()
v := (int)(ret)
@ -429,6 +429,15 @@ func GetClipboardText() string {
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
func EnableEventWaiting() {
C.EnableEventWaiting()
@ -546,10 +555,10 @@ func LoadShaderFromMemory(vsCode string, fsCode string) Shader {
return v
}
// IsShaderReady - Check if a shader is ready
func IsShaderReady(shader Shader) bool {
// IsShaderValid - Check if a shader is valid (loaded on GPU)
func IsShaderValid(shader Shader) bool {
cshader := shader.cptr()
ret := C.IsShaderReady(*cshader)
ret := C.IsShaderValid(*cshader)
v := bool(ret)
return v
}
@ -617,11 +626,29 @@ func UnloadShader(shader Shader) {
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 {
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()
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))
return v
}
@ -738,7 +765,7 @@ func Fade(col color.RGBA, alpha float32) color.RGBA {
return v
}
// ColorToInt - Returns hexadecimal value for a Color
// ColorToInt - Get hexadecimal value for a Color (0xRRGGBBAA)
func ColorToInt(col color.RGBA) int32 {
ccolor := colorCptr(col)
ret := C.ColorToInt(*ccolor)
@ -826,6 +853,15 @@ func ColorAlphaBlend(src, dst, tint color.RGBA) color.RGBA {
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
func GetColor(hexValue uint) color.RGBA {
chexValue := (C.uint)(hexValue)
@ -1081,6 +1117,11 @@ func SetGamepadMappings(mappings string) int32 {
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
func IsMouseButtonPressed(button MouseButton) bool {
cbutton := (C.int)(button)

View file

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

View file

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

View file

@ -8,17 +8,17 @@
*
* ADDITIONAL NOTES:
* 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,
* 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:
* - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data
* - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8
* - 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:
* #define GRAPHICS_API_OPENGL_11
@ -32,9 +32,9 @@
* required by any other module, use rlGetVersion() to check it
*
* #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
* 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
* 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_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_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_VIEW "matView" // view 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_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_BONE_MATRICES "boneMatrices" // bone matrices
* #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_TEXTURE2 "texture2" // texture2 (texture slot active 2)
@ -324,22 +327,33 @@
// Default shader vertex attribute locations
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4
#endif
#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
//----------------------------------------------------------------------------------
@ -527,6 +541,10 @@ typedef enum {
RL_SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int)
RL_SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 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
} 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 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 rlSetClipPlanes(double near, double far); // Set clip planes distances
RLAPI double rlGetCullDistanceNear(); // Get cull plane distance near
RLAPI double rlGetCullDistanceFar(); // Get cull plane distance far
RLAPI void rlSetClipPlanes(double nearPlane, double farPlane); // Set clip planes distances
RLAPI double rlGetCullDistanceNear(void); // Get cull plane distance near
RLAPI double rlGetCullDistanceFar(void); // Get cull plane distance far
//------------------------------------------------------------------------------------
// 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 rlEnableWireMode(void); // Enable wire 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 float rlGetLineWidth(void); // Get the line drawing width
RLAPI void rlEnableSmoothLines(void); // Enable line aliasing
@ -731,7 +749,7 @@ RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, const void
// Textures management
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 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 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
@ -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 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 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 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
#include <GLES2/gl2ext.h> // OpenGL ES 2.0 extensions library
#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
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL)
#if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL)
#define GLAD_GLES2_IMPLEMENTATION
#include "external/glad_gles2.h"
#else
@ -973,6 +992,12 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#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
#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
#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
#define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
#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
#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
#endif
@ -1371,10 +1399,10 @@ void rlViewport(int x, int y, int width, int height)
}
// Set clip planes distances
void rlSetClipPlanes(double near, double far)
void rlSetClipPlanes(double nearPlane, double farPlane)
{
rlCullDistanceNear = near;
rlCullDistanceFar = far;
rlCullDistanceNear = nearPlane;
rlCullDistanceFar = farPlane;
}
// 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 rlVertex2f(float x, float y) { glVertex2f(x, y); }
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;
}
// 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.
// 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
// 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))
{
@ -1560,7 +1588,7 @@ void rlNormal3f(float x, float y, float z)
float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz);
if (length != 0.0f)
{
float ilength = 1.0f / length;
float ilength = 1.0f/length;
normalx *= ilength;
normaly *= ilength;
normalz *= ilength;
@ -1948,6 +1976,7 @@ void rlEnableWireMode(void)
#endif
}
// Enable point mode
void rlEnablePointMode(void)
{
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
@ -1956,6 +1985,7 @@ void rlEnablePointMode(void)
glEnable(GL_PROGRAM_POINT_SIZE);
#endif
}
// Disable wire mode
void rlDisableWireMode(void)
{
@ -2038,7 +2068,7 @@ void rlClearScreenBuffers(void)
}
// Check and log OpenGL error codes
void rlCheckErrors()
void rlCheckErrors(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
int check = 1;
@ -2390,7 +2420,7 @@ void rlLoadExtensions(void *loader)
#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
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");
@ -2442,25 +2472,47 @@ void rlLoadExtensions(void *loader)
}
// 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");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE");
if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
}
else
{
if ((strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0) && // Standard EXT
(strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0))
// Specific check
if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // ANGLE
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE");
}
else if (strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0) // EXT
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT");
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
@ -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);
//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.
// 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().
// NOTE: glMapBuffer() causes sync issue
// 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()
// 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
// 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
// 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)
{
@ -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);
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
// 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
glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint)));
#endif
#if defined(GRAPHICS_API_OPENGL_ES2)
#endif
#if defined(GRAPHICS_API_OPENGL_ES2)
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);
@ -3334,11 +3386,17 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
// Load texture cubemap
// 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
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;
#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);
glGenTextures(1, &id);
@ -3349,24 +3407,28 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format)
if (glInternalFormat != 0)
{
// Load cubemap faces
for (unsigned int i = 0; i < 6; i++)
// Load cubemap faces/mipmaps
for (int i = 0; i < 6*mipmapCount; i++)
{
int mipmapLevel = i/6;
int face = i%6;
if (data == NULL)
{
if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)
{
if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32)
|| (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported");
else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, NULL);
if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) ||
(format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32) ||
(format == RL_PIXELFORMAT_UNCOMPRESSED_R16) ||
(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
{
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);
else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, dataSize, (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 + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, dataSize, (unsigned char *)dataPtr + face*dataSize);
}
#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);
}
#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
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_WRAP_S, 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_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.
// Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting.
// 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
// 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.)
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)
// 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:
// 1 - Bind texture to color fbo attachment and 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);
// 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);
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):
// - 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
glVertexAttribPointer(index, compSize, type, normalized, stride, (void *)offset);
size_t offsetNative = offset;
glVertexAttribPointer(index, compSize, type, normalized, stride, (void *)offsetNative);
#endif
}
@ -3992,18 +4068,18 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
unsigned int fragmentShaderId = 0;
// Compile vertex shader (if provided)
// NOTE: If not vertex shader is provided, use default one
if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER);
// In case no vertex shader was provided or compilation failed, we use default vertex shader
if (vertexShaderId == 0) vertexShaderId = RLGL.State.defaultVShaderId;
else vertexShaderId = RLGL.State.defaultVShaderId;
// Compile fragment shader (if provided)
// NOTE: If not vertex shader is provided, use default one
if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);
// In case no fragment shader was provided or compilation failed, we use default fragment shader
if (fragmentShaderId == 0) fragmentShaderId = RLGL.State.defaultFShaderId;
else 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
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
id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId);
@ -4081,6 +4157,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
//case GL_GEOMETRY_SHADER:
#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;
#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
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);
RL_FREE(log);
}
shader = 0;
}
else
{
@ -4106,6 +4186,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
//case GL_GEOMETRY_SHADER:
#if defined(GRAPHICS_API_OPENGL_43)
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
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_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
glLinkProgram(program);
@ -4166,7 +4253,7 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
else
{
// 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;
//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_IVEC3: glUniform3iv(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;
default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized");
// TODO: Support glUniform1uiv(), glUniform2uiv(), glUniform3uiv(), glUniform4uiv()
}
#endif
}
@ -4261,6 +4356,18 @@ void rlSetUniformMatrix(int locIndex, Matrix mat)
#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
void rlSetUniformSampler(int locIndex, unsigned int textureId)
{
@ -4340,12 +4447,14 @@ unsigned int rlLoadComputeShaderProgram(unsigned int shaderId)
else
{
// 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;
//glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);
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
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);
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);
#else
TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43");
#endif
return ssbo;
@ -4380,7 +4491,10 @@ void rlUnloadShaderBuffer(unsigned int ssboId)
{
#if defined(GRAPHICS_API_OPENGL_43)
glDeleteBuffers(1, &ssboId);
#else
TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43");
#endif
}
// Update SSBO buffer data
@ -4395,14 +4509,14 @@ void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSi
// Get SSBO buffer size
unsigned int rlGetShaderBufferSize(unsigned int id)
{
long long size = 0;
#if defined(GRAPHICS_API_OPENGL_43)
GLint64 size = 0;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
glGetInteger64v(GL_SHADER_STORAGE_BUFFER_SIZE, &size);
#endif
glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size);
return (size > 0)? (unsigned int)size : 0;
#else
return 0;
#endif
}
// 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);
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
}
@ -4518,7 +4634,7 @@ Matrix rlGetMatrixTransform(void)
}
// Get internal projection matrix for stereo render (selected eye)
RLAPI Matrix rlGetMatrixProjectionStereo(int eye)
Matrix rlGetMatrixProjectionStereo(int eye)
{
Matrix mat = rlMatrixIdentity();
#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)
RLAPI Matrix rlGetMatrixViewOffsetStereo(int eye)
Matrix rlGetMatrixViewOffsetStereo(int eye)
{
Matrix mat = rlMatrixIdentity();
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@ -4754,7 +4870,16 @@ static void rlLoadShaderDefault(void)
"out vec2 fragTexCoord; \n"
"out vec4 fragColor; \n"
#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"
"precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) (on some browsers)
"attribute vec3 vertexPosition; \n"
@ -4763,6 +4888,7 @@ static void rlLoadShaderDefault(void)
"varying vec2 fragTexCoord; \n"
"varying vec4 fragColor; \n"
#endif
"uniform mat4 mvp; \n"
"void main() \n"
"{ \n"
@ -4797,7 +4923,21 @@ static void rlLoadShaderDefault(void)
" finalColor = texelColor*colDiffuse*fragColor; \n"
"} \n";
#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"
"precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL)
"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);
// 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_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;
}
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,
// 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)
}
// 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)
func Begin(mode int32) {
cmode := C.int(mode)
@ -312,12 +329,27 @@ func DisableFramebuffer() {
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
func ActiveDrawBuffers(count int32) {
ccount := C.int(count)
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
func EnableColorBlend() {
C.rlEnableColorBlend()
@ -358,6 +390,11 @@ func DisableBackfaceCulling() {
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
func SetCullFace(mode int32) {
cmode := C.int(mode)
@ -592,7 +629,7 @@ func LoadTextureDepth(width, height int32, useRenderBuffer bool) {
}
// LoadFramebuffer - Load an empty framebuffer
func LoadFramebuffer(width int32, height int32) uint32 {
func LoadFramebuffer() uint32 {
return uint32(C.rlLoadFramebuffer())
}
@ -664,6 +701,23 @@ func GetLocationAttrib(shaderId uint32, attribName string) int32 {
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
func SetUniformSampler(locIndex int32, textureId uint32) {
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 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 rlSetClipPlanes func(float64, float64)
var rlGetCullDistanceNear func() float64
var rlGetCullDistanceFar func() float64
var rlBegin func(mode int32)
var rlEnd func()
var rlVertex2i func(x int32, y int32)
@ -49,7 +52,10 @@ var rlEnableShader func(id uint32)
var rlDisableShader func()
var rlEnableFramebuffer func(id uint32)
var rlDisableFramebuffer func()
var rlGetActiveFramebuffer func() uint32
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 rlDisableColorBlend func()
var rlEnableDepthTest func()
@ -58,6 +64,7 @@ var rlEnableDepthMask func()
var rlDisableDepthMask func()
var rlEnableBackfaceCulling func()
var rlDisableBackfaceCulling func()
var rlColorMask func(r, g, b, a bool)
var rlSetCullFace func(mode int32)
var rlEnableScissorTest func()
var rlDisableScissorTest func()
@ -98,7 +105,7 @@ var rlLoadVertexArray func() uint32
var rlUnloadVertexBuffer func(vboId uint32)
var rlSetVertexAttributeDivisor func(index uint32, divisor int32)
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 rlFramebufferComplete func(id uint32) bool
var rlUnloadFramebuffer func(id uint32)
@ -108,6 +115,9 @@ var rlLoadShaderProgram func(vShaderId uint32, fShaderId uint32) uint32
var rlUnloadShaderProgram func(id uint32)
var rlGetLocationUniform func(shaderId uint32, uniformName 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 rlLoadComputeShaderProgram func(shaderID uint32) uint32
var rlComputeShaderDispatch func(groupX uint32, groupY uint32, groupZ uint32)
@ -143,6 +153,9 @@ func initRlglPurego() {
purego.RegisterLibFunc(&rlFrustum, raylibDll, "rlFrustum")
purego.RegisterLibFunc(&rlOrtho, raylibDll, "rlOrtho")
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(&rlEnd, raylibDll, "rlEnd")
purego.RegisterLibFunc(&rlVertex2i, raylibDll, "rlVertex2i")
@ -172,7 +185,10 @@ func initRlglPurego() {
purego.RegisterLibFunc(&rlDisableShader, raylibDll, "rlDisableShader")
purego.RegisterLibFunc(&rlEnableFramebuffer, raylibDll, "rlEnableFramebuffer")
purego.RegisterLibFunc(&rlDisableFramebuffer, raylibDll, "rlDisableFramebuffer")
purego.RegisterLibFunc(&rlGetActiveFramebuffer, raylibDll, "rlGetActiveFramebuffer")
purego.RegisterLibFunc(&rlActiveDrawBuffers, raylibDll, "rlActiveDrawBuffers")
purego.RegisterLibFunc(&rlBlitFramebuffer, raylibDll, "rlBlitFramebuffer")
purego.RegisterLibFunc(&rlBindFramebuffer, raylibDll, "rlBindFramebuffer")
purego.RegisterLibFunc(&rlEnableColorBlend, raylibDll, "rlEnableColorBlend")
purego.RegisterLibFunc(&rlDisableColorBlend, raylibDll, "rlDisableColorBlend")
purego.RegisterLibFunc(&rlEnableDepthTest, raylibDll, "rlEnableDepthTest")
@ -181,6 +197,7 @@ func initRlglPurego() {
purego.RegisterLibFunc(&rlDisableDepthMask, raylibDll, "rlDisableDepthMask")
purego.RegisterLibFunc(&rlEnableBackfaceCulling, raylibDll, "rlEnableBackfaceCulling")
purego.RegisterLibFunc(&rlDisableBackfaceCulling, raylibDll, "rlDisableBackfaceCulling")
purego.RegisterLibFunc(&rlColorMask, raylibDll, "rlColorMask")
purego.RegisterLibFunc(&rlSetCullFace, raylibDll, "rlSetCullFace")
purego.RegisterLibFunc(&rlEnableScissorTest, raylibDll, "rlEnableScissorTest")
purego.RegisterLibFunc(&rlDisableScissorTest, raylibDll, "rlDisableScissorTest")
@ -231,6 +248,9 @@ func initRlglPurego() {
purego.RegisterLibFunc(&rlUnloadShaderProgram, raylibDll, "rlUnloadShaderProgram")
purego.RegisterLibFunc(&rlGetLocationUniform, raylibDll, "rlGetLocationUniform")
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(&rlLoadComputeShaderProgram, raylibDll, "rlLoadComputeShaderProgram")
purego.RegisterLibFunc(&rlComputeShaderDispatch, raylibDll, "rlComputeShaderDispatch")
@ -321,6 +341,21 @@ func Viewport(x int32, y int32, width int32, height int32) {
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)
func Begin(mode int32) {
rlBegin(mode)
@ -466,11 +501,26 @@ func DisableFramebuffer() {
rlDisableFramebuffer()
}
// GetActiveFramebuffer - Get the currently active render texture (fbo), 0 for default framebuffer
func GetActiveFramebuffer() uint32 {
return rlGetActiveFramebuffer()
}
// ActiveDrawBuffers - Activate multiple draw color buffers
func ActiveDrawBuffers(count int32) {
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
func EnableColorBlend() {
rlEnableColorBlend()
@ -511,6 +561,11 @@ func DisableBackfaceCulling() {
rlDisableBackfaceCulling()
}
// ColorMask - Color mask control
func ColorMask(r, g, b, a bool) {
rlColorMask(r, g, b, a)
}
// SetCullFace - Set face culling mode
func SetCullFace(mode int32) {
rlSetCullFace(mode)
@ -714,8 +769,8 @@ func LoadTextureDepth(width, height int32, useRenderBuffer bool) {
}
// LoadFramebuffer - Load an empty framebuffer
func LoadFramebuffer(width int32, height int32) uint32 {
return rlLoadFramebuffer(width, height)
func LoadFramebuffer() uint32 {
return rlLoadFramebuffer()
}
// FramebufferAttach - Attach texture/renderbuffer to a framebuffer
@ -763,6 +818,21 @@ func GetLocationAttrib(shaderId uint32, attribName string) int32 {
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
func SetUniformSampler(locIndex int32, textureId uint32) {
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
}
// IsModelReady - Check if a model is ready
func IsModelReady(model Model) bool {
// IsModelValid - Check if a model is valid (loaded in GPU, VAO/VBOs)
func IsModelValid(model Model) bool {
cmodel := model.cptr()
ret := C.IsModelReady(*cmodel)
ret := C.IsModelValid(*cmodel)
v := bool(ret)
return v
}
@ -331,6 +331,26 @@ func DrawModelWiresEx(model Model, position Vector3, rotationAxis Vector3, rotat
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)
func DrawBoundingBox(box BoundingBox, col color.RGBA) {
cbox := box.cptr()
@ -339,13 +359,13 @@ func DrawBoundingBox(box BoundingBox, col color.RGBA) {
}
// 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()
ctexture := texture.cptr()
ccenter := center.cptr()
csize := (C.float)(size)
cscale := (C.float)(scale)
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
@ -545,10 +565,10 @@ func LoadMaterialDefault() Material {
return v
}
// IsMaterialReady - Check if a material is ready
func IsMaterialReady(material Material) bool {
// IsMaterialValid - Check if a material is valid (shader assigned, map textures loaded in GPU)
func IsMaterialValid(material Material) bool {
cmaterial := material.cptr()
ret := C.IsMaterialReady(*cmaterial)
ret := C.IsMaterialValid(*cmaterial)
v := bool(ret)
return v
}
@ -585,7 +605,7 @@ func LoadModelAnimations(fileName string) []ModelAnimation {
return v
}
// UpdateModelAnimation - Update model animation pose
// UpdateModelAnimation - Update model animation pose (CPU)
func UpdateModelAnimation(model Model, anim ModelAnimation, frame int32) {
cmodel := model.cptr()
canim := anim.cptr()
@ -593,6 +613,14 @@ func UpdateModelAnimation(model Model, anim ModelAnimation, frame int32) {
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
func UnloadModelAnimation(anim ModelAnimation) {
canim := anim.cptr()

View file

@ -79,8 +79,8 @@
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
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 Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (white pixel loaded by rlgl)
static Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
@ -126,7 +126,7 @@ Rectangle GetShapesTextureRectangle(void)
// Draw a pixel
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)
@ -178,9 +178,8 @@ void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color colo
{
rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a);
// WARNING: Adding 0.5f offset to "center" point on selected pixel
rlVertex2f((float)startPosX + 0.5f, (float)startPosY + 0.5f);
rlVertex2f((float)endPosX + 0.5f, (float)endPosY + 0.5f);
rlVertex2f((float)startPosX, (float)startPosY);
rlVertex2f((float)endPosX, (float)endPosY);
rlEnd();
}
@ -189,14 +188,13 @@ void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
{
rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a);
// WARNING: Adding 0.5f offset to "center" point on selected pixel
rlVertex2f(startPos.x + 0.5f, startPos.y + 0.5f);
rlVertex2f(endPos.x + 0.5f, endPos.y + 0.5f);
rlVertex2f(startPos.x, startPos.y);
rlVertex2f(endPos.x, endPos.y);
rlEnd();
}
// 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
@ -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
if (((unsigned int)segments%2) == 1)
if ((((unsigned int)segments)%2) == 1)
{
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
// NOTE: Gradient goes from center (color1) to border (color2)
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer)
{
rlBegin(RL_TRIANGLES);
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);
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);
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);
}
rlEnd();
@ -763,22 +760,19 @@ void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color
}
// 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 color1, Color color2)
void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom)
{
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
// NOTE: Gradient goes from bottom (color1) to top (color2)
void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2)
void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right)
{
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
// NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise
void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight)
{
rlSetTexture(GetShapesTexture().id);
Rectangle shapeRect = GetShapesTextureRectangle();
@ -787,19 +781,19 @@ void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3,
rlNormal3f(0.0f, 0.0f, 1.0f);
// 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);
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);
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);
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);
rlVertex2f(rec.x + rec.width, rec.y);
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
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);
rlColor4ub(color.r, color.g, color.b, color.a);
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 + 1);
rlEnd();
//#endif
*/
}
// 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 (rec.width > rec.height) lineThick = rec.height/2;
else if (rec.width < rec.height) lineThick = rec.width/2;
if (rec.width >= rec.height) lineThick = rec.height/2;
else if (rec.width <= rec.height) lineThick = rec.width/2;
}
// 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
// NOTE: First vertex provided is the center, shared by all triangles
// 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)
{
@ -1416,7 +1436,7 @@ void DrawTriangleFan(Vector2 *points, int pointCount, Color color)
// Draw a triangle strip defined by points
// 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)
{
@ -1570,7 +1590,7 @@ void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, fl
//----------------------------------------------------------------------------------
// 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;
@ -1656,7 +1676,7 @@ void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color)
prevNormal = normal;
}
#else // !SUPPORT_SPLINE_MITTERS
#else // !SUPPORT_SPLINE_MITERS
Vector2 delta = { 0 };
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
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;
@ -1759,11 +1779,12 @@ void DrawSplineBasis(Vector2 *points, int pointCount, float thick, Color 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
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;
@ -1825,28 +1846,31 @@ void DrawSplineCatmullRom(Vector2 *points, int pointCount, float thick, Color co
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...]
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;
for (int i = 0; i < pointCount - 2; i++)
if (pointCount >= 3)
{
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...]
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;
for (int i = 0; i < pointCount - 3; i++)
if (pointCount >= 4)
{
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;
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;
}
@ -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
// 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;
@ -2233,9 +2259,10 @@ bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, floa
float dx = center2.x - center1.x; // X 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;
}
@ -2315,6 +2342,30 @@ bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshol
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
Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
{

View file

@ -17,6 +17,20 @@ func SetShapesTexture(texture Texture2D, source Rectangle) {
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
func DrawPixel(posX, posY int32, col color.RGBA) {
cposX := (C.int)(posX)
@ -108,13 +122,13 @@ func DrawCircleSectorLines(center Vector2, radius, startAngle, endAngle float32,
}
// 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)
ccenterY := (C.int)(centerY)
cradius := (C.float)(radius)
ccolor1 := colorCptr(col1)
ccolor2 := colorCptr(col2)
C.DrawCircleGradient(ccenterX, ccenterY, cradius, *ccolor1, *ccolor2)
cinner := colorCptr(inner)
couter := colorCptr(outer)
C.DrawCircleGradient(ccenterX, ccenterY, cradius, *cinner, *couter)
}
// 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
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)
cposY := (C.int)(posY)
cwidth := (C.int)(width)
cheight := (C.int)(height)
ccolor1 := colorCptr(col1)
ccolor2 := colorCptr(col2)
C.DrawRectangleGradientV(cposX, cposY, cwidth, cheight, *ccolor1, *ccolor2)
ctop := colorCptr(top)
cbottom := colorCptr(bottom)
C.DrawRectangleGradientV(cposX, cposY, cwidth, cheight, *ctop, *cbottom)
}
// 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)
cposY := (C.int)(posY)
cwidth := (C.int)(width)
cheight := (C.int)(height)
ccolor1 := colorCptr(col1)
ccolor2 := colorCptr(col2)
C.DrawRectangleGradientH(cposX, cposY, cwidth, cheight, *ccolor1, *ccolor2)
cleft := colorCptr(left)
cright := colorCptr(right)
C.DrawRectangleGradientH(cposX, cposY, cwidth, cheight, *cleft, *cright)
}
// 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()
ccolor1 := colorCptr(col1)
ccolor2 := colorCptr(col2)
ccolor3 := colorCptr(col3)
ccolor4 := colorCptr(col4)
C.DrawRectangleGradientEx(*crec, *ccolor1, *ccolor2, *ccolor3, *ccolor4)
ctopLeft := colorCptr(topLeft)
cbottomLeft := colorCptr(bottomLeft)
ctopRight := colorCptr(topRight)
cbottomRight := colorCptr(bottomRight)
C.DrawRectangleGradientEx(*crec, *ctopLeft, *cbottomLeft, *ctopRight, *cbottomRight)
}
// DrawRectangleLines - Draw rectangle outline
@ -279,8 +293,8 @@ func DrawRectangleRounded(rec Rectangle, roundness float32, segments int32, col
C.DrawRectangleRounded(*crec, croundness, csegments, *ccolor)
}
// DrawRectangleRoundedLines - Draw rectangle with rounded edges outline
func DrawRectangleRoundedLines(rec Rectangle, roundness float32, segments, lineThick float32, col color.RGBA) {
// DrawRectangleRoundedLines - Draw rectangle lines with rounded edges
func DrawRectangleRoundedLines(rec Rectangle, roundness float32, segments int32, col color.RGBA) {
crec := rec.cptr()
croundness := (C.float)(roundness)
csegments := (C.int)(segments)
@ -288,6 +302,16 @@ func DrawRectangleRoundedLines(rec Rectangle, roundness float32, segments, lineT
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
func DrawTriangle(v1, v2, v3 Vector2, col color.RGBA) {
cv1 := v1.cptr()
@ -537,6 +561,17 @@ func CheckCollisionCircleRec(center Vector2, radius float32, rec Rectangle) bool
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
func CheckCollisionPointRec(point Vector2, rec Rectangle) bool {
cpoint := point.cptr()

View file

@ -124,6 +124,7 @@
//----------------------------------------------------------------------------------
// Global variables
//----------------------------------------------------------------------------------
extern bool isGpuReady;
#if defined(SUPPORT_DEFAULT_FONT)
// Default font provided by raylib
// NOTE: Default font is loaded on InitWindow() and disposed on CloseWindow() [module: core]
@ -252,15 +253,15 @@ extern void LoadFontDefault(void)
counter++;
}
defaultFont.texture = LoadTextureFromImage(imFont);
if (isGpuReady) defaultFont.texture = LoadTextureFromImage(imFont);
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount
//------------------------------------------------------------------------------
// Allocate space for our characters info data
// NOTE: This memory must be freed at end! --> Done by CloseWindow()
defaultFont.glyphs = (GlyphInfo *)RL_MALLOC(defaultFont.glyphCount*sizeof(GlyphInfo));
defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.glyphCount*sizeof(Rectangle));
defaultFont.glyphs = (GlyphInfo *)RL_CALLOC(defaultFont.glyphCount, sizeof(GlyphInfo));
defaultFont.recs = (Rectangle *)RL_CALLOC(defaultFont.glyphCount, sizeof(Rectangle));
int currentLine = 0;
int currentPosX = charsDivisor;
@ -308,7 +309,7 @@ extern void LoadFontDefault(void)
extern void UnloadFontDefault(void)
{
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.recs);
}
@ -362,15 +363,14 @@ Font LoadFont(const char *fileName)
UnloadImage(image);
}
if (font.texture.id == 0)
if (isGpuReady)
{
TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName);
font = GetFontDefault();
}
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);
if (font.texture.id == 0) TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName);
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);
}
}
return font;
@ -394,7 +394,6 @@ Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepoi
UnloadFileData(fileData);
}
else font = GetFontDefault();
return font;
}
@ -492,7 +491,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
};
// 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.glyphPadding = 0;
@ -561,7 +560,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
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()
for (int i = 0; i < font.glyphCount; i++)
@ -582,17 +581,16 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
return font;
}
// Check if a font is ready
bool IsFontReady(Font font)
// Check if a font is valid (font data loaded)
// WARNING: GPU texture not checked
bool IsFontValid(Font font)
{
return ((font.texture.id > 0) && // Validate OpenGL id fot font texture atlas
(font.baseSize > 0) && // Validate font size
return ((font.baseSize > 0) && // Validate font size
(font.glyphCount > 0) && // Validate font contains some glyph
(font.recs != NULL) && // Validate font recs defining glyphs on texture atlas
(font.glyphs != NULL)); // Validate glyph data is loaded
// NOTE: Further validations could be done to verify if recs count and glyphs count
// match glyphCount and to verify that data contained is valid (glyphs values, metrics...)
// NOTE: Further validations could be done to verify if recs and glyphs contain valid data (glyphs values, metrics...)
}
// 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);
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
chars[i].image.width = chw;
chars[i].image.height = chh;
@ -951,7 +951,7 @@ void UnloadFont(Font font)
if (font.texture.id != GetFontDefault().texture.id)
{
UnloadFontData(font.glyphs, font.glyphCount);
UnloadTexture(font.texture);
if (isGpuReady) UnloadTexture(font.texture);
RL_FREE(font.recs);
TRACELOGD("FONT: Unloaded font data from RAM and VRAM");
@ -1035,7 +1035,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
// Save font recs data
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++)
{
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
byteCount += sprintf(txtData + byteCount, "// Font glyphs info data\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++)
{
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);
#endif
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)
byteCount += sprintf(txtData + byteCount, " UnloadImage(imFont); // Uncompressed data can be unloaded from memory\n\n");
#endif
@ -1282,7 +1282,8 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
{
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 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++;
int next = 0;
letter = GetCodepointNext(&text[i], &next);
int codepointByteCount = 0;
letter = GetCodepointNext(&text[i], &codepointByteCount);
index = GetGlyphIndex(font, letter);
i += next;
i += codepointByteCount;
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
@ -1472,8 +1473,7 @@ float TextToFloat(const char *text)
int i = 0;
for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0');
if (text[i++] != '.') value *= sign;
else
if (text[i++] == '.')
{
float divisor = 10.0f;
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)
@ -1577,7 +1577,7 @@ char *TextReplace(const char *text, const char *replace, const char *by)
byLen = TextLength(by);
// Count the number of replacements needed
insertPoint = (char*)text;
insertPoint = (char *)text;
for (count = 0; (temp = strstr(insertPoint, replace)); count++) insertPoint = temp + replaceLen;
// Allocate returning string and point temp to it
@ -1786,6 +1786,62 @@ const char *TextToPascal(const char *text)
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
// REQUIRES: memcpy()
// 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
int *temp = (int *)RL_REALLOC(codepoints, codepointCount*sizeof(int));
if (temp != NULL) codepoints = temp;
codepoints = (int *)RL_REALLOC(codepoints, codepointCount*sizeof(int));
*count = codepointCount;
@ -1875,7 +1930,8 @@ int GetCodepointCount(const char *text)
const char *CodepointToUTF8(int codepoint, int *utf8Size)
{
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)
{
@ -2208,7 +2264,7 @@ static Font LoadBMFont(const char *fileName)
RL_FREE(imFonts);
font.texture = LoadTextureFromImage(fullFont);
if (isGpuReady) font.texture = LoadTextureFromImage(fullFont);
// Fill font characters info data
font.baseSize = fontSize;
@ -2240,13 +2296,17 @@ static Font LoadBMFont(const char *fileName)
// Fill character image data from full font data
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);
UnloadFileText(fileText);
if (font.texture.id == 0)
if (isGpuReady && (font.texture.id == 0))
{
UnloadFont(font);
font = GetFontDefault();
@ -2285,7 +2345,7 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
int readBytes = 0; // Data bytes read (line)
int readVars = 0; // Variables filled by sscanf()
const char *fileText = (const char*)fileData;
const char *fileText = (const char *)fileData;
const char *fileTextPtr = fileText;
bool fontMalformed = false; // Is the font malformed

View file

@ -92,10 +92,10 @@ func LoadFontFromMemory(fileType string, fileData []byte, fontSize int32, codepo
return v
}
// IsFontReady - Check if a font is ready
func IsFontReady(font Font) bool {
// IsFontValid - Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
func IsFontValid(font Font) bool {
cfont := font.cptr()
ret := C.IsFontReady(*cfont)
ret := C.IsFontValid(*cfont)
v := bool(ret)
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
}
// 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)
func LoadImageAnim(fileName string, frames *int32) *Image {
cfileName := C.CString(fileName)
@ -124,6 +113,18 @@ func LoadImageAnim(fileName string, frames *int32) *Image {
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"
func LoadImageFromMemory(fileType string, fileData []byte, dataSize int32) *Image {
cfileType := C.CString(fileType)
@ -150,10 +151,10 @@ func LoadImageFromScreen() *Image {
return v
}
// IsImageReady - Check if an image is ready
func IsImageReady(image *Image) bool {
// IsImageValid - Check if an image is valid (data and parameters)
func IsImageValid(image *Image) bool {
cimage := image.cptr()
ret := C.IsImageReady(*cimage)
ret := C.IsImageValid(*cimage)
v := bool(ret)
return v
}
@ -199,10 +200,10 @@ func UnloadImage(image *Image) {
C.UnloadImage(*cimage)
}
// IsTextureReady - Check if a texture is ready
func IsTextureReady(texture Texture2D) bool {
// IsTextureValid - Check if a texture is valid (loaded in GPU)
func IsTextureValid(texture Texture2D) bool {
ctexture := texture.cptr()
ret := C.IsTextureReady(*ctexture)
ret := C.IsTextureValid(*ctexture)
v := bool(ret)
return v
}
@ -213,10 +214,10 @@ func UnloadTexture(texture Texture2D) {
C.UnloadTexture(*ctexture)
}
// IsRenderTextureReady - Check if a render texture is ready
func IsRenderTextureReady(target RenderTexture2D) bool {
// IsRenderTextureValid - Check if a render texture is valid (loaded in GPU)
func IsRenderTextureValid(target RenderTexture2D) bool {
ctarget := target.cptr()
ret := C.IsRenderTextureReady(*ctarget)
ret := C.IsRenderTextureValid(*ctarget)
v := bool(ret)
return v
}
@ -291,6 +292,15 @@ func ImageFromImage(image Image, rec Rectangle) Image {
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)
func ImageText(text string, fontSize int32, col color.RGBA) *Image {
ctext := C.CString(text)
@ -371,6 +381,13 @@ func ImageBlurGaussian(image *Image, blurSize int32) {
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)
func ImageResize(image *Image, newWidth, newHeight int32) {
cimage := image.cptr()
@ -534,6 +551,16 @@ func ImageDrawLineV(dst *Image, start, end Vector2, col color.RGBA) {
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
func ImageDrawCircle(dst *Image, centerX, centerY, radius int32, col color.RGBA) {
cdst := dst.cptr()
@ -618,6 +645,56 @@ func ImageDrawRectangleLines(dst *Image, rec Rectangle, thick int, col color.RGB
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
func ImageDrawRectangleRec(dst *Image, rec Rectangle, col color.RGBA) {
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 SetSaveFileTextCallback(SaveFileTextCallback callback) { saveFileText = callback; } // Set custom file text saver
#if defined(PLATFORM_ANDROID)
static AAssetManager *assetManager = NULL; // Android assets manager pointer
static const char *internalDataPath = NULL; // Android internal data path