summaryrefslogtreecommitdiffhomepage
path: root/examples
diff options
context:
space:
mode:
authorRay <[email protected]>2023-09-24 23:51:23 +0200
committerRay <[email protected]>2023-09-24 23:51:23 +0200
commitf7c3035b8c5f7b86165ba24dfa868a4527e48a2a (patch)
treeae23cce26bd9e6e529168bf4bcb8e375723ba48c /examples
parentc8a6093d52ff6bdd17f9df012f6666b74629f595 (diff)
downloadraylib-f7c3035b8c5f7b86165ba24dfa868a4527e48a2a.tar.gz
raylib-f7c3035b8c5f7b86165ba24dfa868a4527e48a2a.zip
Update raygui.h
Diffstat (limited to 'examples')
-rw-r--r--examples/shapes/raygui.h1369
1 files changed, 975 insertions, 394 deletions
diff --git a/examples/shapes/raygui.h b/examples/shapes/raygui.h
index 63a27fa9..26d6bacb 100644
--- a/examples/shapes/raygui.h
+++ b/examples/shapes/raygui.h
@@ -1,6 +1,6 @@
/*******************************************************************************************
*
-* raygui v4.0-dev - A simple and easy-to-use immediate-mode gui library
+* raygui v4.0 - A simple and easy-to-use immediate-mode gui library
*
* DESCRIPTION:
* raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also
@@ -10,20 +10,26 @@
* - Immediate-mode gui, minimal retained data
* - +25 controls provided (basic and advanced)
* - Styling system for colors, font and metrics
-* - Icons supported, embeds a complete 1-bit icons pack
-* - Standalone usage mode option (custom graphics backends)
-* - Multiple tools provided for raygui development
+* - Icons supported, embedded as a 1-bit icons pack
+* - Standalone mode option (custom input/graphics backend)
+* - Multiple support tools provided for raygui development
*
* POSSIBLE IMPROVEMENTS:
-* - Redesign functions that require a value as parameter to be returned, pass by reference
* - Better standalone mode API for easy plug of custom backends
-* - Externalize required inputs in some way, allow user customization
+* - Externalize required inputs, allow user easier customization
*
* LIMITATIONS:
-* - No multi-line word-wraped text box support
-* - No auto-layout mechanism provided, up to the user to define controls position and size
+* - No editable multi-line word-wraped text box supported
+* - No auto-layout mechanism, up to the user to define controls position and size
* - Standalone mode requires library modification and some user work to plug another backend
*
+* NOTES:
+* - WARNING: GuiLoadStyle() and GuiLoadStyle{Custom}() functions, allocate memory for
+* font atlas recs and glyphs, freeing that memory is (usually) up to the user,
+* no unload function is explicitly provided... but note that GuiLoadStyleDefaulf() unloads
+* by default any previously loaded font (texture, recs, glyphs).
+* - Global UI alpha (guiAlpha) is applied inside GuiDrawRectangle() and GuiDrawText() functions
+*
* CONTROLS PROVIDED:
* # Container/separators Controls
* - WindowBox --> StatusBar, Panel
@@ -31,13 +37,15 @@
* - Line
* - Panel --> StatusBar
* - ScrollPanel --> StatusBar
+* - TabBar --> Button
*
* # Basic Controls
* - Label
-* - Button
* - LabelButton --> Label
+* - Button
* - Toggle
* - ToggleGroup --> Toggle
+* - ToggleSlider
* - CheckBox
* - ComboBox
* - DropdownBox
@@ -126,11 +134,24 @@
* Includes custom ricons.h header defining a set of custom icons,
* this file can be generated using rGuiIcons tool
*
+* #define RAYGUI_DEBUG_RECS_BOUNDS
+* Draw control bounds rectangles for debug
+*
* #define RAYGUI_DEBUG_TEXT_BOUNDS
* Draw text bounds rectangles for debug
*
* VERSIONS HISTORY:
-* 4.0 (xx-Jun-2023) REDESIGNED: GuiScrollPanel(), get parameters by reference and return result value
+* 4.0 (12-Sep-2023) ADDED: GuiToggleSlider()
+* ADDED: GuiColorPickerHSV() and GuiColorPanelHSV()
+* ADDED: Multiple new icons, mostly compiler related
+* ADDED: New DEFAULT properties: TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE
+* ADDED: New enum values: GuiTextAlignment, GuiTextAlignmentVertical, GuiTextWrapMode
+* ADDED: Support loading styles with custom font charset from external file
+* REDESIGNED: GuiTextBox(), support mouse cursor positioning
+* REDESIGNED: GuiDrawText(), support multiline and word-wrap modes (read only)
+* REDESIGNED: GuiProgressBar() to be more visual, progress affects border color
+* REDESIGNED: Global alpha consideration moved to GuiDrawRectangle() and GuiDrawText()
+* REDESIGNED: GuiScrollPanel(), get parameters by reference and return result value
* REDESIGNED: GuiToggleGroup(), get parameters by reference and return result value
* REDESIGNED: GuiComboBox(), get parameters by reference and return result value
* REDESIGNED: GuiCheckBox(), get parameters by reference and return result value
@@ -146,6 +167,10 @@
* REDESIGNED: GuiGrid(), added extra parameter
* REDESIGNED: GuiListViewEx(), change parameters order
* REDESIGNED: All controls return result as int value
+* REVIEWED: GuiScrollPanel() to avoid smallish scroll-bars
+* REVIEWED: All examples and specially controls_test_suite
+* RENAMED: gui_file_dialog module to gui_window_file_dialog
+* UPDATED: All styles to include ISO-8859-15 charset (as much as possible)
*
* 3.6 (10-May-2023) ADDED: New icon: SAND_TIMER
* ADDED: GuiLoadStyleFromMemory() (binary only)
@@ -221,17 +246,43 @@
* 0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria.
*
* DEPENDENCIES:
-* raylib 4.5 Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing
+* raylib 4.6-dev Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing
*
+* STANDALONE MODE:
* By default raygui depends on raylib mostly for the inputs and the drawing functionality but that dependency can be disabled
* with the config flag RAYGUI_STANDALONE. In that case is up to the user to provide another backend to cover library needs.
*
+* The following functions should be redefined for a custom backend:
+*
+* - Vector2 GetMousePosition(void);
+* - float GetMouseWheelMove(void);
+* - bool IsMouseButtonDown(int button);
+* - bool IsMouseButtonPressed(int button);
+* - bool IsMouseButtonReleased(int button);
+* - bool IsKeyDown(int key);
+* - bool IsKeyPressed(int key);
+* - int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox()
+*
+* - void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle()
+* - void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker()
+*
+* - Font GetFontDefault(void); // -- GuiLoadStyleDefault()
+* - Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle()
+* - Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image
+* - void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization)
+* - char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data
+* - void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data
+* - const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs
+* - int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list
+* - void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list
+* - unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle()
+*
* CONTRIBUTORS:
* Ramon Santamaria: Supervision, review, redesign, update and maintenance
* Vlad Adrian: Complete rewrite of GuiTextBox() to support extended features (2019)
* Sergio Martinez: Review, testing (2015) and redesign of multiple controls (2018)
-* Adria Arranz: Testing and Implementation of additional controls (2018)
-* Jordi Jorba: Testing and Implementation of additional controls (2018)
+* Adria Arranz: Testing and implementation of additional controls (2018)
+* Jordi Jorba: Testing and implementation of additional controls (2018)
* Albert Martos: Review and testing of the library (2015)
* Ian Eito: Review and testing of the library (2015)
* Kevin Gato: Initial implementation of basic components (2014)
@@ -265,7 +316,7 @@
#define RAYGUI_VERSION_MAJOR 4
#define RAYGUI_VERSION_MINOR 0
#define RAYGUI_VERSION_PATCH 0
-#define RAYGUI_VERSION "4.0-dev"
+#define RAYGUI_VERSION "4.0"
#if !defined(RAYGUI_STANDALONE)
#include "raylib.h"
@@ -390,37 +441,69 @@
} Font;
#endif
+
// Style property
+// NOTE: Used when exporting style as code for convenience
typedef struct GuiStyleProp {
- unsigned short controlId;
- unsigned short propertyId;
- unsigned int propertyValue;
+ unsigned short controlId; // Control identifier
+ unsigned short propertyId; // Property identifier
+ int propertyValue; // Property value
} GuiStyleProp;
+/*
+// Controls text style -NOT USED-
+// NOTE: Text style is defined by control
+typedef struct GuiTextStyle {
+ unsigned int size;
+ int charSpacing;
+ int lineSpacing;
+ int alignmentH;
+ int alignmentV;
+ int padding;
+} GuiTextStyle;
+*/
+
// Gui control state
typedef enum {
STATE_NORMAL = 0,
STATE_FOCUSED,
STATE_PRESSED,
- STATE_DISABLED,
+ STATE_DISABLED
} GuiState;
// Gui control text alignment
typedef enum {
TEXT_ALIGN_LEFT = 0,
TEXT_ALIGN_CENTER,
- TEXT_ALIGN_RIGHT,
+ TEXT_ALIGN_RIGHT
} GuiTextAlignment;
+// Gui control text alignment vertical
+// NOTE: Text vertical position inside the text bounds
+typedef enum {
+ TEXT_ALIGN_TOP = 0,
+ TEXT_ALIGN_MIDDLE,
+ TEXT_ALIGN_BOTTOM
+} GuiTextAlignmentVertical;
+
+// Gui control text wrap mode
+// NOTE: Useful for multiline text
+typedef enum {
+ TEXT_WRAP_NONE = 0,
+ TEXT_WRAP_CHAR,
+ TEXT_WRAP_WORD
+} GuiTextWrapMode;
+
// Gui controls
typedef enum {
// Default -> populates to all controls when set
DEFAULT = 0,
+
// Basic controls
LABEL, // Used also for: LABELBUTTON
BUTTON,
TOGGLE, // Used also for: TOGGLEGROUP
- SLIDER, // Used also for: SLIDERBAR
+ SLIDER, // Used also for: SLIDERBAR, TOGGLESLIDER
PROGRESSBAR,
CHECKBOX,
COMBOBOX,
@@ -437,37 +520,55 @@ typedef enum {
// Gui base properties for every control
// NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties)
typedef enum {
- BORDER_COLOR_NORMAL = 0,
- BASE_COLOR_NORMAL,
- TEXT_COLOR_NORMAL,
- BORDER_COLOR_FOCUSED,
- BASE_COLOR_FOCUSED,
- TEXT_COLOR_FOCUSED,
- BORDER_COLOR_PRESSED,
- BASE_COLOR_PRESSED,
- TEXT_COLOR_PRESSED,
- BORDER_COLOR_DISABLED,
- BASE_COLOR_DISABLED,
- TEXT_COLOR_DISABLED,
- BORDER_WIDTH,
- TEXT_PADDING,
- TEXT_ALIGNMENT,
- RESERVED
+ BORDER_COLOR_NORMAL = 0, // Control border color in STATE_NORMAL
+ BASE_COLOR_NORMAL, // Control base color in STATE_NORMAL
+ TEXT_COLOR_NORMAL, // Control text color in STATE_NORMAL
+ BORDER_COLOR_FOCUSED, // Control border color in STATE_FOCUSED
+ BASE_COLOR_FOCUSED, // Control base color in STATE_FOCUSED
+ TEXT_COLOR_FOCUSED, // Control text color in STATE_FOCUSED
+ BORDER_COLOR_PRESSED, // Control border color in STATE_PRESSED
+ BASE_COLOR_PRESSED, // Control base color in STATE_PRESSED
+ TEXT_COLOR_PRESSED, // Control text color in STATE_PRESSED
+ 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
+ //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_WRAP_MODE // Control text wrap-mode inside text bounds -> GLOBAL for all controls
} GuiControlProperty;
+// TODO: Which text styling properties should be global or per-control?
+// At this moment TEXT_PADDING and TEXT_ALIGNMENT is configured and saved per control while
+// TEXT_SIZE, TEXT_SPACING, TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE are global and
+// should be configured by user as needed while defining the UI layout
+
+
// Gui extended properties depend on control
-// NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default 8 properties)
+// NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default, max 8 properties)
//----------------------------------------------------------------------------------
-
// DEFAULT extended properties
// NOTE: Those properties are common to all controls or global
+// WARNING: We only have 8 slots for those properties by default!!! -> New global control: TEXT?
typedef enum {
TEXT_SIZE = 16, // Text size (glyphs max height)
TEXT_SPACING, // Text spacing between glyphs
LINE_COLOR, // Line control color
BACKGROUND_COLOR, // Background color
+ TEXT_LINE_SPACING, // Text spacing between lines
+ TEXT_ALIGNMENT_VERTICAL, // Text vertical alignment inside text bounds (after border and padding)
+ TEXT_WRAP_MODE // Text wrap-mode inside text bounds
+ //TEXT_DECORATION // Text decoration: 0-None, 1-Underline, 2-Line-through, 3-Overline
+ //TEXT_DECORATION_THICK // Text decoration line thikness
} GuiDefaultProperty;
+// Other possible text properties:
+// TEXT_WEIGHT // Normal, Italic, Bold -> Requires specific font change
+// TEXT_INDENT // Text indentation -> Now using TEXT_PADDING...
+
// Label
//typedef enum { } GuiLabelProperty;
@@ -492,12 +593,12 @@ typedef enum {
// ScrollBar
typedef enum {
- ARROWS_SIZE = 16,
- ARROWS_VISIBLE,
- SCROLL_SLIDER_PADDING, // (SLIDERBAR, SLIDER_PADDING)
- SCROLL_SLIDER_SIZE,
- SCROLL_PADDING,
- SCROLL_SPEED,
+ ARROWS_SIZE = 16, // ScrollBar arrows size
+ ARROWS_VISIBLE, // ScrollBar arrows visible
+ SCROLL_SLIDER_PADDING, // ScrollBar slider internal padding
+ SCROLL_SLIDER_SIZE, // ScrollBar slider size
+ SCROLL_PADDING, // ScrollBar scroll padding from arrows
+ SCROLL_SPEED, // ScrollBar scrolling speed
} GuiScrollBarProperty;
// CheckBox
@@ -519,11 +620,7 @@ typedef enum {
// TextBox/TextBoxMulti/ValueBox/Spinner
typedef enum {
- TEXT_INNER_PADDING = 16, // TextBox/TextBoxMulti/ValueBox/Spinner inner text padding
- TEXT_LINES_SPACING, // TextBoxMulti lines separation
- TEXT_ALIGNMENT_VERTICAL, // TextBoxMulti vertical alignment: 0-CENTERED, 1-UP, 2-DOWN
- TEXT_MULTILINE, // TextBox supports multiple lines
- TEXT_WRAP_MODE // TextBox wrap mode for multiline: 0-NO_WRAP, 1-CHAR_WRAP, 2-WORD_WRAP
+ TEXT_READONLY = 16, // TextBox in read-only mode: 0-text editable, 1-text no-editable
} GuiTextBoxProperty;
// Spinner
@@ -537,7 +634,7 @@ typedef enum {
LIST_ITEMS_HEIGHT = 16, // ListView items height
LIST_ITEMS_SPACING, // ListView items separation
SCROLLBAR_WIDTH, // ListView scrollbar size (usually width)
- SCROLLBAR_SIDE, // ListView scrollbar side (0-left, 1-right)
+ SCROLLBAR_SIDE, // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE)
} GuiListViewProperty;
// ColorPicker
@@ -571,7 +668,7 @@ RAYGUIAPI void GuiDisable(void); // Disable gui c
RAYGUIAPI void GuiLock(void); // Lock gui controls (global state)
RAYGUIAPI void GuiUnlock(void); // Unlock gui controls (global state)
RAYGUIAPI bool GuiIsLocked(void); // Check if gui is locked (global state)
-RAYGUIAPI void GuiFade(float alpha); // Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f
+RAYGUIAPI void GuiSetAlpha(float alpha); // Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f
RAYGUIAPI void GuiSetState(int state); // Set gui state (global state)
RAYGUIAPI int GuiGetState(void); // Get gui state (global state)
@@ -618,6 +715,7 @@ RAYGUIAPI int GuiButton(Rectangle bounds, const char *text);
RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text); // Label button control, show true when clicked
RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active); // Toggle Button control, returns true when active
RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active); // Toggle Group control, returns active toggle index
+RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active); // Toggle Slider control, returns true when clicked
RAYGUIAPI int GuiCheckBox(Rectangle bounds, const char *text, bool *checked); // Check Box control, returns true when active
RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); // Combo Box control, returns selected item index
@@ -642,6 +740,8 @@ RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color);
RAYGUIAPI int GuiColorPanel(Rectangle bounds, const char *text, Color *color); // Color Panel control
RAYGUIAPI int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha); // Color Bar Alpha control
RAYGUIAPI int GuiColorBarHue(Rectangle bounds, const char *text, float *value); // Color Bar Hue control
+RAYGUIAPI int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Picker control that avoids conversion to RGB on each call (multiple color controls)
+RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Panel control that returns HSV color value, used by GuiColorPickerHSV()
//----------------------------------------------------------------------------------------------------------
@@ -1134,11 +1234,11 @@ static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] =
0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000, // ICON_MODE_3D
0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE
0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_TOP
- 0x7fe00000, 0x50386030, 0x47fe483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe, // ICON_CUBE_FACE_LEFT
+ 0x7fe00000, 0x50386030, 0x47c2483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe, // ICON_CUBE_FACE_LEFT
0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe, // ICON_CUBE_FACE_FRONT
- 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3ff27fe2, 0x0ffe1ffa, 0x000007fe, // ICON_CUBE_FACE_BOTTOM
+ 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3bf27be2, 0x0bfe1bfa, 0x000007fe, // ICON_CUBE_FACE_BOTTOM
0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe, // ICON_CUBE_FACE_RIGHT
- 0x7fe00000, 0x7fe87ff0, 0x7ffe7fe4, 0x7fe27fe2, 0x7fe27fe2, 0x24127fe2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_BACK
+ 0x7fe00000, 0x6fe85ff0, 0x781e77e4, 0x7be27be2, 0x7be27be2, 0x24127be2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_BACK
0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000, // ICON_CAMERA
0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000, // ICON_SPECIAL
0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800, // ICON_LINK_NET
@@ -1237,8 +1337,10 @@ static unsigned int *guiIconsPtr = guiIcons;
#define RAYGUI_ICON_SIZE 0
#endif
-#define RAYGUI_MAX_CONTROLS 16 // Maximum number of standard controls
-#define RAYGUI_MAX_PROPS_BASE 16 // Maximum number of standard properties
+// WARNING: Those values define the total size of the style data array,
+// if changed, previous saved styles could become incompatible
+#define RAYGUI_MAX_CONTROLS 16 // Maximum number of controls
+#define RAYGUI_MAX_PROPS_BASE 16 // Maximum number of base properties
#define RAYGUI_MAX_PROPS_EXTENDED 8 // Maximum number of extended properties
//----------------------------------------------------------------------------------
@@ -1254,7 +1356,7 @@ static GuiState guiState = STATE_NORMAL; // Gui global state, if !STATE_N
static Font guiFont = { 0 }; // Gui current font (WARNING: highly coupled to raylib)
static bool guiLocked = false; // Gui lock state (no inputs processed)
-static float guiAlpha = 1.0f; // Gui element transpacency on drawing
+static float guiAlpha = 1.0f; // Gui controls transparency
static unsigned int guiIconScale = 1; // Gui icon default scale (if icons enabled)
@@ -1264,7 +1366,7 @@ static const char *guiTooltipPtr = NULL; // Tooltip string pointer (strin
static bool guiSliderDragging = false; // Gui slider drag state (no inputs processed except dragged slider)
static Rectangle guiSliderActive = { 0 }; // Gui slider active bounds rectangle, used as an unique identifier
-static unsigned int textBoxCursorIndex = 0; // Cursor index, shared by all GuiTextBox*()
+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
@@ -1317,25 +1419,33 @@ static int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox()
// Drawing required functions
//-------------------------------------------------------------------------------
-static void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle(), GuiDrawIcon()
+static void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle()
static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker()
//-------------------------------------------------------------------------------
// Text required functions
//-------------------------------------------------------------------------------
-static Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount); // -- GuiLoadStyle()
-static Font GetFontDefault(void); // -- GuiLoadStyleDefault()
-static Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle()
-static void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle()
-static char *LoadFileText(const char *fileName); // -- GuiLoadStyle()
-static const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle()
+static Font GetFontDefault(void); // -- GuiLoadStyleDefault()
+static Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle(), load font
+
+static Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image
+static void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization)
+
+static char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data
+static void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data
+
+static const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs
+
+static int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list
+static void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list
+
+static unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle()
//-------------------------------------------------------------------------------
// raylib functions already implemented in raygui
//-------------------------------------------------------------------------------
static Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
static int ColorToInt(Color color); // Returns hexadecimal value for a Color
-static Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
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 **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
@@ -1358,7 +1468,7 @@ static int GetTextWidth(const char *text); // Gui get text
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
-static void GuiDrawText(const char *text, Rectangle bounds, 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 const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings
@@ -1368,6 +1478,7 @@ static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color
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 Color GuiFade(Color color, float alpha); // Fade color by an alpha factor
//----------------------------------------------------------------------------------
// Gui Setup Functions Definition
@@ -1390,7 +1501,7 @@ void GuiUnlock(void) { guiLocked = false; }
bool GuiIsLocked(void) { return guiLocked; }
// Set gui controls alpha global state
-void GuiFade(float alpha)
+void GuiSetAlpha(float alpha)
{
if (alpha < 0.0f) alpha = 0.0f;
else if (alpha > 1.0f) alpha = 1.0f;
@@ -1416,7 +1527,6 @@ void GuiSetFont(Font font)
if (!guiStyleLoaded) GuiLoadStyleDefault();
guiFont = font;
- GuiSetStyle(DEFAULT, TEXT_SIZE, font.baseSize);
}
}
@@ -1487,7 +1597,7 @@ int GuiWindowBox(Rectangle bounds, const char *title)
GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
#if defined(RAYGUI_NO_ICONS)
- clicked = GuiButton(closeButtonRec, "x");
+ result = GuiButton(closeButtonRec, "x");
#else
result = GuiButton(closeButtonRec, GuiIconText(ICON_CROSS_SMALL, NULL));
#endif
@@ -1510,9 +1620,9 @@ int GuiGroupBox(Rectangle bounds, const char *text)
// Draw control
//--------------------------------------------------------------------
- GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, Fade(GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)), guiAlpha));
- GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, Fade(GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)), guiAlpha));
- GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, Fade(GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)), guiAlpha));
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)));
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)));
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)));
GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text);
//--------------------------------------------------------------------
@@ -1533,7 +1643,7 @@ int GuiLine(Rectangle bounds, const char *text)
int result = 0;
GuiState state = guiState;
- Color color = Fade(GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)), guiAlpha);
+ Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR));
// Draw control
//--------------------------------------------------------------------
@@ -1574,15 +1684,15 @@ int GuiPanel(Rectangle bounds, const char *text)
{
// Move panel bounds after the header bar
bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1;
- bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + 1;
+ bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1;
}
// Draw control
//--------------------------------------------------------------------
if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar
- GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, Fade(GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED: LINE_COLOR)), guiAlpha),
- Fade(GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BASE_COLOR_DISABLED : BACKGROUND_COLOR)), guiAlpha));
+ GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED: LINE_COLOR)),
+ GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BASE_COLOR_DISABLED : BACKGROUND_COLOR)));
//--------------------------------------------------------------------
return result;
@@ -1595,7 +1705,7 @@ int GuiTabBar(Rectangle bounds, const char **text, int count, int *active)
#define RAYGUI_TABBAR_ITEM_WIDTH 160
int result = -1;
- GuiState state = guiState;
+ //GuiState state = guiState;
Rectangle tabBounds = { bounds.x, bounds.y, RAYGUI_TABBAR_ITEM_WIDTH, bounds.height };
@@ -1638,7 +1748,7 @@ int GuiTabBar(Rectangle bounds, const char **text, int count, int *active)
GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment);
// Draw tab close button
- // NOTE: Only draw close button for curren tab: if (CheckCollisionPointRec(mousePoint, tabBounds))
+ // NOTE: Only draw close button for current tab: if (CheckCollisionPointRec(mousePosition, tabBounds))
int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
@@ -1663,8 +1773,12 @@ int GuiTabBar(Rectangle bounds, const char **text, int count, int *active)
// Scroll Panel control
int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view)
{
+ #define RAYGUI_MIN_SCROLLBAR_WIDTH 40
+ #define RAYGUI_MIN_SCROLLBAR_HEIGHT 40
+
int result = 0;
GuiState state = guiState;
+ float mouseWheelSpeed = 20.0f; // Default movement speed with mouse wheel
Rectangle temp = { 0 };
if (view == NULL) view = &temp;
@@ -1692,8 +1806,31 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector
int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0;
int verticalScrollBarWidth = hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0;
- Rectangle horizontalScrollBar = { (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH), (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH), (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH), (float)horizontalScrollBarWidth };
- Rectangle verticalScrollBar = { (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)), (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), (float)verticalScrollBarWidth, (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) };
+ Rectangle horizontalScrollBar = {
+ (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH),
+ (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH),
+ (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH),
+ (float)horizontalScrollBarWidth
+ };
+ Rectangle verticalScrollBar = {
+ (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)),
+ (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH),
+ (float)verticalScrollBarWidth,
+ (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)
+ };
+
+ // Make sure scroll bars have a minimum width/height
+ // NOTE: If content >>> bounds, size could be very small or even 0
+ if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH)
+ {
+ horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH;
+ mouseWheelSpeed = 30.0f; // TODO: Calculate speed increment based on content.height vs bounds.height
+ }
+ if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT)
+ {
+ verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT;
+ mouseWheelSpeed = 30.0f; // TODO: Calculate speed increment based on content.width vs bounds.width
+ }
// Calculate view area (area without the scrollbars)
*view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)?
@@ -1736,9 +1873,9 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector
#endif
float wheelMove = GetMouseWheelMove();
- // Horizontal scroll ((Left Control or Left Shift) + Mouse wheel)
- if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*20;
- else scrollPos.y += wheelMove*20; // Vertical scroll
+ // Horizontal and vertical scrolling with mouse wheel
+ if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*mouseWheelSpeed;
+ else scrollPos.y += wheelMove*mouseWheelSpeed; // Vertical scroll
}
}
@@ -1753,7 +1890,7 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector
//--------------------------------------------------------------------
if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar
- GuiDrawRectangle(bounds, 0, BLANK, Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), guiAlpha)); // Draw background
+ GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background
// Save size of the scrollbar slider
const int slider = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
@@ -1780,11 +1917,11 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector
if (hasHorizontalScrollBar && hasVerticalScrollBar)
{
Rectangle corner = { (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) + 2) : (horizontalScrollBar.x + horizontalScrollBar.width + 2), verticalScrollBar.y + verticalScrollBar.height + 2, (float)horizontalScrollBarWidth - 4, (float)verticalScrollBarWidth - 4 };
- GuiDrawRectangle(corner, 0, BLANK, Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3))), guiAlpha));
+ GuiDrawRectangle(corner, 0, BLANK, GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3))));
}
// Draw scrollbar lines depending on current state
- GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), guiAlpha), BLANK);
+ GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK);
// Set scrollbar slider size back to the way it was before
GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, slider);
@@ -1808,7 +1945,7 @@ int GuiLabel(Rectangle bounds, const char *text)
// Draw control
//--------------------------------------------------------------------
- GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
+ GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
//--------------------------------------------------------------------
return result;
@@ -1839,8 +1976,8 @@ int GuiButton(Rectangle bounds, const char *text)
// Draw control
//--------------------------------------------------------------------
- GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(BUTTON, BASE + (state*3))), guiAlpha));
- GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha));
+ GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), GetColor(GuiGetStyle(BUTTON, BASE + (state*3))));
+ GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))));
if (state == STATE_FOCUSED) GuiTooltip(bounds);
//------------------------------------------------------------------
@@ -1877,7 +2014,7 @@ int GuiLabelButton(Rectangle bounds, const char *text)
// Draw control
//--------------------------------------------------------------------
- GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
+ GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
//--------------------------------------------------------------------
return pressed;
@@ -1916,13 +2053,13 @@ int GuiToggle(Rectangle bounds, const char *text, bool *active)
//--------------------------------------------------------------------
if (state == STATE_NORMAL)
{
- GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TOGGLE, ((*active)? BORDER_COLOR_PRESSED : (BORDER + state*3)))), guiAlpha), Fade(GetColor(GuiGetStyle(TOGGLE, ((*active)? BASE_COLOR_PRESSED : (BASE + state*3)))), guiAlpha));
- GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, ((*active)? TEXT_COLOR_PRESSED : (TEXT + state*3)))), guiAlpha));
+ GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, ((*active)? BORDER_COLOR_PRESSED : (BORDER + state*3)))), GetColor(GuiGetStyle(TOGGLE, ((*active)? BASE_COLOR_PRESSED : (BASE + state*3)))));
+ GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, ((*active)? TEXT_COLOR_PRESSED : (TEXT + state*3)))));
}
else
{
- GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TOGGLE, BORDER + state*3)), guiAlpha), Fade(GetColor(GuiGetStyle(TOGGLE, BASE + state*3)), guiAlpha));
- GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, TEXT + state*3)), guiAlpha));
+ GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + state*3)), GetColor(GuiGetStyle(TOGGLE, BASE + state*3)));
+ GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, TEXT + state*3)));
}
if (state == STATE_FOCUSED) GuiTooltip(bounds);
@@ -1980,7 +2117,79 @@ int GuiToggleGroup(Rectangle bounds, const char *text, int *active)
return result;
}
-// Check Box control, returns true when active
+// Toggle Slider control extended, returns true when clicked
+int GuiToggleSlider(Rectangle bounds, const char *text, int *active)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ int temp = 0;
+ if (active == NULL) active = &temp;
+
+ //bool toggle = false; // Required for individual toggles
+
+ // Get substrings items from text (items pointers)
+ int itemCount = 0;
+ const char **items = GuiTextSplit(text, ';', &itemCount, NULL);
+
+ Rectangle slider = {
+ 0, // Calculated later depending on the active toggle
+ bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),
+ (bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - (itemCount + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING))/itemCount,
+ bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) };
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
+ else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+ {
+ state = STATE_PRESSED;
+ (*active)++;
+ result = 1;
+ }
+ else state = STATE_FOCUSED;
+ }
+
+ if ((*active) && (state != STATE_FOCUSED)) state = STATE_PRESSED;
+ }
+
+ if (*active >= itemCount) *active = 0;
+ slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH) + (*active + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING) + (*active)*slider.width;
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + (state*3))),
+ GetColor(GuiGetStyle(TOGGLE, BASE_COLOR_NORMAL)));
+
+ // Draw internal slider
+ 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, BASE_COLOR_FOCUSED)));
+ else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)));
+
+ // Draw text in slider
+ if (text != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GetTextWidth(text);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = slider.x + slider.width/2 - textBounds.width/2;
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+ GuiDrawText(items[*active], textBounds, GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, TEXT + (state*3))), guiAlpha));
+ }
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Check Box control, returns 1 when state changed
int GuiCheckBox(Rectangle bounds, const char *text, bool *checked)
{
int result = 0;
@@ -2019,14 +2228,18 @@ int GuiCheckBox(Rectangle bounds, const char *text, bool *checked)
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
else state = STATE_FOCUSED;
- if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) *checked = !(*checked);
+ if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+ {
+ *checked = !(*checked);
+ result = 1;
+ }
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
- GuiDrawRectangle(bounds, GuiGetStyle(CHECKBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(CHECKBOX, BORDER + (state*3))), guiAlpha), BLANK);
+ GuiDrawRectangle(bounds, GuiGetStyle(CHECKBOX, BORDER_WIDTH), GetColor(GuiGetStyle(CHECKBOX, BORDER + (state*3))), BLANK);
if (*checked)
{
@@ -2034,10 +2247,10 @@ int GuiCheckBox(Rectangle bounds, const char *text, bool *checked)
bounds.y + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING),
bounds.width - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)),
bounds.height - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)) };
- GuiDrawRectangle(check, 0, BLANK, Fade(GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3)), guiAlpha));
+ GuiDrawRectangle(check, 0, BLANK, GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3)));
}
- GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
+ GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
//--------------------------------------------------------------------
return result;
@@ -2088,8 +2301,8 @@ int GuiComboBox(Rectangle bounds, const char *text, int *active)
// Draw control
//--------------------------------------------------------------------
// Draw combo box main
- GuiDrawRectangle(bounds, GuiGetStyle(COMBOBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(COMBOBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(COMBOBOX, BASE + (state*3))), guiAlpha));
- GuiDrawText(items[*active], GetTextBounds(COMBOBOX, bounds), GuiGetStyle(COMBOBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(COMBOBOX, TEXT + (state*3))), guiAlpha));
+ GuiDrawRectangle(bounds, GuiGetStyle(COMBOBOX, BORDER_WIDTH), GetColor(GuiGetStyle(COMBOBOX, BORDER + (state*3))), GetColor(GuiGetStyle(COMBOBOX, BASE + (state*3))));
+ GuiDrawText(items[*active], GetTextBounds(COMBOBOX, bounds), GuiGetStyle(COMBOBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(COMBOBOX, TEXT + (state*3))));
// Draw selector using a custom button
// NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
@@ -2184,8 +2397,8 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
//--------------------------------------------------------------------
if (editMode) GuiPanel(boundsOpen, NULL);
- GuiDrawRectangle(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), guiAlpha), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3)), guiAlpha));
- GuiDrawText(items[itemSelected], GetTextBounds(DEFAULT, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3)), guiAlpha));
+ GuiDrawRectangle(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3)));
+ GuiDrawText(items[itemSelected], GetTextBounds(DROPDOWNBOX, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3)));
if (editMode)
{
@@ -2197,25 +2410,25 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod
if (i == itemSelected)
{
- GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), guiAlpha), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED)), guiAlpha));
- GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED)), guiAlpha));
+ GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED)));
+ GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED)));
}
else if (i == itemFocused)
{
- GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), guiAlpha), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED)), guiAlpha));
- GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED)), guiAlpha));
+ GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED)));
+ GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED)));
}
- else GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL)), guiAlpha));
+ else GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL)));
}
}
// Draw arrows (using icon if available)
#if defined(RAYGUI_NO_ICONS)
GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },
- TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha));
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));
#else
GuiDrawText("#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },
- TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha)); // ICON_ARROW_DOWN_FILL
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL
#endif
//--------------------------------------------------------------------
@@ -2239,12 +2452,12 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
int result = 0;
GuiState state = guiState;
+ bool multiline = false; // TODO: Consider multiline text input
+ int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE);
+
Rectangle textBounds = GetTextBounds(TEXTBOX, bounds);
int textWidth = GetTextWidth(text) - GetTextWidth(text + textBoxCursorIndex);
- int textIndexOffset = 0; // Text index offset to start drawing in the box
-
- int alignmentVertical = GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT_VERTICAL);
- int multiline = GuiGetStyle(TEXTBOX, TEXT_MULTILINE);
+ int textIndexOffset = 0; // Text index offset to start drawing in the box
// Cursor rectangle
// NOTE: Position X value should be updated
@@ -2255,17 +2468,15 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
(float)GuiGetStyle(DEFAULT, TEXT_SIZE)*2
};
- switch (alignmentVertical)
- {
- case 0: cursor.y = textBounds.y + textBounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE); break; // CENTERED
- case 1: cursor.y = textBounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; break; // UP
- case 2: cursor.y = textBounds.y + textBounds.height; break; // DOWN
- default: break;
- }
-
if (cursor.height >= bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2;
if (cursor.y < (bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH))) cursor.y = bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH);
+ // Mouse cursor rectangle
+ // NOTE: Initialized outside of screen
+ Rectangle mouseCursor = cursor;
+ 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++;
@@ -2281,9 +2492,14 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
// Update control
//--------------------------------------------------------------------
- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ // WARNING: Text editing is only supported under certain conditions:
+ if ((state != STATE_DISABLED) && // Control not disabled
+ !GuiGetStyle(TEXTBOX, TEXT_READONLY) && // TextBox not on read-only mode
+ !guiLocked && // Gui not locked
+ !guiSliderDragging && // No gui slider on dragging
+ (wrapMode == TEXT_WRAP_NONE)) // No wrap mode
{
- Vector2 mousePoint = GetMousePosition();
+ Vector2 mousePosition = GetMousePosition();
if (editMode)
{
@@ -2301,7 +2517,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
textWidth = GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex);
}
- unsigned int textLength = (unsigned int)strlen(text); // Get current text length
+ int textLength = (int)strlen(text); // Get current text length
int codepoint = GetCharPressed(); // Get Unicode codepoint
if (multiline && IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n';
@@ -2329,16 +2545,10 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
}
// Move cursor to start
- if ((textLength > 0) && IsKeyPressed(KEY_HOME))
- {
- textBoxCursorIndex = 0;
- }
+ if ((textLength > 0) && IsKeyPressed(KEY_HOME)) textBoxCursorIndex = 0;
// Move cursor to end
- if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_END))
- {
- textBoxCursorIndex = textLength;
- }
+ 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))))
@@ -2359,7 +2569,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
text[textLength] = '\0';
}
}
-
+
// Delete codepoint from text, before current cursor position
if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))))
{
@@ -2386,7 +2596,6 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
}
// Move cursor position with keys
- //if (IsKeyDown(KEY_LEFT) && autoCursorMode)
if (IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && (autoCursorCooldownCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))
{
autoCursorDelayCounter++;
@@ -2412,19 +2621,59 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
}
}
- // TODO: Get cursor rectangle from mouse position
- //cursor = GetCursorFromMousePosition(bounds, text, mouse); // Gui style considered internally, including wrapMode
+ // Move cursor position with mouse
+ if (CheckCollisionPointRec(mousePosition, textBounds)) // Mouse hover text
+ {
+ float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/(float)guiFont.baseSize;
+ int codepoint = 0;
+ int codepointSize = 0;
+ int codepointIndex = 0;
+ float glyphWidth = 0.0f;
+ float widthToMouseX = 0;
+ int mouseCursorIndex = 0;
+
+ for (int i = textIndexOffset; i < textLength; i++)
+ {
+ codepoint = GetCodepointNext(&text[i], &codepointSize);
+ codepointIndex = GetGlyphIndex(guiFont, codepoint);
+
+ if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor);
+ else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor);
+
+ if (mousePosition.x <= (textBounds.x + (widthToMouseX + glyphWidth/2)))
+ {
+ mouseCursor.x = textBounds.x + widthToMouseX;
+ mouseCursorIndex = i;
+ break;
+ }
+
+ widthToMouseX += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
+ }
- // TODO: Get cursor rectangle from buffer index
- //cursor = GetCursorFromIndex(bounds, text, index); // Gui style considered internally, including wrapMode
+ // Check if mouse cursor is at the last position
+ int textEndWidth = GetTextWidth(text + textIndexOffset);
+ if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2))
+ {
+ mouseCursor.x = textBounds.x + textEndWidth;
+ mouseCursorIndex = strlen(text);
+ }
+
+ // Place cursor at required index on mouse click
+ if ((mouseCursor.x >= 0) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ cursor.x = mouseCursor.x;
+ textBoxCursorIndex = mouseCursorIndex;
+ }
+ }
+ else mouseCursor.x = -1;
// Recalculate cursor position.y depending on textBoxCursorIndex
cursor.x = bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex) + GuiGetStyle(DEFAULT, TEXT_SPACING);
//if (multiline) cursor.y = GetTextLines()
- // Finish text editing on ENTER (if not multiline mode) or mouse click outside bounds
+ // Finish text editing on ENTER or mouse click outside bounds
if ((!multiline && IsKeyPressed(KEY_ENTER)) ||
- (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ (!CheckCollisionPointRec(mousePosition, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
{
textBoxCursorIndex = 0; // GLOBAL: Reset the shared cursor index
result = 1;
@@ -2432,7 +2681,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
}
else
{
- if (CheckCollisionPointRec(mousePoint, bounds))
+ if (CheckCollisionPointRec(mousePosition, bounds))
{
state = STATE_FOCUSED;
@@ -2450,23 +2699,26 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
//--------------------------------------------------------------------
if (state == STATE_PRESSED)
{
- GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha));
+ GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)));
}
else if (state == STATE_DISABLED)
{
- GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)), guiAlpha));
+ GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)));
}
- else GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), BLANK);
+ else GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), BLANK);
// Draw text considering index offset if required
// NOTE: Text index offset depends on cursor position
- GuiDrawText(text + textIndexOffset, textBounds, GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha));
+ GuiDrawText(text + textIndexOffset, textBounds, GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))));
// Draw cursor
- if (editMode)
+ if (editMode && !GuiGetStyle(TEXTBOX, TEXT_READONLY))
{
//if (autoCursorMode || ((blinkCursorFrameCounter/40)%2 == 0))
- GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha));
+ GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)));
+
+ // Draw mouse position cursor (if required)
+ if (mouseCursor.x >= 0) GuiDrawRectangle(mouseCursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)));
}
else if (state == STATE_FOCUSED) GuiTooltip(bounds);
//--------------------------------------------------------------------
@@ -2475,22 +2727,23 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
}
/*
-// Text Box control with multiple lines
-// NOTE: It's a regular GuiTextBox() but enabling multiline support,
-// unfortunately cursor placement is not working properly so the function is removed
+// Text Box control with multiple lines and word-wrap
+// NOTE: This text-box is readonly, no editing supported by default
bool GuiTextBoxMulti(Rectangle bounds, char *text, int bufferSize, bool editMode)
{
bool pressed = false;
- GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT_VERTICAL, 1);
- GuiSetStyle(TEXTBOX, TEXT_MULTILINE, 1);
+ GuiSetStyle(TEXTBOX, TEXT_READONLY, 1);
+ GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // WARNING: If wrap mode enabled, text editing is not supported
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP);
// TODO: Implement methods to calculate cursor position properly
pressed = GuiTextBox(bounds, text, bufferSize, editMode);
- GuiSetStyle(TEXTBOX, TEXT_MULTILINE, 0);
- GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT_VERTICAL, 0);
-
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE);
+ GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE);
+ GuiSetStyle(TEXTBOX, TEXT_READONLY, 0);
+
return pressed;
}
*/
@@ -2562,7 +2815,7 @@ int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int
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, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
+ GuiDrawText(text, textBounds, (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
//--------------------------------------------------------------------
*value = tempValue;
@@ -2661,20 +2914,19 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in
if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));
else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));
- // WARNING: BLANK color does not work properly with Fade()
- GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), guiAlpha), baseColor);
- GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))), guiAlpha));
+ 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
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) };
- GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
+ GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)));
}
// Draw text label if provided
- GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
+ GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
//--------------------------------------------------------------------
return result;
@@ -2718,7 +2970,9 @@ int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight,
{
if (CHECK_BOUNDS_ID(bounds, guiSliderActive))
{
- // Get equivalent value and slider position from mousePoint.x
+ state = STATE_PRESSED;
+
+ // Get equivalent value and slider position from mousePosition.x
*value = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue;
}
}
@@ -2736,11 +2990,14 @@ int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight,
guiSliderDragging = true;
guiSliderActive = bounds; // Store bounds as an identifier when dragging starts
- // Get equivalent value and slider position from mousePoint.x
- *value = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue;
+ if (!CheckCollisionPointRec(mousePoint, slider))
+ {
+ // Get equivalent value and slider position from mousePosition.x
+ *value = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue;
- if (sliderWidth > 0) slider.x = mousePoint.x - slider.width/2; // Slider
- else if (sliderWidth == 0) slider.width = (float)sliderValue; // SliderBar
+ if (sliderWidth > 0) slider.x = mousePoint.x - slider.width/2; // Slider
+ else if (sliderWidth == 0) slider.width = (float)sliderValue; // SliderBar
+ }
}
else state = STATE_FOCUSED;
}
@@ -2763,11 +3020,12 @@ int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight,
// Draw control
//--------------------------------------------------------------------
- GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha));
+ GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)));
// Draw slider internal bar (depends on state)
- if ((state == STATE_NORMAL) || (state == STATE_PRESSED)) GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)), guiAlpha));
- else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED)), guiAlpha));
+ 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)));
// Draw left/right text if provided
if (textLeft != NULL)
@@ -2778,7 +3036,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, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
+ GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))));
}
if (textRight != NULL)
@@ -2789,7 +3047,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, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
+ GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))));
}
//--------------------------------------------------------------------
@@ -2817,6 +3075,7 @@ int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight
float temp = (maxValue - minValue)/2.0f;
if (value == NULL) value = &temp;
+ // Progress bar
Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH),
bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING), 0,
bounds.height - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) };
@@ -2825,16 +3084,39 @@ int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight
//--------------------------------------------------------------------
if (*value > maxValue) *value = maxValue;
- if (state != STATE_DISABLED) progress.width = ((float)(*value/(maxValue - minValue))*(float)(bounds.width - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)));
+ // 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);
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
- GuiDrawRectangle(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), guiAlpha), BLANK);
+ if (state == STATE_DISABLED)
+ {
+ GuiDrawRectangle(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), BLANK);
+ }
+ else
+ {
+ if (*value > minValue)
+ {
+ // Draw progress bar with colored border, more visual
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
+ 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)));
- // Draw slider internal progress bar (depends on state)
- if ((state == STATE_NORMAL) || (state == STATE_PRESSED)) GuiDrawRectangle(progress, 0, BLANK, Fade(GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED)), guiAlpha));
- else if (state == STATE_FOCUSED) GuiDrawRectangle(progress, 0, BLANK, Fade(GetColor(GuiGetStyle(PROGRESSBAR, TEXT_COLOR_FOCUSED)), guiAlpha));
+ 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)));
+ 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)));
+ }
+
+ // Draw slider internal progress bar (depends on state)
+ GuiDrawRectangle(progress, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED)));
+ }
// Draw left/right text if provided
if (textLeft != NULL)
@@ -2845,7 +3127,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, Fade(GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))), guiAlpha));
+ GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))));
}
if (textRight != NULL)
@@ -2856,7 +3138,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, Fade(GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))), guiAlpha));
+ GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))));
}
//--------------------------------------------------------------------
@@ -2871,9 +3153,8 @@ int GuiStatusBar(Rectangle bounds, const char *text)
// Draw control
//--------------------------------------------------------------------
- GuiDrawRectangle(bounds, GuiGetStyle(STATUSBAR, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(STATUSBAR, (state != STATE_DISABLED)? BORDER_COLOR_NORMAL : BORDER_COLOR_DISABLED)), guiAlpha),
- Fade(GetColor(GuiGetStyle(STATUSBAR, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha));
- GuiDrawText(text, GetTextBounds(STATUSBAR, bounds), GuiGetStyle(STATUSBAR, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(STATUSBAR, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED)), guiAlpha));
+ GuiDrawRectangle(bounds, GuiGetStyle(STATUSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(STATUSBAR, BORDER + (state*3))), GetColor(GuiGetStyle(STATUSBAR, BASE + (state*3))));
+ GuiDrawText(text, GetTextBounds(STATUSBAR, bounds), GuiGetStyle(STATUSBAR, TEXT_ALIGNMENT), GetColor(GuiGetStyle(STATUSBAR, TEXT + (state*3))));
//--------------------------------------------------------------------
return result;
@@ -2902,8 +3183,8 @@ int GuiDummyRec(Rectangle bounds, const char *text)
// Draw control
//--------------------------------------------------------------------
- GuiDrawRectangle(bounds, 0, BLANK, Fade(GetColor(GuiGetStyle(DEFAULT, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha));
- GuiDrawText(text, GetTextBounds(DEFAULT, bounds), TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(BUTTON, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED)), guiAlpha));
+ GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)));
+ GuiDrawText(text, GetTextBounds(DEFAULT, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(BUTTON, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED)));
//------------------------------------------------------------------
return result;
@@ -2930,7 +3211,7 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd
GuiState state = guiState;
int itemFocused = (focus == NULL)? -1 : *focus;
- int itemSelected = *active;
+ int itemSelected = (active == NULL)? -1 : *active;
// Check if we need a scroll bar
bool useScrollBar = false;
@@ -3002,35 +3283,35 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd
// Draw control
//--------------------------------------------------------------------
- GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background
+ GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background
// Draw visible items
for (int i = 0; ((i < visibleItems) && (text != NULL)); i++)
{
if (state == STATE_DISABLED)
{
- if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), guiAlpha), Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)), guiAlpha));
+ if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, 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), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha));
+ GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)));
}
else
{
- if ((startIndex + i) == itemSelected)
+ if (((startIndex + i) == itemSelected) && (active != NULL))
{
// Draw item selected
- GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), guiAlpha), Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha));
- GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)), guiAlpha));
+ GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, 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)
+ else if (((startIndex + i) == itemFocused)) // && (focus != NULL)) // NOTE: We want items focused, despite not returned!
{
// Draw item focused
- GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), guiAlpha), Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha));
- GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)), guiAlpha));
+ GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, 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
- GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)), guiAlpha));
+ GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)));
}
}
@@ -3062,10 +3343,10 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd
}
//--------------------------------------------------------------------
+ if (active != NULL) *active = itemSelected;
if (focus != NULL) *focus = itemFocused;
if (scrollIndex != NULL) *scrollIndex = startIndex;
- *active = itemSelected;
return result;
}
@@ -3137,14 +3418,14 @@ int GuiColorPanel(Rectangle bounds, const char *text, Color *color)
// Draw color picker: selector
Rectangle selector = { pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE) };
- GuiDrawRectangle(selector, 0, BLANK, Fade(colWhite, guiAlpha));
+ GuiDrawRectangle(selector, 0, BLANK, colWhite);
}
else
{
DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha));
}
- GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha), BLANK);
+ GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);
//--------------------------------------------------------------------
return result;
@@ -3174,6 +3455,8 @@ int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
{
if (CHECK_BOUNDS_ID(bounds, guiSliderActive))
{
+ state = STATE_PRESSED;
+
*alpha = (mousePoint.x - bounds.x)/bounds.width;
if (*alpha <= 0.0f) *alpha = 0.0f;
if (*alpha >= 1.0f) *alpha = 1.0f;
@@ -3217,7 +3500,7 @@ int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
for (int y = 0; y < checksY; y++)
{
Rectangle check = { bounds.x + x*RAYGUI_COLORBARALPHA_CHECKED_SIZE, bounds.y + y*RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE };
- GuiDrawRectangle(check, 0, BLANK, ((x + y)%2)? Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.4f), guiAlpha) : Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.4f), guiAlpha));
+ GuiDrawRectangle(check, 0, BLANK, ((x + y)%2)? Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.4f) : Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.4f));
}
}
@@ -3225,10 +3508,10 @@ int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
}
else DrawRectangleGradientEx(bounds, Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha));
- GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha), BLANK);
+ GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);
// Draw alpha bar: selector
- GuiDrawRectangle(selector, 0, BLANK, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha));
+ GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)));
//--------------------------------------------------------------------
return result;
@@ -3258,6 +3541,8 @@ int GuiColorBarHue(Rectangle bounds, const char *text, float *hue)
{
if (CHECK_BOUNDS_ID(bounds, guiSliderActive))
{
+ state = STATE_PRESSED;
+
*hue = (mousePoint.y - bounds.y)*360/bounds.height;
if (*hue <= 0.0f) *hue = 0.0f;
if (*hue >= 359.0f) *hue = 359.0f;
@@ -3303,7 +3588,8 @@ int GuiColorBarHue(Rectangle bounds, const char *text, float *hue)
if (state != STATE_DISABLED)
{
// Draw hue bar:color bars
- DrawRectangleGradientV((int)bounds.x, (int)(bounds.y), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha));
+ // TODO: Use directly DrawRectangleGradientEx(bounds, color1, color2, color2, color1);
+ DrawRectangleGradientV((int)bounds.x, (int)(bounds.y), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha));
DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + bounds.height/6), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha));
DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 2*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha));
DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 3*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha));
@@ -3312,10 +3598,10 @@ int GuiColorBarHue(Rectangle bounds, const char *text, float *hue)
}
else DrawRectangleGradientV((int)bounds.x, (int)bounds.y, (int)bounds.width, (int)bounds.height, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha));
- GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha), BLANK);
+ GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);
// Draw hue bar: selector
- GuiDrawRectangle(selector, 0, BLANK, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha));
+ GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)));
//--------------------------------------------------------------------
return result;
@@ -3340,9 +3626,9 @@ int GuiColorPicker(Rectangle bounds, const char *text, Color *color)
//Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) };
Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f });
-
+
GuiColorBarHue(boundsHue, NULL, &hsv.x);
-
+
//color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f);
Vector3 rgb = ConvertHSVtoRGB(hsv);
@@ -3351,6 +3637,105 @@ int GuiColorPicker(Rectangle bounds, const char *text, Color *color)
return result;
}
+// Color Picker control that avoids conversion to RGB and back to HSV on each call, thus avoiding jittering.
+// The user can call ConvertHSVtoRGB() to convert *colorHsv value to RGB.
+// NOTE: It's divided in multiple controls:
+// int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
+// int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
+// float GuiColorBarHue(Rectangle bounds, float value)
+// NOTE: bounds define GuiColorPanelHSV() size
+int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
+{
+ int result = 0;
+
+ Vector3 tempHsv = { 0 };
+
+ if (colorHsv == NULL)
+ {
+ const Vector3 tempColor = { 200.0f/255.0f, 0.0f, 0.0f };
+ tempHsv = ConvertRGBtoHSV(tempColor);
+ colorHsv = &tempHsv;
+ }
+
+ GuiColorPanelHSV(bounds, NULL, colorHsv);
+
+ const Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height };
+
+ GuiColorBarHue(boundsHue, NULL, &colorHsv->x);
+
+ return result;
+}
+
+// Color Panel control, returns HSV color value in *colorHsv.
+// Used by GuiColorPickerHSV()
+int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
+{
+ int result = 0;
+ GuiState state = guiState;
+ Vector2 pickerSelector = { 0 };
+
+ const Color colWhite = { 255, 255, 255, 255 };
+ const Color colBlack = { 0, 0, 0, 255 };
+
+ pickerSelector.x = bounds.x + (float)colorHsv->y*bounds.width; // HSV: Saturation
+ pickerSelector.y = bounds.y + (1.0f - (float)colorHsv->z)*bounds.height; // HSV: Value
+
+ float hue = -1.0f;
+ Vector3 maxHue = { hue >= 0.0f ? hue : colorHsv->x, 1.0f, 1.0f };
+ Vector3 rgbHue = ConvertHSVtoRGB(maxHue);
+ Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x),
+ (unsigned char)(255.0f*rgbHue.y),
+ (unsigned char)(255.0f*rgbHue.z), 255 };
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ state = STATE_PRESSED;
+ pickerSelector = mousePoint;
+
+ // Calculate color from picker
+ Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y };
+
+ colorPick.x /= (float)bounds.width; // Get normalized value on x
+ colorPick.y /= (float)bounds.height; // Get normalized value on y
+
+ colorHsv->y = colorPick.x;
+ colorHsv->z = 1.0f - colorPick.y;
+ }
+ else state = STATE_FOCUSED;
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (state != STATE_DISABLED)
+ {
+ DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha));
+ DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0));
+
+ // Draw color picker: selector
+ Rectangle selector = { pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE) };
+ GuiDrawRectangle(selector, 0, BLANK, colWhite);
+ }
+ else
+ {
+ DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha));
+ }
+
+ GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
// Message Box control
int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons)
{
@@ -3371,7 +3756,7 @@ int GuiMessageBox(Rectangle bounds, const char *title, const char *message, cons
buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount;
buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT;
- int textWidth = GetTextWidth(message);
+ int textWidth = GetTextWidth(message) + 2;
Rectangle textBounds = { 0 };
textBounds.x = bounds.x + bounds.width/2 - textWidth/2;
@@ -3511,8 +3896,9 @@ int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vect
Vector2 mousePoint = GetMousePosition();
Vector2 currentMouseCell = { 0 };
- int linesV = ((int)(bounds.width/spacing))*subdivs + 1;
- int linesH = ((int)(bounds.height/spacing))*subdivs + 1;
+ float spaceWidth = spacing/(float)subdivs;
+ int linesV = (int)(bounds.width/spaceWidth) + 1;
+ int linesH = (int)(bounds.height/spaceWidth) + 1;
// Update control
//--------------------------------------------------------------------
@@ -3539,14 +3925,14 @@ int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vect
for (int i = 0; i < linesV; i++)
{
Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height };
- GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0) ? Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA*4) : Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA));
+ GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA));
}
// Draw horizontal grid lines
for (int i = 0; i < linesH; i++)
{
Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width, 1 };
- GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0) ? Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA*4) : Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA));
+ GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA));
}
}
} break;
@@ -3620,34 +4006,37 @@ void GuiLoadStyle(const char *fileName)
sscanf(buffer, "f %d %s %[^\r\n]s", &fontSize, charmapFileName, fontFileName);
Font font = { 0 };
+ int *codepoints = NULL;
+ int codepointCount = 0;
if (charmapFileName[0] != '0')
{
- // Load characters from charmap file,
- // expected '\n' separated list of integer values
- char *charValues = LoadFileText(charmapFileName);
- if (charValues != NULL)
- {
- int glyphCount = 0;
- const char **chars = TextSplit(charValues, '\n', &glyphCount);
-
- int *values = (int *)RAYGUI_MALLOC(glyphCount*sizeof(int));
- for (int i = 0; i < glyphCount; i++) values[i] = TextToInteger(chars[i]);
-
- if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
- font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, values, glyphCount);
- if (font.texture.id == 0) font = GetFontDefault();
-
- RAYGUI_FREE(values);
- }
+ // Load text data from file
+ // NOTE: Expected an UTF-8 array of codepoints, no separation
+ char *textData = LoadFileText(TextFormat("%s/%s", GetDirectoryPath(fileName), charmapFileName));
+ codepoints = LoadCodepoints(textData, &codepointCount);
+ UnloadFileText(textData);
}
- else
+
+ if (fontFileName[0] != '\0')
{
+ // In case a font is already loaded and it is not default internal font, unload it
if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
- font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0);
- if (font.texture.id == 0) font = GetFontDefault();
+
+ if (codepointCount > 0) font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, codepoints, codepointCount);
+ else font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0); // Default to 95 standard codepoints
}
+ // If font texture not properly loaded, revert to default font and size/spacing
+ if (font.texture.id == 0)
+ {
+ font = GetFontDefault();
+ GuiSetStyle(DEFAULT, TEXT_SIZE, 10);
+ GuiSetStyle(DEFAULT, TEXT_SPACING, 1);
+ }
+
+ UnloadCodepoints(codepoints);
+
if ((font.texture.id > 0) && (font.glyphCount > 0)) GuiSetFont(font);
} break;
@@ -3674,12 +4063,12 @@ void GuiLoadStyle(const char *fileName)
if (fileDataSize > 0)
{
- unsigned char *fileData = (unsigned char *)RL_MALLOC(fileDataSize*sizeof(unsigned char));
+ unsigned char *fileData = (unsigned char *)RAYGUI_MALLOC(fileDataSize*sizeof(unsigned char));
fread(fileData, sizeof(unsigned char), fileDataSize, rgsFile);
GuiLoadStyleFromMemory(fileData, fileDataSize);
- RL_FREE(fileData);
+ RAYGUI_FREE(fileData);
}
fclose(rgsFile);
@@ -3695,6 +4084,8 @@ void GuiLoadStyleDefault(void)
guiStyleLoaded = true;
// Initialize default LIGHT style property values
+ // WARNING: Default value are applied to all controls on set but
+ // they can be overwritten later on for every custom control
GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x838383ff);
GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0xc9c9c9ff);
GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0x686868ff);
@@ -3707,17 +4098,29 @@ void GuiLoadStyleDefault(void)
GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, 0xb5c1c2ff);
GuiSetStyle(DEFAULT, BASE_COLOR_DISABLED, 0xe6e9e9ff);
GuiSetStyle(DEFAULT, TEXT_COLOR_DISABLED, 0xaeb7b8ff);
- GuiSetStyle(DEFAULT, BORDER_WIDTH, 1); // WARNING: Some controls use other values
- GuiSetStyle(DEFAULT, TEXT_PADDING, 0); // WARNING: Some controls use other values
- GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); // WARNING: Some controls use other values
+ GuiSetStyle(DEFAULT, BORDER_WIDTH, 1);
+ GuiSetStyle(DEFAULT, TEXT_PADDING, 0);
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+
+ // Initialize default extended property values
+ // NOTE: By default, extended property values are initialized to 0
+ GuiSetStyle(DEFAULT, TEXT_SIZE, 10); // DEFAULT, shared by all controls
+ GuiSetStyle(DEFAULT, TEXT_SPACING, 1); // DEFAULT, shared by all controls
+ GuiSetStyle(DEFAULT, LINE_COLOR, 0x90abb5ff); // DEFAULT specific property
+ GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xf5f5f5ff); // DEFAULT specific property
+ GuiSetStyle(DEFAULT, TEXT_LINE_SPACING, 15); // DEFAULT, 15 pixels between lines
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); // DEFAULT, text aligned vertically to middle of text-bounds
// Initialize control-specific property values
// NOTE: Those properties are in default list but require specific values by control type
GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
GuiSetStyle(BUTTON, BORDER_WIDTH, 2);
GuiSetStyle(SLIDER, TEXT_PADDING, 4);
+ GuiSetStyle(PROGRESSBAR, TEXT_PADDING, 4);
GuiSetStyle(CHECKBOX, TEXT_PADDING, 4);
GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, TEXT_ALIGN_RIGHT);
+ GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 0);
+ GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
GuiSetStyle(TEXTBOX, TEXT_PADDING, 4);
GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
GuiSetStyle(VALUEBOX, TEXT_PADDING, 0);
@@ -3729,10 +4132,6 @@ void GuiLoadStyleDefault(void)
// Initialize extended property values
// NOTE: By default, extended property values are initialized to 0
- GuiSetStyle(DEFAULT, TEXT_SIZE, 10); // DEFAULT, shared by all controls
- GuiSetStyle(DEFAULT, TEXT_SPACING, 1); // DEFAULT, shared by all controls
- GuiSetStyle(DEFAULT, LINE_COLOR, 0x90abb5ff); // DEFAULT specific property
- GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xf5f5f5ff); // DEFAULT specific property
GuiSetStyle(TOGGLE, GROUP_PADDING, 2);
GuiSetStyle(SLIDER, SLIDER_WIDTH, 16);
GuiSetStyle(SLIDER, SLIDER_PADDING, 1);
@@ -3742,8 +4141,6 @@ void GuiLoadStyleDefault(void)
GuiSetStyle(COMBOBOX, COMBO_BUTTON_SPACING, 2);
GuiSetStyle(DROPDOWNBOX, ARROW_PADDING, 16);
GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 2);
- GuiSetStyle(TEXTBOX, TEXT_LINES_SPACING, (int)((float)GuiGetStyle(DEFAULT, TEXT_SIZE)*1.5f));
- GuiSetStyle(TEXTBOX, TEXT_INNER_PADDING, 4);
GuiSetStyle(SPINNER, SPIN_BUTTON_WIDTH, 24);
GuiSetStyle(SPINNER, SPIN_BUTTON_SPACING, 2);
GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0);
@@ -3767,12 +4164,17 @@ void GuiLoadStyleDefault(void)
{
// Unload previous font texture
UnloadTexture(guiFont.texture);
+ RL_FREE(guiFont.recs);
+ RL_FREE(guiFont.glyphs);
+ guiFont.recs = NULL;
+ guiFont.glyphs = NULL;
// Setup default raylib font
guiFont = GetFontDefault();
// NOTE: Default raylib font character 95 is a white square
Rectangle whiteChar = guiFont.recs[95];
+
// NOTE: We set 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 });
}
@@ -3901,7 +4303,7 @@ 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)
- DrawRectangle(posX + (k%RAYGUI_ICON_SIZE)*pixelSize, posY + y*pixelSize, pixelSize, pixelSize, color);
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ (float)posX + (k%RAYGUI_ICON_SIZE)*pixelSize, (float)posY + y*pixelSize, (float)pixelSize, (float)pixelSize }, 0, BLANK, color);
#endif
}
@@ -3922,7 +4324,8 @@ void GuiSetIconScale(int scale)
// Module specific Functions Definition
//----------------------------------------------------------------------------------
-// Load style from memory (binary only)
+// Load style from memory
+// WARNING: Binary files only
static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize)
{
unsigned char *fileDataPtr = (unsigned char *)fileData;
@@ -3977,7 +4380,6 @@ static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize)
{
Font font = { 0 };
int fontType = 0; // 0-Normal, 1-SDF
- Rectangle whiteRec = { 0 };
memcpy(&font.baseSize, fileDataPtr, sizeof(int));
memcpy(&font.glyphCount, fileDataPtr + 4, sizeof(int));
@@ -3985,7 +4387,8 @@ static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize)
fileDataPtr += 12;
// Load font white rectangle
- memcpy(&whiteRec, fileDataPtr, sizeof(Rectangle));
+ Rectangle fontWhiteRec = { 0 };
+ memcpy(&fontWhiteRec, fileDataPtr, sizeof(Rectangle));
fileDataPtr += 16;
// Load font image parameters
@@ -4002,7 +4405,7 @@ static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize)
memcpy(&imFont.format, fileDataPtr + 4 + 4, sizeof(int));
fileDataPtr += 12;
- if (fontImageCompSize < fontImageUncompSize)
+ if ((fontImageCompSize > 0) && (fontImageCompSize != fontImageUncompSize))
{
// Compressed font atlas image data (DEFLATE), it requires DecompressData()
int dataUncompSize = 0;
@@ -4027,34 +4430,117 @@ static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize)
if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
font.texture = LoadTextureFromImage(imFont);
- if (font.texture.id == 0) font = GetFontDefault();
RAYGUI_FREE(imFont.data);
- // Load font recs data
- font.recs = (Rectangle *)RAYGUI_CALLOC(font.glyphCount, sizeof(Rectangle));
- for (int i = 0; i < font.glyphCount; i++)
+ // Validate font atlas texture was loaded correctly
+ if (font.texture.id != 0)
{
- memcpy(&font.recs[i], fileDataPtr, sizeof(Rectangle));
- fileDataPtr += sizeof(Rectangle);
- }
+ // Load font recs data
+ int recsDataSize = font.glyphCount*sizeof(Rectangle);
+ int recsDataCompressedSize = 0;
- // Load font chars info data
- font.glyphs = (GlyphInfo *)RAYGUI_CALLOC(font.glyphCount, sizeof(GlyphInfo));
- for (int i = 0; i < font.glyphCount; i++)
- {
- memcpy(&font.glyphs[i].value, fileDataPtr, sizeof(int));
- memcpy(&font.glyphs[i].offsetX, fileDataPtr + 4, sizeof(int));
- memcpy(&font.glyphs[i].offsetY, fileDataPtr + 8, sizeof(int));
- memcpy(&font.glyphs[i].advanceX, fileDataPtr + 12, sizeof(int));
- fileDataPtr += 16;
+ // WARNING: Version 400 adds the compression size parameter
+ if (version >= 400)
+ {
+ // RGS files version 400 support compressed recs data
+ memcpy(&recsDataCompressedSize, fileDataPtr, sizeof(int));
+ fileDataPtr += sizeof(int);
+ }
+
+ if ((recsDataCompressedSize > 0) && (recsDataCompressedSize != recsDataSize))
+ {
+ // Recs data is compressed, uncompress it
+ unsigned char *recsDataCompressed = (unsigned char *)RAYGUI_MALLOC(recsDataCompressedSize);
+
+ memcpy(recsDataCompressed, fileDataPtr, recsDataCompressedSize);
+ fileDataPtr += recsDataCompressedSize;
+
+ int recsDataUncompSize = 0;
+ font.recs = (Rectangle *)DecompressData(recsDataCompressed, recsDataCompressedSize, &recsDataUncompSize);
+
+ // Security check, data uncompressed size must match the expected original data size
+ if (recsDataUncompSize != recsDataSize) RAYGUI_LOG("WARNING: Uncompressed font recs data could be corrupted");
+
+ RAYGUI_FREE(recsDataCompressed);
+ }
+ else
+ {
+ // Recs data is uncompressed
+ font.recs = (Rectangle *)RAYGUI_CALLOC(font.glyphCount, sizeof(Rectangle));
+ for (int i = 0; i < font.glyphCount; i++)
+ {
+ memcpy(&font.recs[i], fileDataPtr, sizeof(Rectangle));
+ fileDataPtr += sizeof(Rectangle);
+ }
+ }
+
+ // Load font glyphs info data
+ int glyphsDataSize = font.glyphCount*16; // 16 bytes data per glyph
+ int glyphsDataCompressedSize = 0;
+
+ // WARNING: Version 400 adds the compression size parameter
+ if (version >= 400)
+ {
+ // RGS files version 400 support compressed glyphs data
+ memcpy(&glyphsDataCompressedSize, fileDataPtr, sizeof(int));
+ fileDataPtr += sizeof(int);
+ }
+
+ // Allocate required glyphs space to fill with data
+ font.glyphs = (GlyphInfo *)RAYGUI_CALLOC(font.glyphCount, sizeof(GlyphInfo));
+
+ if ((glyphsDataCompressedSize > 0) && (glyphsDataCompressedSize != glyphsDataSize))
+ {
+ // Glyphs data is compressed, uncompress it
+ unsigned char *glypsDataCompressed = (unsigned char *)RAYGUI_MALLOC(glyphsDataCompressedSize);
+
+ memcpy(glypsDataCompressed, fileDataPtr, glyphsDataCompressedSize);
+ fileDataPtr += glyphsDataCompressedSize;
+
+ int glyphsDataUncompSize = 0;
+ unsigned char *glyphsDataUncomp = DecompressData(glypsDataCompressed, glyphsDataCompressedSize, &glyphsDataUncompSize);
+
+ // Security check, data uncompressed size must match the expected original data size
+ if (glyphsDataUncompSize != glyphsDataSize) RAYGUI_LOG("WARNING: Uncompressed font glyphs data could be corrupted");
+
+ unsigned char *glyphsDataUncompPtr = glyphsDataUncomp;
+
+ for (int i = 0; i < font.glyphCount; i++)
+ {
+ memcpy(&font.glyphs[i].value, glyphsDataUncompPtr, sizeof(int));
+ memcpy(&font.glyphs[i].offsetX, glyphsDataUncompPtr + 4, sizeof(int));
+ memcpy(&font.glyphs[i].offsetY, glyphsDataUncompPtr + 8, sizeof(int));
+ memcpy(&font.glyphs[i].advanceX, glyphsDataUncompPtr + 12, sizeof(int));
+ glyphsDataUncompPtr += 16;
+ }
+
+ RAYGUI_FREE(glypsDataCompressed);
+ RAYGUI_FREE(glyphsDataUncomp);
+ }
+ else
+ {
+ // Glyphs data is uncompressed
+ for (int i = 0; i < font.glyphCount; i++)
+ {
+ memcpy(&font.glyphs[i].value, fileDataPtr, sizeof(int));
+ memcpy(&font.glyphs[i].offsetX, fileDataPtr + 4, sizeof(int));
+ memcpy(&font.glyphs[i].offsetY, fileDataPtr + 8, sizeof(int));
+ memcpy(&font.glyphs[i].advanceX, fileDataPtr + 12, sizeof(int));
+ fileDataPtr += 16;
+ }
+ }
}
+ else font = GetFontDefault(); // Fallback in case of errors loading font atlas texture
GuiSetFont(font);
// Set font texture source rectangle to be used as white texture to draw shapes
- // NOTE: This way, all gui can be draw using a single draw call
- if ((whiteRec.width != 0) && (whiteRec.height != 0)) SetShapesTexture(font.texture, whiteRec);
+ // NOTE: It makes possible to draw shapes and text (full UI) in a single draw call
+ if ((fontWhiteRec.x > 0) &&
+ (fontWhiteRec.y > 0) &&
+ (fontWhiteRec.width > 0) &&
+ (fontWhiteRec.height > 0)) SetShapesTexture(font.texture, fontWhiteRec);
}
#endif
}
@@ -4109,10 +4595,10 @@ static int GetTextWidth(const char *text)
int codepoint = GetCodepointNext(&text[i], &codepointSize);
int codepointIndex = GetGlyphIndex(guiFont, codepoint);
- if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
- else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor + GuiGetStyle(DEFAULT, TEXT_SPACING));
+ if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor);
+ else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor);
- textSize.x += glyphWidth;
+ textSize.x += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
}
}
@@ -4130,15 +4616,23 @@ static Rectangle GetTextBounds(int control, Rectangle bounds)
textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH);
textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH) + GuiGetStyle(control, TEXT_PADDING);
textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING);
- textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING);
+ textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); // NOTE: Text is processed line per line!
- // Consider TEXT_PADDING properly, depends on control type and TEXT_ALIGNMENT
- // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW (scrollbar?)
- // More special cases (label on side): CHECKBOX, SLIDER, VALUEBOX, SPINNER
+ // Depending on control, TEXT_PADDING and TEXT_ALIGNMENT properties could affect the text-bounds
switch (control)
{
+ case COMBOBOX:
+ case DROPDOWNBOX:
+ case LISTVIEW:
+ // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW
+ case SLIDER:
+ case CHECKBOX:
+ case VALUEBOX:
+ case SPINNER:
+ // TODO: More special cases (label on side): SLIDER, CHECKBOX, VALUEBOX, SPINNER
default:
{
+ // TODO: WARNING: TEXT_ALIGNMENT is already considered in GuiDrawText()
if (GuiGetStyle(control, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) textBounds.x -= GuiGetStyle(control, TEXT_PADDING);
else textBounds.x += GuiGetStyle(control, TEXT_PADDING);
}
@@ -4192,13 +4686,13 @@ const char **GetTextLines(const char *text, int *count)
lines[0] = text;
int len = 0;
*count = 1;
- int lineSize = 0; // Stores current line size, not returned
+ //int lineSize = 0; // Stores current line size, not returned
for (int i = 0, k = 0; (i < textSize) && (*count < RAYGUI_MAX_TEXT_LINES); i++)
{
if (text[i] == '\n')
{
- lineSize = len;
+ //lineSize = len;
k++;
lines[k] = &text[i + 1]; // WARNING: next value is valid?
len = 0;
@@ -4212,8 +4706,37 @@ const char **GetTextLines(const char *text, int *count)
return lines;
}
+// Get text width to next space for provided string
+static float GetNextSpaceWidth(const char *text, int *nextSpaceIndex)
+{
+ float width = 0;
+ int codepointByteCount = 0;
+ int codepoint = 0;
+ int index = 0;
+ float glyphWidth = 0;
+ float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize;
+
+ for (int i = 0; text[i] != '\0'; i++)
+ {
+ if (text[i] != ' ')
+ {
+ codepoint = GetCodepoint(&text[i], &codepointByteCount);
+ index = GetGlyphIndex(guiFont, codepoint);
+ glyphWidth = (guiFont.glyphs[index].advanceX == 0)? guiFont.recs[index].width*scaleFactor : guiFont.glyphs[index].advanceX*scaleFactor;
+ width += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
+ }
+ else
+ {
+ *nextSpaceIndex = i;
+ break;
+ }
+ }
+
+ return width;
+}
+
// Gui draw text using default font
-static void GuiDrawText(const char *text, Rectangle bounds, int alignment, Color tint)
+static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint)
{
#define TEXT_VALIGN_PIXEL_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect
@@ -4221,119 +4744,172 @@ static void GuiDrawText(const char *text, Rectangle bounds, int alignment, Color
#define ICON_TEXT_PADDING 4
#endif
- int alignmentVertical = GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT_VERTICAL);
+ if ((text == NULL) || (text[0] == '\0')) return; // Security check
- // We process the text lines one by one
- if ((text != NULL) && (text[0] != '\0'))
- {
- // Get text lines ('\n' delimiter) to process lines individually
- // NOTE: We can't use GuiTextSplit() because it can be already used before calling
- // GuiDrawText() and static buffer would be overriden :(
- int lineCount = 0;
- const char **lines = GetTextLines(text, &lineCount);
+ // PROCEDURE:
+ // - Text is processed line per line
+ // - For every line, horizontal alignment is defined
+ // - For all text, vertical alignment is defined (multiline text only)
+ // - For every line, wordwrap mode is checked (useful for GuitextBox(), read-only)
- //Rectangle textBounds = GetTextBounds(LABEL, bounds);
- float totalHeight = (float)(lineCount*GuiGetStyle(DEFAULT, TEXT_SIZE) + (lineCount - 1)*GuiGetStyle(DEFAULT, TEXT_SIZE)/2);
- float posOffsetY = 0;
+ // Get text lines (using '\n' as delimiter) to be processed individually
+ // WARNING: We can't use GuiTextSplit() function because it can be already used
+ // before the GuiDrawText() call and its buffer is static, it would be overriden :(
+ int lineCount = 0;
+ const char **lines = GetTextLines(text, &lineCount);
- for (int i = 0; i < lineCount; i++)
- {
- int iconId = 0;
- lines[i] = GetTextIcon(lines[i], &iconId); // Check text for icon and move cursor
+ // Text style variables
+ //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT);
+ int alignmentVertical = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL);
+ int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); // Wrap-mode only available in read-only mode, no for text editing
- // Get text position depending on alignment and iconId
- //---------------------------------------------------------------------------------
- Vector2 position = { bounds.x, bounds.y };
+ // TODO: WARNING: This totalHeight is not valid for vertical alignment in case of word-wrap
+ float totalHeight = (float)(lineCount*GuiGetStyle(DEFAULT, TEXT_SIZE) + (lineCount - 1)*GuiGetStyle(DEFAULT, TEXT_SIZE)/2);
+ float posOffsetY = 0.0f;
- // NOTE: We get text size after icon has been processed
- // WARNING: GetTextWidth() also processes text icon to get width! -> Really needed?
- int textSizeX = GetTextWidth(lines[i]);
+ for (int i = 0; i < lineCount; i++)
+ {
+ int iconId = 0;
+ lines[i] = GetTextIcon(lines[i], &iconId); // Check text for icon and move cursor
- // If text requires an icon, add size to measure
- if (iconId >= 0)
- {
- textSizeX += RAYGUI_ICON_SIZE*guiIconScale;
+ // Get text position depending on alignment and iconId
+ //---------------------------------------------------------------------------------
+ Vector2 textBoundsPosition = { textBounds.x, textBounds.y };
- // WARNING: If only icon provided, text could be pointing to EOF character: '\0'
- if ((lines[i] != NULL) && (lines[i][0] != '\0')) textSizeX += ICON_TEXT_PADDING;
- }
+ // NOTE: We get text size after icon has been processed
+ // WARNING: GetTextWidth() also processes text icon to get width! -> Really needed?
+ int textSizeX = GetTextWidth(lines[i]);
- // Check guiTextAlign global variables
- switch (alignment)
- {
- case TEXT_ALIGN_LEFT: position.x = bounds.x; break;
- case TEXT_ALIGN_CENTER: position.x = bounds.x + bounds.width/2 - textSizeX/2; break;
- case TEXT_ALIGN_RIGHT: position.x = bounds.x + bounds.width - textSizeX; break;
- default: break;
- }
+ // If text requires an icon, add size to measure
+ if (iconId >= 0)
+ {
+ textSizeX += RAYGUI_ICON_SIZE*guiIconScale;
- switch (alignmentVertical)
- {
- case 0: position.y = bounds.y + posOffsetY + bounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(bounds.height); break; // CENTERED
- case 1: position.y = bounds.y + posOffsetY; break; // UP
- case 2: position.y = bounds.y + posOffsetY + bounds.height - totalHeight + TEXT_VALIGN_PIXEL_OFFSET(bounds.height); break; // DOWN
- default: break;
- }
+ // WARNING: If only icon provided, text could be pointing to EOF character: '\0'
+#if !defined(RAYGUI_NO_ICONS)
+ if ((lines[i] != NULL) && (lines[i][0] != '\0')) textSizeX += ICON_TEXT_PADDING;
+#endif
+ }
- // NOTE: Make sure we get pixel-perfect coordinates,
- // In case of decimals we got weird text positioning
- position.x = (float)((int)position.x);
- position.y = (float)((int)position.y);
- //---------------------------------------------------------------------------------
+ // Check guiTextAlign global variables
+ switch (alignment)
+ {
+ case TEXT_ALIGN_LEFT: textBoundsPosition.x = textBounds.x; break;
+ case TEXT_ALIGN_CENTER: textBoundsPosition.x = textBounds.x + textBounds.width/2 - textSizeX/2; break;
+ case TEXT_ALIGN_RIGHT: textBoundsPosition.x = textBounds.x + textBounds.width - textSizeX; break;
+ default: break;
+ }
- // Draw text (with icon if available)
- //---------------------------------------------------------------------------------
+ switch (alignmentVertical)
+ {
+ // Only valid in case of wordWrap = 0;
+ case TEXT_ALIGN_TOP: textBoundsPosition.y = textBounds.y + posOffsetY; break;
+ case TEXT_ALIGN_MIDDLE: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break;
+ case TEXT_ALIGN_BOTTOM: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height - totalHeight + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break;
+ default: break;
+ }
+
+ // NOTE: Make sure we get pixel-perfect coordinates,
+ // In case of decimals we got weird text positioning
+ textBoundsPosition.x = (float)((int)textBoundsPosition.x);
+ textBoundsPosition.y = (float)((int)textBoundsPosition.y);
+ //---------------------------------------------------------------------------------
+
+ // Draw text (with icon if available)
+ //---------------------------------------------------------------------------------
#if !defined(RAYGUI_NO_ICONS)
- if (iconId >= 0)
- {
- // NOTE: We consider icon height, probably different than text size
- GuiDrawIcon(iconId, (int)position.x, (int)(bounds.y + bounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(bounds.height)), guiIconScale, tint);
- position.x += (RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);
- }
+ if (iconId >= 0)
+ {
+ // NOTE: We consider icon height, probably different than text size
+ GuiDrawIcon(iconId, (int)textBoundsPosition.x, (int)(textBounds.y + textBounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height)), guiIconScale, tint);
+ textBoundsPosition.x += (RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);
+ }
#endif
- //DrawTextEx(guiFont, text, position, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING), tint);
+ // Get size in bytes of text,
+ // considering end of line and line break
+ int lineSize = 0;
+ for (int c = 0; (lines[i][c] != '\0') && (lines[i][c] != '\n') && (lines[i][c] != '\r'); c++, lineSize++){ }
+ float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize;
+
+ int textOffsetY = 0;
+ float textOffsetX = 0.0f;
+ float glyphWidth = 0;
+ for (int c = 0, codepointSize = 0; c < lineSize; c += codepointSize)
+ {
+ int codepoint = GetCodepointNext(&lines[i][c], &codepointSize);
+ int index = GetGlyphIndex(guiFont, codepoint);
- // Get size in bytes of text,
- // considering end of line and line break
- int size = 0;
- for (int c = 0; (lines[i][c] != '\0') && (lines[i][c] != '\n'); c++, size++){ }
- float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize;
+ // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
+ // but we need to draw all of the bad bytes using the '?' symbol moving one byte
+ if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size
- int textOffsetY = 0;
- float textOffsetX = 0.0f;
- for (int c = 0, codepointSize = 0; c < size; c += codepointSize)
+ // Wrap mode text measuring to space to validate if it can be drawn or
+ // a new line is required
+ if (wrapMode == TEXT_WRAP_CHAR)
{
- int codepoint = GetCodepointNext(&lines[i][c], &codepointSize);
- int index = GetGlyphIndex(guiFont, codepoint);
+ // Get glyph width to check if it goes out of bounds
+ if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor);
+ else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor;
- // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
- // but we need to draw all of the bad bytes using the '?' symbol moving one byte
- if (codepoint == 0x3f) codepointSize = 1;
+ // Jump to next line if current character reach end of the box limits
+ if ((textOffsetX + glyphWidth) > textBounds.width)
+ {
+ textOffsetX = 0.0f;
+ textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);
+ }
+ }
+ else if (wrapMode == TEXT_WRAP_WORD)
+ {
+ // Get width to next space in line
+ int nextSpaceIndex = 0;
+ float nextSpaceWidth = GetNextSpaceWidth(lines[i] + c, &nextSpaceIndex);
- if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint
- else
+ if ((textOffsetX + nextSpaceWidth) > textBounds.width)
+ {
+ textOffsetX = 0.0f;
+ textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);
+ }
+
+ // TODO: Consider case: (nextSpaceWidth >= textBounds.width)
+ }
+
+ if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint
+ else
+ {
+ // TODO: There are multiple types of spaces in Unicode,
+ // maybe it's a good idea to add support for more: http://jkorpela.fi/chars/spaces.html
+ if ((codepoint != ' ') && (codepoint != '\t')) // Do not draw codepoints with no glyph
{
- if ((codepoint != ' ') && (codepoint != '\t'))
+ if (wrapMode == TEXT_WRAP_NONE)
{
- // Draw only required text glyphs fitting the bounds.width
- if (textOffsetX < (bounds.width - guiFont.recs[index].width))
+ // Draw only required text glyphs fitting the textBounds.width
+ if (textOffsetX <= (textBounds.width - glyphWidth))
{
- DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ position.x + textOffsetX, position.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), tint);
+ DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
+ }
+ }
+ else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD))
+ {
+ // Draw only glyphs inside the bounds
+ if ((textBoundsPosition.y + textOffsetY) <= (textBounds.y + textBounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE)))
+ {
+ DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
}
}
-
- if (guiFont.glyphs[index].advanceX == 0) textOffsetX += ((float)guiFont.recs[index].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
- else textOffsetX += ((float)guiFont.glyphs[index].advanceX*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
}
- }
- // TODO: Allow users to set line spacing for text: GuiSetStyle(TEXTBOX, TEXT_LINES_SPACING, x)
- posOffsetY += (float)GuiGetStyle(DEFAULT, TEXT_SIZE)*1.5f;
- //---------------------------------------------------------------------------------
+ if (guiFont.glyphs[index].advanceX == 0) textOffsetX += ((float)guiFont.recs[index].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
+ else textOffsetX += ((float)guiFont.glyphs[index].advanceX*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
+ }
}
+
+ if (wrapMode == TEXT_WRAP_NONE) posOffsetY += (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);
+ else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) posOffsetY += (textOffsetY + (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING));
+ //---------------------------------------------------------------------------------
}
+
#if defined(RAYGUI_DEBUG_TEXT_BOUNDS)
- GuiDrawRectangle(bounds, 0, WHITE, Fade(RED, 0.4f));
+ GuiDrawRectangle(textBounds, 0, WHITE, Fade(BLUE, 0.4f));
#endif
}
@@ -4343,17 +4919,21 @@ static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor,
if (color.a > 0)
{
// Draw rectangle filled with color
- DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, color);
+ DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, GuiFade(color, guiAlpha));
}
if (borderWidth > 0)
{
// Draw rectangle border lines with color
- DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, borderWidth, borderColor);
- DrawRectangle((int)rec.x, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, borderColor);
- DrawRectangle((int)rec.x + (int)rec.width - borderWidth, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, borderColor);
- DrawRectangle((int)rec.x, (int)rec.y + (int)rec.height - borderWidth, (int)rec.width, borderWidth, borderColor);
+ DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha));
+ DrawRectangle((int)rec.x, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha));
+ DrawRectangle((int)rec.x + (int)rec.width - borderWidth, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha));
+ DrawRectangle((int)rec.x, (int)rec.y + (int)rec.height - borderWidth, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha));
}
+
+#if defined(RAYGUI_DEBUG_RECS_BOUNDS)
+ DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, Fade(RED, 0.4f));
+#endif
}
// Draw tooltip using control bounds
@@ -4629,12 +5209,16 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
if (guiSliderDragging) // Keep dragging outside of bounds
{
- if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) &&
+ !CheckCollisionPointRec(mousePoint, arrowUpLeft) &&
+ !CheckCollisionPointRec(mousePoint, arrowDownRight))
{
if (CHECK_BOUNDS_ID(bounds, guiSliderActive))
{
- if (isVertical) value += (int)(GetMouseDelta().y/(scrollbar.height - slider.height)*valueRange);
- else value += (int)(GetMouseDelta().x/(scrollbar.width - slider.width)*valueRange);
+ state = STATE_PRESSED;
+
+ if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue);
+ else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue);
}
}
else
@@ -4646,8 +5230,6 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
else if (CheckCollisionPointRec(mousePoint, bounds))
{
state = STATE_FOCUSED;
- guiSliderDragging = true;
- guiSliderActive = bounds; // Store bounds as an identifier when dragging starts
// Handle mouse wheel
int wheel = (int)GetMouseWheelMove();
@@ -4656,6 +5238,9 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
// Handle mouse button down
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
+ guiSliderDragging = true;
+ guiSliderActive = bounds; // Store bounds as an identifier when dragging starts
+
// Check arrows click
if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
else if (CheckCollisionPointRec(mousePoint, arrowDownRight)) value += valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
@@ -4668,11 +5253,6 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
state = STATE_PRESSED;
}
- else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
- {
- if (isVertical) value += (int)(GetMouseDelta().y/(scrollbar.height - slider.height)*valueRange);
- else value += (int)(GetMouseDelta().x/(scrollbar.width - slider.width)*valueRange);
- }
// Keyboard control on mouse hover scrollbar
/*
@@ -4697,10 +5277,10 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
// Draw control
//--------------------------------------------------------------------
- GuiDrawRectangle(bounds, GuiGetStyle(SCROLLBAR, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha), Fade(GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED)), guiAlpha)); // Draw the background
+ GuiDrawRectangle(bounds, GuiGetStyle(SCROLLBAR, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED))); // Draw the background
- GuiDrawRectangle(scrollbar, 0, BLANK, Fade(GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL)), guiAlpha)); // Draw the scrollbar active area background
- GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, BORDER + state*3)), guiAlpha)); // Draw the slider bar
+ GuiDrawRectangle(scrollbar, 0, BLANK, GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL))); // Draw the scrollbar active area background
+ GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BORDER + state*3))); // Draw the slider bar
// Draw arrows (using icon if available)
if (GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE))
@@ -4708,17 +5288,17 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
#if defined(RAYGUI_NO_ICONS)
GuiDrawText(isVertical? "^" : "<",
RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
- TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha));
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));
GuiDrawText(isVertical? "v" : ">",
RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
- TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha));
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));
#else
GuiDrawText(isVertical? "#121#" : "#118#",
RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
- TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3)), guiAlpha)); // ICON_ARROW_UP_FILL / ICON_ARROW_LEFT_FILL
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_UP_FILL / ICON_ARROW_LEFT_FILL
GuiDrawText(isVertical? "#120#" : "#119#",
RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
- TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3)), guiAlpha)); // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL
#endif
}
//--------------------------------------------------------------------
@@ -4726,6 +5306,18 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
return value;
}
+// Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
+// WARNING: It multiplies current alpha by alpha scale factor
+static Color GuiFade(Color color, float alpha)
+{
+ if (alpha < 0.0f) alpha = 0.0f;
+ else if (alpha > 1.0f) alpha = 1.0f;
+
+ Color result = { color.r, color.g, color.b, (unsigned char)(color.a*alpha) };
+
+ return result;
+}
+
#if defined(RAYGUI_STANDALONE)
// Returns a Color struct from hexadecimal value
static Color GetColor(int hexValue)
@@ -4757,17 +5349,6 @@ static bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
return collision;
}
-// Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
-static Color Fade(Color color, float alpha)
-{
- if (alpha < 0.0f) alpha = 0.0f;
- else if (alpha > 1.0f) alpha = 1.0f;
-
- Color result = { color.r, color.g, color.b, (unsigned char)(255.0f*alpha) };
-
- return result;
-}
-
// Formatting of text with variables to 'embed'
static const char *TextFormat(const char *text, ...)
{