mirror of
https://github.com/raysan5/raylib.git
synced 2026-08-26 06:08:27 -04:00
Compare commits
3 Commits
99b61089c8
...
3d671a6dd4
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d671a6dd4 | |||
| 7711de62fb | |||
| 37712a8fbe |
2
src/external/rlsw.h
vendored
2
src/external/rlsw.h
vendored
@ -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
|
||||
|
||||
@ -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++)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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])
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
249
src/rshapes.c
249
src/rshapes.c
@ -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;
|
||||
}
|
||||
|
||||
10
src/rtext.c
10
src/rtext.c
@ -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 };
|
||||
|
||||
@ -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)
|
||||
|
||||
Reference in New Issue
Block a user