3 Commits

Author SHA1 Message Date
Ray
3d671a6dd4 Merge branch 'master' of https://github.com/raysan5/raylib 2026-08-04 21:16:17 +02:00
Ray
7711de62fb Code gardening 2026-08-04 21:16:08 +02:00
37712a8fbe [rshapes] Fix Draw*LinesEx() functions' inconsistent handling of thick parameter. (#6035)
* [rshapes] Update `DrawRectangleLinesEx()`

Add support for negative `thick` values. When `thick` is negative, lines are drawn growing outside of the rectangle.

* [rshapes] Update `DrawPolyLinesEx()`

Add support for negative `thick` values. When `thick` is negative, lines are drawn growing outside of the polygon. Also refactored to explicitly use an `outerRadius` variable instead of using `radius` as the outer radius.

* [rshapes] Update `DrawRectangleRoundedLinesEx()`

Make the outline vertices easier to work with.

* [rshapes] Updated `DrawRectangleRoundedLinesEx()`.

Lines used to draw outside when `thick` was positive. Added support for negative `thick` values. When `thick` is negative, lines are drawn growing outside of the rectangle.

* [rshapes] Update `DrawRectangleRoundedLines()`.

Make the formatting of the points' x and y coordinates in DrawRectangleRoundedLines() match DrawRectangleRoundedLinesEx().
2026-08-04 18:04:56 +02:00
15 changed files with 224 additions and 110 deletions

2
src/external/rlsw.h vendored
View File

@ -774,7 +774,7 @@ SWAPI void swGetFramebufferAttachmentParameteriv(SWattachment attachment, SWatta
// Simple log system to avoid printf() calls if required
// NOTE: Avoiding those calls, also avoids const strings memory usage
#define RLSW_SUPPORT_LOG_INFO
#if defined(RLSW_SUPPORT_LOG_INFO) //&& defined(_DEBUG) // WARNING: LOG() output required for this tool
#if defined(RLSW_SUPPORT_LOG_INFO)
#include <stdio.h>
#define SW_LOG(...) printf(__VA_ARGS__)
#else

View File

@ -757,12 +757,12 @@ void PollInputEvents(void)
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
// Reset last gamepad button/axis registered state
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
//CORE.Input.Gamepad.axisCount = 0;
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (CORE.Input.Gamepad.ready[i]) // Check if gamepad is available
if (CORE.Input.Gamepad.ready[i]) // Check if gamepad is available
{
// Register previous gamepad states
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++)

View File

@ -1613,11 +1613,11 @@ void PollInputEvents(void)
}
//-----------------------------------------------------------------------------
// using RGFW callbacks instead of polling
// Using RGFW callbacks instead of polling
RGFW_pollEvents();
//-----------------------------------------------------------------------------
mg_event gamepad_event;
mg_event gamepad_event = { 0 };
while (mg_gamepads_check_event(&platform.minigamepad, &gamepad_event))
{
int gamepadIndex = gamepad_event.gamepad->index;

View File

@ -1652,7 +1652,7 @@ void PollInputEvents(void)
} break;
#endif
// Keyboard events
// Check keyboard events
case SDL_KEYDOWN:
{
#if defined(USING_VERSION_SDL3)
@ -1680,10 +1680,8 @@ void PollInputEvents(void)
if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) CORE.Window.shouldClose = true;
} break;
case SDL_KEYUP:
{
#if defined(USING_VERSION_SDL3)
KeyboardKey key = ConvertScancodeToKey(event.key.scancode);
#else
@ -1691,7 +1689,6 @@ void PollInputEvents(void)
#endif
if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0;
} break;
case SDL_TEXTINPUT:
{
// NOTE: event.text.text data comes an UTF-8 text sequence but register codepoints (int)
@ -1700,7 +1697,6 @@ void PollInputEvents(void)
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
{
// Add character (codepoint) to the queue
#if defined(USING_VERSION_SDL3)
size_t textLen = strlen(event.text.text);
unsigned int codepoint = (unsigned int)SDL_StepUTF8(&event.text.text, &textLen);
@ -1769,6 +1765,7 @@ void PollInputEvents(void)
touchAction = 2;
} break;
// Check Touch events
case SDL_FINGERDOWN:
{
UpdateTouchPointsSDL(event.tfinger);
@ -1788,24 +1785,21 @@ void PollInputEvents(void)
realTouch = true;
} break;
// Check gamepad events
// Check Gamepad events
case SDL_JOYDEVICEADDED:
{
int jid = event.jdevice.which; // Joystick device index
// check if already added at InitPlatform
// Check if already added at InitPlatform
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (jid == platform.gamepadId[i])
{
return;
}
if (jid == platform.gamepadId[i]) return;
}
int nextAvailableSlot = 0;
while (nextAvailableSlot < MAX_GAMEPADS && CORE.Input.Gamepad.ready[nextAvailableSlot])
{
++nextAvailableSlot;
nextAvailableSlot++;
}
if ((nextAvailableSlot < MAX_GAMEPADS) && !CORE.Input.Gamepad.ready[nextAvailableSlot])

View File

@ -1071,7 +1071,7 @@ void PollInputEvents(void)
CORE.Input.Keyboard.charPressedQueueCount = 0;
// Reset last gamepad button/axis registered state
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
//CORE.Input.Gamepad.axisCount = 0;
// Register previous keys states
@ -1118,7 +1118,7 @@ void PollInputEvents(void)
// NOTE: For DRM touchscreen devices, this mapping is disabled to avoid false touch detection
// CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
// Handle the mouse/touch/gestures events:
// Handle the mouse/touch/gestures events
PollMouseEvents();
}
@ -1821,7 +1821,7 @@ static void ProcessKeyboard(void)
if (bufferByteCount == 1) CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] = 1;
else
{
if (keysBuffer[i + 1] == 0x5b) // Special function key
if (keysBuffer[i + 1] == 0x5b) // Special function key
{
if ((keysBuffer[i + 2] == 0x5b) || (keysBuffer[i + 2] == 0x31) || (keysBuffer[i + 2] == 0x32))
{
@ -1938,7 +1938,8 @@ static void InitEvdevInput(void)
(strncmp("mouse", entity->d_name, strlen("mouse")) == 0)) // Search for devices named "mouse*"
{
snprintf(path, MAX_FILEPATH_LENGTH, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
ConfigureEvdevDevice(path); // Configure the device if appropriate
ConfigureEvdevDevice(path); // Configure the device if appropriate
}
}

View File

@ -477,7 +477,7 @@ void PollInputEvents(void)
if (kbhit())
{
int key = getch();
if (key == 27) CORE.Window.shouldClose = true; // KEY_SCAPE
if (key == 27) CORE.Window.shouldClose = true; // KEY_ESCAPE
}
}

View File

@ -1086,7 +1086,7 @@ void PollInputEvents(void)
CORE.Input.Keyboard.charPressedQueueCount = 0;
// Reset last gamepad button/axis registered state
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
//CORE.Input.Gamepad.axisCount = 0;
// Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)
@ -1128,7 +1128,7 @@ void PollInputEvents(void)
// Register previous gamepad button states
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
EmscriptenGamepadEvent gamepadState;
EmscriptenGamepadEvent gamepadState = { 0 };
int result = emscripten_get_gamepad_status(i, &gamepadState);
@ -1161,7 +1161,7 @@ void PollInputEvents(void)
default: break;
}
if (button + 1 != 0) // Check for valid button
if (button + 1 != 0) // Check for valid button
{
if (gamepadState.digitalButton[j] == 1)
{

View File

@ -1063,7 +1063,7 @@ void PollInputEvents(void)
CORE.Input.Keyboard.charPressedQueueCount = 0;
// Reset last gamepad button/axis registered state
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
//CORE.Input.Gamepad.axisCount = 0;
// Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)
@ -1134,7 +1134,7 @@ void PollInputEvents(void)
default: break;
}
if (button + 1 != 0) // Check for valid button
if (button + 1 != 0) // Check for valid button
{
if (gamepadState.digitalButton[j] == 1)
{

View File

@ -2660,7 +2660,7 @@ static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 fr
const float localVolume = buffer->volume;
const ma_uint32 channels = AUDIO.System.device.playback.channels;
if (channels == 2) // Consider panning
if (channels == 2) // Consider panning
{
const float right = (buffer->pan + 1.0f)/2.0f; // Normalize: [-1..1] -> [0..1]
const float left = 1.0f - right;

View File

@ -353,7 +353,7 @@ void ProcessGestureEvent(GestureEvent event)
GESTURES.Drag.vector.y = GESTURES.Touch.moveDownPositionA.y - GESTURES.Touch.downDragPosition.y;
}
}
else if (GESTURES.Touch.pointCount == 2) // Two touch points
else if (GESTURES.Touch.pointCount == 2)
{
if (event.touchAction == TOUCH_ACTION_DOWN)
{

View File

@ -2377,7 +2377,7 @@ void rlglClose(void)
// NOTE: External loader function must be provided
void rlLoadExtensions(void *loader)
{
#if defined(GRAPHICS_API_OPENGL_33) // Also defined for GRAPHICS_API_OPENGL_21
#if defined(GRAPHICS_API_OPENGL_33) // Also defined for GRAPHICS_API_OPENGL_21
// NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions)
if (gladLoadGL((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL extensions");
else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL extensions loaded successfully");
@ -2508,7 +2508,7 @@ void rlLoadExtensions(void *loader)
}
// Check instanced rendering support
if (strstr(extList[i], (const char *)"instanced_arrays") != NULL) // Broad check for instanced_arrays
if (strstr(extList[i], (const char *)"instanced_arrays") != NULL) // Broad check for instanced_arrays
{
// Specific check
if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // ANGLE

View File

@ -5348,7 +5348,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
image = LoadImage(TextFormat("%s/%s", texPath, cgltfImage->uri));
}
}
else if ((cgltfImage->buffer_view != NULL) && (cgltfImage->buffer_view->buffer->data != NULL)) // Check if image is provided as data buffer
else if ((cgltfImage->buffer_view != NULL) && (cgltfImage->buffer_view->buffer->data != NULL)) // Check if image is provided as data buffer
{
unsigned char *data = (unsigned char *)RL_MALLOC(cgltfImage->buffer_view->size);
int offset = (int)cgltfImage->buffer_view->offset;
@ -5776,7 +5776,7 @@ static Model LoadGLTF(const char *fileName)
else TRACELOG(LOG_WARNING, "MODEL: [%s] Vertices attribute data format not supported, use vec3 float", fileName);
}
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_normal) // NORMAL, vec3, float
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_normal) // NORMAL, vec3, float
{
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
@ -5876,7 +5876,7 @@ static Model LoadGLTF(const char *fileName)
else TRACELOG(LOG_WARNING, "MODEL: [%s] Normals attribute data format not supported, use vec3 float", fileName);
}
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_tangent) // TANGENT, vec4, float, w is tangent basis sign
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_tangent) // TANGENT, vec4, float, w is tangent basis sign
{
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
@ -5913,7 +5913,7 @@ static Model LoadGLTF(const char *fileName)
if (attribute->type == cgltf_type_vec2)
{
if (attribute->component_type == cgltf_component_type_r_32f) // vec2, float
if (attribute->component_type == cgltf_component_type_r_32f) // vec2, float
{
// Init raylib mesh texcoords to copy glTF attribute data
texcoordPtr = (float *)RL_MALLOC(attribute->count*2*sizeof(float));
@ -5962,7 +5962,7 @@ static Model LoadGLTF(const char *fileName)
if (texcoordPtr != NULL) RL_FREE(texcoordPtr);
}
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_color) // COLOR_n, vec3/vec4, float/u8n/u16n
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_color) // COLOR_n, vec3/vec4, float/u8n/u16n
{
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
@ -5971,7 +5971,7 @@ static Model LoadGLTF(const char *fileName)
if (model.meshes[meshIndex].colors != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Colors attribute data already loaded", fileName);
else
{
if (attribute->type == cgltf_type_vec3) // RGB
if (attribute->type == cgltf_type_vec3) // RGB
{
if (attribute->component_type == cgltf_component_type_r_8u)
{
@ -6264,7 +6264,7 @@ static Model LoadGLTF(const char *fileName)
}
else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint attribute data format not supported", fileName);
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_weights) // WEIGHTS_n (vec4, u8n/u16n/f32)
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_weights) // WEIGHTS_n (vec4, u8n/u16n/f32)
{
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;

View File

@ -637,24 +637,53 @@ void DrawRectangleLinesEx(Rectangle rec, float thick, Color color)
else if (rec.width <= rec.height) thick = rec.width/2;
}
// When rec = { x, y, 8.0f, 6.0f } and thick = 2, the following
// four rectangles are drawn ([T]op, [B]ottom, [L]eft, [R]ight):
//
// TTTTTTTT
// TTTTTTTT
// LL RR
// LL RR
// BBBBBBBB
// BBBBBBBB
//
if (thick > 0.0f)
{
// When rec = { x, y, 8.0f, 6.0f } and thick = 2, the following
// four rectangles are drawn ([T]op, [B]ottom, [L]eft, [R]ight):
//
// TTTTTTTT
// TTTTTTTT
// LL RR
// LL RR
// BBBBBBBB
// BBBBBBBB
//
Rectangle top = { rec.x, rec.y, rec.width, thick };
Rectangle bottom = { rec.x, rec.y - thick + rec.height, rec.width, thick };
Rectangle left = { rec.x, rec.y + thick, thick, rec.height - thick*2.0f };
Rectangle right = { rec.x - thick + rec.width, rec.y + thick, thick, rec.height - thick*2.0f };
DrawRectangleRec(top, color);
DrawRectangleRec(bottom, color);
DrawRectangleRec(left, color);
DrawRectangleRec(right, color);
}
else
{
// When rec = { x, y, 8.0f, 6.0f } and thick = -2, the following
// four rectangles are drawn ([T]op, [B]ottom, [L]eft, [R]ight):
//
// TTTTTTTTTTTT
// TTTTTTTTTTTT
// LL RR
// LL RR
// LL RR
// LL RR
// LL RR
// LL RR
// BBBBBBBBBBBB
// BBBBBBBBBBBB
//
thick *= -1.0f;
Rectangle top = { rec.x - thick, rec.y - thick, rec.width + thick*2.0f, thick };
Rectangle bottom = { rec.x - thick, rec.y + rec.height, rec.width + thick*2.0f, thick};
Rectangle left = { rec.x - thick, rec.y, thick, rec.height };
Rectangle right = { rec.x + rec.width, rec.y, thick, rec.height };
DrawRectangleRec(top, color);
DrawRectangleRec(bottom, color);
DrawRectangleRec(left, color);
@ -931,22 +960,35 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Col
\ /
P5 ------------------ P4
*/
// The x-coordinates used for the outline
const float x0 = rec.x + radius + 0.5f;
const float x1 = (rec.x + rec.width) - radius - 0.5f;
const float x2 = rec.x + rec.width - 0.5f;
const float x3 = rec.x + 0.5f;
// The y-coordinates used for the outline
const float y0 = rec.y + 0.5f;
const float y1 = rec.y + radius + 0.5f;
const float y2 = (rec.y + rec.height) - radius - 0.5f;
const float y3 = rec.y + rec.height - 0.5f;
const Vector2 point[8] = {
{(float)rec.x + radius + 0.5f, rec.y + 0.5f},
{(float)(rec.x + rec.width) - radius - 0.5f, rec.y + 0.5f},
{rec.x + rec.width - 0.5f, (float)rec.y + radius + 0.5f}, // PO, P1, P2
{rec.x + rec.width - 0.5f, (float)(rec.y + rec.height) - radius - 0.5f},
{(float)(rec.x + rec.width) - radius - 0.5f, rec.y + rec.height - 0.5f}, // P3, P4
{(float)rec.x + radius + 0.5f, rec.y + rec.height - 0.5f},
{rec.x + 0.5f, (float)(rec.y + rec.height) - radius - 0.5f},
{rec.x + 0.5f, (float)rec.y + radius + 0.5f}, // P5, P6, P7
{x0, y0}, // P0
{x1, y0}, // P1
{x2, y1}, // P2
{x2, y2}, // P3
{x1, y3}, // P4
{x0, y3}, // P5
{x3, y2}, // P6
{x3, y1}, // P7
};
const Vector2 centers[4] = {
{(float)rec.x + radius + 0.5f, (float)rec.y + radius + 0.5f},
{(float)(rec.x + rec.width) - radius - 0.5f, (float)rec.y + radius + 0.5f}, // P16, P17
{(float)(rec.x + rec.width) - radius - 0.5f, (float)(rec.y + rec.height) - radius - 0.5f},
{(float)rec.x + radius + 0.5f, (float)(rec.y + rec.height) - radius - 0.5f} // P18, P19
{x0, y1}, // P16
{x1, y1}, // P17
{x1, y2}, // P18
{x0, y2} // P19
};
const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
@ -980,32 +1022,81 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Col
// Draw rectangle with rounded edges outline with line thickness
void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float thick, Color color)
{
if (thick <= 0) return;
// Not a rounded rectangle
if (roundness <= 0.0f)
{
DrawRectangleLinesEx((Rectangle){rec.x - thick, rec.y - thick, rec.width + 2*thick, rec.height + 2*thick}, thick, color);
DrawRectangleLinesEx(rec, thick, color);
return;
}
if (roundness >= 1.0f) roundness = 1.0f;
// Calculate corner radius
float radius = (rec.width > rec.height)? (rec.height*roundness)/2 : (rec.width*roundness)/2;
if (radius <= 0.0f) return;
// Calculate number of segments to use for the corners
if (segments < 4)
float radius = 0.0f;
float roundedOutlineThick = 0.0f;
float outerRadius = 0.0f;
float innerRadius = 0.0f;
if (thick >= 0.0f)
{
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
segments = (int)ceilf((2*PI/th)/4.0f);
if (segments <= 0) segments = 4;
// Calculate corner radius
radius = (rec.width > rec.height)? (rec.height*roundness)/2 : (rec.width*roundness)/2;
if (radius <= 0.0f) return;
outerRadius = radius;
innerRadius = outerRadius - thick;
// The maximum thickness the outline can have and still be rounded on the interior edge is equal to the corner radius
// Put another way, when `innerRadius <= 0`, the interior of the outline is just a normal rectangle with no rounding
if (innerRadius <= 0.0f)
{
innerRadius = 0.0f;
roundedOutlineThick = outerRadius;
// Draw the not-rounded portion of the outline
DrawRectangleLinesEx((Rectangle){ rec.x + outerRadius, rec.y + outerRadius, rec.width - outerRadius*2.0f, rec.height - outerRadius*2.0f }, thick - outerRadius, color);
}
else
{
roundedOutlineThick = thick;
}
// Calculate number of segments to use for the corners
if (segments < 4)
{
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
segments = (int)ceilf((2*PI/th)/4.0f);
if (segments <= 0) segments = 4;
}
}
else
{
thick *= -1.0f;
// Calculate corner radius
radius = (rec.width > rec.height)? (rec.height*roundness)/2 : (rec.width*roundness)/2;
if (radius <= 0.0f) return; // Only possible if the rectangle has 0 width or height
// Expand the rectangle
rec.x -= thick;
rec.y -= thick;
rec.width += thick*2.0f;
rec.height += thick*2.0f;
innerRadius = radius;
outerRadius = innerRadius + thick;
roundedOutlineThick = thick;
// Calculate number of segments to use for the corners
if (segments < 4)
{
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/innerRadius, 2) - 1);
segments = (int)ceilf((2*PI/th)/4.0f);
if (segments <= 0) segments = 4;
}
}
float stepLength = 90.0f/(float)segments;
const float outerRadius = radius + thick, innerRadius = radius;
/*
Quick sketch to make sense of all of this,
@ -1023,30 +1114,47 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f
\\ P13 P12 //
P5 ================== P4
*/
// The x-coordinates used for the outline
const float x0 = rec.x + outerRadius;
const float x1 = (rec.x + rec.width) - outerRadius;
const float x2 = rec.x + rec.width;
const float x3 = rec.x;
const float x4 = rec.x + rec.width - roundedOutlineThick;
const float x5 = rec.x + roundedOutlineThick;
// The y-coordinates used for the outline
const float y0 = rec.y;
const float y1 = rec.y + outerRadius;
const float y2 = (rec.y + rec.height) - outerRadius;
const float y3 = rec.y + rec.height;
const float y4 = rec.y + roundedOutlineThick;
const float y5 = rec.y + rec.height - roundedOutlineThick;
const Vector2 point[16] = {
{(float)rec.x + innerRadius + 0.5f, rec.y - thick + 0.5f},
{(float)(rec.x + rec.width) - innerRadius - 0.5f, rec.y - thick + 0.5f},
{rec.x + rec.width + thick - 0.5f, (float)rec.y + innerRadius + 0.5f}, // PO, P1, P2
{rec.x + rec.width + thick - 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f},
{(float)(rec.x + rec.width) - innerRadius - 0.5f, rec.y + rec.height + thick - 0.5f}, // P3, P4
{(float)rec.x + innerRadius + 0.5f, rec.y + rec.height + thick - 0.5f},
{rec.x - thick + 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f},
{rec.x - thick + 0.5f, (float)rec.y + innerRadius + 0.5f}, // P5, P6, P7
{(float)rec.x + innerRadius + 0.5f, rec.y + 0.5f},
{(float)(rec.x + rec.width) - innerRadius - 0.5f, rec.y + 0.5f}, // P8, P9
{rec.x + rec.width - 0.5f, (float)rec.y + innerRadius + 0.5f},
{rec.x + rec.width - 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f}, // P10, P11
{(float)(rec.x + rec.width) - innerRadius - 0.5f, rec.y + rec.height - 0.5f},
{(float)rec.x + innerRadius + 0.5f, rec.y + rec.height - 0.5f}, // P12, P13
{rec.x + 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f},
{rec.x + 0.5f, (float)rec.y + innerRadius + 0.5f} // P14, P15
{x0, y0}, // P0
{x1, y0}, // P1
{x2, y1}, // P2
{x2, y2}, // P3
{x1, y3}, // P4
{x0, y3}, // P5
{x3, y2}, // P6
{x3, y1}, // P7
{x0, y4}, // P8
{x1, y4}, // P9
{x4, y1}, // P10
{x4, y2}, // P11
{x1, y5}, // P12
{x0, y5}, // P13
{x5, y2}, // P14
{x5, y1} // P15
};
const Vector2 centers[4] = {
{(float)rec.x + innerRadius + 0.5f, (float)rec.y + innerRadius + 0.5f},
{(float)(rec.x + rec.width) - innerRadius - 0.5f, (float)rec.y + innerRadius + 0.5f}, // P16, P17
{(float)(rec.x + rec.width) - innerRadius - 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f},
{(float)rec.x + innerRadius + 0.5f, (float)(rec.y + rec.height) - innerRadius - 0.5f} // P18, P19
{x0, y1}, // P16
{x1, y1}, // P17
{x1, y2}, // P18
{x0, y2} // P19
};
const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
@ -1263,13 +1371,24 @@ void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Colo
void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float thick, Color color)
{
if (thick <= 0.0f) return;
if (sides < 3) sides = 3;
float centralAngle = rotation*DEG2RAD;
float exteriorAngle = 360.0f/(float)sides*DEG2RAD;
float apothem = radius*cosf(DEG2RAD*180.0f/(float)sides);
float innerRadius = fmaxf(0.0f, radius - thick*(radius/apothem));
float outerRadius = 0.0f;
float innerRadius = 0.0f;
if (thick >= 0.0f)
{
outerRadius = radius;
innerRadius = fmaxf(0.0f, radius - thick*(radius/apothem));
}
else
{
thick *= -1.0f;
outerRadius = radius + thick*(radius/apothem);
innerRadius = radius;
}
#if SUPPORT_QUADS_DRAW_MODE
rlSetTexture(GetShapesTexture().id);
@ -1282,7 +1401,7 @@ void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, fl
float nextAngle = centralAngle + exteriorAngle;
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
rlVertex2f(center.x + cosf(centralAngle)*outerRadius, center.y + sinf(centralAngle)*outerRadius);
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
@ -1291,7 +1410,7 @@ void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, fl
rlVertex2f(center.x + cosf(nextAngle)*innerRadius, center.y + sinf(nextAngle)*innerRadius);
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
rlVertex2f(center.x + cosf(nextAngle)*outerRadius, center.y + sinf(nextAngle)*outerRadius);
centralAngle = nextAngle;
}
@ -1304,13 +1423,13 @@ void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, fl
rlColor4ub(color.r, color.g, color.b, color.a);
float nextAngle = centralAngle + exteriorAngle;
rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
rlVertex2f(center.x + cosf(nextAngle)*outerRadius, center.y + sinf(nextAngle)*outerRadius);
rlVertex2f(center.x + cosf(centralAngle)*outerRadius, center.y + sinf(centralAngle)*outerRadius);
rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
rlVertex2f(center.x + cosf(nextAngle)*innerRadius, center.y + sinf(nextAngle)*innerRadius);
rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
rlVertex2f(center.x + cosf(nextAngle)*outerRadius, center.y + sinf(nextAngle)*outerRadius);
centralAngle = nextAngle;
}

View File

@ -713,7 +713,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
default: break;
}
if (glyphs[k].image.data != NULL) // Glyph data has been found in the font
if (glyphs[k].image.data != NULL) // Glyph data has been found in the font
{
stbtt_GetCodepointHMetrics(&fontInfo, cp, &glyphs[k].advanceX, NULL);
glyphs[k].advanceX = (int)((float)glyphs[k].advanceX*scaleFactor);
@ -845,7 +845,7 @@ Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyp
// DEBUG: View padding in the generated image setting a gray background...
//for (int i = 0; i < atlas.width*atlas.height; i++) ((unsigned char *)atlas.data)[i] = 100;
if (packMethod == 0) // Use basic packing algorithm
if (packMethod == 0) // Use basic packing algorithm
{
int offsetX = padding;
int offsetY = padding;
@ -907,7 +907,7 @@ Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyp
offsetX += (glyphs[i].image.width + 2*padding);
}
}
else if (packMethod == 1) // Use Skyline rect packing algorithm (stb_pack_rect)
else if (packMethod == 1) // Use Skyline rect packing algorithm (stb_pack_rect)
{
stbrp_context *context = (stbrp_context *)RL_MALLOC(sizeof(*context));
stbrp_node *nodes = (stbrp_node *)RL_MALLOC(glyphCount*sizeof(*nodes));
@ -1860,7 +1860,7 @@ char *TextReplaceAlloc(const char *text, const char *search, const char *replace
int tempLen = textLen + (replaceLen - searchLen)*count + 1;
temp = result = (char *)RL_CALLOC(tempLen, sizeof(char));
if (result != NULL) // Memory was allocated
if (result != NULL) // Memory was allocated
{
// First time through the loop, all the variable are set correctly from here on,
// - 'temp' points to the end of the result string
@ -2736,7 +2736,7 @@ static Font LoadBMFont(const char *fileName)
&charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX, &pageID);
fileTextPtr += (readBytes + 1);
if (readVars == 9) // Make sure all char data has been properly read
if (readVars == 9) // Make sure all char data has been properly read
{
// Get character rectangle in the font atlas texture
font.recs[i] = (Rectangle){ (float)charX, (float)charY + (float)imHeight*pageID, (float)charWidth, (float)charHeight };

View File

@ -315,7 +315,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
unsigned char *dataPtr = fileData;
int size = GetPixelDataSize(width, height, format);
if (size <= dataSize) // Security check
if (size <= dataSize) // Security check
{
// Offset file data to expected raw image by header size
if ((headerSize > 0) && ((headerSize + size) <= dataSize)) dataPtr += headerSize;
@ -4288,7 +4288,7 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
{
TextureCubemap cubemap = { 0 };
if (layout == CUBEMAP_LAYOUT_AUTO_DETECT) // Try to automatically guess layout type
if (layout == CUBEMAP_LAYOUT_AUTO_DETECT) // Try to automatically guess layout type
{
// Check image width/height to determine the type of cubemap provided
if (image.width > image.height)