Sfoglia il codice sorgente

Merge branch 'raysan5:master' into master

pull/5496/head
Catania 1 settimana fa
committed by GitHub
parent
commit
b55ece0798
Non sono state trovate chiavi note per questa firma nel database ID Chiave GPG: B5690EEEBB952194
15 ha cambiato i file con 131 aggiunte e 132 eliminazioni
  1. +25
    -25
      src/external/rlsw.h
  2. +2
    -2
      src/platforms/rcore_android.c
  3. +14
    -14
      src/platforms/rcore_desktop_glfw.c
  4. +21
    -24
      src/platforms/rcore_desktop_sdl.c
  5. +16
    -16
      src/platforms/rcore_desktop_win32.c
  6. +1
    -1
      src/platforms/rcore_memory.c
  7. +4
    -4
      src/platforms/rcore_web.c
  8. +5
    -5
      src/platforms/rcore_web_emscripten.c
  9. +10
    -8
      src/raudio.c
  10. +1
    -1
      src/raylib.h
  11. +14
    -14
      src/raymath.h
  12. +2
    -2
      src/rcore.c
  13. +4
    -4
      src/rlgl.h
  14. +2
    -2
      src/rmodels.c
  15. +10
    -10
      src/rshapes.c

+ 25
- 25
src/external/rlsw.h Vedi File

@ -1177,7 +1177,7 @@ static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4])
static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4]) static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4])
{ {
#if defined(SW_HAS_NEON) #if defined(SW_HAS_NEON)
uint8x8_t bytes8 = vld1_u8(src); //< Read 8 bytes, faster, but let's hope we're not at the end of the page (unlikely)...
uint8x8_t bytes8 = vld1_u8(src); // Reading 8 bytes, faster, but let's hope not hitting the end of the page (unlikely)...
uint16x8_t bytes16 = vmovl_u8(bytes8); uint16x8_t bytes16 = vmovl_u8(bytes8);
uint32x4_t ints = vmovl_u16(vget_low_u16(bytes16)); uint32x4_t ints = vmovl_u16(vget_low_u16(bytes16));
float32x4_t floats = vcvtq_f32_u32(ints); float32x4_t floats = vcvtq_f32_u32(ints);
@ -1224,8 +1224,8 @@ static inline uint32_t sw_half_to_float_ui(uint16_t h)
// denormal: flush to zero // denormal: flush to zero
r = (em < (1 << 10))? 0 : r; r = (em < (1 << 10))? 0 : r;
// infinity/NaN; note that we preserve NaN payload as a byproduct of unifying inf/nan cases
// 112 is an exponent bias fixup; since we already applied it once, applying it twice converts 31 to 255
// l">NOTE: infinity/NaN; NaN payload is preserved as a byproduct of unifying inf/nan cases
// 112 is an exponent bias fixup; since it is already applied once, applying it twice converts 31 to 255
r += (em >= (31 << 10))? (112 << 23) : 0; r += (em >= (31 << 10))? (112 << 23) : 0;
return s | r; return s | r;
@ -1252,7 +1252,7 @@ static inline uint16_t sw_half_from_float_ui(uint32_t ui)
// Overflow: infinity; 143 encodes exponent 16 // Overflow: infinity; 143 encodes exponent 16
h = (em >= (143 << 23))? 0x7c00 : h; h = (em >= (143 << 23))? 0x7c00 : h;
// ">NaN; note that we convert all types of NaN to qNaN
// l">NOTE: NaN; all types of NaN aree converted to qNaN
h = (em > (255 << 23))? 0x7e00 : h; h = (em > (255 << 23))? 0x7e00 : h;
return (uint16_t)(s | h); return (uint16_t)(s | h);
@ -1918,8 +1918,8 @@ 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
// number of operations here, but for now it works fine
// TODO: With a bit more cleverness thee number of operations can
// be clearly reduced, 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;
@ -1933,7 +1933,7 @@ static inline void sw_texture_sample_linear(float *color, const sw_texture_t *te
int x1 = x0 + 1; int x1 = x0 + 1;
int y1 = y0 + 1; int y1 = y0 + 1;
// NOTE: If the textures are POT we could avoid the division for SW_REPEAT
// NOTE: If the textures are POT, avoid the division for SW_REPEAT
if (tex->sWrap == SW_CLAMP) if (tex->sWrap == SW_CLAMP)
{ {
@ -1974,7 +1974,7 @@ static inline void sw_texture_sample_linear(float *color, const sw_texture_t *te
static inline void sw_texture_sample(float *color, const sw_texture_t *tex, float u, float v, float dUdx, float dUdy, float dVdx, float dVdy) static inline void sw_texture_sample(float *color, const sw_texture_t *tex, float u, float v, float dUdx, float dUdy, float dVdx, float dVdy)
{ {
// Previous method: There is no need to compute the square root // Previous method: There is no need to compute the square root
// because using the squared value, the comparison remains err">`L2 > 1.0f*1.0ferr">`
// because using the squared value, the comparison remains p">(L2 > 1.0f*1.0fp">)
//float du = sqrtf(dUdx*dUdx + dUdy*dUdy); //float du = sqrtf(dUdx*dUdx + dUdy*dUdy);
//float dv = sqrtf(dVdx*dVdx + dVdy*dVdy); //float dv = sqrtf(dVdx*dVdx + dVdy*dVdy);
//float L = (du > dv)? du : dv; //float L = (du > dv)? du : dv;
@ -2204,12 +2204,12 @@ 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,
// we perform the winding order test in homogeneous coordinates directly,
// before the perspective division (division by w)
// This test determines the orientation of the triangle in the (x,y,w) plane,
// which corresponds to the projected 2D winding order sign,
// even with negative w values
// To handle triangles crossing the w=0 plane correctly,
// the winding order test is performeed in homogeneous coordinates directly,
// before the perspective division (division by w)
// This test determines the orientation of the triangle in the (x,y,w) plane,
// which corresponds to the projected 2D winding order sign,
// 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;
@ -2558,13 +2558,13 @@ 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,
// we perform the winding order test in homogeneous coordinates directly,
// before the perspective division (division by w)
// 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
// of the triangle P0 P1 P2. We use the homogeneous triangle
// winding test on this first triangle
// To handle quads crossing the w=0 plane correctly,
// the winding order test is performed in homogeneous coordinates directly,
// before the perspective division (division by w)
// 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
// of the triangle P0 P1 P2. The homogeneous triangle is used on
// 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;
@ -2649,7 +2649,7 @@ static inline bool sw_quad_is_axis_aligned(void)
{ {
// Reject quads with perspective projection // Reject quads with perspective projection
// The fast path assumes affine (non-perspective) quads, // The fast path assumes affine (non-perspective) quads,
// so we require all vertices to have homogeneous w = 1.0
// so it's required for all vertices to have homogeneous w = 1.0
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
if (RLSW.vertexBuffer[i].homogeneous[3] != 1.0f) return false; if (RLSW.vertexBuffer[i].homogeneous[3] != 1.0f) return false;
@ -2721,7 +2721,7 @@ static inline void sw_quad_sort_cw(const sw_vertex_t* *output)
// TODO: REVIEW: Could a perfectly aligned quad, where one of the four points has a different depth, // TODO: REVIEW: Could a perfectly aligned quad, where one of the four points has a different depth,
// still appear perfectly aligned from a certain point of view? // still appear perfectly aligned from a certain point of view?
// Because in that case, we would still need to perform perspective division for textures and colors...
// Because in that case, it's still needed to perform perspective division for textures and colors...
#define DEFINE_QUAD_RASTER_AXIS_ALIGNED(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \ #define DEFINE_QUAD_RASTER_AXIS_ALIGNED(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \
static inline void FUNC_NAME(void) \ static inline void FUNC_NAME(void) \
{ \ { \
@ -3090,7 +3090,7 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \
\ \
for (int i = 0; i < numPixels; i++) \ for (int i = 0; i < numPixels; i++) \
{ \ { \
/* REVIEW: May require reviewing projection details */ \
/* TODO: REVIEW: May require reviewing projection details */ \
int px = (int)(x - 0.5f); \ int px = (int)(x - 0.5f); \
int py = (int)(y - 0.5f); \ int py = (int)(y - 0.5f); \
\ \
@ -3721,7 +3721,7 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr
ySrc = sw_clampi(ySrc, 0, hSrc); ySrc = sw_clampi(ySrc, 0, hSrc);
// Check if the sizes are identical after clamping the source to avoid unexpected issues // Check if the sizes are identical after clamping the source to avoid unexpected issues
// REVIEW: This repeats the operations if true, so we could make a copy function without these checks
// TODO: REVIEW: This repeats the operations if true, so a copy function can be made without these checks
if (xDst == xSrc && yDst == ySrc && wDst == wSrc && hDst == hSrc) if (xDst == xSrc && yDst == ySrc && wDst == wSrc && hDst == hSrc)
{ {
swCopyFramebuffer(xSrc, ySrc, wSrc, hSrc, format, type, pixels); swCopyFramebuffer(xSrc, ySrc, wSrc, hSrc, format, type, pixels);

+ 2
- 2
src/platforms/rcore_android.c Vedi File

@ -1189,7 +1189,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
if (FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) || if (FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) ||
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD))
{ {
// For now we'll assume a single gamepad which we "detect" on its input event
// Assuming a single gamepad, "detected" on its input event
CORE.Input.Gamepad.ready[0] = true; CORE.Input.Gamepad.ready[0] = true;
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_LEFT_X] = AMotionEvent_getAxisValue( CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_LEFT_X] = AMotionEvent_getAxisValue(
@ -1256,7 +1256,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) && FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) &&
!FLAG_IS_SET(source, AINPUT_SOURCE_KEYBOARD)) !FLAG_IS_SET(source, AINPUT_SOURCE_KEYBOARD))
{ {
// For now we'll assume a single gamepad which we "detect" on its input event
// Assuming a single gamepad, "detected" on its input event
CORE.Input.Gamepad.ready[0] = true; CORE.Input.Gamepad.ready[0] = true;
GamepadButton button = AndroidTranslateGamepadButton(keycode); GamepadButton button = AndroidTranslateGamepadButton(keycode);

+ 14
- 14
src/platforms/rcore_desktop_glfw.c Vedi File

@ -602,7 +602,7 @@ void SetWindowIcon(Image image)
icon[0].height = image.height; icon[0].height = image.height;
icon[0].pixels = (unsigned char *)image.data; icon[0].pixels = (unsigned char *)image.data;
// NOTE 1: We only support one image icon
// NOTE 1: Only one image icon supported
// NOTE 2: The specified image data is copied before this function returns // NOTE 2: The specified image data is copied before this function returns
glfwSetWindowIcon(platform.handle, 1, icon); glfwSetWindowIcon(platform.handle, 1, icon);
} }
@ -833,7 +833,7 @@ int GetCurrentMonitor(void)
} }
else else
{ {
// In case the window is between two monitors, we use below logic
// In case the window is between two monitors, below logic is used
// to try to detect the "current monitor" for that window, note that // to try to detect the "current monitor" for that window, note that
// this is probably an overengineered solution for a very side case // this is probably an overengineered solution for a very side case
// trying to match SDL behaviour // trying to match SDL behaviour
@ -1186,7 +1186,7 @@ void SetMouseCursor(int cursor)
if (cursor == MOUSE_CURSOR_DEFAULT) glfwSetCursor(platform.handle, NULL); if (cursor == MOUSE_CURSOR_DEFAULT) glfwSetCursor(platform.handle, NULL);
else else
{ {
// NOTE: We are relating internal GLFW enum values to our MouseCursor enum values
// NOTE: Mapping internal GLFW enum values to MouseCursor enum values
glfwSetCursor(platform.handle, glfwCreateStandardCursor(0x00036000 + cursor)); glfwSetCursor(platform.handle, glfwCreateStandardCursor(0x00036000 + cursor));
} }
} }
@ -1247,7 +1247,7 @@ void PollInputEvents(void)
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
// NOTE: We do it here in case of disconnection
// NOTE: Doing it here in case of disconnection
for (int i = 0; i < MAX_GAMEPADS; i++) for (int i = 0; i < MAX_GAMEPADS; i++)
{ {
if (glfwJoystickPresent(i)) CORE.Input.Gamepad.ready[i] = true; if (glfwJoystickPresent(i)) CORE.Input.Gamepad.ready[i] = true;
@ -1263,7 +1263,7 @@ void PollInputEvents(void)
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k]; for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
// Get current gamepad state // Get current gamepad state
// NOTE: There is no callback available, so we get it manually
// NOTE: There is no callback available, getting it manually
GLFWgamepadstate state = { 0 }; GLFWgamepadstate state = { 0 };
int result = glfwGetGamepadState(i, &state); // This remaps all gamepads so they have their buttons mapped like an xbox controller int result = glfwGetGamepadState(i, &state); // This remaps all gamepads so they have their buttons mapped like an xbox controller
if (result == GLFW_FALSE) // No joystick is connected, no gamepad mapping or an error occurred if (result == GLFW_FALSE) // No joystick is connected, no gamepad mapping or an error occurred
@ -1359,8 +1359,8 @@ void PollInputEvents(void)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// 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
// Function wrappers around RL_*ALLOC macros, used by glfwInitAllocator() inside of InitPlatform()
// GLFWallocator expects function pointers with specific signatures to be provided
// REF: 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)
{ {
@ -1742,7 +1742,7 @@ int InitPlatform(void)
for (int i = 0; i < MAX_GAMEPADS; i++) for (int i = 0; i < MAX_GAMEPADS; i++)
{ {
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH, // 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)
// only copying up to (MAX_GAMEPAD_NAME_LENGTH - 1)
if (glfwJoystickPresent(i)) if (glfwJoystickPresent(i))
{ {
CORE.Input.Gamepad.ready[i] = true; CORE.Input.Gamepad.ready[i] = true;
@ -1819,8 +1819,8 @@ static void FramebufferSizeCallback(GLFWwindow *window, int width, int height)
{ {
//TRACELOG(LOG_INFO, "GLFW3: Window framebuffer size callback called [%i,%i]", width, height); //TRACELOG(LOG_INFO, "GLFW3: Window framebuffer size callback called [%i,%i]", width, height);
// WARNING: On window minimization, callback is called,
// but we don't want to change internal screen values, it breaks things
// WARNING: On window minimization, callback is called with 0 values,
// but internal screen values should not be changed, it breaks things
if ((width == 0) || (height == 0)) return; if ((width == 0) || (height == 0)) return;
// Reset viewport and projection matrix for new size // Reset viewport and projection matrix for new size
@ -1926,7 +1926,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
{ {
if (count > 0) if (count > 0)
{ {
// In case previous dropped filepaths have not been freed, we free them
// In case previous dropped filepaths have not been freed, free them
if (CORE.Window.dropFileCount > 0) if (CORE.Window.dropFileCount > 0)
{ {
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]); for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);
@ -1937,7 +1937,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
CORE.Window.dropFilepaths = NULL; CORE.Window.dropFilepaths = NULL;
} }
// WARNING: Paths are freed by GLFW when the callback returns, we must keep an internal copy
// WARNING: Paths are freed by GLFW when the callback returns, keeping an internal copy
CORE.Window.dropFileCount = count; CORE.Window.dropFileCount = count;
CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *)); CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *));
@ -1954,7 +1954,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
{ {
if (key < 0) return; // Security check, macOS fn key generates -1 if (key < 0) return; // Security check, macOS fn key generates -1
// WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1
// WARNING: GLFW could return GLFW_REPEAT, it needs to be considered as 1
// to work properly with our implementation (IsKeyDown/IsKeyUp checks) // to work properly with our implementation (IsKeyDown/IsKeyUp checks)
if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0; if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0;
else if (action == GLFW_PRESS) CORE.Input.Keyboard.currentKeyState[key] = 1; else if (action == GLFW_PRESS) CORE.Input.Keyboard.currentKeyState[key] = 1;
@ -2079,7 +2079,7 @@ static void JoystickCallback(int jid, int event)
if (event == GLFW_CONNECTED) if (event == GLFW_CONNECTED)
{ {
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH, // 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
// only copy up to (MAX_GAMEPAD_NAME_LENGTH -1) to destination string
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH); memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1); strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
} }

+ 21
- 24
src/platforms/rcore_desktop_sdl.c Vedi File

@ -49,7 +49,7 @@
#define USING_SDL3_PROJECT #define USING_SDL3_PROJECT
#endif #endif
#ifndef SDL_ENABLE_OLD_NAMES #ifndef SDL_ENABLE_OLD_NAMES
#define SDL_ENABLE_OLD_NAMES // Just in case we're on SDL3, we need some in-between compatibily
#define SDL_ENABLE_OLD_NAMES // Just in case on SDL3, some in-between compatibily is needed
#endif #endif
// SDL base library (window/rendered, input, timing... functionality) // SDL base library (window/rendered, input, timing... functionality)
#ifdef USING_SDL3_PROJECT #ifdef USING_SDL3_PROJECT
@ -254,10 +254,10 @@ static const int CursorsLUT[] = {
#if defined(USING_VERSION_SDL3) #if defined(USING_VERSION_SDL3)
// SDL3 Migration: // SDL3 Migration:
// SDL_WINDOW_FULLSCREEN_DESKTOP has been removed,
// and you can call SDL_GetWindowFullscreenMode()
// to see whether an exclusive fullscreen mode will be used
// or the borderless fullscreen desktop mode will be used
// SDL_WINDOW_FULLSCREEN_DESKTOP has been removed,
// and you can call SDL_GetWindowFullscreenMode()
// to see whether an exclusive fullscreen mode will be used
// or the borderless fullscreen desktop mode will be used
#define SDL_WINDOW_FULLSCREEN_DESKTOP SDL_WINDOW_FULLSCREEN #define SDL_WINDOW_FULLSCREEN_DESKTOP SDL_WINDOW_FULLSCREEN
#define SDL_IGNORE false #define SDL_IGNORE false
@ -340,9 +340,8 @@ SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth
} }
// SDL3 Migration: // SDL3 Migration:
// SDL_GetDisplayDPI() -
// not reliable across platforms, approximately replaced by multiplying
// SDL_GetWindowDisplayScale() times 160 on iPhone and Android, and 96 on other platforms
// SDL_GetDisplayDPI() not reliable across platforms, approximately replaced by multiplying
// SDL_GetWindowDisplayScale() times 160 on iPhone and Android, and 96 on other platforms
// returns 0 on success or a negative error code on failure // returns 0 on success or a negative error code on failure
int SDL_GetDisplayDPI(int displayIndex, float *ddpi, float *hdpi, float *vdpi) int SDL_GetDisplayDPI(int displayIndex, float *ddpi, float *hdpi, float *vdpi)
{ {
@ -413,7 +412,7 @@ int SDL_GetNumTouchFingers(SDL_TouchID touchID)
return count; return count;
} }
#else // We're on SDL2
#else // SDL2 fallback
// Since SDL2 doesn't have this function we leave a stub // Since SDL2 doesn't have this function we leave a stub
// SDL_GetClipboardData function is available since SDL 3.1.3. (e.g. SDL3) // SDL_GetClipboardData function is available since SDL 3.1.3. (e.g. SDL3)
@ -833,10 +832,9 @@ void SetWindowMonitor(int monitor)
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < monitorCount))
#endif #endif
{ {
// NOTE:
// 1. SDL started supporting moving exclusive fullscreen windows between displays on SDL3,
// see commit https://github.com/libsdl-org/SDL/commit/3f5ef7dd422057edbcf3e736107e34be4b75d9ba
// 2. A workaround for SDL2 is leaving fullscreen, moving the window, then entering full screen again
// NOTE 1: SDL started supporting moving exclusive fullscreen windows between displays on SDL3,
// see commit https://github.com/libsdl-org/SDL/commit/3f5ef7dd422057edbcf3e736107e34be4b75d9ba
// NOTE 2: A workaround for SDL2 is leaving fullscreen, moving the window, then entering full screen again
const bool wasFullscreen = (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))? true : false; const bool wasFullscreen = (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))? true : false;
const int screenWidth = CORE.Window.screen.width; const int screenWidth = CORE.Window.screen.width;
@ -854,14 +852,13 @@ void SetWindowMonitor(int monitor)
// If the screen size is larger than the monitor usable area, anchor it on the top left corner, otherwise, center it // If the screen size is larger than the monitor usable area, anchor it on the top left corner, otherwise, center it
if ((screenWidth >= usableBounds.w) || (screenHeight >= usableBounds.h)) if ((screenWidth >= usableBounds.w) || (screenHeight >= usableBounds.h))
{ {
// NOTE:
// 1. There's a known issue where if the window larger than the target display bounds,
// when moving the windows to that display, the window could be clipped back
// ending up positioned partly outside the target display
// 2. The workaround for that is, previously to moving the window,
// setting the window size to the target display size, so they match
// 3. It wasn't done here because we can't assume changing the window size automatically
// is acceptable behavior by the user
// NOTE 1: There's a known issue where if the window larger than the target display bounds,
// when moving the windows to that display, the window could be clipped back
// ending up positioned partly outside the target display
// NOTE 2: The workaround for that is, previously to moving the window,
// setting the window size to the target display size, so they match
// NOTE 3: It wasn't done here because we can't assume changing the window size automatically
// is acceptable behavior by the user
SDL_SetWindowPosition(platform.window, usableBounds.x, usableBounds.y); SDL_SetWindowPosition(platform.window, usableBounds.x, usableBounds.y);
CORE.Window.position.x = usableBounds.x; CORE.Window.position.x = usableBounds.x;
CORE.Window.position.y = usableBounds.y; CORE.Window.position.y = usableBounds.y;
@ -1250,7 +1247,7 @@ void DisableCursor(void)
void SwapScreenBuffer(void) void SwapScreenBuffer(void)
{ {
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE) #if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
// NOTE: We use a preprocessor condition here because err">`rlCopyFramebuffer` is only declared for software rendering
// NOTE: We use a preprocessor condition here because n">rlCopyFramebuffer() is only declared for software rendering
SDL_Surface *surface = SDL_GetWindowSurface(platform.window); SDL_Surface *surface = SDL_GetWindowSurface(platform.window);
rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, surface->pixels); rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, surface->pixels);
SDL_UpdateWindowSurface(platform.window); SDL_UpdateWindowSurface(platform.window);
@ -1617,7 +1614,7 @@ void PollInputEvents(void)
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
{ {
// NOTE: SDL2 mouse button order is LEFT, MIDDLE, RIGHT, but raylib uses LEFT, RIGHT, MIDDLE like GLFW // NOTE: SDL2 mouse button order is LEFT, MIDDLE, RIGHT, but raylib uses LEFT, RIGHT, MIDDLE like GLFW
// The following conditions align SDL with raylib.h MouseButton enum order
// The following conditions align SDL with raylib.h MouseButton enum order
int btn = event.button.button - 1; int btn = event.button.button - 1;
if (btn == 2) btn = 1; if (btn == 2) btn = 1;
else if (btn == 1) btn = 2; else if (btn == 1) btn = 2;
@ -1630,7 +1627,7 @@ void PollInputEvents(void)
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
{ {
// NOTE: SDL2 mouse button order is LEFT, MIDDLE, RIGHT, but raylib uses LEFT, RIGHT, MIDDLE like GLFW // NOTE: SDL2 mouse button order is LEFT, MIDDLE, RIGHT, but raylib uses LEFT, RIGHT, MIDDLE like GLFW
// The following conditions align SDL with raylib.h MouseButton enum order
// The following conditions align SDL with raylib.h MouseButton enum order
int btn = event.button.button - 1; int btn = event.button.button - 1;
if (btn == 2) btn = 1; if (btn == 2) btn = 1;
else if (btn == 1) btn = 2; else if (btn == 1) btn = 2;

+ 16
- 16
src/platforms/rcore_desktop_win32.c Vedi File

@ -433,7 +433,7 @@ static bool UpdateWindowSize(int mode, HWND hwnd, int width, int height, unsigne
return true; return true;
} }
// Verify if we are running in Windows 10 version 1703 (Creators Update)
// Check if running in Windows 10 version 1703 (Creators Update)
static BOOL IsWindows10Version1703OrGreaterWin32(void) static BOOL IsWindows10Version1703OrGreaterWin32(void)
{ {
HMODULE ntdll = LoadLibraryW(L"ntdll.dll"); HMODULE ntdll = LoadLibraryW(L"ntdll.dll");
@ -1138,7 +1138,7 @@ void ShowCursor(void)
// Hides mouse cursor // Hides mouse cursor
void HideCursor(void) void HideCursor(void)
{ {
// NOTE: We use SetCursor() instead of ShowCursor() because
// NOTE: Using SetCursor() instead of ShowCursor() because
// it makes it easy to only hide the cursor while it's inside the client area // it makes it easy to only hide the cursor while it's inside the client area
SetCursor(NULL); SetCursor(NULL);
CORE.Input.Mouse.cursorHidden = true; CORE.Input.Mouse.cursorHidden = true;
@ -1345,7 +1345,7 @@ void PollInputEvents(void)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Initialize modern OpenGL context // Initialize modern OpenGL context
// NOTE: We need to create a dummy context first to query required extensions
// NOTE: Creating a dummy context first to query required extensions
HGLRC InitOpenGL(HWND hwnd, HDC hdc) HGLRC InitOpenGL(HWND hwnd, HDC hdc)
{ {
// First, create a dummy context to get WGL extensions // First, create a dummy context to get WGL extensions
@ -1460,7 +1460,7 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc)
0 // Terminator 0 // Terminator
}; };
// NOTE: We are not sharing context resources so, second parameters is NULL
// NOTE: Not sharing context resources so, second parameters is NULL
realContext = wglCreateContextAttribsARB(hdc, NULL, contextAttribs); realContext = wglCreateContextAttribsARB(hdc, NULL, contextAttribs);
// Check for error context creation errors // Check for error context creation errors
@ -1476,8 +1476,8 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc)
// Activate real context // Activate real context
if (realContext) wglMakeCurrent(hdc, realContext); if (realContext) wglMakeCurrent(hdc, realContext);
// Once we got a real modern OpenGL context,
// we can load required extensions (function pointers)
// Once a real modern OpenGL context is created,
// required extensions can be loaded (function pointers)
rlLoadExtensions(WglGetProcAddress); rlLoadExtensions(WglGetProcAddress);
return realContext; return realContext;
@ -1521,7 +1521,7 @@ int InitPlatform(void)
.lpfnWndProc = WndProc, // Custom procedure assigned .lpfnWndProc = WndProc, // Custom procedure assigned
.cbWndExtra = sizeof(LONG_PTR), // extra space for the Tuple object ptr .cbWndExtra = sizeof(LONG_PTR), // extra space for the Tuple object ptr
.hInstance = hInstance, .hInstance = hInstance,
.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW), // TODO: Audit if we want to set this since we're implementing WM_SETCURSOR
.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW), // TODO: Check if this is really required, since WM_SETCURSOR event is processed
.lpszClassName = CLASS_NAME // Class name: L"raylibWindow" .lpszClassName = CLASS_NAME // Class name: L"raylibWindow"
}; };
@ -1854,8 +1854,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
SIZE *inoutSize = (SIZE *)lparam; SIZE *inoutSize = (SIZE *)lparam;
UINT newDpi = (UINT)wparam; // TODO: WARNING: Converting from WPARAM = UINT_PTR UINT newDpi = (UINT)wparam; // TODO: WARNING: Converting from WPARAM = UINT_PTR
// k">for any of these other cases, we might want to post a window
// ">resize event after the dpi changes?
// n">For the following flag changes, a window resize event should be posted,
// l">TODO: Should it be done after dpi changes?
if (CORE.Window.flags & FLAG_WINDOW_MINIMIZED) return TRUE; if (CORE.Window.flags & FLAG_WINDOW_MINIMIZED) return TRUE;
if (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) return TRUE; if (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) return TRUE;
if (CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) return TRUE; if (CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) return TRUE;
@ -2025,8 +2025,8 @@ static void HandleRawInput(LPARAM lparam)
if (input.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) TRACELOG(LOG_ERROR, "TODO: handle virtual desktop mouse inputs!"); if (input.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) TRACELOG(LOG_ERROR, "TODO: handle virtual desktop mouse inputs!");
// Trick to keep the mouse position at 0,0 and instead move
// the previous position so we can still get a proper mouse delta
// Trick to keep the mouse position at p">(0,0) and instead move
// the previous position so a proper mouse delta can still be retrieved
//CORE.Input.Mouse.previousPosition.x -= input.data.mouse.lLastX; //CORE.Input.Mouse.previousPosition.x -= input.data.mouse.lLastX;
//CORE.Input.Mouse.previousPosition.y -= input.data.mouse.lLastY; //CORE.Input.Mouse.previousPosition.y -= input.data.mouse.lLastY;
//if (CORE.Input.Mouse.currentPosition.x != 0) abort(); //if (CORE.Input.Mouse.currentPosition.x != 0) abort();
@ -2138,12 +2138,12 @@ static unsigned SanitizeFlags(int mode, unsigned flags)
// This design takes care of many odd corner cases. For example, if you want to restore // This design takes care of many odd corner cases. For example, if you want to restore
// a window that was previously maximized AND minimized and you want to remove both these // a window that was previously maximized AND minimized and you want to remove both these
// flags, you actually need to call ShowWindow with SW_RESTORE twice. Another example is // flags, you actually need to call ShowWindow with SW_RESTORE twice. Another example is
// if you have a maximized window, if the undecorated flag is modified then we'd need to
// update the window style, but updating the style would mean the window size would change
// causing the window to lose its Maximized state which would mean we'd need to update the
// window size and then update the window style a second time to restore that maximized
// if you have a maximized window, if the undecorated flag is modified then the window style
// needs to be updated, but updating the style would mean the window size would change
// causing the window to lose its Maximized state which would mean the window size
// needs to be updated, followed by the update of window style, a second time, to restore that maximized
// state. This implementation is able to handle any/all of these special situations with a // state. This implementation is able to handle any/all of these special situations with a
// retry loop that continues until we either reach the desired state or the state stops changing
// retry loop that continues until either the desired state is reached or the state stops changing
static void UpdateFlags(HWND hwnd, unsigned desiredFlags, int width, int height) static void UpdateFlags(HWND hwnd, unsigned desiredFlags, int width, int height)
{ {
// Flags that just apply immediately without needing any operations // Flags that just apply immediately without needing any operations

+ 1
- 1
src/platforms/rcore_memory.c Vedi File

@ -499,7 +499,7 @@ int InitPlatform(void)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// If everything work as expected, we can continue
// If everything worked as expected, continue
CORE.Window.render.width = CORE.Window.screen.width; CORE.Window.render.width = CORE.Window.screen.width;
CORE.Window.render.height = CORE.Window.screen.height; CORE.Window.render.height = CORE.Window.screen.height;
CORE.Window.currentFbo.width = CORE.Window.render.width; CORE.Window.currentFbo.width = CORE.Window.render.width;

+ 4
- 4
src/platforms/rcore_web.c Vedi File

@ -953,8 +953,8 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
if (duration > MAX_GAMEPAD_VIBRATION_TIME) duration = MAX_GAMEPAD_VIBRATION_TIME; if (duration > MAX_GAMEPAD_VIBRATION_TIME) duration = MAX_GAMEPAD_VIBRATION_TIME;
duration *= 1000.0f; // Convert duration to ms duration *= 1000.0f; // Convert duration to ms
// Note: At the moment (2024.10.21) Chrome, Edge, Opera, Safari, Android Chrome, Android Webview only support the vibrationActuator API,
// and Firefox only supports the hapticActuators API
// NOTE: At the moment (2024.10.21) Chrome, Edge, Opera, Safari, Android Chrome, Android Webview only support the vibrationActuator API,
// and Firefox only supports the hapticActuators API
EM_ASM({ EM_ASM({
try try
{ {
@ -1798,8 +1798,8 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
// Emscripten: Called on fullscreen change events // Emscripten: Called on fullscreen change events
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData) static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData)
{ {
// l">NOTE: 1. Reset the fullscreen flags if the user left fullscreen manually by pressing the Escape key
// 2. Which is a necessary safeguard because that case will bypass the toggles CORE.Window.flags resets
// ">NOTE 1: Reset the fullscreen flags if the user left fullscreen manually by pressing the Escape key
// NOTE 2: Which is a necessary safeguard because that case will bypass the toggles CORE.Window.flags resets
if (platform.ourFullscreen) platform.ourFullscreen = false; if (platform.ourFullscreen) platform.ourFullscreen = false;
else else
{ {

+ 5
- 5
src/platforms/rcore_web_emscripten.c Vedi File

@ -137,7 +137,7 @@ bool WindowShouldClose(void)
// and encapsulating one frame execution on a UpdateDrawFrame() function, // and encapsulating one frame execution on a UpdateDrawFrame() function,
// allowing the browser to manage execution asynchronously // allowing the browser to manage execution asynchronously
// ">Optionally we can manage the time we give-control-back-to-browser k">if required,
// l">NOTE: Optionally, time can be managed, giving control back-to-browser n">as required,
// but it seems below line could generate stuttering on some browsers // but it seems below line could generate stuttering on some browsers
emscripten_sleep(12); emscripten_sleep(12);
@ -1358,7 +1358,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
{ {
if (count > 0) if (count > 0)
{ {
// In case previous dropped filepaths have not been freed, we free them
// In case previous dropped filepaths have not been freed, free them
if (CORE.Window.dropFileCount > 0) if (CORE.Window.dropFileCount > 0)
{ {
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]); for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);
@ -1369,7 +1369,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
CORE.Window.dropFilepaths = NULL; CORE.Window.dropFilepaths = NULL;
} }
// WARNING: Paths are freed by GLFW when the callback returns, we must keep an internal copy
// WARNING: Paths are freed by GLFW when the callback returns, an internal copy should be kept
CORE.Window.dropFileCount = count; CORE.Window.dropFileCount = count;
CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *)); CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *));
@ -1610,7 +1610,7 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
double canvasWidth = 0.0; double canvasWidth = 0.0;
double canvasHeight = 0.0; double canvasHeight = 0.0;
// NOTE: emscripten_get_canvas_element_size() returns canvas.width and canvas.height but // NOTE: emscripten_get_canvas_element_size() returns canvas.width and canvas.height but
// we are looking for actual CSS size: canvas.style.width and canvas.style.height
// looking for actual CSS size: canvas.style.width and canvas.style.height
// EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight); // EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
emscripten_get_element_css_size(platform.canvasId, &canvasWidth, &canvasHeight); emscripten_get_element_css_size(platform.canvasId, &canvasWidth, &canvasHeight);
@ -1630,7 +1630,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 a single touch is detected
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;

+ 10
- 8
src/raudio.c Vedi File

@ -2418,7 +2418,7 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
audioBuffer->frameCursorPos = (audioBuffer->frameCursorPos + framesToRead)%audioBuffer->sizeInFrames; audioBuffer->frameCursorPos = (audioBuffer->frameCursorPos + framesToRead)%audioBuffer->sizeInFrames;
framesRead += framesToRead; framesRead += framesToRead;
// If we've read to the end of the buffer, mark it as processed
// If the end of the buffer is read, mark it as processed
if (framesToRead == framesRemainingInOutputBuffer) if (framesToRead == framesRemainingInOutputBuffer)
{ {
audioBuffer->isSubBufferProcessed[currentSubBufferIndex] = true; audioBuffer->isSubBufferProcessed[currentSubBufferIndex] = true;
@ -2426,7 +2426,7 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
currentSubBufferIndex = (currentSubBufferIndex + 1)%2; currentSubBufferIndex = (currentSubBufferIndex + 1)%2;
// We need to break from this loop if we're not looping
// Break from this loop if looping not enabled
if (!audioBuffer->looping) if (!audioBuffer->looping)
{ {
StopAudioBufferInLockedState(audioBuffer); StopAudioBufferInLockedState(audioBuffer);
@ -2453,10 +2453,12 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
// Reads audio data from an AudioBuffer object in device format, returned data will be in a format appropriate for mixing // Reads audio data from an AudioBuffer object in device format, returned data will be in a format appropriate for mixing
static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, float *framesOut, ma_uint32 frameCount) static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, float *framesOut, ma_uint32 frameCount)
{ {
// What's going on here is that we're continuously converting data from the AudioBuffer's internal format to the mixing format, which
// should be defined by the output format of the data converter. We do this until frameCount frames have been output. The important
// detail to remember here is that we never, ever attempt to read more input data than is required for the specified number of output
// frames. This can be achieved with ma_data_converter_get_required_input_frame_count()
// NOTE: Continuously converting data from the AudioBuffer's internal format to the mixing format,
// which should be defined by the output format of the data converter.
// This is done until frameCount frames have been output.
// The important detail to remember is that more data than required should neeveer be read,
// for the specified number of output frames.
// This can be achieved with ma_data_converter_get_required_input_frame_count()
ma_uint8 inputBuffer[4096] = { 0 }; ma_uint8 inputBuffer[4096] = { 0 };
ma_uint32 inputBufferFrameCap = sizeof(inputBuffer)/ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn); ma_uint32 inputBufferFrameCap = sizeof(inputBuffer)/ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn);
@ -2573,8 +2575,8 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
} }
} }
// If for some reason we weren't able to read every frame we'll need to break from the loop
// Not doing this could theoretically put us into an infinite loop
// If for some reason is not possible to read every frame, the loop needs to be broken
// Not doing this could theoretically eend up into an infinite loop
if (framesToRead > 0) break; if (framesToRead > 0) break;
} }
} }

+ 1
- 1
src/raylib.h Vedi File

@ -336,7 +336,7 @@ typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D
typedef struct Camera2D { typedef struct Camera2D {
Vector2 offset; // Camera offset (screen space offset from window origin) Vector2 offset; // Camera offset (screen space offset from window origin)
Vector2 target; // Camera target (world space target point that is mapped to screen space offset) Vector2 target; // Camera target (world space target point that is mapped to screen space offset)
float rotation; // Camera rotation in degrees (pivots around target)
float rotation; // Camera rotation in degrees (pivots around target)
float zoom; // Camera zoom (scaling around target), must not be set to 0, set to 1.0f for no scale float zoom; // Camera zoom (scaling around target), must not be set to 0, set to 1.0f for no scale
} Camera2D; } Camera2D;

+ 14
- 14
src/raymath.h Vedi File

@ -66,11 +66,11 @@
// Function specifiers definition // Function specifiers definition
#if defined(RAYMATH_IMPLEMENTATION) #if defined(RAYMATH_IMPLEMENTATION)
#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
#define RMAPI __declspec(dllexport) extern inline // We are building raylib as a Win32 shared library (.dll)
#define RMAPI __declspec(dllexport) extern inline // Building raylib as a Win32 shared library (.dll)
#elif defined(BUILD_LIBTYPE_SHARED) #elif defined(BUILD_LIBTYPE_SHARED)
#define RMAPI __attribute__((visibility("default"))) // We are building raylib as a Unix shared library (.so/.dylib)
#define RMAPI __attribute__((visibility("default"))) // Building raylib as a Unix shared library (.so/.dylib)
#elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED) #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
#define RMAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll)
#define RMAPI __declspec(dllimport) // Using raylib as a Win32 shared library (.dll)
#else #else
#define RMAPI extern inline // Provide external definition #define RMAPI extern inline // Provide external definition
#endif #endif
@ -595,7 +595,7 @@ RMAPI int Vector2Equals(Vector2 p, Vector2 q)
// v: normalized direction of the incoming ray // v: normalized direction of the incoming ray
// n: normalized normal vector of the interface of two optical media // n: normalized normal vector of the interface of two optical media
// r: ratio of the refractive index of the medium from where the ray comes // r: ratio of the refractive index of the medium from where the ray comes
// to the refractive index of the medium on the other side of the surface
// to the refractive index of the medium on the other side of the surface
RMAPI Vector2 Vector2Refract(Vector2 v, Vector2 n, float r) RMAPI Vector2 Vector2Refract(Vector2 v, Vector2 n, float r)
{ {
Vector2 result = { 0 }; Vector2 result = { 0 };
@ -1083,7 +1083,7 @@ RMAPI Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
} }
// Projects a Vector3 from screen space into object space // Projects a Vector3 from screen space into object space
// NOTE: We are avoiding calling other raymath functions despite available
// NOTE: Self-contained function, no other raymath functions are called
RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view) RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view)
{ {
Vector3 result = { 0 }; Vector3 result = { 0 };
@ -1245,7 +1245,7 @@ RMAPI int Vector3Equals(Vector3 p, Vector3 q)
// v: normalized direction of the incoming ray // v: normalized direction of the incoming ray
// n: normalized normal vector of the interface of two optical media // n: normalized normal vector of the interface of two optical media
// r: ratio of the refractive index of the medium from where the ray comes // r: ratio of the refractive index of the medium from where the ray comes
// to the refractive index of the medium on the other side of the surface
// to the refractive index of the medium on the other side of the surface
RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r) RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r)
{ {
Vector3 result = { 0 }; Vector3 result = { 0 };
@ -2663,14 +2663,14 @@ RMAPI Matrix MatrixCompose(Vector3 translation, Quaternion rotation, Vector3 sca
forward = Vector3RotateByQuaternion(forward, rotation); forward = Vector3RotateByQuaternion(forward, rotation);
// Set result matrix output // Set result matrix output
Matrix result = {
right.x, up.x, forward.x, translation.x,
right.y, up.y, forward.y, translation.y,
right.z, up.z, forward.z, translation.z,
0.0f, 0.0f, 0.0f, 1.0f
};
return result;
Matrix result = {
right.x, up.x, forward.x, translation.x,
right.y, up.y, forward.y, translation.y,
right.z, up.z, forward.z, translation.z,
0.0f, 0.0f, 0.0f, 1.0f
};
return result;
} }
// Decompose a transformation matrix into its rotational, translational and scaling components and remove shear // Decompose a transformation matrix into its rotational, translational and scaling components and remove shear

+ 2
- 2
src/rcore.c Vedi File

@ -525,7 +525,7 @@ const char *TextFormat(const char *text, ...); // Formatting of text with variab
#define PLATFORM_DESKTOP_GLFW #define PLATFORM_DESKTOP_GLFW
#endif #endif
// We're using '#pragma message' because '#warning' is not adopted by MSVC
// Using '#pragma message' because '#warning' is not adopted by MSVC
#if defined(SUPPORT_CLIPBOARD_IMAGE) #if defined(SUPPORT_CLIPBOARD_IMAGE)
#if !defined(SUPPORT_MODULE_RTEXTURES) #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")
@ -1499,7 +1499,7 @@ Matrix GetCameraMatrix2D(Camera2D camera)
// When setting higher scale, it's more intuitive for the world to become bigger (= camera become smaller), // When setting higher scale, it's more intuitive for the world to become bigger (= camera become smaller),
// not for the camera getting bigger, hence the invert. Same deal with rotation // not for the camera getting bigger, hence the invert. Same deal with rotation
// 3. Move it by (-offset); // 3. Move it by (-offset);
// Offset defines target transform relative to screen, but since we're effectively "moving" screen (camera)
// Offset defines target transform relative to screen, but since effectively "moving" screen (camera)
// we need to do it into opposite direction (inverse transform) // we need to do it into opposite direction (inverse transform)
// Having camera transform in world-space, inverse of it gives the modelview transform // Having camera transform in world-space, inverse of it gives the modelview transform

+ 4
- 4
src/rlgl.h Vedi File

@ -113,11 +113,11 @@
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
// NOTE: visibility(default) attribute makes symbols "visible" when compiled with -fvisibility=hidden // NOTE: visibility(default) attribute makes symbols "visible" when compiled with -fvisibility=hidden
#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
#define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
#define RLAPI __declspec(dllexport) // Building the library as a Win32 shared library (.dll)
#elif defined(BUILD_LIBTYPE_SHARED) #elif defined(BUILD_LIBTYPE_SHARED)
#define RLAPI __attribute__((visibility("default"))) // We are building the library as a Unix shared library (.so/.dylib)
#define RLAPI __attribute__((visibility("default"))) // Building the library as a Unix shared library (.so/.dylib)
#elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED) #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
#define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
#define RLAPI __declspec(dllimport) // Using the library as a Win32 shared library (.dll)
#endif #endif
// Function specifiers definition // Function specifiers definition
@ -3731,7 +3731,7 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
// Two possible Options: // Two possible Options:
// 1 - Bind texture to color fbo attachment and glReadPixels() // 1 - Bind texture to color fbo attachment and glReadPixels()
// 2 - Create an fbo, activate it, render quad with texture, glReadPixels() // 2 - Create an fbo, activate it, render quad with texture, glReadPixels()
// We are using Option 1, just need to care for texture format on retrieval
// Using Option 1, just need to care for texture format on retrieval
// NOTE: This behaviour could be conditioned by graphic driver... // NOTE: This behaviour could be conditioned by graphic driver...
unsigned int fboId = rlLoadFramebuffer(); unsigned int fboId = rlLoadFramebuffer();

+ 2
- 2
src/rmodels.c Vedi File

@ -1754,7 +1754,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
// This could alternatively use a static VBO and either glMapBuffer() or glBufferSubData() // This could alternatively use a static VBO and either glMapBuffer() or glBufferSubData()
// It isn't clear which would be reliably faster in all cases and on all platforms, // It isn't clear which would be reliably faster in all cases and on all platforms,
// anecdotally glMapBuffer() seems very slow (syncs) while glBufferSubData() seems // anecdotally glMapBuffer() seems very slow (syncs) while glBufferSubData() seems
// no faster, since we're transferring all the transform matrices anyway
// no faster, since all the transform matrices are transferred anyway
instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false); instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false);
// Instances transformation matrices are sent to shader attribute location: SHADER_LOC_VERTEX_INSTANCE_TX // Instances transformation matrices are sent to shader attribute location: SHADER_LOC_VERTEX_INSTANCE_TX
@ -4084,7 +4084,7 @@ RayCollision GetRayCollisionBox(Ray ray, BoundingBox box)
{ {
RayCollision collision = { 0 }; RayCollision collision = { 0 };
// Note: If ray.position is inside the box, the distance is negative (as if the ray was reversed)
// NOTE: If ray.position is inside the box, the distance is negative (as if the ray was reversed)
// Reversing ray.direction will give use the correct result // Reversing ray.direction will give use the correct result
bool insideBox = (ray.position.x > box.min.x) && (ray.position.x < box.max.x) && bool insideBox = (ray.position.x > box.min.x) && (ray.position.x < box.max.x) &&
(ray.position.y > box.min.y) && (ray.position.y < box.max.y) && (ray.position.y > box.min.y) && (ray.position.y < box.max.y) &&

+ 10
- 10
src/rshapes.c Vedi File

@ -59,9 +59,9 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Error rate to calculate how many segments we need to draw a smooth circle,
// taken from https://stackoverflow.com/a/2244088
#ifndef SMOOTH_CIRCLE_ERROR_RATE #ifndef SMOOTH_CIRCLE_ERROR_RATE
// Define error rate to calculate how many segments are needed to draw a smooth circle
// REF: https://stackoverflow.com/a/2244088
#define SMOOTH_CIRCLE_ERROR_RATE 0.5f // Circle error rate #define SMOOTH_CIRCLE_ERROR_RATE 0.5f // Circle error rate
#endif #endif
#ifndef SPLINE_SEGMENT_DIVISIONS #ifndef SPLINE_SEGMENT_DIVISIONS
@ -318,7 +318,7 @@ void DrawCircle(int centerX, int centerY, float radius, Color color)
} }
// Draw a color-filled circle (Vector version) // Draw a color-filled circle (Vector version)
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
// NOTE: On OpenGL 3.3 and ES2 using QUADS to avoid drawing order issues
void DrawCircleV(Vector2 center, float radius, Color color) void DrawCircleV(Vector2 center, float radius, Color color)
{ {
DrawCircleSector(center, radius, 0, 360, 36, color); DrawCircleSector(center, radius, 0, 360, 36, color);
@ -379,7 +379,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
angle += (stepLength*2.0f); angle += (stepLength*2.0f);
} }
// NOTE: In case number of segments is odd, we add one last piece to the cake
// NOTE: In case number of segments is odd, adding one last piece to the cake
if ((((unsigned int)segments)%2) == 1) if ((((unsigned int)segments)%2) == 1)
{ {
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
@ -722,7 +722,7 @@ void DrawRectangle(int posX, int posY, int width, int height, Color color)
} }
// Draw a color-filled rectangle (Vector version) // Draw a color-filled rectangle (Vector version)
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
// NOTE: On OpenGL 3.3 and ES2 using QUADS to avoid drawing order issues
void DrawRectangleV(Vector2 position, Vector2 size, Color color) void DrawRectangleV(Vector2 position, Vector2 size, Color color)
{ {
DrawRectanglePro((Rectangle){ position.x, position.y, size.x, size.y }, (Vector2){ 0.0f, 0.0f }, 0.0f, color); DrawRectanglePro((Rectangle){ position.x, position.y, size.x, size.y }, (Vector2){ 0.0f, 0.0f }, 0.0f, color);
@ -968,7 +968,7 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
/* /*
Quick sketch to make sense of all of this, Quick sketch to make sense of all of this,
there are 9 parts to draw, also mark the 12 points we'll use
there are 9 parts to draw, also mark the 12 points used
P0____________________P1 P0____________________P1
/| |\ /| |\
@ -1024,7 +1024,7 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
angle += (stepLength*2); angle += (stepLength*2);
} }
// NOTE: In case number of segments is odd, we add one last piece to the cake
// NOTE: In case number of segments is odd, adding one last piece to the cake
if (segments%2) if (segments%2)
{ {
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
@ -1168,7 +1168,7 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
// Draw rectangle with rounded edges // Draw rectangle with rounded edges
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
// NOTE: For line thicknes <=1.0f using RL_LINES, otherwise using RL_QUADS/RL_TRIANGLES
DrawRectangleRoundedLinesEx(rec, roundness, segments, 1.0f, color); DrawRectangleRoundedLinesEx(rec, roundness, segments, 1.0f, color);
} }
@ -1204,7 +1204,7 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f
/* /*
Quick sketch to make sense of all of this, Quick sketch to make sense of all of this,
marks the 16 + 4(corner centers P16-19) points we'll use
marks the 16 + 4(corner centers P16-19) points used
P0 ================== P1 P0 ================== P1
// P8 P9 \\ // P8 P9 \\
@ -1946,7 +1946,7 @@ void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, C
// Draw spline segment: Linear, 2 points // Draw spline segment: Linear, 2 points
void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color) void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color)
{ {
// NOTE: For the linear spline we don't use subdivisions, just a single quad
// NOTE: For the linear spline no subdivisions are used, just a single quad
Vector2 delta = { p2.x - p1.x, p2.y - p1.y }; Vector2 delta = { p2.x - p1.x, p2.y - p1.y };
float length = sqrtf(delta.x*delta.x + delta.y*delta.y); float length = sqrtf(delta.x*delta.x + delta.y*delta.y);

Caricamento…
Annulla
Salva