Compare commits

5 Commits

Author SHA1 Message Date
Ray
8d33708103 Create Directory.Build.props 2026-06-25 00:48:26 +02:00
Ray
1066fd663f Update raygui.rc 2026-06-25 00:48:18 +02:00
Ray
5d3a35d674 Update raygui.h 2026-06-25 00:38:07 +02:00
Ray
3ad9038e02 ADDED: GuiFontIconBaking() to support icons baking into font atlas image
REDESIGNED: `GuiLoadStyleFromMemory()` to support icons baking
2026-06-25 00:29:17 +02:00
Ray
ad18a0ab07 Code cleaning and some reorganization 2026-06-25 00:26:11 +02:00
4 changed files with 540 additions and 375 deletions

View File

@ -38,6 +38,7 @@
//#define RAYGUI_DEBUG_RECS_BOUNDS
//#define RAYGUI_DEBUG_TEXT_BOUNDS
//#define RAYGUI_FONT_ICONS_BAKING
#define RAYGUI_IMPLEMENTATION
//#define RAYGUI_CUSTOM_ICONS // It requires providing gui_icons.h in the same directory
//#include "gui_icons.h" // External icons data provided, it can be generated with rGuiIcons tool
@ -66,13 +67,17 @@ int main()
// Initialization
//---------------------------------------------------------------------------------------
const int screenWidth = 960;
const int screenHeight = 560;
const int screenHeight = 580;
InitWindow(screenWidth, screenHeight, "raygui - controls test suite");
SetExitKey(0);
// GUI controls initialization
//----------------------------------------------------------------------------------
char *tabNames[] = { "#124#TAB_01", "#98#TAB_02", "#217#TAB_03", "#56#TAB_04", "#24#TAB_05", "#12#TAB_06" };
int tabCount = 6;
int tabActive = 0;
int dropdownBox000Active = 0;
bool dropDown000EditMode = false;
@ -212,31 +217,34 @@ int main()
if (dropDown000EditMode || dropDown001EditMode) GuiLock();
if (showTextInputBox) GuiLock();
GuiSetStyle(TABBAR, TAB_ITEMS_WIDTH, 140);
GuiTabBar((Rectangle){ 0, 8, GetScreenWidth(), 26 }, tabNames, tabCount, &tabActive);
// First GUI column
//GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
GuiCheckBox((Rectangle){ 25, 108, 15, 15 }, "FORCE CHECK!", &forceSquaredChecked);
GuiCheckBox((Rectangle){ 25, 108 + 20, 15, 15 }, "FORCE CHECK!", &forceSquaredChecked);
GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
//GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
if (GuiSpinner((Rectangle){ 25, 135, 125, 30 }, NULL, &spinner001Value, 0, 100, spinnerEditMode)) spinnerEditMode = !spinnerEditMode;
if (GuiValueBox((Rectangle){ 25, 175, 125, 30 }, NULL, &valueBox002Value, 0, 100, valueBoxEditMode)) valueBoxEditMode = !valueBoxEditMode;
if (GuiSpinner((Rectangle){ 25, 135 + 20, 125, 30 }, NULL, &spinner001Value, 0, 100, spinnerEditMode)) spinnerEditMode = !spinnerEditMode;
if (GuiValueBox((Rectangle){ 25, 175 + 20, 125, 30 }, NULL, &valueBox002Value, 0, 100, valueBoxEditMode)) valueBoxEditMode = !valueBoxEditMode;
GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
if (GuiTextBox((Rectangle){ 25, 215, 125, 30 }, textBoxText, 64, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
if (GuiTextBox((Rectangle){ 25, 215 + 20, 125, 30 }, textBoxText, 64, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
if (GuiButton((Rectangle){ 25, 255, 125, 30 }, GuiIconText(ICON_FILE_SAVE, "Save File"))) showTextInputBox = true;
if (GuiButton((Rectangle){ 25, 255 + 20, 125, 30 }, GuiIconText(ICON_FILE_SAVE, "Save File"))) showTextInputBox = true;
GuiGroupBox((Rectangle){ 25, 310, 125, 150 }, "STATES");
GuiGroupBox((Rectangle){ 25, 310 + 20, 125, 150 }, "STATES");
//GuiLock();
GuiSetState(STATE_NORMAL); if (GuiButton((Rectangle){ 30, 320, 115, 30 }, "NORMAL")) { }
GuiSetState(STATE_FOCUSED); if (GuiButton((Rectangle){ 30, 355, 115, 30 }, "FOCUSED")) { }
GuiSetState(STATE_PRESSED); if (GuiButton((Rectangle){ 30, 390, 115, 30 }, "#15#PRESSED")) { }
GuiSetState(STATE_DISABLED); if (GuiButton((Rectangle){ 30, 425, 115, 30 }, "DISABLED")) { }
GuiSetState(STATE_NORMAL); if (GuiButton((Rectangle){ 30, 320 + 20, 115, 30 }, "NORMAL")) { }
GuiSetState(STATE_FOCUSED); if (GuiButton((Rectangle){ 30, 355 + 20, 115, 30 }, "FOCUSED")) { }
GuiSetState(STATE_PRESSED); if (GuiButton((Rectangle){ 30, 390 + 20, 115, 30 }, "#15#PRESSED")) { }
GuiSetState(STATE_DISABLED); if (GuiButton((Rectangle){ 30, 425 + 20, 115, 30 }, "DISABLED")) { }
GuiSetState(STATE_NORMAL);
//GuiUnlock();
GuiComboBox((Rectangle){ 25, 480, 125, 30 },
GuiComboBox((Rectangle){ 25, 480 + 20, 125, 30 },
"default;Jungle;Lavanda;Dark;Bluish;Cyber;Terminal;Candy;Cherry;Ashes;Enefete;Sunny;Amber;Genesis", &visualStyleActive);
// NOTE: GuiDropdownBox must draw after any other control that can be covered on unfolding
@ -245,48 +253,48 @@ int main()
GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 4);
GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
if (GuiDropdownBox((Rectangle){ 25, 65, 125, 30 }, "#01#ONE;#02#TWO;#03#THREE;#04#FOUR", &dropdownBox001Active, dropDown001EditMode)) dropDown001EditMode = !dropDown001EditMode;
if (GuiDropdownBox((Rectangle){ 25, 65 + 20, 125, 30 }, "#01#ONE;#02#TWO;#03#THREE;#04#FOUR", &dropdownBox001Active, dropDown001EditMode)) dropDown001EditMode = !dropDown001EditMode;
GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 0);
if (GuiDropdownBox((Rectangle){ 25, 25, 125, 30 }, "ONE;TWO;THREE", &dropdownBox000Active, dropDown000EditMode)) dropDown000EditMode = !dropDown000EditMode;
if (GuiDropdownBox((Rectangle){ 25, 25 + 20, 125, 30 }, "ONE;TWO;THREE", &dropdownBox000Active, dropDown000EditMode)) dropDown000EditMode = !dropDown000EditMode;
// Second GUI column
//GuiSetStyle(LISTVIEW, LIST_ITEMS_BORDER_NORMAL, 1);
GuiListView((Rectangle){ 165, 25, 140, 124 }, "Charmander;Bulbasaur;#18#Squirtle;Pikachu;Eevee;Pidgey", &listViewScrollIndex, &listViewActive);
GuiListViewEx((Rectangle){ 165, 162, 140, 184 }, listViewExList, 8, &listViewExScrollIndex, &listViewExActive, &listViewExFocus);
GuiListView((Rectangle){ 165, 25 + 20, 140, 124 }, "Charmander;Bulbasaur;#18#Squirtle;Pikachu;Eevee;Pidgey", &listViewScrollIndex, &listViewActive);
GuiListViewEx((Rectangle){ 165, 162 + 20, 140, 184 }, listViewExList, 8, &listViewExScrollIndex, &listViewExActive, &listViewExFocus);
GuiSetStyle(LISTVIEW, LIST_ITEMS_BORDER_NORMAL, 0);
//GuiToggle((Rectangle){ 165, 400, 140, 25 }, "#1#ONE", &toggleGroupActive);
GuiToggleGroup((Rectangle){ 165, 360, 140, 24 }, "#1#ONE\n#3#TWO\n#8#THREE\n#23#", &toggleGroupActive);
GuiToggleGroup((Rectangle){ 165, 360 + 20, 140, 24 }, "#1#ONE\n#3#TWO\n#8#THREE\n#23#", &toggleGroupActive);
//GuiDisable();
GuiSetStyle(SLIDER, SLIDER_PADDING, 2);
GuiToggleSlider((Rectangle){ 165, 480, 140, 30 }, "ON;OFF", &toggleSliderActive);
GuiToggleSlider((Rectangle){ 165, 480 + 20, 140, 30 }, "ON;OFF", &toggleSliderActive);
GuiSetStyle(SLIDER, SLIDER_PADDING, 0);
// Third GUI column
GuiPanel((Rectangle){ 320, 25, 225, 140 }, "Panel Info");
GuiColorPicker((Rectangle){ 320, 185, 196, 192 }, NULL, &colorPickerValue);
GuiPanel((Rectangle){ 320, 25 + 20, 225, 140 }, "Panel Info");
GuiColorPicker((Rectangle){ 320, 185 + 20, 196, 192 }, NULL, &colorPickerValue);
//GuiDisable();
GuiSlider((Rectangle){ 355, 400, 165, 20 }, "TEST", TextFormat("%2.2f", sliderValue), &sliderValue, -50, 100);
GuiSliderBar((Rectangle){ 320, 430, 200, 20 }, NULL, TextFormat("%i", (int)sliderBarValue), &sliderBarValue, 0, 100);
GuiSlider((Rectangle){ 355, 400 + 20, 165, 20 }, "TEST", TextFormat("%2.2f", sliderValue), &sliderValue, -50, 100);
GuiSliderBar((Rectangle){ 320, 430 + 20, 200, 20 }, NULL, TextFormat("%i", (int)sliderBarValue), &sliderBarValue, 0, 100);
GuiProgressBar((Rectangle){ 320, 460, 200, 20 }, NULL, TextFormat("%i%%", (int)(progressValue*100)), &progressValue, 0.0f, 1.0f);
GuiProgressBar((Rectangle){ 320, 460 + 20, 200, 20 }, NULL, TextFormat("%i%%", (int)(progressValue*100)), &progressValue, 0.0f, 1.0f);
GuiEnable();
// NOTE: View rectangle could be used to perform some scissor test
Rectangle view = { 0 };
GuiScrollPanel((Rectangle){ 560, 25, 102, 354 }, NULL, (Rectangle){ 560, 25, 300, 1200 }, &viewScroll, &view);
GuiScrollPanel((Rectangle){ 560, 25 + 20, 102, 354 }, NULL, (Rectangle){ 560, 25, 300, 1200 }, &viewScroll, &view);
Vector2 mouseCell = { 0 };
GuiGrid((Rectangle) { 560, 25 + 180 + 195, 100, 120 }, NULL, 20, 3, &mouseCell);
GuiGrid((Rectangle) { 560, 25 + 180 + 195 + 20, 100, 120 }, NULL, 20, 3, &mouseCell);
GuiColorBarAlpha((Rectangle){ 320, 490, 200, 30 }, NULL, &alphaValue);
GuiColorBarAlpha((Rectangle){ 320, 490 + 20, 200, 30 }, NULL, &alphaValue);
GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP); // WARNING: Word-wrap does not work as expected in case of no-top alignment
GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // WARNING: If wrap mode enabled, text editing is not supported
if (GuiTextBox((Rectangle){ 678, 25, 258, 492 }, textBoxMultiText, 1024, textBoxMultiEditMode)) textBoxMultiEditMode = !textBoxMultiEditMode;
if (GuiTextBox((Rectangle){ 678, 25 + 20, 258, 492 }, textBoxMultiText, 1024, textBoxMultiEditMode)) textBoxMultiEditMode = !textBoxMultiEditMode;
GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE);
GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE);

