2023-10-04 16:07:59 +02:00
/*******************************************************************************************
*
* 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
* available as a standalone library , as long as input and drawing functions are provided .
*
* FEATURES :
* - Immediate - mode gui , minimal retained data
* - + 25 controls provided ( basic and advanced )
* - Styling system for colors , font and metrics
* - 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 :
* - Better standalone mode API for easy plug of custom backends
* - Externalize required inputs , allow user easier customization
*
* LIMITATIONS :
* - 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
* - GroupBox - - > Line
* - Line
* - Panel - - > StatusBar
* - ScrollPanel - - > StatusBar
* - TabBar - - > Button
*
* # Basic Controls
* - Label
* - LabelButton - - > Label
* - Button
* - Toggle
* - ToggleGroup - - > Toggle
* - ToggleSlider
* - CheckBox
* - ComboBox
* - DropdownBox
* - TextBox
* - ValueBox - - > TextBox
* - Spinner - - > Button , ValueBox
* - Slider
* - SliderBar - - > Slider
* - ProgressBar
* - StatusBar
* - DummyRec
* - Grid
*
* # Advance Controls
* - ListView
* - ColorPicker - - > ColorPanel , ColorBarHue
* - MessageBox - - > Window , Label , Button
* - TextInputBox - - > Window , Label , TextBox , Button
*
* It also provides a set of functions for styling the controls based on its properties ( size , color ) .
*
*
* RAYGUI STYLE ( guiStyle ) :
* raygui uses a global data array for all gui style properties ( allocated on data segment by default ) ,
* when a new style is loaded , it is loaded over the global style . . . but a default gui style could always be
* recovered with GuiLoadStyleDefault ( ) function , that overwrites the current style to the default one
*
* The global style array size is fixed and depends on the number of controls and properties :
*
* static unsigned int guiStyle [ RAYGUI_MAX_CONTROLS * ( RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED ) ] ;
*
* guiStyle size is by default : 16 * ( 16 + 8 ) = 384 * 4 = 1536 bytes = 1.5 KB
*
* Note that the first set of BASE properties ( by default guiStyle [ 0. .15 ] ) belong to the generic style
* used for all controls , when any of those base values is set , it is automatically populated to all
* controls , so , specific control values overwriting generic style should be set after base values .
*
* After the first BASE set we have the EXTENDED properties ( by default guiStyle [ 16. .23 ] ) , those
* properties are actually common to all controls and can not be overwritten individually ( like BASE ones )
* Some of those properties are : TEXT_SIZE , TEXT_SPACING , LINE_COLOR , BACKGROUND_COLOR
*
* Custom control properties can be defined using the EXTENDED properties for each independent control .
*
* TOOL : rGuiStyler is a visual tool to customize raygui style : github . com / raysan5 / rguistyler
*
*
* RAYGUI ICONS ( guiIcons ) :
* raygui could use a global array containing icons data ( allocated on data segment by default ) ,
* a custom icons set could be loaded over this array using GuiLoadIcons ( ) , but loaded icons set
* must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS will be loaded
*
* Every icon is codified in binary form , using 1 bit per pixel , so , every 16 x16 icon
* requires 8 integers ( 16 * 16 / 32 ) to be stored in memory .
*
* When the icon is draw , actually one quad per pixel is drawn if the bit for that pixel is set .
*
* The global icons array size is fixed and depends on the number of icons and size :
*
* static unsigned int guiIcons [ RAYGUI_ICON_MAX_ICONS * RAYGUI_ICON_DATA_ELEMENTS ] ;
*
* guiIcons size is by default : 256 * ( 16 * 16 / 32 ) = 2048 * 4 = 8192 bytes = 8 KB
*
* TOOL : rGuiIcons is a visual tool to customize / create raygui icons : github . com / raysan5 / rguiicons
*
* RAYGUI LAYOUT :
* raygui currently does not provide an auto - layout mechanism like other libraries ,
* layouts must be defined manually on controls drawing , providing the right bounds Rectangle for it .
*
* TOOL : rGuiLayout is a visual tool to create raygui layouts : github . com / raysan5 / rguilayout
*
* CONFIGURATION :
* # define RAYGUI_IMPLEMENTATION
* Generates the implementation of the library into the included file .
* If not defined , the library is in header only mode and can be included in other headers
* or source files without problems . But only ONE file should hold the implementation .
*
* # define RAYGUI_STANDALONE
* Avoid raylib . h header inclusion in this file . Data types defined on raylib are defined
* internally in the library and input management and drawing functions must be provided by
* the user ( check library implementation for further details ) .
*
* # define RAYGUI_NO_ICONS
* Avoid including embedded ricons data ( 256 icons , 16 x16 pixels , 1 - bit per pixel , 2 KB )
*
* # define RAYGUI_CUSTOM_ICONS
* 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 ( 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
* REDESIGNED : GuiSlider ( ) , get parameters by reference and return result value
* REDESIGNED : GuiSliderBar ( ) , get parameters by reference and return result value
* REDESIGNED : GuiProgressBar ( ) , get parameters by reference and return result value
* REDESIGNED : GuiListView ( ) , get parameters by reference and return result value
* REDESIGNED : GuiColorPicker ( ) , get parameters by reference and return result value
* REDESIGNED : GuiColorPanel ( ) , get parameters by reference and return result value
* REDESIGNED : GuiColorBarAlpha ( ) , get parameters by reference and return result value
* REDESIGNED : GuiColorBarHue ( ) , get parameters by reference and return result value
* REDESIGNED : GuiGrid ( ) , get parameters by reference and return result value
* 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 )
* REVIEWED : GuiScrollBar ( ) horizontal movement key
* REVIEWED : GuiTextBox ( ) crash on cursor movement
* REVIEWED : GuiTextBox ( ) , additional inputs support
* REVIEWED : GuiLabelButton ( ) , avoid text cut
* REVIEWED : GuiTextInputBox ( ) , password input
* REVIEWED : Local GetCodepointNext ( ) , aligned with raylib
* REDESIGNED : GuiSlider * ( ) / GuiScrollBar ( ) to support out - of - bounds
*
* 3.5 ( 20 - Apr - 2023 ) ADDED : GuiTabBar ( ) , based on GuiToggle ( )
* ADDED : Helper functions to split text in separate lines
* ADDED : Multiple new icons , useful for code editing tools
* REMOVED : Unneeded icon editing functions
* REMOVED : GuiTextBoxMulti ( ) , very limited and broken
* REMOVED : MeasureTextEx ( ) dependency , logic directly implemented
* REMOVED : DrawTextEx ( ) dependency , logic directly implemented
* REVIEWED : GuiScrollBar ( ) , improve mouse - click behaviour
* REVIEWED : Library header info , more info , better organized
* REDESIGNED : GuiTextBox ( ) to support cursor movement
* REDESIGNED : GuiDrawText ( ) to divide drawing by lines
*
* 3.2 ( 22 - May - 2022 ) RENAMED : Some enum values , for unification , avoiding prefixes
* REMOVED : GuiScrollBar ( ) , only internal
* REDESIGNED : GuiPanel ( ) to support text parameter
* REDESIGNED : GuiScrollPanel ( ) to support text parameter
* REDESIGNED : GuiColorPicker ( ) to support text parameter
* REDESIGNED : GuiColorPanel ( ) to support text parameter
* REDESIGNED : GuiColorBarAlpha ( ) to support text parameter
* REDESIGNED : GuiColorBarHue ( ) to support text parameter
* REDESIGNED : GuiTextInputBox ( ) to support password
*
* 3.1 ( 12 - Jan - 2022 ) REVIEWED : Default style for consistency ( aligned with rGuiLayout v2 .5 tool )
* REVIEWED : GuiLoadStyle ( ) to support compressed font atlas image data and unload previous textures
* REVIEWED : External icons usage logic
* REVIEWED : GuiLine ( ) for centered alignment when including text
* RENAMED : Multiple controls properties definitions to prepend RAYGUI_
* RENAMED : RICON_ references to RAYGUI_ICON_ for library consistency
* Projects updated and multiple tweaks
*
* 3.0 ( 04 - Nov - 2021 ) Integrated ricons data to avoid external file
* REDESIGNED : GuiTextBoxMulti ( )
* REMOVED : GuiImageButton * ( )
* Multiple minor tweaks and bugs corrected
*
* 2.9 ( 17 - Mar - 2021 ) REMOVED : Tooltip API
* 2.8 ( 03 - May - 2020 ) Centralized rectangles drawing to GuiDrawRectangle ( )
* 2.7 ( 20 - Feb - 2020 ) ADDED : Possible tooltips API
* 2.6 ( 09 - Sep - 2019 ) ADDED : GuiTextInputBox ( )
* REDESIGNED : GuiListView * ( ) , GuiDropdownBox ( ) , GuiSlider * ( ) , GuiProgressBar ( ) , GuiMessageBox ( )
* REVIEWED : GuiTextBox ( ) , GuiSpinner ( ) , GuiValueBox ( ) , GuiLoadStyle ( )
* Replaced property INNER_PADDING by TEXT_PADDING , renamed some properties
* ADDED : 8 new custom styles ready to use
* Multiple minor tweaks and bugs corrected
*
* 2.5 ( 28 - May - 2019 ) Implemented extended GuiTextBox ( ) , GuiValueBox ( ) , GuiSpinner ( )
* 2.3 ( 29 - Apr - 2019 ) ADDED : rIcons auxiliar library and support for it , multiple controls reviewed
* Refactor all controls drawing mechanism to use control state
* 2.2 ( 05 - Feb - 2019 ) ADDED : GuiScrollBar ( ) , GuiScrollPanel ( ) , reviewed GuiListView ( ) , removed Gui * Ex ( ) controls
* 2.1 ( 26 - Dec - 2018 ) REDESIGNED : GuiCheckBox ( ) , GuiComboBox ( ) , GuiDropdownBox ( ) , GuiToggleGroup ( ) > Use combined text string
* REDESIGNED : Style system ( breaking change )
* 2.0 ( 08 - Nov - 2018 ) ADDED : Support controls guiLock and custom fonts
* REVIEWED : GuiComboBox ( ) , GuiListView ( ) . . .
* 1.9 ( 09 - Oct - 2018 ) REVIEWED : GuiGrid ( ) , GuiTextBox ( ) , GuiTextBoxMulti ( ) , GuiValueBox ( ) . . .
* 1.8 ( 01 - May - 2018 ) Lot of rework and redesign to align with rGuiStyler and rGuiLayout
* 1.5 ( 21 - Jun - 2017 ) Working in an improved styles system
* 1.4 ( 15 - Jun - 2017 ) Rewritten all GUI functions ( removed useless ones )
* 1.3 ( 12 - Jun - 2017 ) Complete redesign of style system
* 1.1 ( 01 - Jun - 2017 ) Complete review of the library
* 1.0 ( 07 - Jun - 2016 ) Converted to header - only by Ramon Santamaria .
* 0.9 ( 07 - Mar - 2016 ) Reviewed and tested by Albert Martos , Ian Eito , Sergio Martinez and Ramon Santamaria .
* 0.8 ( 27 - Aug - 2015 ) Initial release . Implemented by Kevin Gato , Daniel Nicolás and Ramon Santamaria .
*
* DEPENDENCIES :
* 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 )
* 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 )
* Daniel Nicolas : Initial implementation of basic components ( 2014 )
*
*
* LICENSE : zlib / libpng
*
* Copyright ( c ) 2014 - 2023 Ramon Santamaria ( @ raysan5 )
*
* This software is provided " as-is " , without any express or implied warranty . In no event
* will the authors be held liable for any damages arising from the use of this software .
*
* Permission is granted to anyone to use this software for any purpose , including commercial
* applications , and to alter it and redistribute it freely , subject to the following restrictions :
*
* 1. The origin of this software must not be misrepresented ; you must not claim that you
* wrote the original software . If you use this software in a product , an acknowledgment
* in the product documentation would be appreciated but is not required .
*
* 2. Altered source versions must be plainly marked as such , and must not be misrepresented
* as being the original software .
*
* 3. This notice may not be removed or altered from any source distribution .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef RAYGUI_H
# define RAYGUI_H
# define RAYGUI_VERSION_MAJOR 4
# define RAYGUI_VERSION_MINOR 0
# define RAYGUI_VERSION_PATCH 0
# define RAYGUI_VERSION "4.0"
# if !defined(RAYGUI_STANDALONE)
# include "raylib.h"
# endif
// Function specifiers in case library is build/used as a shared library (Windows)
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
# if defined(_WIN32)
# if defined(BUILD_LIBTYPE_SHARED)
# define RAYGUIAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
# elif defined(USE_LIBTYPE_SHARED)
# define RAYGUIAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
# endif
# endif
// Function specifiers definition
# ifndef RAYGUIAPI
# define RAYGUIAPI // Functions defined as 'extern' by default (implicit specifiers)
# endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// Allow custom memory allocators
# ifndef RAYGUI_MALLOC
# define RAYGUI_MALLOC(sz) malloc(sz)
# endif
# ifndef RAYGUI_CALLOC
# define RAYGUI_CALLOC(n,sz) calloc(n,sz)
# endif
# ifndef RAYGUI_FREE
# define RAYGUI_FREE(p) free(p)
# endif
// Simple log system to avoid printf() calls if required
// NOTE: Avoiding those calls, also avoids const strings memory usage
# define RAYGUI_SUPPORT_LOG_INFO
# if defined(RAYGUI_SUPPORT_LOG_INFO)
# define RAYGUI_LOG(...) printf(__VA_ARGS__)
# else
# define RAYGUI_LOG(...)
# endif
//----------------------------------------------------------------------------------
// Types and Structures Definition
// NOTE: Some types are required for RAYGUI_STANDALONE usage
//----------------------------------------------------------------------------------
# if defined(RAYGUI_STANDALONE)
# ifndef __cplusplus
// Boolean type
# ifndef true
typedef enum { false , true } bool ;
# endif
# endif
// Vector2 type
typedef struct Vector2 {
float x ;
float y ;
} Vector2 ;
// Vector3 type // -- ConvertHSVtoRGB(), ConvertRGBtoHSV()
typedef struct Vector3 {
float x ;
float y ;
float z ;
} Vector3 ;
// Color type, RGBA (32bit)
typedef struct Color {
unsigned char r ;
unsigned char g ;
unsigned char b ;
unsigned char a ;
} Color ;
// Rectangle type
typedef struct Rectangle {
float x ;
float y ;
float width ;
float height ;
} Rectangle ;
// TODO: Texture2D type is very coupled to raylib, required by Font type
// It should be redesigned to be provided by user
typedef struct Texture2D {
unsigned int id ; // OpenGL texture id
int width ; // Texture base width
int height ; // Texture base height
int mipmaps ; // Mipmap levels, 1 by default
int format ; // Data format (PixelFormat type)
} Texture2D ;
// Image, pixel data stored in CPU memory (RAM)
typedef struct Image {
void * data ; // Image raw data
int width ; // Image base width
int height ; // Image base height
int mipmaps ; // Mipmap levels, 1 by default
int format ; // Data format (PixelFormat type)
} Image ;
// GlyphInfo, font characters glyphs info
typedef struct GlyphInfo {
int value ; // Character value (Unicode)
int offsetX ; // Character offset X when drawing
int offsetY ; // Character offset Y when drawing
int advanceX ; // Character advance position X
Image image ; // Character image data
} GlyphInfo ;
// TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle()
// It should be redesigned to be provided by user
typedef struct Font {
int baseSize ; // Base size (default chars height)
int glyphCount ; // Number of glyph characters
int glyphPadding ; // Padding around the glyph characters
Texture2D texture ; // Texture atlas containing the glyphs
Rectangle * recs ; // Rectangles in texture for the glyphs
GlyphInfo * glyphs ; // Glyphs info data
} Font ;
# endif
// Style property
// NOTE: Used when exporting style as code for convenience
typedef struct GuiStyleProp {
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
} GuiState ;
// Gui control text alignment
typedef enum {
TEXT_ALIGN_LEFT = 0 ,
TEXT_ALIGN_CENTER ,
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, TOGGLESLIDER
PROGRESSBAR ,
CHECKBOX ,
COMBOBOX ,
DROPDOWNBOX ,
TEXTBOX , // Used also for: TEXTBOXMULTI
VALUEBOX ,
SPINNER , // Uses: BUTTON, VALUEBOX
LISTVIEW ,
COLORPICKER ,
SCROLLBAR ,
STATUSBAR
} GuiControl ;
// Gui base properties for every control
// NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties)
typedef enum {
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, 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;
// Button/Spinner
//typedef enum { } GuiButtonProperty;
// Toggle/ToggleGroup
typedef enum {
GROUP_PADDING = 16 , // ToggleGroup separation between toggles
} GuiToggleProperty ;
// Slider/SliderBar
typedef enum {
SLIDER_WIDTH = 16 , // Slider size of internal bar
SLIDER_PADDING // Slider/SliderBar internal bar padding
} GuiSliderProperty ;
// ProgressBar
typedef enum {
PROGRESS_PADDING = 16 , // ProgressBar internal padding
} GuiProgressBarProperty ;
// ScrollBar
typedef enum {
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
typedef enum {
CHECK_PADDING = 16 // CheckBox internal check padding
} GuiCheckBoxProperty ;
// ComboBox
typedef enum {
COMBO_BUTTON_WIDTH = 16 , // ComboBox right button width
COMBO_BUTTON_SPACING // ComboBox button separation
} GuiComboBoxProperty ;
// DropdownBox
typedef enum {
ARROW_PADDING = 16 , // DropdownBox arrow separation from border and items
DROPDOWN_ITEMS_SPACING // DropdownBox items separation
} GuiDropdownBoxProperty ;
// TextBox/TextBoxMulti/ValueBox/Spinner
typedef enum {
TEXT_READONLY = 16 , // TextBox in read-only mode: 0-text editable, 1-text no-editable
} GuiTextBoxProperty ;
// Spinner
typedef enum {
SPIN_BUTTON_WIDTH = 16 , // Spinner left/right buttons width
SPIN_BUTTON_SPACING , // Spinner buttons separation
} GuiSpinnerProperty ;
// ListView
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-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE)
} GuiListViewProperty ;
// ColorPicker
typedef enum {
COLOR_SELECTOR_SIZE = 16 ,
HUEBAR_WIDTH , // ColorPicker right hue bar width
HUEBAR_PADDING , // ColorPicker right hue bar separation from panel
HUEBAR_SELECTOR_HEIGHT , // ColorPicker right hue bar selector height
HUEBAR_SELECTOR_OVERFLOW // ColorPicker right hue bar selector overflow
} GuiColorPickerProperty ;
# define SCROLLBAR_LEFT_SIDE 0
# define SCROLLBAR_RIGHT_SIDE 1
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
// ...
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
# if defined(__cplusplus)
extern " C " { // Prevents name mangling of functions
# endif
// Global gui state control functions
RAYGUIAPI void GuiEnable ( void ) ; // Enable gui controls (global state)
RAYGUIAPI void GuiDisable ( void ) ; // Disable gui controls (global state)
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 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)
// Font set/get functions
RAYGUIAPI void GuiSetFont ( Font font ) ; // Set gui custom font (global state)
RAYGUIAPI Font GuiGetFont ( void ) ; // Get gui custom font (global state)
// Style set/get functions
RAYGUIAPI void GuiSetStyle ( int control , int property , int value ) ; // Set one style property
RAYGUIAPI int GuiGetStyle ( int control , int property ) ; // Get one style property
// Styles loading functions
RAYGUIAPI void GuiLoadStyle ( const char * fileName ) ; // Load style file over global style variable (.rgs)
RAYGUIAPI void GuiLoadStyleDefault ( void ) ; // Load style default over global style
// Tooltips management functions
RAYGUIAPI void GuiEnableTooltip ( void ) ; // Enable gui tooltips (global state)
RAYGUIAPI void GuiDisableTooltip ( void ) ; // Disable gui tooltips (global state)
RAYGUIAPI void GuiSetTooltip ( const char * tooltip ) ; // Set tooltip string
// Icons functionality
RAYGUIAPI const char * GuiIconText ( int iconId , const char * text ) ; // Get text with icon id prepended (if supported)
# if !defined(RAYGUI_NO_ICONS)
RAYGUIAPI void GuiSetIconScale ( int scale ) ; // Set default icon drawing size
RAYGUIAPI unsigned int * GuiGetIcons ( void ) ; // Get raygui icons data pointer
RAYGUIAPI char * * GuiLoadIcons ( const char * fileName , bool loadIconsName ) ; // Load raygui icons file (.rgi) into internal icons data
RAYGUIAPI void GuiDrawIcon ( int iconId , int posX , int posY , int pixelSize , Color color ) ; // Draw icon using pixel size at specified position
# endif
// Controls
//----------------------------------------------------------------------------------------------------------
// Container/separator controls, useful for controls organization
RAYGUIAPI int GuiWindowBox ( Rectangle bounds , const char * title ) ; // Window Box control, shows a window that can be closed
RAYGUIAPI int GuiGroupBox ( Rectangle bounds , const char * text ) ; // Group Box control with text name
RAYGUIAPI int GuiLine ( Rectangle bounds , const char * text ) ; // Line separator control, could contain text
RAYGUIAPI int GuiPanel ( Rectangle bounds , const char * text ) ; // Panel control, useful to group controls
RAYGUIAPI int GuiTabBar ( Rectangle bounds , const char * * text , int count , int * active ) ; // Tab Bar control, returns TAB to be closed or -1
RAYGUIAPI int GuiScrollPanel ( Rectangle bounds , const char * text , Rectangle content , Vector2 * scroll , Rectangle * view ) ; // Scroll Panel control
// Basic controls set
RAYGUIAPI int GuiLabel ( Rectangle bounds , const char * text ) ; // Label control, shows text
RAYGUIAPI int GuiButton ( Rectangle bounds , const char * text ) ; // Button control, returns true when clicked
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
RAYGUIAPI int GuiDropdownBox ( Rectangle bounds , const char * text , int * active , bool editMode ) ; // Dropdown Box control, returns selected item
RAYGUIAPI int GuiSpinner ( Rectangle bounds , const char * text , int * value , int minValue , int maxValue , bool editMode ) ; // Spinner control, returns selected value
RAYGUIAPI int GuiValueBox ( Rectangle bounds , const char * text , int * value , int minValue , int maxValue , bool editMode ) ; // Value Box control, updates input text with numbers
RAYGUIAPI int GuiTextBox ( Rectangle bounds , char * text , int textSize , bool editMode ) ; // Text Box control, updates input text
RAYGUIAPI int GuiSlider ( Rectangle bounds , const char * textLeft , const char * textRight , float * value , float minValue , float maxValue ) ; // Slider control, returns selected value
RAYGUIAPI int GuiSliderBar ( Rectangle bounds , const char * textLeft , const char * textRight , float * value , float minValue , float maxValue ) ; // Slider Bar control, returns selected value
RAYGUIAPI int GuiProgressBar ( Rectangle bounds , const char * textLeft , const char * textRight , float * value , float minValue , float maxValue ) ; // Progress Bar control, shows current progress value
RAYGUIAPI int GuiStatusBar ( Rectangle bounds , const char * text ) ; // Status Bar control, shows info text
RAYGUIAPI int GuiDummyRec ( Rectangle bounds , const char * text ) ; // Dummy control for placeholders
RAYGUIAPI int GuiGrid ( Rectangle bounds , const char * text , float spacing , int subdivs , Vector2 * mouseCell ) ; // Grid control, returns mouse cell position
// Advance controls set
RAYGUIAPI int GuiListView ( Rectangle bounds , const char * text , int * scrollIndex , int * active ) ; // List View control, returns selected list item index
RAYGUIAPI int GuiListViewEx ( Rectangle bounds , const char * * text , int count , int * scrollIndex , int * active , int * focus ) ; // List View with extended parameters
RAYGUIAPI int GuiMessageBox ( Rectangle bounds , const char * title , const char * message , const char * buttons ) ; // Message Box control, displays a message
RAYGUIAPI int GuiTextInputBox ( Rectangle bounds , const char * title , const char * message , const char * buttons , char * text , int textMaxSize , bool * secretViewActive ) ; // Text Input Box control, ask for text, supports secret
RAYGUIAPI int GuiColorPicker ( Rectangle bounds , const char * text , Color * color ) ; // Color Picker control (multiple color controls)
RAYGUIAPI int 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()
//----------------------------------------------------------------------------------------------------------
# if !defined(RAYGUI_NO_ICONS)
# if !defined(RAYGUI_CUSTOM_ICONS)
//----------------------------------------------------------------------------------
// Icons enumeration
//----------------------------------------------------------------------------------
typedef enum {
ICON_NONE = 0 ,
ICON_FOLDER_FILE_OPEN = 1 ,
ICON_FILE_SAVE_CLASSIC = 2 ,
ICON_FOLDER_OPEN = 3 ,
ICON_FOLDER_SAVE = 4 ,
ICON_FILE_OPEN = 5 ,
ICON_FILE_SAVE = 6 ,
ICON_FILE_EXPORT = 7 ,
ICON_FILE_ADD = 8 ,
ICON_FILE_DELETE = 9 ,
ICON_FILETYPE_TEXT = 10 ,
ICON_FILETYPE_AUDIO = 11 ,
ICON_FILETYPE_IMAGE = 12 ,
ICON_FILETYPE_PLAY = 13 ,
ICON_FILETYPE_VIDEO = 14 ,
ICON_FILETYPE_INFO = 15 ,
ICON_FILE_COPY = 16 ,
ICON_FILE_CUT = 17 ,
ICON_FILE_PASTE = 18 ,
ICON_CURSOR_HAND = 19 ,
ICON_CURSOR_POINTER = 20 ,
ICON_CURSOR_CLASSIC = 21 ,
ICON_PENCIL = 22 ,
ICON_PENCIL_BIG = 23 ,
ICON_BRUSH_CLASSIC = 24 ,
ICON_BRUSH_PAINTER = 25 ,
ICON_WATER_DROP = 26 ,
ICON_COLOR_PICKER = 27 ,
ICON_RUBBER = 28 ,
ICON_COLOR_BUCKET = 29 ,
ICON_TEXT_T = 30 ,
ICON_TEXT_A = 31 ,
ICON_SCALE = 32 ,
ICON_RESIZE = 33 ,
ICON_FILTER_POINT = 34 ,
ICON_FILTER_BILINEAR = 35 ,
ICON_CROP = 36 ,
ICON_CROP_ALPHA = 37 ,
ICON_SQUARE_TOGGLE = 38 ,
ICON_SYMMETRY = 39 ,
ICON_SYMMETRY_HORIZONTAL = 40 ,
ICON_SYMMETRY_VERTICAL = 41 ,
ICON_LENS = 42 ,
ICON_LENS_BIG = 43 ,
ICON_EYE_ON = 44 ,
ICON_EYE_OFF = 45 ,
ICON_FILTER_TOP = 46 ,
ICON_FILTER = 47 ,
ICON_TARGET_POINT = 48 ,
ICON_TARGET_SMALL = 49 ,
ICON_TARGET_BIG = 50 ,
ICON_TARGET_MOVE = 51 ,
ICON_CURSOR_MOVE = 52 ,
ICON_CURSOR_SCALE = 53 ,
ICON_CURSOR_SCALE_RIGHT = 54 ,
ICON_CURSOR_SCALE_LEFT = 55 ,
ICON_UNDO = 56 ,
ICON_REDO = 57 ,
ICON_REREDO = 58 ,
ICON_MUTATE = 59 ,
ICON_ROTATE = 60 ,
ICON_REPEAT = 61 ,
ICON_SHUFFLE = 62 ,
ICON_EMPTYBOX = 63 ,
ICON_TARGET = 64 ,
ICON_TARGET_SMALL_FILL = 65 ,
ICON_TARGET_BIG_FILL = 66 ,
ICON_TARGET_MOVE_FILL = 67 ,
ICON_CURSOR_MOVE_FILL = 68 ,
ICON_CURSOR_SCALE_FILL = 69 ,
ICON_CURSOR_SCALE_RIGHT_FILL = 70 ,
ICON_CURSOR_SCALE_LEFT_FILL = 71 ,
ICON_UNDO_FILL = 72 ,
ICON_REDO_FILL = 73 ,
ICON_REREDO_FILL = 74 ,
ICON_MUTATE_FILL = 75 ,
ICON_ROTATE_FILL = 76 ,
ICON_REPEAT_FILL = 77 ,
ICON_SHUFFLE_FILL = 78 ,
ICON_EMPTYBOX_SMALL = 79 ,
ICON_BOX = 80 ,
ICON_BOX_TOP = 81 ,
ICON_BOX_TOP_RIGHT = 82 ,
ICON_BOX_RIGHT = 83 ,
ICON_BOX_BOTTOM_RIGHT = 84 ,
ICON_BOX_BOTTOM = 85 ,
ICON_BOX_BOTTOM_LEFT = 86 ,
ICON_BOX_LEFT = 87 ,
ICON_BOX_TOP_LEFT = 88 ,
ICON_BOX_CENTER = 89 ,
ICON_BOX_CIRCLE_MASK = 90 ,
ICON_POT = 91 ,
ICON_ALPHA_MULTIPLY = 92 ,
ICON_ALPHA_CLEAR = 93 ,
ICON_DITHERING = 94 ,
ICON_MIPMAPS = 95 ,
ICON_BOX_GRID = 96 ,
ICON_GRID = 97 ,
ICON_BOX_CORNERS_SMALL = 98 ,
ICON_BOX_CORNERS_BIG = 99 ,
ICON_FOUR_BOXES = 100 ,
ICON_GRID_FILL = 101 ,
ICON_BOX_MULTISIZE = 102 ,
ICON_ZOOM_SMALL = 103 ,
ICON_ZOOM_MEDIUM = 104 ,
ICON_ZOOM_BIG = 105 ,
ICON_ZOOM_ALL = 106 ,
ICON_ZOOM_CENTER = 107 ,
ICON_BOX_DOTS_SMALL = 108 ,
ICON_BOX_DOTS_BIG = 109 ,
ICON_BOX_CONCENTRIC = 110 ,
ICON_BOX_GRID_BIG = 111 ,
ICON_OK_TICK = 112 ,
ICON_CROSS = 113 ,
ICON_ARROW_LEFT = 114 ,
ICON_ARROW_RIGHT = 115 ,
ICON_ARROW_DOWN = 116 ,
ICON_ARROW_UP = 117 ,
ICON_ARROW_LEFT_FILL = 118 ,
ICON_ARROW_RIGHT_FILL = 119 ,
ICON_ARROW_DOWN_FILL = 120 ,
ICON_ARROW_UP_FILL = 121 ,
ICON_AUDIO = 122 ,
ICON_FX = 123 ,
ICON_WAVE = 124 ,
ICON_WAVE_SINUS = 125 ,
ICON_WAVE_SQUARE = 126 ,
ICON_WAVE_TRIANGULAR = 127 ,
ICON_CROSS_SMALL = 128 ,
ICON_PLAYER_PREVIOUS = 129 ,
ICON_PLAYER_PLAY_BACK = 130 ,
ICON_PLAYER_PLAY = 131 ,
ICON_PLAYER_PAUSE = 132 ,
ICON_PLAYER_STOP = 133 ,
ICON_PLAYER_NEXT = 134 ,
ICON_PLAYER_RECORD = 135 ,
ICON_MAGNET = 136 ,
ICON_LOCK_CLOSE = 137 ,
ICON_LOCK_OPEN = 138 ,
ICON_CLOCK = 139 ,
ICON_TOOLS = 140 ,
ICON_GEAR = 141 ,
ICON_GEAR_BIG = 142 ,
ICON_BIN = 143 ,
ICON_HAND_POINTER = 144 ,
ICON_LASER = 145 ,
ICON_COIN = 146 ,
ICON_EXPLOSION = 147 ,
ICON_1UP = 148 ,
ICON_PLAYER = 149 ,
ICON_PLAYER_JUMP = 150 ,
ICON_KEY = 151 ,
ICON_DEMON = 152 ,
ICON_TEXT_POPUP = 153 ,
ICON_GEAR_EX = 154 ,
ICON_CRACK = 155 ,
ICON_CRACK_POINTS = 156 ,
ICON_STAR = 157 ,
ICON_DOOR = 158 ,
ICON_EXIT = 159 ,
ICON_MODE_2D = 160 ,
ICON_MODE_3D = 161 ,
ICON_CUBE = 162 ,
ICON_CUBE_FACE_TOP = 163 ,
ICON_CUBE_FACE_LEFT = 164 ,
ICON_CUBE_FACE_FRONT = 165 ,
ICON_CUBE_FACE_BOTTOM = 166 ,
ICON_CUBE_FACE_RIGHT = 167 ,
ICON_CUBE_FACE_BACK = 168 ,
ICON_CAMERA = 169 ,
ICON_SPECIAL = 170 ,
ICON_LINK_NET = 171 ,
ICON_LINK_BOXES = 172 ,
ICON_LINK_MULTI = 173 ,
ICON_LINK = 174 ,
ICON_LINK_BROKE = 175 ,
ICON_TEXT_NOTES = 176 ,
ICON_NOTEBOOK = 177 ,
ICON_SUITCASE = 178 ,
ICON_SUITCASE_ZIP = 179 ,
ICON_MAILBOX = 180 ,
ICON_MONITOR = 181 ,
ICON_PRINTER = 182 ,
ICON_PHOTO_CAMERA = 183 ,
ICON_PHOTO_CAMERA_FLASH = 184 ,
ICON_HOUSE = 185 ,
ICON_HEART = 186 ,
ICON_CORNER = 187 ,
ICON_VERTICAL_BARS = 188 ,
ICON_VERTICAL_BARS_FILL = 189 ,
ICON_LIFE_BARS = 190 ,
ICON_INFO = 191 ,
ICON_CROSSLINE = 192 ,
ICON_HELP = 193 ,
ICON_FILETYPE_ALPHA = 194 ,
ICON_FILETYPE_HOME = 195 ,
ICON_LAYERS_VISIBLE = 196 ,
ICON_LAYERS = 197 ,
ICON_WINDOW = 198 ,
ICON_HIDPI = 199 ,
ICON_FILETYPE_BINARY = 200 ,
ICON_HEX = 201 ,
ICON_SHIELD = 202 ,
ICON_FILE_NEW = 203 ,
ICON_FOLDER_ADD = 204 ,
ICON_ALARM = 205 ,
ICON_CPU = 206 ,
ICON_ROM = 207 ,
ICON_STEP_OVER = 208 ,
ICON_STEP_INTO = 209 ,
ICON_STEP_OUT = 210 ,
ICON_RESTART = 211 ,
ICON_BREAKPOINT_ON = 212 ,
ICON_BREAKPOINT_OFF = 213 ,
ICON_BURGER_MENU = 214 ,
ICON_CASE_SENSITIVE = 215 ,
ICON_REG_EXP = 216 ,
ICON_FOLDER = 217 ,
ICON_FILE = 218 ,
ICON_SAND_TIMER = 219 ,
ICON_220 = 220 ,
ICON_221 = 221 ,
ICON_222 = 222 ,
ICON_223 = 223 ,
ICON_224 = 224 ,
ICON_225 = 225 ,
ICON_226 = 226 ,
ICON_227 = 227 ,
ICON_228 = 228 ,
ICON_229 = 229 ,
ICON_230 = 230 ,
ICON_231 = 231 ,
ICON_232 = 232 ,
ICON_233 = 233 ,
ICON_234 = 234 ,
ICON_235 = 235 ,
ICON_236 = 236 ,
ICON_237 = 237 ,
ICON_238 = 238 ,
ICON_239 = 239 ,
ICON_240 = 240 ,
ICON_241 = 241 ,
ICON_242 = 242 ,
ICON_243 = 243 ,
ICON_244 = 244 ,
ICON_245 = 245 ,
ICON_246 = 246 ,
ICON_247 = 247 ,
ICON_248 = 248 ,
ICON_249 = 249 ,
ICON_250 = 250 ,
ICON_251 = 251 ,
ICON_252 = 252 ,
ICON_253 = 253 ,
ICON_254 = 254 ,
ICON_255 = 255 ,
} GuiIconName ;
# endif
# endif
# if defined(__cplusplus)
} // Prevents name mangling of functions
# endif
# endif // RAYGUI_H
/***********************************************************************************
*
* RAYGUI IMPLEMENTATION
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined(RAYGUI_IMPLEMENTATION)
# include <stdio.h> // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()]
# include <stdlib.h> // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()]
# include <string.h> // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy()
# include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() [TextFormat()]
# include <math.h> // Required for: roundf() [GuiColorPicker()]
# ifdef __cplusplus
# define RAYGUI_CLITERAL(name) name
# else
# define RAYGUI_CLITERAL(name) (name)
# endif
// Check if two rectangles are equal, used to validate a slider bounds as an id
# ifndef CHECK_BOUNDS_ID
# define CHECK_BOUNDS_ID(src, dst) ((src.x == dst.x) && (src.y == dst.y) && (src.width == dst.width) && (src.height == dst.height))
# endif
# if !defined(RAYGUI_NO_ICONS) && !defined(RAYGUI_CUSTOM_ICONS)
// Embedded icons, no external file provided
# define RAYGUI_ICON_SIZE 16 // Size of icons in pixels (squared)
# define RAYGUI_ICON_MAX_ICONS 256 // Maximum number of icons
# define RAYGUI_ICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id
// Icons data is defined by bit array (every bit represents one pixel)
// Those arrays are stored as unsigned int data arrays, so,
// every array element defines 32 pixels (bits) of information
// One icon is defined by 8 int, (8 int * 32 bit = 256 bit = 16*16 pixels)
// NOTE: Number of elemens depend on RAYGUI_ICON_SIZE (by default 16x16 pixels)
# define RAYGUI_ICON_DATA_ELEMENTS (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE / 32)
//----------------------------------------------------------------------------------
// Icons data for all gui possible icons (allocated on data segment by default)
//
// NOTE 1: Every icon is codified in binary form, using 1 bit per pixel, so,
// every 16x16 icon requires 8 integers (16*16/32) to be stored
//
// NOTE 2: A different icon set could be loaded over this array using GuiLoadIcons(),
// but loaded icons set must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS
//
// guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB
//----------------------------------------------------------------------------------
static unsigned int guiIcons [ RAYGUI_ICON_MAX_ICONS * RAYGUI_ICON_DATA_ELEMENTS ] = {
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_NONE
0x3ff80000 , 0x2f082008 , 0x2042207e , 0x40027fc2 , 0x40024002 , 0x40024002 , 0x40024002 , 0x00007ffe , // ICON_FOLDER_FILE_OPEN
0x3ffe0000 , 0x44226422 , 0x400247e2 , 0x5ffa4002 , 0x57ea500a , 0x500a500a , 0x40025ffa , 0x00007ffe , // ICON_FILE_SAVE_CLASSIC
0x00000000 , 0x0042007e , 0x40027fc2 , 0x40024002 , 0x41024002 , 0x44424282 , 0x793e4102 , 0x00000100 , // ICON_FOLDER_OPEN
0x00000000 , 0x0042007e , 0x40027fc2 , 0x40024002 , 0x41024102 , 0x44424102 , 0x793e4282 , 0x00000000 , // ICON_FOLDER_SAVE
0x3ff00000 , 0x201c2010 , 0x20042004 , 0x21042004 , 0x24442284 , 0x21042104 , 0x20042104 , 0x00003ffc , // ICON_FILE_OPEN
0x3ff00000 , 0x201c2010 , 0x20042004 , 0x21042004 , 0x21042104 , 0x22842444 , 0x20042104 , 0x00003ffc , // ICON_FILE_SAVE
0x3ff00000 , 0x201c2010 , 0x00042004 , 0x20041004 , 0x20844784 , 0x00841384 , 0x20042784 , 0x00003ffc , // ICON_FILE_EXPORT
0x3ff00000 , 0x201c2010 , 0x20042004 , 0x20042004 , 0x22042204 , 0x22042f84 , 0x20042204 , 0x00003ffc , // ICON_FILE_ADD
0x3ff00000 , 0x201c2010 , 0x20042004 , 0x20042004 , 0x25042884 , 0x25042204 , 0x20042884 , 0x00003ffc , // ICON_FILE_DELETE
0x3ff00000 , 0x201c2010 , 0x20042004 , 0x20042ff4 , 0x20042ff4 , 0x20042ff4 , 0x20042004 , 0x00003ffc , // ICON_FILETYPE_TEXT
0x3ff00000 , 0x201c2010 , 0x27042004 , 0x244424c4 , 0x26442444 , 0x20642664 , 0x20042004 , 0x00003ffc , // ICON_FILETYPE_AUDIO
0x3ff00000 , 0x201c2010 , 0x26042604 , 0x20042004 , 0x35442884 , 0x2414222c , 0x20042004 , 0x00003ffc , // ICON_FILETYPE_IMAGE
0x3ff00000 , 0x201c2010 , 0x20c42004 , 0x22442144 , 0x22442444 , 0x20c42144 , 0x20042004 , 0x00003ffc , // ICON_FILETYPE_PLAY
0x3ff00000 , 0x3ffc2ff0 , 0x3f3c2ff4 , 0x3dbc2eb4 , 0x3dbc2bb4 , 0x3f3c2eb4 , 0x3ffc2ff4 , 0x00002ff4 , // ICON_FILETYPE_VIDEO
0x3ff00000 , 0x201c2010 , 0x21842184 , 0x21842004 , 0x21842184 , 0x21842184 , 0x20042184 , 0x00003ffc , // ICON_FILETYPE_INFO
0x0ff00000 , 0x381c0810 , 0x28042804 , 0x28042804 , 0x28042804 , 0x28042804 , 0x20102ffc , 0x00003ff0 , // ICON_FILE_COPY
0x00000000 , 0x701c0000 , 0x079c1e14 , 0x55a000f0 , 0x079c00f0 , 0x701c1e14 , 0x00000000 , 0x00000000 , // ICON_FILE_CUT
0x01c00000 , 0x13e41bec , 0x3f841004 , 0x204420c4 , 0x20442044 , 0x20442044 , 0x207c2044 , 0x00003fc0 , // ICON_FILE_PASTE
0x00000000 , 0x3aa00fe0 , 0x2abc2aa0 , 0x2aa42aa4 , 0x20042aa4 , 0x20042004 , 0x3ffc2004 , 0x00000000 , // ICON_CURSOR_HAND
0x00000000 , 0x003c000c , 0x030800c8 , 0x30100c10 , 0x10202020 , 0x04400840 , 0x01800280 , 0x00000000 , // ICON_CURSOR_POINTER
0x00000000 , 0x00180000 , 0x01f00078 , 0x03e007f0 , 0x07c003e0 , 0x04000e40 , 0x00000000 , 0x00000000 , // ICON_CURSOR_CLASSIC
0x00000000 , 0x04000000 , 0x11000a00 , 0x04400a80 , 0x01100220 , 0x00580088 , 0x00000038 , 0x00000000 , // ICON_PENCIL
0x04000000 , 0x15000a00 , 0x50402880 , 0x14102820 , 0x05040a08 , 0x015c028c , 0x007c00bc , 0x00000000 , // ICON_PENCIL_BIG
0x01c00000 , 0x01400140 , 0x01400140 , 0x0ff80140 , 0x0ff80808 , 0x0aa80808 , 0x0aa80aa8 , 0x00000ff8 , // ICON_BRUSH_CLASSIC
0x1ffc0000 , 0x5ffc7ffe , 0x40004000 , 0x00807f80 , 0x01c001c0 , 0x01c001c0 , 0x01c001c0 , 0x00000080 , // ICON_BRUSH_PAINTER
0x00000000 , 0x00800000 , 0x01c00080 , 0x03e001c0 , 0x07f003e0 , 0x036006f0 , 0x000001c0 , 0x00000000 , // ICON_WATER_DROP
0x00000000 , 0x3e003800 , 0x1f803f80 , 0x0c201e40 , 0x02080c10 , 0x00840104 , 0x00380044 , 0x00000000 , // ICON_COLOR_PICKER
0x00000000 , 0x07800300 , 0x1fe00fc0 , 0x3f883fd0 , 0x0e021f04 , 0x02040402 , 0x00f00108 , 0x00000000 , // ICON_RUBBER
0x00c00000 , 0x02800140 , 0x08200440 , 0x20081010 , 0x2ffe3004 , 0x03f807fc , 0x00e001f0 , 0x00000040 , // ICON_COLOR_BUCKET
0x00000000 , 0x21843ffc , 0x01800180 , 0x01800180 , 0x01800180 , 0x01800180 , 0x03c00180 , 0x00000000 , // ICON_TEXT_T
0x00800000 , 0x01400180 , 0x06200340 , 0x0c100620 , 0x1ff80c10 , 0x380c1808 , 0x70067004 , 0x0000f80f , // ICON_TEXT_A
0x78000000 , 0x50004000 , 0x00004800 , 0x03c003c0 , 0x03c003c0 , 0x00100000 , 0x0002000a , 0x0000000e , // ICON_SCALE
0x75560000 , 0x5e004002 , 0x54001002 , 0x41001202 , 0x408200fe , 0x40820082 , 0x40820082 , 0x00006afe , // ICON_RESIZE
0x00000000 , 0x3f003f00 , 0x3f003f00 , 0x3f003f00 , 0x00400080 , 0x001c0020 , 0x001c001c , 0x00000000 , // ICON_FILTER_POINT
0x6d800000 , 0x00004080 , 0x40804080 , 0x40800000 , 0x00406d80 , 0x001c0020 , 0x001c001c , 0x00000000 , // ICON_FILTER_BILINEAR
0x40080000 , 0x1ffe2008 , 0x14081008 , 0x11081208 , 0x10481088 , 0x10081028 , 0x10047ff8 , 0x00001002 , // ICON_CROP
0x00100000 , 0x3ffc0010 , 0x2ab03550 , 0x22b02550 , 0x20b02150 , 0x20302050 , 0x2000fff0 , 0x00002000 , // ICON_CROP_ALPHA
0x40000000 , 0x1ff82000 , 0x04082808 , 0x01082208 , 0x00482088 , 0x00182028 , 0x35542008 , 0x00000002 , // ICON_SQUARE_TOGGLE
0x00000000 , 0x02800280 , 0x06c006c0 , 0x0ea00ee0 , 0x1e901eb0 , 0x3e883e98 , 0x7efc7e8c , 0x00000000 , // ICON_SYMMETRY
0x01000000 , 0x05600100 , 0x1d480d50 , 0x7d423d44 , 0x3d447d42 , 0x0d501d48 , 0x01000560 , 0x00000100 , // ICON_SYMMETRY_HORIZONTAL
0x01800000 , 0x04200240 , 0x10080810 , 0x00001ff8 , 0x00007ffe , 0x0ff01ff8 , 0x03c007e0 , 0x00000180 , // ICON_SYMMETRY_VERTICAL
0x00000000 , 0x010800f0 , 0x02040204 , 0x02040204 , 0x07f00308 , 0x1c000e00 , 0x30003800 , 0x00000000 , // ICON_LENS
0x00000000 , 0x061803f0 , 0x08240c0c , 0x08040814 , 0x0c0c0804 , 0x23f01618 , 0x18002400 , 0x00000000 , // ICON_LENS_BIG
0x00000000 , 0x00000000 , 0x1c7007c0 , 0x638e3398 , 0x1c703398 , 0x000007c0 , 0x00000000 , 0x00000000 , // ICON_EYE_ON
0x00000000 , 0x10002000 , 0x04700fc0 , 0x610e3218 , 0x1c703098 , 0x001007a0 , 0x00000008 , 0x00000000 , // ICON_EYE_OFF
0x00000000 , 0x00007ffc , 0x40047ffc , 0x10102008 , 0x04400820 , 0x02800280 , 0x02800280 , 0x00000100 , // ICON_FILTER_TOP
0x00000000 , 0x40027ffe , 0x10082004 , 0x04200810 , 0x02400240 , 0x02400240 , 0x01400240 , 0x000000c0 , // ICON_FILTER
0x00800000 , 0x00800080 , 0x00000080 , 0x3c9e0000 , 0x00000000 , 0x00800080 , 0x00800080 , 0x00000000 , // ICON_TARGET_POINT
0x00800000 , 0x00800080 , 0x00800080 , 0x3f7e01c0 , 0x008001c0 , 0x00800080 , 0x00800080 , 0x00000000 , // ICON_TARGET_SMALL
0x00800000 , 0x00800080 , 0x03e00080 , 0x3e3e0220 , 0x03e00220 , 0x00800080 , 0x00800080 , 0x00000000 , // ICON_TARGET_BIG
0x01000000 , 0x04400280 , 0x01000100 , 0x43842008 , 0x43849ab2 , 0x01002008 , 0x04400100 , 0x01000280 , // ICON_TARGET_MOVE
0x01000000 , 0x04400280 , 0x01000100 , 0x41042108 , 0x41049ff2 , 0x01002108 , 0x04400100 , 0x01000280 , // ICON_CURSOR_MOVE
0x781e0000 , 0x500a4002 , 0x04204812 , 0x00000240 , 0x02400000 , 0x48120420 , 0x4002500a , 0x0000781e , // ICON_CURSOR_SCALE
0x00000000 , 0x20003c00 , 0x24002800 , 0x01000200 , 0x00400080 , 0x00140024 , 0x003c0004 , 0x00000000 , // ICON_CURSOR_SCALE_RIGHT
0x00000000 , 0x0004003c , 0x00240014 , 0x00800040 , 0x02000100 , 0x28002400 , 0x3c002000 , 0x00000000 , // ICON_CURSOR_SCALE_LEFT
0x00000000 , 0x00100020 , 0x10101fc8 , 0x10001020 , 0x10001000 , 0x10001000 , 0x00001fc0 , 0x00000000 , // ICON_UNDO
0x00000000 , 0x08000400 , 0x080813f8 , 0x00080408 , 0x00080008 , 0x00080008 , 0x000003f8 , 0x00000000 , // ICON_REDO
0x00000000 , 0x3ffc0000 , 0x20042004 , 0x20002000 , 0x20402000 , 0x3f902020 , 0x00400020 , 0x00000000 , // ICON_REREDO
0x00000000 , 0x3ffc0000 , 0x20042004 , 0x27fc2004 , 0x20202000 , 0x3fc82010 , 0x00200010 , 0x00000000 , // ICON_MUTATE
0x00000000 , 0x0ff00000 , 0x10081818 , 0x11801008 , 0x10001180 , 0x18101020 , 0x00100fc8 , 0x00000020 , // ICON_ROTATE
0x00000000 , 0x04000200 , 0x240429fc , 0x20042204 , 0x20442004 , 0x3f942024 , 0x00400020 , 0x00000000 , // ICON_REPEAT
0x00000000 , 0x20001000 , 0x22104c0e , 0x00801120 , 0x11200040 , 0x4c0e2210 , 0x10002000 , 0x00000000 , // ICON_SHUFFLE
0x7ffe0000 , 0x50024002 , 0x44024802 , 0x41024202 , 0x40424082 , 0x40124022 , 0x4002400a , 0x00007ffe , // ICON_EMPTYBOX
0x00800000 , 0x03e00080 , 0x08080490 , 0x3c9e0808 , 0x08080808 , 0x03e00490 , 0x00800080 , 0x00000000 , // ICON_TARGET
0x00800000 , 0x00800080 , 0x00800080 , 0x3ffe01c0 , 0x008001c0 , 0x00800080 , 0x00800080 , 0x00000000 , // ICON_TARGET_SMALL_FILL
0x00800000 , 0x00800080 , 0x03e00080 , 0x3ffe03e0 , 0x03e003e0 , 0x00800080 , 0x00800080 , 0x00000000 , // ICON_TARGET_BIG_FILL
0x01000000 , 0x07c00380 , 0x01000100 , 0x638c2008 , 0x638cfbbe , 0x01002008 , 0x07c00100 , 0x01000380 , // ICON_TARGET_MOVE_FILL
0x01000000 , 0x07c00380 , 0x01000100 , 0x610c2108 , 0x610cfffe , 0x01002108 , 0x07c00100 , 0x01000380 , // ICON_CURSOR_MOVE_FILL
0x781e0000 , 0x6006700e , 0x04204812 , 0x00000240 , 0x02400000 , 0x48120420 , 0x700e6006 , 0x0000781e , // ICON_CURSOR_SCALE_FILL
0x00000000 , 0x38003c00 , 0x24003000 , 0x01000200 , 0x00400080 , 0x000c0024 , 0x003c001c , 0x00000000 , // ICON_CURSOR_SCALE_RIGHT_FILL
0x00000000 , 0x001c003c , 0x0024000c , 0x00800040 , 0x02000100 , 0x30002400 , 0x3c003800 , 0x00000000 , // ICON_CURSOR_SCALE_LEFT_FILL
0x00000000 , 0x00300020 , 0x10301ff8 , 0x10001020 , 0x10001000 , 0x10001000 , 0x00001fc0 , 0x00000000 , // ICON_UNDO_FILL
0x00000000 , 0x0c000400 , 0x0c081ff8 , 0x00080408 , 0x00080008 , 0x00080008 , 0x000003f8 , 0x00000000 , // ICON_REDO_FILL
0x00000000 , 0x3ffc0000 , 0x20042004 , 0x20002000 , 0x20402000 , 0x3ff02060 , 0x00400060 , 0x00000000 , // ICON_REREDO_FILL
0x00000000 , 0x3ffc0000 , 0x20042004 , 0x27fc2004 , 0x20202000 , 0x3ff82030 , 0x00200030 , 0x00000000 , // ICON_MUTATE_FILL
0x00000000 , 0x0ff00000 , 0x10081818 , 0x11801008 , 0x10001180 , 0x18301020 , 0x00300ff8 , 0x00000020 , // ICON_ROTATE_FILL
0x00000000 , 0x06000200 , 0x26042ffc , 0x20042204 , 0x20442004 , 0x3ff42064 , 0x00400060 , 0x00000000 , // ICON_REPEAT_FILL
0x00000000 , 0x30001000 , 0x32107c0e , 0x00801120 , 0x11200040 , 0x7c0e3210 , 0x10003000 , 0x00000000 , // ICON_SHUFFLE_FILL
0x00000000 , 0x30043ffc , 0x24042804 , 0x21042204 , 0x20442084 , 0x20142024 , 0x3ffc200c , 0x00000000 , // ICON_EMPTYBOX_SMALL
0x00000000 , 0x20043ffc , 0x20042004 , 0x20042004 , 0x20042004 , 0x20042004 , 0x3ffc2004 , 0x00000000 , // ICON_BOX
0x00000000 , 0x23c43ffc , 0x23c423c4 , 0x200423c4 , 0x20042004 , 0x20042004 , 0x3ffc2004 , 0x00000000 , // ICON_BOX_TOP
0x00000000 , 0x3e043ffc , 0x3e043e04 , 0x20043e04 , 0x20042004 , 0x20042004 , 0x3ffc2004 , 0x00000000 , // ICON_BOX_TOP_RIGHT
0x00000000 , 0x20043ffc , 0x20042004 , 0x3e043e04 , 0x3e043e04 , 0x20042004 , 0x3ffc2004 , 0x00000000 , // ICON_BOX_RIGHT
0x00000000 , 0x20043ffc , 0x20042004 , 0x20042004 , 0x3e042004 , 0x3e043e04 , 0x3ffc3e04 , 0x00000000 , // ICON_BOX_BOTTOM_RIGHT
0x00000000 , 0x20043ffc , 0x20042004 , 0x20042004 , 0x23c42004 , 0x23c423c4 , 0x3ffc23c4 , 0x00000000 , // ICON_BOX_BOTTOM
0x00000000 , 0x20043ffc , 0x20042004 , 0x20042004 , 0x207c2004 , 0x207c207c , 0x3ffc207c , 0x00000000 , // ICON_BOX_BOTTOM_LEFT
0x00000000 , 0x20043ffc , 0x20042004 , 0x207c207c , 0x207c207c , 0x20042004 , 0x3ffc2004 , 0x00000000 , // ICON_BOX_LEFT
0x00000000 , 0x207c3ffc , 0x207c207c , 0x2004207c , 0x20042004 , 0x20042004 , 0x3ffc2004 , 0x00000000 , // ICON_BOX_TOP_LEFT
0x00000000 , 0x20043ffc , 0x20042004 , 0x23c423c4 , 0x23c423c4 , 0x20042004 , 0x3ffc2004 , 0x00000000 , // ICON_BOX_CENTER
0x7ffe0000 , 0x40024002 , 0x47e24182 , 0x4ff247e2 , 0x47e24ff2 , 0x418247e2 , 0x40024002 , 0x00007ffe , // ICON_BOX_CIRCLE_MASK
0x7fff0000 , 0x40014001 , 0x40014001 , 0x49555ddd , 0x4945495d , 0x400149c5 , 0x40014001 , 0x00007fff , // ICON_POT
0x7ffe0000 , 0x53327332 , 0x44ce4cce , 0x41324332 , 0x404e40ce , 0x48125432 , 0x4006540e , 0x00007ffe , // ICON_ALPHA_MULTIPLY
0x7ffe0000 , 0x53327332 , 0x44ce4cce , 0x41324332 , 0x5c4e40ce , 0x44124432 , 0x40065c0e , 0x00007ffe , // ICON_ALPHA_CLEAR
0x7ffe0000 , 0x42fe417e , 0x42fe417e , 0x42fe417e , 0x42fe417e , 0x42fe417e , 0x42fe417e , 0x00007ffe , // ICON_DITHERING
0x07fe0000 , 0x1ffa0002 , 0x7fea000a , 0x402a402a , 0x5b2a512a , 0x5128552a , 0x40205128 , 0x00007fe0 , // ICON_MIPMAPS
0x00000000 , 0x1ff80000 , 0x12481248 , 0x12481ff8 , 0x1ff81248 , 0x12481248 , 0x00001ff8 , 0x00000000 , // ICON_BOX_GRID
0x12480000 , 0x7ffe1248 , 0x12481248 , 0x12487ffe , 0x7ffe1248 , 0x12481248 , 0x12487ffe , 0x00001248 , // ICON_GRID
0x00000000 , 0x1c380000 , 0x1c3817e8 , 0x08100810 , 0x08100810 , 0x17e81c38 , 0x00001c38 , 0x00000000 , // ICON_BOX_CORNERS_SMALL
0x700e0000 , 0x700e5ffa , 0x20042004 , 0x20042004 , 0x20042004 , 0x20042004 , 0x5ffa700e , 0x0000700e , // ICON_BOX_CORNERS_BIG
0x3f7e0000 , 0x21422142 , 0x21422142 , 0x00003f7e , 0x21423f7e , 0x21422142 , 0x3f7e2142 , 0x00000000 , // ICON_FOUR_BOXES
0x00000000 , 0x3bb80000 , 0x3bb83bb8 , 0x3bb80000 , 0x3bb83bb8 , 0x3bb80000 , 0x3bb83bb8 , 0x00000000 , // ICON_GRID_FILL
0x7ffe0000 , 0x7ffe7ffe , 0x77fe7000 , 0x77fe77fe , 0x777e7700 , 0x777e777e , 0x777e777e , 0x0000777e , // ICON_BOX_MULTISIZE
0x781e0000 , 0x40024002 , 0x00004002 , 0x01800000 , 0x00000180 , 0x40020000 , 0x40024002 , 0x0000781e , // ICON_ZOOM_SMALL
0x781e0000 , 0x40024002 , 0x00004002 , 0x03c003c0 , 0x03c003c0 , 0x40020000 , 0x40024002 , 0x0000781e , // ICON_ZOOM_MEDIUM
0x781e0000 , 0x40024002 , 0x07e04002 , 0x07e007e0 , 0x07e007e0 , 0x400207e0 , 0x40024002 , 0x0000781e , // ICON_ZOOM_BIG
0x781e0000 , 0x5ffa4002 , 0x1ff85ffa , 0x1ff81ff8 , 0x1ff81ff8 , 0x5ffa1ff8 , 0x40025ffa , 0x0000781e , // ICON_ZOOM_ALL
0x00000000 , 0x2004381c , 0x00002004 , 0x00000000 , 0x00000000 , 0x20040000 , 0x381c2004 , 0x00000000 , // ICON_ZOOM_CENTER
0x00000000 , 0x1db80000 , 0x10081008 , 0x10080000 , 0x00001008 , 0x10081008 , 0x00001db8 , 0x00000000 , // ICON_BOX_DOTS_SMALL
0x35560000 , 0x00002002 , 0x00002002 , 0x00002002 , 0x00002002 , 0x00002002 , 0x35562002 , 0x00000000 , // ICON_BOX_DOTS_BIG
0x7ffe0000 , 0x40024002 , 0x48124ff2 , 0x49924812 , 0x48124992 , 0x4ff24812 , 0x40024002 , 0x00007ffe , // ICON_BOX_CONCENTRIC
0x00000000 , 0x10841ffc , 0x10841084 , 0x1ffc1084 , 0x10841084 , 0x10841084 , 0x00001ffc , 0x00000000 , // ICON_BOX_GRID_BIG
0x00000000 , 0x00000000 , 0x10000000 , 0x04000800 , 0x01040200 , 0x00500088 , 0x00000020 , 0x00000000 , // ICON_OK_TICK
0x00000000 , 0x10080000 , 0x04200810 , 0x01800240 , 0x02400180 , 0x08100420 , 0x00001008 , 0x00000000 , // ICON_CROSS
0x00000000 , 0x02000000 , 0x00800100 , 0x00200040 , 0x00200010 , 0x00800040 , 0x02000100 , 0x00000000 , // ICON_ARROW_LEFT
0x00000000 , 0x00400000 , 0x01000080 , 0x04000200 , 0x04000800 , 0x01000200 , 0x00400080 , 0x00000000 , // ICON_ARROW_RIGHT
0x00000000 , 0x00000000 , 0x00000000 , 0x08081004 , 0x02200410 , 0x00800140 , 0x00000000 , 0x00000000 , // ICON_ARROW_DOWN
0x00000000 , 0x00000000 , 0x01400080 , 0x04100220 , 0x10040808 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_ARROW_UP
0x00000000 , 0x02000000 , 0x03800300 , 0x03e003c0 , 0x03e003f0 , 0x038003c0 , 0x02000300 , 0x00000000 , // ICON_ARROW_LEFT_FILL
0x00000000 , 0x00400000 , 0x01c000c0 , 0x07c003c0 , 0x07c00fc0 , 0x01c003c0 , 0x004000c0 , 0x00000000 , // ICON_ARROW_RIGHT_FILL
0x00000000 , 0x00000000 , 0x00000000 , 0x0ff81ffc , 0x03e007f0 , 0x008001c0 , 0x00000000 , 0x00000000 , // ICON_ARROW_DOWN_FILL
0x00000000 , 0x00000000 , 0x01c00080 , 0x07f003e0 , 0x1ffc0ff8 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_ARROW_UP_FILL
0x00000000 , 0x18a008c0 , 0x32881290 , 0x24822686 , 0x26862482 , 0x12903288 , 0x08c018a0 , 0x00000000 , // ICON_AUDIO
0x00000000 , 0x04800780 , 0x004000c0 , 0x662000f0 , 0x08103c30 , 0x130a0e18 , 0x0000318e , 0x00000000 , // ICON_FX
0x00000000 , 0x00800000 , 0x08880888 , 0x2aaa0a8a , 0x0a8a2aaa , 0x08880888 , 0x00000080 , 0x00000000 , // ICON_WAVE
0x00000000 , 0x00600000 , 0x01080090 , 0x02040108 , 0x42044204 , 0x24022402 , 0x00001800 , 0x00000000 , // ICON_WAVE_SINUS
0x00000000 , 0x07f80000 , 0x04080408 , 0x04080408 , 0x04080408 , 0x7c0e0408 , 0x00000000 , 0x00000000 , // ICON_WAVE_SQUARE
0x00000000 , 0x00000000 , 0x00a00040 , 0x22084110 , 0x08021404 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_WAVE_TRIANGULAR
0x00000000 , 0x00000000 , 0x04200000 , 0x01800240 , 0x02400180 , 0x00000420 , 0x00000000 , 0x00000000 , // ICON_CROSS_SMALL
0x00000000 , 0x18380000 , 0x12281428 , 0x10a81128 , 0x112810a8 , 0x14281228 , 0x00001838 , 0x00000000 , // ICON_PLAYER_PREVIOUS
0x00000000 , 0x18000000 , 0x11801600 , 0x10181060 , 0x10601018 , 0x16001180 , 0x00001800 , 0x00000000 , // ICON_PLAYER_PLAY_BACK
0x00000000 , 0x00180000 , 0x01880068 , 0x18080608 , 0x06081808 , 0x00680188 , 0x00000018 , 0x00000000 , // ICON_PLAYER_PLAY
0x00000000 , 0x1e780000 , 0x12481248 , 0x12481248 , 0x12481248 , 0x12481248 , 0x00001e78 , 0x00000000 , // ICON_PLAYER_PAUSE
0x00000000 , 0x1ff80000 , 0x10081008 , 0x10081008 , 0x10081008 , 0x10081008 , 0x00001ff8 , 0x00000000 , // ICON_PLAYER_STOP
0x00000000 , 0x1c180000 , 0x14481428 , 0x15081488 , 0x14881508 , 0x14281448 , 0x00001c18 , 0x00000000 , // ICON_PLAYER_NEXT
0x00000000 , 0x03c00000 , 0x08100420 , 0x10081008 , 0x10081008 , 0x04200810 , 0x000003c0 , 0x00000000 , // ICON_PLAYER_RECORD
0x00000000 , 0x0c3007e0 , 0x13c81818 , 0x14281668 , 0x14281428 , 0x1c381c38 , 0x08102244 , 0x00000000 , // ICON_MAGNET
0x07c00000 , 0x08200820 , 0x3ff80820 , 0x23882008 , 0x21082388 , 0x20082108 , 0x1ff02008 , 0x00000000 , // ICON_LOCK_CLOSE
0x07c00000 , 0x08000800 , 0x3ff80800 , 0x23882008 , 0x21082388 , 0x20082108 , 0x1ff02008 , 0x00000000 , // ICON_LOCK_OPEN
0x01c00000 , 0x0c180770 , 0x3086188c , 0x60832082 , 0x60034781 , 0x30062002 , 0x0c18180c , 0x01c00770 , // ICON_CLOCK
0x0a200000 , 0x1b201b20 , 0x04200e20 , 0x04200420 , 0x04700420 , 0x0e700e70 , 0x0e700e70 , 0x04200e70 , // ICON_TOOLS
0x01800000 , 0x3bdc318c , 0x0ff01ff8 , 0x7c3e1e78 , 0x1e787c3e , 0x1ff80ff0 , 0x318c3bdc , 0x00000180 , // ICON_GEAR
0x01800000 , 0x3ffc318c , 0x1c381ff8 , 0x781e1818 , 0x1818781e , 0x1ff81c38 , 0x318c3ffc , 0x00000180 , // ICON_GEAR_BIG
0x00000000 , 0x08080ff8 , 0x08081ffc , 0x0aa80aa8 , 0x0aa80aa8 , 0x0aa80aa8 , 0x08080aa8 , 0x00000ff8 , // ICON_BIN
0x00000000 , 0x00000000 , 0x20043ffc , 0x08043f84 , 0x04040f84 , 0x04040784 , 0x000007fc , 0x00000000 , // ICON_HAND_POINTER
0x00000000 , 0x24400400 , 0x00001480 , 0x6efe0e00 , 0x00000e00 , 0x24401480 , 0x00000400 , 0x00000000 , // ICON_LASER
0x00000000 , 0x03c00000 , 0x08300460 , 0x11181118 , 0x11181118 , 0x04600830 , 0x000003c0 , 0x00000000 , // ICON_COIN
0x00000000 , 0x10880080 , 0x06c00810 , 0x366c07e0 , 0x07e00240 , 0x00001768 , 0x04200240 , 0x00000000 , // ICON_EXPLOSION
0x00000000 , 0x3d280000 , 0x2528252c , 0x3d282528 , 0x05280528 , 0x05e80528 , 0x00000000 , 0x00000000 , // ICON_1UP
0x01800000 , 0x03c003c0 , 0x018003c0 , 0x0ff007e0 , 0x0bd00bd0 , 0x0a500bd0 , 0x02400240 , 0x02400240 , // ICON_PLAYER
0x01800000 , 0x03c003c0 , 0x118013c0 , 0x03c81ff8 , 0x07c003c8 , 0x04400440 , 0x0c080478 , 0x00000000 , // ICON_PLAYER_JUMP
0x3ff80000 , 0x30183ff8 , 0x30183018 , 0x3ff83ff8 , 0x03000300 , 0x03c003c0 , 0x03e00300 , 0x000003e0 , // ICON_KEY
0x3ff80000 , 0x3ff83ff8 , 0x33983ff8 , 0x3ff83398 , 0x3ff83ff8 , 0x00000540 , 0x0fe00aa0 , 0x00000fe0 , // ICON_DEMON
0x00000000 , 0x0ff00000 , 0x20041008 , 0x25442004 , 0x10082004 , 0x06000bf0 , 0x00000300 , 0x00000000 , // ICON_TEXT_POPUP
0x00000000 , 0x11440000 , 0x07f00be8 , 0x1c1c0e38 , 0x1c1c0c18 , 0x07f00e38 , 0x11440be8 , 0x00000000 , // ICON_GEAR_EX
0x00000000 , 0x20080000 , 0x0c601010 , 0x07c00fe0 , 0x07c007c0 , 0x0c600fe0 , 0x20081010 , 0x00000000 , // ICON_CRACK
0x00000000 , 0x20080000 , 0x0c601010 , 0x04400fe0 , 0x04405554 , 0x0c600fe0 , 0x20081010 , 0x00000000 , // ICON_CRACK_POINTS
0x00000000 , 0x00800080 , 0x01c001c0 , 0x1ffc3ffe , 0x03e007f0 , 0x07f003e0 , 0x0c180770 , 0x00000808 , // ICON_STAR
0x0ff00000 , 0x08180810 , 0x08100818 , 0x0a100810 , 0x08180810 , 0x08100818 , 0x08100810 , 0x00001ff8 , // ICON_DOOR
0x0ff00000 , 0x08100810 , 0x08100810 , 0x10100010 , 0x4f902010 , 0x10102010 , 0x08100010 , 0x00000ff0 , // ICON_EXIT
0x00040000 , 0x001f000e , 0x0ef40004 , 0x12f41284 , 0x0ef41214 , 0x10040004 , 0x7ffc3004 , 0x10003000 , // ICON_MODE_2D
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 , 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 , 0x3bf27be2 , 0x0bfe1bfa , 0x000007fe , // ICON_CUBE_FACE_BOTTOM
0x7fe00000 , 0x70286030 , 0x7ffe7804 , 0x7c227c02 , 0x7c227c22 , 0x3c127de2 , 0x0c061c0a , 0x000007fe , // ICON_CUBE_FACE_RIGHT
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
0x00000000 , 0x44007c00 , 0x45004600 , 0x00627cbe , 0x00620022 , 0x45007cbe , 0x44004600 , 0x00007c00 , // ICON_LINK_BOXES
0x00000000 , 0x0044007c , 0x0010007c , 0x3f100010 , 0x3f1021f0 , 0x3f100010 , 0x3f0021f0 , 0x00000000 , // ICON_LINK_MULTI
0x00000000 , 0x0044007c , 0x00440044 , 0x0010007c , 0x00100010 , 0x44107c10 , 0x440047f0 , 0x00007c00 , // ICON_LINK
0x00000000 , 0x0044007c , 0x00440044 , 0x0000007c , 0x00000010 , 0x44007c10 , 0x44004550 , 0x00007c00 , // ICON_LINK_BROKE
0x02a00000 , 0x22a43ffc , 0x20042004 , 0x20042ff4 , 0x20042ff4 , 0x20042ff4 , 0x20042004 , 0x00003ffc , // ICON_TEXT_NOTES
0x3ffc0000 , 0x20042004 , 0x245e27c4 , 0x27c42444 , 0x2004201e , 0x201e2004 , 0x20042004 , 0x00003ffc , // ICON_NOTEBOOK
0x00000000 , 0x07e00000 , 0x04200420 , 0x24243ffc , 0x24242424 , 0x24242424 , 0x3ffc2424 , 0x00000000 , // ICON_SUITCASE
0x00000000 , 0x0fe00000 , 0x08200820 , 0x40047ffc , 0x7ffc5554 , 0x40045554 , 0x7ffc4004 , 0x00000000 , // ICON_SUITCASE_ZIP
0x00000000 , 0x20043ffc , 0x3ffc2004 , 0x13c81008 , 0x100813c8 , 0x10081008 , 0x1ff81008 , 0x00000000 , // ICON_MAILBOX
0x00000000 , 0x40027ffe , 0x5ffa5ffa , 0x5ffa5ffa , 0x40025ffa , 0x03c07ffe , 0x1ff81ff8 , 0x00000000 , // ICON_MONITOR
0x0ff00000 , 0x6bfe7ffe , 0x7ffe7ffe , 0x68167ffe , 0x08106816 , 0x08100810 , 0x0ff00810 , 0x00000000 , // ICON_PRINTER
0x3ff80000 , 0xfffe2008 , 0x870a8002 , 0x904a888a , 0x904a904a , 0x870a888a , 0xfffe8002 , 0x00000000 , // ICON_PHOTO_CAMERA
0x0fc00000 , 0xfcfe0cd8 , 0x8002fffe , 0x84428382 , 0x84428442 , 0x80028382 , 0xfffe8002 , 0x00000000 , // ICON_PHOTO_CAMERA_FLASH
0x00000000 , 0x02400180 , 0x08100420 , 0x20041008 , 0x23c42004 , 0x22442244 , 0x3ffc2244 , 0x00000000 , // ICON_HOUSE
0x00000000 , 0x1c700000 , 0x3ff83ef8 , 0x3ff83ff8 , 0x0fe01ff0 , 0x038007c0 , 0x00000100 , 0x00000000 , // ICON_HEART
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x80000000 , 0xe000c000 , // ICON_CORNER
0x00000000 , 0x14001c00 , 0x15c01400 , 0x15401540 , 0x155c1540 , 0x15541554 , 0x1ddc1554 , 0x00000000 , // ICON_VERTICAL_BARS
0x00000000 , 0x03000300 , 0x1b001b00 , 0x1b601b60 , 0x1b6c1b60 , 0x1b6c1b6c , 0x1b6c1b6c , 0x00000000 , // ICON_VERTICAL_BARS_FILL
0x00000000 , 0x00000000 , 0x403e7ffe , 0x7ffe403e , 0x7ffe0000 , 0x43fe43fe , 0x00007ffe , 0x00000000 , // ICON_LIFE_BARS
0x7ffc0000 , 0x43844004 , 0x43844284 , 0x43844004 , 0x42844284 , 0x42844284 , 0x40044384 , 0x00007ffc , // ICON_INFO
0x40008000 , 0x10002000 , 0x04000800 , 0x01000200 , 0x00400080 , 0x00100020 , 0x00040008 , 0x00010002 , // ICON_CROSSLINE
0x00000000 , 0x1ff01ff0 , 0x18301830 , 0x1f001830 , 0x03001f00 , 0x00000300 , 0x03000300 , 0x00000000 , // ICON_HELP
0x3ff00000 , 0x2abc3550 , 0x2aac3554 , 0x2aac3554 , 0x2aac3554 , 0x2aac3554 , 0x2aac3554 , 0x00003ffc , // ICON_FILETYPE_ALPHA
0x3ff00000 , 0x201c2010 , 0x22442184 , 0x28142424 , 0x29942814 , 0x2ff42994 , 0x20042004 , 0x00003ffc , // ICON_FILETYPE_HOME
0x07fe0000 , 0x04020402 , 0x7fe20402 , 0x44224422 , 0x44224422 , 0x402047fe , 0x40204020 , 0x00007fe0 , // ICON_LAYERS_VISIBLE
0x07fe0000 , 0x04020402 , 0x7c020402 , 0x44024402 , 0x44024402 , 0x402047fe , 0x40204020 , 0x00007fe0 , // ICON_LAYERS
0x00000000 , 0x40027ffe , 0x7ffe4002 , 0x40024002 , 0x40024002 , 0x40024002 , 0x7ffe4002 , 0x00000000 , // ICON_WINDOW
0x09100000 , 0x09f00910 , 0x09100910 , 0x00000910 , 0x24a2779e , 0x27a224a2 , 0x709e20a2 , 0x00000000 , // ICON_HIDPI
0x3ff00000 , 0x201c2010 , 0x2a842e84 , 0x2e842a84 , 0x2ba42004 , 0x2aa42aa4 , 0x20042ba4 , 0x00003ffc , // ICON_FILETYPE_BINARY
0x00000000 , 0x00000000 , 0x00120012 , 0x4a5e4bd2 , 0x485233d2 , 0x00004bd2 , 0x00000000 , 0x00000000 , // ICON_HEX
0x01800000 , 0x381c0660 , 0x23c42004 , 0x23c42044 , 0x13c82204 , 0x08101008 , 0x02400420 , 0x00000180 , // ICON_SHIELD
0x007e0000 , 0x20023fc2 , 0x40227fe2 , 0x400a403a , 0x400a400a , 0x400a400a , 0x4008400e , 0x00007ff8 , // ICON_FILE_NEW
0x00000000 , 0x0042007e , 0x40027fc2 , 0x44024002 , 0x5f024402 , 0x44024402 , 0x7ffe4002 , 0x00000000 , // ICON_FOLDER_ADD
0x44220000 , 0x12482244 , 0xf3cf0000 , 0x14280420 , 0x48122424 , 0x08100810 , 0x1ff81008 , 0x03c00420 , // ICON_ALARM
0x0aa00000 , 0x1ff80aa0 , 0x1068700e , 0x1008706e , 0x1008700e , 0x1008700e , 0x0aa01ff8 , 0x00000aa0 , // ICON_CPU
0x07e00000 , 0x04201db8 , 0x04a01c38 , 0x04a01d38 , 0x04a01d38 , 0x04a01d38 , 0x04201d38 , 0x000007e0 , // ICON_ROM
0x00000000 , 0x03c00000 , 0x3c382ff0 , 0x3c04380c , 0x01800000 , 0x03c003c0 , 0x00000180 , 0x00000000 , // ICON_STEP_OVER
0x01800000 , 0x01800180 , 0x01800180 , 0x03c007e0 , 0x00000180 , 0x01800000 , 0x03c003c0 , 0x00000180 , // ICON_STEP_INTO
0x01800000 , 0x07e003c0 , 0x01800180 , 0x01800180 , 0x00000180 , 0x01800000 , 0x03c003c0 , 0x00000180 , // ICON_STEP_OUT
0x00000000 , 0x0ff003c0 , 0x181c1c34 , 0x303c301c , 0x30003000 , 0x1c301800 , 0x03c00ff0 , 0x00000000 , // ICON_RESTART
0x00000000 , 0x00000000 , 0x07e003c0 , 0x0ff00ff0 , 0x0ff00ff0 , 0x03c007e0 , 0x00000000 , 0x00000000 , // ICON_BREAKPOINT_ON
0x00000000 , 0x00000000 , 0x042003c0 , 0x08100810 , 0x08100810 , 0x03c00420 , 0x00000000 , 0x00000000 , // ICON_BREAKPOINT_OFF
0x00000000 , 0x00000000 , 0x1ff81ff8 , 0x1ff80000 , 0x00001ff8 , 0x1ff81ff8 , 0x00000000 , 0x00000000 , // ICON_BURGER_MENU
0x00000000 , 0x00000000 , 0x00880070 , 0x0c880088 , 0x1e8810f8 , 0x3e881288 , 0x00000000 , 0x00000000 , // ICON_CASE_SENSITIVE
0x00000000 , 0x02000000 , 0x07000a80 , 0x07001fc0 , 0x02000a80 , 0x00300030 , 0x00000000 , 0x00000000 , // ICON_REG_EXP
0x00000000 , 0x0042007e , 0x40027fc2 , 0x40024002 , 0x40024002 , 0x40024002 , 0x7ffe4002 , 0x00000000 , // ICON_FOLDER
0x3ff00000 , 0x201c2010 , 0x20042004 , 0x20042004 , 0x20042004 , 0x20042004 , 0x20042004 , 0x00003ffc , // ICON_FILE
0x1ff00000 , 0x20082008 , 0x17d02fe8 , 0x05400ba0 , 0x09200540 , 0x23881010 , 0x2fe827c8 , 0x00001ff0 , // ICON_SAND_TIMER
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_220
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_221
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_222
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_223
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_224
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_225
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_226
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_227
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_228
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_229
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_230
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_231
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_232
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_233
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_234
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_235
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_236
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_237
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_238
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_239
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_240
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_241
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_242
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_243
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_244
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_245
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_246
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_247
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_248
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_249
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_250
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_251
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_252
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_253
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_254
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_255
} ;
// NOTE: We keep a pointer to the icons array, useful to point to other sets if required
static unsigned int * guiIconsPtr = guiIcons ;
# endif // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS
# ifndef RAYGUI_ICON_SIZE
# define RAYGUI_ICON_SIZE 0
# endif
// 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
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Gui control property style color element
typedef enum { BORDER = 0 , BASE , TEXT , OTHER } GuiPropertyElement ;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static GuiState guiState = STATE_NORMAL ; // Gui global state, if !STATE_NORMAL, forces defined state
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 controls transparency
static unsigned int guiIconScale = 1 ; // Gui icon default scale (if icons enabled)
static bool guiTooltip = false ; // Tooltip enabled/disabled
static const char * guiTooltipPtr = NULL ; // Tooltip string pointer (string provided by user)
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 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
//----------------------------------------------------------------------------------
// Style data array for all gui style properties (allocated on data segment by default)
//
// NOTE 1: First set of BASE properties are generic to all controls but could be individually
// overwritten per control, first set of EXTENDED properties are generic to all controls and
// can not be overwritten individually but custom EXTENDED properties can be used by control
//
// NOTE 2: A new style set could be loaded over this array using GuiLoadStyle(),
// but default gui style could always be recovered with GuiLoadStyleDefault()
//
// guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB
//----------------------------------------------------------------------------------
static unsigned int guiStyle [ RAYGUI_MAX_CONTROLS * ( RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED ) ] = { 0 } ;
static bool guiStyleLoaded = false ; // Style loaded flag for lazy style initialization
//----------------------------------------------------------------------------------
// Standalone Mode Functions Declaration
//
// NOTE: raygui depend on some raylib input and drawing functions
// To use raygui as standalone library, below functions must be defined by the user
//----------------------------------------------------------------------------------
# if defined(RAYGUI_STANDALONE)
# define KEY_RIGHT 262
# define KEY_LEFT 263
# define KEY_DOWN 264
# define KEY_UP 265
# define KEY_BACKSPACE 259
# define KEY_ENTER 257
# define MOUSE_LEFT_BUTTON 0
// Input required functions
//-------------------------------------------------------------------------------
static Vector2 GetMousePosition ( void ) ;
static float GetMouseWheelMove ( void ) ;
static bool IsMouseButtonDown ( int button ) ;
static bool IsMouseButtonPressed ( int button ) ;
static bool IsMouseButtonReleased ( int button ) ;
static bool IsKeyDown ( int key ) ;
static bool IsKeyPressed ( int key ) ;
static int GetCharPressed ( void ) ; // -- GuiTextBox(), GuiValueBox()
//-------------------------------------------------------------------------------
// Drawing required functions
//-------------------------------------------------------------------------------
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 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 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
static int TextToInteger ( const char * text ) ; // Get integer value from text
static int GetCodepointNext ( const char * text , int * codepointSize ) ; // Get next codepoint in a UTF-8 encoded text
static const char * CodepointToUTF8 ( int codepoint , int * byteSize ) ; // Encode codepoint into UTF-8 text (char array size returned as parameter)
static void DrawRectangleGradientV ( int posX , int posY , int width , int height , Color color1 , Color color2 ) ; // Draw rectangle vertical gradient
//-------------------------------------------------------------------------------
# endif // RAYGUI_STANDALONE
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static void GuiLoadStyleFromMemory ( const unsigned char * fileData , int dataSize ) ; // Load style from memory (binary only)
static int GetTextWidth ( const char * text ) ; // Gui get text width using gui font and style
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 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
static Vector3 ConvertHSVtoRGB ( Vector3 hsv ) ; // Convert color data from HSV to RGB
static Vector3 ConvertRGBtoHSV ( Vector3 rgb ) ; // Convert color data from RGB to HSV
static int GuiScrollBar ( Rectangle bounds , int value , int minValue , int maxValue ) ; // Scroll bar control, used by GuiScrollPanel()
static void GuiTooltip ( Rectangle controlRec ) ; // Draw tooltip using control rec position
static Color GuiFade ( Color color , float alpha ) ; // Fade color by an alpha factor
//----------------------------------------------------------------------------------
// Gui Setup Functions Definition
//----------------------------------------------------------------------------------
// Enable gui global state
// NOTE: We check for STATE_DISABLED to avoid messing custom global state setups
void GuiEnable ( void ) { if ( guiState = = STATE_DISABLED ) guiState = STATE_NORMAL ; }
// Disable gui global state
// NOTE: We check for STATE_NORMAL to avoid messing custom global state setups
void GuiDisable ( void ) { if ( guiState = = STATE_NORMAL ) guiState = STATE_DISABLED ; }
// Lock gui global state
void GuiLock ( void ) { guiLocked = true ; }
// Unlock gui global state
void GuiUnlock ( void ) { guiLocked = false ; }
// Check if gui is locked (global state)
bool GuiIsLocked ( void ) { return guiLocked ; }
// Set gui controls alpha global state
void GuiSetAlpha ( float alpha )
{
if ( alpha < 0.0f ) alpha = 0.0f ;
else if ( alpha > 1.0f ) alpha = 1.0f ;
guiAlpha = alpha ;
}
// Set gui state (global state)
void GuiSetState ( int state ) { guiState = ( GuiState ) state ; }
// Get gui state (global state)
int GuiGetState ( void ) { return guiState ; }
// Set custom gui font
// NOTE: Font loading/unloading is external to raygui
void GuiSetFont ( Font font )
{
if ( font . texture . id > 0 )
{
// NOTE: If we try to setup a font but default style has not been
// lazily loaded before, it will be overwritten, so we need to force
// default style loading first
if ( ! guiStyleLoaded ) GuiLoadStyleDefault ( ) ;
guiFont = font ;
}
}
// Get custom gui font
Font GuiGetFont ( void )
{
return guiFont ;
}
// Set control style property value
void GuiSetStyle ( int control , int property , int value )
{
if ( ! guiStyleLoaded ) GuiLoadStyleDefault ( ) ;
guiStyle [ control * ( RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED ) + property ] = value ;
// Default properties are propagated to all controls
if ( ( control = = 0 ) & & ( property < RAYGUI_MAX_PROPS_BASE ) )
{
for ( int i = 1 ; i < RAYGUI_MAX_CONTROLS ; i + + ) guiStyle [ i * ( RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED ) + property ] = value ;
}
}
// Get control style property value
int GuiGetStyle ( int control , int property )
{
if ( ! guiStyleLoaded ) GuiLoadStyleDefault ( ) ;
return guiStyle [ control * ( RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED ) + property ] ;
}
//----------------------------------------------------------------------------------
// Gui Controls Functions Definition
//----------------------------------------------------------------------------------
// Window Box control
int GuiWindowBox ( Rectangle bounds , const char * title )
{
// Window title bar height (including borders)
// NOTE: This define is also used by GuiMessageBox() and GuiTextInputBox()
# if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT)
# define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24
# endif
int result = 0 ;
//GuiState state = guiState;
int statusBarHeight = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT ;
Rectangle statusBar = { bounds . x , bounds . y , bounds . width , ( float ) statusBarHeight } ;
if ( bounds . height < statusBarHeight * 2.0f ) bounds . height = statusBarHeight * 2.0f ;
Rectangle windowPanel = { bounds . x , bounds . y + ( float ) statusBarHeight - 1 , bounds . width , bounds . height - ( float ) statusBarHeight + 1 } ;
Rectangle closeButtonRec = { statusBar . x + statusBar . width - GuiGetStyle ( STATUSBAR , BORDER_WIDTH ) - 20 ,
statusBar . y + statusBarHeight / 2.0f - 18.0f / 2.0f , 18 , 18 } ;
// Update control
//--------------------------------------------------------------------
// NOTE: Logic is directly managed by button
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
GuiStatusBar ( statusBar , title ) ; // Draw window header as status bar
GuiPanel ( windowPanel , NULL ) ; // Draw window base
// Draw window close button
int tempBorderWidth = GuiGetStyle ( BUTTON , BORDER_WIDTH ) ;
int tempTextAlignment = GuiGetStyle ( BUTTON , TEXT_ALIGNMENT ) ;
GuiSetStyle ( BUTTON , BORDER_WIDTH , 1 ) ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
# if defined(RAYGUI_NO_ICONS)
result = GuiButton ( closeButtonRec , " x " ) ;
# else
result = GuiButton ( closeButtonRec , GuiIconText ( ICON_CROSS_SMALL , NULL ) ) ;
# endif
GuiSetStyle ( BUTTON , BORDER_WIDTH , tempBorderWidth ) ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , tempTextAlignment ) ;
//--------------------------------------------------------------------
return result ; // Window close button clicked: result = 1
}
// Group Box control with text name
int GuiGroupBox ( Rectangle bounds , const char * text )
{
# if !defined(RAYGUI_GROUPBOX_LINE_THICK)
# define RAYGUI_GROUPBOX_LINE_THICK 1
# endif
int result = 0 ;
GuiState state = guiState ;
// Draw control
//--------------------------------------------------------------------
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 ) ;
//--------------------------------------------------------------------
return result ;
}
// Line control
int GuiLine ( Rectangle bounds , const char * text )
{
# if !defined(RAYGUI_LINE_ORIGIN_SIZE)
# define RAYGUI_LINE_MARGIN_TEXT 12
# endif
# if !defined(RAYGUI_LINE_TEXT_PADDING)
# define RAYGUI_LINE_TEXT_PADDING 4
# endif
int result = 0 ;
GuiState state = guiState ;
Color color = GetColor ( GuiGetStyle ( DEFAULT , ( state = = STATE_DISABLED ) ? BORDER_COLOR_DISABLED : LINE_COLOR ) ) ;
// Draw control
//--------------------------------------------------------------------
if ( text = = NULL ) GuiDrawRectangle ( RAYGUI_CLITERAL ( Rectangle ) { bounds . x , bounds . y + bounds . height / 2 , bounds . width , 1 } , 0 , BLANK , color ) ;
else
{
Rectangle textBounds = { 0 } ;
textBounds . width = ( float ) GetTextWidth ( text ) + 2 ;
textBounds . height = bounds . height ;
textBounds . x = bounds . x + RAYGUI_LINE_MARGIN_TEXT ;
textBounds . y = bounds . y ;
// Draw line with embedded text label: "--- text --------------"
GuiDrawRectangle ( RAYGUI_CLITERAL ( Rectangle ) { bounds . x , bounds . y + bounds . height / 2 , RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING , 1 } , 0 , BLANK , color ) ;
GuiDrawText ( text , textBounds , TEXT_ALIGN_LEFT , color ) ;
GuiDrawRectangle ( RAYGUI_CLITERAL ( Rectangle ) { bounds . x + 12 + textBounds . width + 4 , bounds . y + bounds . height / 2 , bounds . width - textBounds . width - RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING , 1 } , 0 , BLANK , color ) ;
}
//--------------------------------------------------------------------
return result ;
}
// Panel control
int GuiPanel ( Rectangle bounds , const char * text )
{
# if !defined(RAYGUI_PANEL_BORDER_WIDTH)
# define RAYGUI_PANEL_BORDER_WIDTH 1
# endif
int result = 0 ;
GuiState state = guiState ;
// Text will be drawn as a header bar (if provided)
Rectangle statusBar = { bounds . x , bounds . y , bounds . width , ( float ) RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT } ;
if ( ( text ! = NULL ) & & ( bounds . height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT * 2.0f ) ) bounds . height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT * 2.0f ;
if ( text ! = NULL )
{
// Move panel bounds after the header bar
bounds . y + = ( 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 , GetColor ( GuiGetStyle ( DEFAULT , ( state = = STATE_DISABLED ) ? BORDER_COLOR_DISABLED : LINE_COLOR ) ) ,
GetColor ( GuiGetStyle ( DEFAULT , ( state = = STATE_DISABLED ) ? BASE_COLOR_DISABLED : BACKGROUND_COLOR ) ) ) ;
//--------------------------------------------------------------------
return result ;
}
// Tab Bar control
// NOTE: Using GuiToggle() for the TABS
int GuiTabBar ( Rectangle bounds , const char * * text , int count , int * active )
{
# define RAYGUI_TABBAR_ITEM_WIDTH 160
int result = - 1 ;
//GuiState state = guiState;
Rectangle tabBounds = { bounds . x , bounds . y , RAYGUI_TABBAR_ITEM_WIDTH , bounds . height } ;
if ( * active < 0 ) * active = 0 ;
else if ( * active > count - 1 ) * active = count - 1 ;
int offsetX = 0 ; // Required in case tabs go out of screen
offsetX = ( * active + 2 ) * RAYGUI_TABBAR_ITEM_WIDTH - GetScreenWidth ( ) ;
if ( offsetX < 0 ) offsetX = 0 ;
bool toggle = false ; // Required for individual toggles
// Draw control
//--------------------------------------------------------------------
for ( int i = 0 ; i < count ; i + + )
{
tabBounds . x = bounds . x + ( RAYGUI_TABBAR_ITEM_WIDTH + 4 ) * i - offsetX ;
if ( tabBounds . x < GetScreenWidth ( ) )
{
// Draw tabs as toggle controls
int textAlignment = GuiGetStyle ( TOGGLE , TEXT_ALIGNMENT ) ;
int textPadding = GuiGetStyle ( TOGGLE , TEXT_PADDING ) ;
GuiSetStyle ( TOGGLE , TEXT_ALIGNMENT , TEXT_ALIGN_LEFT ) ;
GuiSetStyle ( TOGGLE , TEXT_PADDING , 8 ) ;
if ( i = = ( * active ) )
{
toggle = true ;
GuiToggle ( tabBounds , GuiIconText ( 12 , text [ i ] ) , & toggle ) ;
}
else
{
toggle = false ;
GuiToggle ( tabBounds , GuiIconText ( 12 , text [ i ] ) , & toggle ) ;
if ( toggle ) * active = i ;
}
GuiSetStyle ( TOGGLE , TEXT_PADDING , textPadding ) ;
GuiSetStyle ( TOGGLE , TEXT_ALIGNMENT , textAlignment ) ;
// Draw tab close button
// 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 ) ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
# if defined(RAYGUI_NO_ICONS)
if ( GuiButton ( RAYGUI_CLITERAL ( Rectangle ) { tabBounds . x + tabBounds . width - 14 - 5 , tabBounds . y + 5 , 14 , 14 } , " x " ) ) result = i ;
# else
if ( GuiButton ( RAYGUI_CLITERAL ( Rectangle ) { tabBounds . x + tabBounds . width - 14 - 5 , tabBounds . y + 5 , 14 , 14 } , GuiIconText ( ICON_CROSS_SMALL , NULL ) ) ) result = i ;
# endif
GuiSetStyle ( BUTTON , BORDER_WIDTH , tempBorderWidth ) ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , tempTextAlignment ) ;
}
}
// Draw tab-bar bottom line
GuiDrawRectangle ( RAYGUI_CLITERAL ( Rectangle ) { bounds . x , bounds . y + bounds . height - 1 , bounds . width , 1 } , 0 , BLANK , GetColor ( GuiGetStyle ( TOGGLE , BORDER_COLOR_NORMAL ) ) ) ;
//--------------------------------------------------------------------
return result ; // Return as result the current TAB closing requested
}
// 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 ;
Vector2 scrollPos = { 0.0f , 0.0f } ;
if ( scroll ! = NULL ) scrollPos = * scroll ;
// Text will be drawn as a header bar (if provided)
Rectangle statusBar = { bounds . x , bounds . y , bounds . width , ( float ) RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT } ;
if ( bounds . height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT * 2.0f ) bounds . height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT * 2.0f ;
if ( text ! = NULL )
{
// Move panel bounds after the header bar
bounds . y + = ( float ) RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1 ;
bounds . height - = ( float ) RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + 1 ;
}
bool hasHorizontalScrollBar = ( content . width > bounds . width - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) ) ? true : false ;
bool hasVerticalScrollBar = ( content . height > bounds . height - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) ) ? true : false ;
// Recheck to account for the other scrollbar being visible
if ( ! hasHorizontalScrollBar ) hasHorizontalScrollBar = ( hasVerticalScrollBar & & ( content . width > ( bounds . width - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) - GuiGetStyle ( LISTVIEW , SCROLLBAR_WIDTH ) ) ) ) ? true : false ;
if ( ! hasVerticalScrollBar ) hasVerticalScrollBar = ( hasHorizontalScrollBar & & ( content . height > ( bounds . height - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) - GuiGetStyle ( LISTVIEW , SCROLLBAR_WIDTH ) ) ) ) ? true : false ;
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 )
} ;
// 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 ) ?
RAYGUI_CLITERAL ( Rectangle ) { bounds . x + verticalScrollBarWidth + GuiGetStyle ( DEFAULT , BORDER_WIDTH ) , bounds . y + GuiGetStyle ( DEFAULT , BORDER_WIDTH ) , bounds . width - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) - verticalScrollBarWidth , bounds . height - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) - horizontalScrollBarWidth } :
RAYGUI_CLITERAL ( Rectangle ) { bounds . x + GuiGetStyle ( DEFAULT , BORDER_WIDTH ) , bounds . y + GuiGetStyle ( DEFAULT , BORDER_WIDTH ) , bounds . width - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) - verticalScrollBarWidth , bounds . height - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) - horizontalScrollBarWidth } ;
// Clip view area to the actual content size
if ( view - > width > content . width ) view - > width = content . width ;
if ( view - > height > content . height ) view - > height = content . height ;
float horizontalMin = hasHorizontalScrollBar ? ( ( GuiGetStyle ( LISTVIEW , SCROLLBAR_SIDE ) = = SCROLLBAR_LEFT_SIDE ) ? ( float ) - verticalScrollBarWidth : 0 ) - ( float ) GuiGetStyle ( DEFAULT , BORDER_WIDTH ) : ( ( ( float ) GuiGetStyle ( LISTVIEW , SCROLLBAR_SIDE ) = = SCROLLBAR_LEFT_SIDE ) ? ( float ) - verticalScrollBarWidth : 0 ) - ( float ) GuiGetStyle ( DEFAULT , BORDER_WIDTH ) ;
float horizontalMax = hasHorizontalScrollBar ? content . width - bounds . width + ( float ) verticalScrollBarWidth + GuiGetStyle ( DEFAULT , BORDER_WIDTH ) - ( ( ( float ) GuiGetStyle ( LISTVIEW , SCROLLBAR_SIDE ) = = SCROLLBAR_LEFT_SIDE ) ? ( float ) verticalScrollBarWidth : 0 ) : ( float ) - GuiGetStyle ( DEFAULT , BORDER_WIDTH ) ;
float verticalMin = hasVerticalScrollBar ? 0.0f : - 1.0f ;
float verticalMax = hasVerticalScrollBar ? content . height - bounds . height + ( float ) horizontalScrollBarWidth + ( float ) GuiGetStyle ( DEFAULT , BORDER_WIDTH ) : ( float ) - GuiGetStyle ( DEFAULT , BORDER_WIDTH ) ;
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check button state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
# if defined(SUPPORT_SCROLLBAR_KEY_INPUT)
if ( hasHorizontalScrollBar )
{
if ( IsKeyDown ( KEY_RIGHT ) ) scrollPos . x - = GuiGetStyle ( SCROLLBAR , SCROLL_SPEED ) ;
if ( IsKeyDown ( KEY_LEFT ) ) scrollPos . x + = GuiGetStyle ( SCROLLBAR , SCROLL_SPEED ) ;
}
if ( hasVerticalScrollBar )
{
if ( IsKeyDown ( KEY_DOWN ) ) scrollPos . y - = GuiGetStyle ( SCROLLBAR , SCROLL_SPEED ) ;
if ( IsKeyDown ( KEY_UP ) ) scrollPos . y + = GuiGetStyle ( SCROLLBAR , SCROLL_SPEED ) ;
}
# endif
float wheelMove = GetMouseWheelMove ( ) ;
// 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
}
}
// Normalize scroll values
if ( scrollPos . x > - horizontalMin ) scrollPos . x = - horizontalMin ;
if ( scrollPos . x < - horizontalMax ) scrollPos . x = - horizontalMax ;
if ( scrollPos . y > - verticalMin ) scrollPos . y = - verticalMin ;
if ( scrollPos . y < - verticalMax ) scrollPos . y = - verticalMax ;
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
if ( text ! = NULL ) GuiStatusBar ( statusBar , text ) ; // Draw panel header as status bar
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 ) ;
// Draw horizontal scrollbar if visible
if ( hasHorizontalScrollBar )
{
// Change scrollbar slider size to show the diff in size between the content width and the widget width
GuiSetStyle ( SCROLLBAR , SCROLL_SLIDER_SIZE , ( int ) ( ( ( bounds . width - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) - verticalScrollBarWidth ) / ( int ) content . width ) * ( ( int ) bounds . width - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) - verticalScrollBarWidth ) ) ) ;
scrollPos . x = ( float ) - GuiScrollBar ( horizontalScrollBar , ( int ) - scrollPos . x , ( int ) horizontalMin , ( int ) horizontalMax ) ;
}
else scrollPos . x = 0.0f ;
// Draw vertical scrollbar if visible
if ( hasVerticalScrollBar )
{
// Change scrollbar slider size to show the diff in size between the content height and the widget height
GuiSetStyle ( SCROLLBAR , SCROLL_SLIDER_SIZE , ( int ) ( ( ( bounds . height - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) - horizontalScrollBarWidth ) / ( int ) content . height ) * ( ( int ) bounds . height - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH ) - horizontalScrollBarWidth ) ) ) ;
scrollPos . y = ( float ) - GuiScrollBar ( verticalScrollBar , ( int ) - scrollPos . y , ( int ) verticalMin , ( int ) verticalMax ) ;
}
else scrollPos . y = 0.0f ;
// Draw detail corner rectangle if both scroll bars are visible
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 , GetColor ( GuiGetStyle ( LISTVIEW , TEXT + ( state * 3 ) ) ) ) ;
}
// Draw scrollbar lines depending on current state
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 ) ;
//--------------------------------------------------------------------
if ( scroll ! = NULL ) * scroll = scrollPos ;
return result ;
}
// Label control
int GuiLabel ( Rectangle bounds , const char * text )
{
int result = 0 ;
GuiState state = guiState ;
// Update control
//--------------------------------------------------------------------
//...
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
GuiDrawText ( text , GetTextBounds ( LABEL , bounds ) , GuiGetStyle ( LABEL , TEXT_ALIGNMENT ) , GetColor ( GuiGetStyle ( LABEL , TEXT + ( state * 3 ) ) ) ) ;
//--------------------------------------------------------------------
return result ;
}
// Button control, returns true when clicked
int GuiButton ( Rectangle bounds , const char * text )
{
int result = 0 ;
GuiState state = guiState ;
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked & & ! guiSliderDragging )
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check button state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
if ( IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) ) result = 1 ;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
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 ) ;
//------------------------------------------------------------------
return result ; // Button pressed: result = 1
}
// Label button control
int GuiLabelButton ( Rectangle bounds , const char * text )
{
GuiState state = guiState ;
bool pressed = false ;
// NOTE: We force bounds.width to be all text
float textWidth = ( float ) GetTextWidth ( text ) ;
if ( ( bounds . width - 2 * GuiGetStyle ( LABEL , BORDER_WIDTH ) - 2 * GuiGetStyle ( LABEL , TEXT_PADDING ) ) < textWidth ) bounds . width = textWidth + 2 * GuiGetStyle ( LABEL , BORDER_WIDTH ) + 2 * GuiGetStyle ( LABEL , TEXT_PADDING ) + 2 ;
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked & & ! guiSliderDragging )
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check checkbox state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
if ( IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) ) pressed = true ;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
GuiDrawText ( text , GetTextBounds ( LABEL , bounds ) , GuiGetStyle ( LABEL , TEXT_ALIGNMENT ) , GetColor ( GuiGetStyle ( LABEL , TEXT + ( state * 3 ) ) ) ) ;
//--------------------------------------------------------------------
return pressed ;
}
// Toggle Button control, returns true when active
int GuiToggle ( Rectangle bounds , const char * text , bool * active )
{
int result = 0 ;
GuiState state = guiState ;
bool temp = false ;
if ( active = = NULL ) active = & temp ;
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked & & ! guiSliderDragging )
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check toggle button state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else if ( IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) )
{
state = STATE_NORMAL ;
* active = ! ( * active ) ;
}
else state = STATE_FOCUSED ;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
if ( state = = STATE_NORMAL )
{
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 ) , 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 ) ;
//--------------------------------------------------------------------
return result ;
}
// Toggle Group control, returns toggled button codepointIndex
int GuiToggleGroup ( Rectangle bounds , const char * text , int * active )
{
# if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS)
# define RAYGUI_TOGGLEGROUP_MAX_ITEMS 32
# endif
int result = 0 ;
float initBoundsX = bounds . x ;
int temp = 0 ;
if ( active = = NULL ) active = & temp ;
bool toggle = false ; // Required for individual toggles
// Get substrings items from text (items pointers)
int rows [ RAYGUI_TOGGLEGROUP_MAX_ITEMS ] = { 0 } ;
int itemCount = 0 ;
const char * * items = GuiTextSplit ( text , ' ; ' , & itemCount , rows ) ;
int prevRow = rows [ 0 ] ;
for ( int i = 0 ; i < itemCount ; i + + )
{
if ( prevRow ! = rows [ i ] )
{
bounds . x = initBoundsX ;
bounds . y + = ( bounds . height + GuiGetStyle ( TOGGLE , GROUP_PADDING ) ) ;
prevRow = rows [ i ] ;
}
if ( i = = ( * active ) )
{
toggle = true ;
GuiToggle ( bounds , items [ i ] , & toggle ) ;
}
else
{
toggle = false ;
GuiToggle ( bounds , items [ i ] , & toggle ) ;
if ( toggle ) * active = i ;
}
bounds . x + = ( bounds . width + GuiGetStyle ( TOGGLE , GROUP_PADDING ) ) ;
}
return result ;
}
// 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 ;
GuiState state = guiState ;
bool temp = false ;
if ( checked = = NULL ) checked = & temp ;
Rectangle textBounds = { 0 } ;
if ( text ! = NULL )
{
textBounds . width = ( float ) GetTextWidth ( text ) + 2 ;
textBounds . height = ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) ;
textBounds . x = bounds . x + bounds . width + GuiGetStyle ( CHECKBOX , TEXT_PADDING ) ;
textBounds . y = bounds . y + bounds . height / 2 - GuiGetStyle ( DEFAULT , TEXT_SIZE ) / 2 ;
if ( GuiGetStyle ( CHECKBOX , TEXT_ALIGNMENT ) = = TEXT_ALIGN_LEFT ) textBounds . x = bounds . x - textBounds . width - GuiGetStyle ( CHECKBOX , TEXT_PADDING ) ;
}
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked & & ! guiSliderDragging )
{
Vector2 mousePoint = GetMousePosition ( ) ;
Rectangle totalBounds = {
( GuiGetStyle ( CHECKBOX , TEXT_ALIGNMENT ) = = TEXT_ALIGN_LEFT ) ? textBounds . x : bounds . x ,
bounds . y ,
bounds . width + textBounds . width + GuiGetStyle ( CHECKBOX , TEXT_PADDING ) ,
bounds . height ,
} ;
// Check checkbox state
if ( CheckCollisionPointRec ( mousePoint , totalBounds ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
if ( IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) )
{
* checked = ! ( * checked ) ;
result = 1 ;
}
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
GuiDrawRectangle ( bounds , GuiGetStyle ( CHECKBOX , BORDER_WIDTH ) , GetColor ( GuiGetStyle ( CHECKBOX , BORDER + ( state * 3 ) ) ) , BLANK ) ;
if ( * checked )
{
Rectangle check = { bounds . x + GuiGetStyle ( CHECKBOX , BORDER_WIDTH ) + GuiGetStyle ( CHECKBOX , CHECK_PADDING ) ,
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 , GetColor ( GuiGetStyle ( CHECKBOX , TEXT + state * 3 ) ) ) ;
}
GuiDrawText ( text , textBounds , ( GuiGetStyle ( CHECKBOX , TEXT_ALIGNMENT ) = = TEXT_ALIGN_RIGHT ) ? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT , GetColor ( GuiGetStyle ( LABEL , TEXT + ( state * 3 ) ) ) ) ;
//--------------------------------------------------------------------
return result ;
}
// Combo Box control, returns selected item codepointIndex
int GuiComboBox ( Rectangle bounds , const char * text , int * active )
{
int result = 0 ;
GuiState state = guiState ;
int temp = 0 ;
if ( active = = NULL ) active = & temp ;
bounds . width - = ( GuiGetStyle ( COMBOBOX , COMBO_BUTTON_WIDTH ) + GuiGetStyle ( COMBOBOX , COMBO_BUTTON_SPACING ) ) ;
Rectangle selector = { ( float ) bounds . x + bounds . width + GuiGetStyle ( COMBOBOX , COMBO_BUTTON_SPACING ) ,
( float ) bounds . y , ( float ) GuiGetStyle ( COMBOBOX , COMBO_BUTTON_WIDTH ) , ( float ) bounds . height } ;
// Get substrings items from text (items pointers, lengths and count)
int itemCount = 0 ;
const char * * items = GuiTextSplit ( text , ' ; ' , & itemCount , NULL ) ;
if ( * active < 0 ) * active = 0 ;
else if ( * active > ( itemCount - 1 ) ) * active = itemCount - 1 ;
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked & & ( itemCount > 1 ) & & ! guiSliderDragging )
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( CheckCollisionPointRec ( mousePoint , bounds ) | |
CheckCollisionPointRec ( mousePoint , selector ) )
{
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) )
{
* active + = 1 ;
if ( * active > = itemCount ) * active = 0 ; // Cyclic combobox
}
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
// Draw combo box main
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
int tempBorderWidth = GuiGetStyle ( BUTTON , BORDER_WIDTH ) ;
int tempTextAlign = GuiGetStyle ( BUTTON , TEXT_ALIGNMENT ) ;
GuiSetStyle ( BUTTON , BORDER_WIDTH , 1 ) ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
GuiButton ( selector , TextFormat ( " %i/%i " , * active + 1 , itemCount ) ) ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , tempTextAlign ) ;
GuiSetStyle ( BUTTON , BORDER_WIDTH , tempBorderWidth ) ;
//--------------------------------------------------------------------
return result ;
}
// Dropdown Box control
// NOTE: Returns mouse click
int GuiDropdownBox ( Rectangle bounds , const char * text , int * active , bool editMode )
{
int result = 0 ;
GuiState state = guiState ;
int itemSelected = * active ;
int itemFocused = - 1 ;
// Get substrings items from text (items pointers, lengths and count)
int itemCount = 0 ;
const char * * items = GuiTextSplit ( text , ' ; ' , & itemCount , NULL ) ;
Rectangle boundsOpen = bounds ;
boundsOpen . height = ( itemCount + 1 ) * ( bounds . height + GuiGetStyle ( DROPDOWNBOX , DROPDOWN_ITEMS_SPACING ) ) ;
Rectangle itemBounds = bounds ;
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ( editMode | | ! guiLocked ) & & ( itemCount > 1 ) & & ! guiSliderDragging )
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( editMode )
{
state = STATE_PRESSED ;
// Check if mouse has been pressed or released outside limits
if ( ! CheckCollisionPointRec ( mousePoint , boundsOpen ) )
{
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) | | IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) ) result = 1 ;
}
// Check if already selected item has been pressed again
if ( CheckCollisionPointRec ( mousePoint , bounds ) & & IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) ) result = 1 ;
// Check focused and selected item
for ( int i = 0 ; i < itemCount ; i + + )
{
// Update item rectangle y position for next item
itemBounds . y + = ( bounds . height + GuiGetStyle ( DROPDOWNBOX , DROPDOWN_ITEMS_SPACING ) ) ;
if ( CheckCollisionPointRec ( mousePoint , itemBounds ) )
{
itemFocused = i ;
if ( IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) )
{
itemSelected = i ;
result = 1 ; // Item selected
}
break ;
}
}
itemBounds = bounds ;
}
else
{
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) )
{
result = 1 ;
state = STATE_PRESSED ;
}
else state = STATE_FOCUSED ;
}
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
if ( editMode ) GuiPanel ( boundsOpen , NULL ) ;
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 )
{
// Draw visible items
for ( int i = 0 ; i < itemCount ; i + + )
{
// Update item rectangle y position for next item
itemBounds . y + = ( bounds . height + GuiGetStyle ( DROPDOWNBOX , DROPDOWN_ITEMS_SPACING ) ) ;
if ( i = = itemSelected )
{
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 ) , 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 ( 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 , 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 , GetColor ( GuiGetStyle ( DROPDOWNBOX , TEXT + ( state * 3 ) ) ) ) ; // ICON_ARROW_DOWN_FILL
# endif
//--------------------------------------------------------------------
* active = itemSelected ;
// TODO: Use result to return more internal states: mouse-press out-of-bounds, mouse-press over selected-item...
return result ; // Mouse click: result = 1
}
// Text Box control
// NOTE: Returns true on ENTER pressed (useful for data validation)
int GuiTextBox ( Rectangle bounds , char * text , int bufferSize , bool editMode )
{
# if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)
# define RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN 40 // Frames to wait for autocursor movement
# endif
# if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY)
# define RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY 1 // Frames delay for autocursor movement
# endif
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
// Cursor rectangle
// NOTE: Position X value should be updated
Rectangle cursor = {
textBounds . x + textWidth + GuiGetStyle ( DEFAULT , TEXT_SPACING ) ,
textBounds . y + textBounds . height / 2 - GuiGetStyle ( DEFAULT , TEXT_SIZE ) ,
2 ,
( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) * 2
} ;
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 + + ;
else
{
autoCursorCooldownCounter = 0 ; // GLOBAL: Cursor cooldown counter
autoCursorDelayCounter = 0 ; // GLOBAL: Cursor delay counter
}
// Blink-cursor frame counter
//if (!autoCursorMode) blinkCursorFrameCounter++;
//else blinkCursorFrameCounter = 0;
// Update control
//--------------------------------------------------------------------
// 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 mousePosition = GetMousePosition ( ) ;
if ( editMode )
{
state = STATE_PRESSED ;
// If text does not fit in the textbox and current cursor position is out of bounds,
// we add an index offset to text for drawing only what requires depending on cursor
while ( textWidth > = textBounds . width )
{
int nextCodepointSize = 0 ;
GetCodepointNext ( text + textIndexOffset , & nextCodepointSize ) ;
textIndexOffset + = nextCodepointSize ;
textWidth = GetTextWidth ( text + textIndexOffset ) - GetTextWidth ( text + textBoxCursorIndex ) ;
}
int textLength = ( int ) strlen ( text ) ; // Get current text length
int codepoint = GetCharPressed ( ) ; // Get Unicode codepoint
if ( multiline & & IsKeyPressed ( KEY_ENTER ) ) codepoint = ( int ) ' \n ' ;
if ( textBoxCursorIndex > textLength ) textBoxCursorIndex = textLength ;
// Encode codepoint as UTF-8
int codepointSize = 0 ;
const char * charEncoded = CodepointToUTF8 ( codepoint , & codepointSize ) ;
// Add codepoint to text, at current cursor position
// NOTE: Make sure we do not overflow buffer size
if ( ( ( multiline & & ( codepoint = = ( int ) ' \n ' ) ) | | ( codepoint > = 32 ) ) & & ( ( textLength + codepointSize ) < bufferSize ) )
{
// Move forward data from cursor position
for ( int i = ( textLength + codepointSize ) ; i > textBoxCursorIndex ; i - - ) text [ i ] = text [ i - codepointSize ] ;
// Add new codepoint in current cursor position
for ( int i = 0 ; i < codepointSize ; i + + ) text [ textBoxCursorIndex + i ] = charEncoded [ i ] ;
textBoxCursorIndex + = codepointSize ;
textLength + = codepointSize ;
// Make sure text last character is EOL
text [ textLength ] = ' \0 ' ;
}
// Move cursor to start
if ( ( textLength > 0 ) & & IsKeyPressed ( KEY_HOME ) ) textBoxCursorIndex = 0 ;
// Move cursor to end
if ( ( textLength > textBoxCursorIndex ) & & IsKeyPressed ( KEY_END ) ) textBoxCursorIndex = textLength ;
// Delete codepoint from text, after current cursor position
if ( ( textLength > textBoxCursorIndex ) & & ( IsKeyPressed ( KEY_DELETE ) | | ( IsKeyDown ( KEY_DELETE ) & & ( autoCursorCooldownCounter > = RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN ) ) ) )
{
autoCursorDelayCounter + + ;
if ( IsKeyPressed ( KEY_DELETE ) | | ( autoCursorDelayCounter % RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY ) = = 0 ) // Delay every movement some frames
{
int nextCodepointSize = 0 ;
GetCodepointNext ( text + textBoxCursorIndex , & nextCodepointSize ) ;
// Move backward text from cursor position
for ( int i = textBoxCursorIndex ; i < textLength ; i + + ) text [ i ] = text [ i + nextCodepointSize ] ;
textLength - = codepointSize ;
// Make sure text last character is EOL
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 ) ) ) )
{
autoCursorDelayCounter + + ;
if ( IsKeyPressed ( KEY_BACKSPACE ) | | ( autoCursorDelayCounter % RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY ) = = 0 ) // Delay every movement some frames
{
int prevCodepointSize = 0 ;
GetCodepointPrevious ( text + textBoxCursorIndex , & prevCodepointSize ) ;
// Move backward text from cursor position
for ( int i = ( textBoxCursorIndex - prevCodepointSize ) ; i < textLength ; i + + ) text [ i ] = text [ i + prevCodepointSize ] ;
// Prevent cursor index from decrementing past 0
if ( textBoxCursorIndex > 0 )
{
textBoxCursorIndex - = codepointSize ;
textLength - = codepointSize ;
}
// Make sure text last character is EOL
text [ textLength ] = ' \0 ' ;
}
}
// Move cursor position with keys
if ( IsKeyPressed ( KEY_LEFT ) | | ( IsKeyDown ( KEY_LEFT ) & & ( autoCursorCooldownCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN ) ) )
{
autoCursorDelayCounter + + ;
if ( IsKeyPressed ( KEY_LEFT ) | | ( autoCursorDelayCounter % RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY ) = = 0 ) // Delay every movement some frames
{
int prevCodepointSize = 0 ;
GetCodepointPrevious ( text + textBoxCursorIndex , & prevCodepointSize ) ;
if ( textBoxCursorIndex > = prevCodepointSize ) textBoxCursorIndex - = prevCodepointSize ;
}
}
else if ( IsKeyPressed ( KEY_RIGHT ) | | ( IsKeyDown ( KEY_RIGHT ) & & ( autoCursorCooldownCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN ) ) )
{
autoCursorDelayCounter + + ;
if ( IsKeyPressed ( KEY_RIGHT ) | | ( autoCursorDelayCounter % RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY ) = = 0 ) // Delay every movement some frames
{
int nextCodepointSize = 0 ;
GetCodepointNext ( text + textBoxCursorIndex , & nextCodepointSize ) ;
if ( ( textBoxCursorIndex + nextCodepointSize ) < = textLength ) textBoxCursorIndex + = nextCodepointSize ;
}
}
// 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 ) ) ;
}
// 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 or mouse click outside bounds
if ( ( ! multiline & & IsKeyPressed ( KEY_ENTER ) ) | |
( ! CheckCollisionPointRec ( mousePosition , bounds ) & & IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) ) )
{
textBoxCursorIndex = 0 ; // GLOBAL: Reset the shared cursor index
result = 1 ;
}
}
else
{
if ( CheckCollisionPointRec ( mousePosition , bounds ) )
{
state = STATE_FOCUSED ;
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) )
{
textBoxCursorIndex = ( int ) strlen ( text ) ; // GLOBAL: Place cursor index to the end of current text
result = 1 ;
}
}
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
if ( state = = STATE_PRESSED )
{
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 ) , GetColor ( GuiGetStyle ( TEXTBOX , BORDER + ( state * 3 ) ) ) , GetColor ( GuiGetStyle ( TEXTBOX , BASE_COLOR_DISABLED ) ) ) ;
}
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 ) , GetColor ( GuiGetStyle ( TEXTBOX , TEXT + ( state * 3 ) ) ) ) ;
// Draw cursor
if ( editMode & & ! GuiGetStyle ( TEXTBOX , TEXT_READONLY ) )
{
//if (autoCursorMode || ((blinkCursorFrameCounter/40)%2 == 0))
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 ) ;
//--------------------------------------------------------------------
return result ; // Mouse button pressed: result = 1
}
/*
// 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_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 ( DEFAULT , TEXT_ALIGNMENT_VERTICAL , TEXT_ALIGN_MIDDLE ) ;
GuiSetStyle ( DEFAULT , TEXT_WRAP_MODE , TEXT_WRAP_NONE ) ;
GuiSetStyle ( TEXTBOX , TEXT_READONLY , 0 ) ;
return pressed ;
}
*/
// Spinner control, returns selected value
int GuiSpinner ( Rectangle bounds , const char * text , int * value , int minValue , int maxValue , bool editMode )
{
int result = 1 ;
GuiState state = guiState ;
int tempValue = * value ;
Rectangle spinner = { bounds . x + GuiGetStyle ( SPINNER , SPIN_BUTTON_WIDTH ) + GuiGetStyle ( SPINNER , SPIN_BUTTON_SPACING ) , bounds . y ,
bounds . width - 2 * ( GuiGetStyle ( SPINNER , SPIN_BUTTON_WIDTH ) + GuiGetStyle ( SPINNER , SPIN_BUTTON_SPACING ) ) , bounds . height } ;
Rectangle leftButtonBound = { ( float ) bounds . x , ( float ) bounds . y , ( float ) GuiGetStyle ( SPINNER , SPIN_BUTTON_WIDTH ) , ( float ) bounds . height } ;
Rectangle rightButtonBound = { ( float ) bounds . x + bounds . width - GuiGetStyle ( SPINNER , SPIN_BUTTON_WIDTH ) , ( float ) bounds . y , ( float ) GuiGetStyle ( SPINNER , SPIN_BUTTON_WIDTH ) , ( float ) bounds . height } ;
Rectangle textBounds = { 0 } ;
if ( text ! = NULL )
{
textBounds . width = ( float ) GetTextWidth ( text ) + 2 ;
textBounds . height = ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) ;
textBounds . x = bounds . x + bounds . width + GuiGetStyle ( SPINNER , TEXT_PADDING ) ;
textBounds . y = bounds . y + bounds . height / 2 - GuiGetStyle ( DEFAULT , TEXT_SIZE ) / 2 ;
if ( GuiGetStyle ( SPINNER , TEXT_ALIGNMENT ) = = TEXT_ALIGN_LEFT ) textBounds . x = bounds . x - textBounds . width - GuiGetStyle ( SPINNER , TEXT_PADDING ) ;
}
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked & & ! guiSliderDragging )
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check spinner state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
}
}
# if defined(RAYGUI_NO_ICONS)
if ( GuiButton ( leftButtonBound , " < " ) ) tempValue - - ;
if ( GuiButton ( rightButtonBound , " > " ) ) tempValue + + ;
# else
if ( GuiButton ( leftButtonBound , GuiIconText ( ICON_ARROW_LEFT_FILL , NULL ) ) ) tempValue - - ;
if ( GuiButton ( rightButtonBound , GuiIconText ( ICON_ARROW_RIGHT_FILL , NULL ) ) ) tempValue + + ;
# endif
if ( ! editMode )
{
if ( tempValue < minValue ) tempValue = minValue ;
if ( tempValue > maxValue ) tempValue = maxValue ;
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
result = GuiValueBox ( spinner , NULL , & tempValue , minValue , maxValue , editMode ) ;
// Draw value selector custom buttons
// NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
int tempBorderWidth = GuiGetStyle ( BUTTON , BORDER_WIDTH ) ;
int tempTextAlign = GuiGetStyle ( BUTTON , TEXT_ALIGNMENT ) ;
GuiSetStyle ( BUTTON , BORDER_WIDTH , GuiGetStyle ( SPINNER , BORDER_WIDTH ) ) ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , tempTextAlign ) ;
GuiSetStyle ( BUTTON , BORDER_WIDTH , tempBorderWidth ) ;
// Draw text label if provided
GuiDrawText ( text , textBounds , ( GuiGetStyle ( SPINNER , TEXT_ALIGNMENT ) = = TEXT_ALIGN_RIGHT ) ? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT , GetColor ( GuiGetStyle ( LABEL , TEXT + ( state * 3 ) ) ) ) ;
//--------------------------------------------------------------------
* value = tempValue ;
return result ;
}
// Value Box control, updates input text with numbers
// NOTE: Requires static variables: frameCounter
int GuiValueBox ( Rectangle bounds , const char * text , int * value , int minValue , int maxValue , bool editMode )
{
# if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
# define RAYGUI_VALUEBOX_MAX_CHARS 32
# endif
int result = 0 ;
GuiState state = guiState ;
char textValue [ RAYGUI_VALUEBOX_MAX_CHARS + 1 ] = " \0 " ;
sprintf ( textValue , " %i " , * value ) ;
Rectangle textBounds = { 0 } ;
if ( text ! = NULL )
{
textBounds . width = ( float ) GetTextWidth ( text ) + 2 ;
textBounds . height = ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) ;
textBounds . x = bounds . x + bounds . width + GuiGetStyle ( VALUEBOX , TEXT_PADDING ) ;
textBounds . y = bounds . y + bounds . height / 2 - GuiGetStyle ( DEFAULT , TEXT_SIZE ) / 2 ;
if ( GuiGetStyle ( VALUEBOX , TEXT_ALIGNMENT ) = = TEXT_ALIGN_LEFT ) textBounds . x = bounds . x - textBounds . width - GuiGetStyle ( VALUEBOX , TEXT_PADDING ) ;
}
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked & & ! guiSliderDragging )
{
Vector2 mousePoint = GetMousePosition ( ) ;
bool valueHasChanged = false ;
if ( editMode )
{
state = STATE_PRESSED ;
int keyCount = ( int ) strlen ( textValue ) ;
// Only allow keys in range [48..57]
if ( keyCount < RAYGUI_VALUEBOX_MAX_CHARS )
{
if ( GetTextWidth ( textValue ) < bounds . width )
{
int key = GetCharPressed ( ) ;
if ( ( key > = 48 ) & & ( key < = 57 ) )
{
textValue [ keyCount ] = ( char ) key ;
keyCount + + ;
valueHasChanged = true ;
}
}
}
// Delete text
if ( keyCount > 0 )
{
if ( IsKeyPressed ( KEY_BACKSPACE ) )
{
keyCount - - ;
textValue [ keyCount ] = ' \0 ' ;
valueHasChanged = true ;
}
}
if ( valueHasChanged ) * value = TextToInteger ( textValue ) ;
// NOTE: We are not clamp values until user input finishes
//if (*value > maxValue) *value = maxValue;
//else if (*value < minValue) *value = minValue;
if ( IsKeyPressed ( KEY_ENTER ) | | ( ! CheckCollisionPointRec ( mousePoint , bounds ) & & IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) ) ) result = 1 ;
}
else
{
if ( * value > maxValue ) * value = maxValue ;
else if ( * value < minValue ) * value = minValue ;
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
state = STATE_FOCUSED ;
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) ) result = 1 ;
}
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
Color baseColor = BLANK ;
if ( state = = STATE_PRESSED ) baseColor = GetColor ( GuiGetStyle ( VALUEBOX , BASE_COLOR_PRESSED ) ) ;
else if ( state = = STATE_DISABLED ) baseColor = GetColor ( GuiGetStyle ( VALUEBOX , BASE_COLOR_DISABLED ) ) ;
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 , 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 , GetColor ( GuiGetStyle ( LABEL , TEXT + ( state * 3 ) ) ) ) ;
//--------------------------------------------------------------------
return result ;
}
// Slider control with pro parameters
// NOTE: Other GuiSlider*() controls use this one
int GuiSliderPro ( Rectangle bounds , const char * textLeft , const char * textRight , float * value , float minValue , float maxValue , int sliderWidth )
{
int result = 0 ;
2023-10-13 18:15:54 +02:00
float oldValue = * value ;
2023-10-04 16:07:59 +02:00
GuiState state = guiState ;
float temp = ( maxValue - minValue ) / 2.0f ;
if ( value = = NULL ) value = & temp ;
int sliderValue = ( int ) ( ( ( * value - minValue ) / ( maxValue - minValue ) ) * ( bounds . width - 2 * GuiGetStyle ( SLIDER , BORDER_WIDTH ) ) ) ;
Rectangle slider = { bounds . x , bounds . y + GuiGetStyle ( SLIDER , BORDER_WIDTH ) + GuiGetStyle ( SLIDER , SLIDER_PADDING ) ,
0 , bounds . height - 2 * GuiGetStyle ( SLIDER , BORDER_WIDTH ) - 2 * GuiGetStyle ( SLIDER , SLIDER_PADDING ) } ;
if ( sliderWidth > 0 ) // Slider
{
slider . x + = ( sliderValue - sliderWidth / 2 ) ;
slider . width = ( float ) sliderWidth ;
}
else if ( sliderWidth = = 0 ) // SliderBar
{
slider . x + = GuiGetStyle ( SLIDER , BORDER_WIDTH ) ;
slider . width = ( float ) sliderValue ;
}
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( guiSliderDragging ) // Keep dragging outside of bounds
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) )
{
if ( CHECK_BOUNDS_ID ( bounds , guiSliderActive ) )
{
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 ;
}
}
else
{
guiSliderDragging = false ;
guiSliderActive = RAYGUI_CLITERAL ( Rectangle ) { 0 , 0 , 0 , 0 } ;
}
}
else if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) )
{
state = STATE_PRESSED ;
guiSliderDragging = true ;
guiSliderActive = bounds ; // Store bounds as an identifier when dragging starts
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
}
}
else state = STATE_FOCUSED ;
}
if ( * value > maxValue ) * value = maxValue ;
else if ( * value < minValue ) * value = minValue ;
}
2023-10-13 18:15:54 +02:00
// Control value change check
if ( oldValue = = * value ) result = 0 ;
else result = 1 ;
2023-10-04 16:07:59 +02:00
// Bar limits check
if ( sliderWidth > 0 ) // Slider
{
if ( slider . x < = ( bounds . x + GuiGetStyle ( SLIDER , BORDER_WIDTH ) ) ) slider . x = bounds . x + GuiGetStyle ( SLIDER , BORDER_WIDTH ) ;
else if ( ( slider . x + slider . width ) > = ( bounds . x + bounds . width ) ) slider . x = bounds . x + bounds . width - slider . width - GuiGetStyle ( SLIDER , BORDER_WIDTH ) ;
}
else if ( sliderWidth = = 0 ) // SliderBar
{
if ( slider . width > bounds . width ) slider . width = bounds . width - 2 * GuiGetStyle ( SLIDER , BORDER_WIDTH ) ;
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
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 ) 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 )
{
Rectangle textBounds = { 0 } ;
textBounds . width = ( float ) GetTextWidth ( textLeft ) ;
textBounds . height = ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) ;
textBounds . x = bounds . x - textBounds . width - GuiGetStyle ( SLIDER , TEXT_PADDING ) ;
textBounds . y = bounds . y + bounds . height / 2 - GuiGetStyle ( DEFAULT , TEXT_SIZE ) / 2 ;
GuiDrawText ( textLeft , textBounds , TEXT_ALIGN_RIGHT , GetColor ( GuiGetStyle ( SLIDER , TEXT + ( state * 3 ) ) ) ) ;
}
if ( textRight ! = NULL )
{
Rectangle textBounds = { 0 } ;
textBounds . width = ( float ) GetTextWidth ( textRight ) ;
textBounds . height = ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) ;
textBounds . x = bounds . x + bounds . width + GuiGetStyle ( SLIDER , TEXT_PADDING ) ;
textBounds . y = bounds . y + bounds . height / 2 - GuiGetStyle ( DEFAULT , TEXT_SIZE ) / 2 ;
GuiDrawText ( textRight , textBounds , TEXT_ALIGN_LEFT , GetColor ( GuiGetStyle ( SLIDER , TEXT + ( state * 3 ) ) ) ) ;
}
//--------------------------------------------------------------------
return result ;
}
// Slider control extended, returns selected value and has text
int GuiSlider ( Rectangle bounds , const char * textLeft , const char * textRight , float * value , float minValue , float maxValue )
{
return GuiSliderPro ( bounds , textLeft , textRight , value , minValue , maxValue , GuiGetStyle ( SLIDER , SLIDER_WIDTH ) ) ;
}
// Slider Bar control extended, returns selected value
int GuiSliderBar ( Rectangle bounds , const char * textLeft , const char * textRight , float * value , float minValue , float maxValue )
{
return GuiSliderPro ( bounds , textLeft , textRight , value , minValue , maxValue , 0 ) ;
}
// Progress Bar control extended, shows current progress value
int GuiProgressBar ( Rectangle bounds , const char * textLeft , const char * textRight , float * value , float minValue , float maxValue )
{
int result = 0 ;
GuiState state = guiState ;
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 ) } ;
// Update control
//--------------------------------------------------------------------
if ( * value > maxValue ) * value = maxValue ;
// WARNING: Working with floats could lead to rounding issues
2023-10-13 18:15:54 +02:00
if ( ( state ! = STATE_DISABLED ) ) progress . width = ( float ) ( * value / ( maxValue - minValue ) ) * bounds . width - ( ( * value > = maxValue ) ? ( float ) ( 2 * GuiGetStyle ( PROGRESSBAR , BORDER_WIDTH ) ) : 0.0f ) ;
2023-10-04 16:07:59 +02:00
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
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 ) ) ) ;
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 )
{
Rectangle textBounds = { 0 } ;
textBounds . width = ( float ) GetTextWidth ( textLeft ) ;
textBounds . height = ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) ;
textBounds . x = bounds . x - textBounds . width - GuiGetStyle ( PROGRESSBAR , TEXT_PADDING ) ;
textBounds . y = bounds . y + bounds . height / 2 - GuiGetStyle ( DEFAULT , TEXT_SIZE ) / 2 ;
GuiDrawText ( textLeft , textBounds , TEXT_ALIGN_RIGHT , GetColor ( GuiGetStyle ( PROGRESSBAR , TEXT + ( state * 3 ) ) ) ) ;
}
if ( textRight ! = NULL )
{
Rectangle textBounds = { 0 } ;
textBounds . width = ( float ) GetTextWidth ( textRight ) ;
textBounds . height = ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) ;
textBounds . x = bounds . x + bounds . width + GuiGetStyle ( PROGRESSBAR , TEXT_PADDING ) ;
textBounds . y = bounds . y + bounds . height / 2 - GuiGetStyle ( DEFAULT , TEXT_SIZE ) / 2 ;
GuiDrawText ( textRight , textBounds , TEXT_ALIGN_LEFT , GetColor ( GuiGetStyle ( PROGRESSBAR , TEXT + ( state * 3 ) ) ) ) ;
}
//--------------------------------------------------------------------
return result ;
}
// Status Bar control
int GuiStatusBar ( Rectangle bounds , const char * text )
{
int result = 0 ;
GuiState state = guiState ;
// Draw control
//--------------------------------------------------------------------
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 ;
}
// Dummy rectangle control, intended for placeholding
int GuiDummyRec ( Rectangle bounds , const char * text )
{
int result = 0 ;
GuiState state = guiState ;
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked & & ! guiSliderDragging )
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check button state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
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 ;
}
// List View control
int GuiListView ( Rectangle bounds , const char * text , int * scrollIndex , int * active )
{
int result = 0 ;
int itemCount = 0 ;
const char * * items = NULL ;
if ( text ! = NULL ) items = GuiTextSplit ( text , ' ; ' , & itemCount , NULL ) ;
result = GuiListViewEx ( bounds , items , itemCount , scrollIndex , active , NULL ) ;
return result ;
}
// List View control with extended parameters
int GuiListViewEx ( Rectangle bounds , const char * * text , int count , int * scrollIndex , int * active , int * focus )
{
int result = 0 ;
GuiState state = guiState ;
int itemFocused = ( focus = = NULL ) ? - 1 : * focus ;
int itemSelected = ( active = = NULL ) ? - 1 : * active ;
// Check if we need a scroll bar
bool useScrollBar = false ;
if ( ( GuiGetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT ) + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) ) * count > bounds . height ) useScrollBar = true ;
// Define base item rectangle [0]
Rectangle itemBounds = { 0 } ;
itemBounds . x = bounds . x + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) ;
itemBounds . y = bounds . y + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) + GuiGetStyle ( DEFAULT , BORDER_WIDTH ) ;
itemBounds . width = bounds . width - 2 * GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) - GuiGetStyle ( DEFAULT , BORDER_WIDTH ) ;
itemBounds . height = ( float ) GuiGetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT ) ;
if ( useScrollBar ) itemBounds . width - = GuiGetStyle ( LISTVIEW , SCROLLBAR_WIDTH ) ;
// Get items on the list
int visibleItems = ( int ) bounds . height / ( GuiGetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT ) + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) ) ;
if ( visibleItems > count ) visibleItems = count ;
int startIndex = ( scrollIndex = = NULL ) ? 0 : * scrollIndex ;
if ( ( startIndex < 0 ) | | ( startIndex > ( count - visibleItems ) ) ) startIndex = 0 ;
int endIndex = startIndex + visibleItems ;
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked & & ! guiSliderDragging )
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check mouse inside list view
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
state = STATE_FOCUSED ;
// Check focused and selected item
for ( int i = 0 ; i < visibleItems ; i + + )
{
if ( CheckCollisionPointRec ( mousePoint , itemBounds ) )
{
itemFocused = startIndex + i ;
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) )
{
if ( itemSelected = = ( startIndex + i ) ) itemSelected = - 1 ;
else itemSelected = startIndex + i ;
}
break ;
}
// Update item rectangle y position for next item
itemBounds . y + = ( GuiGetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT ) + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) ) ;
}
if ( useScrollBar )
{
int wheelMove = ( int ) GetMouseWheelMove ( ) ;
startIndex - = wheelMove ;
if ( startIndex < 0 ) startIndex = 0 ;
else if ( startIndex > ( count - visibleItems ) ) startIndex = count - visibleItems ;
endIndex = startIndex + visibleItems ;
if ( endIndex > count ) endIndex = count ;
}
}
else itemFocused = - 1 ;
// Reset item rectangle y to [0]
itemBounds . y = bounds . y + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) + GuiGetStyle ( DEFAULT , BORDER_WIDTH ) ;
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
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 ) , GetColor ( GuiGetStyle ( LISTVIEW , BORDER_COLOR_DISABLED ) ) , GetColor ( GuiGetStyle ( LISTVIEW , BASE_COLOR_DISABLED ) ) ) ;
GuiDrawText ( text [ startIndex + i ] , GetTextBounds ( DEFAULT , itemBounds ) , GuiGetStyle ( LISTVIEW , TEXT_ALIGNMENT ) , GetColor ( GuiGetStyle ( LISTVIEW , TEXT_COLOR_DISABLED ) ) ) ;
}
else
{
if ( ( ( startIndex + i ) = = itemSelected ) & & ( active ! = NULL ) )
{
// Draw item selected
GuiDrawRectangle ( itemBounds , GuiGetStyle ( LISTVIEW , BORDER_WIDTH ) , GetColor ( GuiGetStyle ( LISTVIEW , BORDER_COLOR_PRESSED ) ) , GetColor ( GuiGetStyle ( LISTVIEW , BASE_COLOR_PRESSED ) ) ) ;
GuiDrawText ( text [ startIndex + i ] , GetTextBounds ( DEFAULT , itemBounds ) , GuiGetStyle ( LISTVIEW , TEXT_ALIGNMENT ) , GetColor ( GuiGetStyle ( LISTVIEW , TEXT_COLOR_PRESSED ) ) ) ;
}
else if ( ( ( startIndex + i ) = = itemFocused ) ) // && (focus != NULL)) // NOTE: We want items focused, despite not returned!
{
// Draw item focused
GuiDrawRectangle ( itemBounds , GuiGetStyle ( LISTVIEW , BORDER_WIDTH ) , GetColor ( GuiGetStyle ( LISTVIEW , BORDER_COLOR_FOCUSED ) ) , GetColor ( GuiGetStyle ( LISTVIEW , BASE_COLOR_FOCUSED ) ) ) ;
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 ) , GetColor ( GuiGetStyle ( LISTVIEW , TEXT_COLOR_NORMAL ) ) ) ;
}
}
// Update item rectangle y position for next item
itemBounds . y + = ( GuiGetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT ) + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) ) ;
}
if ( useScrollBar )
{
Rectangle scrollBarBounds = {
bounds . x + bounds . width - GuiGetStyle ( LISTVIEW , BORDER_WIDTH ) - GuiGetStyle ( LISTVIEW , SCROLLBAR_WIDTH ) ,
bounds . y + GuiGetStyle ( LISTVIEW , BORDER_WIDTH ) , ( float ) GuiGetStyle ( LISTVIEW , SCROLLBAR_WIDTH ) ,
bounds . height - 2 * GuiGetStyle ( DEFAULT , BORDER_WIDTH )
} ;
// Calculate percentage of visible items and apply same percentage to scrollbar
float percentVisible = ( float ) ( endIndex - startIndex ) / count ;
float sliderSize = bounds . height * percentVisible ;
int prevSliderSize = GuiGetStyle ( SCROLLBAR , SCROLL_SLIDER_SIZE ) ; // Save default slider size
int prevScrollSpeed = GuiGetStyle ( SCROLLBAR , SCROLL_SPEED ) ; // Save default scroll speed
GuiSetStyle ( SCROLLBAR , SCROLL_SLIDER_SIZE , ( int ) sliderSize ) ; // Change slider size
GuiSetStyle ( SCROLLBAR , SCROLL_SPEED , count - visibleItems ) ; // Change scroll speed
startIndex = GuiScrollBar ( scrollBarBounds , startIndex , 0 , count - visibleItems ) ;
GuiSetStyle ( SCROLLBAR , SCROLL_SPEED , prevScrollSpeed ) ; // Reset scroll speed to default
GuiSetStyle ( SCROLLBAR , SCROLL_SLIDER_SIZE , prevSliderSize ) ; // Reset slider size to default
}
//--------------------------------------------------------------------
if ( active ! = NULL ) * active = itemSelected ;
if ( focus ! = NULL ) * focus = itemFocused ;
if ( scrollIndex ! = NULL ) * scrollIndex = startIndex ;
return result ;
}
// Color Panel control
int GuiColorPanel ( Rectangle bounds , const char * text , Color * color )
{
int result = 0 ;
GuiState state = guiState ;
Vector2 pickerSelector = { 0 } ;
const Color colWhite = { 255 , 255 , 255 , 255 } ;
const Color colBlack = { 0 , 0 , 0 , 255 } ;
Vector3 vcolor = { ( float ) color - > r / 255.0f , ( float ) color - > g / 255.0f , ( float ) color - > b / 255.0f } ;
Vector3 hsv = ConvertRGBtoHSV ( vcolor ) ;
pickerSelector . x = bounds . x + ( float ) hsv . y * bounds . width ; // HSV: Saturation
pickerSelector . y = bounds . y + ( 1.0f - ( float ) hsv . z ) * bounds . height ; // HSV: Value
float hue = - 1.0f ;
2023-10-13 18:15:54 +02:00
Vector3 maxHue = { ( hue > = 0.0f ) ? hue : hsv . x , 1.0f , 1.0f } ;
2023-10-04 16:07:59 +02:00
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
hsv . y = colorPick . x ;
hsv . z = 1.0f - colorPick . y ;
Vector3 rgb = ConvertHSVtoRGB ( hsv ) ;
// NOTE: Vector3ToColor() only available on raylib 1.8.1
* color = RAYGUI_CLITERAL ( Color ) { ( unsigned char ) ( 255.0f * rgb . x ) ,
( unsigned char ) ( 255.0f * rgb . y ) ,
( unsigned char ) ( 255.0f * rgb . z ) ,
( unsigned char ) ( 255.0f * ( float ) color - > a / 255.0f ) } ;
}
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 ;
}
// Color Bar Alpha control
// NOTE: Returns alpha value normalized [0..1]
int GuiColorBarAlpha ( Rectangle bounds , const char * text , float * alpha )
{
# if !defined(RAYGUI_COLORBARALPHA_CHECKED_SIZE)
# define RAYGUI_COLORBARALPHA_CHECKED_SIZE 10
# endif
int result = 0 ;
GuiState state = guiState ;
Rectangle selector = { ( float ) bounds . x + ( * alpha ) * bounds . width - GuiGetStyle ( COLORPICKER , HUEBAR_SELECTOR_HEIGHT ) / 2 , ( float ) bounds . y - GuiGetStyle ( COLORPICKER , HUEBAR_SELECTOR_OVERFLOW ) , ( float ) GuiGetStyle ( COLORPICKER , HUEBAR_SELECTOR_HEIGHT ) , ( float ) bounds . height + GuiGetStyle ( COLORPICKER , HUEBAR_SELECTOR_OVERFLOW ) * 2 } ;
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( guiSliderDragging ) // Keep dragging outside of bounds
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) )
{
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 ;
}
}
else
{
guiSliderDragging = false ;
guiSliderActive = RAYGUI_CLITERAL ( Rectangle ) { 0 , 0 , 0 , 0 } ;
}
}
else if ( CheckCollisionPointRec ( mousePoint , bounds ) | | CheckCollisionPointRec ( mousePoint , selector ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) )
{
state = STATE_PRESSED ;
guiSliderDragging = true ;
guiSliderActive = bounds ; // Store bounds as an identifier when dragging starts
* alpha = ( mousePoint . x - bounds . x ) / bounds . width ;
if ( * alpha < = 0.0f ) * alpha = 0.0f ;
if ( * alpha > = 1.0f ) * alpha = 1.0f ;
//selector.x = bounds.x + (int)(((alpha - 0)/(100 - 0))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))) - selector.width/2;
}
else state = STATE_FOCUSED ;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
// Draw alpha bar: checked background
if ( state ! = STATE_DISABLED )
{
int checksX = ( int ) bounds . width / RAYGUI_COLORBARALPHA_CHECKED_SIZE ;
int checksY = ( int ) bounds . height / RAYGUI_COLORBARALPHA_CHECKED_SIZE ;
for ( int x = 0 ; x < checksX ; x + + )
{
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 ( GetColor ( GuiGetStyle ( COLORPICKER , BORDER_COLOR_DISABLED ) ) , 0.4f ) : Fade ( GetColor ( GuiGetStyle ( COLORPICKER , BASE_COLOR_DISABLED ) ) , 0.4f ) ) ;
}
}
DrawRectangleGradientEx ( bounds , RAYGUI_CLITERAL ( Color ) { 255 , 255 , 255 , 0 } , RAYGUI_CLITERAL ( Color ) { 255 , 255 , 255 , 0 } , Fade ( RAYGUI_CLITERAL ( Color ) { 0 , 0 , 0 , 255 } , guiAlpha ) , Fade ( RAYGUI_CLITERAL ( Color ) { 0 , 0 , 0 , 255 } , guiAlpha ) ) ;
}
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 ) , GetColor ( GuiGetStyle ( COLORPICKER , BORDER + state * 3 ) ) , BLANK ) ;
// Draw alpha bar: selector
GuiDrawRectangle ( selector , 0 , BLANK , GetColor ( GuiGetStyle ( COLORPICKER , BORDER + state * 3 ) ) ) ;
//--------------------------------------------------------------------
return result ;
}
// Color Bar Hue control
// Returns hue value normalized [0..1]
// NOTE: Other similar bars (for reference):
// Color GuiColorBarSat() [WHITE->color]
// Color GuiColorBarValue() [BLACK->color], HSV/HSL
// float GuiColorBarLuminance() [BLACK->WHITE]
int GuiColorBarHue ( Rectangle bounds , const char * text , float * hue )
{
int result = 0 ;
GuiState state = guiState ;
Rectangle selector = { ( float ) bounds . x - GuiGetStyle ( COLORPICKER , HUEBAR_SELECTOR_OVERFLOW ) , ( float ) bounds . y + ( * hue ) / 360.0f * bounds . height - GuiGetStyle ( COLORPICKER , HUEBAR_SELECTOR_HEIGHT ) / 2 , ( float ) bounds . width + GuiGetStyle ( COLORPICKER , HUEBAR_SELECTOR_OVERFLOW ) * 2 , ( float ) GuiGetStyle ( COLORPICKER , HUEBAR_SELECTOR_HEIGHT ) } ;
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( guiSliderDragging ) // Keep dragging outside of bounds
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) )
{
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 ;
}
}
else
{
guiSliderDragging = false ;
guiSliderActive = RAYGUI_CLITERAL ( Rectangle ) { 0 , 0 , 0 , 0 } ;
}
}
else if ( CheckCollisionPointRec ( mousePoint , bounds ) | | CheckCollisionPointRec ( mousePoint , selector ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) )
{
state = STATE_PRESSED ;
guiSliderDragging = true ;
guiSliderActive = bounds ; // Store bounds as an identifier when dragging starts
* hue = ( mousePoint . y - bounds . y ) * 360 / bounds . height ;
if ( * hue < = 0.0f ) * hue = 0.0f ;
if ( * hue > = 359.0f ) * hue = 359.0f ;
}
else state = STATE_FOCUSED ;
/*if (IsKeyDown(KEY_UP))
{
hue - = 2.0f ;
if ( hue < = 0.0f ) hue = 0.0f ;
}
else if ( IsKeyDown ( KEY_DOWN ) )
{
hue + = 2.0f ;
if ( hue > = 360.0f ) hue = 360.0f ;
} */
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
if ( state ! = STATE_DISABLED )
{
// Draw hue bar:color bars
// 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 ) ) ;
DrawRectangleGradientV ( ( int ) bounds . x , ( int ) ( bounds . y + 4 * ( bounds . height / 6 ) ) , ( int ) bounds . width , ( int ) ceilf ( bounds . height / 6 ) , Fade ( RAYGUI_CLITERAL ( Color ) { 0 , 0 , 255 , 255 } , guiAlpha ) , Fade ( RAYGUI_CLITERAL ( Color ) { 255 , 0 , 255 , 255 } , guiAlpha ) ) ;
DrawRectangleGradientV ( ( int ) bounds . x , ( int ) ( bounds . y + 5 * ( bounds . height / 6 ) ) , ( int ) bounds . width , ( int ) ( bounds . height / 6 ) , Fade ( RAYGUI_CLITERAL ( Color ) { 255 , 0 , 255 , 255 } , guiAlpha ) , Fade ( RAYGUI_CLITERAL ( Color ) { 255 , 0 , 0 , 255 } , guiAlpha ) ) ;
}
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 ) , GetColor ( GuiGetStyle ( COLORPICKER , BORDER + state * 3 ) ) , BLANK ) ;
// Draw hue bar: selector
GuiDrawRectangle ( selector , 0 , BLANK , GetColor ( GuiGetStyle ( COLORPICKER , BORDER + state * 3 ) ) ) ;
//--------------------------------------------------------------------
return result ;
}
// Color Picker control
// NOTE: It's divided in multiple controls:
// Color GuiColorPanel(Rectangle bounds, Color color)
// float GuiColorBarAlpha(Rectangle bounds, float alpha)
// float GuiColorBarHue(Rectangle bounds, float value)
// NOTE: bounds define GuiColorPanel() size
int GuiColorPicker ( Rectangle bounds , const char * text , Color * color )
{
int result = 0 ;
Color temp = { 200 , 0 , 0 , 255 } ;
if ( color = = NULL ) color = & temp ;
GuiColorPanel ( bounds , NULL , color ) ;
Rectangle boundsHue = { ( float ) bounds . x + bounds . width + GuiGetStyle ( COLORPICKER , HUEBAR_PADDING ) , ( float ) bounds . y , ( float ) GuiGetStyle ( COLORPICKER , HUEBAR_WIDTH ) , ( float ) bounds . height } ;
//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 ) ;
* color = RAYGUI_CLITERAL ( Color ) { ( unsigned char ) roundf ( rgb . x * 255.0f ) , ( unsigned char ) roundf ( rgb . y * 255.0f ) , ( unsigned char ) roundf ( rgb . z * 255.0f ) , ( * color ) . a } ;
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 ;
2023-10-13 18:15:54 +02:00
Vector3 maxHue = { ( hue > = 0.0f ) ? hue : colorHsv - > x , 1.0f , 1.0f } ;
2023-10-04 16:07:59 +02:00
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 )
{
# if !defined(RAYGUI_MESSAGEBOX_BUTTON_HEIGHT)
# define RAYGUI_MESSAGEBOX_BUTTON_HEIGHT 24
# endif
# if !defined(RAYGUI_MESSAGEBOX_BUTTON_PADDING)
# define RAYGUI_MESSAGEBOX_BUTTON_PADDING 12
# endif
int result = - 1 ; // Returns clicked button from buttons list, 0 refers to closed window button
int buttonCount = 0 ;
const char * * buttonsText = GuiTextSplit ( buttons , ' ; ' , & buttonCount , NULL ) ;
Rectangle buttonBounds = { 0 } ;
buttonBounds . x = bounds . x + RAYGUI_MESSAGEBOX_BUTTON_PADDING ;
buttonBounds . y = bounds . y + bounds . height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING ;
buttonBounds . width = ( bounds . width - RAYGUI_MESSAGEBOX_BUTTON_PADDING * ( buttonCount + 1 ) ) / buttonCount ;
buttonBounds . height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT ;
int textWidth = GetTextWidth ( message ) + 2 ;
Rectangle textBounds = { 0 } ;
textBounds . x = bounds . x + bounds . width / 2 - textWidth / 2 ;
textBounds . y = bounds . y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING ;
textBounds . width = ( float ) textWidth ;
textBounds . height = bounds . height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 3 * RAYGUI_MESSAGEBOX_BUTTON_PADDING - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT ;
// Draw control
//--------------------------------------------------------------------
if ( GuiWindowBox ( bounds , title ) ) result = 0 ;
int prevTextAlignment = GuiGetStyle ( LABEL , TEXT_ALIGNMENT ) ;
GuiSetStyle ( LABEL , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
GuiLabel ( textBounds , message ) ;
GuiSetStyle ( LABEL , TEXT_ALIGNMENT , prevTextAlignment ) ;
prevTextAlignment = GuiGetStyle ( BUTTON , TEXT_ALIGNMENT ) ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
for ( int i = 0 ; i < buttonCount ; i + + )
{
if ( GuiButton ( buttonBounds , buttonsText [ i ] ) ) result = i + 1 ;
buttonBounds . x + = ( buttonBounds . width + RAYGUI_MESSAGEBOX_BUTTON_PADDING ) ;
}
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , prevTextAlignment ) ;
//--------------------------------------------------------------------
return result ;
}
// Text Input Box control, ask for text
int GuiTextInputBox ( Rectangle bounds , const char * title , const char * message , const char * buttons , char * text , int textMaxSize , bool * secretViewActive )
{
# if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT)
# define RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT 24
# endif
# if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_PADDING)
# define RAYGUI_TEXTINPUTBOX_BUTTON_PADDING 12
# endif
# if !defined(RAYGUI_TEXTINPUTBOX_HEIGHT)
# define RAYGUI_TEXTINPUTBOX_HEIGHT 26
# endif
// Used to enable text edit mode
// WARNING: No more than one GuiTextInputBox() should be open at the same time
static bool textEditMode = false ;
int result = - 1 ;
int buttonCount = 0 ;
const char * * buttonsText = GuiTextSplit ( buttons , ' ; ' , & buttonCount , NULL ) ;
Rectangle buttonBounds = { 0 } ;
buttonBounds . x = bounds . x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING ;
buttonBounds . y = bounds . y + bounds . height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING ;
buttonBounds . width = ( bounds . width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING * ( buttonCount + 1 ) ) / buttonCount ;
buttonBounds . height = RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT ;
int messageInputHeight = ( int ) bounds . height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - GuiGetStyle ( STATUSBAR , BORDER_WIDTH ) - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - 2 * RAYGUI_TEXTINPUTBOX_BUTTON_PADDING ;
Rectangle textBounds = { 0 } ;
if ( message ! = NULL )
{
int textSize = GetTextWidth ( message ) + 2 ;
textBounds . x = bounds . x + bounds . width / 2 - textSize / 2 ;
textBounds . y = bounds . y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight / 4 - ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) / 2 ;
textBounds . width = ( float ) textSize ;
textBounds . height = ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) ;
}
Rectangle textBoxBounds = { 0 } ;
textBoxBounds . x = bounds . x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING ;
textBoxBounds . y = bounds . y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_TEXTINPUTBOX_HEIGHT / 2 ;
if ( message = = NULL ) textBoxBounds . y = bounds . y + 24 + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING ;
else textBoxBounds . y + = ( messageInputHeight / 2 + messageInputHeight / 4 ) ;
textBoxBounds . width = bounds . width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING * 2 ;
textBoxBounds . height = RAYGUI_TEXTINPUTBOX_HEIGHT ;
// Draw control
//--------------------------------------------------------------------
if ( GuiWindowBox ( bounds , title ) ) result = 0 ;
// Draw message if available
if ( message ! = NULL )
{
int prevTextAlignment = GuiGetStyle ( LABEL , TEXT_ALIGNMENT ) ;
GuiSetStyle ( LABEL , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
GuiLabel ( textBounds , message ) ;
GuiSetStyle ( LABEL , TEXT_ALIGNMENT , prevTextAlignment ) ;
}
if ( secretViewActive ! = NULL )
{
static char stars [ ] = " **************** " ;
if ( GuiTextBox ( RAYGUI_CLITERAL ( Rectangle ) { textBoxBounds . x , textBoxBounds . y , textBoxBounds . width - 4 - RAYGUI_TEXTINPUTBOX_HEIGHT , textBoxBounds . height } ,
( ( * secretViewActive = = 1 ) | | textEditMode ) ? text : stars , textMaxSize , textEditMode ) ) textEditMode = ! textEditMode ;
GuiToggle ( RAYGUI_CLITERAL ( Rectangle ) { textBoxBounds . x + textBoxBounds . width - RAYGUI_TEXTINPUTBOX_HEIGHT , textBoxBounds . y , RAYGUI_TEXTINPUTBOX_HEIGHT , RAYGUI_TEXTINPUTBOX_HEIGHT } , ( * secretViewActive = = 1 ) ? " #44# " : " #45# " , secretViewActive ) ;
}
else
{
if ( GuiTextBox ( textBoxBounds , text , textMaxSize , textEditMode ) ) textEditMode = ! textEditMode ;
}
int prevBtnTextAlignment = GuiGetStyle ( BUTTON , TEXT_ALIGNMENT ) ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
for ( int i = 0 ; i < buttonCount ; i + + )
{
if ( GuiButton ( buttonBounds , buttonsText [ i ] ) ) result = i + 1 ;
buttonBounds . x + = ( buttonBounds . width + RAYGUI_MESSAGEBOX_BUTTON_PADDING ) ;
}
if ( result > = 0 ) textEditMode = false ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , prevBtnTextAlignment ) ;
//--------------------------------------------------------------------
return result ; // Result is the pressed button index
}
// Grid control
// NOTE: Returns grid mouse-hover selected cell
// About drawing lines at subpixel spacing, simple put, not easy solution:
// https://stackoverflow.com/questions/4435450/2d-opengl-drawing-lines-that-dont-exactly-fit-pixel-raster
int GuiGrid ( Rectangle bounds , const char * text , float spacing , int subdivs , Vector2 * mouseCell )
{
// Grid lines alpha amount
# if !defined(RAYGUI_GRID_ALPHA)
# define RAYGUI_GRID_ALPHA 0.15f
# endif
int result = 0 ;
GuiState state = guiState ;
Vector2 mousePoint = GetMousePosition ( ) ;
Vector2 currentMouseCell = { - 1 , - 1 } ;
float spaceWidth = spacing / ( float ) subdivs ;
int linesV = ( int ) ( bounds . width / spaceWidth ) + 1 ;
int linesH = ( int ) ( bounds . height / spaceWidth ) + 1 ;
int color = GuiGetStyle ( DEFAULT , LINE_COLOR ) ;
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked & & ! guiSliderDragging )
{
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
// NOTE: Cell values must be the upper left of the cell the mouse is in
currentMouseCell . x = floorf ( ( mousePoint . x - bounds . x ) / spacing ) ;
currentMouseCell . y = floorf ( ( mousePoint . y - bounds . y ) / spacing ) ;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
if ( state = = STATE_DISABLED ) color = GuiGetStyle ( DEFAULT , BORDER_COLOR_DISABLED ) ;
if ( subdivs > 0 )
{
// Draw vertical grid lines
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 ) ? GuiFade ( GetColor ( color ) , RAYGUI_GRID_ALPHA * 4 ) : GuiFade ( GetColor ( 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 ) ? GuiFade ( GetColor ( color ) , RAYGUI_GRID_ALPHA * 4 ) : GuiFade ( GetColor ( color ) , RAYGUI_GRID_ALPHA ) ) ;
}
}
if ( mouseCell ! = NULL ) * mouseCell = currentMouseCell ;
return result ;
}
//----------------------------------------------------------------------------------
// Tooltip management functions
// NOTE: Tooltips requires some global variables: tooltipPtr
//----------------------------------------------------------------------------------
// Enable gui tooltips (global state)
void GuiEnableTooltip ( void ) { guiTooltip = true ; }
// Disable gui tooltips (global state)
void GuiDisableTooltip ( void ) { guiTooltip = false ; }
// Set tooltip string
void GuiSetTooltip ( const char * tooltip ) { guiTooltipPtr = tooltip ; }
//----------------------------------------------------------------------------------
// Styles loading functions
//----------------------------------------------------------------------------------
// Load raygui style file (.rgs)
// NOTE: By default a binary file is expected, that file could contain a custom font,
// in that case, custom font image atlas is GRAY+ALPHA and pixel data can be compressed (DEFLATE)
void GuiLoadStyle ( const char * fileName )
{
# define MAX_LINE_BUFFER_SIZE 256
bool tryBinary = false ;
// Try reading the files as text file first
FILE * rgsFile = fopen ( fileName , " rt " ) ;
if ( rgsFile ! = NULL )
{
char buffer [ MAX_LINE_BUFFER_SIZE ] = { 0 } ;
fgets ( buffer , MAX_LINE_BUFFER_SIZE , rgsFile ) ;
if ( buffer [ 0 ] = = ' # ' )
{
int controlId = 0 ;
int propertyId = 0 ;
unsigned int propertyValue = 0 ;
while ( ! feof ( rgsFile ) )
{
switch ( buffer [ 0 ] )
{
case ' p ' :
{
// Style property: p <control_id> <property_id> <property_value> <property_name>
sscanf ( buffer , " p %d %d 0x%x " , & controlId , & propertyId , & propertyValue ) ;
GuiSetStyle ( controlId , propertyId , ( int ) propertyValue ) ;
} break ;
case ' f ' :
{
// Style font: f <gen_font_size> <charmap_file> <font_file>
int fontSize = 0 ;
char charmapFileName [ 256 ] = { 0 } ;
char fontFileName [ 256 ] = { 0 } ;
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 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 ) ;
}
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 ) ;
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 ;
default : break ;
}
fgets ( buffer , MAX_LINE_BUFFER_SIZE , rgsFile ) ;
}
}
else tryBinary = true ;
fclose ( rgsFile ) ;
}
if ( tryBinary )
{
rgsFile = fopen ( fileName , " rb " ) ;
if ( rgsFile ! = NULL )
{
fseek ( rgsFile , 0 , SEEK_END ) ;
int fileDataSize = ftell ( rgsFile ) ;
fseek ( rgsFile , 0 , SEEK_SET ) ;
if ( fileDataSize > 0 )
{
unsigned char * fileData = ( unsigned char * ) RAYGUI_MALLOC ( fileDataSize * sizeof ( unsigned char ) ) ;
fread ( fileData , sizeof ( unsigned char ) , fileDataSize , rgsFile ) ;
GuiLoadStyleFromMemory ( fileData , fileDataSize ) ;
RAYGUI_FREE ( fileData ) ;
}
fclose ( rgsFile ) ;
}
}
}
// Load style default over global style
void GuiLoadStyleDefault ( void )
{
// We set this variable first to avoid cyclic function calls
// when calling GuiSetStyle() and GuiGetStyle()
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 ) ;
GuiSetStyle ( DEFAULT , BORDER_COLOR_FOCUSED , 0x5bb2d9ff ) ;
GuiSetStyle ( DEFAULT , BASE_COLOR_FOCUSED , 0xc9effeff ) ;
GuiSetStyle ( DEFAULT , TEXT_COLOR_FOCUSED , 0x6c9bbcff ) ;
GuiSetStyle ( DEFAULT , BORDER_COLOR_PRESSED , 0x0492c7ff ) ;
GuiSetStyle ( DEFAULT , BASE_COLOR_PRESSED , 0x97e8ffff ) ;
GuiSetStyle ( DEFAULT , TEXT_COLOR_PRESSED , 0x368bafff ) ;
GuiSetStyle ( DEFAULT , BORDER_COLOR_DISABLED , 0xb5c1c2ff ) ;
GuiSetStyle ( DEFAULT , BASE_COLOR_DISABLED , 0xe6e9e9ff ) ;
GuiSetStyle ( DEFAULT , TEXT_COLOR_DISABLED , 0xaeb7b8ff ) ;
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 ) ;
GuiSetStyle ( VALUEBOX , TEXT_ALIGNMENT , TEXT_ALIGN_LEFT ) ;
GuiSetStyle ( SPINNER , TEXT_PADDING , 0 ) ;
GuiSetStyle ( SPINNER , TEXT_ALIGNMENT , TEXT_ALIGN_LEFT ) ;
GuiSetStyle ( STATUSBAR , TEXT_PADDING , 8 ) ;
GuiSetStyle ( STATUSBAR , TEXT_ALIGNMENT , TEXT_ALIGN_LEFT ) ;
// Initialize extended property values
// NOTE: By default, extended property values are initialized to 0
GuiSetStyle ( TOGGLE , GROUP_PADDING , 2 ) ;
GuiSetStyle ( SLIDER , SLIDER_WIDTH , 16 ) ;
GuiSetStyle ( SLIDER , SLIDER_PADDING , 1 ) ;
GuiSetStyle ( PROGRESSBAR , PROGRESS_PADDING , 1 ) ;
GuiSetStyle ( CHECKBOX , CHECK_PADDING , 1 ) ;
GuiSetStyle ( COMBOBOX , COMBO_BUTTON_WIDTH , 32 ) ;
GuiSetStyle ( COMBOBOX , COMBO_BUTTON_SPACING , 2 ) ;
GuiSetStyle ( DROPDOWNBOX , ARROW_PADDING , 16 ) ;
GuiSetStyle ( DROPDOWNBOX , DROPDOWN_ITEMS_SPACING , 2 ) ;
GuiSetStyle ( SPINNER , SPIN_BUTTON_WIDTH , 24 ) ;
GuiSetStyle ( SPINNER , SPIN_BUTTON_SPACING , 2 ) ;
GuiSetStyle ( SCROLLBAR , BORDER_WIDTH , 0 ) ;
GuiSetStyle ( SCROLLBAR , ARROWS_VISIBLE , 0 ) ;
GuiSetStyle ( SCROLLBAR , ARROWS_SIZE , 6 ) ;
GuiSetStyle ( SCROLLBAR , SCROLL_SLIDER_PADDING , 0 ) ;
GuiSetStyle ( SCROLLBAR , SCROLL_SLIDER_SIZE , 16 ) ;
GuiSetStyle ( SCROLLBAR , SCROLL_PADDING , 0 ) ;
GuiSetStyle ( SCROLLBAR , SCROLL_SPEED , 12 ) ;
GuiSetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT , 28 ) ;
GuiSetStyle ( LISTVIEW , LIST_ITEMS_SPACING , 2 ) ;
GuiSetStyle ( LISTVIEW , SCROLLBAR_WIDTH , 12 ) ;
GuiSetStyle ( LISTVIEW , SCROLLBAR_SIDE , SCROLLBAR_RIGHT_SIDE ) ;
GuiSetStyle ( COLORPICKER , COLOR_SELECTOR_SIZE , 8 ) ;
GuiSetStyle ( COLORPICKER , HUEBAR_WIDTH , 16 ) ;
GuiSetStyle ( COLORPICKER , HUEBAR_PADDING , 8 ) ;
GuiSetStyle ( COLORPICKER , HUEBAR_SELECTOR_HEIGHT , 8 ) ;
GuiSetStyle ( COLORPICKER , HUEBAR_SELECTOR_OVERFLOW , 2 ) ;
if ( guiFont . texture . id ! = GetFontDefault ( ) . texture . id )
{
// 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 } ) ;
}
}
// Get text with icon id prepended
// NOTE: Useful to add icons by name id (enum) instead of
// a number that can change between ricon versions
const char * GuiIconText ( int iconId , const char * text )
{
# if defined(RAYGUI_NO_ICONS)
return NULL ;
# else
static char buffer [ 1024 ] = { 0 } ;
static char iconBuffer [ 6 ] = { 0 } ;
if ( text ! = NULL )
{
memset ( buffer , 0 , 1024 ) ;
sprintf ( buffer , " #%03i# " , iconId ) ;
for ( int i = 5 ; i < 1024 ; i + + )
{
buffer [ i ] = text [ i - 5 ] ;
if ( text [ i - 5 ] = = ' \0 ' ) break ;
}
return buffer ;
}
else
{
sprintf ( iconBuffer , " #%03i# " , iconId & 0x1ff ) ;
return iconBuffer ;
}
# endif
}
# if !defined(RAYGUI_NO_ICONS)
// Get full icons data pointer
unsigned int * GuiGetIcons ( void ) { return guiIconsPtr ; }
// Load raygui icons file (.rgi)
// NOTE: In case nameIds are required, they can be requested with loadIconsName,
// they are returned as a guiIconsName[iconCount][RAYGUI_ICON_MAX_NAME_LENGTH],
// WARNING: guiIconsName[]][] memory should be manually freed!
char * * GuiLoadIcons ( const char * fileName , bool loadIconsName )
{
// Style File Structure (.rgi)
// ------------------------------------------------------
// Offset | Size | Type | Description
// ------------------------------------------------------
// 0 | 4 | char | Signature: "rGI "
// 4 | 2 | short | Version: 100
// 6 | 2 | short | reserved
// 8 | 2 | short | Num icons (N)
// 10 | 2 | short | Icons size (Options: 16, 32, 64) (S)
// Icons name id (32 bytes per name id)
// foreach (icon)
// {
// 12+32*i | 32 | char | Icon NameId
// }
// Icons data: One bit per pixel, stored as unsigned int array (depends on icon size)
// S*S pixels/32bit per unsigned int = K unsigned int per icon
// foreach (icon)
// {
// ... | K | unsigned int | Icon Data
// }
FILE * rgiFile = fopen ( fileName , " rb " ) ;
char * * guiIconsName = NULL ;
if ( rgiFile ! = NULL )
{
char signature [ 5 ] = { 0 } ;
short version = 0 ;
short reserved = 0 ;
short iconCount = 0 ;
short iconSize = 0 ;
fread ( signature , 1 , 4 , rgiFile ) ;
fread ( & version , sizeof ( short ) , 1 , rgiFile ) ;
fread ( & reserved , sizeof ( short ) , 1 , rgiFile ) ;
fread ( & iconCount , sizeof ( short ) , 1 , rgiFile ) ;
fread ( & iconSize , sizeof ( short ) , 1 , rgiFile ) ;
if ( ( signature [ 0 ] = = ' r ' ) & &
( signature [ 1 ] = = ' G ' ) & &
( signature [ 2 ] = = ' I ' ) & &
( signature [ 3 ] = = ' ' ) )
{
if ( loadIconsName )
{
guiIconsName = ( char * * ) RAYGUI_MALLOC ( iconCount * sizeof ( char * * ) ) ;
for ( int i = 0 ; i < iconCount ; i + + )
{
guiIconsName [ i ] = ( char * ) RAYGUI_MALLOC ( RAYGUI_ICON_MAX_NAME_LENGTH ) ;
fread ( guiIconsName [ i ] , 1 , RAYGUI_ICON_MAX_NAME_LENGTH , rgiFile ) ;
}
}
else fseek ( rgiFile , iconCount * RAYGUI_ICON_MAX_NAME_LENGTH , SEEK_CUR ) ;
// Read icons data directly over internal icons array
fread ( guiIconsPtr , sizeof ( unsigned int ) , iconCount * ( iconSize * iconSize / 32 ) , rgiFile ) ;
}
fclose ( rgiFile ) ;
}
return guiIconsName ;
}
// Draw selected icon using rectangles pixel-by-pixel
void GuiDrawIcon ( int iconId , int posX , int posY , int pixelSize , Color color )
{
# define BIT_CHECK(a,b) ((a) & (1u<<(b)))
for ( int i = 0 , y = 0 ; i < RAYGUI_ICON_SIZE * RAYGUI_ICON_SIZE / 32 ; i + + )
{
for ( int k = 0 ; k < 32 ; k + + )
{
if ( BIT_CHECK ( guiIconsPtr [ iconId * RAYGUI_ICON_DATA_ELEMENTS + i ] , k ) )
{
# if !defined(RAYGUI_STANDALONE)
GuiDrawRectangle ( RAYGUI_CLITERAL ( Rectangle ) { ( float ) posX + ( k % RAYGUI_ICON_SIZE ) * pixelSize , ( float ) posY + y * pixelSize , ( float ) pixelSize , ( float ) pixelSize } , 0 , BLANK , color ) ;
# endif
}
if ( ( k = = 15 ) | | ( k = = 31 ) ) y + + ;
}
}
}
// Set icon drawing size
void GuiSetIconScale ( int scale )
{
if ( scale > = 1 ) guiIconScale = scale ;
}
# endif // !RAYGUI_NO_ICONS
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
// Load style from memory
// WARNING: Binary files only
static void GuiLoadStyleFromMemory ( const unsigned char * fileData , int dataSize )
{
unsigned char * fileDataPtr = ( unsigned char * ) fileData ;
char signature [ 5 ] = { 0 } ;
short version = 0 ;
short reserved = 0 ;
int propertyCount = 0 ;
memcpy ( signature , fileDataPtr , 4 ) ;
memcpy ( & version , fileDataPtr + 4 , sizeof ( short ) ) ;
memcpy ( & reserved , fileDataPtr + 4 + 2 , sizeof ( short ) ) ;
memcpy ( & propertyCount , fileDataPtr + 4 + 2 + 2 , sizeof ( int ) ) ;
fileDataPtr + = 12 ;
if ( ( signature [ 0 ] = = ' r ' ) & &
( signature [ 1 ] = = ' G ' ) & &
( signature [ 2 ] = = ' S ' ) & &
( signature [ 3 ] = = ' ' ) )
{
short controlId = 0 ;
short propertyId = 0 ;
unsigned int propertyValue = 0 ;
for ( int i = 0 ; i < propertyCount ; i + + )
{
memcpy ( & controlId , fileDataPtr , sizeof ( short ) ) ;
memcpy ( & propertyId , fileDataPtr + 2 , sizeof ( short ) ) ;
memcpy ( & propertyValue , fileDataPtr + 2 + 2 , sizeof ( unsigned int ) ) ;
fileDataPtr + = 8 ;
if ( controlId = = 0 ) // DEFAULT control
{
// If a DEFAULT property is loaded, it is propagated to all controls
// NOTE: All DEFAULT properties should be defined first in the file
GuiSetStyle ( 0 , ( int ) propertyId , propertyValue ) ;
if ( propertyId < RAYGUI_MAX_PROPS_BASE ) for ( int i = 1 ; i < RAYGUI_MAX_CONTROLS ; i + + ) GuiSetStyle ( i , ( int ) propertyId , propertyValue ) ;
}
else GuiSetStyle ( ( int ) controlId , ( int ) propertyId , propertyValue ) ;
}
// Font loading is highly dependant on raylib API to load font data and image
# if !defined(RAYGUI_STANDALONE)
// Load custom font if available
int fontDataSize = 0 ;
memcpy ( & fontDataSize , fileDataPtr , sizeof ( int ) ) ;
fileDataPtr + = 4 ;
if ( fontDataSize > 0 )
{
Font font = { 0 } ;
int fontType = 0 ; // 0-Normal, 1-SDF
memcpy ( & font . baseSize , fileDataPtr , sizeof ( int ) ) ;
memcpy ( & font . glyphCount , fileDataPtr + 4 , sizeof ( int ) ) ;
memcpy ( & fontType , fileDataPtr + 4 + 4 , sizeof ( int ) ) ;
fileDataPtr + = 12 ;
// Load font white rectangle
Rectangle fontWhiteRec = { 0 } ;
memcpy ( & fontWhiteRec , fileDataPtr , sizeof ( Rectangle ) ) ;
fileDataPtr + = 16 ;
// Load font image parameters
int fontImageUncompSize = 0 ;
int fontImageCompSize = 0 ;
memcpy ( & fontImageUncompSize , fileDataPtr , sizeof ( int ) ) ;
memcpy ( & fontImageCompSize , fileDataPtr + 4 , sizeof ( int ) ) ;
fileDataPtr + = 8 ;
Image imFont = { 0 } ;
imFont . mipmaps = 1 ;
memcpy ( & imFont . width , fileDataPtr , sizeof ( int ) ) ;
memcpy ( & imFont . height , fileDataPtr + 4 , sizeof ( int ) ) ;
memcpy ( & imFont . format , fileDataPtr + 4 + 4 , sizeof ( int ) ) ;
fileDataPtr + = 12 ;
if ( ( fontImageCompSize > 0 ) & & ( fontImageCompSize ! = fontImageUncompSize ) )
{
// Compressed font atlas image data (DEFLATE), it requires DecompressData()
int dataUncompSize = 0 ;
unsigned char * compData = ( unsigned char * ) RAYGUI_MALLOC ( fontImageCompSize ) ;
memcpy ( compData , fileDataPtr , fontImageCompSize ) ;
fileDataPtr + = fontImageCompSize ;
imFont . data = DecompressData ( compData , fontImageCompSize , & dataUncompSize ) ;
// Security check, dataUncompSize must match the provided fontImageUncompSize
if ( dataUncompSize ! = fontImageUncompSize ) RAYGUI_LOG ( " WARNING: Uncompressed font atlas image data could be corrupted " ) ;
RAYGUI_FREE ( compData ) ;
}
else
{
// Font atlas image data is not compressed
imFont . data = ( unsigned char * ) RAYGUI_MALLOC ( fontImageUncompSize ) ;
memcpy ( imFont . data , fileDataPtr , fontImageUncompSize ) ;
fileDataPtr + = fontImageUncompSize ;
}
if ( font . texture . id ! = GetFontDefault ( ) . texture . id ) UnloadTexture ( font . texture ) ;
font . texture = LoadTextureFromImage ( imFont ) ;
RAYGUI_FREE ( imFont . data ) ;
// Validate font atlas texture was loaded correctly
if ( font . texture . id ! = 0 )
{
// Load font recs data
int recsDataSize = font . glyphCount * sizeof ( Rectangle ) ;
int recsDataCompressedSize = 0 ;
// 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: 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
}
}
// Gui get text width considering icon
static int GetTextWidth ( const char * text )
{
# if !defined(ICON_TEXT_PADDING)
# define ICON_TEXT_PADDING 4
# endif
Vector2 textSize = { 0 } ;
int textIconOffset = 0 ;
if ( ( text ! = NULL ) & & ( text [ 0 ] ! = ' \0 ' ) )
{
if ( text [ 0 ] = = ' # ' )
{
for ( int i = 1 ; ( i < 5 ) & & ( text [ i ] ! = ' \0 ' ) ; i + + )
{
if ( text [ i ] = = ' # ' )
{
textIconOffset = i ;
break ;
}
}
}
text + = textIconOffset ;
// Make sure guiFont is set, GuiGetStyle() initializes it lazynessly
float fontSize = ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) ;
// Custom MeasureText() implementation
if ( ( guiFont . texture . id > 0 ) & & ( text ! = NULL ) )
{
// Get size in bytes of text, considering end of line and line break
int size = 0 ;
for ( int i = 0 ; i < MAX_LINE_BUFFER_SIZE ; i + + )
{
if ( ( text [ i ] ! = ' \0 ' ) & & ( text [ i ] ! = ' \n ' ) ) size + + ;
else break ;
}
float scaleFactor = fontSize / ( float ) guiFont . baseSize ;
textSize . y = ( float ) guiFont . baseSize * scaleFactor ;
float glyphWidth = 0.0f ;
for ( int i = 0 , codepointSize = 0 ; i < size ; i + = codepointSize )
{
int codepoint = GetCodepointNext ( & text [ i ] , & codepointSize ) ;
int 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 ) ;
textSize . x + = ( glyphWidth + ( float ) GuiGetStyle ( DEFAULT , TEXT_SPACING ) ) ;
}
}
if ( textIconOffset > 0 ) textSize . x + = ( RAYGUI_ICON_SIZE - ICON_TEXT_PADDING ) ;
}
return ( int ) textSize . x ;
}
// Get text bounds considering control bounds
static Rectangle GetTextBounds ( int control , Rectangle bounds )
{
Rectangle textBounds = 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 ) ; // NOTE: Text is processed line per line!
// 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 ) ;
}
break ;
}
return textBounds ;
}
// Get text icon if provided and move text cursor
// NOTE: We support up to 999 values for iconId
static const char * GetTextIcon ( const char * text , int * iconId )
{
# if !defined(RAYGUI_NO_ICONS)
* iconId = - 1 ;
if ( text [ 0 ] = = ' # ' ) // Maybe we have an icon!
{
char iconValue [ 4 ] = { 0 } ; // Maximum length for icon value: 3 digits + '\0'
int pos = 1 ;
while ( ( pos < 4 ) & & ( text [ pos ] > = ' 0 ' ) & & ( text [ pos ] < = ' 9 ' ) )
{
iconValue [ pos - 1 ] = text [ pos ] ;
pos + + ;
}
if ( text [ pos ] = = ' # ' )
{
* iconId = TextToInteger ( iconValue ) ;
// Move text pointer after icon
// WARNING: If only icon provided, it could point to EOL character: '\0'
if ( * iconId > = 0 ) text + = ( pos + 1 ) ;
}
}
# endif
return text ;
}
// Get text divided into lines (by line-breaks '\n')
const char * * GetTextLines ( const char * text , int * count )
{
# define RAYGUI_MAX_TEXT_LINES 128
static const char * lines [ RAYGUI_MAX_TEXT_LINES ] = { 0 } ;
for ( int i = 0 ; i < RAYGUI_MAX_TEXT_LINES ; i + + ) lines [ i ] = NULL ; // Init NULL pointers to substrings
int textSize = ( int ) strlen ( text ) ;
lines [ 0 ] = text ;
int len = 0 ;
* count = 1 ;
//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;
k + + ;
lines [ k ] = & text [ i + 1 ] ; // WARNING: next value is valid?
len = 0 ;
* count + = 1 ;
}
else len + + ;
}
//lines[*count - 1].size = len;
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 textBounds , int alignment , Color tint )
{
# define TEXT_VALIGN_PIXEL_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect
# if !defined(ICON_TEXT_PADDING)
# define ICON_TEXT_PADDING 4
# endif
if ( ( text = = NULL ) | | ( text [ 0 ] = = ' \0 ' ) ) return ; // Security check
// 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)
// 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 ) ;
// 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
// 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 ;
for ( int i = 0 ; i < lineCount ; i + + )
{
int iconId = 0 ;
lines [ i ] = GetTextIcon ( lines [ i ] , & iconId ) ; // Check text for icon and move cursor
// Get text position depending on alignment and iconId
//---------------------------------------------------------------------------------
Vector2 textBoundsPosition = { textBounds . x , textBounds . y } ;
// 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 ] ) ;
// If text requires an icon, add size to measure
if ( iconId > = 0 )
{
textSizeX + = RAYGUI_ICON_SIZE * guiIconScale ;
// 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
}
// 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 ;
}
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 ) 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
// 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 ) ;
// 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
// Wrap mode text measuring to space to validate if it can be drawn or
// a new line is required
if ( wrapMode = = TEXT_WRAP_CHAR )
{
// 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 ;
// 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 ( ( 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 ( wrapMode = = TEXT_WRAP_NONE )
{
// Draw only required text glyphs fitting the textBounds.width
if ( textOffsetX < = ( textBounds . width - glyphWidth ) )
{
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 ) ) ;
}
}
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 ( textBounds , 0 , WHITE , Fade ( BLUE , 0.4f ) ) ;
# endif
}
// Gui draw rectangle using default raygui plain style with borders
static void GuiDrawRectangle ( Rectangle rec , int borderWidth , Color borderColor , Color color )
{
if ( color . a > 0 )
{
// Draw rectangle filled with 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 , 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
static void GuiTooltip ( Rectangle controlRec )
{
if ( ! guiLocked & & guiTooltip & & ( guiTooltipPtr ! = NULL ) & & ! guiSliderDragging )
{
Vector2 textSize = MeasureTextEx ( GuiGetFont ( ) , guiTooltipPtr , ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) , ( float ) GuiGetStyle ( DEFAULT , TEXT_SPACING ) ) ;
if ( ( controlRec . x + textSize . x + 16 ) > GetScreenWidth ( ) ) controlRec . x - = ( textSize . x + 16 - controlRec . width ) ;
GuiPanel ( RAYGUI_CLITERAL ( Rectangle ) { controlRec . x , controlRec . y + controlRec . height + 4 , textSize . x + 16 , GuiGetStyle ( DEFAULT , TEXT_SIZE ) + 8.f } , NULL ) ;
int textPadding = GuiGetStyle ( LABEL , TEXT_PADDING ) ;
int textAlignment = GuiGetStyle ( LABEL , TEXT_ALIGNMENT ) ;
GuiSetStyle ( LABEL , TEXT_PADDING , 0 ) ;
GuiSetStyle ( LABEL , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
GuiLabel ( RAYGUI_CLITERAL ( Rectangle ) { controlRec . x , controlRec . y + controlRec . height + 4 , textSize . x + 16 , GuiGetStyle ( DEFAULT , TEXT_SIZE ) + 8.f } , guiTooltipPtr ) ;
GuiSetStyle ( LABEL , TEXT_ALIGNMENT , textAlignment ) ;
GuiSetStyle ( LABEL , TEXT_PADDING , textPadding ) ;
}
}
// Split controls text into multiple strings
// Also check for multiple columns (required by GuiToggleGroup())
static const char * * GuiTextSplit ( const char * text , char delimiter , int * count , int * textRow )
{
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
// inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
// all used memory is static... it has some limitations:
// 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS
// 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE
// NOTE: Those definitions could be externally provided if required
// TODO: HACK: GuiTextSplit() - Review how textRows are returned to user
// textRow is an externally provided array of integers that stores row number for every splitted string
# if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS)
# define RAYGUI_TEXTSPLIT_MAX_ITEMS 128
# endif
# if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE)
# define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024
# endif
static const char * result [ RAYGUI_TEXTSPLIT_MAX_ITEMS ] = { NULL } ; // String pointers array (points to buffer data)
static char buffer [ RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE ] = { 0 } ; // Buffer data (text input copy with '\0' added)
memset ( buffer , 0 , RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE ) ;
result [ 0 ] = buffer ;
int counter = 1 ;
if ( textRow ! = NULL ) textRow [ 0 ] = 0 ;
// Count how many substrings we have on text and point to every one
for ( int i = 0 ; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE ; i + + )
{
buffer [ i ] = text [ i ] ;
if ( buffer [ i ] = = ' \0 ' ) break ;
else if ( ( buffer [ i ] = = delimiter ) | | ( buffer [ i ] = = ' \n ' ) )
{
result [ counter ] = buffer + i + 1 ;
if ( textRow ! = NULL )
{
if ( buffer [ i ] = = ' \n ' ) textRow [ counter ] = textRow [ counter - 1 ] + 1 ;
else textRow [ counter ] = textRow [ counter - 1 ] ;
}
buffer [ i ] = ' \0 ' ; // Set an end of string at this point
counter + + ;
if ( counter = = RAYGUI_TEXTSPLIT_MAX_ITEMS ) break ;
}
}
* count = counter ;
return result ;
}
// Convert color data from RGB to HSV
// NOTE: Color data should be passed normalized
static Vector3 ConvertRGBtoHSV ( Vector3 rgb )
{
Vector3 hsv = { 0 } ;
float min = 0.0f ;
float max = 0.0f ;
float delta = 0.0f ;
min = ( rgb . x < rgb . y ) ? rgb . x : rgb . y ;
min = ( min < rgb . z ) ? min : rgb . z ;
max = ( rgb . x > rgb . y ) ? rgb . x : rgb . y ;
max = ( max > rgb . z ) ? max : rgb . z ;
hsv . z = max ; // Value
delta = max - min ;
if ( delta < 0.00001f )
{
hsv . y = 0.0f ;
hsv . x = 0.0f ; // Undefined, maybe NAN?
return hsv ;
}
if ( max > 0.0f )
{
// NOTE: If max is 0, this divide would cause a crash
hsv . y = ( delta / max ) ; // Saturation
}
else
{
// NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
hsv . y = 0.0f ;
hsv . x = 0.0f ; // Undefined, maybe NAN?
return hsv ;
}
// NOTE: Comparing float values could not work properly
if ( rgb . x > = max ) hsv . x = ( rgb . y - rgb . z ) / delta ; // Between yellow & magenta
else
{
if ( rgb . y > = max ) hsv . x = 2.0f + ( rgb . z - rgb . x ) / delta ; // Between cyan & yellow
else hsv . x = 4.0f + ( rgb . x - rgb . y ) / delta ; // Between magenta & cyan
}
hsv . x * = 60.0f ; // Convert to degrees
if ( hsv . x < 0.0f ) hsv . x + = 360.0f ;
return hsv ;
}
// Convert color data from HSV to RGB
// NOTE: Color data should be passed normalized
static Vector3 ConvertHSVtoRGB ( Vector3 hsv )
{
Vector3 rgb = { 0 } ;
float hh = 0.0f , p = 0.0f , q = 0.0f , t = 0.0f , ff = 0.0f ;
long i = 0 ;
// NOTE: Comparing float values could not work properly
if ( hsv . y < = 0.0f )
{
rgb . x = hsv . z ;
rgb . y = hsv . z ;
rgb . z = hsv . z ;
return rgb ;
}
hh = hsv . x ;
if ( hh > = 360.0f ) hh = 0.0f ;
hh / = 60.0f ;
i = ( long ) hh ;
ff = hh - i ;
p = hsv . z * ( 1.0f - hsv . y ) ;
q = hsv . z * ( 1.0f - ( hsv . y * ff ) ) ;
t = hsv . z * ( 1.0f - ( hsv . y * ( 1.0f - ff ) ) ) ;
switch ( i )
{
case 0 :
{
rgb . x = hsv . z ;
rgb . y = t ;
rgb . z = p ;
} break ;
case 1 :
{
rgb . x = q ;
rgb . y = hsv . z ;
rgb . z = p ;
} break ;
case 2 :
{
rgb . x = p ;
rgb . y = hsv . z ;
rgb . z = t ;
} break ;
case 3 :
{
rgb . x = p ;
rgb . y = q ;
rgb . z = hsv . z ;
} break ;
case 4 :
{
rgb . x = t ;
rgb . y = p ;
rgb . z = hsv . z ;
} break ;
case 5 :
default :
{
rgb . x = hsv . z ;
rgb . y = p ;
rgb . z = q ;
} break ;
}
return rgb ;
}
// Scroll bar control (used by GuiScrollPanel())
static int GuiScrollBar ( Rectangle bounds , int value , int minValue , int maxValue )
{
GuiState state = guiState ;
// Is the scrollbar horizontal or vertical?
bool isVertical = ( bounds . width > bounds . height ) ? false : true ;
// The size (width or height depending on scrollbar type) of the spinner buttons
const int spinnerSize = GuiGetStyle ( SCROLLBAR , ARROWS_VISIBLE ) ?
( isVertical ? ( int ) bounds . width - 2 * GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) :
( int ) bounds . height - 2 * GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) ) : 0 ;
// Arrow buttons [<] [>] [∧] [∨ ]
Rectangle arrowUpLeft = { 0 } ;
Rectangle arrowDownRight = { 0 } ;
// Actual area of the scrollbar excluding the arrow buttons
Rectangle scrollbar = { 0 } ;
// Slider bar that moves --[///]-----
Rectangle slider = { 0 } ;
// Normalize value
if ( value > maxValue ) value = maxValue ;
if ( value < minValue ) value = minValue ;
const int valueRange = maxValue - minValue ;
int sliderSize = GuiGetStyle ( SCROLLBAR , SCROLL_SLIDER_SIZE ) ;
// Calculate rectangles for all of the components
arrowUpLeft = RAYGUI_CLITERAL ( Rectangle ) {
( float ) bounds . x + GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) ,
( float ) bounds . y + GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) ,
( float ) spinnerSize , ( float ) spinnerSize } ;
if ( isVertical )
{
arrowDownRight = RAYGUI_CLITERAL ( Rectangle ) { ( float ) bounds . x + GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) , ( float ) bounds . y + bounds . height - spinnerSize - GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) , ( float ) spinnerSize , ( float ) spinnerSize } ;
scrollbar = RAYGUI_CLITERAL ( Rectangle ) { bounds . x + GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_PADDING ) , arrowUpLeft . y + arrowUpLeft . height , bounds . width - 2 * ( GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_PADDING ) ) , bounds . height - arrowUpLeft . height - arrowDownRight . height - 2 * GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) } ;
// Make sure the slider won't get outside of the scrollbar
sliderSize = ( sliderSize > = scrollbar . height ) ? ( ( int ) scrollbar . height - 2 ) : sliderSize ;
slider = RAYGUI_CLITERAL ( Rectangle ) {
bounds . x + GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_SLIDER_PADDING ) ,
scrollbar . y + ( int ) ( ( ( float ) ( value - minValue ) / valueRange ) * ( scrollbar . height - sliderSize ) ) ,
bounds . width - 2 * ( GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_SLIDER_PADDING ) ) ,
( float ) sliderSize } ;
}
else // horizontal
{
arrowDownRight = RAYGUI_CLITERAL ( Rectangle ) { ( float ) bounds . x + bounds . width - spinnerSize - GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) , ( float ) bounds . y + GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) , ( float ) spinnerSize , ( float ) spinnerSize } ;
scrollbar = RAYGUI_CLITERAL ( Rectangle ) { arrowUpLeft . x + arrowUpLeft . width , bounds . y + GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_PADDING ) , bounds . width - arrowUpLeft . width - arrowDownRight . width - 2 * GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) , bounds . height - 2 * ( GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_PADDING ) ) } ;
// Make sure the slider won't get outside of the scrollbar
sliderSize = ( sliderSize > = scrollbar . width ) ? ( ( int ) scrollbar . width - 2 ) : sliderSize ;
slider = RAYGUI_CLITERAL ( Rectangle ) {
scrollbar . x + ( int ) ( ( ( float ) ( value - minValue ) / valueRange ) * ( scrollbar . width - sliderSize ) ) ,
bounds . y + GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_SLIDER_PADDING ) ,
( float ) sliderSize ,
bounds . height - 2 * ( GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_SLIDER_PADDING ) ) } ;
}
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( guiSliderDragging ) // Keep dragging outside of bounds
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) & &
! CheckCollisionPointRec ( mousePoint , arrowUpLeft ) & &
! CheckCollisionPointRec ( mousePoint , arrowDownRight ) )
{
if ( CHECK_BOUNDS_ID ( bounds , guiSliderActive ) )
{
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
{
guiSliderDragging = false ;
guiSliderActive = RAYGUI_CLITERAL ( Rectangle ) { 0 , 0 , 0 , 0 } ;
}
}
else if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
state = STATE_FOCUSED ;
// Handle mouse wheel
int wheel = ( int ) GetMouseWheelMove ( ) ;
if ( wheel ! = 0 ) value + = wheel ;
// 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 ) ;
else if ( ! CheckCollisionPointRec ( mousePoint , slider ) )
{
// If click on scrollbar position but not on slider, place slider directly on that position
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 ) ;
}
state = STATE_PRESSED ;
}
// Keyboard control on mouse hover scrollbar
/*
if ( isVertical )
{
if ( IsKeyDown ( KEY_DOWN ) ) value + = 5 ;
else if ( IsKeyDown ( KEY_UP ) ) value - = 5 ;
}
else
{
if ( IsKeyDown ( KEY_RIGHT ) ) value + = 5 ;
else if ( IsKeyDown ( KEY_LEFT ) ) value - = 5 ;
}
*/
}
// Normalize value
if ( value > maxValue ) value = maxValue ;
if ( value < minValue ) value = minValue ;
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
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 , 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 ) )
{
# 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 , 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 , 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 , 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 , GetColor ( GuiGetStyle ( SCROLLBAR , TEXT + state * 3 ) ) ) ; // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL
# endif
}
//--------------------------------------------------------------------
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 )
{
Color color ;
color . r = ( unsigned char ) ( hexValue > > 24 ) & 0xFF ;
color . g = ( unsigned char ) ( hexValue > > 16 ) & 0xFF ;
color . b = ( unsigned char ) ( hexValue > > 8 ) & 0xFF ;
color . a = ( unsigned char ) hexValue & 0xFF ;
return color ;
}
// Returns hexadecimal value for a Color
static int ColorToInt ( Color color )
{
return ( ( ( int ) color . r < < 24 ) | ( ( int ) color . g < < 16 ) | ( ( int ) color . b < < 8 ) | ( int ) color . a ) ;
}
// Check if point is inside rectangle
static bool CheckCollisionPointRec ( Vector2 point , Rectangle rec )
{
bool collision = false ;
if ( ( point . x > = rec . x ) & & ( point . x < = ( rec . x + rec . width ) ) & &
( point . y > = rec . y ) & & ( point . y < = ( rec . y + rec . height ) ) ) collision = true ;
return collision ;
}
// Formatting of text with variables to 'embed'
static const char * TextFormat ( const char * text , . . . )
{
# if !defined(RAYGUI_TEXTFORMAT_MAX_SIZE)
# define RAYGUI_TEXTFORMAT_MAX_SIZE 256
# endif
static char buffer [ RAYGUI_TEXTFORMAT_MAX_SIZE ] ;
va_list args ;
va_start ( args , text ) ;
vsprintf ( buffer , text , args ) ;
va_end ( args ) ;
return buffer ;
}
// Draw rectangle with vertical gradient fill color
// NOTE: This function is only used by GuiColorPicker()
static void DrawRectangleGradientV ( int posX , int posY , int width , int height , Color color1 , Color color2 )
{
Rectangle bounds = { ( float ) posX , ( float ) posY , ( float ) width , ( float ) height } ;
DrawRectangleGradientEx ( bounds , color1 , color2 , color2 , color1 ) ;
}
// Split string into multiple strings
const char * * TextSplit ( const char * text , char delimiter , int * count )
{
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
// inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
// all used memory is static... it has some limitations:
// 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS
// 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE
# if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS)
# define RAYGUI_TEXTSPLIT_MAX_ITEMS 128
# endif
# if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE)
# define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024
# endif
static const char * result [ RAYGUI_TEXTSPLIT_MAX_ITEMS ] = { NULL } ;
static char buffer [ RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE ] = { 0 } ;
memset ( buffer , 0 , RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE ) ;
result [ 0 ] = buffer ;
int counter = 0 ;
if ( text ! = NULL )
{
counter = 1 ;
// Count how many substrings we have on text and point to every one
for ( int i = 0 ; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE ; i + + )
{
buffer [ i ] = text [ i ] ;
if ( buffer [ i ] = = ' \0 ' ) break ;
else if ( buffer [ i ] = = delimiter )
{
buffer [ i ] = ' \0 ' ; // Set an end of string at this point
result [ counter ] = buffer + i + 1 ;
counter + + ;
if ( counter = = RAYGUI_TEXTSPLIT_MAX_ITEMS ) break ;
}
}
}
* count = counter ;
return result ;
}
// Get integer value from text
// NOTE: This function replaces atoi() [stdlib.h]
static int TextToInteger ( const char * text )
{
int value = 0 ;
int sign = 1 ;
if ( ( text [ 0 ] = = ' + ' ) | | ( text [ 0 ] = = ' - ' ) )
{
if ( text [ 0 ] = = ' - ' ) sign = - 1 ;
text + + ;
}
for ( int i = 0 ; ( ( text [ i ] > = ' 0 ' ) & & ( text [ i ] < = ' 9 ' ) ) ; + + i ) value = value * 10 + ( int ) ( text [ i ] - ' 0 ' ) ;
return value * sign ;
}
// Encode codepoint into UTF-8 text (char array size returned as parameter)
static const char * CodepointToUTF8 ( int codepoint , int * byteSize )
{
static char utf8 [ 6 ] = { 0 } ;
int size = 0 ;
if ( codepoint < = 0x7f )
{
utf8 [ 0 ] = ( char ) codepoint ;
size = 1 ;
}
else if ( codepoint < = 0x7ff )
{
utf8 [ 0 ] = ( char ) ( ( ( codepoint > > 6 ) & 0x1f ) | 0xc0 ) ;
utf8 [ 1 ] = ( char ) ( ( codepoint & 0x3f ) | 0x80 ) ;
size = 2 ;
}
else if ( codepoint < = 0xffff )
{
utf8 [ 0 ] = ( char ) ( ( ( codepoint > > 12 ) & 0x0f ) | 0xe0 ) ;
utf8 [ 1 ] = ( char ) ( ( ( codepoint > > 6 ) & 0x3f ) | 0x80 ) ;
utf8 [ 2 ] = ( char ) ( ( codepoint & 0x3f ) | 0x80 ) ;
size = 3 ;
}
else if ( codepoint < = 0x10ffff )
{
utf8 [ 0 ] = ( char ) ( ( ( codepoint > > 18 ) & 0x07 ) | 0xf0 ) ;
utf8 [ 1 ] = ( char ) ( ( ( codepoint > > 12 ) & 0x3f ) | 0x80 ) ;
utf8 [ 2 ] = ( char ) ( ( ( codepoint > > 6 ) & 0x3f ) | 0x80 ) ;
utf8 [ 3 ] = ( char ) ( ( codepoint & 0x3f ) | 0x80 ) ;
size = 4 ;
}
* byteSize = size ;
return utf8 ;
}
// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found
// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned
// Total number of bytes processed are returned as a parameter
// NOTE: the standard says U+FFFD should be returned in case of errors
// but that character is not supported by the default font in raylib
static int GetCodepointNext ( const char * text , int * codepointSize )
{
const char * ptr = text ;
int codepoint = 0x3f ; // Codepoint (defaults to '?')
* codepointSize = 1 ;
// Get current codepoint and bytes processed
if ( 0xf0 = = ( 0xf8 & ptr [ 0 ] ) )
{
// 4 byte UTF-8 codepoint
if ( ( ( ptr [ 1 ] & 0xC0 ) ^ 0x80 ) | | ( ( ptr [ 2 ] & 0xC0 ) ^ 0x80 ) | | ( ( ptr [ 3 ] & 0xC0 ) ^ 0x80 ) ) { return codepoint ; } //10xxxxxx checks
codepoint = ( ( 0x07 & ptr [ 0 ] ) < < 18 ) | ( ( 0x3f & ptr [ 1 ] ) < < 12 ) | ( ( 0x3f & ptr [ 2 ] ) < < 6 ) | ( 0x3f & ptr [ 3 ] ) ;
* codepointSize = 4 ;
}
else if ( 0xe0 = = ( 0xf0 & ptr [ 0 ] ) )
{
// 3 byte UTF-8 codepoint */
if ( ( ( ptr [ 1 ] & 0xC0 ) ^ 0x80 ) | | ( ( ptr [ 2 ] & 0xC0 ) ^ 0x80 ) ) { return codepoint ; } //10xxxxxx checks
codepoint = ( ( 0x0f & ptr [ 0 ] ) < < 12 ) | ( ( 0x3f & ptr [ 1 ] ) < < 6 ) | ( 0x3f & ptr [ 2 ] ) ;
* codepointSize = 3 ;
}
else if ( 0xc0 = = ( 0xe0 & ptr [ 0 ] ) )
{
// 2 byte UTF-8 codepoint
if ( ( ptr [ 1 ] & 0xC0 ) ^ 0x80 ) { return codepoint ; } //10xxxxxx checks
codepoint = ( ( 0x1f & ptr [ 0 ] ) < < 6 ) | ( 0x3f & ptr [ 1 ] ) ;
* codepointSize = 2 ;
}
else if ( 0x00 = = ( 0x80 & ptr [ 0 ] ) )
{
// 1 byte UTF-8 codepoint
codepoint = ptr [ 0 ] ;
* codepointSize = 1 ;
}
return codepoint ;
}
# endif // RAYGUI_STANDALONE
# endif // RAYGUI_IMPLEMENTATION