Some TODOs and format reviews

This commit is contained in:
Ray
2025-11-23 21:40:39 +01:00
parent cf5e84c3c4
commit e1b9857b14
16 changed files with 154 additions and 191 deletions

View File

@@ -49,10 +49,10 @@
#define SUPPORT_RPRAND_GENERATOR 1 #define SUPPORT_RPRAND_GENERATOR 1
// Mouse gestures are directly mapped like touches and processed by gestures system // Mouse gestures are directly mapped like touches and processed by gestures system
#define SUPPORT_MOUSE_GESTURES 1 #define SUPPORT_MOUSE_GESTURES 1
// Reconfigure standard input to receive key inputs, works with SSH connection. // Reconfigure standard input to receive key inputs, works with SSH connection
#define SUPPORT_SSH_KEYBOARD_RPI 1 #define SUPPORT_SSH_KEYBOARD_RPI 1
// Setting a higher resolution can improve the accuracy of time-out intervals in wait functions. // Setting a higher resolution can improve the accuracy of time-out intervals in wait functions
// However, it can also reduce overall system performance, because the thread scheduler switches tasks more often. // However, it can also reduce overall system performance, because the thread scheduler switches tasks more often
#define SUPPORT_WINMM_HIGHRES_TIMER 1 #define SUPPORT_WINMM_HIGHRES_TIMER 1
// Use busy wait loop for timing sync, if not defined, a high-resolution timer is set up and used // Use busy wait loop for timing sync, if not defined, a high-resolution timer is set up and used
//#define SUPPORT_BUSY_WAIT_LOOP 1 //#define SUPPORT_BUSY_WAIT_LOOP 1
@@ -225,7 +225,7 @@
// On font atlas image generation [GenImageFontAtlas()], add a 3x3 pixels white rectangle // On font atlas image generation [GenImageFontAtlas()], add a 3x3 pixels white rectangle
// at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow // at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow
// drawing text and shapes with a single draw call [SetShapesTexture()]. // drawing text and shapes with a single draw call [SetShapesTexture()]
#define SUPPORT_FONT_ATLAS_WHITE_REC 1 #define SUPPORT_FONT_ATLAS_WHITE_REC 1
// Support conservative font atlas size estimation // Support conservative font atlas size estimation

54
src/external/rlsw.h vendored
View File

@@ -145,7 +145,7 @@
#define SW_MAX_TEXTURES 128 #define SW_MAX_TEXTURES 128
#endif #endif
// Under normal circumstances, clipping a polygon can add at most one vertex per clipping plane. // Under normal circumstances, clipping a polygon can add at most one vertex per clipping plane
// Considering the largest polygon involved is a quadrilateral (4 vertices), // Considering the largest polygon involved is a quadrilateral (4 vertices),
// and that clipping occurs against both the frustum (6 planes) and the scissors (4 planes), // and that clipping occurs against both the frustum (6 planes) and the scissors (4 planes),
// the maximum number of vertices after clipping is: // the maximum number of vertices after clipping is:
@@ -1530,7 +1530,7 @@ DEFINE_FRAMEBUFFER_COPY_BEGIN(R5G5B5A1, uint16_t)
uint8_t r5 = (color[0]*31 + 127)/255; uint8_t r5 = (color[0]*31 + 127)/255;
uint8_t g5 = (color[1]*31 + 127)/255; uint8_t g5 = (color[1]*31 + 127)/255;
uint8_t b5 = (color[2]*31 + 127)/255; uint8_t b5 = (color[2]*31 + 127)/255;
uint8_t a1 = color[3] >= 128 ? 1 : 0; uint8_t a1 = (color[3] >= 128)? 1 : 0;
#if SW_GL_FRAMEBUFFER_COPY_BGRA #if SW_GL_FRAMEBUFFER_COPY_BGRA
uint16_t pixel = (b5 << 11) | (g5 << 6) | (r5 << 1) | a1; uint16_t pixel = (b5 << 11) | (g5 << 6) | (r5 << 1) | a1;
@@ -1661,7 +1661,7 @@ DEFINE_FRAMEBUFFER_BLIT_BEGIN(R5G5B5A1, uint16_t)
uint8_t r5 = (color[0]*31 + 127)/255; uint8_t r5 = (color[0]*31 + 127)/255;
uint8_t g5 = (color[1]*31 + 127)/255; uint8_t g5 = (color[1]*31 + 127)/255;
uint8_t b5 = (color[2]*31 + 127)/255; uint8_t b5 = (color[2]*31 + 127)/255;
uint8_t a1 = color[3] >= 128 ? 1 : 0; uint8_t a1 = (color[3] >= 128)? 1 : 0;
#if SW_GL_FRAMEBUFFER_COPY_BGRA #if SW_GL_FRAMEBUFFER_COPY_BGRA
uint16_t pixel = (b5 << 11) | (g5 << 6) | (r5 << 1) | a1; uint16_t pixel = (b5 << 11) | (g5 << 6) | (r5 << 1) | a1;
@@ -1919,7 +1919,7 @@ static inline void sw_texture_sample_nearest(float *color, const sw_texture_t *t
static inline void sw_texture_sample_linear(float *color, const sw_texture_t *tex, float u, float v) static inline void sw_texture_sample_linear(float *color, const sw_texture_t *tex, float u, float v)
{ {
// TODO: With a bit more cleverness we could clearly reduce the // TODO: With a bit more cleverness we could clearly reduce the
// number of operations here, but for now it works fine. // number of operations here, but for now it works fine
float xf = (u*tex->width) - 0.5f; float xf = (u*tex->width) - 0.5f;
float yf = (v*tex->height) - 0.5f; float yf = (v*tex->height) - 0.5f;
@@ -2203,13 +2203,13 @@ static inline bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VE
//------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------
static inline bool sw_triangle_face_culling(void) static inline bool sw_triangle_face_culling(void)
{ {
// NOTE: Face culling is done before clipping to avoid unnecessary computations. // NOTE: Face culling is done before clipping to avoid unnecessary computations
// To handle triangles crossing the w=0 plane correctly, // To handle triangles crossing the w=0 plane correctly,
// we perform the winding order test in homogeneous coordinates directly, // we perform the winding order test in homogeneous coordinates directly,
// before the perspective division (division by w). // before the perspective division (division by w)
// This test determines the orientation of the triangle in the (x,y,w) plane, // This test determines the orientation of the triangle in the (x,y,w) plane,
// which corresponds to the projected 2D winding order sign, // which corresponds to the projected 2D winding order sign,
// even with negative w values. // even with negative w values
// Preload homogeneous coordinates into local variables // Preload homogeneous coordinates into local variables
const float *h0 = RLSW.vertexBuffer[0].homogeneous; const float *h0 = RLSW.vertexBuffer[0].homogeneous;
@@ -2221,7 +2221,7 @@ static inline bool sw_triangle_face_culling(void)
// This is the determinant of the matrix formed by the (x, y, w) components // This is the determinant of the matrix formed by the (x, y, w) components
// of the vertices, which correctly captures the winding order in homogeneous // of the vertices, which correctly captures the winding order in homogeneous
// space and its relationship to the projected 2D winding order, even with // space and its relationship to the projected 2D winding order, even with
// negative w values. // negative w values
// The determinant formula used here is: // The determinant formula used here is:
// h0.x*(h1.y*h2.w - h2.y*h1.w) + // h0.x*(h1.y*h2.w - h2.y*h1.w) +
// h1.x*(h2.y*h0.w - h0.y*h2.w) + // h1.x*(h2.y*h0.w - h0.y*h2.w) +
@@ -2233,20 +2233,18 @@ static inline bool sw_triangle_face_culling(void)
h2[0]*(h0[1]*h1[3] - h1[1]*h0[3]); h2[0]*(h0[1]*h1[3] - h1[1]*h0[3]);
// Discard the triangle if its winding order (determined by the sign // Discard the triangle if its winding order (determined by the sign
// of the homogeneous area/determinant) matches the culled direction. // of the homogeneous area/determinant) matches the culled direction
// A positive hSgnArea typically corresponds to a counter-clockwise // A positive hSgnArea typically corresponds to a counter-clockwise
// winding in the projected space when all w > 0. // winding in the projected space when all w > 0.
// This test is robust for points with w > 0 or w < 0, correctly // This test is robust for points with w > 0 or w < 0, correctly
// capturing the change in orientation when crossing the w=0 plane. // capturing the change in orientation when crossing the w=0 plane
// The culling logic remains the same based on the signed area/determinant. // The culling logic remains the same based on the signed area/determinant
// A value of 0 for hSgnArea means the points are collinear in (x, y, w) // A value of 0 for hSgnArea means the points are collinear in (x, y, w)
// space, which corresponds to a degenerate triangle projection. // space, which corresponds to a degenerate triangle projection.
// Such triangles are typically not culled by this test (0 < 0 is false, 0 > 0 is false) // Such triangles are typically not culled by this test (0 < 0 is false, 0 > 0 is false)
// and should be handled by the clipper if necessary. // and should be handled by the clipper if necessary
return (RLSW.cullFace == SW_FRONT) return (RLSW.cullFace == SW_FRONT)? (hSgnArea < 0) : (hSgnArea > 0); // Cull if winding is "clockwise" : "counter-clockwise"
? (hSgnArea < 0) // Cull if winding is "clockwise" in the projected sense
: (hSgnArea > 0); // Cull if winding is "counter-clockwise" in the projected sense
} }
static inline void sw_triangle_clip_and_project(void) static inline void sw_triangle_clip_and_project(void)
@@ -2559,14 +2557,14 @@ static inline void sw_triangle_render(void)
//------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------
static inline bool sw_quad_face_culling(void) static inline bool sw_quad_face_culling(void)
{ {
// NOTE: Face culling is done before clipping to avoid unnecessary computations. // NOTE: Face culling is done before clipping to avoid unnecessary computations
// To handle quads crossing the w=0 plane correctly, // To handle quads crossing the w=0 plane correctly,
// we perform the winding order test in homogeneous coordinates directly, // we perform the winding order test in homogeneous coordinates directly,
// before the perspective division (division by w). // before the perspective division (division by w)
// For a convex quad with vertices P0, P1, P2, P3 in sequential order, // For a convex quad with vertices P0, P1, P2, P3 in sequential order,
// the winding order of the quad is the same as the winding order // the winding order of the quad is the same as the winding order
// of the triangle P0 P1 P2. We use the homogeneous triangle // of the triangle P0 P1 P2. We use the homogeneous triangle
// winding test on this first triangle. // winding test on this first triangle
// Preload homogeneous coordinates into local variables // Preload homogeneous coordinates into local variables
const float *h0 = RLSW.vertexBuffer[0].homogeneous; const float *h0 = RLSW.vertexBuffer[0].homogeneous;
@@ -2578,11 +2576,11 @@ static inline bool sw_quad_face_culling(void)
// Compute a value proportional to the signed area of the triangle P0 P1 P2 // Compute a value proportional to the signed area of the triangle P0 P1 P2
// in the projected 2D plane, calculated directly using homogeneous coordinates // in the projected 2D plane, calculated directly using homogeneous coordinates
// BEFORE division by w. // BEFORE division by w
// This is the determinant of the matrix formed by the (x, y, w) components // This is the determinant of the matrix formed by the (x, y, w) components
// of the vertices P0, P1, and P2. Its sign correctly indicates the winding order // of the vertices P0, P1, and P2. Its sign correctly indicates the winding order
// in homogeneous space and its relationship to the projected 2D winding order, // in homogeneous space and its relationship to the projected 2D winding order,
// even with negative w values. // even with negative w values
// The determinant formula used here is: // The determinant formula used here is:
// h0.x*(h1.y*h2.w - h2.y*h1.w) + // h0.x*(h1.y*h2.w - h2.y*h1.w) +
// h1.x*(h2.y*h0.w - h0.y*h2.w) + // h1.x*(h2.y*h0.w - h0.y*h2.w) +
@@ -2594,21 +2592,19 @@ static inline bool sw_quad_face_culling(void)
h2[0]*(h0[1]*h1[3] - h1[1]*h0[3]); h2[0]*(h0[1]*h1[3] - h1[1]*h0[3]);
// Perform face culling based on the winding order determined by the sign // Perform face culling based on the winding order determined by the sign
// of the homogeneous area/determinant of triangle P0 P1 P2. // of the homogeneous area/determinant of triangle P0 P1 P2
// This test is robust for points with w > 0 or w < 0 within the triangle, // This test is robust for points with w > 0 or w < 0 within the triangle,
// correctly capturing the change in orientation when crossing the w=0 plane. // correctly capturing the change in orientation when crossing the w=0 plane
// A positive hSgnArea typically corresponds to a counter-clockwise // A positive hSgnArea typically corresponds to a counter-clockwise
// winding in the projected space when all w > 0. // winding in the projected space when all w > 0
// A value of 0 for hSgnArea means P0, P1, P2 are collinear in (x, y, w) // A value of 0 for hSgnArea means P0, P1, P2 are collinear in (x, y, w)
// space, which corresponds to a degenerate triangle projection. // space, which corresponds to a degenerate triangle projection
// Such quads might also be degenerate or non-planar. They are typically // Such quads might also be degenerate or non-planar. They are typically
// not culled by this test (0 < 0 is false, 0 > 0 is false) // not culled by this test (0 < 0 is false, 0 > 0 is false)
// and should be handled by the clipper if necessary. // and should be handled by the clipper if necessary.
return (RLSW.cullFace == SW_FRONT) return (RLSW.cullFace == SW_FRONT)? (hSgnArea < 0.0f) : (hSgnArea > 0.0f); // Cull if winding is "clockwise" : "counter-clockwise"
? (hSgnArea < 0.0f) // Cull if winding is "clockwise" in the projected sense
: (hSgnArea > 0.0f); // Cull if winding is "counter-clockwise" in the projected sense
} }
static inline void sw_quad_clip_and_project(void) static inline void sw_quad_clip_and_project(void)
@@ -4596,8 +4592,8 @@ void swDrawElements(SWdraw mode, int count, int type, const void *indices)
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
int index = indicesUb ? indicesUb[i] : int index = indicesUb? indicesUb[i] :
(indicesUs ? indicesUs[i] : indicesUi[i]); (indicesUs? indicesUs[i] : indicesUi[i]);
float u, v; float u, v;
if (texcoords) if (texcoords)

View File

@@ -623,10 +623,9 @@ double GetTime(void)
} }
// Open URL with default system browser (if available) // Open URL with default system browser (if available)
// NOTE: This function is only safe to use if you control the URL given. // NOTE: This function is only safe to use if you control the URL given
// A user could craft a malicious string performing another action. // A user could craft a malicious string performing another action
// Only call this function yourself not with user input or make sure to check the string yourself. // Only call this function yourself not with user input or make sure to check the string yourself
// Ref: https://github.com/raysan5/raylib/issues/686
void OpenURL(const char *url) void OpenURL(const char *url)
{ {
// Security check to (partially) avoid malicious code // Security check to (partially) avoid malicious code
@@ -687,7 +686,7 @@ void SetMouseCursor(int cursor)
TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform"); TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform");
} }
// Get physical key name. // Get physical key name
const char *GetKeyName(int key) const char *GetKeyName(int key)
{ {
TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform"); TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");
@@ -748,9 +747,9 @@ void PollInputEvents(void)
// Process this event // Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source); if (platform.source != NULL) platform.source->process(platform.app, platform.source);
// NOTE: Allow closing the window in case a configuration change happened. // NOTE: Allow closing the window in case a configuration change happened
// The android_main function should be allowed to return to its caller in order for the // The android_main function should be allowed to return to its caller in order for the
// Android OS to relaunch the activity. // Android OS to relaunch the activity
if (platform.app->destroyRequested != 0) if (platform.app->destroyRequested != 0)
{ {
CORE.Window.shouldClose = true; CORE.Window.shouldClose = true;
@@ -829,13 +828,13 @@ int InitPlatform(void)
// Wait for window to be initialized (display and context) // Wait for window to be initialized (display and context)
while (!CORE.Window.ready) while (!CORE.Window.ready)
{ {
// Process events until we reach TIMEOUT, which indicates no more events queued. // 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 // Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source); if (platform.source != NULL) platform.source->process(platform.app, platform.source);
// NOTE: It's highly likely destroyRequested will never be non-zero at the start of the activity lifecycle. // NOTE: It's highly likely destroyRequested will never be non-zero at the start of the activity lifecycle
//if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true; //if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true;
} }
} }
@@ -869,8 +868,9 @@ void ClosePlatform(void)
platform.device = EGL_NO_DISPLAY; platform.device = EGL_NO_DISPLAY;
} }
// NOTE: Reset global state in case the activity is being relaunched. // NOTE: Reset global state in case the activity is being relaunched
if (platform.app->destroyRequested != 0) { if (platform.app->destroyRequested != 0)
{
CORE = (CoreData){0}; CORE = (CoreData){0};
platform = (PlatformData){0}; platform = (PlatformData){0};
} }
@@ -925,7 +925,7 @@ static int InitGraphicsDevice(void)
// Initialize the EGL device connection // Initialize the EGL device connection
if (eglInitialize(platform.device, NULL, NULL) == EGL_FALSE) if (eglInitialize(platform.device, NULL, NULL) == EGL_FALSE)
{ {
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred. // If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
return -1; return -1;
} }
@@ -1081,21 +1081,6 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Initialize random seed // Initialize random seed
SetRandomSeed((unsigned int)time(NULL)); SetRandomSeed((unsigned int)time(NULL));
// TODO: GPU assets reload in case of lost focus (lost context)
// NOTE: This problem has been solved just unbinding and rebinding context from display
/*
if (assetsReloadRequired)
{
for (int i = 0; i < assetCount; i++)
{
// TODO: Unload old asset if required
// Load texture again to pointed texture
(*textureAsset + i) = LoadTexture(assetPath[i]);
}
}
*/
} }
} }
} break; } break;
@@ -1115,7 +1100,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
case APP_CMD_TERM_WINDOW: case APP_CMD_TERM_WINDOW:
{ {
// Detach OpenGL context and destroy display surface // Detach OpenGL context and destroy display surface
// NOTE 1: This case is used when the user exits the app without closing it. We detach the context to ensure everything is recoverable upon resuming. // NOTE 1: This case is used when the user exits the app without closing it, context is detached to ensure everything is recoverable upon resuming
// NOTE 2: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...) // NOTE 2: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...)
// NOTE 3: In some cases (too many context loaded), OS could unload context automatically... :( // NOTE 3: In some cases (too many context loaded), OS could unload context automatically... :(
if (platform.device != EGL_NO_DISPLAY) if (platform.device != EGL_NO_DISPLAY)
@@ -1179,8 +1164,8 @@ static GamepadButton AndroidTranslateGamepadButton(int button)
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
{ {
// If additional inputs are required check: // If additional inputs are required check:
// https://developer.android.com/ndk/reference/group/input // Ref: https://developer.android.com/ndk/reference/group/input
// https://developer.android.com/training/game-controllers/controller-input // Ref: https://developer.android.com/training/game-controllers/controller-input
int type = AInputEvent_getType(event); int type = AInputEvent_getType(event);
int source = AInputEvent_getSource(event); int source = AInputEvent_getSource(event);
@@ -1290,7 +1275,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
{ {
// Let the OS handle input to avoid app stuck. Behaviour: CMD_PAUSE -> CMD_SAVE_STATE -> CMD_STOP -> CMD_CONFIG_CHANGED -> CMD_LOST_FOCUS // Let the OS handle input to avoid app stuck. Behaviour: CMD_PAUSE -> CMD_SAVE_STATE -> CMD_STOP -> CMD_CONFIG_CHANGED -> CMD_LOST_FOCUS
// Resuming Behaviour: CMD_START -> CMD_RESUME -> CMD_CONFIG_CHANGED -> CMD_CONFIG_CHANGED -> CMD_GAINED_FOCUS // Resuming Behaviour: CMD_START -> CMD_RESUME -> CMD_CONFIG_CHANGED -> CMD_CONFIG_CHANGED -> CMD_GAINED_FOCUS
// It seems like locking mobile, screen size (CMD_CONFIG_CHANGED) is affected. // It seems like locking mobile, screen size (CMD_CONFIG_CHANGED) is affected
// NOTE: AndroidManifest.xml must have <activity android:configChanges="orientation|keyboardHidden|screenSize" > // NOTE: AndroidManifest.xml must have <activity android:configChanges="orientation|keyboardHidden|screenSize" >
// Before that change, activity was calling CMD_TERM_WINDOW and CMD_DESTROY when locking mobile, so that was not a normal behaviour // Before that change, activity was calling CMD_TERM_WINDOW and CMD_DESTROY when locking mobile, so that was not a normal behaviour
return 0; return 0;
@@ -1419,15 +1404,9 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
if (CORE.Input.Touch.pointCount > 0) CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 1; if (CORE.Input.Touch.pointCount > 0) CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 1;
else CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 0; else CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 0;
// Stores the previous position of touch[0] only while it's active to calculate the delta. // Stores the previous position of touch[0] only while it's active to calculate the delta
if (flags == AMOTION_EVENT_ACTION_MOVE) if (flags == AMOTION_EVENT_ACTION_MOVE) CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
{ else CORE.Input.Mouse.previousPosition = CORE.Input.Touch.position[0];
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
}
else
{
CORE.Input.Mouse.previousPosition = CORE.Input.Touch.position[0];
}
// Map touch[0] as mouse input for convenience // Map touch[0] as mouse input for convenience
CORE.Input.Mouse.currentPosition = CORE.Input.Touch.position[0]; CORE.Input.Mouse.currentPosition = CORE.Input.Touch.position[0];

View File

@@ -1220,9 +1220,9 @@ void PollInputEvents(void)
// Map touch position to mouse position for convenience // Map touch position to mouse position for convenience
// WARNING: If the target desktop device supports touch screen, this behaviour should be reviewed! // WARNING: If the target desktop device supports touch screen, this behaviour should be reviewed!
// TODO: GLFW does not support multi-touch input just yet // TODO: GLFW does not support multi-touch input yet
// https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch // Ref: https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch
// https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages // Ref: https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
// Check if gamepads are ready // Check if gamepads are ready
@@ -1334,7 +1334,7 @@ void PollInputEvents(void)
// Function wrappers around RL_*alloc macros, used by glfwInitAllocator() inside of InitPlatform() // 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 // 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 // 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 // Ref: https://www.glfw.org/docs/latest/intro_guide.html#init_allocator
static void *AllocateWrapper(size_t size, void *user) static void *AllocateWrapper(size_t size, void *user)
{ {
(void)user; (void)user;
@@ -1592,8 +1592,8 @@ int InitPlatform(void)
bool requestWindowedFullscreen = (CORE.Window.screen.height == 0) && (CORE.Window.screen.width == 0); bool requestWindowedFullscreen = (CORE.Window.screen.height == 0) && (CORE.Window.screen.width == 0);
// Default to at least one pixel in size, as creation with a zero dimension is not allowed // Default to at least one pixel in size, as creation with a zero dimension is not allowed
int creationWidth = CORE.Window.screen.width != 0 ? CORE.Window.screen.width : 1; int creationWidth = (CORE.Window.screen.width != 0)? CORE.Window.screen.width : 1;
int creationHeight = CORE.Window.screen.height != 0 ? CORE.Window.screen.height : 1; 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); platform.handle = glfwCreateWindow(creationWidth, creationHeight, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
if (!platform.handle) if (!platform.handle)

View File

@@ -870,17 +870,27 @@ double GetTime(void)
} }
// Open URL with default system browser (if available) // Open URL with default system browser (if available)
// NOTE: This function is only safe to use if you control the URL given. // NOTE: This function is only safe to use if you control the URL given
// A user could craft a malicious string performing another action. // A user could craft a malicious string performing another action
// Only call this function yourself not with user input or make sure to check the string yourself.
// Ref: https://github.com/raysan5/raylib/issues/686
void OpenURL(const char *url) void OpenURL(const char *url)
{ {
// Security check to (partially) avoid malicious code on target platform // Security check to (partially) avoid malicious code on target platform
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
else else
{ {
// TODO: Open URL implementation char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char));
#if defined(_WIN32)
sprintf(cmd, "explorer \"%s\"", url);
#endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
sprintf(cmd, "xdg-open '%s'", url); // Alternatives: firefox, x-www-browser
#endif
#if defined(__APPLE__)
sprintf(cmd, "open '%s'", url);
#endif
int result = system(cmd);
if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
RL_FREE(cmd);
} }
} }
@@ -915,7 +925,7 @@ void SetMouseCursor(int cursor)
RGFW_window_setMouseStandard(platform.window, cursor); RGFW_window_setMouseStandard(platform.window, cursor);
} }
// Get physical key name. // Get physical key name
const char *GetKeyName(int key) const char *GetKeyName(int key)
{ {
TRACELOG(LOG_WARNING, "GetKeyName() unsupported on target platform"); TRACELOG(LOG_WARNING, "GetKeyName() unsupported on target platform");
@@ -1095,11 +1105,7 @@ void PollInputEvents(void)
CORE.Input.Keyboard.currentKeyState[key] = 1; CORE.Input.Keyboard.currentKeyState[key] = 1;
} }
// TODO: Put exitKey verification outside the switch? if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) CORE.Window.shouldClose = true;
if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey])
{
CORE.Window.shouldClose = true;
}
// NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int) // NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int)
// Check if there is space available in the queue // Check if there is space available in the queue

View File

@@ -1129,7 +1129,7 @@ Vector2 GetWindowScaleDPI(void)
#ifndef USING_VERSION_SDL3 #ifndef USING_VERSION_SDL3
// NOTE: SDL_GetWindowDisplayScale was only added on SDL3 // NOTE: SDL_GetWindowDisplayScale was only added on SDL3
// see https://wiki.libsdl.org/SDL3/SDL_GetWindowDisplayScale // Ref: https://wiki.libsdl.org/SDL3/SDL_GetWindowDisplayScale
// TODO: Implement the window scale factor calculation manually // TODO: Implement the window scale factor calculation manually
TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform"); TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform");
#else #else
@@ -1425,8 +1425,10 @@ void PollInputEvents(void)
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
#if defined(USING_VERSION_SDL3) #if defined(USING_VERSION_SDL3)
// const char *data; /**< The text for SDL_EVENT_DROP_TEXT and the file name for SDL_EVENT_DROP_FILE, NULL for other events */ // 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. // 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); strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data);
#else #else
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file); strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file);
@@ -1458,7 +1460,7 @@ void PollInputEvents(void)
// SDL3 states: // SDL3 states:
// The SDL_WINDOWEVENT_* events have been moved to top level events, and SDL_WINDOWEVENT has been removed // The SDL_WINDOWEVENT_* events have been moved to top level events, and SDL_WINDOWEVENT has been removed
// In general, handling this change just means checking for the individual events instead of first checking for SDL_WINDOWEVENT // In general, handling this change just means checking for the individual events instead of first checking for SDL_WINDOWEVENT
// and then checking for window events. You can compare the event >= SDL_EVENT_WINDOW_FIRST and <= SDL_EVENT_WINDOW_LAST if you need to see whether it's a window event. // and then checking for window events. You can compare the event >= SDL_EVENT_WINDOW_FIRST and <= SDL_EVENT_WINDOW_LAST if you need to see whether it's a window event
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
{ {
switch (event.window.event) switch (event.window.event)
@@ -1582,11 +1584,9 @@ void PollInputEvents(void)
if (event.key.repeat) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1; if (event.key.repeat) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;
// TODO: Put exitKey verification outside the switch? // Check for registered exit key to request exit game loop on next iteration
if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) CORE.Window.shouldClose = true;
{
CORE.Window.shouldClose = true;
}
} break; } break;
case SDL_KEYUP: case SDL_KEYUP:
@@ -2080,7 +2080,7 @@ int InitPlatform(void)
// Disable mouse events being interpreted as touch events // Disable mouse events being interpreted as touch events
// NOTE: This is wanted because there are SDL_FINGER* events available which provide unique data // NOTE: This is wanted because there are SDL_FINGER* events available which provide unique data
// Due to the way PollInputEvents() and rgestures.h are currently implemented, setting this won't break SUPPORT_MOUSE_GESTURES // Due to the way PollInputEvents() and rgestures.h are currently implemented, setting this won't break SUPPORT_MOUSE_GESTURES
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
SDL_EventState(SDL_DROPFILE, SDL_ENABLE); SDL_EventState(SDL_DROPFILE, SDL_ENABLE);

View File

@@ -939,7 +939,7 @@ void SetWindowIcon(Image image)
// Set icon for window // Set icon for window
void SetWindowIcons(Image *images, int count) void SetWindowIcons(Image *images, int count)
{ {
// TODO. // TODO: Implement SetWindowIcons()
} }
void SetWindowTitle(const char *title) void SetWindowTitle(const char *title)
@@ -1246,7 +1246,11 @@ void OpenURL(const char *url)
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
else else
{ {
TRACELOG(LOG_WARNING, "OpenURL not implemented"); char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char));
sprintf(cmd, "explorer \"%s\"", url);
int result = system(cmd);
if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
RL_FREE(cmd);
} }
} }

View File

@@ -220,7 +220,7 @@ static const short linuxToRaylibMap[KEYMAP_SIZE] = {
248, 0, 0, 0, 0, 0, 0, 0, 248, 0, 0, 0, 0, 0, 0, 0,
// Gamepads are mapped according to: // Gamepads are mapped according to:
// https://www.kernel.org/doc/html/next/input/gamepad.html // Ref: https://www.kernel.org/doc/html/next/input/gamepad.html
// Those mappings are standardized, but that doesn't mean people follow // Those mappings are standardized, but that doesn't mean people follow
// the standards, so this is more of an approximation // the standards, so this is more of an approximation
[BTN_DPAD_UP] = GAMEPAD_BUTTON_LEFT_FACE_UP, [BTN_DPAD_UP] = GAMEPAD_BUTTON_LEFT_FACE_UP,
@@ -637,7 +637,7 @@ static uint32_t GetOrCreateFbForBo(struct gbm_bo *bo)
} }
// Renders a blank frame to allocate initial buffers // Renders a blank frame to allocate initial buffers
// TODO: WARNING: Platform layers do not include OpenGL code! // TODO: WARNING: Platform backend should not include OpenGL code
void RenderBlankFrame() void RenderBlankFrame()
{ {
glClearColor(0, 0, 0, 1); glClearColor(0, 0, 0, 1);
@@ -1213,9 +1213,9 @@ int InitPlatform(void)
TRACELOG(LOG_TRACE, "DISPLAY: Connector %i modes detected: %i", i, con->count_modes); TRACELOG(LOG_TRACE, "DISPLAY: Connector %i modes detected: %i", i, con->count_modes);
TRACELOG(LOG_TRACE, "DISPLAY: Connector %i status: %s", i, TRACELOG(LOG_TRACE, "DISPLAY: Connector %i status: %s", i,
(con->connection == DRM_MODE_CONNECTED) ? "CONNECTED" : (con->connection == DRM_MODE_CONNECTED)? "CONNECTED" :
(con->connection == DRM_MODE_DISCONNECTED) ? "DISCONNECTED" : (con->connection == DRM_MODE_DISCONNECTED)? "DISCONNECTED" :
(con->connection == DRM_MODE_UNKNOWNCONNECTION) ? "UNKNOWN" : "OTHER"); (con->connection == DRM_MODE_UNKNOWNCONNECTION)? "UNKNOWN" : "OTHER");
// In certain cases the status of the conneciton is reported as UKNOWN, but it is still connected // In certain cases the status of the conneciton is reported as UKNOWN, but it is still connected
// This might be a hardware or software limitation like on Raspberry Pi Zero with composite output // This might be a hardware or software limitation like on Raspberry Pi Zero with composite output
@@ -1298,7 +1298,7 @@ int InitPlatform(void)
} }
const bool allowInterlaced = FLAG_IS_SET(CORE.Window.flags, FLAG_INTERLACED_HINT); const bool allowInterlaced = FLAG_IS_SET(CORE.Window.flags, FLAG_INTERLACED_HINT);
const int fps = (CORE.Time.target > 0) ? (1.0/CORE.Time.target) : 60; const int fps = (CORE.Time.target > 0)? (1.0/CORE.Time.target) : 60;
// Try to find an exact matching mode // Try to find an exact matching mode
platform.modeIndex = FindExactConnectorMode(platform.connector, CORE.Window.screen.width, CORE.Window.screen.height, fps, allowInterlaced); platform.modeIndex = FindExactConnectorMode(platform.connector, CORE.Window.screen.width, CORE.Window.screen.height, fps, allowInterlaced);
@@ -1345,7 +1345,7 @@ int InitPlatform(void)
platform.connector->modes[0].name, platform.connector->modes[0].name,
platform.connector->modes[0].hdisplay, platform.connector->modes[0].hdisplay,
platform.connector->modes[0].vdisplay, platform.connector->modes[0].vdisplay,
(platform.connector->modes[0].flags & DRM_MODE_FLAG_INTERLACE) ? 'i' : 'p', (platform.connector->modes[0].flags & DRM_MODE_FLAG_INTERLACE)? 'i' : 'p',
platform.connector->modes[0].vrefresh); platform.connector->modes[0].vrefresh);
} }
else else
@@ -1740,10 +1740,10 @@ static void InitKeyboard(void)
else else
{ {
// Reconfigure keyboard mode to get: // Reconfigure keyboard mode to get:
// - scancodes (K_RAW) // - scancodes (K_RAW)
// - keycodes (K_MEDIUMRAW) // - keycodes (K_MEDIUMRAW)
// - ASCII chars (K_XLATE) // - ASCII chars (K_XLATE)
// - UNICODE chars (K_UNICODE) // - UNICODE chars (K_UNICODE)
ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE); // ASCII chars ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE); // ASCII chars
} }

View File

@@ -159,7 +159,7 @@ static const char *GetCanvasId(void);
bool WindowShouldClose(void) bool WindowShouldClose(void)
{ {
// Emscripten Asyncify is required to run synchronous code in asynchronous JS // Emscripten Asyncify is required to run synchronous code in asynchronous JS
// REF: https://emscripten.org/docs/porting/asyncify.html // Ref: https://emscripten.org/docs/porting/asyncify.html
// WindowShouldClose() is not called on a web-ready raylib application if using emscripten_set_main_loop() // WindowShouldClose() is not called on a web-ready raylib application if using emscripten_set_main_loop()
// and encapsulating one frame execution on a UpdateDrawFrame() function, // and encapsulating one frame execution on a UpdateDrawFrame() function,
@@ -309,8 +309,8 @@ void ToggleBorderlessWindowed(void)
if (enterBorderless) if (enterBorderless)
{ {
// NOTE: 1. The setTimeouts handle the browser mode change delay // 1. The setTimeouts handle the browser mode change delay
// 2. The style unset handles the possibility of a width="value%" like on the default shell.html file // 2. The style unset handles the possibility of a width="value%" like on the default shell.html file
EM_ASM EM_ASM
( (
setTimeout(function() setTimeout(function()
@@ -866,7 +866,6 @@ void EnableCursor(void)
// Disables cursor (lock cursor) // Disables cursor (lock cursor)
void DisableCursor(void) void DisableCursor(void)
{ {
// TODO: figure out how not to hard code the canvas ID here.
emscripten_request_pointerlock(GetCanvasId(), 1); emscripten_request_pointerlock(GetCanvasId(), 1);
// Set cursor position in the middle // Set cursor position in the middle
@@ -893,10 +892,9 @@ double GetTime(void)
} }
// Open URL with default system browser (if available) // Open URL with default system browser (if available)
// NOTE: This function is only safe to use if you control the URL given. // NOTE: This function is only safe to use if you control the URL given
// A user could craft a malicious string performing another action. // A user could craft a malicious string performing another action
// Only call this function yourself not with user input or make sure to check the string yourself. // Only call this function yourself not with user input or make sure to check the string yourself
// Ref: https://github.com/raysan5/raylib/issues/686
void OpenURL(const char *url) void OpenURL(const char *url)
{ {
// Security check to (partially) avoid malicious code on target platform // Security check to (partially) avoid malicious code on target platform
@@ -1090,10 +1088,6 @@ void PollInputEvents(void)
} }
CORE.Window.resizedLastFrame = false; CORE.Window.resizedLastFrame = false;
// TODO: This code does not seem to do anything??
//if (CORE.Window.eventWaiting) glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
//else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) --> WARNING: Where is key input reset?
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@@ -1161,8 +1155,8 @@ int InitPlatform(void)
} }
// NOTE: When asking for an OpenGL context version, most drivers provide the highest supported version // NOTE: When asking for an OpenGL context version, most drivers provide the highest supported version
// with backward compatibility to older OpenGL versions. // with backward compatibility to older OpenGL versions
// For example, if using OpenGL 1.1, driver can provide a 4.3 backwards compatible context. // For example, if using OpenGL 1.1, driver can provide a 4.3 backwards compatible context
// Check selection OpenGL version // Check selection OpenGL version
if (rlGetVersion() == RL_OPENGL_21) if (rlGetVersion() == RL_OPENGL_21)
@@ -1172,10 +1166,12 @@ int InitPlatform(void)
} }
else if (rlGetVersion() == RL_OPENGL_33) else if (rlGetVersion() == RL_OPENGL_33)
{ {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Choose OpenGL major version (just hint) glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Choose OpenGL major version (just hint)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint) glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above! // Profiles Hint, only OpenGL 3.3 and above
// Values: GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE // Possible values: GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); // Forward Compatibility Hint: Only 3.3 and above! glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); // Forward Compatibility Hint: Only 3.3 and above!
// glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Request OpenGL DEBUG context // glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Request OpenGL DEBUG context
} }
@@ -1198,7 +1194,6 @@ int InitPlatform(void)
} }
else if (rlGetVersion() == RL_OPENGL_ES_30) // Request OpenGL ES 3.0 context else if (rlGetVersion() == RL_OPENGL_ES_30) // Request OpenGL ES 3.0 context
{ {
// TODO: It seems WebGL 2.0 context is not set despite being requested
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
@@ -1217,8 +1212,8 @@ int InitPlatform(void)
// remember center for switchinging from fullscreen to window // remember center for switchinging from fullscreen to window
if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width)) if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))
{ {
// If screen width/height equal to the display, we can't calculate the window pos for toggling full-screened/windowed. // If screen width/height equal to the display, we can't calculate the window pos for toggling full-screened/windowed
// Toggling full-screened/windowed with pos(0, 0) can cause problems in some platforms, such as X11. // Toggling full-screened/windowed with pos(0, 0) can cause problems in some platforms, such as X11
CORE.Window.position.x = CORE.Window.display.width/4; CORE.Window.position.x = CORE.Window.display.width/4;
CORE.Window.position.y = CORE.Window.display.height/4; CORE.Window.position.y = CORE.Window.display.height/4;
} }
@@ -1714,7 +1709,7 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) CORE.Input.Touch.currentTouchState[i] = 0; else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) CORE.Input.Touch.currentTouchState[i] = 0;
} }
// Update mouse position if we detect a single touch. // Update mouse position if we detect a single touch
if (CORE.Input.Touch.pointCount == 1) if (CORE.Input.Touch.pointCount == 1)
{ {
CORE.Input.Mouse.currentPosition.x = CORE.Input.Touch.position[0].x; CORE.Input.Mouse.currentPosition.x = CORE.Input.Touch.position[0].x;

View File

@@ -2092,9 +2092,7 @@ float GetMusicTimePlayed(Music music)
int framesInFirstBuffer = music.stream.buffer->isSubBufferProcessed[0]? 0 : subBufferSize; int framesInFirstBuffer = music.stream.buffer->isSubBufferProcessed[0]? 0 : subBufferSize;
int framesInSecondBuffer = music.stream.buffer->isSubBufferProcessed[1]? 0 : subBufferSize; int framesInSecondBuffer = music.stream.buffer->isSubBufferProcessed[1]? 0 : subBufferSize;
int framesInBuffers = framesInFirstBuffer + framesInSecondBuffer; int framesInBuffers = framesInFirstBuffer + framesInSecondBuffer;
if ((unsigned int)framesInBuffers > music.frameCount) { if (((unsigned int)framesInBuffers > music.frameCount) && !music.looping) framesInBuffers = music.frameCount;
if (!music.looping) framesInBuffers = music.frameCount;
}
int framesSentToMix = music.stream.buffer->frameCursorPos%subBufferSize; int framesSentToMix = music.stream.buffer->frameCursorPos%subBufferSize;
int framesPlayed = (framesProcessed - framesInBuffers + framesSentToMix)%(int)music.frameCount; int framesPlayed = (framesProcessed - framesInBuffers + framesSentToMix)%(int)music.frameCount;
if (framesPlayed < 0) framesPlayed += music.frameCount; if (framesPlayed < 0) framesPlayed += music.frameCount;
@@ -2125,7 +2123,7 @@ AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
if (deviceBitsPerSample > 4) deviceBitsPerSample = 4; if (deviceBitsPerSample > 4) deviceBitsPerSample = 4;
deviceBitsPerSample *= AUDIO.System.device.playback.channels; deviceBitsPerSample *= AUDIO.System.device.playback.channels;
unsigned int subBufferSize = (AUDIO.Buffer.defaultSize == 0) ? (AUDIO.System.device.sampleRate/30*deviceBitsPerSample) : AUDIO.Buffer.defaultSize; unsigned int subBufferSize = (AUDIO.Buffer.defaultSize == 0)? (AUDIO.System.device.sampleRate/30*deviceBitsPerSample) : AUDIO.Buffer.defaultSize;
if (subBufferSize < periodSize) subBufferSize = periodSize; if (subBufferSize < periodSize) subBufferSize = periodSize;

View File

@@ -30,7 +30,7 @@
* - Windows (Win32, Win64) * - Windows (Win32, Win64)
* CONFIGURATION: * CONFIGURATION:
* #define SUPPORT_DEFAULT_FONT (default) * #define SUPPORT_DEFAULT_FONT (default)
* Default font is loaded on window initialization to be available for the user to render simple text. * Default font is loaded on window initialization to be available for the user to render simple text
* NOTE: If enabled, uses external module functions to load default raylib font (module: text) * NOTE: If enabled, uses external module functions to load default raylib font (module: text)
* *
* #define SUPPORT_CAMERA_SYSTEM * #define SUPPORT_CAMERA_SYSTEM
@@ -41,7 +41,7 @@
* Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag * Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag
* *
* #define SUPPORT_MOUSE_GESTURES * #define SUPPORT_MOUSE_GESTURES
* Mouse gestures are directly mapped like touches and processed by gestures system. * Mouse gestures are directly mapped like touches and processed by gestures system
* *
* #define SUPPORT_BUSY_WAIT_LOOP * #define SUPPORT_BUSY_WAIT_LOOP
* Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used * Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used
@@ -423,7 +423,7 @@ typedef enum AutomationEventType {
} AutomationEventType; } AutomationEventType;
// Event type to config events flags // Event type to config events flags
// TODO: Not used at the moment // WARNING: Not used at the moment
typedef enum { typedef enum {
EVENT_INPUT_KEYBOARD = 0, EVENT_INPUT_KEYBOARD = 0,
EVENT_INPUT_MOUSE = 1, EVENT_INPUT_MOUSE = 1,
@@ -534,12 +534,10 @@ const char *TextFormat(const char *text, ...); // Formatting of text with variab
// 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) // #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 #endif // SUPPORT_CLIPBOARD_IMAGE
// Include platform-specific submodules // Include platform-specific submodules
#if defined(PLATFORM_DESKTOP_GLFW) #if defined(PLATFORM_MEM)
#include "platforms/rcore_desktop_glfw.c" #include "platforms/rcore_desktop_glfw.c"
#elif defined(PLATFORM_DESKTOP_SDL) #elif defined(PLATFORM_DESKTOP_SDL)
#include "platforms/rcore_desktop_sdl.c" #include "platforms/rcore_desktop_sdl.c"
@@ -611,7 +609,9 @@ void InitWindow(int width, int height, const char *title)
{ {
TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION); TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);
#if defined(PLATFORM_DESKTOP_GLFW) #if defined(PLATFORM_MEM)
TRACELOG(LOG_INFO, "Platform backend: NONE (Memory Buffer)");
#elif defined(PLATFORM_DESKTOP_GLFW)
TRACELOG(LOG_INFO, "Platform backend: DESKTOP (GLFW)"); TRACELOG(LOG_INFO, "Platform backend: DESKTOP (GLFW)");
#elif defined(PLATFORM_DESKTOP_SDL) #elif defined(PLATFORM_DESKTOP_SDL)
TRACELOG(LOG_INFO, "Platform backend: DESKTOP (SDL)"); TRACELOG(LOG_INFO, "Platform backend: DESKTOP (SDL)");
@@ -1267,14 +1267,14 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
{ {
// After custom shader loading, we TRY to set default location names // After custom shader loading, we TRY to set default location names
// Default shader attribute locations have been binded before linking: // Default shader attribute locations have been binded before linking:
// vertex position location = 0 // - vertex position location = 0
// vertex texcoord location = 1 // - vertex texcoord location = 1
// vertex normal location = 2 // - vertex normal location = 2
// vertex color location = 3 // - vertex color location = 3
// vertex tangent location = 4 // - vertex tangent location = 4
// vertex texcoord2 location = 5 // - vertex texcoord2 location = 5
// vertex boneIds location = 6 // - vertex boneIds location = 6
// vertex boneWeights location = 7 // - vertex boneWeights location = 7
// NOTE: If any location is not found, loc point becomes -1 // NOTE: If any location is not found, loc point becomes -1
@@ -1543,8 +1543,6 @@ Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int heigh
// Calculate view matrix from camera look at (and transpose it) // Calculate view matrix from camera look at (and transpose it)
Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
// TODO: Why not use Vector3Transform(Vector3 v, Matrix mat)?
// Convert world position vector to quaternion // Convert world position vector to quaternion
Quaternion worldPos = { position.x, position.y, position.z, 1.0f }; Quaternion worldPos = { position.x, position.y, position.z, 1.0f };
@@ -2484,8 +2482,6 @@ bool IsFileNameValid(const char *fileName)
// Check non-glyph characters // Check non-glyph characters
if ((unsigned char)fileName[i] < 32) { valid = false; break; } if ((unsigned char)fileName[i] < 32) { valid = false; break; }
// TODO: Check trailing periods/spaces?
// Check if filename is not all periods // Check if filename is not all periods
if (fileName[i] != '.') allPeriods = false; if (fileName[i] != '.') allPeriods = false;
} }
@@ -3210,7 +3206,7 @@ bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
*/ */
// Export events as text // Export events as text
// TODO: Save to memory buffer and SaveFileText() // NOTE: Save to memory buffer and SaveFileText()
char *txtData = (char *)RL_CALLOC(256*list.count + 2048, sizeof(char)); // 256 characters per line plus some header char *txtData = (char *)RL_CALLOC(256*list.count + 2048, sizeof(char)); // 256 characters per line plus some header
int byteCount = 0; int byteCount = 0;
@@ -3279,7 +3275,7 @@ void PlayAutomationEvent(AutomationEvent event)
#if defined(SUPPORT_AUTOMATION_EVENTS) #if defined(SUPPORT_AUTOMATION_EVENTS)
// WARNING: When should event be played? After/before/replace PollInputEvents()? -> Up to the user! // WARNING: When should event be played? After/before/replace PollInputEvents()? -> Up to the user!
if (!automationEventRecording) // TODO: Allow recording events while playing? if (!automationEventRecording)
{ {
switch (event.type) switch (event.type)
{ {
@@ -3716,7 +3712,6 @@ int GetTouchY(void)
} }
// Get touch position XY for a touch point index (relative to screen size) // Get touch position XY for a touch point index (relative to screen size)
// TODO: Touch position should be scaled depending on display size and render size
Vector2 GetTouchPosition(int index) Vector2 GetTouchPosition(int index)
{ {
Vector2 position = { -1.0f, -1.0f }; Vector2 position = { -1.0f, -1.0f };
@@ -4015,13 +4010,11 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi
#if defined(SUPPORT_AUTOMATION_EVENTS) #if defined(SUPPORT_AUTOMATION_EVENTS)
// Automation event recording // Automation event recording
// Checking events in current frame and save them into currentEventList
// NOTE: Recording is by default done at EndDrawing(), before PollInputEvents() // NOTE: Recording is by default done at EndDrawing(), before PollInputEvents()
static void RecordAutomationEvent(void) static void RecordAutomationEvent(void)
{ {
// Checking events in current frame and save them into currentEventList if (currentEventList->count == currentEventList->capacity) return;
// TODO: How important is the current frame? Could it be modified?
if (currentEventList->count == currentEventList->capacity) return; // Security check
// Keyboard input events recording // Keyboard input events recording
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------

View File

@@ -903,6 +903,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
// It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi // It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi
// provided headers (despite being defined in official Khronos GLES2 headers) // provided headers (despite being defined in official Khronos GLES2 headers)
// TODO: Avoid raylib platform-dependant code on rlgl, it should be a completely portable library
#if defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
@@ -2921,7 +2922,7 @@ rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements)
batch.bufferCount = numBuffers; // Record buffer count batch.bufferCount = numBuffers; // Record buffer count
batch.drawCounter = 1; // Reset draws counter batch.drawCounter = 1; // Reset draws counter
batch.currentDepth = -1.0f; // Reset depth value batch.currentDepth = -1.0f; // Reset depth value
//-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
#endif #endif
@@ -2982,7 +2983,8 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
// Update batch vertex buffers // Update batch vertex buffers
//------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------
// NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0) // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
// TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (use a change detector flag?) // TODO: If no data changed on the CPU arrays there is no need to re-upload data to GPU,
// a flag can be used to detect changes but it would imply keeping a copy buffer and memcmp() both, does it worth it?
if (RLGL.State.vertexCounter > 0) if (RLGL.State.vertexCounter > 0)
{ {
// Activate elements VAO // Activate elements VAO
@@ -3900,7 +3902,7 @@ void rlUnloadFramebuffer(unsigned int id)
// TODO: Review warning retrieving object name in WebGL // TODO: Review warning retrieving object name in WebGL
// WARNING: WebGL: INVALID_ENUM: getFramebufferAttachmentParameter: invalid parameter name // WARNING: WebGL: INVALID_ENUM: getFramebufferAttachmentParameter: invalid parameter name
// https://registry.khronos.org/webgl/specs/latest/1.0/ // Ref: https://registry.khronos.org/webgl/specs/latest/1.0/
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId); glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId);
unsigned int depthIdU = (unsigned int)depthId; unsigned int depthIdU = (unsigned int)depthId;
@@ -4427,8 +4429,6 @@ void rlSetUniform(int locIndex, const void *value, int uniformType, int count)
#endif #endif
case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break;
default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized"); default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized");
// TODO: Support glUniform1uiv(), glUniform2uiv(), glUniform3uiv(), glUniform4uiv()
} }
#endif #endif
} }
@@ -4469,7 +4469,7 @@ void rlSetUniformMatrices(int locIndex, const Matrix *matrices, int count)
glUniformMatrix4fv(locIndex, count, true, (const float *)matrices); glUniformMatrix4fv(locIndex, count, true, (const float *)matrices);
#elif defined(GRAPHICS_API_OPENGL_ES2) #elif defined(GRAPHICS_API_OPENGL_ES2)
// WARNING: WebGL does not support Matrix transpose ("true" parameter) // WARNING: WebGL does not support Matrix transpose ("true" parameter)
// REF: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniformMatrix // Ref: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniformMatrix
glUniformMatrix4fv(locIndex, count, false, (const float *)matrices); glUniformMatrix4fv(locIndex, count, false, (const float *)matrices);
#endif #endif
} }

View File

@@ -3845,7 +3845,6 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float
// Draw a model points // Draw a model points
// WARNING: OpenGL ES 2.0 does not support point mode drawing // WARNING: OpenGL ES 2.0 does not support point mode drawing
// TODO: gate these properly for non es 2.0 versions only
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint) void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)
{ {
rlEnablePointMode(); rlEnablePointMode();
@@ -5021,7 +5020,7 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCou
animations[a].framePoses = (Transform **)RL_MALLOC(anim[a].num_frames*sizeof(Transform *)); animations[a].framePoses = (Transform **)RL_MALLOC(anim[a].num_frames*sizeof(Transform *));
memcpy(animations[a].name, fileDataPtr + iqmHeader->ofs_text + anim[a].name, 32); // I don't like this 32 here memcpy(animations[a].name, fileDataPtr + iqmHeader->ofs_text + anim[a].name, 32); // I don't like this 32 here
TRACELOG(LOG_INFO, "IQM Anim %s", animations[a].name); TRACELOG(LOG_INFO, "IQM Anim %s", animations[a].name);
// animations[a].framerate = anim.framerate; // TODO: Use animation framerate data? //animations[a].framerate = anim.framerate; // TODO: Use animation framerate data?
for (unsigned int j = 0; j < iqmHeader->num_poses; j++) for (unsigned int j = 0; j < iqmHeader->num_poses; j++)
{ {
@@ -5029,7 +5028,7 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCou
if (iqmHeader->num_joints > 0) if (iqmHeader->num_joints > 0)
memcpy(animations[a].bones[j].name, fileDataPtr + iqmHeader->ofs_text + joints[j].name, BONE_NAME_LENGTH*sizeof(char)); memcpy(animations[a].bones[j].name, fileDataPtr + iqmHeader->ofs_text + joints[j].name, BONE_NAME_LENGTH*sizeof(char));
else else
strcpy(animations[a].bones[j].name, "ANIMJOINTNAME"); // default bone name otherwise strcpy(animations[a].bones[j].name, "ANIMJOINTNAME"); // Default bone name otherwise
animations[a].bones[j].parent = poses[j].parent; animations[a].bones[j].parent = poses[j].parent;
} }
@@ -5875,8 +5874,8 @@ static Model LoadGLTF(const char *fileName)
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
// Load animation data // Load animation data
// REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skins // Ref: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skins
// REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skinned-mesh-attributes // Ref: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skinned-mesh-attributes
// //
// LIMITATIONS: // LIMITATIONS:
// - Only supports 1 armature per file, and skips loading it if there are multiple armatures // - Only supports 1 armature per file, and skips loading it if there are multiple armatures

View File

@@ -1169,9 +1169,9 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
} }
// Draw rectangle with rounded edges // Draw rectangle with rounded edges
// TODO: This function should be refactored to use RL_LINES, for consistency with other Draw*Lines()
void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color) void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color)
{ {
// NOTE: For line thicknes <=1.0f we use RL_LINES, otherwise wee use RL_QUADS/RL_TRIANGLES
DrawRectangleRoundedLinesEx(rec, roundness, segments, 1.0f, color); DrawRectangleRoundedLinesEx(rec, roundness, segments, 1.0f, color);
} }
@@ -1395,7 +1395,6 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f
{ {
// Use LINES to draw the outline // Use LINES to draw the outline
rlBegin(RL_LINES); rlBegin(RL_LINES);
// Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner // Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
{ {
@@ -1418,7 +1417,6 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f
rlVertex2f(point[i].x, point[i].y); rlVertex2f(point[i].x, point[i].y);
rlVertex2f(point[i + 1].x, point[i + 1].y); rlVertex2f(point[i + 1].x, point[i + 1].y);
} }
rlEnd(); rlEnd();
} }
} }

View File

@@ -1701,7 +1701,7 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
// Replace text string // Replace text string
// REQUIRES: strstr(), strncpy(), strcpy() // REQUIRES: strstr(), strncpy(), strcpy()
// TODO: If (replacement == NULL) remove "search" text // TODO: If (replacement == "") remove "search" text
// WARNING: Allocated memory must be manually freed // WARNING: Allocated memory must be manually freed
char *TextReplace(const char *text, const char *search, const char *replacement) char *TextReplace(const char *text, const char *search, const char *replacement)
{ {

View File

@@ -514,7 +514,7 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
image.data = qoi_decode(fileData, dataSize, &desc, (int) fileData[12]); image.data = qoi_decode(fileData, dataSize, &desc, (int) fileData[12]);
image.width = desc.width; image.width = desc.width;
image.height = desc.height; image.height = desc.height;
image.format = desc.channels == 4 ? PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 : PIXELFORMAT_UNCOMPRESSED_R8G8B8; image.format = (desc.channels == 4)? PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 : PIXELFORMAT_UNCOMPRESSED_R8G8B8;
image.mipmaps = 1; image.mipmaps = 1;
} }
} }
@@ -4001,9 +4001,7 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color
// [x] Consider fast path: no alpha blending required cases (src has no alpha) // [x] Consider fast path: no alpha blending required cases (src has no alpha)
// [x] Consider fast path: same src/dst format with no alpha -> direct line copy // [x] Consider fast path: same src/dst format with no alpha -> direct line copy
// [-] GetPixelColor(): Get Vector4 instead of Color, easier for ColorAlphaBlend() // [-] GetPixelColor(): Get Vector4 instead of Color, easier for ColorAlphaBlend()
// [ ] Support f32bit channels drawing // [ ] TODO: Support 16bit and 32bit (float) channels drawing
// TODO: Support PIXELFORMAT_UNCOMPRESSED_R32G32B32A32 and PIXELFORMAT_UNCOMPRESSED_R1616B16A16
Color colSrc, colDst, blend; Color colSrc, colDst, blend;
bool blendRequired = true; bool blendRequired = true;
@@ -4201,7 +4199,7 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
} }
/*else if (layout == CUBEMAP_LAYOUT_PANORAMA) /*else if (layout == CUBEMAP_LAYOUT_PANORAMA)
{ {
// TODO: implement panorama by converting image to square faces... // TODO: Implement panorama by converting image to square faces...
// Ref: https://github.com/denivip/panorama/blob/master/panorama.cpp // Ref: https://github.com/denivip/panorama/blob/master/panorama.cpp
} */ } */
else else
@@ -4227,6 +4225,7 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
} }
// Convert image data to 6 faces in a vertical column, that's the optimum layout for loading // Convert image data to 6 faces in a vertical column, that's the optimum layout for loading
// NOTE: Image formatting does not work with compressed textures
faces = GenImageColor(size, size*6, MAGENTA); faces = GenImageColor(size, size*6, MAGENTA);
ImageFormat(&faces, image.format); ImageFormat(&faces, image.format);
@@ -4239,8 +4238,6 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
} }
#endif #endif
// NOTE: Image formatting does not work with compressed textures
for (int i = 0; i < 6; i++) ImageDraw(&faces, mipmapped, faceRecs[i], (Rectangle){ 0, (float)size*i, (float)size, (float)size }, WHITE); for (int i = 0; i < 6; i++) ImageDraw(&faces, mipmapped, faceRecs[i], (Rectangle){ 0, (float)size*i, (float)size, (float)size }, WHITE);
UnloadImage(mipmapped); UnloadImage(mipmapped);
@@ -4309,13 +4306,11 @@ bool IsTextureValid(Texture2D texture)
{ {
bool result = false; bool result = false;
// TODO: Validate maximum texture size supported by GPU
if ((texture.id > 0) && // Validate OpenGL id (texture uplaoded to GPU) if ((texture.id > 0) && // Validate OpenGL id (texture uplaoded to GPU)
(texture.width > 0) && // Validate texture width (texture.width > 0) && // Validate texture width
(texture.height > 0) && // Validate texture height (texture.height > 0) && // Validate texture height
(texture.format > 0) && // Validate texture pixel format (texture.format > 0) && // Validate texture pixel format
(texture.mipmaps > 0)) result = true; // Validate texture mipmaps (at least 1 for basic mipmap level) (texture.mipmaps > 0)) result = true; // Validate texture mipmaps (at least 1 for basic mipmap level)
return result; return result;
} }
@@ -5412,7 +5407,7 @@ int GetPixelDataSize(int width, int height, int format)
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Convert half-float (stored as unsigned short) to float // Convert half-float (stored as unsigned short) to float
// REF: https://stackoverflow.com/questions/1659440/32-bit-to-16-bit-floating-point-conversion/60047308#60047308 // Ref: https://stackoverflow.com/questions/1659440/32-bit-to-16-bit-floating-point-conversion/60047308#60047308
static float HalfToFloat(unsigned short x) static float HalfToFloat(unsigned short x)
{ {
float result = 0.0f; float result = 0.0f;