View File

@ -1,8 +1,8 @@
GLFW_ICON ICON "raygui.ico"
1 VERSIONINFO
FILEVERSION 4,0,0,0
PRODUCTVERSION 4,0,0,0
FILEVERSION 5,0,0,0
PRODUCTVERSION 5,0,0,0
BEGIN
BLOCK "StringFileInfo"
BEGIN
@ -11,12 +11,12 @@ BEGIN
BEGIN
//VALUE "CompanyName", "raylib technologies"
VALUE "FileDescription", "raygui application (www.raylib.com)"
VALUE "FileVersion", "4.0.0"
VALUE "FileVersion", "5.0.0"
VALUE "InternalName", "raygui app"
VALUE "LegalCopyright", "(c) 2023 Ramon Santamaria (@raysan5)"
VALUE "LegalCopyright", "(c) 2026 Ramon Santamaria (@raysan5)"
//VALUE "OriginalFilename", "raygui_app.exe"
VALUE "ProductName", "raygui app"
VALUE "ProductVersion", "4.0.0"
VALUE "ProductVersion", "5.0.0"
END
END
BLOCK "VarFileInfo"

View File

@ -0,0 +1,7 @@
<Project>
<ItemDefinitionGroup>
<ClCompile>
<PreProcessorDefinitions>%(PreProcessorDefinitions);EXTERNAL_CONFIG_FLAGS;SUPPORT_MODULE_RSHAPES;SUPPORT_MODULE_RTEXTURES;SUPPORT_MODULE_RTEXT;SUPPORT_COMPRESSION_API;SUPPORT_SCREEN_CAPTURE;SUPPORT_QUADS_DRAW_MODE;SUPPORT_FILEFORMAT_TTF;SUPPORT_FILEFORMAT_PNG;SUPPORT_IMAGE_EXPORT;SUPPORT_TRACELOG</PreProcessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</Project>

