Update C sources
This commit is contained in:
parent
e08c4cd054
commit
3327fcaf9f
22 changed files with 14167 additions and 10920 deletions
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2018-2024 Ahmad Fatoum & Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2018-2025 Ahmad Fatoum & Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -71,6 +71,30 @@
|
|||
// Enabling this flag allows manual control of the frame processes, use at your own risk
|
||||
//#define SUPPORT_CUSTOM_FRAME_CONTROL 1
|
||||
|
||||
// Support for clipboard image loading
|
||||
// NOTE: Only working on SDL3, GLFW (Windows) and RGFW (Windows)
|
||||
#define SUPPORT_CLIPBOARD_IMAGE 1
|
||||
|
||||
// NOTE: Clipboard image loading requires support for some image file formats
|
||||
// TODO: Those defines should probably be removed from here, I prefer to let the user manage them
|
||||
#if defined(SUPPORT_CLIPBOARD_IMAGE)
|
||||
#ifndef SUPPORT_MODULE_RTEXTURES
|
||||
#define SUPPORT_MODULE_RTEXTURES 1
|
||||
#endif
|
||||
#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
|
||||
#endif
|
||||
|
||||
|
||||
// rcore: Configuration values
|
||||
//------------------------------------------------------------------------------------
|
||||
|
@ -80,7 +104,7 @@
|
|||
#define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
|
||||
#define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported
|
||||
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported
|
||||
#define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
|
||||
#define MAX_GAMEPAD_AXES 8 // Maximum number of axes supported (per gamepad)
|
||||
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
||||
#define MAX_GAMEPAD_VIBRATION_TIME 2.0f // Maximum vibration time in seconds
|
||||
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
|
||||
|
@ -112,8 +136,8 @@
|
|||
|
||||
#define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
|
||||
|
||||
#define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance
|
||||
#define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
|
||||
#define RL_CULL_DISTANCE_NEAR 0.001 // Default projection matrix near cull distance
|
||||
#define RL_CULL_DISTANCE_FAR 10000.0 // Default projection matrix far cull distance
|
||||
|
||||
// Default shader vertex attribute locations
|
||||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
|
||||
|
@ -127,6 +151,8 @@
|
|||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
|
||||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
|
||||
#endif
|
||||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX 9
|
||||
|
||||
|
||||
// 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
|
||||
|
@ -273,31 +299,4 @@
|
|||
//------------------------------------------------------------------------------------
|
||||
#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
|
||||
|
|
15670
raylib/external/RGFW.h
vendored
15670
raylib/external/RGFW.h
vendored
File diff suppressed because it is too large
Load diff
1809
raylib/external/miniaudio.h
vendored
1809
raylib/external/miniaudio.h
vendored
File diff suppressed because it is too large
Load diff
9
raylib/external/sinfl.h
vendored
9
raylib/external/sinfl.h
vendored
|
@ -171,10 +171,11 @@ extern int zsinflate(void *out, int cap, const void *in, int size);
|
|||
|
||||
static int
|
||||
sinfl_bsr(unsigned n) {
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
_BitScanReverse(&n, n);
|
||||
return n;
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#ifdef _MSC_VER
|
||||
unsigned long uln = 0;
|
||||
_BitScanReverse(&uln, n);
|
||||
return (int)(uln);
|
||||
#else // defined(__GNUC__) || defined(__clang__) || defined(__TINYC__)
|
||||
return 31 - __builtin_clz(n);
|
||||
#endif
|
||||
}
|
||||
|
|
8
raylib/external/stb_truetype.h
vendored
8
raylib/external/stb_truetype.h
vendored
|
@ -1863,11 +1863,11 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
|||
stbtt_vertex* v = &comp_verts[i];
|
||||
stbtt_vertex_type x,y;
|
||||
x=v->x; y=v->y;
|
||||
v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
|
||||
v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
|
||||
v->x = (stbtt_vertex_type)(mtx[0]*x + mtx[2]*y + mtx[4]*m);
|
||||
v->y = (stbtt_vertex_type)(mtx[1]*x + mtx[3]*y + mtx[5]*n);
|
||||
x=v->cx; y=v->cy;
|
||||
v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
|
||||
v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
|
||||
v->cx = (stbtt_vertex_type)(mtx[0]*x + mtx[2]*y + mtx[4]*m);
|
||||
v->cy = (stbtt_vertex_type)(mtx[1]*x + mtx[3]*y + mtx[5]*n);
|
||||
}
|
||||
// Append vertices.
|
||||
tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) and contributors
|
||||
*
|
||||
* 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.
|
||||
|
@ -70,6 +70,16 @@ typedef struct {
|
|||
EGLConfig config; // Graphic config
|
||||
} PlatformData;
|
||||
|
||||
typedef struct {
|
||||
// Store data for both Hover and Touch events
|
||||
// Used to ignore Hover events which are interpreted as Touch events
|
||||
int32_t pointCount; // Number of touch points active
|
||||
int32_t pointId[MAX_TOUCH_POINTS]; // Point identifiers
|
||||
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
|
||||
|
||||
int32_t hoverPoints[MAX_TOUCH_POINTS]; // Hover Points
|
||||
} TouchRaw;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -246,6 +256,8 @@ static const KeyboardKey mapKeycode[KEYCODE_MAP_SIZE] = {
|
|||
KEY_KP_EQUAL // AKEYCODE_NUMPAD_EQUALS
|
||||
};
|
||||
|
||||
static TouchRaw touchRaw = { 0 };
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Internal Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -339,7 +351,7 @@ void MinimizeWindow(void)
|
|||
TRACELOG(LOG_WARNING, "MinimizeWindow() not available on target platform");
|
||||
}
|
||||
|
||||
// Set window state: not minimized/maximized
|
||||
// Restore window from being minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
||||
|
@ -433,7 +445,7 @@ int GetMonitorCount(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Get number of monitors
|
||||
// Get current monitor where window is placed
|
||||
int GetCurrentMonitor(void)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GetCurrentMonitor() not implemented on target platform");
|
||||
|
@ -462,17 +474,21 @@ int GetMonitorHeight(int monitor)
|
|||
}
|
||||
|
||||
// Get selected monitor physical width in millimetres
|
||||
// NOTE: It seems to return a slightly underestimated value on some devices
|
||||
int GetMonitorPhysicalWidth(int monitor)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GetMonitorPhysicalWidth() not implemented on target platform");
|
||||
return 0;
|
||||
int widthPixels = ANativeWindow_getWidth(platform.app->window);
|
||||
float dpi = AConfiguration_getDensity(platform.app->config);
|
||||
return (widthPixels/dpi)*25.4f;
|
||||
}
|
||||
|
||||
// Get selected monitor physical height in millimetres
|
||||
// NOTE: It seems to return a slightly underestimated value on some devices
|
||||
int GetMonitorPhysicalHeight(int monitor)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GetMonitorPhysicalHeight() not implemented on target platform");
|
||||
return 0;
|
||||
int heightPixels = ANativeWindow_getHeight(platform.app->window);
|
||||
float dpi = AConfiguration_getDensity(platform.app->config);
|
||||
return (heightPixels/dpi)*25.4f;
|
||||
}
|
||||
|
||||
// Get selected monitor refresh rate
|
||||
|
@ -499,8 +515,9 @@ Vector2 GetWindowPosition(void)
|
|||
// Get window scale DPI factor for current monitor
|
||||
Vector2 GetWindowScaleDPI(void)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform");
|
||||
return (Vector2){ 1.0f, 1.0f };
|
||||
int density = AConfiguration_getDensity(platform.app->config);
|
||||
float scale = (float)density/160;
|
||||
return (Vector2){ scale, scale };
|
||||
}
|
||||
|
||||
// Set clipboard text content
|
||||
|
@ -629,7 +646,7 @@ int SetGamepadMappings(const char *mappings)
|
|||
// Set gamepad vibration
|
||||
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform");
|
||||
TRACELOG(LOG_WARNING, "SetGamepadVibration() not implemented on target platform");
|
||||
}
|
||||
|
||||
// Set mouse position XY
|
||||
|
@ -701,7 +718,7 @@ void PollInputEvents(void)
|
|||
|
||||
// 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_pollOnce(platform.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT)
|
||||
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);
|
||||
|
@ -788,7 +805,7 @@ int InitPlatform(void)
|
|||
while (!CORE.Window.ready)
|
||||
{
|
||||
// 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)
|
||||
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);
|
||||
|
@ -798,6 +815,8 @@ int InitPlatform(void)
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) touchRaw.hoverPoints[i] = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -850,22 +869,20 @@ static int InitGraphicsDevice(void)
|
|||
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4");
|
||||
}
|
||||
|
||||
const EGLint framebufferAttribs[] =
|
||||
{
|
||||
EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support
|
||||
const EGLint framebufferAttribs[] = {
|
||||
EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support
|
||||
EGL_RED_SIZE, 8, // RED color bit depth (alternative: 5)
|
||||
EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6)
|
||||
EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5)
|
||||
//EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI)
|
||||
EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!)
|
||||
EGL_DEPTH_SIZE, 24, // Depth buffer size (Required to use Depth testing!)
|
||||
//EGL_STENCIL_SIZE, 8, // Stencil buffer size
|
||||
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
|
||||
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
|
||||
EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs)
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
const EGLint contextAttribs[] =
|
||||
{
|
||||
const EGLint contextAttribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
|
@ -1228,7 +1245,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|||
return 1; // Handled gamepad button
|
||||
}
|
||||
|
||||
KeyboardKey key = (keycode > 0 && keycode < KEYCODE_MAP_SIZE)? mapKeycode[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
|
||||
|
@ -1268,25 +1285,85 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|||
}
|
||||
|
||||
// Register touch points count
|
||||
CORE.Input.Touch.pointCount = AMotionEvent_getPointerCount(event);
|
||||
touchRaw.pointCount = AMotionEvent_getPointerCount(event);
|
||||
|
||||
for (int i = 0; (i < CORE.Input.Touch.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||
for (int i = 0; (i < touchRaw.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||
{
|
||||
// Register touch points id
|
||||
CORE.Input.Touch.pointId[i] = AMotionEvent_getPointerId(event, i);
|
||||
touchRaw.pointId[i] = AMotionEvent_getPointerId(event, i);
|
||||
|
||||
// Register touch points position
|
||||
CORE.Input.Touch.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) };
|
||||
touchRaw.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;
|
||||
touchRaw.position[i].x = touchRaw.position[i].x*widthRatio - (float)CORE.Window.renderOffset.x/2;
|
||||
touchRaw.position[i].y = touchRaw.position[i].y*heightRatio - (float)CORE.Window.renderOffset.y/2;
|
||||
}
|
||||
|
||||
int32_t action = AMotionEvent_getAction(event);
|
||||
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
||||
int32_t pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
|
||||
if (flags == AMOTION_EVENT_ACTION_HOVER_ENTER)
|
||||
{
|
||||
// The new pointer is hover
|
||||
// So add it to hoverPoints
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++)
|
||||
{
|
||||
if (touchRaw.hoverPoints[i] == -1)
|
||||
{
|
||||
touchRaw.hoverPoints[i] = touchRaw.pointId[pointerIndex];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags == AMOTION_EVENT_ACTION_POINTER_UP) || (flags == AMOTION_EVENT_ACTION_UP) || (flags == AMOTION_EVENT_ACTION_HOVER_EXIT))
|
||||
{
|
||||
// One of the touchpoints is released, remove it from touch point arrays
|
||||
if (flags == AMOTION_EVENT_ACTION_HOVER_EXIT)
|
||||
{
|
||||
// If the touchPoint is hover, remove it from hoverPoints
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++)
|
||||
{
|
||||
if (touchRaw.hoverPoints[i] == touchRaw.pointId[pointerIndex])
|
||||
{
|
||||
touchRaw.hoverPoints[i] = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = pointerIndex; (i < touchRaw.pointCount - 1) && (i < MAX_TOUCH_POINTS - 1); i++)
|
||||
{
|
||||
touchRaw.pointId[i] = touchRaw.pointId[i+1];
|
||||
touchRaw.position[i] = touchRaw.position[i+1];
|
||||
}
|
||||
touchRaw.pointCount--;
|
||||
}
|
||||
|
||||
int pointCount = 0;
|
||||
for (int i = 0; (i < touchRaw.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||
{
|
||||
// If the touchPoint is hover, Ignore it
|
||||
bool hover = false;
|
||||
for (int j = 0; j < MAX_TOUCH_POINTS; j++)
|
||||
{
|
||||
// Check if the touchPoint is in hoverPointers
|
||||
if (touchRaw.hoverPoints[j] == touchRaw.pointId[i])
|
||||
{
|
||||
hover = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hover) continue;
|
||||
|
||||
CORE.Input.Touch.pointId[pointCount] = touchRaw.pointId[i];
|
||||
CORE.Input.Touch.position[pointCount] = touchRaw.position[i];
|
||||
pointCount++;
|
||||
}
|
||||
CORE.Input.Touch.pointCount = pointCount;
|
||||
|
||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
||||
GestureEvent gestureEvent = { 0 };
|
||||
|
@ -1311,20 +1388,6 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|||
ProcessGestureEvent(gestureEvent);
|
||||
#endif
|
||||
|
||||
int32_t pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
|
||||
if (flags == AMOTION_EVENT_ACTION_POINTER_UP || flags == AMOTION_EVENT_ACTION_UP)
|
||||
{
|
||||
// One of the touchpoints is released, remove it from touch point arrays
|
||||
for (int i = pointerIndex; (i < CORE.Input.Touch.pointCount - 1) && (i < MAX_TOUCH_POINTS); i++)
|
||||
{
|
||||
CORE.Input.Touch.pointId[i] = CORE.Input.Touch.pointId[i+1];
|
||||
CORE.Input.Touch.position[i] = CORE.Input.Touch.position[i+1];
|
||||
}
|
||||
|
||||
CORE.Input.Touch.pointCount--;
|
||||
}
|
||||
|
||||
// When all touchpoints are tapped and released really quickly, this event is generated
|
||||
if (flags == AMOTION_EVENT_ACTION_CANCEL) CORE.Input.Touch.pointCount = 0;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**********************************************************************************************
|
||||
*
|
||||
* rcore_desktop - Functions to manage window, graphics device and inputs
|
||||
* rcore_desktop_glfw - Functions to manage window, graphics device and inputs
|
||||
*
|
||||
* PLATFORM: DESKTOP: GLFW
|
||||
* - Windows (Win32, Win64)
|
||||
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) and contributors
|
||||
*
|
||||
* 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.
|
||||
|
@ -86,6 +86,8 @@
|
|||
#include "GLFW/glfw3native.h" // Required for: glfwGetCocoaWindow()
|
||||
#endif
|
||||
|
||||
#include <stddef.h> // Required for: size_t
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -127,6 +129,11 @@ static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffs
|
|||
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
|
||||
static void JoystickCallback(int jid, int event); // GLFW3 Joystick Connected/Disconnected Callback
|
||||
|
||||
// Wrappers used by glfwInitAllocator
|
||||
static void *AllocateWrapper(size_t size, void *user); // GLFW3 GLFWallocatefun, wrapps around RL_MALLOC macro
|
||||
static void *ReallocateWrapper(void *block, size_t size, void *user); // GLFW3 GLFWreallocatefun, wrapps around RL_MALLOC macro
|
||||
static void DeallocateWrapper(void *block, void *user); // GLFW3 GLFWdeallocatefun, wraps around RL_FREE macro
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -223,11 +230,9 @@ void ToggleBorderlessWindowed(void)
|
|||
if (!wasOnFullscreen) CORE.Window.previousPosition = CORE.Window.position;
|
||||
CORE.Window.previousScreen = CORE.Window.screen;
|
||||
|
||||
// Set undecorated and topmost modes and flags
|
||||
// Set undecorated flag
|
||||
glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_FALSE);
|
||||
CORE.Window.flags |= FLAG_WINDOW_UNDECORATED;
|
||||
glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_TRUE);
|
||||
CORE.Window.flags |= FLAG_WINDOW_TOPMOST;
|
||||
|
||||
// Get monitor position and size
|
||||
int monitorPosX = 0;
|
||||
|
@ -247,9 +252,7 @@ void ToggleBorderlessWindowed(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Remove topmost and undecorated modes and flags
|
||||
glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_FALSE);
|
||||
CORE.Window.flags &= ~FLAG_WINDOW_TOPMOST;
|
||||
// Remove undecorated flag
|
||||
glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_TRUE);
|
||||
CORE.Window.flags &= ~FLAG_WINDOW_UNDECORATED;
|
||||
|
||||
|
@ -289,7 +292,7 @@ void MinimizeWindow(void)
|
|||
glfwIconifyWindow(platform.handle);
|
||||
}
|
||||
|
||||
// Set window state: not minimized/maximized
|
||||
// Restore window from being minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
|
||||
|
@ -304,6 +307,8 @@ void RestoreWindow(void)
|
|||
// Set window configuration state using flags
|
||||
void SetWindowState(unsigned int flags)
|
||||
{
|
||||
if (!CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetWindowState does nothing before window initialization, Use \"SetConfigFlags\" instead");
|
||||
|
||||
// Check previous state and requested state to apply required changes
|
||||
// NOTE: In most cases the functions already change the flags internally
|
||||
|
||||
|
@ -322,7 +327,7 @@ void SetWindowState(unsigned int flags)
|
|||
}
|
||||
|
||||
// State change: FLAG_FULLSCREEN_MODE
|
||||
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE))
|
||||
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE) && ((flags & FLAG_FULLSCREEN_MODE) > 0))
|
||||
{
|
||||
ToggleFullscreen(); // NOTE: Window state flag updated inside function
|
||||
}
|
||||
|
@ -571,7 +576,7 @@ void SetWindowIcons(Image *images, int count)
|
|||
else
|
||||
{
|
||||
int valid = 0;
|
||||
GLFWimage *icons = RL_CALLOC(count, sizeof(GLFWimage));
|
||||
GLFWimage *icons = (GLFWimage *)RL_CALLOC(count, sizeof(GLFWimage));
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
|
@ -733,7 +738,7 @@ int GetMonitorCount(void)
|
|||
return monitorCount;
|
||||
}
|
||||
|
||||
// Get number of monitors
|
||||
// Get current monitor where window is placed
|
||||
int GetCurrentMonitor(void)
|
||||
{
|
||||
int index = 0;
|
||||
|
@ -967,32 +972,29 @@ const char *GetClipboardText(void)
|
|||
return glfwGetClipboardString(platform.handle);
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_CLIPBOARD_IMAGE)
|
||||
// Get clipboard image
|
||||
Image GetClipboardImage(void)
|
||||
{
|
||||
Image image = {0};
|
||||
Image image = { 0 };
|
||||
|
||||
#if defined(SUPPORT_CLIPBOARD_IMAGE)
|
||||
#if defined(_WIN32)
|
||||
unsigned long long int dataSize = 0;
|
||||
void* fileData = NULL;
|
||||
void *fileData = NULL;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
#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);
|
||||
}
|
||||
if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data.");
|
||||
else image = LoadImageFromMemory(".bmp", fileData, (int)dataSize);
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform");
|
||||
#endif
|
||||
#endif // SUPPORT_CLIPBOARD_IMAGE
|
||||
|
||||
return image;
|
||||
}
|
||||
#endif // SUPPORT_CLIPBOARD_IMAGE
|
||||
|
||||
// Show mouse cursor
|
||||
void ShowCursor(void)
|
||||
|
@ -1024,6 +1026,9 @@ void EnableCursor(void)
|
|||
// Disables cursor (lock cursor)
|
||||
void DisableCursor(void)
|
||||
{
|
||||
// Reset mouse position within the window area before disabling cursor
|
||||
SetMousePosition(CORE.Window.screen.width, CORE.Window.screen.height);
|
||||
|
||||
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Set cursor position in the middle
|
||||
|
@ -1091,7 +1096,7 @@ int SetGamepadMappings(const char *mappings)
|
|||
// Set gamepad vibration
|
||||
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GamepadSetVibration() not available on target platform");
|
||||
TRACELOG(LOG_WARNING, "SetGamepadVibration() not available on target platform");
|
||||
}
|
||||
|
||||
// Set mouse position XY
|
||||
|
@ -1233,7 +1238,7 @@ void PollInputEvents(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Get current axis state
|
||||
// Get current state of axes
|
||||
const float *axes = state.axes;
|
||||
|
||||
for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1); k++)
|
||||
|
@ -1241,9 +1246,19 @@ void PollInputEvents(void)
|
|||
CORE.Input.Gamepad.axisState[i][k] = axes[k];
|
||||
}
|
||||
|
||||
// Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather axis)
|
||||
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f);
|
||||
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f);
|
||||
// Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather as axes)
|
||||
if (CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f)
|
||||
{
|
||||
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = 1;
|
||||
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_LEFT_TRIGGER_2;
|
||||
}
|
||||
else CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = 0;
|
||||
if (CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f)
|
||||
{
|
||||
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = 1;
|
||||
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
|
||||
}
|
||||
else CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = 0;
|
||||
|
||||
CORE.Input.Gamepad.axisCount[i] = GLFW_GAMEPAD_AXIS_LAST + 1;
|
||||
}
|
||||
|
@ -1251,12 +1266,13 @@ void PollInputEvents(void)
|
|||
|
||||
CORE.Window.resizedLastFrame = false;
|
||||
|
||||
if (CORE.Window.eventWaiting) glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
|
||||
if ((CORE.Window.eventWaiting) || (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)))
|
||||
{
|
||||
glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
|
||||
CORE.Time.previous = GetTime();
|
||||
}
|
||||
else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) -> Update keys state
|
||||
|
||||
// While window minimized, stop loop execution
|
||||
while (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)) glfwWaitEvents();
|
||||
|
||||
CORE.Window.shouldClose = glfwWindowShouldClose(platform.handle);
|
||||
|
||||
// Reset close status for next frame
|
||||
|
@ -1280,21 +1296,39 @@ static void SetDimensionsFromMonitor(GLFWmonitor *monitor)
|
|||
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;
|
||||
}
|
||||
|
||||
// Function wrappers around RL_*alloc macros, used by glfwInitAllocator() inside of InitPlatform()
|
||||
// We need to provide these because GLFWallocator expects function pointers with specific signatures.
|
||||
// Similar wrappers exist in utils.c but we cannot reuse them here due to declaration mismatch.
|
||||
// https://www.glfw.org/docs/latest/intro_guide.html#init_allocator
|
||||
static void *AllocateWrapper(size_t size, void *user)
|
||||
{
|
||||
(void)user;
|
||||
return RL_MALLOC(size);
|
||||
}
|
||||
static void *ReallocateWrapper(void *block, size_t size, void *user)
|
||||
{
|
||||
(void)user;
|
||||
return RL_REALLOC(block, size);
|
||||
}
|
||||
static void DeallocateWrapper(void *block, void *user)
|
||||
{
|
||||
(void)user;
|
||||
RL_FREE(block);
|
||||
}
|
||||
|
||||
// Initialize platform: graphics, inputs and more
|
||||
int InitPlatform(void)
|
||||
{
|
||||
glfwSetErrorCallback(ErrorCallback);
|
||||
/*
|
||||
// TODO: Setup GLFW custom allocators to match raylib ones
|
||||
|
||||
const GLFWallocator allocator = {
|
||||
.allocate = MemAlloc,
|
||||
.deallocate = MemFree,
|
||||
.reallocate = MemRealloc,
|
||||
.user = NULL
|
||||
.allocate = AllocateWrapper,
|
||||
.deallocate = DeallocateWrapper,
|
||||
.reallocate = ReallocateWrapper,
|
||||
.user = NULL, // RL_*ALLOC macros are not capable of handling user-provided data
|
||||
};
|
||||
|
||||
glfwInitAllocator(&allocator);
|
||||
*/
|
||||
|
||||
#if defined(__APPLE__)
|
||||
glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE);
|
||||
|
@ -1348,6 +1382,12 @@ int InitPlatform(void)
|
|||
if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer
|
||||
else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); // Opaque framebuffer
|
||||
|
||||
// HACK: Most of this was written before GLFW_SCALE_FRAMEBUFFER existed and
|
||||
// was enabled by default. Disabling it gets back the old behavior. A
|
||||
// complete fix will require removing a lot of CORE.Window.render
|
||||
// manipulation code.
|
||||
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_FALSE);
|
||||
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
|
||||
{
|
||||
// Resize window content area based on the monitor content scale.
|
||||
|
@ -1355,7 +1395,7 @@ int InitPlatform(void)
|
|||
// On platforms like macOS the resolution of the framebuffer is changed independently of the window size.
|
||||
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); // Scale content area based on the monitor content scale where window is placed on
|
||||
#if defined(__APPLE__)
|
||||
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
|
||||
#endif
|
||||
}
|
||||
else glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);
|
||||
|
@ -1490,6 +1530,12 @@ int InitPlatform(void)
|
|||
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
||||
|
||||
platform.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, (CORE.Window.title != 0)? CORE.Window.title : " ", monitor, NULL);
|
||||
if (!platform.handle)
|
||||
{
|
||||
glfwTerminate();
|
||||
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// NOTE: Full-screen change, not working properly...
|
||||
//glfwSetWindowMonitor(platform.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||
|
@ -1504,6 +1550,12 @@ int InitPlatform(void)
|
|||
int creationHeight = CORE.Window.screen.height != 0 ? CORE.Window.screen.height : 1;
|
||||
|
||||
platform.handle = glfwCreateWindow(creationWidth, creationHeight, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
|
||||
if (!platform.handle)
|
||||
{
|
||||
glfwTerminate();
|
||||
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// After the window was created, determine the monitor that the window manager assigned.
|
||||
// Derive display sizes, and, if possible, window size in case it was zero at beginning.
|
||||
|
@ -1527,18 +1579,8 @@ int InitPlatform(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (platform.handle)
|
||||
{
|
||||
CORE.Window.render.width = CORE.Window.screen.width;
|
||||
CORE.Window.render.height = CORE.Window.screen.height;
|
||||
}
|
||||
}
|
||||
|
||||
if (!platform.handle)
|
||||
{
|
||||
glfwTerminate();
|
||||
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
||||
return -1;
|
||||
CORE.Window.render.width = CORE.Window.screen.width;
|
||||
CORE.Window.render.height = CORE.Window.screen.height;
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(platform.handle);
|
||||
|
@ -1567,7 +1609,7 @@ int InitPlatform(void)
|
|||
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
|
||||
{
|
||||
// NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling.
|
||||
// Framebuffer scaling should be activated with: glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
|
||||
// Framebuffer scaling should be activated with: glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
|
||||
#if !defined(__APPLE__)
|
||||
glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);
|
||||
|
||||
|
@ -1655,7 +1697,9 @@ int InitPlatform(void)
|
|||
// Retrieve gamepad names
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
if (glfwJoystickPresent(i)) strcpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i));
|
||||
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
|
||||
// we can get a not-NULL terminated string, so, we only copy up to (MAX_GAMEPAD_NAME_LENGTH - 1)
|
||||
if (glfwJoystickPresent(i)) strncpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
@ -1708,9 +1752,13 @@ static void ErrorCallback(int error, const char *description)
|
|||
}
|
||||
|
||||
// GLFW3 WindowSize Callback, runs when window is resizedLastFrame
|
||||
// NOTE: Window resizing not allowed by default
|
||||
// NOTE: Window resizing not enabled by default, use SetConfigFlags()
|
||||
static void WindowSizeCallback(GLFWwindow *window, int width, int height)
|
||||
{
|
||||
// WARNING: On window minimization, callback is called,
|
||||
// but we don't want to change internal screen values, it breaks things
|
||||
if ((width == 0) || (height == 0)) return;
|
||||
|
||||
// Reset viewport and projection matrix for new size
|
||||
SetupViewport(width, height);
|
||||
|
||||
|
@ -1720,12 +1768,22 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
|
|||
|
||||
if (IsWindowFullscreen()) return;
|
||||
|
||||
// Set current screen size
|
||||
// if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
|
||||
if (IsWindowState(FLAG_WINDOW_HIGHDPI))
|
||||
{
|
||||
width = (int)(width/GetWindowScaleDPI().x);
|
||||
height = (int)(height/GetWindowScaleDPI().y);
|
||||
}
|
||||
|
||||
// Set render size
|
||||
CORE.Window.render.width = width;
|
||||
CORE.Window.render.height = height;
|
||||
|
||||
// Set current screen size
|
||||
CORE.Window.screen.width = width;
|
||||
CORE.Window.screen.height = height;
|
||||
|
||||
// NOTE: Postprocessing texture is not scaled to new size
|
||||
// WARNING: If using a render texture, it is not scaled to new size
|
||||
}
|
||||
static void WindowPosCallback(GLFWwindow* window, int x, int y)
|
||||
{
|
||||
|
@ -1918,11 +1976,14 @@ static void JoystickCallback(int jid, int event)
|
|||
{
|
||||
if (event == GLFW_CONNECTED)
|
||||
{
|
||||
strcpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid));
|
||||
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
|
||||
// we can get a not-NULL terminated string, so, we clean destination and only copy up to -1
|
||||
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
|
||||
strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||
}
|
||||
else if (event == GLFW_DISCONNECTED)
|
||||
{
|
||||
memset(CORE.Input.Gamepad.name[jid], 0, 64);
|
||||
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,13 +23,13 @@
|
|||
* Custom flag for rcore on target platform -not used-
|
||||
*
|
||||
* DEPENDENCIES:
|
||||
* - SDL 2 or SLD 3 (main library): Windowing and inputs management
|
||||
* - SDL 2 or SDL 3 (main library): Windowing and inputs management
|
||||
* - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs)
|
||||
*
|
||||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) and contributors
|
||||
*
|
||||
* 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.
|
||||
|
@ -68,13 +68,12 @@
|
|||
#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))
|
||||
#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
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -83,6 +82,7 @@ typedef struct {
|
|||
SDL_GLContext glContext;
|
||||
|
||||
SDL_GameController *gamepad[MAX_GAMEPADS];
|
||||
SDL_JoystickID gamepadId[MAX_GAMEPADS]; // Joystick instance ids
|
||||
SDL_Cursor *cursor;
|
||||
bool cursorRelative;
|
||||
} PlatformData;
|
||||
|
@ -240,7 +240,7 @@ static const int CursorsLUT[] = {
|
|||
|
||||
|
||||
// SDL3 Migration Layer made to avoid `ifdefs` inside functions when we can.
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
|
||||
// SDL3 Migration:
|
||||
// SDL_WINDOW_FULLSCREEN_DESKTOP has been removed,
|
||||
|
@ -249,7 +249,6 @@ static const int CursorsLUT[] = {
|
|||
// 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
|
||||
|
@ -260,27 +259,29 @@ static const int CursorsLUT[] = {
|
|||
// 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
|
||||
//
|
||||
// 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)
|
||||
// SDL2 implementation for SDL3 function
|
||||
const char *SDL_GameControllerNameForIndex(int joystickIndex)
|
||||
{
|
||||
// NOTE: SDL3 uses the IDs itself (SDL_JoystickID) instead of SDL2 joystick_index
|
||||
const char* name = NULL;
|
||||
const char *name = NULL;
|
||||
int numJoysticks = 0;
|
||||
SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks);
|
||||
if (joysticks) {
|
||||
if (joystickIndex < numJoysticks) {
|
||||
|
||||
if (joysticks)
|
||||
{
|
||||
if (joystickIndex < numJoysticks)
|
||||
{
|
||||
SDL_JoystickID instance_id = joysticks[joystickIndex];
|
||||
name = SDL_GetGamepadNameForID(instance_id);
|
||||
}
|
||||
|
||||
SDL_free(joysticks);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -288,45 +289,40 @@ int SDL_GetNumVideoDisplays(void)
|
|||
{
|
||||
int monitorCount = 0;
|
||||
SDL_DisplayID *displays = SDL_GetDisplays(&monitorCount);
|
||||
// Safe because If `mem` is NULL, SDL_free does nothing.
|
||||
|
||||
// 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) {
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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));
|
||||
|
@ -337,11 +333,14 @@ SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth
|
|||
// 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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -368,17 +367,13 @@ int SDL_NumJoysticks(void)
|
|||
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
|
||||
|
@ -398,7 +393,6 @@ bool SDL_GetRelativeMouseMode_Adapter(void)
|
|||
|
||||
#define SDL_GetRelativeMouseMode SDL_GetRelativeMouseMode_Adapter
|
||||
|
||||
|
||||
int SDL_GetNumTouchFingers(SDL_TouchID touchID)
|
||||
{
|
||||
// SDL_Finger **SDL_GetTouchFingers(SDL_TouchID touchID, int *count)
|
||||
|
@ -412,16 +406,16 @@ int SDL_GetNumTouchFingers(SDL_TouchID touchID)
|
|||
|
||||
// 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) {
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -452,7 +446,7 @@ 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 defined(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))
|
||||
|
@ -479,7 +473,8 @@ 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 defined(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))
|
||||
|
@ -503,25 +498,28 @@ void ToggleBorderlessWindowed(void)
|
|||
void MaximizeWindow(void)
|
||||
{
|
||||
SDL_MaximizeWindow(platform.window);
|
||||
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
|
||||
}
|
||||
|
||||
// Set window state: minimized
|
||||
void MinimizeWindow(void)
|
||||
{
|
||||
SDL_MinimizeWindow(platform.window);
|
||||
CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
|
||||
}
|
||||
|
||||
// Set window state: not minimized/maximized
|
||||
// Restore window from being minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
SDL_ShowWindow(platform.window);
|
||||
SDL_RestoreWindow(platform.window);
|
||||
// CORE.Window.flags will be removed on PollInputEvents()
|
||||
}
|
||||
|
||||
// Set window configuration state using flags
|
||||
void SetWindowState(unsigned int flags)
|
||||
{
|
||||
if (!CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetWindowState does nothing before window initialization, Use \"SetConfigFlags\" instead");
|
||||
|
||||
CORE.Window.flags |= flags;
|
||||
|
||||
if (flags & FLAG_VSYNC_HINT)
|
||||
|
@ -532,7 +530,8 @@ 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 defined(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))
|
||||
|
@ -575,7 +574,7 @@ void SetWindowState(unsigned int flags)
|
|||
}
|
||||
if (flags & FLAG_WINDOW_ALWAYS_RUN)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_ALWAYS_RUN is not supported on PLATFORM_DESKTOP_SDL");
|
||||
CORE.Window.flags |= FLAG_WINDOW_ALWAYS_RUN;
|
||||
}
|
||||
if (flags & FLAG_WINDOW_TRANSPARENT)
|
||||
{
|
||||
|
@ -595,7 +594,8 @@ 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 defined(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))
|
||||
|
@ -661,7 +661,7 @@ void ClearWindowState(unsigned int flags)
|
|||
}
|
||||
if (flags & FLAG_WINDOW_ALWAYS_RUN)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_ALWAYS_RUN is not supported on PLATFORM_DESKTOP_SDL");
|
||||
CORE.Window.flags &= ~FLAG_WINDOW_ALWAYS_RUN;
|
||||
}
|
||||
if (flags & FLAG_WINDOW_TRANSPARENT)
|
||||
{
|
||||
|
@ -704,70 +704,84 @@ void SetWindowIcon(Image image)
|
|||
switch (image.format)
|
||||
{
|
||||
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
|
||||
{
|
||||
rmask = 0xFF, gmask = 0;
|
||||
bmask = 0, amask = 0;
|
||||
depth = 8, pitch = image.width;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
|
||||
{
|
||||
rmask = 0xFF, gmask = 0xFF00;
|
||||
bmask = 0, amask = 0;
|
||||
depth = 16, pitch = image.width*2;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
|
||||
{
|
||||
rmask = 0xF800, gmask = 0x07E0;
|
||||
bmask = 0x001F, amask = 0;
|
||||
depth = 16, pitch = image.width*2;
|
||||
break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // Uses BGR for 24-bit
|
||||
rmask = 0x0000FF, gmask = 0x00FF00;
|
||||
bmask = 0xFF0000, amask = 0;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R8G8B8:
|
||||
{
|
||||
// WARNING: SDL2 could be using BGR but SDL3 RGB
|
||||
rmask = 0xFF0000, gmask = 0x00FF00;
|
||||
bmask = 0x0000FF, amask = 0;
|
||||
depth = 24, pitch = image.width*3;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
|
||||
{
|
||||
rmask = 0xF800, gmask = 0x07C0;
|
||||
bmask = 0x003E, amask = 0x0001;
|
||||
depth = 16, pitch = image.width*2;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
|
||||
{
|
||||
rmask = 0xF000, gmask = 0x0F00;
|
||||
bmask = 0x00F0, amask = 0x000F;
|
||||
depth = 16, pitch = image.width*2;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
|
||||
{
|
||||
rmask = 0xFF000000, gmask = 0x00FF0000;
|
||||
bmask = 0x0000FF00, amask = 0x000000FF;
|
||||
depth = 32, pitch = image.width*4;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R32:
|
||||
{
|
||||
rmask = 0xFFFFFFFF, gmask = 0;
|
||||
bmask = 0, amask = 0;
|
||||
depth = 32, pitch = image.width*4;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
|
||||
{
|
||||
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
|
||||
bmask = 0xFFFFFFFF, amask = 0;
|
||||
depth = 96, pitch = image.width*12;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
|
||||
{
|
||||
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
|
||||
bmask = 0xFFFFFFFF, amask = 0xFFFFFFFF;
|
||||
depth = 128, pitch = image.width*16;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R16:
|
||||
{
|
||||
rmask = 0xFFFF, gmask = 0;
|
||||
bmask = 0, amask = 0;
|
||||
depth = 16, pitch = image.width*2;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R16G16B16:
|
||||
{
|
||||
rmask = 0xFFFF, gmask = 0xFFFF;
|
||||
bmask = 0xFFFF, amask = 0;
|
||||
depth = 48, pitch = image.width*6;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:
|
||||
{
|
||||
rmask = 0xFFFF, gmask = 0xFFFF;
|
||||
bmask = 0xFFFF, amask = 0xFFFF;
|
||||
depth = 64, pitch = image.width*8;
|
||||
break;
|
||||
} break;
|
||||
default: return; // Compressed formats are not supported
|
||||
}
|
||||
|
||||
|
@ -818,7 +832,8 @@ void SetWindowMonitor(int monitor)
|
|||
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 defined(PLATFORM_DESKTOP_SDL3) // Different style for success checking
|
||||
if (SDL_GetDisplayUsableBounds(monitor, &usableBounds))
|
||||
#else
|
||||
if (SDL_GetDisplayUsableBounds(monitor, &usableBounds) == 0)
|
||||
|
@ -915,7 +930,7 @@ int GetMonitorCount(void)
|
|||
return monitorCount;
|
||||
}
|
||||
|
||||
// Get number of monitors
|
||||
// Get current monitor where window is placed
|
||||
int GetCurrentMonitor(void)
|
||||
{
|
||||
int currentMonitor = 0;
|
||||
|
@ -933,7 +948,8 @@ Vector2 GetMonitorPosition(int monitor)
|
|||
if ((monitor >= 0) && (monitor < monitorCount))
|
||||
{
|
||||
SDL_Rect displayBounds;
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
if (SDL_GetDisplayUsableBounds(monitor, &displayBounds))
|
||||
#else
|
||||
if (SDL_GetDisplayUsableBounds(monitor, &displayBounds) == 0)
|
||||
|
@ -1104,53 +1120,55 @@ const char *GetClipboardText(void)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
#if defined(SUPPORT_CLIPBOARD_IMAGE)
|
||||
// Get clipboard image
|
||||
Image GetClipboardImage(void)
|
||||
{
|
||||
Image image = { 0 };
|
||||
|
||||
#if defined(SUPPORT_CLIPBOARD_IMAGE)
|
||||
// Let's hope compiler put these arrays in static memory
|
||||
const char *image_formats[] = {
|
||||
const char *imageFormats[] = {
|
||||
"image/bmp",
|
||||
"image/png",
|
||||
"image/jpg",
|
||||
"image/tiff",
|
||||
};
|
||||
const char *image_extensions[] = {
|
||||
const char *imageExtensions[] = {
|
||||
".bmp",
|
||||
".png",
|
||||
".jpg",
|
||||
".tiff",
|
||||
};
|
||||
|
||||
|
||||
Image image = {0};
|
||||
size_t dataSize = 0;
|
||||
void *fileData = NULL;
|
||||
for (int i = 0; i < SDL_arraysize(image_formats); ++i)
|
||||
|
||||
for (int i = 0; i < SDL_arraysize(imageFormats); ++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);
|
||||
// NOTE: This pointer should be free with SDL_free() at some point
|
||||
fileData = SDL_GetClipboardData(imageFormats[i], &dataSize);
|
||||
|
||||
if (fileData)
|
||||
{
|
||||
image = LoadImageFromMemory(imageExtensions[i], fileData, dataSize);
|
||||
if (IsImageValid(image))
|
||||
{
|
||||
TRACELOG(LOG_INFO, "Clipboard image: Got image from clipboard as a `%s` successfully", image_extensions[i]);
|
||||
TRACELOG(LOG_INFO, "Clipboard image: Got image from clipboard as a `%s` successfully", imageExtensions[i]);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data. %s", SDL_GetError());
|
||||
return image;
|
||||
}
|
||||
if (!IsImageValid(image)) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data. Error: %s", SDL_GetError());
|
||||
#endif
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
// Show mouse cursor
|
||||
void ShowCursor(void)
|
||||
{
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
SDL_ShowCursor();
|
||||
#else
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
|
@ -1161,7 +1179,7 @@ void ShowCursor(void)
|
|||
// Hides mouse cursor
|
||||
void HideCursor(void)
|
||||
{
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
SDL_HideCursor();
|
||||
#else
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
@ -1174,7 +1192,7 @@ void EnableCursor(void)
|
|||
{
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
// SDL_ShowCursor() has been split into three functions: SDL_ShowCursor(), SDL_HideCursor(), and SDL_CursorVisible()
|
||||
SDL_ShowCursor();
|
||||
#else
|
||||
|
@ -1275,7 +1293,7 @@ const char *GetKeyName(int key)
|
|||
|
||||
static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event)
|
||||
{
|
||||
#ifdef PLATFORM_DESKTOP_SDL3 // SDL3
|
||||
#if defined(PLATFORM_DESKTOP_SDL3) // SDL3
|
||||
int count = 0;
|
||||
SDL_Finger **fingers = SDL_GetTouchFingers(event.touchID, &count);
|
||||
CORE.Input.Touch.pointCount = count;
|
||||
|
@ -1288,7 +1306,9 @@ static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event)
|
|||
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);
|
||||
|
@ -1345,7 +1365,7 @@ void PollInputEvents(void)
|
|||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
|
||||
|
||||
// Map touch position to mouse position for convenience
|
||||
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
||||
if (CORE.Input.Touch.pointCount == 0) CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
||||
|
||||
int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
|
||||
bool realTouch = false; // Flag to differentiate real touch gestures from mouse ones
|
||||
|
@ -1375,6 +1395,12 @@ void PollInputEvents(void)
|
|||
|
||||
CORE.Window.resizedLastFrame = false;
|
||||
|
||||
if ((CORE.Window.eventWaiting) || (((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) && ((CORE.Window.flags & FLAG_WINDOW_ALWAYS_RUN) == 0)))
|
||||
{
|
||||
SDL_WaitEvent(NULL);
|
||||
CORE.Time.previous = GetTime();
|
||||
}
|
||||
|
||||
SDL_Event event = { 0 };
|
||||
while (SDL_PollEvent(&event) != 0)
|
||||
{
|
||||
|
@ -1393,7 +1419,8 @@ 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
|
||||
|
||||
#if defined(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);
|
||||
|
@ -1407,7 +1434,8 @@ void PollInputEvents(void)
|
|||
else if (CORE.Window.dropFileCount < 1024)
|
||||
{
|
||||
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data);
|
||||
#else
|
||||
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file);
|
||||
|
@ -1422,7 +1450,7 @@ void PollInputEvents(void)
|
|||
|
||||
// Window events are also polled (Minimized, maximized, close...)
|
||||
|
||||
#ifndef PLATFORM_DESKTOP_SDL3
|
||||
#ifndef PLATFORM_DESKTOP_SDL3
|
||||
// SDL3 states:
|
||||
// The SDL_WINDOWEVENT_* events have been moved to top level events,
|
||||
// and SDL_WINDOWEVENT has been removed.
|
||||
|
@ -1432,19 +1460,45 @@ void PollInputEvents(void)
|
|||
{
|
||||
switch (event.window.event)
|
||||
{
|
||||
#endif
|
||||
#endif
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
{
|
||||
const int width = event.window.data1;
|
||||
const int height = event.window.data2;
|
||||
SetupViewport(width, height);
|
||||
CORE.Window.screen.width = width;
|
||||
CORE.Window.screen.height = height;
|
||||
// if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
|
||||
if (IsWindowState(FLAG_WINDOW_HIGHDPI))
|
||||
{
|
||||
CORE.Window.screen.width = (int)(width / GetWindowScaleDPI().x);
|
||||
CORE.Window.screen.height = (int)(height / GetWindowScaleDPI().y);
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE.Window.screen.width = width;
|
||||
CORE.Window.screen.height = height;
|
||||
}
|
||||
CORE.Window.currentFbo.width = width;
|
||||
CORE.Window.currentFbo.height = height;
|
||||
CORE.Window.resizedLastFrame = true;
|
||||
|
||||
#ifndef PLATFORM_DESKTOP_SDL3
|
||||
// Manually detect if the window was maximized (due to SDL2 restore being unreliable on some platforms) to remove the FLAG_WINDOW_MAXIMIZED accordingly
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0)
|
||||
{
|
||||
int borderTop = 0;
|
||||
int borderLeft = 0;
|
||||
int borderBottom = 0;
|
||||
int borderRight = 0;
|
||||
SDL_GetWindowBordersSize(platform.window, &borderTop, &borderLeft, &borderBottom, &borderRight);
|
||||
SDL_Rect usableBounds;
|
||||
SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(platform.window), &usableBounds);
|
||||
|
||||
if ((width + borderLeft + borderRight != usableBounds.w) && (height + borderTop + borderBottom != usableBounds.h)) CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case SDL_WINDOWEVENT_ENTER:
|
||||
{
|
||||
CORE.Input.Mouse.cursorOnScreen = true;
|
||||
|
@ -1453,16 +1507,49 @@ void PollInputEvents(void)
|
|||
{
|
||||
CORE.Input.Mouse.cursorOnScreen = false;
|
||||
} break;
|
||||
case SDL_WINDOWEVENT_HIDDEN:
|
||||
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
case SDL_WINDOWEVENT_SHOWN:
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
|
||||
} break;
|
||||
case SDL_WINDOWEVENT_MAXIMIZED:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
|
||||
} break;
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
break;
|
||||
#else
|
||||
{
|
||||
if ((SDL_GetWindowFlags(platform.window) & SDL_WINDOW_MINIMIZED) == 0)
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
if ((SDL_GetWindowFlags(platform.window) & SDL_WINDOW_MAXIMIZED) == 0)
|
||||
{
|
||||
if ((CORE.Window.flags & SDL_WINDOW_MAXIMIZED) > 0) CORE.Window.flags &= ~SDL_WINDOW_MAXIMIZED;
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case SDL_WINDOWEVENT_HIDDEN:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) == 0) CORE.Window.flags |= FLAG_WINDOW_HIDDEN;
|
||||
} break;
|
||||
case SDL_WINDOWEVENT_SHOWN:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN;
|
||||
} break;
|
||||
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;
|
||||
} break;
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0) CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;
|
||||
} break;
|
||||
|
||||
#ifndef PLATFORM_DESKTOP_SDL3
|
||||
default: break;
|
||||
}
|
||||
} break;
|
||||
|
@ -1471,7 +1558,7 @@ void PollInputEvents(void)
|
|||
// Keyboard events
|
||||
case SDL_KEYDOWN:
|
||||
{
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
// SDL3 Migration: The following structures have been removed: * SDL_Keysym
|
||||
KeyboardKey key = ConvertScancodeToKey(event.key.scancode);
|
||||
#else
|
||||
|
@ -1502,7 +1589,7 @@ void PollInputEvents(void)
|
|||
case SDL_KEYUP:
|
||||
{
|
||||
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
KeyboardKey key = ConvertScancodeToKey(event.key.scancode);
|
||||
#else
|
||||
KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode);
|
||||
|
@ -1597,11 +1684,12 @@ void PollInputEvents(void)
|
|||
// Check gamepad events
|
||||
case SDL_JOYDEVICEADDED:
|
||||
{
|
||||
int jid = event.jdevice.which;
|
||||
int jid = event.jdevice.which; // Joystick device index
|
||||
|
||||
if (!CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS))
|
||||
if (CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS))
|
||||
{
|
||||
platform.gamepad[jid] = SDL_GameControllerOpen(jid);
|
||||
platform.gamepadId[jid] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[jid]));
|
||||
|
||||
if (platform.gamepad[jid])
|
||||
{
|
||||
|
@ -1609,8 +1697,8 @@ void PollInputEvents(void)
|
|||
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_GameControllerNameForIndex(jid), 63);
|
||||
CORE.Input.Gamepad.name[jid][63] = '\0';
|
||||
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
|
||||
strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1620,14 +1708,18 @@ void PollInputEvents(void)
|
|||
} break;
|
||||
case SDL_JOYDEVICEREMOVED:
|
||||
{
|
||||
int jid = event.jdevice.which;
|
||||
int jid = event.jdevice.which; // Joystick instance id
|
||||
|
||||
if (jid == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[jid])))
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
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);
|
||||
if (platform.gamepadId[i] == jid)
|
||||
{
|
||||
SDL_GameControllerClose(platform.gamepad[i]);
|
||||
CORE.Input.Gamepad.ready[i] = false;
|
||||
memset(CORE.Input.Gamepad.name[i], 0, MAX_GAMEPAD_NAME_LENGTH);
|
||||
platform.gamepadId[i] = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
|
@ -1660,8 +1752,15 @@ void PollInputEvents(void)
|
|||
|
||||
if (button >= 0)
|
||||
{
|
||||
CORE.Input.Gamepad.currentButtonState[event.jbutton.which][button] = 1;
|
||||
CORE.Input.Gamepad.lastButtonPressed = button;
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
if (platform.gamepadId[i] == event.jbutton.which)
|
||||
{
|
||||
CORE.Input.Gamepad.currentButtonState[i][button] = 1;
|
||||
CORE.Input.Gamepad.lastButtonPressed = button;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
|
@ -1694,8 +1793,15 @@ void PollInputEvents(void)
|
|||
|
||||
if (button >= 0)
|
||||
{
|
||||
CORE.Input.Gamepad.currentButtonState[event.jbutton.which][button] = 0;
|
||||
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
if (platform.gamepadId[i] == event.jbutton.which)
|
||||
{
|
||||
CORE.Input.Gamepad.currentButtonState[i][button] = 0;
|
||||
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
|
@ -1715,18 +1821,25 @@ 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;
|
||||
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))
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
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;
|
||||
else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
|
||||
if (platform.gamepadId[i] == event.jaxis.which)
|
||||
{
|
||||
// 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;
|
||||
CORE.Input.Gamepad.axisState[i][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 pressed = (value > 0.1f);
|
||||
CORE.Input.Gamepad.currentButtonState[i][button] = pressed;
|
||||
if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
|
||||
else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
@ -1858,7 +1971,7 @@ int InitPlatform(void)
|
|||
}
|
||||
|
||||
// Init window
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
#if defined(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);
|
||||
|
@ -1906,9 +2019,15 @@ int InitPlatform(void)
|
|||
// Initialize input events system
|
||||
//----------------------------------------------------------------------------
|
||||
// Initialize gamepads
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
platform.gamepadId[i] = -1; // Set all gamepad initial instance ids as invalid to not conflict with instance id zero
|
||||
}
|
||||
|
||||
for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++)
|
||||
{
|
||||
platform.gamepad[i] = SDL_GameControllerOpen(i);
|
||||
platform.gamepadId[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[i]));
|
||||
|
||||
if (platform.gamepad[i])
|
||||
{
|
||||
|
@ -1916,8 +2035,8 @@ int InitPlatform(void)
|
|||
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_GameControllerNameForIndex(i), 63);
|
||||
CORE.Input.Gamepad.name[i][63] = '\0';
|
||||
strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||
CORE.Input.Gamepad.name[i][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0';
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
|
||||
}
|
||||
|
@ -1946,11 +2065,10 @@ int InitPlatform(void)
|
|||
CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory();
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL3): Initialized successfully");
|
||||
#else
|
||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully");
|
||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL2): Initialized successfully");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -1968,7 +2086,7 @@ void ClosePlatform(void)
|
|||
// Scancode to keycode mapping
|
||||
static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode)
|
||||
{
|
||||
if (sdlScancode >= 0 && sdlScancode < SCANCODE_MAPPED_NUM)
|
||||
if ((sdlScancode >= 0) && (sdlScancode < SCANCODE_MAPPED_NUM))
|
||||
{
|
||||
return mapScancodeToKey[sdlScancode];
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) and contributors
|
||||
*
|
||||
* 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.
|
||||
|
@ -125,7 +125,7 @@ typedef struct {
|
|||
|
||||
// Gamepad data
|
||||
int gamepadStreamFd[MAX_GAMEPADS]; // Gamepad device file descriptor
|
||||
int gamepadAbsAxisRange[MAX_GAMEPADS][MAX_GAMEPAD_AXIS][2]; // [0] = min, [1] = range value of the axis
|
||||
int gamepadAbsAxisRange[MAX_GAMEPADS][MAX_GAMEPAD_AXES][2]; // [0] = min, [1] = range value of the axes
|
||||
int gamepadAbsAxisMap[MAX_GAMEPADS][ABS_CNT]; // Maps the axes gamepads from the evdev api to a sequential one
|
||||
int gamepadCount; // The number of gamepads registered
|
||||
} PlatformData;
|
||||
|
@ -278,7 +278,7 @@ void MinimizeWindow(void)
|
|||
TRACELOG(LOG_WARNING, "MinimizeWindow() not available on target platform");
|
||||
}
|
||||
|
||||
// Set window state: not minimized/maximized
|
||||
// Restore window from being minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
||||
|
@ -372,7 +372,7 @@ int GetMonitorCount(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Get number of monitors
|
||||
// Get current monitor where window is placed
|
||||
int GetCurrentMonitor(void)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GetCurrentMonitor() not implemented on target platform");
|
||||
|
@ -623,7 +623,7 @@ int SetGamepadMappings(const char *mappings)
|
|||
// Set gamepad vibration
|
||||
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform");
|
||||
TRACELOG(LOG_WARNING, "SetGamepadVibration() not implemented on target platform");
|
||||
}
|
||||
|
||||
// Set mouse position XY
|
||||
|
@ -736,20 +736,24 @@ int InitPlatform(void)
|
|||
|
||||
#if defined(DEFAULT_GRAPHIC_DEVICE_DRM)
|
||||
platform.fd = open(DEFAULT_GRAPHIC_DEVICE_DRM, O_RDWR);
|
||||
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: Default graphic device DRM opened successfully");
|
||||
#else
|
||||
TRACELOG(LOG_INFO, "DISPLAY: No graphic card set, trying platform-gpu-card");
|
||||
TRACELOG(LOG_WARNING, "DISPLAY: No graphic card set, trying platform-gpu-card");
|
||||
platform.fd = open("/dev/dri/by-path/platform-gpu-card", O_RDWR); // VideoCore VI (Raspberry Pi 4)
|
||||
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: platform-gpu-card opened successfully");
|
||||
|
||||
if ((platform.fd == -1) || (drmModeGetResources(platform.fd) == NULL))
|
||||
{
|
||||
TRACELOG(LOG_INFO, "DISPLAY: Failed to open platform-gpu-card, trying card1");
|
||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open platform-gpu-card, trying card1");
|
||||
platform.fd = open("/dev/dri/card1", O_RDWR); // Other Embedded
|
||||
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: card1 opened successfully");
|
||||
}
|
||||
|
||||
if ((platform.fd == -1) || (drmModeGetResources(platform.fd) == NULL))
|
||||
{
|
||||
TRACELOG(LOG_INFO, "DISPLAY: Failed to open graphic card1, trying card0");
|
||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open graphic card1, trying card0");
|
||||
platform.fd = open("/dev/dri/card0", O_RDWR); // VideoCore IV (Raspberry Pi 1-3)
|
||||
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: card0 opened successfully");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -899,18 +903,17 @@ int InitPlatform(void)
|
|||
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4");
|
||||
}
|
||||
|
||||
const EGLint framebufferAttribs[] =
|
||||
{
|
||||
EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, // Don't use it on Android!
|
||||
const EGLint framebufferAttribs[] = {
|
||||
EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, // Don't use it on Android!
|
||||
EGL_RED_SIZE, 8, // RED color bit depth (alternative: 5)
|
||||
EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6)
|
||||
EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5)
|
||||
EGL_ALPHA_SIZE, 8, // ALPHA bit depth (required for transparent framebuffer)
|
||||
//EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI)
|
||||
EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!)
|
||||
EGL_DEPTH_SIZE, 24, // Depth buffer size (Required to use Depth testing!)
|
||||
//EGL_STENCIL_SIZE, 8, // Stencil buffer size
|
||||
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
|
||||
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
|
||||
EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs)
|
||||
EGL_NONE
|
||||
};
|
||||
|
@ -946,7 +949,7 @@ int InitPlatform(void)
|
|||
|
||||
TRACELOG(LOG_TRACE, "DISPLAY: EGL configs available: %d", numConfigs);
|
||||
|
||||
EGLConfig *configs = RL_CALLOC(numConfigs, sizeof(*configs));
|
||||
EGLConfig *configs = (EGLConfig *)RL_CALLOC(numConfigs, sizeof(*configs));
|
||||
if (!configs)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get memory for EGL configs");
|
||||
|
@ -1372,7 +1375,7 @@ static void InitEvdevInput(void)
|
|||
if ((strncmp("event", entity->d_name, strlen("event")) == 0) || // Search for devices named "event*"
|
||||
(strncmp("mouse", entity->d_name, strlen("mouse")) == 0)) // Search for devices named "mouse*"
|
||||
{
|
||||
sprintf(path, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
|
||||
snprintf(path, MAX_FILEPATH_LENGTH, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
|
||||
ConfigureEvdevDevice(path); // Configure the device if appropriate
|
||||
}
|
||||
}
|
||||
|
@ -1401,7 +1404,7 @@ static void ConfigureEvdevDevice(char *device)
|
|||
int fd = open(device, O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "DRM: Failed to open input device: %s", device);
|
||||
TRACELOG(LOG_WARNING, "SYSTEM: Failed to open input device: %s", device);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1458,7 +1461,7 @@ static void ConfigureEvdevDevice(char *device)
|
|||
// matter if we support them
|
||||
else if (hasAbsXY && TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;
|
||||
|
||||
// If any of the common joystick axis is present, we assume it's a gamepad
|
||||
// If any of the common joystick axes are present, we assume it's a gamepad
|
||||
else
|
||||
{
|
||||
for (int axis = (hasAbsXY? ABS_Z : ABS_X); axis < ABS_PRESSURE; axis++)
|
||||
|
@ -1530,7 +1533,7 @@ static void ConfigureEvdevDevice(char *device)
|
|||
platform.absRange.height = absinfo[ABS_Y].info.maximum - absinfo[ABS_Y].info.minimum;
|
||||
}
|
||||
}
|
||||
else if (isGamepad && !isMouse && !isKeyboard && platform.gamepadCount < MAX_GAMEPADS)
|
||||
else if (isGamepad && !isMouse && !isKeyboard && (platform.gamepadCount < MAX_GAMEPADS))
|
||||
{
|
||||
deviceKindStr = "gamepad";
|
||||
int index = platform.gamepadCount++;
|
||||
|
@ -1544,7 +1547,7 @@ static void ConfigureEvdevDevice(char *device)
|
|||
if (absAxisCount > 0)
|
||||
{
|
||||
// TODO / NOTE
|
||||
// So gamepad axis (as in the actual linux joydev.c) are just simply enumerated
|
||||
// So gamepad axes (as in the actual linux joydev.c) are just simply enumerated
|
||||
// and (at least for some input drivers like xpat) it's convention to use
|
||||
// ABS_X, ABX_Y for one joystick ABS_RX, ABS_RY for the other and the Z axes for the
|
||||
// shoulder buttons
|
||||
|
@ -1679,7 +1682,7 @@ static void PollGamepadEvents(void)
|
|||
|
||||
TRACELOG(LOG_DEBUG, "INPUT: Gamepad %2i: Axis: %2i Value: %i", i, axisRaylib, event.value);
|
||||
|
||||
if (axisRaylib < MAX_GAMEPAD_AXIS)
|
||||
if (axisRaylib < MAX_GAMEPAD_AXES)
|
||||
{
|
||||
int min = platform.gamepadAbsAxisRange[i][event.code][0];
|
||||
int range = platform.gamepadAbsAxisRange[i][event.code][1];
|
||||
|
@ -1894,7 +1897,7 @@ static int FindExactConnectorMode(const drmModeConnector *connector, uint width,
|
|||
|
||||
TRACELOG(LOG_TRACE, "DISPLAY: DRM Mode %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE)? "interlaced" : "progressive");
|
||||
|
||||
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && (!allowInterlaced)) continue;
|
||||
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && !allowInterlaced) continue;
|
||||
|
||||
if ((mode->hdisplay == width) && (mode->vdisplay == height) && (mode->vrefresh == fps)) return i;
|
||||
}
|
||||
|
@ -1924,7 +1927,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && (!allowInterlaced))
|
||||
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && !allowInterlaced)
|
||||
{
|
||||
TRACELOG(LOG_TRACE, "DISPLAY: DRM shouldn't choose an interlaced mode");
|
||||
continue;
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -607,6 +607,7 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
|
|||
|
||||
audioBuffer->usage = usage;
|
||||
audioBuffer->frameCursorPos = 0;
|
||||
audioBuffer->framesProcessed = 0;
|
||||
audioBuffer->sizeInFrames = sizeInFrames;
|
||||
|
||||
// Buffers should be marked as processed by default so that a call to
|
||||
|
@ -653,6 +654,9 @@ void PlayAudioBuffer(AudioBuffer *buffer)
|
|||
buffer->playing = true;
|
||||
buffer->paused = false;
|
||||
buffer->frameCursorPos = 0;
|
||||
buffer->framesProcessed = 0;
|
||||
buffer->isSubBufferProcessed[0] = true;
|
||||
buffer->isSubBufferProcessed[1] = true;
|
||||
ma_mutex_unlock(&AUDIO.System.lock);
|
||||
}
|
||||
}
|
||||
|
@ -804,10 +808,10 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
|||
wave.sampleRate = wav.sampleRate;
|
||||
wave.sampleSize = 16;
|
||||
wave.channels = wav.channels;
|
||||
wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short));
|
||||
wave.data = (short *)RL_MALLOC((size_t)wave.frameCount*wave.channels*sizeof(short));
|
||||
|
||||
// NOTE: We are forcing conversion to 16bit sample size on reading
|
||||
drwav_read_pcm_frames_s16(&wav, wav.totalPCMFrameCount, wave.data);
|
||||
drwav_read_pcm_frames_s16(&wav, wave.frameCount, wave.data);
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "WAVE: Failed to load WAV data");
|
||||
|
||||
|
@ -1128,7 +1132,7 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
|
|||
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2024 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2025 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "//////////////////////////////////////////////////////////////////////////////////\n\n");
|
||||
|
||||
|
@ -1243,6 +1247,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
|
|||
frameCount = (ma_uint32)ma_convert_frames(data, frameCount, formatOut, channels, sampleRate, wave->data, frameCountIn, formatIn, wave->channels, wave->sampleRate);
|
||||
if (frameCount == 0)
|
||||
{
|
||||
RL_FREE(wave->data);
|
||||
TRACELOG(LOG_WARNING, "WAVE: Failed format conversion");
|
||||
return;
|
||||
}
|
||||
|
@ -1335,7 +1340,7 @@ Music LoadMusicStream(const char *fileName)
|
|||
#if defined(SUPPORT_FILEFORMAT_WAV)
|
||||
else if (IsFileExtension(fileName, ".wav"))
|
||||
{
|
||||
drwav *ctxWav = RL_CALLOC(1, sizeof(drwav));
|
||||
drwav *ctxWav = (drwav *)RL_CALLOC(1, sizeof(drwav));
|
||||
bool success = drwav_init_file(ctxWav, fileName, NULL);
|
||||
|
||||
if (success)
|
||||
|
@ -1385,7 +1390,7 @@ Music LoadMusicStream(const char *fileName)
|
|||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||
else if (IsFileExtension(fileName, ".mp3"))
|
||||
{
|
||||
drmp3 *ctxMp3 = RL_CALLOC(1, sizeof(drmp3));
|
||||
drmp3 *ctxMp3 = (drmp3 *)RL_CALLOC(1, sizeof(drmp3));
|
||||
int result = drmp3_init_file(ctxMp3, fileName, NULL);
|
||||
|
||||
if (result > 0)
|
||||
|
@ -1476,7 +1481,7 @@ Music LoadMusicStream(const char *fileName)
|
|||
#if defined(SUPPORT_FILEFORMAT_MOD)
|
||||
else if (IsFileExtension(fileName, ".mod"))
|
||||
{
|
||||
jar_mod_context_t *ctxMod = RL_CALLOC(1, sizeof(jar_mod_context_t));
|
||||
jar_mod_context_t *ctxMod = (jar_mod_context_t *)RL_CALLOC(1, sizeof(jar_mod_context_t));
|
||||
jar_mod_init(ctxMod);
|
||||
int result = jar_mod_load_file(ctxMod, fileName);
|
||||
|
||||
|
@ -1527,7 +1532,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
|||
#if defined(SUPPORT_FILEFORMAT_WAV)
|
||||
else if ((strcmp(fileType, ".wav") == 0) || (strcmp(fileType, ".WAV") == 0))
|
||||
{
|
||||
drwav *ctxWav = RL_CALLOC(1, sizeof(drwav));
|
||||
drwav *ctxWav = (drwav *)RL_CALLOC(1, sizeof(drwav));
|
||||
|
||||
bool success = drwav_init_memory(ctxWav, (const void *)data, dataSize, NULL);
|
||||
|
||||
|
@ -1553,7 +1558,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)
|
||||
{
|
||||
|
@ -1578,7 +1583,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
|||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||
else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
|
||||
{
|
||||
drmp3 *ctxMp3 = RL_CALLOC(1, sizeof(drmp3));
|
||||
drmp3 *ctxMp3 = (drmp3 *)RL_CALLOC(1, sizeof(drmp3));
|
||||
int success = drmp3_init_memory(ctxMp3, (const void*)data, dataSize, NULL);
|
||||
|
||||
if (success)
|
||||
|
@ -1858,6 +1863,8 @@ void SeekMusicStream(Music music, float position)
|
|||
|
||||
ma_mutex_lock(&AUDIO.System.lock);
|
||||
music.stream.buffer->framesProcessed = positionInFrames;
|
||||
music.stream.buffer->isSubBufferProcessed[0] = true;
|
||||
music.stream.buffer->isSubBufferProcessed[1] = true;
|
||||
ma_mutex_unlock(&AUDIO.System.lock);
|
||||
}
|
||||
|
||||
|
@ -2104,8 +2111,12 @@ AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
|
|||
// The size of a streaming buffer must be at least double the size of a period
|
||||
unsigned int periodSize = AUDIO.System.device.playback.internalPeriodSizeInFrames;
|
||||
|
||||
// If the buffer is not set, compute one that would give us a buffer good enough for a decent frame rate
|
||||
unsigned int subBufferSize = (AUDIO.Buffer.defaultSize == 0)? AUDIO.System.device.sampleRate/30 : AUDIO.Buffer.defaultSize;
|
||||
// If the buffer is not set, compute one that would give us a buffer good enough for a decent frame rate at the device bit size/rate
|
||||
int deviceBitsPerSample = AUDIO.System.device.playback.format;
|
||||
if (deviceBitsPerSample > 4) deviceBitsPerSample = 4;
|
||||
deviceBitsPerSample *= AUDIO.System.device.playback.channels;
|
||||
|
||||
unsigned int subBufferSize = (AUDIO.Buffer.defaultSize == 0) ? (AUDIO.System.device.sampleRate/30*deviceBitsPerSample) : AUDIO.Buffer.defaultSize;
|
||||
|
||||
if (subBufferSize < periodSize) subBufferSize = periodSize;
|
||||
|
||||
|
@ -2462,23 +2473,18 @@ static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, f
|
|||
|
||||
float *runningFramesOut = framesOut + (totalOutputFramesProcessed*audioBuffer->converter.channelsOut);
|
||||
|
||||
/* At this point we can convert the data to our mixing format. */
|
||||
ma_uint64 inputFramesProcessedThisIteration = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, (ma_uint32)inputFramesToProcessThisIteration); /* Safe cast. */
|
||||
// At this point we can convert the data to our mixing format
|
||||
ma_uint64 inputFramesProcessedThisIteration = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, (ma_uint32)inputFramesToProcessThisIteration);
|
||||
ma_uint64 outputFramesProcessedThisIteration = outputFramesToProcessThisIteration;
|
||||
ma_data_converter_process_pcm_frames(&audioBuffer->converter, inputBuffer, &inputFramesProcessedThisIteration, runningFramesOut, &outputFramesProcessedThisIteration);
|
||||
|
||||
totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration; /* Safe cast. */
|
||||
totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration; // Safe cast
|
||||
|
||||
if (inputFramesProcessedThisIteration < inputFramesToProcessThisIteration)
|
||||
{
|
||||
break; /* Ran out of input data. */
|
||||
}
|
||||
if (inputFramesProcessedThisIteration < inputFramesToProcessThisIteration) break; // Ran out of input data
|
||||
|
||||
/* This should never be hit, but will add it here for safety. Ensures we get out of the loop when no input nor output frames are processed. */
|
||||
if (inputFramesProcessedThisIteration == 0 && outputFramesProcessedThisIteration == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// This should never be hit, but added here for safety
|
||||
// Ensures we get out of the loop when no input nor output frames are processed
|
||||
if ((inputFramesProcessedThisIteration == 0) && (outputFramesProcessedThisIteration == 0)) break;
|
||||
}
|
||||
|
||||
return totalOutputFramesProcessed;
|
||||
|
|
176
raylib/raylib.h
176
raylib/raylib.h
|
@ -1,6 +1,6 @@
|
|||
/**********************************************************************************************
|
||||
*
|
||||
* raylib v5.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
||||
* raylib v5.6-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
||||
*
|
||||
* FEATURES:
|
||||
* - NO external dependencies, all required libraries included with raylib
|
||||
|
@ -63,7 +63,7 @@
|
|||
* raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software:
|
||||
*
|
||||
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -88,9 +88,9 @@
|
|||
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
||||
|
||||
#define RAYLIB_VERSION_MAJOR 5
|
||||
#define RAYLIB_VERSION_MINOR 5
|
||||
#define RAYLIB_VERSION_MINOR 6
|
||||
#define RAYLIB_VERSION_PATCH 0
|
||||
#define RAYLIB_VERSION "5.5"
|
||||
#define RAYLIB_VERSION "5.6-dev"
|
||||
|
||||
// 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
|
||||
|
@ -743,7 +743,7 @@ typedef enum {
|
|||
GAMEPAD_BUTTON_RIGHT_THUMB // Gamepad joystick pressed button right
|
||||
} GamepadButton;
|
||||
|
||||
// Gamepad axis
|
||||
// Gamepad axes
|
||||
typedef enum {
|
||||
GAMEPAD_AXIS_LEFT_X = 0, // Gamepad left stick X axis
|
||||
GAMEPAD_AXIS_LEFT_Y = 1, // Gamepad left stick Y axis
|
||||
|
@ -801,7 +801,8 @@ typedef enum {
|
|||
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
|
||||
SHADER_LOC_BONE_MATRICES, // Shader location: array of matrices uniform: boneMatrices
|
||||
SHADER_LOC_VERTEX_INSTANCE_TX // Shader location: vertex attribute: instanceTransform
|
||||
} ShaderLocationIndex;
|
||||
|
||||
#define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO
|
||||
|
@ -817,6 +818,10 @@ typedef enum {
|
|||
SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int)
|
||||
SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int)
|
||||
SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int)
|
||||
SHADER_UNIFORM_UINT, // Shader uniform type: unsigned int
|
||||
SHADER_UNIFORM_UIVEC2, // Shader uniform type: uivec2 (2 unsigned int)
|
||||
SHADER_UNIFORM_UIVEC3, // Shader uniform type: uivec3 (3 unsigned int)
|
||||
SHADER_UNIFORM_UIVEC4, // Shader uniform type: uivec4 (4 unsigned int)
|
||||
SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d
|
||||
} ShaderUniformDataType;
|
||||
|
||||
|
@ -949,7 +954,7 @@ typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args);
|
|||
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
|
||||
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data
|
||||
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
||||
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
||||
typedef bool (*SaveFileTextCallback)(const char *fileName, const char *text); // FileIO: Save text data
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
|
@ -982,7 +987,7 @@ RLAPI void ToggleFullscreen(void); // Toggle wind
|
|||
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 RestoreWindow(void); // Restore window from being 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
|
||||
|
@ -1056,7 +1061,7 @@ RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Ge
|
|||
RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value
|
||||
RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count); // Set shader uniform value vector
|
||||
RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4)
|
||||
RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value for texture (sampler2d)
|
||||
RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value and bind the texture (sampler2d)
|
||||
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
||||
|
||||
// Screen-space-related functions
|
||||
|
@ -1118,7 +1123,7 @@ RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save
|
|||
RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success
|
||||
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
||||
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
|
||||
RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
||||
RLAPI bool SaveFileText(const char *fileName, const char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
||||
//------------------------------------------------------------------
|
||||
|
||||
// File system functions
|
||||
|
@ -1148,22 +1153,21 @@ RLAPI long GetFileModTime(const char *fileName); // Get file mo
|
|||
// Compression/Encoding functionality
|
||||
RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize); // Compress data (DEFLATE algorithm), memory must be MemFree()
|
||||
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree()
|
||||
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
|
||||
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
|
||||
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)
|
||||
|
||||
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string (includes NULL terminator), memory must be MemFree()
|
||||
RLAPI unsigned char *DecodeDataBase64(const char *text, int *outputSize); // Decode Base64 string (expected NULL terminated), 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 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
|
||||
RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set)
|
||||
RLAPI void StopAutomationEventRecording(void); // Stop recording automation events
|
||||
RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event
|
||||
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 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
|
||||
RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set)
|
||||
RLAPI void StopAutomationEventRecording(void); // Stop recording automation events
|
||||
RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Input Handling Functions (Module: core)
|
||||
|
@ -1177,19 +1181,20 @@ RLAPI bool IsKeyReleased(int key); // Check if a key
|
|||
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
||||
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
|
||||
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
|
||||
RLAPI const char *GetKeyName(int key); // Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard)
|
||||
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
||||
|
||||
// Input-related functions: gamepads
|
||||
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
||||
RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id
|
||||
RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once
|
||||
RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed
|
||||
RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once
|
||||
RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed
|
||||
RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
|
||||
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 bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
||||
RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id
|
||||
RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once
|
||||
RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed
|
||||
RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once
|
||||
RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed
|
||||
RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
|
||||
RLAPI int GetGamepadAxisCount(int gamepad); // Get axis count for a gamepad
|
||||
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get 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, float duration); // Set gamepad vibration for both motors (duration in seconds)
|
||||
|
||||
// Input-related functions: mouse
|
||||
|
@ -1218,19 +1223,19 @@ RLAPI int GetTouchPointCount(void); // Get number of t
|
|||
//------------------------------------------------------------------------------------
|
||||
// Gestures and Touch Handling Functions (Module: rgestures)
|
||||
//------------------------------------------------------------------------------------
|
||||
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 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
|
||||
RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle
|
||||
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 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
|
||||
RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Camera System Functions (Module: rcamera)
|
||||
//------------------------------------------------------------------------------------
|
||||
RLAPI void UpdateCamera(Camera *camera, int mode); // Update camera position for selected mode
|
||||
RLAPI void UpdateCamera(Camera *camera, int mode); // Update camera position for selected mode
|
||||
RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom); // Update camera movement/rotation
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
@ -1239,9 +1244,9 @@ RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, f
|
|||
// Set texture and rectangle to be used on shapes drawing
|
||||
// NOTE: It can be useful when using basic shapes and one single font,
|
||||
// defining a font char white rectangle would allow drawing everything in a single draw call
|
||||
RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing
|
||||
RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing
|
||||
RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing
|
||||
RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing
|
||||
RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing
|
||||
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 using geometry [Can be slow, use with care]
|
||||
|
@ -1259,7 +1264,9 @@ RLAPI void DrawCircleV(Vector2 center, float radius, Color color);
|
|||
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
||||
RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
|
||||
RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
|
||||
RLAPI void DrawEllipseV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse (Vector version)
|
||||
RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
|
||||
RLAPI void DrawEllipseLinesV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse outline (Vector version)
|
||||
RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
|
||||
RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline
|
||||
RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle
|
||||
|
@ -1268,7 +1275,7 @@ RLAPI void DrawRectangleRec(Rectangle rec, Color color);
|
|||
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 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 DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color bottomRight, Color topRight); // 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
|
||||
|
@ -1283,11 +1290,11 @@ RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation
|
|||
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(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 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
|
||||
|
@ -1360,7 +1367,7 @@ RLAPI void ImageAlphaPremultiply(Image *image);
|
|||
RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation
|
||||
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 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 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)
|
||||
|
@ -1401,8 +1408,8 @@ RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color c
|
|||
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 ImageDrawTriangleFan(Image *dst, const 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, const 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)
|
||||
|
@ -1486,18 +1493,19 @@ RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint);
|
|||
RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
|
||||
|
||||
// Text codepoints management functions (unicode characters)
|
||||
RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array
|
||||
RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array
|
||||
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
|
||||
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
|
||||
RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
|
||||
RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
|
||||
RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array
|
||||
RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array
|
||||
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
|
||||
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
|
||||
RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
|
||||
RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
|
||||
|
||||
// Text strings management functions (no UTF-8 strings, only byte chars)
|
||||
// NOTE: Some strings allocate memory internally for returned strings, just be careful!
|
||||
// WARNING 1: Most of these functions use internal static buffers, it's recommended to store returned data on user-side for re-use
|
||||
// WARNING 2: Some strings allocate memory internally for the returned strings, those strings must be free by user using MemFree()
|
||||
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
|
||||
RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal
|
||||
RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending
|
||||
|
@ -1505,18 +1513,18 @@ RLAPI const char *TextFormat(const char *text, ...);
|
|||
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
|
||||
RLAPI char *TextReplace(const char *text, const char *replace, const char *by); // Replace text string (WARNING: memory must be freed!)
|
||||
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!)
|
||||
RLAPI const char *TextJoin(const char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
||||
RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
|
||||
RLAPI char *TextJoin(char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
||||
RLAPI char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
|
||||
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor!
|
||||
RLAPI int TextFindIndex(const char *text, const char *find); // Find first text occurrence within a string
|
||||
RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string
|
||||
RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string
|
||||
RLAPI const char *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 char *TextToUpper(const char *text); // Get upper case version of provided string
|
||||
RLAPI char *TextToLower(const char *text); // Get lower case version of provided string
|
||||
RLAPI char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
|
||||
RLAPI char *TextToSnake(const char *text); // Get Snake case notation version of provided string
|
||||
RLAPI 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)
|
||||
RLAPI int TextToInteger(const char *text); // Get integer value from text
|
||||
RLAPI float TextToFloat(const char *text); // Get float value from text
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Basic 3d Shapes Drawing Functions (Module: models)
|
||||
|
@ -1609,14 +1617,14 @@ RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount);
|
|||
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
||||
|
||||
// Collision detection functions
|
||||
RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres
|
||||
RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes
|
||||
RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere
|
||||
RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere
|
||||
RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box
|
||||
RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh
|
||||
RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle
|
||||
RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad
|
||||
RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres
|
||||
RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes
|
||||
RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere
|
||||
RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere
|
||||
RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box
|
||||
RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh
|
||||
RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle
|
||||
RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Audio Loading and Playing Functions (Module: audio)
|
||||
|
@ -1695,10 +1703,10 @@ RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan
|
|||
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
||||
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
||||
|
||||
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives the samples as 'float'
|
||||
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives frames x 2 samples as 'float' (stereo)
|
||||
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
||||
|
||||
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives the samples as 'float'
|
||||
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives frames x 2 samples as 'float' (stereo)
|
||||
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -304,6 +304,14 @@ RMAPI float Vector2DotProduct(Vector2 v1, Vector2 v2)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Calculate two vectors cross product
|
||||
RMAPI float Vector2CrossProduct(Vector2 v1, Vector2 v2)
|
||||
{
|
||||
float result = (v1.x*v2.y - v1.y*v2.x);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate distance between two vectors
|
||||
RMAPI float Vector2Distance(Vector2 v1, Vector2 v2)
|
||||
{
|
||||
|
@ -320,8 +328,9 @@ RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Calculate angle between two vectors
|
||||
// NOTE: Angle is calculated from origin point (0, 0)
|
||||
// Calculate the signed angle from v1 to v2, relative to the origin (0, 0)
|
||||
// NOTE: Coordinate system convention: positive X right, positive Y down,
|
||||
// positive angles appear clockwise, and negative angles appear counterclockwise
|
||||
RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
|
||||
{
|
||||
float result = 0.0f;
|
||||
|
@ -1459,19 +1468,35 @@ RMAPI int Vector4Equals(Vector4 p, Vector4 q)
|
|||
RMAPI float MatrixDeterminant(Matrix mat)
|
||||
{
|
||||
float result = 0.0f;
|
||||
|
||||
/*
|
||||
// Cache the matrix values (speed optimization)
|
||||
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
|
||||
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
|
||||
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
|
||||
float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
|
||||
|
||||
// NOTE: It takes 72 multiplication to calculate 4x4 matrix determinant
|
||||
result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 +
|
||||
a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 +
|
||||
a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 +
|
||||
a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 +
|
||||
a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 +
|
||||
a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
|
||||
*/
|
||||
// Using Laplace expansion (https://en.wikipedia.org/wiki/Laplace_expansion),
|
||||
// previous operation can be simplified to 40 multiplications, decreasing matrix
|
||||
// size from 4x4 to 2x2 using minors
|
||||
|
||||
// Cache the matrix values (speed optimization)
|
||||
float m0 = mat.m0, m1 = mat.m1, m2 = mat.m2, m3 = mat.m3;
|
||||
float m4 = mat.m4, m5 = mat.m5, m6 = mat.m6, m7 = mat.m7;
|
||||
float m8 = mat.m8, m9 = mat.m9, m10 = mat.m10, m11 = mat.m11;
|
||||
float m12 = mat.m12, m13 = mat.m13, m14 = mat.m14, m15 = mat.m15;
|
||||
|
||||
result = (m0*((m5*(m10*m15 - m11*m14) - m9*(m6*m15 - m7*m14) + m13*(m6*m11 - m7*m10))) -
|
||||
m4*((m1*(m10*m15 - m11*m14) - m9*(m2*m15 - m3*m14) + m13*(m2*m11 - m3*m10))) +
|
||||
m8*((m1*(m6*m15 - m7*m14) - m5*(m2*m15 - m3*m14) + m13*(m2*m7 - m3*m6))) -
|
||||
m12*((m1*(m6*m11 - m7*m10) - m5*(m2*m11 - m3*m10) + m9*(m2*m7 - m3*m6))));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -2648,7 +2673,7 @@ inline Vector2 operator * (const Vector2& lhs, const Matrix& rhs)
|
|||
return Vector2Transform(lhs, rhs);
|
||||
}
|
||||
|
||||
inline const Vector2& operator -= (Vector2& lhs, const Matrix& rhs)
|
||||
inline const Vector2& operator *= (Vector2& lhs, const Matrix& rhs)
|
||||
{
|
||||
lhs = Vector2Transform(lhs, rhs);
|
||||
return lhs;
|
||||
|
@ -2656,12 +2681,12 @@ inline const Vector2& operator -= (Vector2& lhs, const Matrix& rhs)
|
|||
|
||||
inline Vector2 operator / (const Vector2& lhs, const float& rhs)
|
||||
{
|
||||
return Vector2Scale(lhs, 1.0f / rhs);
|
||||
return Vector2Scale(lhs, 1.0f/rhs);
|
||||
}
|
||||
|
||||
inline const Vector2& operator /= (Vector2& lhs, const float& rhs)
|
||||
{
|
||||
lhs = Vector2Scale(lhs, rhs);
|
||||
lhs = Vector2Scale(lhs, 1.0f/rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
|
@ -2742,7 +2767,7 @@ inline Vector3 operator * (const Vector3& lhs, const Matrix& rhs)
|
|||
return Vector3Transform(lhs, rhs);
|
||||
}
|
||||
|
||||
inline const Vector3& operator -= (Vector3& lhs, const Matrix& rhs)
|
||||
inline const Vector3& operator *= (Vector3& lhs, const Matrix& rhs)
|
||||
{
|
||||
lhs = Vector3Transform(lhs, rhs);
|
||||
return lhs;
|
||||
|
@ -2750,12 +2775,12 @@ inline const Vector3& operator -= (Vector3& lhs, const Matrix& rhs)
|
|||
|
||||
inline Vector3 operator / (const Vector3& lhs, const float& rhs)
|
||||
{
|
||||
return Vector3Scale(lhs, 1.0f / rhs);
|
||||
return Vector3Scale(lhs, 1.0f/rhs);
|
||||
}
|
||||
|
||||
inline const Vector3& operator /= (Vector3& lhs, const float& rhs)
|
||||
{
|
||||
lhs = Vector3Scale(lhs, rhs);
|
||||
lhs = Vector3Scale(lhs, 1.0f/rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
|
@ -2834,12 +2859,12 @@ inline const Vector4& operator *= (Vector4& lhs, const Vector4& rhs)
|
|||
|
||||
inline Vector4 operator / (const Vector4& lhs, const float& rhs)
|
||||
{
|
||||
return Vector4Scale(lhs, 1.0f / rhs);
|
||||
return Vector4Scale(lhs, 1.0f/rhs);
|
||||
}
|
||||
|
||||
inline const Vector4& operator /= (Vector4& lhs, const float& rhs)
|
||||
{
|
||||
lhs = Vector4Scale(lhs, rhs);
|
||||
lhs = Vector4Scale(lhs, 1.0f/rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2022-2024 Christoph Wagner (@Crydsch) & Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2022-2025 Christoph Wagner (@Crydsch) & Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -154,7 +154,7 @@ RLAPI void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAr
|
|||
RLAPI void CameraRoll(Camera *camera, float angle);
|
||||
|
||||
RLAPI Matrix GetCameraViewMatrix(Camera *camera);
|
||||
RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
|
||||
RLAPI Matrix GetCameraProjectionMatrix(Camera *camera, float aspect);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
386
raylib/rcore.c
386
raylib/rcore.c
|
@ -12,6 +12,13 @@
|
|||
* - Windows (Win32, Win64)
|
||||
* - Linux (X11/Wayland desktop mode)
|
||||
* - Others (not tested)
|
||||
* > PLATFORM_DESKTOP_RGFW (RGFW backend):
|
||||
* - Windows (Win32, Win64)
|
||||
* - Linux (X11/Wayland desktop mode)
|
||||
* - macOS/OSX (x64, arm64)
|
||||
* - Others (not tested)
|
||||
* > PLATFORM_WEB_RGFW:
|
||||
* - HTML5 (WebAssembly)
|
||||
* > PLATFORM_WEB:
|
||||
* - HTML5 (WebAssembly)
|
||||
* > PLATFORM_DRM:
|
||||
|
@ -63,7 +70,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) and contributors
|
||||
*
|
||||
* 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.
|
||||
|
@ -85,12 +92,12 @@
|
|||
//----------------------------------------------------------------------------------
|
||||
// Feature Test Macros required for this module
|
||||
//----------------------------------------------------------------------------------
|
||||
#if (defined(__linux__) || defined(PLATFORM_WEB)) && (_XOPEN_SOURCE < 500)
|
||||
#if (defined(__linux__) || defined(PLATFORM_WEB) || defined(PLATFORM_WEB_RGFW)) && (_XOPEN_SOURCE < 500)
|
||||
#undef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 500 // Required for: readlink if compiled with c99 without gnu ext.
|
||||
#endif
|
||||
|
||||
#if (defined(__linux__) || defined(PLATFORM_WEB)) && (_POSIX_C_SOURCE < 199309L)
|
||||
#if (defined(__linux__) || defined(PLATFORM_WEB) || defined(PLATFORM_WEB_RGFW)) && (_POSIX_C_SOURCE < 199309L)
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 199309L // Required for: CLOCK_MONOTONIC if compiled with c99 without gnu ext.
|
||||
#endif
|
||||
|
@ -158,9 +165,10 @@
|
|||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 1025
|
||||
#endif
|
||||
__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);
|
||||
struct HINSTANCE__;
|
||||
__declspec(dllimport) unsigned long __stdcall GetModuleFileNameA(struct HINSTANCE__ *hModule, char *lpFilename, unsigned long nSize);
|
||||
__declspec(dllimport) unsigned long __stdcall GetModuleFileNameW(struct HINSTANCE__ *hModule, wchar_t *lpFilename, unsigned long nSize);
|
||||
__declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default);
|
||||
__declspec(dllimport) unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);
|
||||
__declspec(dllimport) unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
|
||||
#elif defined(__linux__)
|
||||
|
@ -226,8 +234,11 @@ __declspec(dllimport) unsigned int __stdcall timeEndPeriod(unsigned int uPeriod)
|
|||
#ifndef MAX_GAMEPADS
|
||||
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported
|
||||
#endif
|
||||
#ifndef MAX_GAMEPAD_AXIS
|
||||
#define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
|
||||
#ifndef MAX_GAMEPAD_NAME_LENGTH
|
||||
#define MAX_GAMEPAD_NAME_LENGTH 128 // Maximum number of characters in a gamepad name (byte size)
|
||||
#endif
|
||||
#ifndef MAX_GAMEPAD_AXES
|
||||
#define MAX_GAMEPAD_AXES 8 // Maximum number of axes supported (per gamepad)
|
||||
#endif
|
||||
#ifndef MAX_GAMEPAD_BUTTONS
|
||||
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
||||
|
@ -343,12 +354,12 @@ typedef struct CoreData {
|
|||
} Touch;
|
||||
struct {
|
||||
int lastButtonPressed; // Register last gamepad button pressed
|
||||
int axisCount[MAX_GAMEPADS]; // Register number of available gamepad axis
|
||||
int axisCount[MAX_GAMEPADS]; // Register number of available gamepad axes
|
||||
bool ready[MAX_GAMEPADS]; // Flag to know if gamepad is ready
|
||||
char name[MAX_GAMEPADS][64]; // Gamepad name holder
|
||||
char name[MAX_GAMEPADS][MAX_GAMEPAD_NAME_LENGTH]; // Gamepad name holder
|
||||
char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
|
||||
char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
|
||||
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
|
||||
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXES]; // Gamepad axes state
|
||||
|
||||
} Gamepad;
|
||||
} Input;
|
||||
|
@ -501,7 +512,7 @@ static void RecordAutomationEvent(void); // Record frame events (to internal eve
|
|||
|
||||
#if defined(_WIN32) && !defined(PLATFORM_DESKTOP_RGFW)
|
||||
// NOTE: We declare Sleep() function symbol to avoid including windows.h (kernel32.lib linkage required)
|
||||
void __stdcall Sleep(unsigned long msTimeout); // Required for: WaitTime()
|
||||
__declspec(dllimport) void __stdcall Sleep(unsigned long msTimeout); // Required for: WaitTime()
|
||||
#endif
|
||||
|
||||
#if !defined(SUPPORT_MODULE_RTEXT)
|
||||
|
@ -512,25 +523,25 @@ const char *TextFormat(const char *text, ...); // Formatting of tex
|
|||
#define PLATFORM_DESKTOP_GLFW
|
||||
#endif
|
||||
|
||||
// We're using `#pragma message` because `#warning` is not adopted by MSVC.
|
||||
// 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")
|
||||
#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")
|
||||
#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.
|
||||
// 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")
|
||||
#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.
|
||||
// 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"
|
||||
// #pragma message ("WARNING: "STBI_REQUIRED is not defined, that means we can't load images from clipbard"
|
||||
// #endif
|
||||
|
||||
#endif // SUPPORT_CLIPBOARD_IMAGE
|
||||
|
@ -540,7 +551,7 @@ const char *TextFormat(const char *text, ...); // Formatting of tex
|
|||
#include "platforms/rcore_desktop_glfw.c"
|
||||
#elif defined(PLATFORM_DESKTOP_SDL)
|
||||
#include "platforms/rcore_desktop_sdl.c"
|
||||
#elif defined(PLATFORM_DESKTOP_RGFW)
|
||||
#elif (defined(PLATFORM_DESKTOP_RGFW) || defined(PLATFORM_WEB_RGFW))
|
||||
#include "platforms/rcore_desktop_rgfw.c"
|
||||
#elif defined(PLATFORM_WEB)
|
||||
#include "platforms/rcore_web.c"
|
||||
|
@ -611,6 +622,8 @@ void InitWindow(int width, int height, const char *title)
|
|||
TRACELOG(LOG_INFO, "Platform backend: DESKTOP (SDL)");
|
||||
#elif defined(PLATFORM_DESKTOP_RGFW)
|
||||
TRACELOG(LOG_INFO, "Platform backend: DESKTOP (RGFW)");
|
||||
#elif defined(PLATFORM_WEB_RGFW)
|
||||
TRACELOG(LOG_INFO, "Platform backend: WEB (RGFW) (HTML5)");
|
||||
#elif defined(PLATFORM_WEB)
|
||||
TRACELOG(LOG_INFO, "Platform backend: WEB (HTML5)");
|
||||
#elif defined(PLATFORM_DRM)
|
||||
|
@ -668,7 +681,13 @@ void InitWindow(int width, int height, const char *title)
|
|||
|
||||
// Initialize platform
|
||||
//--------------------------------------------------------------
|
||||
InitPlatform();
|
||||
int result = InitPlatform();
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "SYSTEM: Failed to initialize Platform");
|
||||
return;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
|
||||
// Initialize rlgl default data (buffers and shaders)
|
||||
|
@ -1100,7 +1119,7 @@ void BeginTextureMode(RenderTexture2D target)
|
|||
//rlScalef(0.0f, -1.0f, 0.0f); // Flip Y-drawing (?)
|
||||
|
||||
// Setup current width/height for proper aspect ratio
|
||||
// calculation when using BeginMode3D()
|
||||
// calculation when using BeginTextureMode()
|
||||
CORE.Window.currentFbo.width = target.texture.width;
|
||||
CORE.Window.currentFbo.height = target.texture.height;
|
||||
CORE.Window.usingFbo = true;
|
||||
|
@ -1302,6 +1321,8 @@ Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
|||
if (vsFileName != NULL) vShaderStr = LoadFileText(vsFileName);
|
||||
if (fsFileName != NULL) fShaderStr = LoadFileText(fsFileName);
|
||||
|
||||
if ((vShaderStr == NULL) && (fShaderStr == NULL)) TraceLog(LOG_WARNING, "SHADER: Shader files provided are not valid, using default shader");
|
||||
|
||||
shader = LoadShaderFromMemory(vShaderStr, fShaderStr);
|
||||
|
||||
UnloadFileText(vShaderStr);
|
||||
|
@ -1317,9 +1338,10 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
|
|||
|
||||
shader.id = rlLoadShaderCode(vsCode, fsCode);
|
||||
|
||||
// After shader loading, we TRY to set default location names
|
||||
if (shader.id > 0)
|
||||
if (shader.id == rlGetShaderIdDefault()) shader.locs = rlGetShaderLocsDefault();
|
||||
else if (shader.id > 0)
|
||||
{
|
||||
// After custom shader loading, we TRY to set default location names
|
||||
// Default shader attribute locations have been binded before linking:
|
||||
// vertex position location = 0
|
||||
// vertex texcoord location = 1
|
||||
|
@ -1346,6 +1368,7 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
|
|||
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);
|
||||
shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX);
|
||||
|
||||
// Get handles to GLSL uniform locations (vertex shader)
|
||||
shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP);
|
||||
|
@ -1856,12 +1879,15 @@ void TakeScreenshot(const char *fileName)
|
|||
// Security check to (partially) avoid malicious code
|
||||
if (strchr(fileName, '\'') != NULL) { TRACELOG(LOG_WARNING, "SYSTEM: Provided fileName could be potentially malicious, avoid [\'] character"); return; }
|
||||
|
||||
Vector2 scale = GetWindowScaleDPI();
|
||||
// Apply a scale if we are doing HIGHDPI auto-scaling
|
||||
Vector2 scale = { 1.0f, 1.0f };
|
||||
if (IsWindowState(FLAG_WINDOW_HIGHDPI)) scale = GetWindowScaleDPI();
|
||||
|
||||
unsigned char *imgData = rlReadScreenPixels((int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y));
|
||||
Image image = { imgData, (int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y), 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
||||
|
||||
char path[512] = { 0 };
|
||||
strcpy(path, TextFormat("%s/%s", CORE.Storage.basePath, GetFileName(fileName)));
|
||||
strcpy(path, TextFormat("%s/%s", CORE.Storage.basePath, fileName));
|
||||
|
||||
ExportImage(image, path); // WARNING: Module required: rtextures
|
||||
RL_FREE(imgData);
|
||||
|
@ -1879,6 +1905,8 @@ void TakeScreenshot(const char *fileName)
|
|||
// To configure window states after creation, just use SetWindowState()
|
||||
void SetConfigFlags(unsigned int flags)
|
||||
{
|
||||
if (CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetConfigFlags called after window initialization, Use \"SetWindowState\" to set flags instead");
|
||||
|
||||
// Selected flags are set but not evaluated at this point,
|
||||
// flag evaluation happens at InitWindow() or SetWindowState()
|
||||
CORE.Window.flags |= flags;
|
||||
|
@ -1920,7 +1948,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
|
|||
{
|
||||
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_TEXT_MANIPULATION)
|
||||
int extCount = 0;
|
||||
const char **checkExts = TextSplit(ext, ';', &extCount); // WARNING: Module required: rtext
|
||||
char **checkExts = TextSplit(ext, ';', &extCount); // WARNING: Module required: rtext
|
||||
|
||||
char fileExtLower[MAX_FILE_EXTENSION_LENGTH + 1] = { 0 };
|
||||
strncpy(fileExtLower, TextToLower(fileExt), MAX_FILE_EXTENSION_LENGTH); // WARNING: Module required: rtext
|
||||
|
@ -2062,7 +2090,7 @@ const char *GetDirectoryPath(const char *filePath)
|
|||
|
||||
// In case provided path does not contain a root drive letter (C:\, D:\) nor leading path separator (\, /),
|
||||
// we add the current directory path to dirPath
|
||||
if (filePath[1] != ':' && filePath[0] != '\\' && filePath[0] != '/')
|
||||
if ((filePath[1] != ':') && (filePath[0] != '\\') && (filePath[0] != '/'))
|
||||
{
|
||||
// For security, we set starting path to current directory,
|
||||
// obtained path will be concatenated to this
|
||||
|
@ -2286,9 +2314,12 @@ FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool
|
|||
// WARNING: files.count is not reseted to 0 after unloading
|
||||
void UnloadDirectoryFiles(FilePathList files)
|
||||
{
|
||||
for (unsigned int i = 0; i < files.capacity; i++) RL_FREE(files.paths[i]);
|
||||
if (files.paths != NULL)
|
||||
{
|
||||
for (unsigned int i = 0; i < files.capacity; i++) RL_FREE(files.paths[i]);
|
||||
|
||||
RL_FREE(files.paths);
|
||||
RL_FREE(files.paths);
|
||||
}
|
||||
}
|
||||
|
||||
// Create directories (including full path requested), returns 0 on success
|
||||
|
@ -2331,6 +2362,7 @@ bool ChangeDirectory(const char *dir)
|
|||
bool result = CHDIR(dir);
|
||||
|
||||
if (result != 0) TRACELOG(LOG_WARNING, "SYSTEM: Failed to change to directory: %s", dir);
|
||||
else TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", dir);
|
||||
|
||||
return (result == 0);
|
||||
}
|
||||
|
@ -2468,7 +2500,7 @@ unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDa
|
|||
|
||||
#if defined(SUPPORT_COMPRESSION_API)
|
||||
// Compress data and generate a valid DEFLATE stream
|
||||
struct sdefl *sdefl = RL_CALLOC(1, sizeof(struct sdefl)); // WARNING: Possible stack overflow, struct sdefl is almost 1MB
|
||||
struct sdefl *sdefl = (struct sdefl *)RL_CALLOC(1, sizeof(struct sdefl)); // WARNING: Possible stack overflow, struct sdefl is almost 1MB
|
||||
int bounds = sdefl_bound(dataSize);
|
||||
compData = (unsigned char *)RL_CALLOC(bounds, 1);
|
||||
|
||||
|
@ -2507,96 +2539,112 @@ unsigned char *DecompressData(const unsigned char *compData, int compDataSize, i
|
|||
}
|
||||
|
||||
// Encode data to Base64 string
|
||||
// NOTE: Returned string includes NULL terminator, considered on outputSize
|
||||
char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize)
|
||||
{
|
||||
static const unsigned char base64encodeTable[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
// Base64 conversion table from RFC 4648 [0..63]
|
||||
// NOTE: They represent 64 values (6 bits), to encode 3 bytes of data into 4 "sixtets" (6bit characters)
|
||||
static const char base64EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static const int modTable[] = { 0, 2, 1 };
|
||||
// Compute expected size and padding
|
||||
int paddedSize = dataSize;
|
||||
while (paddedSize%3 != 0) paddedSize++; // Padding bytes to round 4*(dataSize/3) to 4 bytes
|
||||
int estimatedOutputSize = 4*(paddedSize/3);
|
||||
int padding = paddedSize - dataSize;
|
||||
|
||||
*outputSize = 4*((dataSize + 2)/3);
|
||||
// Adding null terminator to string
|
||||
estimatedOutputSize += 1;
|
||||
|
||||
char *encodedData = (char *)RL_MALLOC(*outputSize);
|
||||
// Load some memory to store encoded string
|
||||
char *encodedData = (char *)RL_CALLOC(estimatedOutputSize, 1);
|
||||
if (encodedData == NULL) return NULL;
|
||||
|
||||
if (encodedData == NULL) return NULL; // Security check
|
||||
|
||||
for (int i = 0, j = 0; i < dataSize;)
|
||||
int outputCount = 0;
|
||||
for (int i = 0; i < dataSize;)
|
||||
{
|
||||
unsigned int octetA = (i < dataSize)? (unsigned char)data[i++] : 0;
|
||||
unsigned int octetB = (i < dataSize)? (unsigned char)data[i++] : 0;
|
||||
unsigned int octetC = (i < dataSize)? (unsigned char)data[i++] : 0;
|
||||
unsigned int octetA = 0;
|
||||
unsigned int octetB = 0;
|
||||
unsigned int octetC = 0;
|
||||
unsigned int octetPack = 0;
|
||||
|
||||
unsigned int triple = (octetA << 0x10) + (octetB << 0x08) + octetC;
|
||||
octetA = data[i]; // Generates 2 sextets
|
||||
octetB = ((i + 1) < dataSize)? data[i + 1] : 0; // Generates 3 sextets
|
||||
octetC = ((i + 2) < dataSize)? data[i + 2] : 0; // Generates 4 sextets
|
||||
|
||||
encodedData[j++] = base64encodeTable[(triple >> 3*6) & 0x3F];
|
||||
encodedData[j++] = base64encodeTable[(triple >> 2*6) & 0x3F];
|
||||
encodedData[j++] = base64encodeTable[(triple >> 1*6) & 0x3F];
|
||||
encodedData[j++] = base64encodeTable[(triple >> 0*6) & 0x3F];
|
||||
octetPack = (octetA << 16) | (octetB << 8) | octetC;
|
||||
|
||||
encodedData[outputCount + 0] = (unsigned char)(base64EncodeTable[(octetPack >> 18) & 0x3f]);
|
||||
encodedData[outputCount + 1] = (unsigned char)(base64EncodeTable[(octetPack >> 12) & 0x3f]);
|
||||
encodedData[outputCount + 2] = (unsigned char)(base64EncodeTable[(octetPack >> 6) & 0x3f]);
|
||||
encodedData[outputCount + 3] = (unsigned char)(base64EncodeTable[octetPack & 0x3f]);
|
||||
outputCount += 4;
|
||||
i += 3;
|
||||
}
|
||||
|
||||
for (int i = 0; i < modTable[dataSize%3]; i++) encodedData[*outputSize - 1 - i] = '='; // Padding character
|
||||
// Add required padding bytes
|
||||
for (int p = 0; p < padding; p++) encodedData[outputCount - p - 1] = '=';
|
||||
|
||||
// Add null terminator to string
|
||||
encodedData[outputCount] = '\0';
|
||||
outputCount++;
|
||||
|
||||
if (outputCount != estimatedOutputSize) TRACELOG(LOG_WARNING, "BASE64: Output size differs from estimation");
|
||||
|
||||
*outputSize = estimatedOutputSize;
|
||||
return encodedData;
|
||||
}
|
||||
|
||||
// Decode Base64 string data
|
||||
unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
|
||||
// Decode Base64 string (expected NULL terminated)
|
||||
unsigned char *DecodeDataBase64(const char *text, int *outputSize)
|
||||
{
|
||||
static const unsigned char base64decodeTable[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
|
||||
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
||||
// Base64 decode table
|
||||
// NOTE: Following ASCII order [0..255] assigning the expected sixtet value to
|
||||
// every character in the corresponding ASCII position
|
||||
static const unsigned char base64DecodeTable[256] = {
|
||||
['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7,
|
||||
['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15,
|
||||
['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19, ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, ['Y'] = 24, ['Z'] = 25,
|
||||
['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29, ['e'] = 30, ['f'] = 31, ['g'] = 32, ['h'] = 33,
|
||||
['i'] = 34, ['j'] = 35, ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39, ['o'] = 40, ['p'] = 41,
|
||||
['q'] = 42, ['r'] = 43, ['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47, ['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51,
|
||||
['0'] = 52, ['1'] = 53, ['2'] = 54, ['3'] = 55, ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59,
|
||||
['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63
|
||||
};
|
||||
|
||||
// Get output size of Base64 input data
|
||||
int outSize = 0;
|
||||
for (int i = 0; data[4*i] != 0; i++)
|
||||
// Compute expected size and padding
|
||||
int dataSize = (int)strlen(text); // WARNING: Expecting NULL terminated strings!
|
||||
int ending = dataSize - 1;
|
||||
int padding = 0;
|
||||
while (text[ending] == '=') { padding++; ending--; }
|
||||
int estimatedOutputSize = 3*(dataSize/4) - padding;
|
||||
int maxOutputSize = 3*(dataSize/4);
|
||||
|
||||
// Load some memory to store decoded data
|
||||
// NOTE: Allocated enough size to include padding
|
||||
unsigned char *decodedData = (unsigned char *)RL_CALLOC(maxOutputSize, 1);
|
||||
if (decodedData == NULL) return NULL;
|
||||
|
||||
int outputCount = 0;
|
||||
for (int i = 0; i < dataSize;)
|
||||
{
|
||||
if (data[4*i + 3] == '=')
|
||||
{
|
||||
if (data[4*i + 2] == '=') outSize += 1;
|
||||
else outSize += 2;
|
||||
}
|
||||
else outSize += 3;
|
||||
// Every 4 sixtets must generate 3 octets
|
||||
unsigned int sixtetA = base64DecodeTable[(unsigned char)text[i]];
|
||||
unsigned int sixtetB = base64DecodeTable[(unsigned char)text[i + 1]];
|
||||
unsigned int sixtetC = ((unsigned char)text[i + 2] != '=')? base64DecodeTable[(unsigned char)text[i + 2]] : 0;
|
||||
unsigned int sixtetD = ((unsigned char)text[i + 3] != '=')? base64DecodeTable[(unsigned char)text[i + 3]] : 0;
|
||||
|
||||
unsigned int octetPack = (sixtetA << 18) | (sixtetB << 12) | (sixtetC << 6) | sixtetD;
|
||||
|
||||
decodedData[outputCount + 0] = (octetPack >> 16) & 0xff;
|
||||
decodedData[outputCount + 1] = (octetPack >> 8) & 0xff;
|
||||
decodedData[outputCount + 2] = octetPack & 0xff;
|
||||
outputCount += 3;
|
||||
i += 4;
|
||||
}
|
||||
|
||||
// Allocate memory to store decoded Base64 data
|
||||
unsigned char *decodedData = (unsigned char *)RL_MALLOC(outSize);
|
||||
if (estimatedOutputSize != (outputCount - padding)) TRACELOG(LOG_WARNING, "BASE64: Decoded size differs from estimation");
|
||||
|
||||
for (int i = 0; i < outSize/3; i++)
|
||||
{
|
||||
unsigned char a = base64decodeTable[(int)data[4*i]];
|
||||
unsigned char b = base64decodeTable[(int)data[4*i + 1]];
|
||||
unsigned char c = base64decodeTable[(int)data[4*i + 2]];
|
||||
unsigned char d = base64decodeTable[(int)data[4*i + 3]];
|
||||
|
||||
decodedData[3*i] = (a << 2) | (b >> 4);
|
||||
decodedData[3*i + 1] = (b << 4) | (c >> 2);
|
||||
decodedData[3*i + 2] = (c << 6) | d;
|
||||
}
|
||||
|
||||
if (outSize%3 == 1)
|
||||
{
|
||||
int n = outSize/3;
|
||||
unsigned char a = base64decodeTable[(int)data[4*n]];
|
||||
unsigned char b = base64decodeTable[(int)data[4*n + 1]];
|
||||
decodedData[outSize - 1] = (a << 2) | (b >> 4);
|
||||
}
|
||||
else if (outSize%3 == 2)
|
||||
{
|
||||
int n = outSize/3;
|
||||
unsigned char a = base64decodeTable[(int)data[4*n]];
|
||||
unsigned char b = base64decodeTable[(int)data[4*n + 1]];
|
||||
unsigned char c = base64decodeTable[(int)data[4*n + 2]];
|
||||
decodedData[outSize - 2] = (a << 2) | (b >> 4);
|
||||
decodedData[outSize - 1] = (b << 4) | (c >> 2);
|
||||
}
|
||||
|
||||
*outputSize = outSize;
|
||||
*outputSize = estimatedOutputSize;
|
||||
return decodedData;
|
||||
}
|
||||
|
||||
|
@ -2604,38 +2652,38 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
|
|||
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
|
||||
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;
|
||||
|
@ -2699,7 +2747,7 @@ unsigned int *ComputeMD5(unsigned char *data, int dataSize)
|
|||
|
||||
int newDataSize = ((((dataSize + 8)/64) + 1)*64) - 8;
|
||||
|
||||
unsigned char *msg = RL_CALLOC(newDataSize + 64, 1); // Initialize with '0' bits, allocating 64 extra bytes
|
||||
unsigned char *msg = (unsigned char *)RL_CALLOC(newDataSize + 64, 1); // Initialize with '0' bits, allocating 64 extra bytes
|
||||
memcpy(msg, data, dataSize);
|
||||
msg[dataSize] = 128; // Write the '1' bit
|
||||
|
||||
|
@ -2765,7 +2813,8 @@ unsigned int *ComputeMD5(unsigned char *data, int dataSize)
|
|||
|
||||
// Compute SHA-1 hash code
|
||||
// NOTE: Returns a static int[5] array (20 bytes)
|
||||
unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
|
||||
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
|
||||
|
@ -2788,7 +2837,7 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
|
|||
|
||||
int newDataSize = ((((dataSize + 8)/64) + 1)*64);
|
||||
|
||||
unsigned char *msg = RL_CALLOC(newDataSize, 1); // Initialize with '0' bits
|
||||
unsigned char *msg = (unsigned char *)RL_CALLOC(newDataSize, 1); // Initialize with '0' bits
|
||||
memcpy(msg, data, dataSize);
|
||||
msg[dataSize] = 128; // Write the '1' bit
|
||||
|
||||
|
@ -2800,17 +2849,16 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
|
|||
{
|
||||
// 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]);
|
||||
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);
|
||||
}
|
||||
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];
|
||||
|
@ -2824,16 +2872,23 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
|
|||
unsigned int f = 0;
|
||||
unsigned int k = 0;
|
||||
|
||||
if (i < 20) {
|
||||
if (i < 20)
|
||||
{
|
||||
f = (b & c) | ((~b) & d);
|
||||
k = 0x5A827999;
|
||||
} else if (i < 40) {
|
||||
}
|
||||
else if (i < 40)
|
||||
{
|
||||
f = b ^ c ^ d;
|
||||
k = 0x6ED9EBA1;
|
||||
} else if (i < 60) {
|
||||
}
|
||||
else if (i < 60)
|
||||
{
|
||||
f = (b & c) | (b & d) | (c & d);
|
||||
k = 0x8F1BBCDC;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
f = b ^ c ^ d;
|
||||
k = 0xCA62C1D6;
|
||||
}
|
||||
|
@ -2982,7 +3037,7 @@ bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
|||
byteCount += sprintf(txtData + byteCount, "# more info and bugs-report: github.com/raysan5/raylib\n");
|
||||
byteCount += sprintf(txtData + byteCount, "# feedback and support: ray[at]raylib.com\n");
|
||||
byteCount += sprintf(txtData + byteCount, "#\n");
|
||||
byteCount += sprintf(txtData + byteCount, "# Copyright (c) 2023-2024 Ramon Santamaria (@raysan5)\n");
|
||||
byteCount += sprintf(txtData + byteCount, "# Copyright (c) 2023-2025 Ramon Santamaria (@raysan5)\n");
|
||||
byteCount += sprintf(txtData + byteCount, "#\n\n");
|
||||
|
||||
// Add events data
|
||||
|
@ -3313,10 +3368,11 @@ int GetGamepadAxisCount(int gamepad)
|
|||
// Get axis movement vector for a gamepad
|
||||
float GetGamepadAxisMovement(int gamepad, int axis)
|
||||
{
|
||||
float value = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f;
|
||||
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)) {
|
||||
float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]);
|
||||
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXES))
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
@ -3657,12 +3713,16 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
|
|||
(strcmp(dp->d_name, "..") != 0))
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
sprintf(path, "%s\\%s", basePath, dp->d_name);
|
||||
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", basePath, dp->d_name);
|
||||
#else
|
||||
sprintf(path, "%s/%s", basePath, dp->d_name);
|
||||
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", basePath, dp->d_name);
|
||||
#endif
|
||||
|
||||
if (filter != NULL)
|
||||
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH))
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "FILEIO: Path longer than %d characters (%s...)", MAX_FILEPATH_LENGTH, basePath);
|
||||
}
|
||||
else if (filter != NULL)
|
||||
{
|
||||
if (IsPathFile(path))
|
||||
{
|
||||
|
@ -3674,7 +3734,7 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
|
|||
}
|
||||
else
|
||||
{
|
||||
if (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0)
|
||||
if (strstr(filter, DIRECTORY_FILTER_TAG) != NULL)
|
||||
{
|
||||
strcpy(files->paths[files->count], path);
|
||||
files->count++;
|
||||
|
@ -3697,7 +3757,7 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
|
|||
// Scan all files and directories recursively from a base path
|
||||
static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *files, const char *filter)
|
||||
{
|
||||
char path[MAX_FILEPATH_LENGTH] = { 0 };
|
||||
static char path[MAX_FILEPATH_LENGTH] = { 0 };
|
||||
memset(path, 0, MAX_FILEPATH_LENGTH);
|
||||
|
||||
struct dirent *dp = NULL;
|
||||
|
@ -3711,12 +3771,16 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi
|
|||
{
|
||||
// Construct new path from our base path
|
||||
#if defined(_WIN32)
|
||||
sprintf(path, "%s\\%s", basePath, dp->d_name);
|
||||
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", basePath, dp->d_name);
|
||||
#else
|
||||
sprintf(path, "%s/%s", basePath, dp->d_name);
|
||||
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", basePath, dp->d_name);
|
||||
#endif
|
||||
|
||||
if (IsPathFile(path))
|
||||
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH))
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "FILEIO: Path longer than %d characters (%s...)", MAX_FILEPATH_LENGTH, basePath);
|
||||
}
|
||||
else if (IsPathFile(path))
|
||||
{
|
||||
if (filter != NULL)
|
||||
{
|
||||
|
@ -3740,7 +3804,7 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi
|
|||
}
|
||||
else
|
||||
{
|
||||
if ((filter != NULL) && (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0))
|
||||
if ((filter != NULL) && (strstr(filter, DIRECTORY_FILTER_TAG) != NULL))
|
||||
{
|
||||
strcpy(files->paths[files->count], path);
|
||||
files->count++;
|
||||
|
@ -3986,10 +4050,10 @@ static void RecordAutomationEvent(void)
|
|||
if (currentEventList->count == currentEventList->capacity) return; // Security check
|
||||
}
|
||||
|
||||
for (int axis = 0; axis < MAX_GAMEPAD_AXIS; axis++)
|
||||
for (int axis = 0; axis < MAX_GAMEPAD_AXES; axis++)
|
||||
{
|
||||
// Event type: INPUT_GAMEPAD_AXIS_MOTION
|
||||
float defaultMovement = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f;
|
||||
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;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
|
106
raylib/rlgl.h
106
raylib/rlgl.h
|
@ -3,14 +3,14 @@
|
|||
* rlgl v5.0 - A multi-OpenGL abstraction layer with an immediate-mode style API
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0)
|
||||
* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0, ES 3.0)
|
||||
* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...)
|
||||
*
|
||||
* ADDITIONAL NOTES:
|
||||
* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are
|
||||
* initialized on rlglInit() to accumulate vertex data
|
||||
*
|
||||
* When an internal state change is required all the stored vertex data is renderer in batch,
|
||||
* When an internal state change is required all the stored vertex data is rendered in batch,
|
||||
* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch
|
||||
*
|
||||
* Some resources are also loaded for convenience, here the complete list:
|
||||
|
@ -56,8 +56,8 @@
|
|||
*
|
||||
* #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack
|
||||
* #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
|
||||
* #define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance
|
||||
* #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
|
||||
* #define RL_CULL_DISTANCE_NEAR 0.05 // Default projection matrix near cull distance
|
||||
* #define RL_CULL_DISTANCE_FAR 4000.0 // Default projection matrix far cull distance
|
||||
*
|
||||
* When loading a shader, the following vertex attributes and uniform
|
||||
* location names are tried to be set automatically:
|
||||
|
@ -88,7 +88,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -234,10 +234,10 @@
|
|||
|
||||
// Projection matrix culling
|
||||
#ifndef RL_CULL_DISTANCE_NEAR
|
||||
#define RL_CULL_DISTANCE_NEAR 0.01 // Default near cull distance
|
||||
#define RL_CULL_DISTANCE_NEAR 0.05 // Default near cull distance
|
||||
#endif
|
||||
#ifndef RL_CULL_DISTANCE_FAR
|
||||
#define RL_CULL_DISTANCE_FAR 1000.0 // Default far cull distance
|
||||
#define RL_CULL_DISTANCE_FAR 4000.0 // Default far cull distance
|
||||
#endif
|
||||
|
||||
// Texture parameters (equivalent to OpenGL defines)
|
||||
|
@ -355,6 +355,9 @@
|
|||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
|
||||
#endif
|
||||
#endif
|
||||
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX
|
||||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX 9
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
|
@ -681,9 +684,10 @@ RLAPI void rlSetCullFace(int mode); // Set face culling mode
|
|||
RLAPI void rlEnableScissorTest(void); // Enable scissor test
|
||||
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 (and point) mode
|
||||
RLAPI void rlDisablePointMode(void); // Disable point mode
|
||||
RLAPI void rlEnableWireMode(void); // Enable wire mode
|
||||
RLAPI void rlDisableWireMode(void); // Disable wire 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
|
||||
|
@ -998,6 +1002,9 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
|||
#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_ATTRIB_NAME_INSTANCE_TX
|
||||
#define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX "instanceTransform" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX
|
||||
#endif
|
||||
|
||||
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP
|
||||
#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
|
||||
|
@ -1741,7 +1748,6 @@ void rlTextureParameters(unsigned int id, int param, int value)
|
|||
#endif
|
||||
}
|
||||
else glTexParameteri(GL_TEXTURE_2D, param, value);
|
||||
|
||||
} break;
|
||||
case RL_TEXTURE_MAG_FILTER:
|
||||
case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_2D, param, value); break;
|
||||
|
@ -1786,7 +1792,6 @@ void rlCubemapParameters(unsigned int id, int param, int value)
|
|||
else TRACELOG(RL_LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)");
|
||||
}
|
||||
else glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value);
|
||||
|
||||
} break;
|
||||
case RL_TEXTURE_MAG_FILTER:
|
||||
case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value); break;
|
||||
|
@ -1884,16 +1889,6 @@ void rlActiveDrawBuffers(int count)
|
|||
else
|
||||
{
|
||||
unsigned int buffers[8] = {
|
||||
#if defined(GRAPHICS_API_OPENGL_ES3)
|
||||
GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_COLOR_ATTACHMENT1_EXT,
|
||||
GL_COLOR_ATTACHMENT2_EXT,
|
||||
GL_COLOR_ATTACHMENT3_EXT,
|
||||
GL_COLOR_ATTACHMENT4_EXT,
|
||||
GL_COLOR_ATTACHMENT5_EXT,
|
||||
GL_COLOR_ATTACHMENT6_EXT,
|
||||
GL_COLOR_ATTACHMENT7_EXT,
|
||||
#else
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
GL_COLOR_ATTACHMENT1,
|
||||
GL_COLOR_ATTACHMENT2,
|
||||
|
@ -1902,14 +1897,9 @@ void rlActiveDrawBuffers(int count)
|
|||
GL_COLOR_ATTACHMENT5,
|
||||
GL_COLOR_ATTACHMENT6,
|
||||
GL_COLOR_ATTACHMENT7,
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_ES3)
|
||||
glDrawBuffersEXT(count, buffers);
|
||||
#else
|
||||
glDrawBuffers(count, buffers);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "GL: One color buffer active by default");
|
||||
|
@ -1976,6 +1966,15 @@ void rlEnableWireMode(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
// Disable wire mode
|
||||
void rlDisableWireMode(void)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
|
||||
// NOTE: glPolygonMode() not available on OpenGL ES
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Enable point mode
|
||||
void rlEnablePointMode(void)
|
||||
{
|
||||
|
@ -1986,8 +1985,8 @@ void rlEnablePointMode(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
// Disable wire mode
|
||||
void rlDisableWireMode(void)
|
||||
// Disable point mode
|
||||
void rlDisablePointMode(void)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
|
||||
// NOTE: glPolygonMode() not available on OpenGL ES
|
||||
|
@ -2111,14 +2110,12 @@ void rlSetBlendMode(int mode)
|
|||
{
|
||||
// NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactors()
|
||||
glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation);
|
||||
|
||||
} break;
|
||||
case RL_BLEND_CUSTOM_SEPARATE:
|
||||
{
|
||||
// NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactorsSeparate()
|
||||
glBlendFuncSeparate(RLGL.State.glBlendSrcFactorRGB, RLGL.State.glBlendDestFactorRGB, RLGL.State.glBlendSrcFactorAlpha, RLGL.State.glBlendDestFactorAlpha);
|
||||
glBlendEquationSeparate(RLGL.State.glBlendEquationRGB, RLGL.State.glBlendEquationAlpha);
|
||||
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
@ -2428,7 +2425,7 @@ void rlLoadExtensions(void *loader)
|
|||
|
||||
// Get supported extensions list
|
||||
GLint numExt = 0;
|
||||
const char **extList = RL_MALLOC(512*sizeof(const char *)); // Allocate 512 strings pointers (2 KB)
|
||||
const char **extList = (const char **)RL_MALLOC(512*sizeof(const char *)); // Allocate 512 strings pointers (2 KB)
|
||||
const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string
|
||||
|
||||
// NOTE: We have to duplicate string because glGetString() returns a const string
|
||||
|
@ -2525,11 +2522,11 @@ void rlLoadExtensions(void *loader)
|
|||
|
||||
// Check depth texture support
|
||||
if (strcmp(extList[i], (const char *)"GL_OES_depth_texture") == 0) RLGL.ExtSupported.texDepth = true;
|
||||
if (strcmp(extList[i], (const char *)"GL_WEBGL_depth_texture") == 0) RLGL.ExtSupported.texDepthWebGL = true; // WebGL requires unsized internal format
|
||||
if (strcmp(extList[i], (const char *)"GL_WEBGL_depth_texture") == 0) RLGL.ExtSupported.texDepthWebGL = true; // WebGL requires unsized internal format
|
||||
if (RLGL.ExtSupported.texDepthWebGL) RLGL.ExtSupported.texDepth = true;
|
||||
|
||||
if (strcmp(extList[i], (const char *)"GL_OES_depth24") == 0) RLGL.ExtSupported.maxDepthBits = 24; // Not available on WebGL
|
||||
if (strcmp(extList[i], (const char *)"GL_OES_depth32") == 0) RLGL.ExtSupported.maxDepthBits = 32; // Not available on WebGL
|
||||
if (strcmp(extList[i], (const char *)"GL_OES_depth24") == 0) RLGL.ExtSupported.maxDepthBits = 24; // Not available on WebGL
|
||||
if (strcmp(extList[i], (const char *)"GL_OES_depth32") == 0) RLGL.ExtSupported.maxDepthBits = 32; // Not available on WebGL
|
||||
|
||||
// Check texture compression support: DXT
|
||||
if ((strcmp(extList[i], (const char *)"GL_EXT_texture_compression_s3tc") == 0) ||
|
||||
|
@ -3054,7 +3051,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
|
|||
|
||||
for (int i = 0, vertexOffset = 0; i < batch->drawCounter; i++)
|
||||
{
|
||||
// Bind current draw call texture, activated as GL_TEXTURE0 and Bound to sampler2D texture0 by default
|
||||
// Bind current draw call texture, activated as GL_TEXTURE0 and bound to sampler2D texture0 by default
|
||||
glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId);
|
||||
|
||||
if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount);
|
||||
|
@ -3310,6 +3307,7 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
|
|||
// Activate Trilinear filtering if mipmaps are available
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmapCount); // Required for user-defined mip count
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3674,29 +3672,37 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
|
|||
// Read screen pixel data (color buffer)
|
||||
unsigned char *rlReadScreenPixels(int width, int height)
|
||||
{
|
||||
unsigned char *screenData = (unsigned char *)RL_CALLOC(width*height*4, sizeof(unsigned char));
|
||||
unsigned char *imgData = (unsigned char *)RL_CALLOC(width*height*4, sizeof(unsigned char));
|
||||
|
||||
// NOTE 1: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
|
||||
// NOTE 2: We are getting alpha channel! Be careful, it can be transparent if not cleared properly!
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, imgData);
|
||||
|
||||
// Flip image vertically!
|
||||
unsigned char *imgData = (unsigned char *)RL_MALLOC(width*height*4*sizeof(unsigned char));
|
||||
|
||||
for (int y = height - 1; y >= 0; y--)
|
||||
// NOTE: Alpha value has already been applied to RGB in framebuffer, we don't need it!
|
||||
for (int y = height - 1; y >= height/2; y--)
|
||||
{
|
||||
for (int x = 0; x < (width*4); x++)
|
||||
for (int x = 0; x < (width*4); x += 4)
|
||||
{
|
||||
imgData[((height - 1) - y)*width*4 + x] = screenData[(y*width*4) + x]; // Flip line
|
||||
unsigned int s = ((height - 1) - y)*width*4 + x;
|
||||
unsigned int e = y*width*4 + x;
|
||||
|
||||
// Set alpha component value to 255 (no trasparent image retrieval)
|
||||
// NOTE: Alpha value has already been applied to RGB in framebuffer, we don't need it!
|
||||
if (((x + 1)%4) == 0) imgData[((height - 1) - y)*width*4 + x] = 255;
|
||||
unsigned char r = imgData[s];
|
||||
unsigned char g = imgData[s+1];
|
||||
unsigned char b = imgData[s+2];
|
||||
|
||||
imgData[s] = imgData[e];
|
||||
imgData[s+1] = imgData[e+1];
|
||||
imgData[s+2] = imgData[e+2];
|
||||
imgData[s+3] = 255; // Set alpha component value to 255 (no trasparent image retrieval)
|
||||
|
||||
imgData[e] = r;
|
||||
imgData[e+1] = g;
|
||||
imgData[e+2] = b;
|
||||
imgData[e+3] = 255; // Ditto
|
||||
}
|
||||
}
|
||||
|
||||
RL_FREE(screenData);
|
||||
|
||||
return imgData; // NOTE: image data should be freed
|
||||
}
|
||||
|
||||
|
@ -3737,19 +3743,16 @@ void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType,
|
|||
if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_2D, texId, mipLevel);
|
||||
else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_RENDERBUFFER, texId);
|
||||
else if (texType >= RL_ATTACHMENT_CUBEMAP_POSITIVE_X) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_CUBE_MAP_POSITIVE_X + texType, texId, mipLevel);
|
||||
|
||||
} break;
|
||||
case RL_ATTACHMENT_DEPTH:
|
||||
{
|
||||
if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel);
|
||||
else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, texId);
|
||||
|
||||
} break;
|
||||
case RL_ATTACHMENT_STENCIL:
|
||||
{
|
||||
if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel);
|
||||
else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, texId);
|
||||
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
@ -3959,7 +3962,7 @@ void rlDrawVertexArrayElements(int offset, int count, const void *buffer)
|
|||
void rlDrawVertexArrayInstanced(int offset, int count, int instances)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
glDrawArraysInstanced(GL_TRIANGLES, 0, count, instances);
|
||||
glDrawArraysInstanced(GL_TRIANGLES, offset, count, instances);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -4216,6 +4219,7 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
|
|||
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
|
||||
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
|
||||
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
|
||||
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX, RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX);
|
||||
|
||||
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
|
||||
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);
|
||||
|
|
700
raylib/rmodels.c
700
raylib/rmodels.c
File diff suppressed because it is too large
Load diff
|
@ -25,7 +25,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -285,6 +285,7 @@ void DrawCircleV(Vector2 center, float radius, Color color)
|
|||
// Draw a piece of a circle
|
||||
void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
|
||||
{
|
||||
if (startAngle == endAngle) return;
|
||||
if (radius <= 0.0f) radius = 0.1f; // Avoid div by zero
|
||||
|
||||
// Function expects (endAngle > startAngle)
|
||||
|
@ -376,6 +377,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
|||
// Draw a piece of a circle outlines
|
||||
void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
|
||||
{
|
||||
if (startAngle == endAngle) return;
|
||||
if (radius <= 0.0f) radius = 0.1f; // Avoid div by zero issue
|
||||
|
||||
// Function expects (endAngle > startAngle)
|
||||
|
@ -468,27 +470,39 @@ void DrawCircleLinesV(Vector2 center, float radius, Color color)
|
|||
|
||||
// Draw ellipse
|
||||
void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color)
|
||||
{
|
||||
DrawEllipseV((Vector2){ (float)centerX, (float)centerY }, radiusH, radiusV, color);
|
||||
}
|
||||
|
||||
// Draw ellipse (Vector version)
|
||||
void DrawEllipseV(Vector2 center, float radiusH, float radiusV, Color color)
|
||||
{
|
||||
rlBegin(RL_TRIANGLES);
|
||||
for (int i = 0; i < 360; i += 10)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f((float)centerX, (float)centerY);
|
||||
rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radiusH, (float)centerY + sinf(DEG2RAD*(i + 10))*radiusV);
|
||||
rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radiusH, (float)centerY + sinf(DEG2RAD*i)*radiusV);
|
||||
rlVertex2f(center.x, center.y);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(i + 10))*radiusH, center.y + sinf(DEG2RAD*(i + 10))*radiusV);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*i)*radiusH, center.y + sinf(DEG2RAD*i)*radiusV);
|
||||
}
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// Draw ellipse outline
|
||||
void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color)
|
||||
{
|
||||
DrawEllipseLinesV((Vector2){ (float)centerX, (float)centerY }, radiusH, radiusV, color);
|
||||
}
|
||||
|
||||
// Draw ellipse outline
|
||||
void DrawEllipseLinesV(Vector2 center, float radiusH, float radiusV, Color color)
|
||||
{
|
||||
rlBegin(RL_LINES);
|
||||
for (int i = 0; i < 360; i += 10)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(centerX + cosf(DEG2RAD*(i + 10))*radiusH, centerY + sinf(DEG2RAD*(i + 10))*radiusV);
|
||||
rlVertex2f(centerX + cosf(DEG2RAD*i)*radiusH, centerY + sinf(DEG2RAD*i)*radiusV);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(i + 10))*radiusH, center.y + sinf(DEG2RAD*(i + 10))*radiusV);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*i)*radiusH, center.y + sinf(DEG2RAD*i)*radiusV);
|
||||
}
|
||||
rlEnd();
|
||||
}
|
||||
|
@ -772,7 +786,7 @@ void DrawRectangleGradientH(int posX, int posY, int width, int height, Color lef
|
|||
}
|
||||
|
||||
// Draw a gradient-filled rectangle
|
||||
void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight)
|
||||
void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color bottomRight, Color topRight)
|
||||
{
|
||||
rlSetTexture(GetShapesTexture().id);
|
||||
Rectangle shapeRect = GetShapesTextureRectangle();
|
||||
|
@ -789,11 +803,11 @@ void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Col
|
|||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(rec.x, rec.y + rec.height);
|
||||
|
||||
rlColor4ub(topRight.r, topRight.g, topRight.b, topRight.a);
|
||||
rlColor4ub(bottomRight.r, bottomRight.g, bottomRight.b, bottomRight.a);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
|
||||
|
||||
rlColor4ub(bottomRight.r, bottomRight.g, bottomRight.b, bottomRight.a);
|
||||
rlColor4ub(topRight.r, topRight.g, topRight.b, topRight.a);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(rec.x + rec.width, rec.y);
|
||||
rlEnd();
|
||||
|
@ -807,22 +821,25 @@ void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Col
|
|||
// 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;
|
||||
Matrix mat = rlGetMatrixTransform();
|
||||
float xOffset = 0.5f/mat.m0;
|
||||
float yOffset = 0.5f/mat.m5;
|
||||
|
||||
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 + xOffset, (float)posY + yOffset);
|
||||
rlVertex2f((float)posX + (float)width - xOffset, (float)posY + yOffset);
|
||||
|
||||
rlVertex2f((float)posX + (float)width, (float)posY - zoomFactor);
|
||||
rlVertex2f((float)posX + (float)width, (float)posY + (float)height + zoomFactor);
|
||||
rlVertex2f((float)posX + (float)width - xOffset, (float)posY + yOffset);
|
||||
rlVertex2f((float)posX + (float)width - xOffset, (float)posY + (float)height - yOffset);
|
||||
|
||||
rlVertex2f((float)posX + (float)width + zoomFactor, (float)posY + (float)height);
|
||||
rlVertex2f((float)posX - zoomFactor, (float)posY + (float)height);
|
||||
rlVertex2f((float)posX + (float)width - xOffset, (float)posY + (float)height - yOffset);
|
||||
rlVertex2f((float)posX + xOffset, (float)posY + (float)height - yOffset);
|
||||
|
||||
rlVertex2f((float)posX, (float)posY + (float)height + zoomFactor);
|
||||
rlVertex2f((float)posX, (float)posY - zoomFactor);
|
||||
rlVertex2f((float)posX + xOffset, (float)posY + (float)height - yOffset);
|
||||
rlVertex2f((float)posX + xOffset, (float)posY + yOffset);
|
||||
rlEnd();
|
||||
|
||||
/*
|
||||
// Previous implementation, it has issues... but it does not require view matrix...
|
||||
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
||||
|
@ -845,7 +862,7 @@ 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
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
|
@ -884,7 +901,7 @@ void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color)
|
|||
void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color)
|
||||
{
|
||||
// Not a rounded rectangle
|
||||
if ((roundness <= 0.0f) || (rec.width < 1) || (rec.height < 1 ))
|
||||
if (roundness <= 0.0f)
|
||||
{
|
||||
DrawRectangleRec(rec, color);
|
||||
return;
|
||||
|
@ -1160,18 +1177,29 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f
|
|||
P5 ================== P4
|
||||
*/
|
||||
const Vector2 point[16] = {
|
||||
{(float)rec.x + innerRadius, rec.y - lineThick}, {(float)(rec.x + rec.width) - innerRadius, rec.y - lineThick}, { rec.x + rec.width + lineThick, (float)rec.y + innerRadius }, // PO, P1, P2
|
||||
{rec.x + rec.width + lineThick, (float)(rec.y + rec.height) - innerRadius}, {(float)(rec.x + rec.width) - innerRadius, rec.y + rec.height + lineThick}, // P3, P4
|
||||
{(float)rec.x + innerRadius, rec.y + rec.height + lineThick}, { rec.x - lineThick, (float)(rec.y + rec.height) - innerRadius}, {rec.x - lineThick, (float)rec.y + innerRadius}, // P5, P6, P7
|
||||
{(float)rec.x + innerRadius, rec.y}, {(float)(rec.x + rec.width) - innerRadius, rec.y}, // P8, P9
|
||||
{ rec.x + rec.width, (float)rec.y + innerRadius }, {rec.x + rec.width, (float)(rec.y + rec.height) - innerRadius}, // P10, P11
|
||||
{(float)(rec.x + rec.width) - innerRadius, rec.y + rec.height}, {(float)rec.x + innerRadius, rec.y + rec.height}, // P12, P13
|
||||
{ rec.x, (float)(rec.y + rec.height) - innerRadius}, {rec.x, (float)rec.y + innerRadius} // P14, P15
|
||||
{(float)rec.x + innerRadius + 0.5f, rec.y - lineThick + 0.5f},
|
||||
{(float)(rec.x + rec.width) - innerRadius - 0.5f, rec.y - lineThick + 0.5f},
|
||||
{rec.x + rec.width + lineThick - 0.5f, (float)rec.y + innerRadius + 0.5f}, // PO, P1, P2
|
||||
{rec.x + rec.width + lineThick - 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f},
|
||||
{(float)(rec.x + rec.width) - innerRadius - 0.5f, rec.y + rec.height + lineThick - 0.5f}, // P3, P4
|
||||
{(float)rec.x + innerRadius + 0.5f, rec.y + rec.height + lineThick - 0.5f},
|
||||
{rec.x - lineThick + 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f},
|
||||
{rec.x - lineThick + 0.5f, (float)rec.y + innerRadius + 0.5f}, // P5, P6, P7
|
||||
{(float)rec.x + innerRadius + 0.5f, rec.y + 0.5f},
|
||||
{(float)(rec.x + rec.width) - innerRadius - 0.5f, rec.y + 0.5f}, // P8, P9
|
||||
{rec.x + rec.width - 0.5f, (float)rec.y + innerRadius + 0.5f},
|
||||
{rec.x + rec.width - 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f}, // P10, P11
|
||||
{(float)(rec.x + rec.width) - innerRadius - 0.5f, rec.y + rec.height - 0.5f},
|
||||
{(float)rec.x + innerRadius + 0.5f, rec.y + rec.height - 0.5f}, // P12, P13
|
||||
{rec.x + 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f},
|
||||
{rec.x + 0.5f, (float)rec.y + innerRadius + 0.5f} // P14, P15
|
||||
};
|
||||
|
||||
const Vector2 centers[4] = {
|
||||
{(float)rec.x + innerRadius, (float)rec.y + innerRadius}, {(float)(rec.x + rec.width) - innerRadius, (float)rec.y + innerRadius}, // P16, P17
|
||||
{(float)(rec.x + rec.width) - innerRadius, (float)(rec.y + rec.height) - innerRadius}, {(float)rec.x + innerRadius, (float)(rec.y + rec.height) - innerRadius} // P18, P19
|
||||
{(float)rec.x + innerRadius + 0.5f, (float)rec.y + innerRadius + 0.5f},
|
||||
{(float)(rec.x + rec.width) - innerRadius - 0.5f, (float)rec.y + innerRadius + 0.5f}, // P16, P17
|
||||
{(float)(rec.x + rec.width) - innerRadius - 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f},
|
||||
{(float)rec.x + innerRadius + 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f} // P18, P19
|
||||
};
|
||||
|
||||
const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
|
||||
|
@ -2223,7 +2251,7 @@ bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2
|
|||
// NOTE: Based on http://jeffreythompson.org/collision-detection/poly-point.php
|
||||
bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount)
|
||||
{
|
||||
bool inside = false;
|
||||
bool collision = false;
|
||||
|
||||
if (pointCount > 2)
|
||||
{
|
||||
|
@ -2232,12 +2260,12 @@ bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCoun
|
|||
if ((points[i].y > point.y) != (points[j].y > point.y) &&
|
||||
(point.x < (points[j].x - points[i].x)*(point.y - points[i].y)/(points[j].y - points[i].y) + points[i].x))
|
||||
{
|
||||
inside = !inside;
|
||||
collision = !collision;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return inside;
|
||||
return collision;
|
||||
}
|
||||
|
||||
// Check collision between two rectangles
|
||||
|
@ -2342,7 +2370,7 @@ 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]
|
||||
// Check if circle collides with a line created between two points [p1] and [p2]
|
||||
RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2)
|
||||
{
|
||||
float dx = p1.x - p2.x;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -161,6 +161,10 @@ extern void LoadFontDefault(void)
|
|||
{
|
||||
#define BIT_CHECK(a,b) ((a) & (1u << (b)))
|
||||
|
||||
// check to see if we have allready allocated the font for an image, and if we don't need to upload, then just return
|
||||
if (defaultFont.glyphs != NULL && !isGpuReady)
|
||||
return;
|
||||
|
||||
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
|
||||
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
|
||||
|
||||
|
@ -247,13 +251,28 @@ extern void LoadFontDefault(void)
|
|||
// we must consider data as little-endian order (alpha + gray)
|
||||
((unsigned short *)imFont.data)[i + j] = 0xffff;
|
||||
}
|
||||
else ((unsigned short *)imFont.data)[i + j] = 0x00ff;
|
||||
else
|
||||
{
|
||||
((unsigned char *)imFont.data)[(i + j)*sizeof(short)] = 0xff;
|
||||
((unsigned char *)imFont.data)[(i + j)*sizeof(short) + 1] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
if (isGpuReady) defaultFont.texture = LoadTextureFromImage(imFont);
|
||||
if (isGpuReady)
|
||||
{
|
||||
defaultFont.texture = LoadTextureFromImage(imFont);
|
||||
|
||||
// we have already loaded the font glyph data an image, and the GPU is ready, we are done
|
||||
// if we don't do this, we will leak memory by reallocating the glyphs and rects
|
||||
if (defaultFont.glyphs != NULL)
|
||||
{
|
||||
UnloadImage(imFont);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -278,7 +297,7 @@ extern void LoadFontDefault(void)
|
|||
|
||||
testPosX += (int)(defaultFont.recs[i].width + (float)charsDivisor);
|
||||
|
||||
if (testPosX >= defaultFont.texture.width)
|
||||
if (testPosX >= imFont.width)
|
||||
{
|
||||
currentLine++;
|
||||
currentPosX = 2*charsDivisor + charsWidth[i];
|
||||
|
@ -312,6 +331,9 @@ extern void UnloadFontDefault(void)
|
|||
if (isGpuReady) UnloadTexture(defaultFont.texture);
|
||||
RL_FREE(defaultFont.glyphs);
|
||||
RL_FREE(defaultFont.recs);
|
||||
defaultFont.glyphCount = 0;
|
||||
defaultFont.glyphs = NULL;
|
||||
defaultFont.recs = NULL;
|
||||
}
|
||||
#endif // SUPPORT_DEFAULT_FONT
|
||||
|
||||
|
@ -985,7 +1007,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
|
|||
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2024 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2025 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// ---------------------------------------------------------------------------------- //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
|
@ -1071,7 +1093,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, " if (isGpuReady) font.texture = LoadTextureFromImage(imFont);\n");
|
||||
byteCount += sprintf(txtData + byteCount, " 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
|
||||
|
@ -1339,6 +1361,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
|||
int GetGlyphIndex(Font font, int codepoint)
|
||||
{
|
||||
int index = 0;
|
||||
if (!IsFontValid(font)) return index;
|
||||
|
||||
#define SUPPORT_UNORDERED_CHARSET
|
||||
#if defined(SUPPORT_UNORDERED_CHARSET)
|
||||
|
@ -1535,27 +1558,27 @@ const char *TextSubtext(const char *text, int position, int length)
|
|||
|
||||
if (position >= textLength)
|
||||
{
|
||||
position = textLength - 1;
|
||||
length = 0;
|
||||
return buffer; //First char is already '\0' by memset
|
||||
}
|
||||
|
||||
if (length >= textLength) length = textLength;
|
||||
int maxLength = textLength - position;
|
||||
if (length > maxLength) length = maxLength;
|
||||
if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1;
|
||||
|
||||
// NOTE: Alternative: memcpy(buffer, text + position, length)
|
||||
|
||||
for (int c = 0 ; c < length ; c++)
|
||||
{
|
||||
*(buffer + c) = *(text + position);
|
||||
text++;
|
||||
buffer[c] = text[position + c];
|
||||
}
|
||||
|
||||
*(buffer + length) = '\0';
|
||||
buffer[length] = '\0';
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Replace text string
|
||||
// REQUIRES: strlen(), strstr(), strncpy(), strcpy()
|
||||
// REQUIRES: strstr(), strncpy(), strcpy()
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextReplace(const char *text, const char *replace, const char *by)
|
||||
{
|
||||
|
@ -1624,7 +1647,7 @@ char *TextInsert(const char *text, const char *insert, int position)
|
|||
|
||||
// Join text strings with delimiter
|
||||
// REQUIRES: memset(), memcpy()
|
||||
const char *TextJoin(const char **textList, int count, const char *delimiter)
|
||||
char *TextJoin(char **textList, int count, const char *delimiter)
|
||||
{
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
@ -1658,7 +1681,7 @@ const char *TextJoin(const char **textList, int count, const char *delimiter)
|
|||
|
||||
// Split string into multiple strings
|
||||
// REQUIRES: memset()
|
||||
const char **TextSplit(const char *text, char delimiter, int *count)
|
||||
char **TextSplit(const char *text, char delimiter, int *count)
|
||||
{
|
||||
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
|
||||
// inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
|
||||
|
@ -1666,7 +1689,7 @@ const char **TextSplit(const char *text, char delimiter, int *count)
|
|||
// 1. Maximum number of possible split strings is set by MAX_TEXTSPLIT_COUNT
|
||||
// 2. Maximum size of text to split is MAX_TEXT_BUFFER_LENGTH
|
||||
|
||||
static const char *result[MAX_TEXTSPLIT_COUNT] = { NULL };
|
||||
static char *result[MAX_TEXTSPLIT_COUNT] = { NULL };
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
||||
|
@ -1722,7 +1745,7 @@ int TextFindIndex(const char *text, const char *find)
|
|||
// Get upper case version of provided string
|
||||
// WARNING: Limited functionality, only basic characters set
|
||||
// TODO: Support UTF-8 diacritics to upper-case, check codepoints
|
||||
const char *TextToUpper(const char *text)
|
||||
char *TextToUpper(const char *text)
|
||||
{
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
@ -1741,7 +1764,7 @@ const char *TextToUpper(const char *text)
|
|||
|
||||
// Get lower case version of provided string
|
||||
// WARNING: Limited functionality, only basic characters set
|
||||
const char *TextToLower(const char *text)
|
||||
char *TextToLower(const char *text)
|
||||
{
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
@ -1760,7 +1783,7 @@ const char *TextToLower(const char *text)
|
|||
|
||||
// Get Pascal case notation version of provided string
|
||||
// WARNING: Limited functionality, only basic characters set
|
||||
const char *TextToPascal(const char *text)
|
||||
char *TextToPascal(const char *text)
|
||||
{
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
@ -1788,7 +1811,7 @@ const char *TextToPascal(const char *text)
|
|||
|
||||
// Get snake case notation version of provided string
|
||||
// WARNING: Limited functionality, only basic characters set
|
||||
const char *TextToSnake(const char *text)
|
||||
char *TextToSnake(const char *text)
|
||||
{
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = {0};
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
@ -1816,7 +1839,7 @@ const char *TextToSnake(const char *text)
|
|||
|
||||
// Get Camel case notation version of provided string
|
||||
// WARNING: Limited functionality, only basic characters set
|
||||
const char *TextToCamel(const char *text)
|
||||
char *TextToCamel(const char *text)
|
||||
{
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = {0};
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
@ -1910,7 +1933,7 @@ void UnloadCodepoints(int *codepoints)
|
|||
int GetCodepointCount(const char *text)
|
||||
{
|
||||
unsigned int length = 0;
|
||||
char *ptr = (char *)&text[0];
|
||||
const char *ptr = text;
|
||||
|
||||
while (*ptr != '\0')
|
||||
{
|
||||
|
@ -2324,9 +2347,9 @@ static Font LoadBMFont(const char *fileName)
|
|||
// Convert hexadecimal to decimal (single digit)
|
||||
static unsigned char HexToInt(char hex)
|
||||
{
|
||||
if (hex >= '0' && hex <= '9') return hex - '0';
|
||||
else if (hex >= 'a' && hex <= 'f') return hex - 'a' + 10;
|
||||
else if (hex >= 'A' && hex <= 'F') return hex - 'A' + 10;
|
||||
if ((hex >= '0') && (hex <= '9')) return hex - '0';
|
||||
else if ((hex >= 'a') && (hex <= 'f')) return hex - 'a' + 10;
|
||||
else if ((hex >= 'A') && (hex <= 'F')) return hex - 'A' + 10;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -124,10 +124,6 @@
|
|||
#endif
|
||||
|
||||
// Image fileformats not supported by default
|
||||
#if defined(__TINYC__)
|
||||
#define STBI_NO_SIMD
|
||||
#endif
|
||||
|
||||
#if (defined(SUPPORT_FILEFORMAT_BMP) || \
|
||||
defined(SUPPORT_FILEFORMAT_PNG) || \
|
||||
defined(SUPPORT_FILEFORMAT_TGA) || \
|
||||
|
@ -149,6 +145,10 @@
|
|||
|
||||
#define STBI_NO_THREAD_LOCALS
|
||||
|
||||
#if defined(__TINYC__)
|
||||
#define STBI_NO_SIMD
|
||||
#endif
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "external/stb_image.h" // Required for: stbi_load_from_file()
|
||||
// NOTE: Used to read image data (multiple formats support)
|
||||
|
@ -218,6 +218,9 @@
|
|||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
#if defined(__TINYC__)
|
||||
#define STBIR_NO_SIMD
|
||||
#endif
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include "external/stb_image_resize2.h" // Required for: stbir_resize_uint8_linear() [ImageResize()]
|
||||
|
||||
|
@ -761,7 +764,7 @@ bool ExportImageAsCode(Image image, const char *fileName)
|
|||
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2024 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2025 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
|
||||
|
||||
|
@ -829,25 +832,23 @@ Image GenImageGradientLinear(int width, int height, int direction, Color start,
|
|||
|
||||
// Calculate how far the top-left pixel is along the gradient direction from the center of said gradient
|
||||
float startingPos = 0.5f - (cosDir*width/2) - (sinDir*height/2);
|
||||
|
||||
// With directions that lie in the first or third quadrant (i.e. from top-left to
|
||||
// bottom-right or vice-versa), pixel (0, 0) is the farthest point on the gradient
|
||||
// (i.e. the pixel which should become one of the gradient's ends color); while for
|
||||
// directions that lie in the second or fourth quadrant, that point is pixel (width, 0).
|
||||
float maxPosValue =
|
||||
((signbit(sinDir) != 0) == (signbit(cosDir) != 0))
|
||||
? fabsf(startingPos)
|
||||
: fabsf(startingPos+width*cosDir);
|
||||
// directions that lie in the second or fourth quadrant, that point is pixel (width, 0)
|
||||
float maxPosValue = ((signbit(sinDir) != 0) == (signbit(cosDir) != 0))? fabsf(startingPos) : fabsf(startingPos + width*cosDir);
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
// Calculate the relative position of the pixel along the gradient direction
|
||||
float pos = (startingPos + (i*cosDir + j*sinDir)) / maxPosValue;
|
||||
float pos = (startingPos + (i*cosDir + j*sinDir))/maxPosValue;
|
||||
|
||||
float factor = pos;
|
||||
factor = (factor > 1.0f)? 1.0f : factor; // Clamp to [-1,1]
|
||||
factor = (factor < -1.0f)? -1.0f : factor; // Clamp to [-1,1]
|
||||
factor = factor / 2 + 0.5f;
|
||||
factor = factor/2.0f + 0.5f;
|
||||
|
||||
// Generate the color for this pixel
|
||||
pixels[j*width + i].r = (int)((float)end.r*factor + (float)start.r*(1.0f - factor));
|
||||
|
@ -1007,7 +1008,8 @@ Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float
|
|||
{
|
||||
Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color));
|
||||
|
||||
float aspectRatio = (float)width / (float)height;
|
||||
float aspectRatio = (float)width/(float)height;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
|
@ -2100,8 +2102,8 @@ void ImageBlurGaussian(Image *image, int blurSize)
|
|||
Color *pixels = LoadImageColors(*image);
|
||||
|
||||
// Loop switches between pixelsCopy1 and pixelsCopy2
|
||||
Vector4 *pixelsCopy1 = RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
||||
Vector4 *pixelsCopy2 = RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
||||
Vector4 *pixelsCopy1 = (Vector4 *)RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
||||
Vector4 *pixelsCopy2 = (Vector4 *)RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
||||
|
||||
for (int i = 0; i < (image->height*image->width); i++)
|
||||
{
|
||||
|
@ -2249,8 +2251,8 @@ void ImageKernelConvolution(Image *image, const float *kernel, int kernelSize)
|
|||
|
||||
Color *pixels = LoadImageColors(*image);
|
||||
|
||||
Vector4 *imageCopy2 = RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
||||
Vector4 *temp = RL_MALLOC(kernelSize*sizeof(Vector4));
|
||||
Vector4 *imageCopy2 = (Vector4 *)RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
||||
Vector4 *temp = (Vector4 *)RL_MALLOC(kernelSize*sizeof(Vector4));
|
||||
|
||||
for (int i = 0; i < kernelSize; i++)
|
||||
{
|
||||
|
@ -3567,7 +3569,7 @@ void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color co
|
|||
ImageDrawLine(dst, x1, y1, x2, y2, color);
|
||||
|
||||
// Determine if the line is more horizontal or vertical
|
||||
if (dx != 0 && abs(dy/dx) < 1)
|
||||
if ((dx != 0) && (abs(dy/dx) < 1))
|
||||
{
|
||||
// Line is more horizontal
|
||||
// Calculate half the width of the line
|
||||
|
@ -3834,7 +3836,7 @@ void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c
|
|||
|
||||
// Calculate the inverse of the sum of the barycentric coordinates for normalization
|
||||
// NOTE 1: Here, we act as if we multiply by 255 the reciprocal, which avoids additional
|
||||
// calculations in the loop. This is acceptable because we are only interpolating colors.
|
||||
// calculations in the loop. This is acceptable because we are only interpolating colors
|
||||
// NOTE 2: This sum remains constant throughout the triangle
|
||||
float wInvSum = 255.0f/(w1Row + w2Row + w3Row);
|
||||
|
||||
|
@ -3889,7 +3891,7 @@ void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Colo
|
|||
}
|
||||
|
||||
// Draw a triangle fan defined by points within an image (first vertex is the center)
|
||||
void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color color)
|
||||
void ImageDrawTriangleFan(Image *dst, const Vector2 *points, int pointCount, Color color)
|
||||
{
|
||||
if (pointCount >= 3)
|
||||
{
|
||||
|
@ -3901,7 +3903,7 @@ void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color col
|
|||
}
|
||||
|
||||
// Draw a triangle strip defined by points within an image
|
||||
void ImageDrawTriangleStrip(Image *dst, Vector2 *points, int pointCount, Color color)
|
||||
void ImageDrawTriangleStrip(Image *dst, const Vector2 *points, int pointCount, Color color)
|
||||
{
|
||||
if (pointCount >= 3)
|
||||
{
|
||||
|
@ -4206,8 +4208,13 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
|
|||
ImageFormat(&faces, image.format);
|
||||
|
||||
Image mipmapped = ImageCopy(image);
|
||||
ImageMipmaps(&mipmapped);
|
||||
ImageMipmaps(&faces);
|
||||
#if defined(SUPPORT_IMAGE_MANIPULATION)
|
||||
if (image.mipmaps > 1)
|
||||
{
|
||||
ImageMipmaps(&mipmapped);
|
||||
ImageMipmaps(&faces);
|
||||
}
|
||||
#endif
|
||||
|
||||
// NOTE: Image formatting does not work with compressed textures
|
||||
|
||||
|
@ -4223,7 +4230,7 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
|
|||
if (cubemap.id != 0)
|
||||
{
|
||||
cubemap.format = faces.format;
|
||||
cubemap.mipmaps = 1;
|
||||
cubemap.mipmaps = faces.mipmaps;
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "IMAGE: Failed to load cubemap image");
|
||||
|
||||
|
@ -5141,10 +5148,10 @@ Color GetColor(unsigned int hexValue)
|
|||
{
|
||||
Color color;
|
||||
|
||||
color.r = (unsigned char)(hexValue >> 24) & 0xFF;
|
||||
color.g = (unsigned char)(hexValue >> 16) & 0xFF;
|
||||
color.b = (unsigned char)(hexValue >> 8) & 0xFF;
|
||||
color.a = (unsigned char)hexValue & 0xFF;
|
||||
color.r = (unsigned char)(hexValue >> 24) & 0xff;
|
||||
color.g = (unsigned char)(hexValue >> 16) & 0xff;
|
||||
color.b = (unsigned char)(hexValue >> 8) & 0xff;
|
||||
color.a = (unsigned char)hexValue & 0xff;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
@ -5384,13 +5391,18 @@ static float HalfToFloat(unsigned short x)
|
|||
{
|
||||
float result = 0.0f;
|
||||
|
||||
const unsigned int e = (x & 0x7C00) >> 10; // Exponent
|
||||
const unsigned int m = (x & 0x03FF) << 13; // Mantissa
|
||||
const float fm = (float)m;
|
||||
const unsigned int v = (*(unsigned int*)&fm) >> 23; // Evil log2 bit hack to count leading zeros in denormalized format
|
||||
const unsigned int r = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized
|
||||
union {
|
||||
float fm;
|
||||
unsigned int ui;
|
||||
} uni;
|
||||
|
||||
result = *(float *)&r;
|
||||
const unsigned int e = (x & 0x7c00) >> 10; // Exponent
|
||||
const unsigned int m = (x & 0x03cc) << 13; // Mantissa
|
||||
uni.fm = (float)m;
|
||||
const unsigned int v = uni.ui >> 23; // Evil log2 bit hack to count leading zeros in denormalized format
|
||||
uni.ui = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007fe000)); // sign : normalized : denormalized
|
||||
|
||||
result = uni.fm;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -5400,11 +5412,17 @@ static unsigned short FloatToHalf(float x)
|
|||
{
|
||||
unsigned short result = 0;
|
||||
|
||||
const unsigned int b = (*(unsigned int*) & x) + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa
|
||||
const unsigned int e = (b & 0x7F800000) >> 23; // Exponent
|
||||
const unsigned int m = b & 0x007FFFFF; // Mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
|
||||
union {
|
||||
float fm;
|
||||
unsigned int ui;
|
||||
} uni;
|
||||
uni.fm = x;
|
||||
|
||||
result = (b & 0x80000000) >> 16 | (e > 112)*((((e - 112) << 10) & 0x7C00) | m >> 13) | ((e < 113) & (e > 101))*((((0x007FF000 + m) >> (125 - e)) + 1) >> 1) | (e > 143)*0x7FFF; // sign : normalized : denormalized : saturate
|
||||
const unsigned int b = uni.ui + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa
|
||||
const unsigned int e = (b & 0x7f800000) >> 23; // Exponent
|
||||
const unsigned int m = b & 0x007fffff; // Mantissa; in line below: 0x007ff000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
|
||||
|
||||
result = (b & 0x80000000) >> 16 | (e > 112)*((((e - 112) << 10) & 0x7c00) | m >> 13) | ((e < 113) & (e > 101))*((((0x007ff000 + m) >> (125 - e)) + 1) >> 1) | (e > 143)*0x7fff; // sign : normalized : denormalized : saturate
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -5493,6 +5511,7 @@ static Vector4 *LoadImageDataNormalized(Image image)
|
|||
pixels[i].z = 0.0f;
|
||||
pixels[i].w = 1.0f;
|
||||
|
||||
k += 1;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
|
||||
{
|
||||
|
@ -5518,6 +5537,8 @@ static Vector4 *LoadImageDataNormalized(Image image)
|
|||
pixels[i].y = 0.0f;
|
||||
pixels[i].z = 0.0f;
|
||||
pixels[i].w = 1.0f;
|
||||
|
||||
k += 1;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R16G16B16:
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -308,7 +308,7 @@ bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileN
|
|||
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2022-2024 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2022-2025 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
|
||||
|
||||
|
@ -405,7 +405,7 @@ void UnloadFileText(char *text)
|
|||
}
|
||||
|
||||
// Save text data to file (write), string must be '\0' terminated
|
||||
bool SaveFileText(const char *fileName, char *text)
|
||||
bool SaveFileText(const char *fileName, const char *text)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue