12 Commits

Author SHA1 Message Date
Ray
c519e9f566 REVIEWED: Simplified char ** approach 2026-02-20 23:56:11 +01:00
Ray
09f22f3c86 REVIEWED: Avoid const char ** usage (aligned with raylib) 2026-02-20 23:02:43 +01:00
29b9c050c7 fix example (#5575) 2026-02-20 20:18:28 +01:00
Ray
0343cb6a37 Update rcore_desktop_sdl.c 2026-02-20 18:47:53 +01:00
d148d9515b Fix text input on SDL3 (#5574) 2026-02-20 18:44:34 +01:00
Ray
19e6352d37 Update shapes_easings_testbed.c 2026-02-20 18:16:49 +01:00
Ray
d03a59ca3e Update core_directory_files.c 2026-02-20 16:36:13 +01:00
Ray
2454b3ed4b REVIEWED: TextReplace() and TextLength(), avoid using strcpy() 2026-02-20 16:27:08 +01:00
Ray
d996bf2bbd Update textures_screen_buffer.c 2026-02-20 16:06:59 +01:00
Ray
f33823cefe Update textures_screen_buffer.c 2026-02-20 15:55:38 +01:00
0aacd330d4 [raudio] Remove usage of ma_data_converter_get_required_input_frame_count() (#5568)
* Audio: Remove use of ma_data_converter_get_required_input_frame_count().

This function is being removed from miniaudio. To make this work with
the current architecture of raylib it requires the use of a cache.

This commit implements a generic solution that works across all
AudioBuffer types (static, streams and callback based), but the static
case could be optimized to avoid the cache by incorporating the
functionality of ReadAudioBufferFramesInInternalFormat() into
ReadAudioBufferFramesInMixingFormat(). It would be unpractical to avoid
the cache with streams and callback-based AudioBuffers however so this
commit sticks with a generic solution.

* Audio: Correct usage of miniaudio's dynamic rate adjustment.

This affects pitch shifting. The output rate is being modified with
ma_data_converter_set_rate(), but then that value is being used in the
computation of the output rate the next time SetAudioBufferPitch() which
results in a cascade. The correct way to do this is to use an anchored
output rate as the basis for the calculation after pitch shifting. In
this case, it's the device's sample rate that acts as the anchor.

* Audio: Optimize memory usage for data conversion.

This reduces the per-AudioBuffer conversion cache from 256 PCM frames
down to 8.
2026-02-20 13:46:41 +01:00
Ray
ce617cd814 Update rlgl.h 2026-02-20 11:46:46 +01:00
11 changed files with 229 additions and 186 deletions

View File

@ -81,27 +81,6 @@ int main(void)
GuiListViewEx((Rectangle){ 0, 50, GetScreenWidth(), GetScreenHeight() - 50 }, GuiListViewEx((Rectangle){ 0, 50, GetScreenWidth(), GetScreenHeight() - 50 },
files.paths, files.count, &listScrollIndex, &listItemActive, &listItemFocused); files.paths, files.count, &listScrollIndex, &listItemActive, &listItemFocused);
/*
for (int i = 0; i < (int)files.count; i++)
{
Color color = Fade(LIGHTGRAY, 0.3f);
if (!IsPathFile(files.paths[i]) && DirectoryExists(files.paths[i]))
{
if (GuiButton((Rectangle){0.0f, 85.0f + 40.0f*(float)i, screenWidth, 40}, ""))
{
TextCopy(directory, files.paths[i]);
UnloadDirectoryFiles(files);
files = LoadDirectoryFiles(directory);
continue;
}
}
DrawRectangle(0, 85 + 40*i, screenWidth, 40, color);
DrawText(GetFileName(files.paths[i]), 120, 100 + 40*i, 10, GRAY);
}
*/
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
} }

View File

@ -772,7 +772,7 @@ RAYGUIAPI int GuiWindowBox(Rectangle bounds, const char *title);
RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name
RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text
RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls
RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1 RAYGUIAPI int GuiTabBar(Rectangle bounds, char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1
RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control
// Basic controls set // Basic controls set
@ -800,7 +800,7 @@ RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int sub
// Advance controls set // Advance controls set
RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control
RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters RAYGUIAPI int GuiListViewEx(Rectangle bounds, char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters
RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message
RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret
RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls) RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls)
@ -1526,7 +1526,7 @@ static Color GetColor(int hexValue); // Returns a Color struct fr
static int ColorToInt(Color color); // Returns hexadecimal value for a Color static int ColorToInt(Color color); // Returns hexadecimal value for a Color
static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings static char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
static int TextToInteger(const char *text); // Get integer value from text static int TextToInteger(const char *text); // Get integer value from text
static float TextToFloat(const char *text); // Get float value from text static float TextToFloat(const char *text); // Get float value from text
@ -1549,7 +1549,7 @@ static const char *GetTextIcon(const char *text, int *iconId); // Get text icon
static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font
static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style
static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings static char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings
static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB
static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV
@ -1783,7 +1783,7 @@ int GuiPanel(Rectangle bounds, const char *text)
// Tab Bar control // Tab Bar control
// NOTE: Using GuiToggle() for the TABS // NOTE: Using GuiToggle() for the TABS
int GuiTabBar(Rectangle bounds, const char **text, int count, int *active) int GuiTabBar(Rectangle bounds, char **text, int count, int *active)
{ {
#define RAYGUI_TABBAR_ITEM_WIDTH 148 #define RAYGUI_TABBAR_ITEM_WIDTH 148
@ -2168,7 +2168,7 @@ int GuiToggleGroup(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers) // Get substrings items from text (items pointers)
int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 }; int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 };
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, rows); char **items = GuiTextSplit(text, ';', &itemCount, rows);
int prevRow = rows[0]; int prevRow = rows[0];
@ -2212,7 +2212,7 @@ int GuiToggleSlider(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers) // Get substrings items from text (items pointers)
int itemCount = 0; int itemCount = 0;
const char **items = NULL; char **items = NULL;
if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
@ -2356,7 +2356,7 @@ int GuiComboBox(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers, lengths and count) // Get substrings items from text (items pointers, lengths and count)
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, NULL); char **items = GuiTextSplit(text, ';', &itemCount, NULL);
if (*active < 0) *active = 0; if (*active < 0) *active = 0;
else if (*active > (itemCount - 1)) *active = itemCount - 1; else if (*active > (itemCount - 1)) *active = itemCount - 1;
@ -2422,7 +2422,7 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
// Get substrings items from text (items pointers, lengths and count) // Get substrings items from text (items pointers, lengths and count)
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, NULL); char **items = GuiTextSplit(text, ';', &itemCount, NULL);
Rectangle boundsOpen = bounds; Rectangle boundsOpen = bounds;
boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
@ -3602,7 +3602,7 @@ int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *activ
{ {
int result = 0; int result = 0;
int itemCount = 0; int itemCount = 0;
const char **items = NULL; char **items = NULL;
if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
@ -3612,7 +3612,7 @@ int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *activ
} }
// List View control with extended parameters // List View control with extended parameters
int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus) int GuiListViewEx(Rectangle bounds, char **text, int count, int *scrollIndex, int *active, int *focus)
{ {
int result = 0; int result = 0;
GuiState state = guiState; GuiState state = guiState;
@ -4140,7 +4140,7 @@ int GuiMessageBox(Rectangle bounds, const char *title, const char *message, cons
int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button
int buttonCount = 0; int buttonCount = 0;
const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
Rectangle buttonBounds = { 0 }; Rectangle buttonBounds = { 0 };
buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING; buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING;
@ -4199,7 +4199,7 @@ int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, co
int result = -1; int result = -1;
int buttonCount = 0; int buttonCount = 0;
const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
Rectangle buttonBounds = { 0 }; Rectangle buttonBounds = { 0 };
buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
@ -5119,11 +5119,11 @@ static const char *GetTextIcon(const char *text, int *iconId)
// Get text divided into lines (by line-breaks '\n') // Get text divided into lines (by line-breaks '\n')
// WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator! // WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator!
static const char **GetTextLines(const char *text, int *count) static char **GetTextLines(const char *text, int *count)
{ {
#define RAYGUI_MAX_TEXT_LINES 128 #define RAYGUI_MAX_TEXT_LINES 128
static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 }; static char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 };
for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings
int textLength = (int)strlen(text); int textLength = (int)strlen(text);
@ -5131,12 +5131,11 @@ static const char **GetTextLines(const char *text, int *count)
lines[0] = text; lines[0] = text;
*count = 1; *count = 1;
for (int i = 0, k = 0; (i < textLength) && (*count < RAYGUI_MAX_TEXT_LINES); i++) for (int i = 0; (i < textLength) && (*count < RAYGUI_MAX_TEXT_LINES); i++)
{ {
if (text[i] == '\n') if ((text[i] == '\n') && ((i + 1) < textLength))
{ {
k++; lines[*count] = &text[i + 1];
lines[k] = &text[i + 1]; // WARNING: next value is valid?
*count += 1; *count += 1;
} }
} }
@ -5194,7 +5193,7 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C
// WARNING: GuiTextSplit() function can't be used now because it can have already been used // WARNING: GuiTextSplit() function can't be used now because it can have already been used
// before the GuiDrawText() call and its buffer is static, it would be overriden :( // before the GuiDrawText() call and its buffer is static, it would be overriden :(
int lineCount = 0; int lineCount = 0;
const char **lines = GetTextLines(text, &lineCount); char **lines = GetTextLines(text, &lineCount);
// Text style variables // Text style variables
//int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT); //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT);
@ -5444,7 +5443,7 @@ static void GuiTooltip(Rectangle controlRec)
// Split controls text into multiple strings // Split controls text into multiple strings
// Also check for multiple columns (required by GuiToggleGroup()) // Also check for multiple columns (required by GuiToggleGroup())
static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow) static char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow)
{ {
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
// inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
@ -5463,8 +5462,8 @@ static const char **GuiTextSplit(const char *text, char delimiter, int *count, i
#define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024
#endif #endif
static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data) static char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data)
static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added) static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added)
memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE);
result[0] = buffer; result[0] = buffer;
@ -5863,7 +5862,7 @@ static void DrawRectangleGradientV(int posX, int posY, int width, int height, Co
} }
// Split string into multiple strings // Split string into multiple strings
const char **TextSplit(const char *text, char delimiter, int *count) char **TextSplit(const char *text, char delimiter, int *count)
{ {
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
// inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,

View File

@ -772,7 +772,7 @@ RAYGUIAPI int GuiWindowBox(Rectangle bounds, const char *title);
RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name
RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text
RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls
RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1 RAYGUIAPI int GuiTabBar(Rectangle bounds, char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1
RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control
// Basic controls set // Basic controls set
@ -800,7 +800,7 @@ RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int sub
// Advance controls set // Advance controls set
RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control
RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters RAYGUIAPI int GuiListViewEx(Rectangle bounds, char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters
RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message
RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret
RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls) RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls)
@ -1526,7 +1526,7 @@ static Color GetColor(int hexValue); // Returns a Color struct fr
static int ColorToInt(Color color); // Returns hexadecimal value for a Color static int ColorToInt(Color color); // Returns hexadecimal value for a Color
static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings static char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
static int TextToInteger(const char *text); // Get integer value from text static int TextToInteger(const char *text); // Get integer value from text
static float TextToFloat(const char *text); // Get float value from text static float TextToFloat(const char *text); // Get float value from text
@ -1549,7 +1549,7 @@ static const char *GetTextIcon(const char *text, int *iconId); // Get text icon
static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font
static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style
static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings static char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings
static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB
static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV
@ -1783,7 +1783,7 @@ int GuiPanel(Rectangle bounds, const char *text)
// Tab Bar control // Tab Bar control
// NOTE: Using GuiToggle() for the TABS // NOTE: Using GuiToggle() for the TABS
int GuiTabBar(Rectangle bounds, const char **text, int count, int *active) int GuiTabBar(Rectangle bounds, char **text, int count, int *active)
{ {
#define RAYGUI_TABBAR_ITEM_WIDTH 148 #define RAYGUI_TABBAR_ITEM_WIDTH 148
@ -2168,7 +2168,7 @@ int GuiToggleGroup(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers) // Get substrings items from text (items pointers)
int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 }; int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 };
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, rows); char **items = GuiTextSplit(text, ';', &itemCount, rows);
int prevRow = rows[0]; int prevRow = rows[0];
@ -2212,7 +2212,7 @@ int GuiToggleSlider(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers) // Get substrings items from text (items pointers)
int itemCount = 0; int itemCount = 0;
const char **items = NULL; char **items = NULL;
if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
@ -2356,7 +2356,7 @@ int GuiComboBox(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers, lengths and count) // Get substrings items from text (items pointers, lengths and count)
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, NULL); char **items = GuiTextSplit(text, ';', &itemCount, NULL);
if (*active < 0) *active = 0; if (*active < 0) *active = 0;
else if (*active > (itemCount - 1)) *active = itemCount - 1; else if (*active > (itemCount - 1)) *active = itemCount - 1;
@ -2422,7 +2422,7 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
// Get substrings items from text (items pointers, lengths and count) // Get substrings items from text (items pointers, lengths and count)
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, NULL); char **items = GuiTextSplit(text, ';', &itemCount, NULL);
Rectangle boundsOpen = bounds; Rectangle boundsOpen = bounds;
boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
@ -3602,7 +3602,7 @@ int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *activ
{ {
int result = 0; int result = 0;
int itemCount = 0; int itemCount = 0;
const char **items = NULL; char **items = NULL;
if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
@ -3612,7 +3612,7 @@ int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *activ
} }
// List View control with extended parameters // List View control with extended parameters
int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus) int GuiListViewEx(Rectangle bounds, char **text, int count, int *scrollIndex, int *active, int *focus)
{ {
int result = 0; int result = 0;
GuiState state = guiState; GuiState state = guiState;
@ -4140,7 +4140,7 @@ int GuiMessageBox(Rectangle bounds, const char *title, const char *message, cons
int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button
int buttonCount = 0; int buttonCount = 0;
const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
Rectangle buttonBounds = { 0 }; Rectangle buttonBounds = { 0 };
buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING; buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING;
@ -4199,7 +4199,7 @@ int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, co
int result = -1; int result = -1;
int buttonCount = 0; int buttonCount = 0;
const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
Rectangle buttonBounds = { 0 }; Rectangle buttonBounds = { 0 };
buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
@ -5119,11 +5119,11 @@ static const char *GetTextIcon(const char *text, int *iconId)
// Get text divided into lines (by line-breaks '\n') // Get text divided into lines (by line-breaks '\n')
// WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator! // WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator!
static const char **GetTextLines(const char *text, int *count) static char **GetTextLines(const char *text, int *count)
{ {
#define RAYGUI_MAX_TEXT_LINES 128 #define RAYGUI_MAX_TEXT_LINES 128
static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 }; static char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 };
for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings
int textLength = (int)strlen(text); int textLength = (int)strlen(text);
@ -5131,12 +5131,11 @@ static const char **GetTextLines(const char *text, int *count)
lines[0] = text; lines[0] = text;
*count = 1; *count = 1;
for (int i = 0, k = 0; (i < textLength) && (*count < RAYGUI_MAX_TEXT_LINES); i++) for (int i = 0; (i < textLength) && (*count < RAYGUI_MAX_TEXT_LINES); i++)
{ {
if (text[i] == '\n') if ((text[i] == '\n') && ((i + 1) < textLength))
{ {
k++; lines[*count] = &text[i + 1];
lines[k] = &text[i + 1]; // WARNING: next value is valid?
*count += 1; *count += 1;
} }
} }
@ -5194,7 +5193,7 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C
// WARNING: GuiTextSplit() function can't be used now because it can have already been used // WARNING: GuiTextSplit() function can't be used now because it can have already been used
// before the GuiDrawText() call and its buffer is static, it would be overriden :( // before the GuiDrawText() call and its buffer is static, it would be overriden :(
int lineCount = 0; int lineCount = 0;
const char **lines = GetTextLines(text, &lineCount); char **lines = GetTextLines(text, &lineCount);
// Text style variables // Text style variables
//int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT); //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT);
@ -5444,7 +5443,7 @@ static void GuiTooltip(Rectangle controlRec)
// Split controls text into multiple strings // Split controls text into multiple strings
// Also check for multiple columns (required by GuiToggleGroup()) // Also check for multiple columns (required by GuiToggleGroup())
static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow) static char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow)
{ {
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
// inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
@ -5463,8 +5462,8 @@ static const char **GuiTextSplit(const char *text, char delimiter, int *count, i
#define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024
#endif #endif
static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data) static char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data)
static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added) static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added)
memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE);
result[0] = buffer; result[0] = buffer;
@ -5863,7 +5862,7 @@ static void DrawRectangleGradientV(int posX, int posY, int width, int height, Co
} }
// Split string into multiple strings // Split string into multiple strings
const char **TextSplit(const char *text, char delimiter, int *count) char **TextSplit(const char *text, char delimiter, int *count)
{ {
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
// inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,

View File

@ -772,7 +772,7 @@ RAYGUIAPI int GuiWindowBox(Rectangle bounds, const char *title);
RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name
RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text
RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls
RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1 RAYGUIAPI int GuiTabBar(Rectangle bounds, char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1
RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control
// Basic controls set // Basic controls set
@ -800,7 +800,7 @@ RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int sub
// Advance controls set // Advance controls set
RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control
RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters RAYGUIAPI int GuiListViewEx(Rectangle bounds, char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters
RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message
RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret
RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls) RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls)
@ -1526,7 +1526,7 @@ static Color GetColor(int hexValue); // Returns a Color struct fr
static int ColorToInt(Color color); // Returns hexadecimal value for a Color static int ColorToInt(Color color); // Returns hexadecimal value for a Color
static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings static char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
static int TextToInteger(const char *text); // Get integer value from text static int TextToInteger(const char *text); // Get integer value from text
static float TextToFloat(const char *text); // Get float value from text static float TextToFloat(const char *text); // Get float value from text
@ -1549,7 +1549,7 @@ static const char *GetTextIcon(const char *text, int *iconId); // Get text icon
static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font
static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style
static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings static char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings
static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB
static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV
@ -1783,7 +1783,7 @@ int GuiPanel(Rectangle bounds, const char *text)
// Tab Bar control // Tab Bar control
// NOTE: Using GuiToggle() for the TABS // NOTE: Using GuiToggle() for the TABS
int GuiTabBar(Rectangle bounds, const char **text, int count, int *active) int GuiTabBar(Rectangle bounds, char **text, int count, int *active)
{ {
#define RAYGUI_TABBAR_ITEM_WIDTH 148 #define RAYGUI_TABBAR_ITEM_WIDTH 148
@ -2168,7 +2168,7 @@ int GuiToggleGroup(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers) // Get substrings items from text (items pointers)
int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 }; int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 };
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, rows); char **items = GuiTextSplit(text, ';', &itemCount, rows);
int prevRow = rows[0]; int prevRow = rows[0];
@ -2212,7 +2212,7 @@ int GuiToggleSlider(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers) // Get substrings items from text (items pointers)
int itemCount = 0; int itemCount = 0;
const char **items = NULL; char **items = NULL;
if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
@ -2356,7 +2356,7 @@ int GuiComboBox(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers, lengths and count) // Get substrings items from text (items pointers, lengths and count)
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, NULL); char **items = GuiTextSplit(text, ';', &itemCount, NULL);
if (*active < 0) *active = 0; if (*active < 0) *active = 0;
else if (*active > (itemCount - 1)) *active = itemCount - 1; else if (*active > (itemCount - 1)) *active = itemCount - 1;
@ -2422,7 +2422,7 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
// Get substrings items from text (items pointers, lengths and count) // Get substrings items from text (items pointers, lengths and count)
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, NULL); char **items = GuiTextSplit(text, ';', &itemCount, NULL);
Rectangle boundsOpen = bounds; Rectangle boundsOpen = bounds;
boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
@ -3602,7 +3602,7 @@ int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *activ
{ {
int result = 0; int result = 0;
int itemCount = 0; int itemCount = 0;
const char **items = NULL; char **items = NULL;
if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
@ -3612,7 +3612,7 @@ int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *activ
} }
// List View control with extended parameters // List View control with extended parameters
int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus) int GuiListViewEx(Rectangle bounds, char **text, int count, int *scrollIndex, int *active, int *focus)
{ {
int result = 0; int result = 0;
GuiState state = guiState; GuiState state = guiState;
@ -4140,7 +4140,7 @@ int GuiMessageBox(Rectangle bounds, const char *title, const char *message, cons
int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button
int buttonCount = 0; int buttonCount = 0;
const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
Rectangle buttonBounds = { 0 }; Rectangle buttonBounds = { 0 };
buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING; buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING;
@ -4199,7 +4199,7 @@ int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, co
int result = -1; int result = -1;
int buttonCount = 0; int buttonCount = 0;
const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
Rectangle buttonBounds = { 0 }; Rectangle buttonBounds = { 0 };
buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
@ -5119,11 +5119,11 @@ static const char *GetTextIcon(const char *text, int *iconId)
// Get text divided into lines (by line-breaks '\n') // Get text divided into lines (by line-breaks '\n')
// WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator! // WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator!
static const char **GetTextLines(const char *text, int *count) static char **GetTextLines(const char *text, int *count)
{ {
#define RAYGUI_MAX_TEXT_LINES 128 #define RAYGUI_MAX_TEXT_LINES 128
static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 }; static char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 };
for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings
int textLength = (int)strlen(text); int textLength = (int)strlen(text);
@ -5131,12 +5131,11 @@ static const char **GetTextLines(const char *text, int *count)
lines[0] = text; lines[0] = text;
*count = 1; *count = 1;
for (int i = 0, k = 0; (i < textLength) && (*count < RAYGUI_MAX_TEXT_LINES); i++) for (int i = 0; (i < textLength) && (*count < RAYGUI_MAX_TEXT_LINES); i++)
{ {
if (text[i] == '\n') if ((text[i] == '\n') && ((i + 1) < textLength))
{ {
k++; lines[*count] = &text[i + 1];
lines[k] = &text[i + 1]; // WARNING: next value is valid?
*count += 1; *count += 1;
} }
} }
@ -5194,7 +5193,7 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C
// WARNING: GuiTextSplit() function can't be used now because it can have already been used // WARNING: GuiTextSplit() function can't be used now because it can have already been used
// before the GuiDrawText() call and its buffer is static, it would be overriden :( // before the GuiDrawText() call and its buffer is static, it would be overriden :(
int lineCount = 0; int lineCount = 0;
const char **lines = GetTextLines(text, &lineCount); char **lines = GetTextLines(text, &lineCount);
// Text style variables // Text style variables
//int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT); //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT);
@ -5444,7 +5443,7 @@ static void GuiTooltip(Rectangle controlRec)
// Split controls text into multiple strings // Split controls text into multiple strings
// Also check for multiple columns (required by GuiToggleGroup()) // Also check for multiple columns (required by GuiToggleGroup())
static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow) static char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow)
{ {
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
// inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
@ -5463,8 +5462,8 @@ static const char **GuiTextSplit(const char *text, char delimiter, int *count, i
#define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024
#endif #endif
static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data) static char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data)
static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added) static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added)
memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE);
result[0] = buffer; result[0] = buffer;
@ -5863,7 +5862,7 @@ static void DrawRectangleGradientV(int posX, int posY, int width, int height, Co
} }
// Split string into multiple strings // Split string into multiple strings
const char **TextSplit(const char *text, char delimiter, int *count) char **TextSplit(const char *text, char delimiter, int *count)
{ {
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
// inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,

View File

@ -772,7 +772,7 @@ RAYGUIAPI int GuiWindowBox(Rectangle bounds, const char *title);
RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name
RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text
RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls
RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1 RAYGUIAPI int GuiTabBar(Rectangle bounds, char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1
RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control
// Basic controls set // Basic controls set
@ -800,7 +800,7 @@ RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int sub
// Advance controls set // Advance controls set
RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control
RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters RAYGUIAPI int GuiListViewEx(Rectangle bounds, char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters
RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message
RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret
RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls) RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls)
@ -1526,7 +1526,7 @@ static Color GetColor(int hexValue); // Returns a Color struct fr
static int ColorToInt(Color color); // Returns hexadecimal value for a Color static int ColorToInt(Color color); // Returns hexadecimal value for a Color
static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings static char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
static int TextToInteger(const char *text); // Get integer value from text static int TextToInteger(const char *text); // Get integer value from text
static float TextToFloat(const char *text); // Get float value from text static float TextToFloat(const char *text); // Get float value from text
@ -1549,7 +1549,7 @@ static const char *GetTextIcon(const char *text, int *iconId); // Get text icon
static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font
static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style
static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings static char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings
static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB
static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV
@ -1783,7 +1783,7 @@ int GuiPanel(Rectangle bounds, const char *text)
// Tab Bar control // Tab Bar control
// NOTE: Using GuiToggle() for the TABS // NOTE: Using GuiToggle() for the TABS
int GuiTabBar(Rectangle bounds, const char **text, int count, int *active) int GuiTabBar(Rectangle bounds, char **text, int count, int *active)
{ {
#define RAYGUI_TABBAR_ITEM_WIDTH 148 #define RAYGUI_TABBAR_ITEM_WIDTH 148
@ -2168,7 +2168,7 @@ int GuiToggleGroup(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers) // Get substrings items from text (items pointers)
int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 }; int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 };
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, rows); char **items = GuiTextSplit(text, ';', &itemCount, rows);
int prevRow = rows[0]; int prevRow = rows[0];
@ -2212,7 +2212,7 @@ int GuiToggleSlider(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers) // Get substrings items from text (items pointers)
int itemCount = 0; int itemCount = 0;
const char **items = NULL; char **items = NULL;
if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
@ -2356,7 +2356,7 @@ int GuiComboBox(Rectangle bounds, const char *text, int *active)
// Get substrings items from text (items pointers, lengths and count) // Get substrings items from text (items pointers, lengths and count)
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, NULL); char **items = GuiTextSplit(text, ';', &itemCount, NULL);
if (*active < 0) *active = 0; if (*active < 0) *active = 0;
else if (*active > (itemCount - 1)) *active = itemCount - 1; else if (*active > (itemCount - 1)) *active = itemCount - 1;
@ -2422,7 +2422,7 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
// Get substrings items from text (items pointers, lengths and count) // Get substrings items from text (items pointers, lengths and count)
int itemCount = 0; int itemCount = 0;
const char **items = GuiTextSplit(text, ';', &itemCount, NULL); char **items = GuiTextSplit(text, ';', &itemCount, NULL);
Rectangle boundsOpen = bounds; Rectangle boundsOpen = bounds;
boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
@ -3602,7 +3602,7 @@ int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *activ
{ {
int result = 0; int result = 0;
int itemCount = 0; int itemCount = 0;
const char **items = NULL; char **items = NULL;
if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
@ -3612,7 +3612,7 @@ int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *activ
} }
// List View control with extended parameters // List View control with extended parameters
int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus) int GuiListViewEx(Rectangle bounds, char **text, int count, int *scrollIndex, int *active, int *focus)
{ {
int result = 0; int result = 0;
GuiState state = guiState; GuiState state = guiState;
@ -4140,7 +4140,7 @@ int GuiMessageBox(Rectangle bounds, const char *title, const char *message, cons
int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button
int buttonCount = 0; int buttonCount = 0;
const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
Rectangle buttonBounds = { 0 }; Rectangle buttonBounds = { 0 };
buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING; buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING;
@ -4199,7 +4199,7 @@ int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, co
int result = -1; int result = -1;
int buttonCount = 0; int buttonCount = 0;
const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
Rectangle buttonBounds = { 0 }; Rectangle buttonBounds = { 0 };
buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
@ -5119,11 +5119,11 @@ static const char *GetTextIcon(const char *text, int *iconId)
// Get text divided into lines (by line-breaks '\n') // Get text divided into lines (by line-breaks '\n')
// WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator! // WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator!
static const char **GetTextLines(const char *text, int *count) static char **GetTextLines(const char *text, int *count)
{ {
#define RAYGUI_MAX_TEXT_LINES 128 #define RAYGUI_MAX_TEXT_LINES 128
static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 }; static char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 };
for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings
int textLength = (int)strlen(text); int textLength = (int)strlen(text);
@ -5131,12 +5131,11 @@ static const char **GetTextLines(const char *text, int *count)
lines[0] = text; lines[0] = text;
*count = 1; *count = 1;
for (int i = 0, k = 0; (i < textLength) && (*count < RAYGUI_MAX_TEXT_LINES); i++) for (int i = 0; (i < textLength) && (*count < RAYGUI_MAX_TEXT_LINES); i++)
{ {
if (text[i] == '\n') if ((text[i] == '\n') && ((i + 1) < textLength))
{ {
k++; lines[*count] = &text[i + 1];
lines[k] = &text[i + 1]; // WARNING: next value is valid?
*count += 1; *count += 1;
} }
} }
@ -5194,7 +5193,7 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C
// WARNING: GuiTextSplit() function can't be used now because it can have already been used // WARNING: GuiTextSplit() function can't be used now because it can have already been used
// before the GuiDrawText() call and its buffer is static, it would be overriden :( // before the GuiDrawText() call and its buffer is static, it would be overriden :(
int lineCount = 0; int lineCount = 0;
const char **lines = GetTextLines(text, &lineCount); char **lines = GetTextLines(text, &lineCount);
// Text style variables // Text style variables
//int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT); //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT);
@ -5444,7 +5443,7 @@ static void GuiTooltip(Rectangle controlRec)
// Split controls text into multiple strings // Split controls text into multiple strings
// Also check for multiple columns (required by GuiToggleGroup()) // Also check for multiple columns (required by GuiToggleGroup())
static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow) static char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow)
{ {
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
// inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
@ -5463,8 +5462,8 @@ static const char **GuiTextSplit(const char *text, char delimiter, int *count, i
#define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024
#endif #endif
static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data) static char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data)
static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added) static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added)
memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE);
result[0] = buffer; result[0] = buffer;
@ -5863,7 +5862,7 @@ static void DrawRectangleGradientV(int posX, int posY, int width, int height, Co
} }
// Split string into multiple strings // Split string into multiple strings
const char **TextSplit(const char *text, char delimiter, int *count) char **TextSplit(const char *text, char delimiter, int *count)
{ {
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
// inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,

View File

@ -17,7 +17,7 @@
#include "raylib.h" #include "raylib.h"
#include "reasings.h" // Required for easing functions #include "reasings.h" // Required for: easing functions
#define FONT_SIZE 20 #define FONT_SIZE 20

View File

@ -52,6 +52,7 @@ int main(void)
float hue = t*t; float hue = t*t;
float saturation = t; float saturation = t;
float value = t; float value = t;
palette[i] = ColorFromHSV(250.0f + 150.0f*hue, saturation, value); palette[i] = ColorFromHSV(250.0f + 150.0f*hue, saturation, value);
} }
@ -66,11 +67,9 @@ int main(void)
// Grow flameRoot // Grow flameRoot
for (int x = 2; x < flameWidth; x++) for (int x = 2; x < flameWidth; x++)
{ {
unsigned char flame = flameRootBuffer[x]; int flame = (int)flameRootBuffer[x];
if (flame == 255) continue;
flame += GetRandomValue(0, 2); flame += GetRandomValue(0, 2);
if (flame > 255) flame = 255; flameRootBuffer[x] = (flame > 255)? 255: (unsigned char)flame;
flameRootBuffer[x] = flame;
} }
// Transfer flameRoot to indexBuffer // Transfer flameRoot to indexBuffer
@ -83,8 +82,7 @@ int main(void)
// Clear top row, because it can't move any higher // Clear top row, because it can't move any higher
for (int x = 0; x < imageWidth; x++) for (int x = 0; x < imageWidth; x++)
{ {
if (indexBuffer[x] == 0) continue; if (indexBuffer[x] != 0) indexBuffer[x] = 0;
indexBuffer[x] = 0;
} }
// Skip top row, it is already cleared // Skip top row, it is already cleared
@ -94,18 +92,22 @@ int main(void)
{ {
unsigned int i = x + y*imageWidth; unsigned int i = x + y*imageWidth;
unsigned char colorIndex = indexBuffer[i]; unsigned char colorIndex = indexBuffer[i];
if (colorIndex == 0) continue;
// Move pixel a row above if (colorIndex != 0)
indexBuffer[i] = 0; {
int moveX = GetRandomValue(0, 2) - 1; // Move pixel a row above
int newX = x + moveX; indexBuffer[i] = 0;
if (newX < 0 || newX >= imageWidth) continue; int moveX = GetRandomValue(0, 2) - 1;
int newX = x + moveX;
unsigned int iabove = i - imageWidth + moveX; if ((newX > 0) && (newX < imageWidth))
int decay = GetRandomValue(0, 3); {
colorIndex -= (decay < colorIndex)? decay : colorIndex; unsigned int iabove = i - imageWidth + moveX;
indexBuffer[iabove] = colorIndex; int decay = GetRandomValue(0, 3);
colorIndex -= (decay < colorIndex)? decay : colorIndex;
indexBuffer[iabove] = colorIndex;
}
}
} }
} }
@ -117,6 +119,7 @@ int main(void)
unsigned int i = x + y*imageWidth; unsigned int i = x + y*imageWidth;
unsigned char colorIndex = indexBuffer[i]; unsigned char colorIndex = indexBuffer[i];
Color col = palette[colorIndex]; Color col = palette[colorIndex];
ImageDrawPixel(&screenImage, x, y, col); ImageDrawPixel(&screenImage, x, y, col);
} }
} }

View File

@ -2016,6 +2016,15 @@ int InitPlatform(void)
// Init window // Init window
#if defined(USING_VERSION_SDL3) #if defined(USING_VERSION_SDL3)
platform.window = SDL_CreateWindow(CORE.Window.title, CORE.Window.screen.width, CORE.Window.screen.height, flags); platform.window = SDL_CreateWindow(CORE.Window.title, CORE.Window.screen.width, CORE.Window.screen.height, flags);
// NOTE: SDL3 no longer enables text input by default,
// it is needed to be enabled manually to keep GetCharPressed() working
// REF: https://github.com/libsdl-org/SDL/commit/72fc6f86e5d605a3787222bc7dc18c5379047f4a
const char *enableOSK = SDL_GetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD);
if (enableOSK == NULL) SDL_SetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD, "0");
if (!SDL_StartTextInput(platform.window)) TRACELOG(LOG_WARNING, "SDL: Failed to start text input: %s", SDL_GetError());
if (enableOSK == NULL) SDL_SetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD, NULL);
#else #else
platform.window = SDL_CreateWindow(CORE.Window.title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, CORE.Window.screen.width, CORE.Window.screen.height, flags); platform.window = SDL_CreateWindow(CORE.Window.title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, CORE.Window.screen.width, CORE.Window.screen.height, flags);
#endif #endif

View File

@ -295,6 +295,10 @@ typedef struct tagBITMAPINFOHEADER {
#define MAX_AUDIO_BUFFER_POOL_CHANNELS 16 // Audio pool channels #define MAX_AUDIO_BUFFER_POOL_CHANNELS 16 // Audio pool channels
#endif #endif
#ifndef AUDIO_BUFFER_RESIDUAL_CAPACITY
#define AUDIO_BUFFER_RESIDUAL_CAPACITY 8 // In PCM frames. For resampling and pitch shifting.
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -337,6 +341,8 @@ typedef enum {
// Audio buffer struct // Audio buffer struct
struct rAudioBuffer { struct rAudioBuffer {
ma_data_converter converter; // Audio data converter ma_data_converter converter; // Audio data converter
unsigned char* converterResidual; // Cached residual input frames for use by the converter
unsigned int converterResidualCount; // The number of valid frames sitting in converterResidual
AudioCallback callback; // Audio buffer callback for buffer filling on audio threads AudioCallback callback; // Audio buffer callback for buffer filling on audio threads
rAudioProcessor *processor; // Audio processor rAudioProcessor *processor; // Audio processor
@ -586,6 +592,15 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
return NULL; return NULL;
} }
// A cache for use by the converter is necessary when resampling because
// when generating output frames a different number of input frames will
// be consumed. Any residual input frames need to be kept track of to
// ensure there are no discontinuities. Since raylib supports pitch
// shifting, which is done through resampling, a cache will always be
// required. This will be kept relatively small to avoid too much wastage.
audioBuffer->converterResidualCount = 0;
audioBuffer->converterResidual = (unsigned char*)RL_CALLOC(AUDIO_BUFFER_RESIDUAL_CAPACITY*ma_get_bytes_per_frame(format, channels), 1);
// Init audio buffer values // Init audio buffer values
audioBuffer->volume = 1.0f; audioBuffer->volume = 1.0f;
audioBuffer->pitch = 1.0f; audioBuffer->pitch = 1.0f;
@ -621,6 +636,7 @@ void UnloadAudioBuffer(AudioBuffer *buffer)
{ {
UntrackAudioBuffer(buffer); UntrackAudioBuffer(buffer);
ma_data_converter_uninit(&buffer->converter, NULL); ma_data_converter_uninit(&buffer->converter, NULL);
RL_FREE(buffer->converterResidual);
RL_FREE(buffer->data); RL_FREE(buffer->data);
RL_FREE(buffer); RL_FREE(buffer);
} }
@ -705,7 +721,7 @@ void SetAudioBufferPitch(AudioBuffer *buffer, float pitch)
// Note that this changes the duration of the sound: // Note that this changes the duration of the sound:
// - higher pitches will make the sound faster // - higher pitches will make the sound faster
// - lower pitches make it slower // - lower pitches make it slower
ma_uint32 outputSampleRate = (ma_uint32)((float)buffer->converter.sampleRateOut/pitch); ma_uint32 outputSampleRate = (ma_uint32)((float)AUDIO.System.device.sampleRate/pitch);
ma_data_converter_set_rate(&buffer->converter, buffer->converter.sampleRateIn, outputSampleRate); ma_data_converter_set_rate(&buffer->converter, buffer->converter.sampleRateIn, outputSampleRate);
buffer->pitch = pitch; buffer->pitch = pitch;
@ -2456,38 +2472,78 @@ static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, f
// NOTE: Continuously converting data from the AudioBuffer's internal format to the mixing format, // 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. // which should be defined by the output format of the data converter.
// This is done until frameCount frames have been output. // This is done until frameCount frames have been output.
// The important detail to remember is that more data than required should neeveer be read, ma_uint32 bpf = ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn);
// 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)/bpf;
ma_uint32 totalOutputFramesProcessed = 0; ma_uint32 totalOutputFramesProcessed = 0;
while (totalOutputFramesProcessed < frameCount) while (totalOutputFramesProcessed < frameCount)
{ {
float *runningFramesOut = framesOut + (totalOutputFramesProcessed*audioBuffer->converter.channelsOut);
ma_uint64 outputFramesToProcessThisIteration = frameCount - totalOutputFramesProcessed; ma_uint64 outputFramesToProcessThisIteration = frameCount - totalOutputFramesProcessed;
ma_uint64 inputFramesToProcessThisIteration = 0; ma_uint64 inputFramesToProcessThisIteration = 0;
(void)ma_data_converter_get_required_input_frame_count(&audioBuffer->converter, outputFramesToProcessThisIteration, &inputFramesToProcessThisIteration); // Process any residual input frames from the previous read first.
if (inputFramesToProcessThisIteration > inputBufferFrameCap) if (audioBuffer->converterResidualCount > 0)
{ {
inputFramesToProcessThisIteration = inputBufferFrameCap; ma_uint64 inputFramesProcessedThisIteration = audioBuffer->converterResidualCount;
ma_uint64 outputFramesProcessedThisIteration = outputFramesToProcessThisIteration;
ma_data_converter_process_pcm_frames(&audioBuffer->converter, audioBuffer->converterResidual, &inputFramesProcessedThisIteration, runningFramesOut, &outputFramesProcessedThisIteration);
// Make sure the data in the cache is consumed. This can be optimized to use a cursor instead of a memmove().
memmove(audioBuffer->converterResidual, audioBuffer->converterResidual + inputFramesProcessedThisIteration*bpf, (size_t)(AUDIO_BUFFER_RESIDUAL_CAPACITY - inputFramesProcessedThisIteration) * bpf);
audioBuffer->converterResidualCount -= (ma_uint32)inputFramesProcessedThisIteration; // Safe cast
totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration; // Safe cast
} }
else
{
// Getting here means there are no residual frames from the previous read. Fresh data can now be
// pulled from the AudioBuffer and processed.
//
// A best guess needs to be used made to determine how many input frames to pull from the
// buffer. There are three possible outcomes: 1) exact; 2) underestimated; 3) overestimated.
//
// When the guess is exactly correct or underestimated there is nothing special to handle - it'll be
// handled naturally by the loop.
//
// When the guess is overestimated, that's when it gets more complicated. In this case, any overflow
// needs to be stored in a buffer for later processing by the next read.
ma_uint32 estimatedInputFrameCount = (ma_uint32)(((float)audioBuffer->converter.resampler.sampleRateIn / audioBuffer->converter.resampler.sampleRateOut) * outputFramesToProcessThisIteration);
if (estimatedInputFrameCount == 0)
{
estimatedInputFrameCount = 1; // Make sure at least one input frame is read.
}
float *runningFramesOut = framesOut + (totalOutputFramesProcessed*audioBuffer->converter.channelsOut); if (estimatedInputFrameCount > inputBufferFrameCap)
{
estimatedInputFrameCount = inputBufferFrameCap;
}
// At this point we can convert the data to our mixing format estimatedInputFrameCount = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, estimatedInputFrameCount);
ma_uint64 inputFramesProcessedThisIteration = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, (ma_uint32)inputFramesToProcessThisIteration);
ma_uint64 outputFramesProcessedThisIteration = outputFramesToProcessThisIteration;
ma_data_converter_process_pcm_frames(&audioBuffer->converter, inputBuffer, &inputFramesProcessedThisIteration, runningFramesOut, &outputFramesProcessedThisIteration);
totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration; // Safe cast ma_uint64 inputFramesProcessedThisIteration = estimatedInputFrameCount;
ma_uint64 outputFramesProcessedThisIteration = outputFramesToProcessThisIteration;
ma_data_converter_process_pcm_frames(&audioBuffer->converter, inputBuffer, &inputFramesProcessedThisIteration, runningFramesOut, &outputFramesProcessedThisIteration);
if (inputFramesProcessedThisIteration < inputFramesToProcessThisIteration) break; // Ran out of input data if (estimatedInputFrameCount > inputFramesProcessedThisIteration)
{
// Getting here means the estimated input frame count was overestimated. The residual needs
// be stored for later use.
ma_uint64 residualFrameCount = estimatedInputFrameCount - inputFramesProcessedThisIteration;
// This should never be hit, but added here for safety // A safety check to make sure the capacity of the residual cache is not exceeded.
// Ensures we get out of the loop when no input nor output frames are processed if (residualFrameCount > AUDIO_BUFFER_RESIDUAL_CAPACITY)
if ((inputFramesProcessedThisIteration == 0) && (outputFramesProcessedThisIteration == 0)) break; {
residualFrameCount = AUDIO_BUFFER_RESIDUAL_CAPACITY;
}
memcpy(audioBuffer->converterResidual, inputBuffer + inputFramesProcessedThisIteration*bpf, (size_t)(residualFrameCount * bpf));
audioBuffer->converterResidualCount = residualFrameCount;
}
totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration;
}
} }
return totalOutputFramesProcessed; return totalOutputFramesProcessed;

View File

@ -3422,7 +3422,7 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
// Possible formats: GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32 and GL_DEPTH_COMPONENT32F // Possible formats: GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32 and GL_DEPTH_COMPONENT32F
unsigned int glInternalFormat = GL_DEPTH_COMPONENT; unsigned int glInternalFormat = GL_DEPTH_COMPONENT;
#if (defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_ES3)) #if defined(GRAPHICS_API_OPENGL_ES2)
// WARNING: WebGL platform requires unsized internal format definition (GL_DEPTH_COMPONENT) // WARNING: WebGL platform requires unsized internal format definition (GL_DEPTH_COMPONENT)
// while other platforms using OpenGL ES 2.0 require/support sized internal formats depending on the GPU capabilities // while other platforms using OpenGL ES 2.0 require/support sized internal formats depending on the GPU capabilities
if (!RLGL.ExtSupported.texDepthWebGL || useRenderBuffer) if (!RLGL.ExtSupported.texDepthWebGL || useRenderBuffer)

View File

@ -1497,15 +1497,14 @@ void UnloadTextLines(char **lines, int lineCount)
} }
// Get text length in bytes, check for \0 character // Get text length in bytes, check for \0 character
// NOTE: Alternative: use strlen(text)
unsigned int TextLength(const char *text) unsigned int TextLength(const char *text)
{ {
unsigned int length = 0; unsigned int length = 0;
if (text != NULL) if (text != NULL)
{ {
// NOTE: Alternative: use strlen(text) while (text[length] != '\0') length++;
while (*text++) length++;
} }
return length; return length;
@ -1718,7 +1717,7 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
{ {
char *result = NULL; char *result = NULL;
if ((text != NULL) && (search != NULL)) if ((text != NULL) && (search != NULL) && (search[0] != '\0'))
{ {
if (replacement == NULL) replacement = ""; if (replacement == NULL) replacement = "";
@ -1732,8 +1731,6 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
textLen = TextLength(text); textLen = TextLength(text);
searchLen = TextLength(search); searchLen = TextLength(search);
if (searchLen == 0) return NULL; // Empty search causes infinite loop during count
replaceLen = TextLength(replacement); replaceLen = TextLength(replacement);
// Count the number of replacements needed // Count the number of replacements needed
@ -1742,34 +1739,37 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
// Allocate returning string and point temp to it // Allocate returning string and point temp to it
int tempLen = textLen + (replaceLen - searchLen)*count + 1; int tempLen = textLen + (replaceLen - searchLen)*count + 1;
temp = result = (char *)RL_MALLOC(tempLen); temp = result = (char *)RL_CALLOC(tempLen, sizeof(char));
if (!result) return NULL; // Memory could not be 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
// - 'insertPoint' points to the next occurrence of replace in text
// - 'text' points to the remainder of text after "end of replace"
while (count--)
{ {
insertPoint = (char *)strstr(text, search); // First time through the loop, all the variable are set correctly from here on,
lastReplacePos = (int)(insertPoint - text); // - 'temp' points to the end of the result string
// - 'insertPoint' points to the next occurrence of replace in text
memcpy(temp, text, lastReplacePos); // - 'text' points to the remainder of text after "end of replace"
temp += lastReplacePos; while (count > 0)
if (replaceLen > 0)
{ {
memcpy(temp, replacement, replaceLen); insertPoint = (char *)strstr(text, search);
temp += replaceLen; lastReplacePos = (int)(insertPoint - text);
memcpy(temp, text, lastReplacePos);
temp += lastReplacePos;
if (replaceLen > 0)
{
memcpy(temp, replacement, replaceLen);
temp += replaceLen;
}
text += (lastReplacePos + searchLen); // Move to next "end of replace"
count--;
} }
text += lastReplacePos + searchLen; // Move to next "end of replace" // Copy remaind text part after replacement to result (pointed by moving temp)
// NOTE: Text pointer internal copy has been updated along the process
strncpy(temp, text, TextLength(text));
} }
// Copy remaind text part after replacement to result (pointed by moving temp)
strcpy(temp, text); // OK
//strncpy(temp, text, tempLen - 1); // WRONG
} }
return result; return result;