View File

@ -134,6 +134,10 @@
* Includes custom ricons.h header defining a set of custom icons,
* this file can be generated using rGuiIcons tool
*
* #define RAYGUI_FONT_ICONS_BAKING
* On gui font loading from style file, append the icons to font atlas image, so,
* icons can be drawn along the text as a texture, instead of using shapes to draw them
*
* #define RAYGUI_DEBUG_RECS_BOUNDS
* Draw control bounds rectangles for debug
*
@ -143,6 +147,7 @@
* VERSIONS HISTORY:
* 5.0 (xx-Jun-2026) ADDED: TABBAR control: GuiTabBar()
* ADDED: Support up to 512 icons (v500)
* ADDED: Support icons baking into font atlas image
* ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes
* ADDED: Altrnative VALUEBOX: GuiValueBoxFloat()
* ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP
@ -167,6 +172,7 @@
* REVIEWED: GuiProgressBar(), improved borders computing
* REVIEWED: GuiTextBox(), multiple improvements: autocursor and more
* REVIEWED: Functions descriptions, removed wrong return value reference
* REDESIGNED: GuiLoadStyleFromMemory() to support icons baking into font atlas
* REDESIGNED: GuiToggleGroup() to process rows/cols with no need for GuiTextSplit()
* REDESIGNED: GuiColorPanel(), improved HSV <-> RGBA convertion
* REDESIGNED: WARNING: TEXT_LINE_SPACING does not consider text height, only lines spacing
@ -386,8 +392,8 @@
#define RAYGUI_LOG(...)
#endif
#if !defined(RAYGUI_STANDALONE)
// Macros to define required UI inputs, including mapping to gamepad controls
// TODO: Define additionally required macros for missing inputs
#if !defined(GUI_BUTTON_DOWN)
#define GUI_BUTTON_DOWN (IsMouseButtonDown(MOUSE_LEFT_BUTTON) || IsGamepadButtonDown(0, GAMEPAD_BUTTON_RIGHT_FACE_DOWN))
#endif
@ -398,7 +404,9 @@
#if !defined(GUI_BUTTON_PRESSED)
#define GUI_BUTTON_PRESSED (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsGamepadButtonPressed(0, GAMEPAD_BUTTON_RIGHT_FACE_DOWN))
#endif
// TODO: WARNING: GuiTabBar() still requires IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)
#if !defined(GUI_BUTTON_PRESSED_MID)
#define GUI_BUTTON_PRESSED_MID (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON) || IsGamepadButtonPressed(0, GAMEPAD_BUTTON_RIGHT_FACE_UP))
#endif
#if !defined(GUI_BUTTON_RELEASED)
#define GUI_BUTTON_RELEASED (IsMouseButtonReleased(MOUSE_LEFT_BUTTON) || IsGamepadButtonReleased(0, GAMEPAD_BUTTON_RIGHT_FACE_DOWN))
#endif
@ -424,6 +432,18 @@
#if !defined(GUI_INPUT_KEY)
#define GUI_INPUT_KEY GetCharPressed()
#endif
#else
#define GUI_BUTTON_DOWN 0
#define GUI_BUTTON_DOWN_ALT 0
#define GUI_BUTTON_PRESSED 0
#define GUI_BUTTON_PRESSED_MID 0
#define GUI_BUTTON_RELEASED 0
#define GUI_SCROLL_DELTA 0
#define GUI_POINTER_POSITION (Vector2){ 0 }
#define GUI_KEY_DOWN(key) 0
#define GUI_KEY_PRESSED(key) 0
#define GUI_INPUT_KEY 0
#endif
//----------------------------------------------------------------------------------
// Types and Structures Definition
@ -458,6 +478,8 @@
unsigned char a;
} Color;
#define BLANK (Color){ 0, 0, 0, 0 } // Blank (Transparent)
// Rectangle type
typedef struct Rectangle {
float x;
@ -466,7 +488,7 @@
float height;
} Rectangle;
// TODO: Texture2D type is very coupled to raylib, required by Font type
// NOTE: Texture2D type is very coupled to raylib, required by Font type
// It should be redesigned to be provided by user
typedef struct Texture {
unsigned int id; // OpenGL texture id
@ -497,7 +519,7 @@
Image image; // Character image data
} GlyphInfo;
// TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle()
// NOTE: Font type is very coupled to raylib, mostly required by GuiLoadStyle()
// It should be redesigned to be provided by user
typedef struct Font {
int baseSize; // Base size (default chars height)
@ -1152,7 +1174,9 @@ typedef enum {
// Embedded icons, no external file provided
#define RAYGUI_ICON_SIZE 16 // Size of icons in pixels (squared)
#define RAYGUI_ICON_MAX_ICONS 512 // Maximum number of icons
#define RAYGUI_ICON_MAX_FONT_BACKED 257 // Maximum number of icons to back in font atlas
#define RAYGUI_ICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id
#define RAYGUI_ICON_FONT_ATLAS_PADDING 1 // Padding between backed icons in font atlas
// Icons data is defined by bit array (every bit represents one pixel)
// Those arrays are stored as unsigned int data arrays, so,
@ -1465,6 +1489,7 @@ static bool guiLocked = false; // Gui lock state (no inputs pro
static float guiAlpha = 1.0f; // Gui controls transparency
static unsigned int guiIconScale = 1; // Gui icon default scale (if icons enabled)
static unsigned int guiIconFontOffsetY = 0; // Gui icon font atlas offset (if icons backed)
static bool guiTooltip = false; // Tooltip enabled/disabled
static const char *guiTooltipPtr = NULL; // Tooltip string pointer (string provided by user)
@ -1545,11 +1570,14 @@ static int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(
static void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list
static unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle()
static Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
//-------------------------------------------------------------------------------
// raylib functions already implemented in raygui
//-------------------------------------------------------------------------------
static Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
static Color Fade(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
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 const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
@ -1567,6 +1595,7 @@ static void DrawRectangleGradientV(int posX, int posY, int width, int height, Co
//----------------------------------------------------------------------------------
// Module Internal Functions Declaration
//----------------------------------------------------------------------------------
static int GetLineWidth(const char *text); // Get text line width (stops at '\n' or '\0')
static Rectangle GetTextBounds(int control, Rectangle bounds); // Get text bounds considering control bounds
static const char *GetTextIcon(const char *text, int *iconId); // Get text icon if provided and move text cursor
@ -1577,8 +1606,9 @@ static char **GuiTextSplit(const char *text, char delimiter, int *count); // Spl
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 int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue); // Scroll bar control, used by GuiScrollPanel()
static void GuiTooltip(Rectangle controlRec); // Draw tooltip using control rec position
static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue); // Scroll bar control, used by GuiScrollPanel()
static int GuiFontIconBaking(Image *imFont, Font font, Rectangle *whiteRec); // Update font image atlas to append raygui icons
static Color GuiFade(Color color, float alpha); // Fade color by an alpha factor
@ -1851,7 +1881,7 @@ int GuiTabBar(Rectangle bounds, char **text, int count, int *active)
}
// Close tab with middle mouse button pressed
if (CheckCollisionPointRec(GUI_POINTER_POSITION, tabBounds) && IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) result = i;
if (CheckCollisionPointRec(GUI_POINTER_POSITION, tabBounds) && GUI_BUTTON_PRESSED_MID) result = i;
GuiSetStyle(TOGGLE, TEXT_PADDING, textPadding);
GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment);
@ -1877,7 +1907,7 @@ int GuiTabBar(Rectangle bounds, char **text, int count, int *active)
}
// Draw tab-bar bottom line
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, 1 }, 0, BLANK, GetColor(GuiGetStyle(TOGGLE, BORDER_COLOR_NORMAL)));
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, 1 }, 0, BLANK, GetColor(GuiGetStyle(TABBAR, BORDER_COLOR_NORMAL)));
//--------------------------------------------------------------------
return result; // Return as result the current TAB closing requested
@ -2614,7 +2644,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
int result = 0;
GuiState state = guiState;
bool multiline = false; // TODO: Consider multiline text input
bool multiline = false;
int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE);
Rectangle textBounds = GetTextBounds(TEXTBOX, bounds);
@ -4663,10 +4693,8 @@ void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize)
else GuiSetStyle((int)controlId, (int)propertyId, propertyValue);
}
// Font loading is highly dependant on raylib API to load font data and image
#if !defined(RAYGUI_STANDALONE)
// Load custom font if available
// NOTE: Font texture loading requires raylib
int fontDataSize = 0;
memcpy(&fontDataSize, fileDataPtr, sizeof(int));
fileDataPtr += 4;
@ -4732,16 +4760,7 @@ void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize)
fileDataPtr += fontImageUncompSize;
}
// Load texture from image
if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
font.texture = LoadTextureFromImage(imFont);
RAYGUI_FREE(imFont.data);
// Validate font atlas texture was loaded correctly
if (font.texture.id != 0)
{
// Load font recs data
// Load font recs data (glyphs position and size in the image atlas)
int recsDataSize = font.glyphCount*sizeof(Rectangle);
int recsDataCompressedSize = 0;
@ -4835,11 +4854,22 @@ void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize)
fileDataPtr += 16;
}
}
}
else font = GetFontDefault(); // Fallback in case of errors loading font atlas texture
GuiSetFont(font);
#if defined(RAYGUI_FONT_ICONS_BAKING)
// Font atlas image icons baking
Rectangle updatedWhiteRec = { 0 };
guiIconFontOffsetY = GuiFontIconBaking(&imFont, font, &updatedWhiteRec);
if (guiIconFontOffsetY > 0) fontWhiteRec = updatedWhiteRec;
#endif
#if !defined(RAYGUI_STANDALONE)
// Load texture from image
if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
font.texture = LoadTextureFromImage(imFont);
// Fallback to default raylib texture if font texture loading fails
if (font.texture.id != 0)
{
// Set font texture source rectangle to be used as white texture to draw shapes
// NOTE: It makes possible to draw shapes and text (full UI) in a single draw call
if ((fontWhiteRec.x > 0) &&
@ -4847,7 +4877,12 @@ void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize)
(fontWhiteRec.width > 0) &&
(fontWhiteRec.height > 0)) SetShapesTexture(font.texture, fontWhiteRec);
}
else font = GetFontDefault();
GuiSetFont(font);
#endif
RAYGUI_FREE(imFont.data);
}
}
}
@ -4952,6 +4987,9 @@ void GuiLoadStyleDefault(void)
// NOTE: Setting up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
SetShapesTexture(guiFont.texture, RAYGUI_CLITERAL(Rectangle){ whiteChar.x + 1, whiteChar.y + 1, whiteChar.width - 2, whiteChar.height - 2 });
// Reset baked icons offset in font
guiIconFontOffsetY = 0;
}
}
@ -5102,6 +5140,21 @@ char **GuiLoadIconsFromMemory(const unsigned char *fileData, int dataSize, bool
// Draw selected icon using rectangles pixel-by-pixel
void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color)
{
if ((guiIconFontOffsetY > 0) && (iconId < RAYGUI_ICON_MAX_FONT_BACKED))
{
int maxIconsPerLine = guiFont.texture.width/(RAYGUI_ICON_SIZE + 2*RAYGUI_ICON_FONT_ATLAS_PADDING);
int x = iconId%maxIconsPerLine;
int y = iconId/maxIconsPerLine;
Rectangle srcRec = { x*(RAYGUI_ICON_SIZE + 2*RAYGUI_ICON_FONT_ATLAS_PADDING) + RAYGUI_ICON_FONT_ATLAS_PADDING,
guiIconFontOffsetY + y*(RAYGUI_ICON_SIZE + 2*RAYGUI_ICON_FONT_ATLAS_PADDING) + RAYGUI_ICON_FONT_ATLAS_PADDING,
RAYGUI_ICON_SIZE, RAYGUI_ICON_SIZE };
Rectangle dstRec = { posX, posY, RAYGUI_ICON_SIZE*pixelSize, RAYGUI_ICON_SIZE*pixelSize };
DrawTexturePro(guiFont.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, color);
}
else
{
#define BIT_CHECK(a,b) ((a) & (1u<<(b)))
for (int i = 0, y = 0; i < RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32; i++)
@ -5110,14 +5163,14 @@ void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color)
{
if (BIT_CHECK(guiIconsPtr[iconId*RAYGUI_ICON_DATA_ELEMENTS + i], k))
{
#if !defined(RAYGUI_STANDALONE)
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ (float)posX + (k%RAYGUI_ICON_SIZE)*pixelSize, (float)posY + y*pixelSize, (float)pixelSize, (float)pixelSize }, 0, BLANK, color);
#endif
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ (float)posX + (k%RAYGUI_ICON_SIZE)*pixelSize,
(float)posY + y*pixelSize, (float)pixelSize, (float)pixelSize }, 0, BLANK, color);
}
if ((k == 15) || (k == 31)) y++;
}
}
}
}
// Set icon drawing size
@ -5126,15 +5179,44 @@ void GuiSetIconScale(int scale)
if (scale >= 1) guiIconScale = scale;
}
// Get the width of a single line of gui text (stops at '\n' or '\0'),
// considering the gui font/style and an optional icon marker '#NNN#' at
// the start. Icon detection matches GetTextIcon(): 1..3 digits, skip past
// the closing '#'.
// Get text width considering gui style and icon size (if required).
// For multi-line text (containing '\n'), returns the width of the widest line.
int GuiGetTextWidth(const char *text)
{
if (text == NULL) return 0;
int maxWidth = 0;
const char *linePtr = text;
while ((linePtr[0] != '\0') && ((linePtr - text) < MAX_LINE_BUFFER_SIZE))
{
int lineWidth = GetLineWidth(linePtr);
if (lineWidth > maxWidth) maxWidth = lineWidth;
// Skip to the next '\n' (or end of string/buffer)
while ((linePtr[0] != '\0') && (linePtr[0] != '\n') && ((linePtr - text) < MAX_LINE_BUFFER_SIZE))
{
linePtr++;
}
// Advance past the '\n' delimiter to the start of the next line
if (linePtr[0] == '\n') linePtr++;
}
return maxWidth;
}
#endif // !RAYGUI_NO_ICONS
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
// Get text line width (stops at '\n' or '\0')
// NOTE: Considers icon marker '#NNN#'
static int GetLineWidth(const char *text)
{
#if !defined(RAYGUI_ICON_TEXT_PADDING)
#if !defined(RAYGUI_ICON_TEXT_PADDING)
#define RAYGUI_ICON_TEXT_PADDING 4
#endif
#endif
Vector2 textSize = { 0 };
int textIconOffset = 0;
@ -5187,37 +5269,6 @@ static int GetLineWidth(const char *text)
return (int)textSize.x;
}
// Get text width considering gui style and icon size (if required).
// For multi-line text (containing '\n'), returns the width of the widest line.
int GuiGetTextWidth(const char *text)
{
if (text == NULL) return 0;
int maxWidth = 0;
const char *linePtr = text;
while ((linePtr[0] != '\0') && ((linePtr - text) < MAX_LINE_BUFFER_SIZE))
{
int lineWidth = GetLineWidth(linePtr);
if (lineWidth > maxWidth) maxWidth = lineWidth;
// Skip to the next '\n' (or end of string/buffer)
while ((linePtr[0] != '\0') && (linePtr[0] != '\n') && ((linePtr - text) < MAX_LINE_BUFFER_SIZE))
{
linePtr++;
}
// Advance past the '\n' delimiter to the start of the next line
if (linePtr[0] == '\n') linePtr++;
}
return maxWidth;
}
#endif // !RAYGUI_NO_ICONS
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
// Get text bounds considering control bounds
static Rectangle GetTextBounds(int control, Rectangle bounds)
{
@ -5590,7 +5641,8 @@ static void GuiTooltip(Rectangle controlRec)
{
if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiControlExclusiveMode)
{
Vector2 textSize = MeasureTextEx(GuiGetFont(), guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
Vector2 textSize = MeasureTextEx(guiFont, guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE),
(float)GuiGetStyle(DEFAULT, TEXT_SPACING));
if ((controlRec.x + textSize.x + 16) > GetScreenWidth()) controlRec.x -= (textSize.x + 16 - controlRec.width);
@ -5612,174 +5664,6 @@ static void GuiTooltip(Rectangle controlRec)
}
}
// Split controls text into multiple strings
// NOTE: Re-used by GuiToggleSlider(), GuiComboBox(), GuiDropdownBox(), GuiListView(), GuiMessageBox(), GuiInputBox()
static char **GuiTextSplit(const char *text, char delimiter, int *count)
{
// 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,
// all used memory is static... it has some limitations:
// 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS
// 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE
// NOTE: Those definitions could be externally provided if required
#if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS)
#define RAYGUI_TEXTSPLIT_MAX_ITEMS 128
#endif
#if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE)
#define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 // WARNING: Max expected size for all concat items
#endif
static char *itemPtrs[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { 0 }; // String pointers array (points to buffer data)
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);
itemPtrs[0] = buffer;
int itemCounter = 1;
// Count how many substrings text contains and point to every one of them
for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++)
{
buffer[i] = text[i];
if (buffer[i] == '\0') break;
else if ((buffer[i] == delimiter) || (buffer[i] == '\n'))
{
itemPtrs[itemCounter] = buffer + i + 1;
buffer[i] = '\0'; // Set terminator for current item
itemCounter++;
if (itemCounter >= RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
}
}
*count = itemCounter;
return itemPtrs;
}
// Convert color data from RGB to HSV
// NOTE: Color data should be passed normalized
static Vector3 ConvertRGBtoHSV(Vector3 rgb)
{
Vector3 hsv = { 0 };
float min = 0.0f;
float max = 0.0f;
float delta = 0.0f;
min = (rgb.x < rgb.y)? rgb.x : rgb.y;
min = (min < rgb.z)? min : rgb.z;
max = (rgb.x > rgb.y)? rgb.x : rgb.y;
max = (max > rgb.z)? max : rgb.z;
hsv.z = max; // Value
delta = max - min;
if (delta < 0.00001f)
{
hsv.y = 0.0f;
hsv.x = 0.0f; // Undefined, maybe NAN?
return hsv;
}
if (max > 0.0f)
{
// NOTE: If max is 0, this divide would cause a crash
hsv.y = (delta/max); // Saturation
}
else
{
// NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
hsv.y = 0.0f;
hsv.x = 0.0f; // Undefined, maybe NAN?
return hsv;
}
// NOTE: Comparing float values could not work properly
if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta
else
{
if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow
else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan
}
hsv.x *= 60.0f; // Convert to degrees
if (hsv.x < 0.0f) hsv.x += 360.0f;
return hsv;
}
// Convert color data from HSV to RGB
// NOTE: Color data should be passed normalized
static Vector3 ConvertHSVtoRGB(Vector3 hsv)
{
Vector3 rgb = { 0 };
float hh = 0.0f, p = 0.0f, q = 0.0f, t = 0.0f, ff = 0.0f;
long i = 0;
// NOTE: Comparing float values could not work properly
if (hsv.y <= 0.0f)
{
rgb.x = hsv.z;
rgb.y = hsv.z;
rgb.z = hsv.z;
return rgb;
}
hh = hsv.x;
if (hh >= 360.0f) hh = 0.0f;
hh /= 60.0f;
i = (long)hh;
ff = hh - i;
p = hsv.z*(1.0f - hsv.y);
q = hsv.z*(1.0f - (hsv.y*ff));
t = hsv.z*(1.0f - (hsv.y*(1.0f - ff)));
switch (i)
{
case 0:
{
rgb.x = hsv.z;
rgb.y = t;
rgb.z = p;
} break;
case 1:
{
rgb.x = q;
rgb.y = hsv.z;
rgb.z = p;
} break;
case 2:
{
rgb.x = p;
rgb.y = hsv.z;
rgb.z = t;
} break;
case 3:
{
rgb.x = p;
rgb.y = q;
rgb.z = hsv.z;
} break;
case 4:
{
rgb.x = t;
rgb.y = p;
rgb.z = hsv.z;
} break;
case 5:
default:
{
rgb.x = hsv.z;
rgb.y = p;
rgb.z = q;
} break;
}
return rgb;
}
// Scroll bar control (used by GuiScrollPanel())
static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
{
@ -5951,8 +5835,261 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
return value;
}
// Update font image atlas to append raygui icons
static int GuiFontIconBaking(Image *imFont, Font font, Rectangle *whiteRec)
{
int iconOffsetY = 0;
// Check max glyph rec y bottom position in the atlas image,
// to start drawing icons below that line
int maxGlyphRecY = 0;
for (int i = 0; i < font.glyphCount; i++)
{
if ((font.recs[i].y + font.recs[i].height) > maxGlyphRecY)
maxGlyphRecY = font.recs[i].y + font.recs[i].height;
}
int maxIconsPerLine = imFont->width/(RAYGUI_ICON_SIZE + 2*RAYGUI_ICON_FONT_ATLAS_PADDING);
int reqIconLines = RAYGUI_ICON_MAX_FONT_BACKED/maxIconsPerLine + RAYGUI_ICON_MAX_FONT_BACKED%maxIconsPerLine + 1; // One extra line
int reqHeight = reqIconLines*(RAYGUI_ICON_SIZE + 2*RAYGUI_ICON_FONT_ATLAS_PADDING);
// Check if image requires scaling and how much
if ((maxGlyphRecY + reqHeight) > imFont->height)
{
int newImHeight = 1;
while (newImHeight < (maxGlyphRecY + reqHeight)) newImHeight <<= 1; // Round to next POT
char *newImData = (char *)RL_CALLOC(imFont->width*newImHeight*2, sizeof(char));
memcpy(newImData, imFont->data, imFont->width*imFont->height*2);
RL_FREE(imFont->data);
// Clear imFont bottom-right corner rec
for (int y = 0; y < 4; y++)
for (int x = 0; x < 4; x++)
((unsigned short *)newImData)[(imFont->height - y - 1)*imFont->width + imFont->width - x - 1] = 0x0000;
imFont->data = newImData;
imFont->height = newImHeight;
// Set new image white corner and new white rec
for (int y = 0; y < 3; y++)
for (int x = 0; x < 3; x++)
((unsigned short *)newImData)[(imFont->height - y - 1)*imFont->width + imFont->width - x - 1] = 0xffff;
*whiteRec = (Rectangle){ imFont->width - 2, imFont->height - 2, 1, 1 };
}
// Calculate image offset positions to start drawing
// NOTE: For Y, look for a multiple of icon size + 2*padding, for better alignment
int offsetX = RAYGUI_ICON_FONT_ATLAS_PADDING;
int offsetY = ((maxGlyphRecY + (RAYGUI_ICON_SIZE + 2*RAYGUI_ICON_FONT_ATLAS_PADDING - 1))/
(RAYGUI_ICON_SIZE + 2*RAYGUI_ICON_FONT_ATLAS_PADDING))*(RAYGUI_ICON_SIZE + 2*RAYGUI_ICON_FONT_ATLAS_PADDING) +
RAYGUI_ICON_FONT_ATLAS_PADDING;
iconOffsetY = offsetY - RAYGUI_ICON_FONT_ATLAS_PADDING;
unsigned short *pixels = (unsigned short *)imFont->data;
#define BIT_CHECK(a,b) ((a) & (1u<<(b)))
for (int iconId = 0; iconId < RAYGUI_ICON_MAX_FONT_BACKED; iconId++)
{
// Wrap to next line if next icon won't fit
if ((offsetX + (RAYGUI_ICON_SIZE + 2*RAYGUI_ICON_FONT_ATLAS_PADDING)) > imFont->width)
{
offsetX = RAYGUI_ICON_FONT_ATLAS_PADDING;
offsetY += RAYGUI_ICON_SIZE + 2*RAYGUI_ICON_FONT_ATLAS_PADDING;
}
for (int i = 0, y = 0; i < RAYGUI_ICON_DATA_ELEMENTS; i++)
{
unsigned int data = guiIconsPtr[iconId*RAYGUI_ICON_DATA_ELEMENTS + i];
for (int k = 0; k < 32; k++)
{
pixels[(offsetY + y)*imFont->width + offsetX + k%16] = (BIT_CHECK(data, k))? 0xffff : 0x00ff;
if ((k == 15) || (k == 31)) y++;
}
}
// Update current icon X position
offsetX += (RAYGUI_ICON_SIZE + 2*RAYGUI_ICON_FONT_ATLAS_PADDING);
}
return iconOffsetY;
}
// Split controls text into multiple strings
// NOTE: Re-used by GuiToggleSlider(), GuiComboBox(), GuiDropdownBox(), GuiListView(), GuiMessageBox(), GuiInputBox()
static char **GuiTextSplit(const char *text, char delimiter, int *count)
{
// 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,
// all used memory is static... it has some limitations:
// 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS
// 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE
// NOTE: Those definitions could be externally provided if required
#if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS)
#define RAYGUI_TEXTSPLIT_MAX_ITEMS 128
#endif
#if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE)
#define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 // WARNING: Max expected size for all concat items
#endif
static char *itemPtrs[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { 0 }; // String pointers array (points to buffer data)
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);
itemPtrs[0] = buffer;
int itemCounter = 1;
// Count how many substrings text contains and point to every one of them
for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++)
{
buffer[i] = text[i];
if (buffer[i] == '\0') break;
else if ((buffer[i] == delimiter) || (buffer[i] == '\n'))
{
itemPtrs[itemCounter] = buffer + i + 1;
buffer[i] = '\0'; // Set terminator for current item
itemCounter++;
if (itemCounter >= RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
}
}
*count = itemCounter;
return itemPtrs;
}
// Convert color data from RGB to HSV
// NOTE: Color data should be passed normalized
static Vector3 ConvertRGBtoHSV(Vector3 rgb)
{
Vector3 hsv = { 0 };
float min = 0.0f;
float max = 0.0f;
float delta = 0.0f;
min = (rgb.x < rgb.y)? rgb.x : rgb.y;
min = (min < rgb.z)? min : rgb.z;
max = (rgb.x > rgb.y)? rgb.x : rgb.y;
max = (max > rgb.z)? max : rgb.z;
hsv.z = max; // Value
delta = max - min;
if (delta < 0.00001f)
{
hsv.y = 0.0f;
hsv.x = 0.0f; // Undefined, maybe NAN?
return hsv;
}
if (max > 0.0f)
{
// NOTE: If max is 0, this divide would cause a crash
hsv.y = (delta/max); // Saturation
}
else
{
// NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
hsv.y = 0.0f;
hsv.x = 0.0f; // Undefined, maybe NAN?
return hsv;
}
// NOTE: Comparing float values could not work properly
if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta
else
{
if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow
else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan
}
hsv.x *= 60.0f; // Convert to degrees
if (hsv.x < 0.0f) hsv.x += 360.0f;
return hsv;
}
// Convert color data from HSV to RGB
// NOTE: Color data should be passed normalized
static Vector3 ConvertHSVtoRGB(Vector3 hsv)
{
Vector3 rgb = { 0 };
float hh = 0.0f, p = 0.0f, q = 0.0f, t = 0.0f, ff = 0.0f;
long i = 0;
// NOTE: Comparing float values could not work properly
if (hsv.y <= 0.0f)
{
rgb.x = hsv.z;
rgb.y = hsv.z;
rgb.z = hsv.z;
return rgb;
}
hh = hsv.x;
if (hh >= 360.0f) hh = 0.0f;
hh /= 60.0f;
i = (long)hh;
ff = hh - i;
p = hsv.z*(1.0f - hsv.y);
q = hsv.z*(1.0f - (hsv.y*ff));
t = hsv.z*(1.0f - (hsv.y*(1.0f - ff)));
switch (i)
{
case 0:
{
rgb.x = hsv.z;
rgb.y = t;
rgb.z = p;
} break;
case 1:
{
rgb.x = q;
rgb.y = hsv.z;
rgb.z = p;
} break;
case 2:
{
rgb.x = p;
rgb.y = hsv.z;
rgb.z = t;
} break;
case 3:
{
rgb.x = p;
rgb.y = q;
rgb.z = hsv.z;
} break;
case 4:
{
rgb.x = t;
rgb.y = p;
rgb.z = hsv.z;
} break;
case 5:
default:
{
rgb.x = hsv.z;
rgb.y = p;
rgb.z = q;
} break;
}
return rgb;
}
// Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
// WARNING: It multiplies current alpha by alpha scale factor
// WARNING: It multiplies current alpha by alpha scale factor,
// raylib Fade() multiplies alpha by 255.0f
static Color GuiFade(Color color, float alpha)
{
if (alpha < 0.0f) alpha = 0.0f;
@ -5977,6 +6114,19 @@ static Color GetColor(int hexValue)
return color;
}
// Get color with alpha applied, alpha goes from 0.0f to 1.0f
static Color Fade(Color color, float alpha)
{
Color result = color;
if (alpha < 0.0f) alpha = 0.0f;
else if (alpha > 1.0f) alpha = 1.0f;
result.a = (unsigned char)(255.0f*alpha);
return result;
}
// Returns hexadecimal value for a Color
static int ColorToInt(Color color)
{