Update to Zig 0.14.0 and raylib 5.6-dev
This commit is contained in:
parent
ae7cb3fa93
commit
1b6a05ca3b
15 changed files with 586 additions and 321 deletions
467
lib/raygui.h
vendored
467
lib/raygui.h
vendored
|
|
@ -141,12 +141,16 @@
|
|||
* Draw text bounds rectangles for debug
|
||||
*
|
||||
* VERSIONS HISTORY:
|
||||
* 4.5-dev (Sep-2024) Current dev version...
|
||||
* 5.0-dev (2025) Current dev version...
|
||||
* ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes
|
||||
* ADDED: GuiValueBoxFloat()
|
||||
* ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP
|
||||
* ADDED: GuiListView() property: LIST_ITEMS_BORDER_WIDTH
|
||||
* ADDED: GuiLoadIconsFromMemory()
|
||||
* ADDED: Multiple new icons
|
||||
* REMOVED: GuiSpinner() from controls list, using BUTTON + VALUEBOX properties
|
||||
* REVIEWED: Controls using text labels to use LABEL properties
|
||||
* REVIEWED: Replaced sprintf() by snprintf() for more safety
|
||||
* REVIEWED: GuiTabBar(), close tab with mouse middle button
|
||||
* REVIEWED: GuiScrollPanel(), scroll speed proportional to content
|
||||
* REVIEWED: GuiDropdownBox(), support roll up and hidden arrow
|
||||
|
|
@ -309,7 +313,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
|
|
@ -334,7 +338,7 @@
|
|||
#define RAYGUI_VERSION_MAJOR 4
|
||||
#define RAYGUI_VERSION_MINOR 5
|
||||
#define RAYGUI_VERSION_PATCH 0
|
||||
#define RAYGUI_VERSION "4.5-dev"
|
||||
#define RAYGUI_VERSION "5.0-dev"
|
||||
|
||||
#if !defined(RAYGUI_STANDALONE)
|
||||
#include "raylib.h"
|
||||
|
|
@ -527,7 +531,7 @@ typedef enum {
|
|||
DROPDOWNBOX,
|
||||
TEXTBOX, // Used also for: TEXTBOXMULTI
|
||||
VALUEBOX,
|
||||
SPINNER, // Uses: BUTTON, VALUEBOX
|
||||
CONTROL11,
|
||||
LISTVIEW,
|
||||
COLORPICKER,
|
||||
SCROLLBAR,
|
||||
|
|
@ -549,12 +553,12 @@ typedef enum {
|
|||
BORDER_COLOR_DISABLED, // Control border color in STATE_DISABLED
|
||||
BASE_COLOR_DISABLED, // Control base color in STATE_DISABLED
|
||||
TEXT_COLOR_DISABLED, // Control text color in STATE_DISABLED
|
||||
BORDER_WIDTH, // Control border size, 0 for no border
|
||||
BORDER_WIDTH = 12, // Control border size, 0 for no border
|
||||
//TEXT_SIZE, // Control text size (glyphs max height) -> GLOBAL for all controls
|
||||
//TEXT_SPACING, // Control text spacing between glyphs -> GLOBAL for all controls
|
||||
//TEXT_LINE_SPACING // Control text spacing between lines -> GLOBAL for all controls
|
||||
TEXT_PADDING, // Control text padding, not considering border
|
||||
TEXT_ALIGNMENT, // Control text horizontal alignment inside control text bound (after border and padding)
|
||||
//TEXT_LINE_SPACING, // Control text spacing between lines -> GLOBAL for all controls
|
||||
TEXT_PADDING = 13, // Control text padding, not considering border
|
||||
TEXT_ALIGNMENT = 14, // Control text horizontal alignment inside control text bound (after border and padding)
|
||||
//TEXT_WRAP_MODE // Control text wrap-mode inside text bounds -> GLOBAL for all controls
|
||||
} GuiControlProperty;
|
||||
|
||||
|
|
@ -641,11 +645,14 @@ typedef enum {
|
|||
TEXT_READONLY = 16, // TextBox in read-only mode: 0-text editable, 1-text no-editable
|
||||
} GuiTextBoxProperty;
|
||||
|
||||
// Spinner
|
||||
// ValueBox/Spinner
|
||||
typedef enum {
|
||||
SPIN_BUTTON_WIDTH = 16, // Spinner left/right buttons width
|
||||
SPIN_BUTTON_SPACING, // Spinner buttons separation
|
||||
} GuiSpinnerProperty;
|
||||
SPINNER_BUTTON_WIDTH = 16, // Spinner left/right buttons width
|
||||
SPINNER_BUTTON_SPACING, // Spinner buttons separation
|
||||
} GuiValueBoxProperty;
|
||||
|
||||
// Control11
|
||||
//typedef enum { } GuiControl11Property;
|
||||
|
||||
// ListView
|
||||
typedef enum {
|
||||
|
|
@ -653,6 +660,7 @@ typedef enum {
|
|||
LIST_ITEMS_SPACING, // ListView items separation
|
||||
SCROLLBAR_WIDTH, // ListView scrollbar size (usually width)
|
||||
SCROLLBAR_SIDE, // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE)
|
||||
LIST_ITEMS_BORDER_NORMAL, // ListView items border enabled in normal state
|
||||
LIST_ITEMS_BORDER_WIDTH // ListView items border width
|
||||
} GuiListViewProperty;
|
||||
|
||||
|
|
@ -1046,7 +1054,7 @@ typedef enum {
|
|||
#if defined(RAYGUI_IMPLEMENTATION)
|
||||
|
||||
#include <ctype.h> // required for: isspace() [GuiTextBox()]
|
||||
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()]
|
||||
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), snprintf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()]
|
||||
#include <stdlib.h> // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()]
|
||||
#include <string.h> // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy()
|
||||
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() [TextFormat()]
|
||||
|
|
@ -1387,8 +1395,7 @@ static Rectangle guiControlExclusiveRec = { 0 }; // Gui control exclusive bounds
|
|||
|
||||
static int textBoxCursorIndex = 0; // Cursor index, shared by all GuiTextBox*()
|
||||
//static int blinkCursorFrameCounter = 0; // Frame counter for cursor blinking
|
||||
static int autoCursorCooldownCounter = 0; // Cooldown frame counter for automatic cursor movement on key-down
|
||||
static int autoCursorDelayCounter = 0; // Delay frame counter for automatic cursor movement
|
||||
static int autoCursorCounter = 0; // Frame counter for automatic repeated cursor movement on key-down (cooldown and delay)
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Style data array for all gui style properties (allocated on data segment by default)
|
||||
|
|
@ -1589,6 +1596,10 @@ int GuiWindowBox(Rectangle bounds, const char *title)
|
|||
#define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24
|
||||
#endif
|
||||
|
||||
#if !defined(RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT)
|
||||
#define RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT 18
|
||||
#endif
|
||||
|
||||
int result = 0;
|
||||
//GuiState state = guiState;
|
||||
|
||||
|
|
@ -1597,9 +1608,10 @@ int GuiWindowBox(Rectangle bounds, const char *title)
|
|||
Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)statusBarHeight };
|
||||
if (bounds.height < statusBarHeight*2.0f) bounds.height = statusBarHeight*2.0f;
|
||||
|
||||
const float vPadding = statusBarHeight/2.0f - RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT/2.0f;
|
||||
Rectangle windowPanel = { bounds.x, bounds.y + (float)statusBarHeight - 1, bounds.width, bounds.height - (float)statusBarHeight + 1 };
|
||||
Rectangle closeButtonRec = { statusBar.x + statusBar.width - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - 20,
|
||||
statusBar.y + statusBarHeight/2.0f - 18.0f/2.0f, 18, 18 };
|
||||
Rectangle closeButtonRec = { statusBar.x + statusBar.width - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT - vPadding,
|
||||
statusBar.y + vPadding, RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT, RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT };
|
||||
|
||||
// Update control
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -1653,7 +1665,7 @@ int GuiGroupBox(Rectangle bounds, const char *text)
|
|||
// Line control
|
||||
int GuiLine(Rectangle bounds, const char *text)
|
||||
{
|
||||
#if !defined(RAYGUI_LINE_ORIGIN_SIZE)
|
||||
#if !defined(RAYGUI_LINE_MARGIN_TEXT)
|
||||
#define RAYGUI_LINE_MARGIN_TEXT 12
|
||||
#endif
|
||||
#if !defined(RAYGUI_LINE_TEXT_PADDING)
|
||||
|
|
@ -2149,7 +2161,9 @@ int GuiToggleSlider(Rectangle bounds, const char *text, int *active)
|
|||
|
||||
// Get substrings items from text (items pointers)
|
||||
int itemCount = 0;
|
||||
const char **items = GuiTextSplit(text, ';', &itemCount, NULL);
|
||||
const char **items = NULL;
|
||||
|
||||
if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
|
||||
|
||||
Rectangle slider = {
|
||||
0, // Calculated later depending on the active toggle
|
||||
|
|
@ -2474,10 +2488,10 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
|
|||
int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||
{
|
||||
#if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)
|
||||
#define RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN 40 // Frames to wait for autocursor movement
|
||||
#define RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN 30 // Frames to wait for autocursor movement
|
||||
#endif
|
||||
#if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY)
|
||||
#define RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY 1 // Frames delay for autocursor movement
|
||||
#define RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY 2 // Frames delay for autocursor movement
|
||||
#endif
|
||||
|
||||
int result = 0;
|
||||
|
|
@ -2511,15 +2525,6 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
|||
mouseCursor.x = -1;
|
||||
mouseCursor.width = 1;
|
||||
|
||||
// Auto-cursor movement logic
|
||||
// NOTE: Cursor moves automatically when key down after some time
|
||||
if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_UP) || IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_BACKSPACE) || IsKeyDown(KEY_DELETE)) autoCursorCooldownCounter++;
|
||||
else
|
||||
{
|
||||
autoCursorCooldownCounter = 0; // GLOBAL: Cursor cooldown counter
|
||||
autoCursorDelayCounter = 0; // GLOBAL: Cursor delay counter
|
||||
}
|
||||
|
||||
// Blink-cursor frame counter
|
||||
//if (!autoCursorMode) blinkCursorFrameCounter++;
|
||||
//else blinkCursorFrameCounter = 0;
|
||||
|
|
@ -2537,6 +2542,15 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
|||
|
||||
if (editMode)
|
||||
{
|
||||
// GLOBAL: Auto-cursor movement logic
|
||||
// NOTE: Keystrokes are handled repeatedly when button is held down for some time
|
||||
if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_UP) || IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_BACKSPACE) || IsKeyDown(KEY_DELETE)) autoCursorCounter++;
|
||||
else
|
||||
{
|
||||
autoCursorCounter = 0;
|
||||
}
|
||||
bool autoCursorShouldTrigger = (autoCursorCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN) && ((autoCursorCounter % RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0);
|
||||
|
||||
state = STATE_PRESSED;
|
||||
|
||||
if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;
|
||||
|
|
@ -2560,9 +2574,40 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
|||
int codepointSize = 0;
|
||||
const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize);
|
||||
|
||||
// Handle Paste action
|
||||
if (IsKeyPressed(KEY_V) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
|
||||
{
|
||||
const char *pasteText = GetClipboardText();
|
||||
if (pasteText != NULL)
|
||||
{
|
||||
int pasteLength = 0;
|
||||
int pasteCodepoint;
|
||||
int pasteCodepointSize;
|
||||
// count how many codepoints to copy, stopping at the first unwanted control character
|
||||
while (true)
|
||||
{
|
||||
pasteCodepoint = GetCodepointNext(pasteText + pasteLength, &pasteCodepointSize);
|
||||
if (textLength + pasteLength + pasteCodepointSize >= textSize) break;
|
||||
if (!(multiline && (pasteCodepoint == (int)'\n')) && !(pasteCodepoint >= 32)) break;
|
||||
pasteLength += pasteCodepointSize;
|
||||
}
|
||||
if (pasteLength > 0)
|
||||
{
|
||||
// Move forward data from cursor position
|
||||
for (int i = textLength + pasteLength; i > textBoxCursorIndex; i--) text[i] = text[i - pasteLength];
|
||||
|
||||
// Paste data in at cursor
|
||||
for (int i = 0; i < pasteLength; i++) text[textBoxCursorIndex + i] = pasteText[i];
|
||||
|
||||
textBoxCursorIndex += pasteLength;
|
||||
textLength += pasteLength;
|
||||
text[textLength] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add codepoint to text, at current cursor position
|
||||
// NOTE: Make sure we do not overflow buffer size
|
||||
if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < textSize))
|
||||
else if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < textSize))
|
||||
{
|
||||
// Move forward data from cursor position
|
||||
for (int i = (textLength + codepointSize); i > textBoxCursorIndex; i--) text[i] = text[i - codepointSize];
|
||||
|
|
@ -2583,113 +2628,175 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
|||
// Move cursor to end
|
||||
if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_END)) textBoxCursorIndex = textLength;
|
||||
|
||||
// Delete codepoint from text, after current cursor position
|
||||
if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))))
|
||||
// Delete related codepoints from text, after current cursor position
|
||||
if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_DELETE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
|
||||
{
|
||||
autoCursorDelayCounter++;
|
||||
|
||||
if (IsKeyPressed(KEY_DELETE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames
|
||||
int offset = textBoxCursorIndex;
|
||||
int accCodepointSize = 0;
|
||||
int nextCodepointSize;
|
||||
int nextCodepoint;
|
||||
// Check characters of the same type to delete (either ASCII punctuation or anything non-whitespace)
|
||||
// Not using isalnum() since it only works on ASCII characters
|
||||
nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
|
||||
bool puctuation = ispunct(nextCodepoint & 0xFF);
|
||||
while (offset < textLength)
|
||||
{
|
||||
int nextCodepointSize = 0;
|
||||
GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize);
|
||||
|
||||
// Move backward text from cursor position
|
||||
for (int i = textBoxCursorIndex; i < textLength; i++) text[i] = text[i + nextCodepointSize];
|
||||
|
||||
textLength -= codepointSize;
|
||||
if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;
|
||||
|
||||
// Make sure text last character is EOL
|
||||
text[textLength] = '\0';
|
||||
if ((puctuation && !ispunct(nextCodepoint & 0xFF)) || (!puctuation && (isspace(nextCodepoint & 0xFF) || ispunct(nextCodepoint & 0xFF))))
|
||||
break;
|
||||
offset += nextCodepointSize;
|
||||
accCodepointSize += nextCodepointSize;
|
||||
nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
|
||||
}
|
||||
// Check whitespace to delete (ASCII only)
|
||||
while (offset < textLength)
|
||||
{
|
||||
if (!isspace(nextCodepoint & 0xFF))
|
||||
break;
|
||||
offset += nextCodepointSize;
|
||||
accCodepointSize += nextCodepointSize;
|
||||
nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
|
||||
}
|
||||
|
||||
// Move text after cursor forward (including final null terminator)
|
||||
for (int i = offset; i <= textLength; i++) text[i - accCodepointSize] = text[i];
|
||||
|
||||
textLength -= accCodepointSize;
|
||||
}
|
||||
// Delete single codepoint from text, after current cursor position
|
||||
else if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && autoCursorShouldTrigger)))
|
||||
{
|
||||
int nextCodepointSize = 0;
|
||||
GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize);
|
||||
|
||||
// Move text after cursor forward (including final null terminator)
|
||||
for (int i = textBoxCursorIndex + nextCodepointSize; i <= textLength; i++) text[i - nextCodepointSize] = text[i];
|
||||
|
||||
textLength -= nextCodepointSize;
|
||||
}
|
||||
|
||||
// Delete related codepoints from text, before current cursor position
|
||||
if ((textLength > 0) && IsKeyPressed(KEY_BACKSPACE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
|
||||
if ((textBoxCursorIndex > 0) && IsKeyPressed(KEY_BACKSPACE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
|
||||
{
|
||||
int i = textBoxCursorIndex - 1;
|
||||
int offset = textBoxCursorIndex;
|
||||
int accCodepointSize = 0;
|
||||
int prevCodepointSize;
|
||||
int prevCodepoint;
|
||||
|
||||
// Move cursor to the end of word if on space already
|
||||
while ((i > 0) && isspace(text[i]))
|
||||
// Check whitespace to delete (ASCII only)
|
||||
while (offset > 0)
|
||||
{
|
||||
int prevCodepointSize = 0;
|
||||
GetCodepointPrevious(text + i, &prevCodepointSize);
|
||||
i -= prevCodepointSize;
|
||||
prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize);
|
||||
if (!isspace(prevCodepoint & 0xFF))
|
||||
break;
|
||||
offset -= prevCodepointSize;
|
||||
accCodepointSize += prevCodepointSize;
|
||||
}
|
||||
// Check characters of the same type to delete (either ASCII punctuation or anything non-whitespace)
|
||||
// Not using isalnum() since it only works on ASCII characters
|
||||
bool puctuation = ispunct(prevCodepoint & 0xFF);
|
||||
while (offset > 0)
|
||||
{
|
||||
prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize);
|
||||
if ((puctuation && !ispunct(prevCodepoint & 0xFF)) || (!puctuation && (isspace(prevCodepoint & 0xFF) || ispunct(prevCodepoint & 0xFF))))
|
||||
break;
|
||||
offset -= prevCodepointSize;
|
||||
accCodepointSize += prevCodepointSize;
|
||||
}
|
||||
|
||||
// Move cursor to the start of the word
|
||||
while ((i > 0) && !isspace(text[i]))
|
||||
{
|
||||
int prevCodepointSize = 0;
|
||||
GetCodepointPrevious(text + i, &prevCodepointSize);
|
||||
i -= prevCodepointSize;
|
||||
accCodepointSize += prevCodepointSize;
|
||||
}
|
||||
// Move text after cursor forward (including final null terminator)
|
||||
for (int i = textBoxCursorIndex; i <= textLength; i++) text[i - accCodepointSize] = text[i];
|
||||
|
||||
// Move forward text from cursor position
|
||||
for (int j = (textBoxCursorIndex - accCodepointSize); j < textLength; j++) text[j] = text[j + accCodepointSize];
|
||||
|
||||
// Prevent cursor index from decrementing past 0
|
||||
if (textBoxCursorIndex > 0)
|
||||
{
|
||||
textBoxCursorIndex -= accCodepointSize;
|
||||
textLength -= accCodepointSize;
|
||||
}
|
||||
|
||||
// Make sure text last character is EOL
|
||||
text[textLength] = '\0';
|
||||
}
|
||||
else if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))))
|
||||
textLength -= accCodepointSize;
|
||||
textBoxCursorIndex -= accCodepointSize;
|
||||
}
|
||||
// Delete single codepoint from text, before current cursor position
|
||||
else if ((textBoxCursorIndex > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && autoCursorShouldTrigger)))
|
||||
{
|
||||
autoCursorDelayCounter++;
|
||||
int prevCodepointSize = 0;
|
||||
|
||||
if (IsKeyPressed(KEY_BACKSPACE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames
|
||||
{
|
||||
int prevCodepointSize = 0;
|
||||
GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);
|
||||
|
||||
// Prevent cursor index from decrementing past 0
|
||||
if (textBoxCursorIndex > 0)
|
||||
{
|
||||
GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);
|
||||
// Move text after cursor forward (including final null terminator)
|
||||
for (int i = textBoxCursorIndex; i <= textLength; i++) text[i - prevCodepointSize] = text[i];
|
||||
|
||||
// Move backward text from cursor position
|
||||
for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize];
|
||||
|
||||
textBoxCursorIndex -= codepointSize;
|
||||
textLength -= codepointSize;
|
||||
}
|
||||
|
||||
// Make sure text last character is EOL
|
||||
text[textLength] = '\0';
|
||||
}
|
||||
textLength -= prevCodepointSize;
|
||||
textBoxCursorIndex -= prevCodepointSize;
|
||||
}
|
||||
|
||||
// Move cursor position with keys
|
||||
if (IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && (autoCursorCooldownCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))
|
||||
if ((textBoxCursorIndex > 0) && IsKeyPressed(KEY_LEFT) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
|
||||
{
|
||||
autoCursorDelayCounter++;
|
||||
int offset = textBoxCursorIndex;
|
||||
int accCodepointSize = 0;
|
||||
int prevCodepointSize;
|
||||
int prevCodepoint;
|
||||
|
||||
if (IsKeyPressed(KEY_LEFT) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames
|
||||
// Check whitespace to skip (ASCII only)
|
||||
while (offset > 0)
|
||||
{
|
||||
int prevCodepointSize = 0;
|
||||
if (textBoxCursorIndex > 0) GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);
|
||||
|
||||
if (textBoxCursorIndex >= prevCodepointSize) textBoxCursorIndex -= prevCodepointSize;
|
||||
prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize);
|
||||
if (!isspace(prevCodepoint & 0xFF))
|
||||
break;
|
||||
offset -= prevCodepointSize;
|
||||
accCodepointSize += prevCodepointSize;
|
||||
}
|
||||
// Check characters of the same type to skip (either ASCII punctuation or anything non-whitespace)
|
||||
// Not using isalnum() since it only works on ASCII characters
|
||||
bool puctuation = ispunct(prevCodepoint & 0xFF);
|
||||
while (offset > 0)
|
||||
{
|
||||
prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize);
|
||||
if ((puctuation && !ispunct(prevCodepoint & 0xFF)) || (!puctuation && (isspace(prevCodepoint & 0xFF) || ispunct(prevCodepoint & 0xFF))))
|
||||
break;
|
||||
offset -= prevCodepointSize;
|
||||
accCodepointSize += prevCodepointSize;
|
||||
}
|
||||
|
||||
textBoxCursorIndex = offset;
|
||||
}
|
||||
else if (IsKeyPressed(KEY_RIGHT) || (IsKeyDown(KEY_RIGHT) && (autoCursorCooldownCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))
|
||||
else if ((textBoxCursorIndex > 0) && (IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && autoCursorShouldTrigger)))
|
||||
{
|
||||
autoCursorDelayCounter++;
|
||||
int prevCodepointSize = 0;
|
||||
GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);
|
||||
|
||||
if (IsKeyPressed(KEY_RIGHT) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames
|
||||
textBoxCursorIndex -= prevCodepointSize;
|
||||
}
|
||||
else if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_RIGHT) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
|
||||
{
|
||||
int offset = textBoxCursorIndex;
|
||||
int accCodepointSize = 0;
|
||||
int nextCodepointSize;
|
||||
int nextCodepoint;
|
||||
// Check characters of the same type to skip (either ASCII punctuation or anything non-whitespace)
|
||||
// Not using isalnum() since it only works on ASCII characters
|
||||
nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
|
||||
bool puctuation = ispunct(nextCodepoint & 0xFF);
|
||||
while (offset < textLength)
|
||||
{
|
||||
int nextCodepointSize = 0;
|
||||
GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize);
|
||||
|
||||
if ((textBoxCursorIndex + nextCodepointSize) <= textLength) textBoxCursorIndex += nextCodepointSize;
|
||||
if ((puctuation && !ispunct(nextCodepoint & 0xFF)) || (!puctuation && (isspace(nextCodepoint & 0xFF) || ispunct(nextCodepoint & 0xFF))))
|
||||
break;
|
||||
offset += nextCodepointSize;
|
||||
accCodepointSize += nextCodepointSize;
|
||||
nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
|
||||
}
|
||||
// Check whitespace to skip (ASCII only)
|
||||
while (offset < textLength)
|
||||
{
|
||||
if (!isspace(nextCodepoint & 0xFF))
|
||||
break;
|
||||
offset += nextCodepointSize;
|
||||
accCodepointSize += nextCodepointSize;
|
||||
nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
|
||||
}
|
||||
|
||||
textBoxCursorIndex = offset;
|
||||
}
|
||||
else if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_RIGHT) || (IsKeyDown(KEY_RIGHT) && autoCursorShouldTrigger)))
|
||||
{
|
||||
int nextCodepointSize = 0;
|
||||
GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize);
|
||||
|
||||
textBoxCursorIndex += nextCodepointSize;
|
||||
}
|
||||
|
||||
// Move cursor position with mouse
|
||||
|
|
@ -2701,7 +2808,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
|||
float widthToMouseX = 0;
|
||||
int mouseCursorIndex = 0;
|
||||
|
||||
for (int i = textIndexOffset; i < textLength; i++)
|
||||
for (int i = textIndexOffset; i < textLength; i += codepointSize)
|
||||
{
|
||||
codepoint = GetCodepointNext(&text[i], &codepointSize);
|
||||
codepointIndex = GetGlyphIndex(guiFont, codepoint);
|
||||
|
|
@ -2745,6 +2852,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
|||
(!CheckCollisionPointRec(mousePosition, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
|
||||
{
|
||||
textBoxCursorIndex = 0; // GLOBAL: Reset the shared cursor index
|
||||
autoCursorCounter = 0; // GLOBAL: Reset counter for repeated keystrokes
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -2757,6 +2865,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
|||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
|
||||
{
|
||||
textBoxCursorIndex = textLength; // GLOBAL: Place cursor index to the end of current text
|
||||
autoCursorCounter = 0; // GLOBAL: Reset counter for repeated keystrokes
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -2825,19 +2934,22 @@ int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int
|
|||
|
||||
int tempValue = *value;
|
||||
|
||||
Rectangle spinner = { bounds.x + GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_SPACING), bounds.y,
|
||||
bounds.width - 2*(GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_SPACING)), bounds.height };
|
||||
Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height };
|
||||
Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height };
|
||||
Rectangle valueBoxBounds = {
|
||||
bounds.x + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING),
|
||||
bounds.y,
|
||||
bounds.width - 2*(GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING)), bounds.height };
|
||||
Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height };
|
||||
Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.y,
|
||||
(float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height };
|
||||
|
||||
Rectangle textBounds = { 0 };
|
||||
if (text != NULL)
|
||||
{
|
||||
textBounds.width = (float)GetTextWidth(text) + 2;
|
||||
textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
|
||||
textBounds.x = bounds.x + bounds.width + GuiGetStyle(SPINNER, TEXT_PADDING);
|
||||
textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
|
||||
textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
|
||||
if (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SPINNER, TEXT_PADDING);
|
||||
if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
|
||||
}
|
||||
|
||||
// Update control
|
||||
|
|
@ -2871,20 +2983,20 @@ int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int
|
|||
|
||||
// Draw control
|
||||
//--------------------------------------------------------------------
|
||||
result = GuiValueBox(spinner, NULL, &tempValue, minValue, maxValue, editMode);
|
||||
result = GuiValueBox(valueBoxBounds, NULL, &tempValue, minValue, maxValue, editMode);
|
||||
|
||||
// Draw value selector custom buttons
|
||||
// NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
|
||||
int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
|
||||
int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
|
||||
GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(SPINNER, BORDER_WIDTH));
|
||||
GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(VALUEBOX, BORDER_WIDTH));
|
||||
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
|
||||
|
||||
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
|
||||
GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
|
||||
|
||||
// Draw text label if provided
|
||||
GuiDrawText(text, textBounds, (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
|
||||
GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
*value = tempValue;
|
||||
|
|
@ -2903,7 +3015,7 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in
|
|||
GuiState state = guiState;
|
||||
|
||||
char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";
|
||||
sprintf(textValue, "%i", *value);
|
||||
snprintf(textValue, RAYGUI_VALUEBOX_MAX_CHARS + 1, "%i", *value);
|
||||
|
||||
Rectangle textBounds = { 0 };
|
||||
if (text != NULL)
|
||||
|
|
@ -2992,11 +3104,14 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in
|
|||
GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor);
|
||||
GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))));
|
||||
|
||||
// Draw cursor
|
||||
// Draw cursor rectangle
|
||||
if (editMode)
|
||||
{
|
||||
// NOTE: ValueBox internal text is always centered
|
||||
Rectangle cursor = { bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 1, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH) };
|
||||
Rectangle cursor = { bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 1,
|
||||
bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + 2,
|
||||
2, bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2 - 4 };
|
||||
if (cursor.height > bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2;
|
||||
GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)));
|
||||
}
|
||||
|
||||
|
|
@ -3019,7 +3134,7 @@ int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float
|
|||
GuiState state = guiState;
|
||||
|
||||
//char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";
|
||||
//sprintf(textValue, "%2.2f", *value);
|
||||
//snprintf(textValue, sizeof(textValue), "%2.2f", *value);
|
||||
|
||||
Rectangle textBounds = {0};
|
||||
if (text != NULL)
|
||||
|
|
@ -3205,6 +3320,7 @@ int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight,
|
|||
if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)));
|
||||
else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED)));
|
||||
else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_PRESSED)));
|
||||
else if (state == STATE_DISABLED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_DISABLED)));
|
||||
|
||||
// Draw left/right text if provided
|
||||
if (textLeft != NULL)
|
||||
|
|
@ -3215,7 +3331,7 @@ int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight,
|
|||
textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SLIDER, TEXT_PADDING);
|
||||
textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
|
||||
|
||||
GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))));
|
||||
GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
|
||||
}
|
||||
|
||||
if (textRight != NULL)
|
||||
|
|
@ -3226,7 +3342,7 @@ int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight,
|
|||
textBounds.x = bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING);
|
||||
textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
|
||||
|
||||
GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))));
|
||||
GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
|
||||
}
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
|
|
@ -3255,16 +3371,16 @@ int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight
|
|||
if (value == NULL) value = &temp;
|
||||
|
||||
// Progress bar
|
||||
Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH),
|
||||
Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING),
|
||||
bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING), 0,
|
||||
bounds.height - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) };
|
||||
bounds.height - GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) -1 };
|
||||
|
||||
// Update control
|
||||
//--------------------------------------------------------------------
|
||||
if (*value > maxValue) *value = maxValue;
|
||||
|
||||
// WARNING: Working with floats could lead to rounding issues
|
||||
if ((state != STATE_DISABLED)) progress.width = (float)(*value/(maxValue - minValue))*bounds.width - ((*value >= maxValue)? (float)(2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)) : 0.0f);
|
||||
if ((state != STATE_DISABLED)) progress.width = ((float)*value / (maxValue - minValue)) * (bounds.width - 2 * GuiGetStyle(PROGRESSBAR, BORDER_WIDTH));
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Draw control
|
||||
|
|
@ -3282,18 +3398,18 @@ int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight
|
|||
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
|
||||
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
|
||||
}
|
||||
else GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
|
||||
else GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
|
||||
|
||||
if (*value >= maxValue) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + progress.width + 1, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
|
||||
if (*value >= maxValue) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1}, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
|
||||
else
|
||||
{
|
||||
// Draw borders not yet reached by value
|
||||
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + 1, bounds.y, bounds.width - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
|
||||
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + 1, bounds.y + bounds.height - 1, bounds.width - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
|
||||
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
|
||||
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
|
||||
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y + bounds.height - 1, bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
|
||||
GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
|
||||
}
|
||||
|
||||
// Draw slider internal progress bar (depends on state)
|
||||
progress.width -= 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING);
|
||||
GuiDrawRectangle(progress, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED)));
|
||||
}
|
||||
|
||||
|
|
@ -3306,7 +3422,7 @@ int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight
|
|||
textBounds.x = bounds.x - textBounds.width - GuiGetStyle(PROGRESSBAR, TEXT_PADDING);
|
||||
textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
|
||||
|
||||
GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))));
|
||||
GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
|
||||
}
|
||||
|
||||
if (textRight != NULL)
|
||||
|
|
@ -3317,7 +3433,7 @@ int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight
|
|||
textBounds.x = bounds.x + bounds.width + GuiGetStyle(PROGRESSBAR, TEXT_PADDING);
|
||||
textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
|
||||
|
||||
GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))));
|
||||
GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
|
||||
}
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
|
|
@ -3467,11 +3583,11 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd
|
|||
// Draw visible items
|
||||
for (int i = 0; ((i < visibleItems) && (text != NULL)); i++)
|
||||
{
|
||||
GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_NORMAL)), BLANK);
|
||||
if (GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_NORMAL)) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_NORMAL)), BLANK);
|
||||
|
||||
if (state == STATE_DISABLED)
|
||||
{
|
||||
if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)));
|
||||
if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)));
|
||||
|
||||
GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)));
|
||||
}
|
||||
|
|
@ -3480,18 +3596,18 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd
|
|||
if (((startIndex + i) == itemSelected) && (active != NULL))
|
||||
{
|
||||
// Draw item selected
|
||||
GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)));
|
||||
GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)));
|
||||
GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)));
|
||||
}
|
||||
else if (((startIndex + i) == itemFocused)) // && (focus != NULL)) // NOTE: We want items focused, despite not returned!
|
||||
{
|
||||
// Draw item focused
|
||||
GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)));
|
||||
GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)));
|
||||
GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw item normal
|
||||
// Draw item normal (no rectangle)
|
||||
GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)));
|
||||
}
|
||||
}
|
||||
|
|
@ -3570,7 +3686,10 @@ int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
|
|||
|
||||
int result = 0;
|
||||
GuiState state = guiState;
|
||||
Rectangle selector = { (float)bounds.x + (*alpha)*bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, (float)bounds.y - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT), (float)bounds.height + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2 };
|
||||
Rectangle selector = { (float)bounds.x + (*alpha)*bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2,
|
||||
(float)bounds.y - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW),
|
||||
(float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT),
|
||||
(float)bounds.height + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2 };
|
||||
|
||||
// Update control
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -3617,7 +3736,6 @@ int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
|
|||
|
||||
// Draw control
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Draw alpha bar: checked background
|
||||
if (state != STATE_DISABLED)
|
||||
{
|
||||
|
|
@ -4283,8 +4401,6 @@ void GuiLoadStyleDefault(void)
|
|||
GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
|
||||
GuiSetStyle(VALUEBOX, TEXT_PADDING, 0);
|
||||
GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
|
||||
GuiSetStyle(SPINNER, TEXT_PADDING, 0);
|
||||
GuiSetStyle(SPINNER, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
|
||||
GuiSetStyle(STATUSBAR, TEXT_PADDING, 8);
|
||||
GuiSetStyle(STATUSBAR, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
|
||||
|
||||
|
|
@ -4299,8 +4415,8 @@ void GuiLoadStyleDefault(void)
|
|||
GuiSetStyle(COMBOBOX, COMBO_BUTTON_SPACING, 2);
|
||||
GuiSetStyle(DROPDOWNBOX, ARROW_PADDING, 16);
|
||||
GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 2);
|
||||
GuiSetStyle(SPINNER, SPIN_BUTTON_WIDTH, 24);
|
||||
GuiSetStyle(SPINNER, SPIN_BUTTON_SPACING, 2);
|
||||
GuiSetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH, 24);
|
||||
GuiSetStyle(VALUEBOX, SPINNER_BUTTON_SPACING, 2);
|
||||
GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0);
|
||||
GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0);
|
||||
GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6);
|
||||
|
|
@ -4310,6 +4426,7 @@ void GuiLoadStyleDefault(void)
|
|||
GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 12);
|
||||
GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 28);
|
||||
GuiSetStyle(LISTVIEW, LIST_ITEMS_SPACING, 2);
|
||||
GuiSetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH, 1);
|
||||
GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 12);
|
||||
GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE);
|
||||
GuiSetStyle(COLORPICKER, COLOR_SELECTOR_SIZE, 8);
|
||||
|
|
@ -4352,7 +4469,7 @@ const char *GuiIconText(int iconId, const char *text)
|
|||
if (text != NULL)
|
||||
{
|
||||
memset(buffer, 0, 1024);
|
||||
sprintf(buffer, "#%03i#", iconId);
|
||||
snprintf(buffer, 1024, "#%03i#", iconId);
|
||||
|
||||
for (int i = 5; i < 1024; i++)
|
||||
{
|
||||
|
|
@ -4364,7 +4481,7 @@ const char *GuiIconText(int iconId, const char *text)
|
|||
}
|
||||
else
|
||||
{
|
||||
sprintf(iconBuffer, "#%03i#", iconId);
|
||||
snprintf(iconBuffer, 16, "#%03i#", iconId);
|
||||
|
||||
return iconBuffer;
|
||||
}
|
||||
|
|
@ -4449,6 +4566,56 @@ char **GuiLoadIcons(const char *fileName, bool loadIconsName)
|
|||
return guiIconsName;
|
||||
}
|
||||
|
||||
// Load icons from memory
|
||||
// WARNING: Binary files only
|
||||
char **GuiLoadIconsFromMemory(const unsigned char *fileData, size_t dataSize, bool loadIconsName)
|
||||
{
|
||||
unsigned char *fileDataPtr = (unsigned char *)fileData;
|
||||
char **guiIconsName = NULL;
|
||||
|
||||
char signature[5] = { 0 };
|
||||
short version = 0;
|
||||
short reserved = 0;
|
||||
short iconCount = 0;
|
||||
short iconSize = 0;
|
||||
|
||||
memcpy(signature, fileDataPtr, 4);
|
||||
memcpy(&version, fileDataPtr + 4, sizeof(short));
|
||||
memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short));
|
||||
memcpy(&iconCount, fileDataPtr + 4 + 2 + 2, sizeof(short));
|
||||
memcpy(&iconSize, fileDataPtr + 4 + 2 + 2 + 2, sizeof(short));
|
||||
fileDataPtr += 12;
|
||||
|
||||
if ((signature[0] == 'r') &&
|
||||
(signature[1] == 'G') &&
|
||||
(signature[2] == 'I') &&
|
||||
(signature[3] == ' '))
|
||||
{
|
||||
if (loadIconsName)
|
||||
{
|
||||
guiIconsName = (char **)RAYGUI_MALLOC(iconCount*sizeof(char *));
|
||||
for (int i = 0; i < iconCount; i++)
|
||||
{
|
||||
guiIconsName[i] = (char *)RAYGUI_MALLOC(RAYGUI_ICON_MAX_NAME_LENGTH);
|
||||
memcpy(guiIconsName[i], fileDataPtr, RAYGUI_ICON_MAX_NAME_LENGTH);
|
||||
fileDataPtr += RAYGUI_ICON_MAX_NAME_LENGTH;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip icon name data if not required
|
||||
fileDataPtr += iconCount*RAYGUI_ICON_MAX_NAME_LENGTH;
|
||||
}
|
||||
|
||||
int iconDataSize = iconCount*(iconSize*iconSize/32)*sizeof(unsigned int);
|
||||
guiIconsPtr = (unsigned int *)RAYGUI_MALLOC(iconDataSize);
|
||||
|
||||
memcpy(guiIconsPtr, fileDataPtr, iconDataSize);
|
||||
}
|
||||
|
||||
return guiIconsName;
|
||||
}
|
||||
|
||||
// Draw selected icon using rectangles pixel-by-pixel
|
||||
void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color)
|
||||
{
|
||||
|
|
@ -4786,7 +4953,7 @@ static Rectangle GetTextBounds(int control, Rectangle bounds)
|
|||
case SLIDER:
|
||||
case CHECKBOX:
|
||||
case VALUEBOX:
|
||||
case SPINNER:
|
||||
case CONTROL11:
|
||||
// TODO: More special cases (label on side): SLIDER, CHECKBOX, VALUEBOX, SPINNER
|
||||
default:
|
||||
{
|
||||
|
|
@ -5204,7 +5371,7 @@ static const char **GuiTextSplit(const char *text, char delimiter, int *count, i
|
|||
buffer[i] = '\0'; // Set an end of string at this point
|
||||
|
||||
counter++;
|
||||
if (counter > RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
|
||||
if (counter >= RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue