2021-07-28 14:15:43 +03:00
/*******************************************************************************************
*
2022-06-06 12:11:39 +03:00
* raygui v3 .2 - A simple and easy - to - use immediate - mode gui library
2021-07-28 14:15:43 +03:00
*
* 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 .
*
* Controls provided :
*
* # Container / separators Controls
2022-06-06 12:11:39 +03:00
* - WindowBox - - > StatusBar , Panel
* - GroupBox - - > Line
2021-07-28 14:15:43 +03:00
* - Line
2022-06-06 12:11:39 +03:00
* - Panel - - > StatusBar
* - ScrollPanel - - > StatusBar
2021-07-28 14:15:43 +03:00
*
* # Basic Controls
* - Label
* - Button
* - LabelButton - - > Label
* - Toggle
* - ToggleGroup - - > Toggle
* - CheckBox
* - ComboBox
* - DropdownBox
* - TextBox
* - TextBoxMulti
* - 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 ) .
*
2021-10-27 12:25:24 +03:00
*
2022-06-06 12:11:39 +03:00
* RAYGUI STYLE ( guiStyle ) :
2021-10-27 12:25:24 +03:00
*
* 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 .
*
*
2022-06-06 12:11:39 +03:00
* RAYGUI ICONS ( guiIcons ) :
2021-10-27 12:25:24 +03:00
*
* 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
2022-06-06 12:11:39 +03:00
* must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS will be loaded
2021-10-27 12:25:24 +03:00
*
* 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 :
*
2022-06-06 12:11:39 +03:00
* static unsigned int guiIcons [ RAYGUI_ICON_MAX_ICONS * RAYGUI_ICON_DATA_ELEMENTS ] ;
2021-10-27 12:25:24 +03:00
*
* guiIcons size is by default : 256 * ( 16 * 16 / 32 ) = 2048 * 4 = 8192 bytes = 8 KB
*
* TOOL : rGuiIcons is a visual tool to customize raygui icons .
*
*
2021-07-28 14:15:43 +03:00
* 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 ) .
*
2022-06-06 12:11:39 +03:00
* # define RAYGUI_NO_ICONS
2021-10-27 12:25:24 +03:00
* Avoid including embedded ricons data ( 256 icons , 16 x16 pixels , 1 - bit per pixel , 2 KB )
2021-08-25 01:51:37 +03:00
*
2022-06-06 12:11:39 +03:00
* # define RAYGUI_CUSTOM_ICONS
2021-10-27 12:25:24 +03:00
* Includes custom ricons . h header defining a set of custom icons ,
2021-08-25 01:51:37 +03:00
* this file can be generated using rGuiIcons tool
2021-07-28 14:15:43 +03:00
*
*
* VERSIONS HISTORY :
2022-06-06 12:11:39 +03:00
* 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
2021-10-27 12:25:24 +03:00
* REDESIGNED : GuiTextBoxMulti ( )
* REMOVED : GuiImageButton * ( )
* Multiple minor tweaks and bugs corrected
* 2.9 ( 17 - Mar - 2021 ) REMOVED : Tooltip API
2021-07-28 14:15:43 +03:00
* 2.8 ( 03 - May - 2020 ) Centralized rectangles drawing to GuiDrawRectangle ( )
2021-10-27 12:25:24 +03:00
* 2.7 ( 20 - Feb - 2020 ) ADDED : Possible tooltips API
2021-07-28 14:15:43 +03:00
* 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
2021-10-27 12:25:24 +03:00
* ADDED : 8 new custom styles ready to use
2021-07-28 14:15:43 +03:00
* Multiple minor tweaks and bugs corrected
* 2.5 ( 28 - May - 2019 ) Implemented extended GuiTextBox ( ) , GuiValueBox ( ) , GuiSpinner ( )
2021-10-27 12:25:24 +03:00
* 2.3 ( 29 - Apr - 2019 ) ADDED : rIcons auxiliar library and support for it , multiple controls reviewed
2021-07-28 14:15:43 +03:00
* Refactor all controls drawing mechanism to use control state
2021-10-27 12:25:24 +03:00
* 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 ( ) . . .
2021-07-28 14:15:43 +03:00
* 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 )
2021-10-27 12:25:24 +03:00
* 1.3 ( 12 - Jun - 2017 ) Complete redesign of style system
2021-07-28 14:15:43 +03:00
* 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 .
*
2021-10-27 12:25:24 +03:00
*
2021-07-28 14:15:43 +03:00
* CONTRIBUTORS :
2021-08-25 01:51:37 +03:00
*
* Ramon Santamaria : Supervision , review , redesign , update and maintenance
2021-07-28 14:15:43 +03:00
* 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
*
2022-06-06 12:11:39 +03:00
* Copyright ( c ) 2014 - 2022 Ramon Santamaria ( @ raysan5 )
2021-07-28 14:15:43 +03:00
*
* 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
2022-06-06 12:11:39 +03:00
# define RAYGUI_VERSION "3.2"
2021-07-28 14:15:43 +03:00
# if !defined(RAYGUI_STANDALONE)
# include "raylib.h"
# endif
2021-10-27 12:25:24 +03:00
// 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
2021-07-28 14:15:43 +03:00
# if defined(_WIN32)
# if defined(BUILD_LIBTYPE_SHARED)
2021-10-27 12:25:24 +03:00
# define RAYGUIAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
2021-07-28 14:15:43 +03:00
# elif defined(USE_LIBTYPE_SHARED)
2021-10-27 12:25:24 +03:00
# define RAYGUIAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
2021-07-28 14:15:43 +03:00
# endif
# endif
2021-10-27 12:25:24 +03:00
// Function specifiers definition
# ifndef RAYGUIAPI
# define RAYGUIAPI // Functions defined as 'extern' by default (implicit specifiers)
2021-07-28 14:15:43 +03:00
# endif
2021-10-27 12:25:24 +03:00
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
2021-07-28 14:15:43 +03:00
// 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
2022-06-06 12:11:39 +03:00
// 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
2021-07-28 14:15:43 +03:00
//----------------------------------------------------------------------------------
// 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 ;
2021-10-27 12:25:24 +03:00
// Vector3 type // -- ConvertHSVtoRGB(), ConvertRGBtoHSV()
2021-07-28 14:15:43 +03:00
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 ;
2021-10-27 12:25:24 +03:00
// TODO: Texture2D type is very coupled to raylib, required by Font type
2021-07-28 14:15:43 +03:00
// 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 ;
2021-09-02 01:39:47 +03:00
// 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 ;
2021-07-28 14:15:43 +03:00
// 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)
2021-09-02 01:39:47 +03:00
int glyphCount ; // Number of characters
2021-07-28 14:15:43 +03:00
Texture2D texture ; // Characters texture atlas
Rectangle * recs ; // Characters rectangles in texture
2021-08-25 01:51:37 +03:00
GlyphInfo * chars ; // Characters info data
2021-07-28 14:15:43 +03:00
} Font ;
# endif
// Style property
typedef struct GuiStyleProp {
unsigned short controlId ;
unsigned short propertyId ;
2022-06-06 12:11:39 +03:00
unsigned int propertyValue ;
2021-07-28 14:15:43 +03:00
} GuiStyleProp ;
// Gui control state
typedef enum {
2022-06-06 12:11:39 +03:00
STATE_NORMAL = 0 ,
STATE_FOCUSED ,
STATE_PRESSED ,
STATE_DISABLED ,
} GuiState ;
2021-07-28 14:15:43 +03:00
// Gui control text alignment
typedef enum {
2022-06-06 12:11:39 +03:00
TEXT_ALIGN_LEFT = 0 ,
TEXT_ALIGN_CENTER ,
TEXT_ALIGN_RIGHT ,
2021-07-28 14:15:43 +03:00
} GuiTextAlignment ;
// Gui controls
typedef enum {
2022-06-06 12:11:39 +03:00
// Default -> populates to all controls when set
DEFAULT = 0 ,
// Basic controls
2021-10-27 12:25:24 +03:00
LABEL , // Used also for: LABELBUTTON
BUTTON ,
TOGGLE , // Used also for: TOGGLEGROUP
SLIDER , // Used also for: SLIDERBAR
2021-07-28 14:15:43 +03:00
PROGRESSBAR ,
CHECKBOX ,
COMBOBOX ,
DROPDOWNBOX ,
2021-10-27 12:25:24 +03:00
TEXTBOX , // Used also for: TEXTBOXMULTI
2021-07-28 14:15:43 +03:00
VALUEBOX ,
2022-06-06 12:11:39 +03:00
SPINNER , // Uses: BUTTON, VALUEBOX
2021-07-28 14:15:43 +03:00
LISTVIEW ,
COLORPICKER ,
SCROLLBAR ,
STATUSBAR
} GuiControl ;
// Gui base properties for every control
2021-10-27 12:25:24 +03:00
// NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties)
2021-07-28 14:15:43 +03:00
typedef enum {
BORDER_COLOR_NORMAL = 0 ,
BASE_COLOR_NORMAL ,
TEXT_COLOR_NORMAL ,
BORDER_COLOR_FOCUSED ,
BASE_COLOR_FOCUSED ,
TEXT_COLOR_FOCUSED ,
BORDER_COLOR_PRESSED ,
BASE_COLOR_PRESSED ,
TEXT_COLOR_PRESSED ,
BORDER_COLOR_DISABLED ,
BASE_COLOR_DISABLED ,
TEXT_COLOR_DISABLED ,
BORDER_WIDTH ,
TEXT_PADDING ,
TEXT_ALIGNMENT ,
RESERVED
} GuiControlProperty ;
// Gui extended properties depend on control
2021-10-27 12:25:24 +03:00
// NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default 8 properties)
2022-06-06 12:11:39 +03:00
//----------------------------------------------------------------------------------
2021-07-28 14:15:43 +03:00
2021-10-27 12:25:24 +03:00
// DEFAULT extended properties
2022-06-06 12:11:39 +03:00
// NOTE: Those properties are common to all controls or global
2021-07-28 14:15:43 +03:00
typedef enum {
2022-06-06 12:11:39 +03:00
TEXT_SIZE = 16 , // Text size (glyphs max height)
TEXT_SPACING , // Text spacing between glyphs
LINE_COLOR , // Line control color
BACKGROUND_COLOR , // Background color
2021-07-28 14:15:43 +03:00
} GuiDefaultProperty ;
// Label
//typedef enum { } GuiLabelProperty;
2022-06-06 12:11:39 +03:00
// Button/Spinner
2021-07-28 14:15:43 +03:00
//typedef enum { } GuiButtonProperty;
2021-10-27 12:25:24 +03:00
// Toggle/ToggleGroup
2021-07-28 14:15:43 +03:00
typedef enum {
2022-06-06 12:11:39 +03:00
GROUP_PADDING = 16 , // ToggleGroup separation between toggles
2021-07-28 14:15:43 +03:00
} GuiToggleProperty ;
2021-10-27 12:25:24 +03:00
// Slider/SliderBar
2021-07-28 14:15:43 +03:00
typedef enum {
2022-06-06 12:11:39 +03:00
SLIDER_WIDTH = 16 , // Slider size of internal bar
SLIDER_PADDING // Slider/SliderBar internal bar padding
2021-07-28 14:15:43 +03:00
} GuiSliderProperty ;
// ProgressBar
typedef enum {
2022-06-06 12:11:39 +03:00
PROGRESS_PADDING = 16 , // ProgressBar internal padding
2021-07-28 14:15:43 +03:00
} GuiProgressBarProperty ;
2022-06-06 12:11:39 +03:00
// ScrollBar
typedef enum {
ARROWS_SIZE = 16 ,
ARROWS_VISIBLE ,
SCROLL_SLIDER_PADDING , // (SLIDERBAR, SLIDER_PADDING)
SCROLL_SLIDER_SIZE ,
SCROLL_PADDING ,
SCROLL_SPEED ,
} GuiScrollBarProperty ;
2021-07-28 14:15:43 +03:00
// CheckBox
typedef enum {
2022-06-06 12:11:39 +03:00
CHECK_PADDING = 16 // CheckBox internal check padding
2021-07-28 14:15:43 +03:00
} GuiCheckBoxProperty ;
// ComboBox
typedef enum {
2022-06-06 12:11:39 +03:00
COMBO_BUTTON_WIDTH = 16 , // ComboBox right button width
COMBO_BUTTON_SPACING // ComboBox button separation
2021-07-28 14:15:43 +03:00
} GuiComboBoxProperty ;
// DropdownBox
typedef enum {
2022-06-06 12:11:39 +03:00
ARROW_PADDING = 16 , // DropdownBox arrow separation from border and items
DROPDOWN_ITEMS_SPACING // DropdownBox items separation
2021-07-28 14:15:43 +03:00
} GuiDropdownBoxProperty ;
2021-10-27 12:25:24 +03:00
// TextBox/TextBoxMulti/ValueBox/Spinner
2021-07-28 14:15:43 +03:00
typedef enum {
2022-06-06 12:11:39 +03:00
TEXT_INNER_PADDING = 16 , // TextBox/TextBoxMulti/ValueBox/Spinner inner text padding
TEXT_LINES_SPACING , // TextBoxMulti lines separation
2021-07-28 14:15:43 +03:00
} GuiTextBoxProperty ;
// Spinner
typedef enum {
2022-06-06 12:11:39 +03:00
SPIN_BUTTON_WIDTH = 16 , // Spinner left/right buttons width
SPIN_BUTTON_SPACING , // Spinner buttons separation
2021-07-28 14:15:43 +03:00
} GuiSpinnerProperty ;
// ListView
typedef enum {
2022-06-06 12:11:39 +03:00
LIST_ITEMS_HEIGHT = 16 , // ListView items height
LIST_ITEMS_SPACING , // ListView items separation
SCROLLBAR_WIDTH , // ListView scrollbar size (usually width)
SCROLLBAR_SIDE , // ListView scrollbar side (0-left, 1-right)
2021-07-28 14:15:43 +03:00
} GuiListViewProperty ;
// ColorPicker
typedef enum {
COLOR_SELECTOR_SIZE = 16 ,
2022-06-06 12:11:39 +03:00
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
2021-07-28 14:15:43 +03:00
} GuiColorPickerProperty ;
2022-06-06 12:11:39 +03:00
# define SCROLLBAR_LEFT_SIDE 0
# define SCROLLBAR_RIGHT_SIDE 1
2021-07-28 14:15:43 +03:00
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
// ...
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
2021-08-20 12:56:25 +03:00
# if defined(__cplusplus)
extern " C " { // Prevents name mangling of functions
# endif
2021-09-02 01:39:47 +03:00
// Global gui state control functions
2021-10-27 12:25:24 +03:00
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 GuiFade ( 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)
2021-07-28 14:15:43 +03:00
// Font set/get functions
2021-10-27 12:25:24 +03:00
RAYGUIAPI void GuiSetFont ( Font font ) ; // Set gui custom font (global state)
RAYGUIAPI Font GuiGetFont ( void ) ; // Get gui custom font (global state)
2021-07-28 14:15:43 +03:00
// Style set/get functions
2021-10-27 12:25:24 +03:00
RAYGUIAPI void GuiSetStyle ( int control , int property , int value ) ; // Set one style property
RAYGUIAPI int GuiGetStyle ( int control , int property ) ; // Get one style property
2021-07-28 14:15:43 +03:00
// Container/separator controls, useful for controls organization
2021-10-27 12:25:24 +03:00
RAYGUIAPI bool GuiWindowBox ( Rectangle bounds , const char * title ) ; // Window Box control, shows a window that can be closed
RAYGUIAPI void GuiGroupBox ( Rectangle bounds , const char * text ) ; // Group Box control with text name
RAYGUIAPI void GuiLine ( Rectangle bounds , const char * text ) ; // Line separator control, could contain text
2022-06-06 12:11:39 +03:00
RAYGUIAPI void GuiPanel ( Rectangle bounds , const char * text ) ; // Panel control, useful to group controls
RAYGUIAPI Rectangle GuiScrollPanel ( Rectangle bounds , const char * text , Rectangle content , Vector2 * scroll ) ; // Scroll Panel control
2021-07-28 14:15:43 +03:00
// Basic controls set
2021-10-27 12:25:24 +03:00
RAYGUIAPI void GuiLabel ( Rectangle bounds , const char * text ) ; // Label control, shows text
RAYGUIAPI bool GuiButton ( Rectangle bounds , const char * text ) ; // Button control, returns true when clicked
RAYGUIAPI bool GuiLabelButton ( Rectangle bounds , const char * text ) ; // Label button control, show true when clicked
RAYGUIAPI bool 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 bool 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 bool GuiDropdownBox ( Rectangle bounds , const char * text , int * active , bool editMode ) ; // Dropdown Box control, returns selected item
RAYGUIAPI bool GuiSpinner ( Rectangle bounds , const char * text , int * value , int minValue , int maxValue , bool editMode ) ; // Spinner control, returns selected value
RAYGUIAPI bool GuiValueBox ( Rectangle bounds , const char * text , int * value , int minValue , int maxValue , bool editMode ) ; // Value Box control, updates input text with numbers
RAYGUIAPI bool GuiTextBox ( Rectangle bounds , char * text , int textSize , bool editMode ) ; // Text Box control, updates input text
RAYGUIAPI bool GuiTextBoxMulti ( Rectangle bounds , char * text , int textSize , bool editMode ) ; // Text Box control with multiple lines
RAYGUIAPI float GuiSlider ( Rectangle bounds , const char * textLeft , const char * textRight , float value , float minValue , float maxValue ) ; // Slider control, returns selected value
RAYGUIAPI float GuiSliderBar ( Rectangle bounds , const char * textLeft , const char * textRight , float value , float minValue , float maxValue ) ; // Slider Bar control, returns selected value
RAYGUIAPI float GuiProgressBar ( Rectangle bounds , const char * textLeft , const char * textRight , float value , float minValue , float maxValue ) ; // Progress Bar control, shows current progress value
RAYGUIAPI void GuiStatusBar ( Rectangle bounds , const char * text ) ; // Status Bar control, shows info text
RAYGUIAPI void GuiDummyRec ( Rectangle bounds , const char * text ) ; // Dummy control for placeholders
2022-06-06 12:11:39 +03:00
RAYGUIAPI Vector2 GuiGrid ( Rectangle bounds , const char * text , float spacing , int subdivs ) ; // Grid control, returns mouse cell position
2021-07-28 14:15:43 +03:00
// Advance controls set
2021-10-27 12:25:24 +03:00
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 * focus , int * scrollIndex , int active ) ; // 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
2022-06-06 12:11:39 +03:00
RAYGUIAPI int GuiTextInputBox ( Rectangle bounds , const char * title , const char * message , const char * buttons , char * text , int textMaxSize , int * secretViewActive ) ; // Text Input Box control, ask for text, supports secret
RAYGUIAPI Color GuiColorPicker ( Rectangle bounds , const char * text , Color color ) ; // Color Picker control (multiple color controls)
RAYGUIAPI Color GuiColorPanel ( Rectangle bounds , const char * text , Color color ) ; // Color Panel control
RAYGUIAPI float GuiColorBarAlpha ( Rectangle bounds , const char * text , float alpha ) ; // Color Bar Alpha control
RAYGUIAPI float GuiColorBarHue ( Rectangle bounds , const char * text , float value ) ; // Color Bar Hue control
2021-07-28 14:15:43 +03:00
// Styles loading functions
2021-10-27 12:25:24 +03:00
RAYGUIAPI void GuiLoadStyle ( const char * fileName ) ; // Load style file over global style variable (.rgs)
RAYGUIAPI void GuiLoadStyleDefault ( void ) ; // Load style default over global style
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
// Icons functionality
2021-10-27 12:25:24 +03:00
RAYGUIAPI const char * GuiIconText ( int iconId , const char * text ) ; // Get text with icon id prepended (if supported)
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_NO_ICONS)
2021-10-27 12:25:24 +03:00
RAYGUIAPI void GuiDrawIcon ( int iconId , int posX , int posY , int pixelSize , Color color ) ;
2021-07-28 14:15:43 +03:00
2021-10-27 12:25:24 +03:00
RAYGUIAPI unsigned int * GuiGetIcons ( void ) ; // Get full icons data pointer
RAYGUIAPI unsigned int * GuiGetIconData ( int iconId ) ; // Get icon bit data
RAYGUIAPI void GuiSetIconData ( int iconId , unsigned int * data ) ; // Set icon bit data
2022-06-06 12:11:39 +03:00
RAYGUIAPI void GuiSetIconScale ( unsigned int scale ) ; // Set icon scale (1 by default)
2021-07-28 14:15:43 +03:00
2021-10-27 12:25:24 +03:00
RAYGUIAPI void GuiSetIconPixel ( int iconId , int x , int y ) ; // Set icon pixel value
RAYGUIAPI void GuiClearIconPixel ( int iconId , int x , int y ) ; // Clear icon pixel value
RAYGUIAPI bool GuiCheckIconPixel ( int iconId , int x , int y ) ; // Check icon pixel value
2022-06-06 12:11:39 +03:00
# 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_206 = 206 ,
ICON_207 = 207 ,
ICON_208 = 208 ,
ICON_209 = 209 ,
ICON_210 = 210 ,
ICON_211 = 211 ,
ICON_212 = 212 ,
ICON_213 = 213 ,
ICON_214 = 214 ,
ICON_215 = 215 ,
ICON_216 = 216 ,
ICON_217 = 217 ,
ICON_218 = 218 ,
ICON_219 = 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
2021-07-28 14:15:43 +03:00
# endif
# if defined(__cplusplus)
} // Prevents name mangling of functions
# endif
# endif // RAYGUI_H
/***********************************************************************************
*
* RAYGUI IMPLEMENTATION
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined(RAYGUI_IMPLEMENTATION)
2021-10-27 12:25:24 +03:00
# 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(), GuiTextBoxMulti(), GuiValueBox()], memset(), memcpy()
# include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() [TextFormat()]
2021-07-28 14:15:43 +03:00
# include <math.h> // Required for: roundf() [GuiColorPicker()]
# ifdef __cplusplus
# define RAYGUI_CLITERAL(name) name
# else
# define RAYGUI_CLITERAL(name) (name)
# endif
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_NO_ICONS) && !defined(RAYGUI_CUSTOM_ICONS)
2021-08-25 01:51:37 +03:00
2022-06-06 12:11:39 +03:00
// 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
2021-08-25 01:51:37 +03:00
// Icons data is defined by bit array (every bit represents one pixel)
2022-06-06 12:11:39 +03:00
// 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)
2021-10-27 12:25:24 +03:00
2021-07-28 14:15:43 +03:00
//----------------------------------------------------------------------------------
2021-10-27 12:25:24 +03:00
// 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
//
2022-06-06 12:11:39 +03:00
// 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
2021-10-27 12:25:24 +03:00
//
// guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB
2021-07-28 14:15:43 +03:00
//----------------------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
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 , 0x47fe483c , 0x443e443e , 0x443e443e , 0x241e75fe , 0x0c06140e , 0x000007fe , // ICON_CUBE_FACE_LEFT
0x7fe00000 , 0x50286030 , 0x47fe4804 , 0x47fe47fe , 0x47fe47fe , 0x27fe77fe , 0x0ffe17fe , 0x000007fe , // ICON_CUBE_FACE_FRONT
0x7fe00000 , 0x50286030 , 0x47fe4804 , 0x44224402 , 0x44224422 , 0x3ff27fe2 , 0x0ffe1ffa , 0x000007fe , // ICON_CUBE_FACE_BOTTOM
0x7fe00000 , 0x70286030 , 0x7ffe7804 , 0x7c227c02 , 0x7c227c22 , 0x3c127de2 , 0x0c061c0a , 0x000007fe , // ICON_CUBE_FACE_RIGHT
0x7fe00000 , 0x7fe87ff0 , 0x7ffe7fe4 , 0x7fe27fe2 , 0x7fe27fe2 , 0x24127fe2 , 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
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_206
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_207
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_208
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_209
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_210
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_211
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_212
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_213
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_214
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_215
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_216
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_217
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_218
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 , // ICON_219
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
2021-08-25 01:51:37 +03:00
} ;
2022-06-06 12:11:39 +03:00
# endif // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS
2021-08-25 01:51:37 +03:00
2022-06-06 12:11:39 +03:00
# ifndef RAYGUI_ICON_SIZE
# define RAYGUI_ICON_SIZE 0
2021-08-25 01:51:37 +03:00
# endif
# define RAYGUI_MAX_CONTROLS 16 // Maximum number of standard controls
2021-10-27 12:25:24 +03:00
# define RAYGUI_MAX_PROPS_BASE 16 // Maximum number of standard properties
2021-08-25 01:51:37 +03:00
# define RAYGUI_MAX_PROPS_EXTENDED 8 // Maximum number of extended properties
2021-07-28 14:15:43 +03:00
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Gui control property style color element
typedef enum { BORDER = 0 , BASE , TEXT , OTHER } GuiPropertyElement ;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
static GuiState guiState = STATE_NORMAL ; // Gui global state, if !STATE_NORMAL, forces defined state
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
static Font guiFont = { 0 } ; // Gui current font (WARNING: highly coupled to raylib)
static bool guiLocked = false ; // Gui lock state (no inputs processed)
static float guiAlpha = 1.0f ; // Gui element transpacency on drawing
static unsigned int guiIconScale = 1 ; // Gui icon default scale (if icons enabled)
2021-07-28 14:15:43 +03:00
2021-10-27 12:25:24 +03:00
//----------------------------------------------------------------------------------
// 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 } ;
2022-06-06 12:11:39 +03:00
static bool guiStyleLoaded = false ; // Style loaded flag for lazy style initialization
2021-07-28 14:15:43 +03:00
//----------------------------------------------------------------------------------
// 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 ) ;
2021-10-27 12:25:24 +03:00
static float GetMouseWheelMove ( void ) ;
2021-07-28 14:15:43 +03:00
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(), GuiTextBoxMulti(), GuiValueBox()
//-------------------------------------------------------------------------------
// Drawing required functions
//-------------------------------------------------------------------------------
static void DrawRectangle ( int x , int y , int width , int height , Color color ) ; // -- GuiDrawRectangle(), GuiDrawIcon()
2021-10-27 12:25:24 +03:00
static void DrawRectangleGradientEx ( Rectangle rec , Color col1 , Color col2 , Color col3 , Color col4 ) ; // -- GuiColorPicker()
2021-07-28 14:15:43 +03:00
//-------------------------------------------------------------------------------
// Text required functions
//-------------------------------------------------------------------------------
2021-10-27 12:25:24 +03:00
static Font LoadFontEx ( const char * fileName , int fontSize , int * fontChars , int glyphCount ) ; // -- GuiLoadStyle()
2021-07-28 14:15:43 +03:00
static Font GetFontDefault ( void ) ; // -- GuiLoadStyleDefault()
2021-10-27 12:25:24 +03:00
static Texture2D LoadTextureFromImage ( Image image ) ; // -- GuiLoadStyle()
static void SetShapesTexture ( Texture2D tex , Rectangle rec ) ; // -- GuiLoadStyle()
2021-07-28 14:15:43 +03:00
static char * LoadFileText ( const char * fileName ) ; // -- GuiLoadStyle()
static const char * GetDirectoryPath ( const char * filePath ) ; // -- GuiLoadStyle()
2021-10-27 12:25:24 +03:00
static Vector2 MeasureTextEx ( Font font , const char * text , float fontSize , float spacing ) ; // -- GetTextWidth(), GuiTextBoxMulti()
static void DrawTextEx ( Font font , const char * text , Vector2 position , float fontSize , float spacing , Color tint ) ; // -- GuiDrawText()
2021-07-28 14:15:43 +03:00
//-------------------------------------------------------------------------------
// raylib functions already implemented in raygui
//-------------------------------------------------------------------------------
2021-09-02 01:39:47 +03:00
static Color GetColor ( int hexValue ) ; // Returns a Color struct from hexadecimal value
2021-07-28 14:15:43 +03:00
static int ColorToInt ( Color color ) ; // Returns hexadecimal value for a Color
static Color Fade ( Color color , float alpha ) ; // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
static bool CheckCollisionPointRec ( Vector2 point , Rectangle rec ) ; // Check if point is inside rectangle
static const char * TextFormat ( const char * text , . . . ) ; // Formatting of text with variables to 'embed'
static const char * * TextSplit ( const char * text , char delimiter , int * count ) ; // Split text into multiple strings
static int TextToInteger ( const char * text ) ; // Get integer value from text
2021-10-27 12:25:24 +03:00
static int GetCodepoint ( const char * text , int * bytesProcessed ) ; // 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)
2021-07-28 14:15:43 +03:00
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 int GetTextWidth ( const char * text ) ; // Gui get text width using default font
static Rectangle GetTextBounds ( int control , Rectangle bounds ) ; // Get text bounds considering control bounds
static const char * GetTextIcon ( const char * text , int * iconId ) ; // Get text icon if provided and move text cursor
static void GuiDrawText ( const char * text , Rectangle bounds , int alignment , Color tint ) ; // Gui draw text using default font
static void GuiDrawRectangle ( Rectangle rec , int borderWidth , Color borderColor , Color color ) ; // Gui draw rectangle using default raygui style
2022-06-06 12:11:39 +03:00
static const char * * GuiTextSplit ( const char * text , int * count , int * textRow ) ; // Split controls text into multiple strings
2021-07-28 14:15:43 +03:00
static Vector3 ConvertHSVtoRGB ( Vector3 hsv ) ; // Convert color data from HSV to RGB
static Vector3 ConvertRGBtoHSV ( Vector3 rgb ) ; // Convert color data from RGB to HSV
2022-06-06 12:11:39 +03:00
static int GuiScrollBar ( Rectangle bounds , int value , int minValue , int maxValue ) ; // Scroll bar control, used by GuiScrollPanel()
2021-07-28 14:15:43 +03:00
//----------------------------------------------------------------------------------
// Gui Setup Functions Definition
//----------------------------------------------------------------------------------
// Enable gui global state
2022-06-06 12:11:39 +03:00
// NOTE: We check for STATE_DISABLED to avoid messing custom global state setups
void GuiEnable ( void ) { if ( guiState = = STATE_DISABLED ) guiState = STATE_NORMAL ; }
2021-07-28 14:15:43 +03:00
// Disable gui global state
2022-06-06 12:11:39 +03:00
// NOTE: We check for STATE_NORMAL to avoid messing custom global state setups
void GuiDisable ( void ) { if ( guiState = = STATE_NORMAL ) guiState = STATE_DISABLED ; }
2021-07-28 14:15:43 +03:00
// Lock gui global state
void GuiLock ( void ) { guiLocked = true ; }
// Unlock gui global state
void GuiUnlock ( void ) { guiLocked = false ; }
2021-10-27 12:25:24 +03:00
// Check if gui is locked (global state)
bool GuiIsLocked ( void ) { return guiLocked ; }
2021-07-28 14:15:43 +03:00
// Set gui controls alpha global state
void GuiFade ( float alpha )
{
if ( alpha < 0.0f ) alpha = 0.0f ;
else if ( alpha > 1.0f ) alpha = 1.0f ;
guiAlpha = alpha ;
}
// Set gui state (global state)
2022-06-06 12:11:39 +03:00
void GuiSetState ( int state ) { guiState = ( GuiState ) state ; }
2021-07-28 14:15:43 +03:00
// 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 ;
GuiSetStyle ( DEFAULT , TEXT_SIZE , font . baseSize ) ;
}
}
// 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 ( ) ;
2021-10-27 12:25:24 +03:00
guiStyle [ control * ( RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED ) + property ] = value ;
2021-07-28 14:15:43 +03:00
// Default properties are propagated to all controls
2021-10-27 12:25:24 +03:00
if ( ( control = = 0 ) & & ( property < RAYGUI_MAX_PROPS_BASE ) )
2021-07-28 14:15:43 +03:00
{
2021-10-27 12:25:24 +03:00
for ( int i = 1 ; i < RAYGUI_MAX_CONTROLS ; i + + ) guiStyle [ i * ( RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED ) + property ] = value ;
2021-07-28 14:15:43 +03:00
}
}
// Get control style property value
int GuiGetStyle ( int control , int property )
{
if ( ! guiStyleLoaded ) GuiLoadStyleDefault ( ) ;
2021-10-27 12:25:24 +03:00
return guiStyle [ control * ( RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED ) + property ] ;
2021-07-28 14:15:43 +03:00
}
//----------------------------------------------------------------------------------
// Gui Controls Functions Definition
//----------------------------------------------------------------------------------
// Window Box control
bool GuiWindowBox ( Rectangle bounds , const char * title )
{
2022-06-06 12:11:39 +03:00
// Window title bar height (including borders)
2021-07-28 14:15:43 +03:00
// NOTE: This define is also used by GuiMessageBox() and GuiTextInputBox()
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT)
# define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24
# endif
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
//GuiState state = guiState;
2021-07-28 14:15:43 +03:00
bool clicked = false ;
2022-06-06 12:11:39 +03:00
int statusBarHeight = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT ;
2021-07-28 14:15:43 +03:00
Rectangle statusBar = { bounds . x , bounds . y , bounds . width , ( float ) statusBarHeight } ;
if ( bounds . height < statusBarHeight * 2.0f ) bounds . height = statusBarHeight * 2.0f ;
2022-06-06 12:11:39 +03:00
Rectangle windowPanel = { bounds . x , bounds . y + ( float ) statusBarHeight - 1 , bounds . width , bounds . height - ( float ) statusBarHeight + 1 } ;
2021-07-28 14:15:43 +03:00
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
2022-06-06 12:11:39 +03:00
GuiPanel ( windowPanel , NULL ) ; // Draw window base
2021-07-28 14:15:43 +03:00
// Draw window close button
int tempBorderWidth = GuiGetStyle ( BUTTON , BORDER_WIDTH ) ;
int tempTextAlignment = GuiGetStyle ( BUTTON , TEXT_ALIGNMENT ) ;
GuiSetStyle ( BUTTON , BORDER_WIDTH , 1 ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
# if defined(RAYGUI_NO_ICONS)
2021-07-28 14:15:43 +03:00
clicked = GuiButton ( closeButtonRec , " x " ) ;
2021-10-27 12:25:24 +03:00
# else
2022-06-06 12:11:39 +03:00
clicked = GuiButton ( closeButtonRec , GuiIconText ( ICON_CROSS_SMALL , NULL ) ) ;
2021-07-28 14:15:43 +03:00
# endif
GuiSetStyle ( BUTTON , BORDER_WIDTH , tempBorderWidth ) ;
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , tempTextAlignment ) ;
//--------------------------------------------------------------------
return clicked ;
}
// Group Box control with text name
void GuiGroupBox ( Rectangle bounds , const char * text )
{
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_GROUPBOX_LINE_THICK)
# define RAYGUI_GROUPBOX_LINE_THICK 1
# endif
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
// Draw control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
GuiDrawRectangle ( RAYGUI_CLITERAL ( Rectangle ) { bounds . x , bounds . y , RAYGUI_GROUPBOX_LINE_THICK , bounds . height } , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( DEFAULT , ( state = = STATE_DISABLED ) ? BORDER_COLOR_DISABLED : LINE_COLOR ) ) , guiAlpha ) ) ;
GuiDrawRectangle ( RAYGUI_CLITERAL ( Rectangle ) { bounds . x , bounds . y + bounds . height - 1 , bounds . width , RAYGUI_GROUPBOX_LINE_THICK } , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( DEFAULT , ( state = = STATE_DISABLED ) ? BORDER_COLOR_DISABLED : LINE_COLOR ) ) , guiAlpha ) ) ;
GuiDrawRectangle ( RAYGUI_CLITERAL ( Rectangle ) { bounds . x + bounds . width - 1 , bounds . y , RAYGUI_GROUPBOX_LINE_THICK , bounds . height } , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( DEFAULT , ( state = = STATE_DISABLED ) ? BORDER_COLOR_DISABLED : LINE_COLOR ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
GuiLine ( RAYGUI_CLITERAL ( Rectangle ) { bounds . x , bounds . y - GuiGetStyle ( DEFAULT , TEXT_SIZE ) / 2 , bounds . width , ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) } , text ) ;
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
}
// Line control
void GuiLine ( Rectangle bounds , const char * text )
{
2022-06-06 12:11:39 +03:00
# 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
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
Color color = Fade ( GetColor ( GuiGetStyle ( DEFAULT , ( state = = STATE_DISABLED ) ? BORDER_COLOR_DISABLED : LINE_COLOR ) ) , guiAlpha ) ;
2021-07-28 14:15:43 +03:00
// 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 } ;
2021-10-27 12:25:24 +03:00
textBounds . width = ( float ) GetTextWidth ( text ) ;
2022-06-06 12:11:39 +03:00
textBounds . height = bounds . height ;
textBounds . x = bounds . x + RAYGUI_LINE_MARGIN_TEXT ;
textBounds . y = bounds . y ;
2021-07-28 14:15:43 +03:00
// Draw line with embedded text label: "--- text --------------"
2022-06-06 12:11:39 +03:00
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 ) ;
2021-07-28 14:15:43 +03:00
}
//--------------------------------------------------------------------
}
// Panel control
2022-06-06 12:11:39 +03:00
void GuiPanel ( Rectangle bounds , const char * text )
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_PANEL_BORDER_WIDTH)
# define RAYGUI_PANEL_BORDER_WIDTH 1
# endif
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 ;
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
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 ;
}
2021-07-28 14:15:43 +03:00
// Draw control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( text ! = NULL ) GuiStatusBar ( statusBar , text ) ; // Draw panel header as status bar
GuiDrawRectangle ( bounds , RAYGUI_PANEL_BORDER_WIDTH , Fade ( GetColor ( GuiGetStyle ( DEFAULT , ( state = = STATE_DISABLED ) ? BORDER_COLOR_DISABLED : LINE_COLOR ) ) , guiAlpha ) ,
Fade ( GetColor ( GuiGetStyle ( DEFAULT , ( state = = STATE_DISABLED ) ? BASE_COLOR_DISABLED : BACKGROUND_COLOR ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
}
// Scroll Panel control
2022-06-06 12:11:39 +03:00
Rectangle GuiScrollPanel ( Rectangle bounds , const char * text , Rectangle content , Vector2 * scroll )
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
Vector2 scrollPos = { 0.0f , 0.0f } ;
if ( scroll ! = NULL ) scrollPos = * scroll ;
2022-06-06 12:11:39 +03:00
// 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 ;
}
2021-07-28 14:15:43 +03:00
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 ;
2022-06-06 12:11:39 +03:00
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 ) } ;
2021-07-28 14:15:43 +03:00
// Calculate view area (area without the scrollbars)
Rectangle 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 ;
2022-06-06 12:11:39 +03:00
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 : - 1 ;
float verticalMax = hasVerticalScrollBar ? content . height - bounds . height + ( float ) horizontalScrollBarWidth + ( float ) GuiGetStyle ( DEFAULT , BORDER_WIDTH ) : ( float ) - GuiGetStyle ( DEFAULT , BORDER_WIDTH ) ;
2021-07-28 14:15:43 +03:00
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check button state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
2022-06-06 12:11:39 +03:00
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
# if defined(SUPPORT_SCROLLBAR_KEY_INPUT)
2021-07-28 14:15:43 +03:00
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 ) ;
}
2022-06-06 12:11:39 +03:00
# endif
2021-07-28 14:15:43 +03:00
float wheelMove = GetMouseWheelMove ( ) ;
// Horizontal scroll (Shift + Mouse wheel)
2022-06-06 12:11:39 +03:00
if ( hasHorizontalScrollBar & & ( IsKeyDown ( KEY_LEFT_CONTROL ) | | IsKeyDown ( KEY_RIGHT_SHIFT ) ) ) scrollPos . x + = wheelMove * 20 ;
2021-07-28 14:15:43 +03:00
else scrollPos . y + = wheelMove * 20 ; // 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
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( text ! = NULL ) GuiStatusBar ( statusBar , text ) ; // Draw panel header as status bar
2021-07-28 14:15:43 +03:00
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
2021-10-27 12:25:24 +03:00
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 ) ) ) ;
2021-07-28 14:15:43 +03:00
scrollPos . x = ( float ) - GuiScrollBar ( horizontalScrollBar , ( int ) - scrollPos . x , ( int ) horizontalMin , ( int ) horizontalMax ) ;
}
2022-06-06 12:11:39 +03:00
else scrollPos . x = 0.0f ;
2021-07-28 14:15:43 +03:00
// 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
2021-10-27 12:25:24 +03:00
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 ) ) ) ;
2021-07-28 14:15:43 +03:00
scrollPos . y = ( float ) - GuiScrollBar ( verticalScrollBar , ( int ) - scrollPos . y , ( int ) verticalMin , ( int ) verticalMax ) ;
}
2022-06-06 12:11:39 +03:00
else scrollPos . y = 0.0f ;
2021-07-28 14:15:43 +03:00
// Draw detail corner rectangle if both scroll bars are visible
if ( hasHorizontalScrollBar & & hasVerticalScrollBar )
{
2022-06-06 12:11:39 +03:00
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 } ;
2021-07-28 14:15:43 +03:00
GuiDrawRectangle ( corner , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
}
// Draw scrollbar lines depending on current state
GuiDrawRectangle ( bounds , GuiGetStyle ( DEFAULT , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , BORDER + ( state * 3 ) ) ) , guiAlpha ) , BLANK ) ;
// Set scrollbar slider size back to the way it was before
GuiSetStyle ( SCROLLBAR , SCROLL_SLIDER_SIZE , slider ) ;
//--------------------------------------------------------------------
if ( scroll ! = NULL ) * scroll = scrollPos ;
return view ;
}
// Label control
void GuiLabel ( Rectangle bounds , const char * text )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
// Update control
//--------------------------------------------------------------------
// ...
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
GuiDrawText ( text , GetTextBounds ( LABEL , bounds ) , GuiGetStyle ( LABEL , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( LABEL , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
}
// Button control, returns true when clicked
bool GuiButton ( Rectangle bounds , const char * text )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
bool pressed = false ;
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check button state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
2022-06-06 12:11:39 +03:00
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
if ( IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) ) pressed = true ;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
GuiDrawRectangle ( bounds , GuiGetStyle ( BUTTON , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( BUTTON , BORDER + ( state * 3 ) ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( BUTTON , BASE + ( state * 3 ) ) ) , guiAlpha ) ) ;
GuiDrawText ( text , GetTextBounds ( BUTTON , bounds ) , GuiGetStyle ( BUTTON , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( BUTTON , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
//------------------------------------------------------------------
return pressed ;
}
// Label button control
bool GuiLabelButton ( Rectangle bounds , const char * text )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
bool pressed = false ;
// NOTE: We force bounds.width to be all text
float textWidth = MeasureTextEx ( guiFont , text , ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) , ( float ) GuiGetStyle ( DEFAULT , TEXT_SPACING ) ) . x ;
if ( bounds . width < textWidth ) bounds . width = textWidth ;
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check checkbox state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
2022-06-06 12:11:39 +03:00
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
if ( IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) ) pressed = true ;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
GuiDrawText ( text , GetTextBounds ( LABEL , bounds ) , GuiGetStyle ( LABEL , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( LABEL , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
//--------------------------------------------------------------------
return pressed ;
}
// Toggle Button control, returns true when active
bool GuiToggle ( Rectangle bounds , const char * text , bool active )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check toggle button state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
2022-06-06 12:11:39 +03:00
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
2021-07-28 14:15:43 +03:00
else if ( IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) )
{
2022-06-06 12:11:39 +03:00
state = STATE_NORMAL ;
2021-07-28 14:15:43 +03:00
active = ! active ;
}
2022-06-06 12:11:39 +03:00
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( state = = STATE_NORMAL )
2021-07-28 14:15:43 +03:00
{
GuiDrawRectangle ( bounds , GuiGetStyle ( TOGGLE , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( TOGGLE , ( active ? BORDER_COLOR_PRESSED : ( BORDER + state * 3 ) ) ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( TOGGLE , ( active ? BASE_COLOR_PRESSED : ( BASE + state * 3 ) ) ) ) , guiAlpha ) ) ;
GuiDrawText ( text , GetTextBounds ( TOGGLE , bounds ) , GuiGetStyle ( TOGGLE , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( TOGGLE , ( active ? TEXT_COLOR_PRESSED : ( TEXT + state * 3 ) ) ) ) , guiAlpha ) ) ;
}
else
{
GuiDrawRectangle ( bounds , GuiGetStyle ( TOGGLE , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( TOGGLE , BORDER + state * 3 ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( TOGGLE , BASE + state * 3 ) ) , guiAlpha ) ) ;
GuiDrawText ( text , GetTextBounds ( TOGGLE , bounds ) , GuiGetStyle ( TOGGLE , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( TOGGLE , TEXT + state * 3 ) ) , guiAlpha ) ) ;
}
//--------------------------------------------------------------------
return active ;
}
// Toggle Group control, returns toggled button index
int GuiToggleGroup ( Rectangle bounds , const char * text , int active )
{
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS)
# define RAYGUI_TOGGLEGROUP_MAX_ITEMS 32
2021-07-28 14:15:43 +03:00
# endif
float initBoundsX = bounds . x ;
// Get substrings items from text (items pointers)
2022-06-06 12:11:39 +03:00
int rows [ RAYGUI_TOGGLEGROUP_MAX_ITEMS ] = { 0 } ;
2021-09-02 01:39:47 +03:00
int itemCount = 0 ;
const char * * items = GuiTextSplit ( text , & itemCount , rows ) ;
2021-07-28 14:15:43 +03:00
int prevRow = rows [ 0 ] ;
2021-09-02 01:39:47 +03:00
for ( int i = 0 ; i < itemCount ; i + + )
2021-07-28 14:15:43 +03:00
{
if ( prevRow ! = rows [ i ] )
{
bounds . x = initBoundsX ;
bounds . y + = ( bounds . height + GuiGetStyle ( TOGGLE , GROUP_PADDING ) ) ;
prevRow = rows [ i ] ;
}
if ( i = = active ) GuiToggle ( bounds , items [ i ] , true ) ;
else if ( GuiToggle ( bounds , items [ i ] , false ) = = true ) active = i ;
bounds . x + = ( bounds . width + GuiGetStyle ( TOGGLE , GROUP_PADDING ) ) ;
}
return active ;
}
// Check Box control, returns true when active
bool GuiCheckBox ( Rectangle bounds , const char * text , bool checked )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
Rectangle textBounds = { 0 } ;
if ( text ! = NULL )
{
textBounds . width = ( float ) GetTextWidth ( text ) ;
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 ;
2022-06-06 12:11:39 +03:00
if ( GuiGetStyle ( CHECKBOX , TEXT_ALIGNMENT ) = = TEXT_ALIGN_LEFT ) textBounds . x = bounds . x - textBounds . width - GuiGetStyle ( CHECKBOX , TEXT_PADDING ) ;
2021-07-28 14:15:43 +03:00
}
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
Rectangle totalBounds = {
2022-06-06 12:11:39 +03:00
( GuiGetStyle ( CHECKBOX , TEXT_ALIGNMENT ) = = TEXT_ALIGN_LEFT ) ? textBounds . x : bounds . x ,
2021-07-28 14:15:43 +03:00
bounds . y ,
bounds . width + textBounds . width + GuiGetStyle ( CHECKBOX , TEXT_PADDING ) ,
bounds . height ,
} ;
// Check checkbox state
if ( CheckCollisionPointRec ( mousePoint , totalBounds ) )
{
2022-06-06 12:11:39 +03:00
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
if ( IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) ) checked = ! checked ;
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
GuiDrawRectangle ( bounds , GuiGetStyle ( CHECKBOX , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( CHECKBOX , BORDER + ( state * 3 ) ) ) , guiAlpha ) , 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 , Fade ( GetColor ( GuiGetStyle ( CHECKBOX , TEXT + state * 3 ) ) , guiAlpha ) ) ;
}
2022-06-06 12:11:39 +03:00
GuiDrawText ( text , textBounds , ( GuiGetStyle ( CHECKBOX , TEXT_ALIGNMENT ) = = TEXT_ALIGN_RIGHT ) ? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT , Fade ( GetColor ( GuiGetStyle ( LABEL , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
return checked ;
}
// Combo Box control, returns selected item index
int GuiComboBox ( Rectangle bounds , const char * text , int active )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
bounds . width - = ( GuiGetStyle ( COMBOBOX , COMBO_BUTTON_WIDTH ) + GuiGetStyle ( COMBOBOX , COMBO_BUTTON_SPACING ) ) ;
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
Rectangle selector = { ( float ) bounds . x + bounds . width + GuiGetStyle ( COMBOBOX , COMBO_BUTTON_SPACING ) ,
2021-07-28 14:15:43 +03:00
( float ) bounds . y , ( float ) GuiGetStyle ( COMBOBOX , COMBO_BUTTON_WIDTH ) , ( float ) bounds . height } ;
// Get substrings items from text (items pointers, lengths and count)
2021-09-02 01:39:47 +03:00
int itemCount = 0 ;
const char * * items = GuiTextSplit ( text , & itemCount , NULL ) ;
2021-07-28 14:15:43 +03:00
if ( active < 0 ) active = 0 ;
2021-09-02 01:39:47 +03:00
else if ( active > itemCount - 1 ) active = itemCount - 1 ;
2021-07-28 14:15:43 +03:00
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked & & ( itemCount > 1 ) )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( CheckCollisionPointRec ( mousePoint , bounds ) | |
CheckCollisionPointRec ( mousePoint , selector ) )
{
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) )
{
active + = 1 ;
2021-09-02 01:39:47 +03:00
if ( active > = itemCount ) active = 0 ;
2021-07-28 14:15:43 +03:00
}
2022-06-06 12:11:39 +03:00
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
// Draw combo box main
GuiDrawRectangle ( bounds , GuiGetStyle ( COMBOBOX , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( COMBOBOX , BORDER + ( state * 3 ) ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( COMBOBOX , BASE + ( state * 3 ) ) ) , guiAlpha ) ) ;
GuiDrawText ( items [ active ] , GetTextBounds ( COMBOBOX , bounds ) , GuiGetStyle ( COMBOBOX , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( COMBOBOX , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
// 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 ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
2021-07-28 14:15:43 +03:00
2021-09-02 01:39:47 +03:00
GuiButton ( selector , TextFormat ( " %i/%i " , active + 1 , itemCount ) ) ;
2021-07-28 14:15:43 +03:00
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , tempTextAlign ) ;
GuiSetStyle ( BUTTON , BORDER_WIDTH , tempBorderWidth ) ;
//--------------------------------------------------------------------
return active ;
}
// Dropdown Box control
// NOTE: Returns mouse click
bool GuiDropdownBox ( Rectangle bounds , const char * text , int * active , bool editMode )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
int itemSelected = * active ;
int itemFocused = - 1 ;
// Get substrings items from text (items pointers, lengths and count)
2021-09-02 01:39:47 +03:00
int itemCount = 0 ;
const char * * items = GuiTextSplit ( text , & itemCount , NULL ) ;
2021-07-28 14:15:43 +03:00
Rectangle boundsOpen = bounds ;
2022-06-06 12:11:39 +03:00
boundsOpen . height = ( itemCount + 1 ) * ( bounds . height + GuiGetStyle ( DROPDOWNBOX , DROPDOWN_ITEMS_SPACING ) ) ;
2021-07-28 14:15:43 +03:00
Rectangle itemBounds = bounds ;
bool pressed = false ; // Check mouse button pressed
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ( editMode | | ! guiLocked ) & & ( itemCount > 1 ) )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( editMode )
{
2022-06-06 12:11:39 +03:00
state = STATE_PRESSED ;
2021-07-28 14:15:43 +03:00
// Check if mouse has been pressed or released outside limits
if ( ! CheckCollisionPointRec ( mousePoint , boundsOpen ) )
{
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) | | IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) ) pressed = true ;
}
// Check if already selected item has been pressed again
if ( CheckCollisionPointRec ( mousePoint , bounds ) & & IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) ) pressed = true ;
// Check focused and selected item
2021-09-02 01:39:47 +03:00
for ( int i = 0 ; i < itemCount ; i + + )
2021-07-28 14:15:43 +03:00
{
// Update item rectangle y position for next item
2022-06-06 12:11:39 +03:00
itemBounds . y + = ( bounds . height + GuiGetStyle ( DROPDOWNBOX , DROPDOWN_ITEMS_SPACING ) ) ;
2021-07-28 14:15:43 +03:00
if ( CheckCollisionPointRec ( mousePoint , itemBounds ) )
{
itemFocused = i ;
if ( IsMouseButtonReleased ( MOUSE_LEFT_BUTTON ) )
{
itemSelected = i ;
pressed = true ; // Item selected, change to editMode = false
}
break ;
}
}
itemBounds = bounds ;
}
else
{
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) )
{
pressed = true ;
2022-06-06 12:11:39 +03:00
state = STATE_PRESSED ;
2021-07-28 14:15:43 +03:00
}
2022-06-06 12:11:39 +03:00
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
}
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( editMode ) GuiPanel ( boundsOpen , NULL ) ;
2021-07-28 14:15:43 +03:00
GuiDrawRectangle ( bounds , GuiGetStyle ( DROPDOWNBOX , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , BORDER + state * 3 ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , BASE + state * 3 ) ) , guiAlpha ) ) ;
GuiDrawText ( items [ itemSelected ] , GetTextBounds ( DEFAULT , bounds ) , GuiGetStyle ( DROPDOWNBOX , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , TEXT + state * 3 ) ) , guiAlpha ) ) ;
if ( editMode )
{
// Draw visible items
2021-09-02 01:39:47 +03:00
for ( int i = 0 ; i < itemCount ; i + + )
2021-07-28 14:15:43 +03:00
{
// Update item rectangle y position for next item
2022-06-06 12:11:39 +03:00
itemBounds . y + = ( bounds . height + GuiGetStyle ( DROPDOWNBOX , DROPDOWN_ITEMS_SPACING ) ) ;
2021-07-28 14:15:43 +03:00
if ( i = = itemSelected )
{
GuiDrawRectangle ( itemBounds , GuiGetStyle ( DROPDOWNBOX , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , BORDER_COLOR_PRESSED ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , BASE_COLOR_PRESSED ) ) , guiAlpha ) ) ;
GuiDrawText ( items [ i ] , GetTextBounds ( DEFAULT , itemBounds ) , GuiGetStyle ( DROPDOWNBOX , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , TEXT_COLOR_PRESSED ) ) , guiAlpha ) ) ;
}
else if ( i = = itemFocused )
{
GuiDrawRectangle ( itemBounds , GuiGetStyle ( DROPDOWNBOX , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , BORDER_COLOR_FOCUSED ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , BASE_COLOR_FOCUSED ) ) , guiAlpha ) ) ;
GuiDrawText ( items [ i ] , GetTextBounds ( DEFAULT , itemBounds ) , GuiGetStyle ( DROPDOWNBOX , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , TEXT_COLOR_FOCUSED ) ) , guiAlpha ) ) ;
}
else GuiDrawText ( items [ i ] , GetTextBounds ( DEFAULT , itemBounds ) , GuiGetStyle ( DROPDOWNBOX , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , TEXT_COLOR_NORMAL ) ) , guiAlpha ) ) ;
}
}
2021-10-27 12:25:24 +03:00
// Draw arrows (using icon if available)
2022-06-06 12:11:39 +03:00
# if defined(RAYGUI_NO_ICONS)
2021-10-27 12:25:24 +03:00
GuiDrawText ( " v " , RAYGUI_CLITERAL ( Rectangle ) { bounds . x + bounds . width - GuiGetStyle ( DROPDOWNBOX , ARROW_PADDING ) , bounds . y + bounds . height / 2 - 2 , 10 , 10 } ,
2022-06-06 12:11:39 +03:00
TEXT_ALIGN_CENTER , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-10-27 12:25:24 +03:00
# else
GuiDrawText ( " #120# " , RAYGUI_CLITERAL ( Rectangle ) { bounds . x + bounds . width - GuiGetStyle ( DROPDOWNBOX , ARROW_PADDING ) , bounds . y + bounds . height / 2 - 6 , 10 , 10 } ,
2022-06-06 12:11:39 +03:00
TEXT_ALIGN_CENTER , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ; // ICON_ARROW_DOWN_FILL
2021-10-27 12:25:24 +03:00
# endif
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
* active = itemSelected ;
return pressed ;
}
// Text Box control, updates input text
// NOTE 2: Returns if KEY_ENTER pressed (useful for data validation)
bool GuiTextBox ( Rectangle bounds , char * text , int textSize , bool editMode )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
bool pressed = false ;
Rectangle cursor = {
bounds . x + GuiGetStyle ( TEXTBOX , TEXT_PADDING ) + GetTextWidth ( text ) + 2 ,
bounds . y + bounds . height / 2 - GuiGetStyle ( DEFAULT , TEXT_SIZE ) ,
2021-09-02 01:39:47 +03:00
4 ,
2021-07-28 14:15:43 +03:00
( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) * 2
} ;
2022-06-06 12:11:39 +03:00
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 ) ;
2021-10-27 12:25:24 +03:00
2021-07-28 14:15:43 +03:00
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( editMode )
{
2022-06-06 12:11:39 +03:00
state = STATE_PRESSED ;
2021-10-27 12:25:24 +03:00
2021-07-28 14:15:43 +03:00
int key = GetCharPressed ( ) ; // Returns codepoint as Unicode
int keyCount = ( int ) strlen ( text ) ;
2022-06-06 12:11:39 +03:00
int byteSize = 0 ;
const char * textUTF8 = CodepointToUTF8 ( key , & byteSize ) ;
2021-07-28 14:15:43 +03:00
// Only allow keys in range [32..125]
2022-06-06 12:11:39 +03:00
if ( ( keyCount + byteSize ) < textSize )
2021-07-28 14:15:43 +03:00
{
float maxWidth = ( bounds . width - ( GuiGetStyle ( TEXTBOX , TEXT_INNER_PADDING ) * 2 ) ) ;
if ( ( GetTextWidth ( text ) < ( maxWidth - GuiGetStyle ( DEFAULT , TEXT_SIZE ) ) ) & & ( key > = 32 ) )
{
2021-09-02 01:39:47 +03:00
for ( int i = 0 ; i < byteSize ; i + + )
2021-07-28 14:15:43 +03:00
{
2021-08-20 12:56:25 +03:00
text [ keyCount ] = textUTF8 [ i ] ;
2021-07-28 14:15:43 +03:00
keyCount + + ;
}
text [ keyCount ] = ' \0 ' ;
}
}
// Delete text
if ( keyCount > 0 )
{
if ( IsKeyPressed ( KEY_BACKSPACE ) )
{
2022-06-06 12:11:39 +03:00
while ( ( keyCount > 0 ) & & ( ( text [ - - keyCount ] & 0xc0 ) = = 0x80 ) ) ;
2021-07-28 14:15:43 +03:00
text [ keyCount ] = ' \0 ' ;
}
}
if ( IsKeyPressed ( KEY_ENTER ) | | ( ! CheckCollisionPointRec ( mousePoint , bounds ) & & IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) ) ) pressed = true ;
// Check text alignment to position cursor properly
int textAlignment = GuiGetStyle ( TEXTBOX , TEXT_ALIGNMENT ) ;
2022-06-06 12:11:39 +03:00
if ( textAlignment = = TEXT_ALIGN_CENTER ) cursor . x = bounds . x + GetTextWidth ( text ) / 2 + bounds . width / 2 + 1 ;
else if ( textAlignment = = TEXT_ALIGN_RIGHT ) cursor . x = bounds . x + bounds . width - GuiGetStyle ( TEXTBOX , TEXT_INNER_PADDING ) ;
2021-07-28 14:15:43 +03:00
}
else
{
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
2022-06-06 12:11:39 +03:00
state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) ) pressed = true ;
}
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( state = = STATE_PRESSED )
2021-07-28 14:15:43 +03:00
{
GuiDrawRectangle ( bounds , GuiGetStyle ( TEXTBOX , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BORDER + ( state * 3 ) ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BASE_COLOR_PRESSED ) ) , guiAlpha ) ) ;
}
2022-06-06 12:11:39 +03:00
else if ( state = = STATE_DISABLED )
2021-07-28 14:15:43 +03:00
{
GuiDrawRectangle ( bounds , GuiGetStyle ( TEXTBOX , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BORDER + ( state * 3 ) ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BASE_COLOR_DISABLED ) ) , guiAlpha ) ) ;
}
else GuiDrawRectangle ( bounds , 1 , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BORDER + ( state * 3 ) ) ) , guiAlpha ) , BLANK ) ;
GuiDrawText ( text , GetTextBounds ( TEXTBOX , bounds ) , GuiGetStyle ( TEXTBOX , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-10-27 12:25:24 +03:00
2021-09-02 01:39:47 +03:00
// Draw cursor
if ( editMode ) GuiDrawRectangle ( cursor , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BORDER_COLOR_PRESSED ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
return pressed ;
}
// Spinner control, returns selected value
bool GuiSpinner ( Rectangle bounds , const char * text , int * value , int minValue , int maxValue , bool editMode )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
bool pressed = false ;
int tempValue = * value ;
2022-06-06 12:11:39 +03:00
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 } ;
2021-07-28 14:15:43 +03:00
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 ) ;
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 ;
2022-06-06 12:11:39 +03:00
if ( GuiGetStyle ( SPINNER , TEXT_ALIGNMENT ) = = TEXT_ALIGN_LEFT ) textBounds . x = bounds . x - textBounds . width - GuiGetStyle ( SPINNER , TEXT_PADDING ) ;
2021-07-28 14:15:43 +03:00
}
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check spinner state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
2022-06-06 12:11:39 +03:00
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
}
}
2022-06-06 12:11:39 +03:00
# 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
2021-07-28 14:15:43 +03:00
if ( ! editMode )
{
if ( tempValue < minValue ) tempValue = minValue ;
if ( tempValue > maxValue ) tempValue = maxValue ;
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
// TODO: Set Spinner properties for ValueBox
pressed = 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 ) ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
2021-07-28 14:15:43 +03:00
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , tempTextAlign ) ;
GuiSetStyle ( BUTTON , BORDER_WIDTH , tempBorderWidth ) ;
// Draw text label if provided
2022-06-06 12:11:39 +03:00
GuiDrawText ( text , textBounds , ( GuiGetStyle ( SPINNER , TEXT_ALIGNMENT ) = = TEXT_ALIGN_RIGHT ) ? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT , Fade ( GetColor ( GuiGetStyle ( LABEL , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
* value = tempValue ;
return pressed ;
}
// Value Box control, updates input text with numbers
2021-09-02 01:39:47 +03:00
// NOTE: Requires static variables: frameCounter
2021-07-28 14:15:43 +03:00
bool GuiValueBox ( Rectangle bounds , const char * text , int * value , int minValue , int maxValue , bool editMode )
{
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
# define RAYGUI_VALUEBOX_MAX_CHARS 32
2021-07-28 14:15:43 +03:00
# endif
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
bool pressed = false ;
2022-06-06 12:11:39 +03:00
char textValue [ RAYGUI_VALUEBOX_MAX_CHARS + 1 ] = " \0 " ;
2021-07-28 14:15:43 +03:00
sprintf ( textValue , " %i " , * value ) ;
Rectangle textBounds = { 0 } ;
if ( text ! = NULL )
{
textBounds . width = ( float ) GetTextWidth ( text ) ;
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 ;
2022-06-06 12:11:39 +03:00
if ( GuiGetStyle ( VALUEBOX , TEXT_ALIGNMENT ) = = TEXT_ALIGN_LEFT ) textBounds . x = bounds . x - textBounds . width - GuiGetStyle ( VALUEBOX , TEXT_PADDING ) ;
2021-07-28 14:15:43 +03:00
}
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
bool valueHasChanged = false ;
if ( editMode )
{
2022-06-06 12:11:39 +03:00
state = STATE_PRESSED ;
2021-07-28 14:15:43 +03:00
int keyCount = ( int ) strlen ( textValue ) ;
// Only allow keys in range [48..57]
2022-06-06 12:11:39 +03:00
if ( keyCount < RAYGUI_VALUEBOX_MAX_CHARS )
2021-07-28 14:15:43 +03:00
{
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 ) ;
2022-06-06 12:11:39 +03:00
// NOTE: We are not clamp values until user input finishes
//if (*value > maxValue) *value = maxValue;
//else if (*value < minValue) *value = minValue;
2021-07-28 14:15:43 +03:00
if ( IsKeyPressed ( KEY_ENTER ) | | ( ! CheckCollisionPointRec ( mousePoint , bounds ) & & IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) ) ) pressed = true ;
}
else
{
if ( * value > maxValue ) * value = maxValue ;
else if ( * value < minValue ) * value = minValue ;
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
2022-06-06 12:11:39 +03:00
state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) ) pressed = true ;
}
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
Color baseColor = BLANK ;
2022-06-06 12:11:39 +03:00
if ( state = = STATE_PRESSED ) baseColor = GetColor ( GuiGetStyle ( VALUEBOX , BASE_COLOR_PRESSED ) ) ;
else if ( state = = STATE_DISABLED ) baseColor = GetColor ( GuiGetStyle ( VALUEBOX , BASE_COLOR_DISABLED ) ) ;
2021-07-28 14:15:43 +03:00
// WARNING: BLANK color does not work properly with Fade()
GuiDrawRectangle ( bounds , GuiGetStyle ( VALUEBOX , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( VALUEBOX , BORDER + ( state * 3 ) ) ) , guiAlpha ) , baseColor ) ;
2022-06-06 12:11:39 +03:00
GuiDrawText ( textValue , GetTextBounds ( VALUEBOX , bounds ) , TEXT_ALIGN_CENTER , Fade ( GetColor ( GuiGetStyle ( VALUEBOX , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
2021-09-02 01:39:47 +03:00
// Draw cursor
if ( editMode )
2021-07-28 14:15:43 +03:00
{
// NOTE: ValueBox internal text is always centered
2021-09-02 01:39:47 +03:00
Rectangle cursor = { bounds . x + GetTextWidth ( textValue ) / 2 + bounds . width / 2 + 2 , bounds . y + 2 * GuiGetStyle ( VALUEBOX , BORDER_WIDTH ) , 4 , bounds . height - 4 * GuiGetStyle ( VALUEBOX , BORDER_WIDTH ) } ;
2021-07-28 14:15:43 +03:00
GuiDrawRectangle ( cursor , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( VALUEBOX , BORDER_COLOR_PRESSED ) ) , guiAlpha ) ) ;
}
// Draw text label if provided
2022-06-06 12:11:39 +03:00
GuiDrawText ( text , textBounds , ( GuiGetStyle ( VALUEBOX , TEXT_ALIGNMENT ) = = TEXT_ALIGN_RIGHT ) ? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT , Fade ( GetColor ( GuiGetStyle ( LABEL , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
return pressed ;
}
// Text Box control with multiple lines
bool GuiTextBoxMulti ( Rectangle bounds , char * text , int textSize , bool editMode )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
bool pressed = false ;
Rectangle textAreaBounds = {
2021-10-27 12:25:24 +03:00
bounds . x + GuiGetStyle ( TEXTBOX , BORDER_WIDTH ) + GuiGetStyle ( TEXTBOX , TEXT_INNER_PADDING ) ,
bounds . y + GuiGetStyle ( TEXTBOX , BORDER_WIDTH ) + GuiGetStyle ( TEXTBOX , TEXT_INNER_PADDING ) ,
bounds . width - 2 * ( GuiGetStyle ( TEXTBOX , BORDER_WIDTH ) + GuiGetStyle ( TEXTBOX , TEXT_INNER_PADDING ) ) ,
bounds . height - 2 * ( GuiGetStyle ( TEXTBOX , BORDER_WIDTH ) + GuiGetStyle ( TEXTBOX , TEXT_INNER_PADDING ) )
2021-07-28 14:15:43 +03:00
} ;
// Cursor position, [x, y] values should be updated
2021-09-02 01:39:47 +03:00
Rectangle cursor = { 0 , - 1 , 4 , ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) + 2 } ;
2021-10-27 12:25:24 +03:00
2021-09-02 01:39:47 +03:00
float scaleFactor = ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) / ( float ) guiFont . baseSize ; // Character rectangle scaling factor
2021-07-28 14:15:43 +03:00
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( editMode )
{
2022-06-06 12:11:39 +03:00
state = STATE_PRESSED ;
2021-07-28 14:15:43 +03:00
2021-09-02 01:39:47 +03:00
// We get an Unicode codepoint
2021-10-27 12:25:24 +03:00
int codepoint = GetCharPressed ( ) ;
2021-09-02 01:39:47 +03:00
int textLength = ( int ) strlen ( text ) ; // Length in bytes (UTF-8 string)
2021-07-28 14:15:43 +03:00
// Introduce characters
2021-09-02 01:39:47 +03:00
if ( textLength < ( textSize - 1 ) )
2021-07-28 14:15:43 +03:00
{
2021-09-02 01:39:47 +03:00
if ( IsKeyPressed ( KEY_ENTER ) )
2021-07-28 14:15:43 +03:00
{
2021-09-02 01:39:47 +03:00
text [ textLength ] = ' \n ' ;
textLength + + ;
2021-07-28 14:15:43 +03:00
}
2021-09-02 01:39:47 +03:00
else if ( codepoint > = 32 )
2021-07-28 14:15:43 +03:00
{
2021-09-02 01:39:47 +03:00
// Supports Unicode inputs -> Encoded to UTF-8
int charUTF8Length = 0 ;
const char * charEncoded = CodepointToUTF8 ( codepoint , & charUTF8Length ) ;
memcpy ( text + textLength , charEncoded , charUTF8Length ) ;
textLength + = charUTF8Length ;
2021-07-28 14:15:43 +03:00
}
}
2021-09-02 01:39:47 +03:00
// Delete characters
if ( textLength > 0 )
2021-07-28 14:15:43 +03:00
{
2021-09-02 01:39:47 +03:00
if ( IsKeyPressed ( KEY_BACKSPACE ) )
2021-07-28 14:15:43 +03:00
{
2021-09-02 01:39:47 +03:00
if ( ( unsigned char ) text [ textLength - 1 ] < 127 )
{
// Remove ASCII equivalent character (1 byte)
textLength - - ;
text [ textLength ] = ' \0 ' ;
}
else
{
// Remove latest UTF-8 unicode character introduced (n bytes)
int charUTF8Length = 0 ;
while ( ( ( unsigned char ) text [ textLength - 1 - charUTF8Length ] & 0 b01000000 ) = = 0 ) charUTF8Length + + ;
2021-10-27 12:25:24 +03:00
2021-09-02 01:39:47 +03:00
textLength - = ( charUTF8Length + 1 ) ;
text [ textLength ] = ' \0 ' ;
}
2021-07-28 14:15:43 +03:00
}
}
// Exit edit mode
if ( ! CheckCollisionPointRec ( mousePoint , bounds ) & & IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) ) pressed = true ;
}
else
{
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
2022-06-06 12:11:39 +03:00
state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) ) pressed = true ;
}
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( state = = STATE_PRESSED )
2021-07-28 14:15:43 +03:00
{
GuiDrawRectangle ( bounds , GuiGetStyle ( TEXTBOX , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BORDER + ( state * 3 ) ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BASE_COLOR_PRESSED ) ) , guiAlpha ) ) ;
}
2022-06-06 12:11:39 +03:00
else if ( state = = STATE_DISABLED )
2021-07-28 14:15:43 +03:00
{
GuiDrawRectangle ( bounds , GuiGetStyle ( TEXTBOX , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BORDER + ( state * 3 ) ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BASE_COLOR_DISABLED ) ) , guiAlpha ) ) ;
}
else GuiDrawRectangle ( bounds , 1 , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BORDER + ( state * 3 ) ) ) , guiAlpha ) , BLANK ) ;
2021-09-02 01:39:47 +03:00
int wrapMode = 1 ; // 0-No wrap, 1-Char wrap, 2-Word wrap
Vector2 cursorPos = { textAreaBounds . x , textAreaBounds . y } ;
//int lastSpacePos = 0;
//int lastSpaceWidth = 0;
//int lastSpaceCursorPos = 0;
2021-10-27 12:25:24 +03:00
2021-09-02 01:39:47 +03:00
for ( int i = 0 , codepointLength = 0 ; text [ i ] ! = ' \0 ' ; i + = codepointLength )
{
int codepoint = GetCodepoint ( text + i , & codepointLength ) ;
2021-10-27 12:25:24 +03:00
int index = GetGlyphIndex ( guiFont , codepoint ) ; // If requested codepoint is not found, we get '?' (0x3f)
2021-09-02 01:39:47 +03:00
Rectangle atlasRec = guiFont . recs [ index ] ;
2021-10-27 12:25:24 +03:00
GlyphInfo glyphInfo = guiFont . glyphs [ index ] ; // Glyph measures
if ( ( codepointLength = = 1 ) & & ( codepoint = = ' \n ' ) )
2021-09-02 01:39:47 +03:00
{
2022-06-06 12:11:39 +03:00
cursorPos . y + = ( guiFont . baseSize * scaleFactor + GuiGetStyle ( TEXTBOX , TEXT_LINES_SPACING ) ) ; // Line feed
2021-10-27 12:25:24 +03:00
cursorPos . x = textAreaBounds . x ; // Carriage return
2021-09-02 01:39:47 +03:00
}
else
{
if ( wrapMode = = 1 )
{
int glyphWidth = 0 ;
if ( glyphInfo . advanceX ! = 0 ) glyphWidth + = glyphInfo . advanceX ;
2022-06-06 12:11:39 +03:00
else glyphWidth + = ( int ) ( atlasRec . width + glyphInfo . offsetX ) ;
2021-10-27 12:25:24 +03:00
2021-09-02 01:39:47 +03:00
// Jump line if the end of the text box area has been reached
if ( ( cursorPos . x + ( glyphWidth * scaleFactor ) ) > ( textAreaBounds . x + textAreaBounds . width ) )
{
2022-06-06 12:11:39 +03:00
cursorPos . y + = ( guiFont . baseSize * scaleFactor + GuiGetStyle ( TEXTBOX , TEXT_LINES_SPACING ) ) ; // Line feed
2021-09-02 01:39:47 +03:00
cursorPos . x = textAreaBounds . x ; // Carriage return
}
}
else if ( wrapMode = = 2 )
{
/*
2021-10-27 12:25:24 +03:00
if ( ( codepointLength = = 1 ) & & ( codepoint = = ' ' ) )
2021-09-02 01:39:47 +03:00
{
lastSpacePos = i ;
lastSpaceWidth = 0 ;
lastSpaceCursorPos = cursorPos . x ;
}
// Jump line if last word reaches end of text box area
if ( ( lastSpaceCursorPos + lastSpaceWidth ) > ( textAreaBounds . x + textAreaBounds . width ) )
{
cursorPos . y + = 12 ; // Line feed
cursorPos . x = textAreaBounds . x ; // Carriage return
}
*/
}
2021-10-27 12:25:24 +03:00
2021-09-02 01:39:47 +03:00
// Draw current character glyph
DrawTextCodepoint ( guiFont , codepoint , cursorPos , ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-10-27 12:25:24 +03:00
2021-09-02 01:39:47 +03:00
int glyphWidth = 0 ;
if ( glyphInfo . advanceX ! = 0 ) glyphWidth + = glyphInfo . advanceX ;
2022-06-06 12:11:39 +03:00
else glyphWidth + = ( int ) ( atlasRec . width + glyphInfo . offsetX ) ;
2021-10-27 12:25:24 +03:00
2021-09-02 01:39:47 +03:00
cursorPos . x + = ( glyphWidth * scaleFactor + ( float ) GuiGetStyle ( DEFAULT , TEXT_SPACING ) ) ;
//if (i > lastSpacePos) lastSpaceWidth += (atlasRec.width + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
}
}
cursor . x = cursorPos . x ;
cursor . y = cursorPos . y ;
2021-10-27 12:25:24 +03:00
2021-09-02 01:39:47 +03:00
// Draw cursor position considering text glyphs
if ( editMode ) GuiDrawRectangle ( cursor , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( TEXTBOX , BORDER_COLOR_PRESSED ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
return pressed ;
}
// Slider control with pro parameters
// NOTE: Other GuiSlider*() controls use this one
float GuiSliderPro ( Rectangle bounds , const char * textLeft , const char * textRight , float value , float minValue , float maxValue , int sliderWidth )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
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
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) )
{
2022-06-06 12:11:39 +03:00
state = STATE_PRESSED ;
2021-07-28 14:15:43 +03:00
// Get equivalent value and slider position from mousePoint.x
value = ( ( maxValue - minValue ) * ( mousePoint . x - ( float ) ( bounds . x + sliderWidth / 2 ) ) ) / ( float ) ( bounds . width - sliderWidth ) + minValue ;
if ( sliderWidth > 0 ) slider . x = mousePoint . x - slider . width / 2 ; // Slider
else if ( sliderWidth = = 0 ) slider . width = ( float ) sliderValue ; // SliderBar
}
2022-06-06 12:11:39 +03:00
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
}
if ( value > maxValue ) value = maxValue ;
else if ( value < minValue ) value = minValue ;
}
// 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
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
GuiDrawRectangle ( bounds , GuiGetStyle ( SLIDER , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( SLIDER , BORDER + ( state * 3 ) ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( SLIDER , ( state ! = STATE_DISABLED ) ? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
// Draw slider internal bar (depends on state)
2022-06-06 12:11:39 +03:00
if ( ( state = = STATE_NORMAL ) | | ( state = = STATE_PRESSED ) ) GuiDrawRectangle ( slider , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( SLIDER , BASE_COLOR_PRESSED ) ) , guiAlpha ) ) ;
else if ( state = = STATE_FOCUSED ) GuiDrawRectangle ( slider , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( SLIDER , TEXT_COLOR_FOCUSED ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
// Draw left/right text if provided
if ( textLeft ! = NULL )
{
Rectangle textBounds = { 0 } ;
2021-10-27 12:25:24 +03:00
textBounds . width = ( float ) GetTextWidth ( textLeft ) ;
2021-07-28 14:15:43 +03:00
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 ;
2022-06-06 12:11:39 +03:00
GuiDrawText ( textLeft , textBounds , TEXT_ALIGN_RIGHT , Fade ( GetColor ( GuiGetStyle ( SLIDER , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
}
if ( textRight ! = NULL )
{
Rectangle textBounds = { 0 } ;
2021-10-27 12:25:24 +03:00
textBounds . width = ( float ) GetTextWidth ( textRight ) ;
2021-07-28 14:15:43 +03:00
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 ;
2022-06-06 12:11:39 +03:00
GuiDrawText ( textRight , textBounds , TEXT_ALIGN_LEFT , Fade ( GetColor ( GuiGetStyle ( SLIDER , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
}
//--------------------------------------------------------------------
return value ;
}
// Slider control extended, returns selected value and has text
float 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
float 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
float GuiProgressBar ( Rectangle bounds , const char * textLeft , const char * textRight , float value , float minValue , float maxValue )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
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
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( value > maxValue ) value = maxValue ;
if ( state ! = STATE_DISABLED ) progress . width = ( ( float ) ( value / ( maxValue - minValue ) ) * ( float ) ( bounds . width - 2 * GuiGetStyle ( PROGRESSBAR , BORDER_WIDTH ) ) ) ;
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
GuiDrawRectangle ( bounds , GuiGetStyle ( PROGRESSBAR , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( PROGRESSBAR , BORDER + ( state * 3 ) ) ) , guiAlpha ) , BLANK ) ;
// Draw slider internal progress bar (depends on state)
2022-06-06 12:11:39 +03:00
if ( ( state = = STATE_NORMAL ) | | ( state = = STATE_PRESSED ) ) GuiDrawRectangle ( progress , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( PROGRESSBAR , BASE_COLOR_PRESSED ) ) , guiAlpha ) ) ;
else if ( state = = STATE_FOCUSED ) GuiDrawRectangle ( progress , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( PROGRESSBAR , TEXT_COLOR_FOCUSED ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
// Draw left/right text if provided
if ( textLeft ! = NULL )
{
Rectangle textBounds = { 0 } ;
2021-10-27 12:25:24 +03:00
textBounds . width = ( float ) GetTextWidth ( textLeft ) ;
2021-07-28 14:15:43 +03:00
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 ;
2022-06-06 12:11:39 +03:00
GuiDrawText ( textLeft , textBounds , TEXT_ALIGN_RIGHT , Fade ( GetColor ( GuiGetStyle ( PROGRESSBAR , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
}
if ( textRight ! = NULL )
{
Rectangle textBounds = { 0 } ;
2021-10-27 12:25:24 +03:00
textBounds . width = ( float ) GetTextWidth ( textRight ) ;
2021-07-28 14:15:43 +03:00
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 ;
2022-06-06 12:11:39 +03:00
GuiDrawText ( textRight , textBounds , TEXT_ALIGN_LEFT , Fade ( GetColor ( GuiGetStyle ( PROGRESSBAR , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
}
//--------------------------------------------------------------------
return value ;
}
// Status Bar control
void GuiStatusBar ( Rectangle bounds , const char * text )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
// Draw control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
GuiDrawRectangle ( bounds , GuiGetStyle ( STATUSBAR , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( STATUSBAR , ( state ! = STATE_DISABLED ) ? BORDER_COLOR_NORMAL : BORDER_COLOR_DISABLED ) ) , guiAlpha ) ,
Fade ( GetColor ( GuiGetStyle ( STATUSBAR , ( state ! = STATE_DISABLED ) ? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED ) ) , guiAlpha ) ) ;
GuiDrawText ( text , GetTextBounds ( STATUSBAR , bounds ) , GuiGetStyle ( STATUSBAR , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( STATUSBAR , ( state ! = STATE_DISABLED ) ? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
}
// Dummy rectangle control, intended for placeholding
void GuiDummyRec ( Rectangle bounds , const char * text )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check button state
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
2022-06-06 12:11:39 +03:00
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) ) state = STATE_PRESSED ;
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
GuiDrawRectangle ( bounds , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( DEFAULT , ( state ! = STATE_DISABLED ) ? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED ) ) , guiAlpha ) ) ;
GuiDrawText ( text , GetTextBounds ( DEFAULT , bounds ) , TEXT_ALIGN_CENTER , Fade ( GetColor ( GuiGetStyle ( BUTTON , ( state ! = STATE_DISABLED ) ? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED ) ) , guiAlpha ) ) ;
2021-07-28 14:15:43 +03:00
//------------------------------------------------------------------
}
// List View control
int GuiListView ( Rectangle bounds , const char * text , int * scrollIndex , int active )
{
2021-09-02 01:39:47 +03:00
int itemCount = 0 ;
2021-07-28 14:15:43 +03:00
const char * * items = NULL ;
2021-09-02 01:39:47 +03:00
if ( text ! = NULL ) items = GuiTextSplit ( text , & itemCount , NULL ) ;
2021-07-28 14:15:43 +03:00
2021-09-02 01:39:47 +03:00
return GuiListViewEx ( bounds , items , itemCount , NULL , scrollIndex , active ) ;
2021-07-28 14:15:43 +03:00
}
// List View control with extended parameters
int GuiListViewEx ( Rectangle bounds , const char * * text , int count , int * focus , int * scrollIndex , int active )
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
int itemFocused = ( focus = = NULL ) ? - 1 : * focus ;
int itemSelected = active ;
// Check if we need a scroll bar
bool useScrollBar = false ;
2022-06-06 12:11:39 +03:00
if ( ( GuiGetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT ) + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) ) * count > bounds . height ) useScrollBar = true ;
2021-07-28 14:15:43 +03:00
// Define base item rectangle [0]
Rectangle itemBounds = { 0 } ;
2022-06-06 12:11:39 +03:00
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 ) ;
2021-07-28 14:15:43 +03:00
itemBounds . height = ( float ) GuiGetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT ) ;
if ( useScrollBar ) itemBounds . width - = GuiGetStyle ( LISTVIEW , SCROLLBAR_WIDTH ) ;
// Get items on the list
2022-06-06 12:11:39 +03:00
int visibleItems = ( int ) bounds . height / ( GuiGetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT ) + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) ) ;
2021-07-28 14:15:43 +03:00
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
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
// Check mouse inside list view
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
2022-06-06 12:11:39 +03:00
state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
// 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
2022-06-06 12:11:39 +03:00
itemBounds . y + = ( GuiGetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT ) + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) ) ;
2021-07-28 14:15:43 +03:00
}
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]
2022-06-06 12:11:39 +03:00
itemBounds . y = bounds . y + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) + GuiGetStyle ( DEFAULT , BORDER_WIDTH ) ;
2021-07-28 14:15:43 +03:00
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
GuiDrawRectangle ( bounds , GuiGetStyle ( DEFAULT , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , BORDER + state * 3 ) ) , guiAlpha ) , GetColor ( GuiGetStyle ( DEFAULT , BACKGROUND_COLOR ) ) ) ; // Draw background
// Draw visible items
for ( int i = 0 ; ( ( i < visibleItems ) & & ( text ! = NULL ) ) ; i + + )
{
2022-06-06 12:11:39 +03:00
if ( state = = STATE_DISABLED )
2021-07-28 14:15:43 +03:00
{
if ( ( startIndex + i ) = = itemSelected ) GuiDrawRectangle ( itemBounds , GuiGetStyle ( LISTVIEW , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , BORDER_COLOR_DISABLED ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , BASE_COLOR_DISABLED ) ) , guiAlpha ) ) ;
GuiDrawText ( text [ startIndex + i ] , GetTextBounds ( DEFAULT , itemBounds ) , GuiGetStyle ( LISTVIEW , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , TEXT_COLOR_DISABLED ) ) , guiAlpha ) ) ;
}
else
{
if ( ( startIndex + i ) = = itemSelected )
{
// Draw item selected
GuiDrawRectangle ( itemBounds , GuiGetStyle ( LISTVIEW , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , BORDER_COLOR_PRESSED ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , BASE_COLOR_PRESSED ) ) , guiAlpha ) ) ;
GuiDrawText ( text [ startIndex + i ] , GetTextBounds ( DEFAULT , itemBounds ) , GuiGetStyle ( LISTVIEW , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , TEXT_COLOR_PRESSED ) ) , guiAlpha ) ) ;
}
else if ( ( startIndex + i ) = = itemFocused )
{
// Draw item focused
GuiDrawRectangle ( itemBounds , GuiGetStyle ( LISTVIEW , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , BORDER_COLOR_FOCUSED ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , BASE_COLOR_FOCUSED ) ) , guiAlpha ) ) ;
GuiDrawText ( text [ startIndex + i ] , GetTextBounds ( DEFAULT , itemBounds ) , GuiGetStyle ( LISTVIEW , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , TEXT_COLOR_FOCUSED ) ) , guiAlpha ) ) ;
}
else
{
// Draw item normal
GuiDrawText ( text [ startIndex + i ] , GetTextBounds ( DEFAULT , itemBounds ) , GuiGetStyle ( LISTVIEW , TEXT_ALIGNMENT ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , TEXT_COLOR_NORMAL ) ) , guiAlpha ) ) ;
}
}
// Update item rectangle y position for next item
2022-06-06 12:11:39 +03:00
itemBounds . y + = ( GuiGetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT ) + GuiGetStyle ( LISTVIEW , LIST_ITEMS_SPACING ) ) ;
2021-07-28 14:15:43 +03:00
}
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 ( focus ! = NULL ) * focus = itemFocused ;
if ( scrollIndex ! = NULL ) * scrollIndex = startIndex ;
return itemSelected ;
}
// Color Panel control
2022-06-06 12:11:39 +03:00
Color GuiColorPanel ( Rectangle bounds , const char * text , Color color )
2021-07-28 14:15:43 +03:00
{
2021-10-27 12:25:24 +03:00
const Color colWhite = { 255 , 255 , 255 , 255 } ;
const Color colBlack = { 0 , 0 , 0 , 255 } ;
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
Vector2 pickerSelector = { 0 } ;
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
2021-10-27 12:25:24 +03:00
float hue = - 1.0f ;
2021-07-28 14:15:43 +03:00
Vector3 maxHue = { hue > = 0.0f ? hue : hsv . x , 1.0f , 1.0f } ;
Vector3 rgbHue = ConvertHSVtoRGB ( maxHue ) ;
Color maxHueCol = { ( unsigned char ) ( 255.0f * rgbHue . x ) ,
( unsigned char ) ( 255.0f * rgbHue . y ) ,
( unsigned char ) ( 255.0f * rgbHue . z ) , 255 } ;
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) )
{
2022-06-06 12:11:39 +03:00
state = STATE_PRESSED ;
2021-07-28 14:15:43 +03:00
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 ) } ;
}
2022-06-06 12:11:39 +03:00
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( state ! = STATE_DISABLED )
2021-07-28 14:15:43 +03:00
{
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 , Fade ( colWhite , guiAlpha ) ) ;
}
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 ) ) ;
}
2021-10-27 12:25:24 +03:00
GuiDrawRectangle ( bounds , GuiGetStyle ( COLORPICKER , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( COLORPICKER , BORDER + state * 3 ) ) , guiAlpha ) , BLANK ) ;
2021-07-28 14:15:43 +03:00
//--------------------------------------------------------------------
return color ;
}
// Color Bar Alpha control
// NOTE: Returns alpha value normalized [0..1]
2022-06-06 12:11:39 +03:00
float GuiColorBarAlpha ( Rectangle bounds , const char * text , float alpha )
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_COLORBARALPHA_CHECKED_SIZE)
# define RAYGUI_COLORBARALPHA_CHECKED_SIZE 10
# endif
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-10-27 12:25:24 +03:00
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 } ;
2021-07-28 14:15:43 +03:00
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( CheckCollisionPointRec ( mousePoint , bounds ) | |
CheckCollisionPointRec ( mousePoint , selector ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) )
{
2022-06-06 12:11:39 +03:00
state = STATE_PRESSED ;
2021-07-28 14:15:43 +03:00
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;
}
2022-06-06 12:11:39 +03:00
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
// Draw alpha bar: checked background
2022-06-06 12:11:39 +03:00
if ( state ! = STATE_DISABLED )
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
int checksX = ( int ) bounds . width / RAYGUI_COLORBARALPHA_CHECKED_SIZE ;
int checksY = ( int ) bounds . height / RAYGUI_COLORBARALPHA_CHECKED_SIZE ;
2021-07-28 14:15:43 +03:00
for ( int x = 0 ; x < checksX ; x + + )
{
for ( int y = 0 ; y < checksY ; y + + )
{
2022-06-06 12:11:39 +03:00
Rectangle check = { bounds . x + x * RAYGUI_COLORBARALPHA_CHECKED_SIZE , bounds . y + y * RAYGUI_COLORBARALPHA_CHECKED_SIZE , RAYGUI_COLORBARALPHA_CHECKED_SIZE , RAYGUI_COLORBARALPHA_CHECKED_SIZE } ;
2021-07-28 14:15:43 +03:00
GuiDrawRectangle ( check , 0 , BLANK , ( ( x + y ) % 2 ) ? Fade ( Fade ( GetColor ( GuiGetStyle ( COLORPICKER , BORDER_COLOR_DISABLED ) ) , 0.4f ) , guiAlpha ) : Fade ( Fade ( GetColor ( GuiGetStyle ( COLORPICKER , BASE_COLOR_DISABLED ) ) , 0.4f ) , guiAlpha ) ) ;
}
}
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 ) ) ;
2021-10-27 12:25:24 +03:00
GuiDrawRectangle ( bounds , GuiGetStyle ( COLORPICKER , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( COLORPICKER , BORDER + state * 3 ) ) , guiAlpha ) , BLANK ) ;
2021-07-28 14:15:43 +03:00
// Draw alpha bar: selector
GuiDrawRectangle ( selector , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( COLORPICKER , BORDER + state * 3 ) ) , guiAlpha ) ) ;
//--------------------------------------------------------------------
return alpha ;
}
// Color Bar Hue control
2021-10-27 12:25:24 +03:00
// 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]
2022-06-06 12:11:39 +03:00
float GuiColorBarHue ( Rectangle bounds , const char * text , float hue )
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-10-27 12:25:24 +03:00
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 ) } ;
2021-07-28 14:15:43 +03:00
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( CheckCollisionPointRec ( mousePoint , bounds ) | |
CheckCollisionPointRec ( mousePoint , selector ) )
{
if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) )
{
2022-06-06 12:11:39 +03:00
state = STATE_PRESSED ;
2021-07-28 14:15:43 +03:00
hue = ( mousePoint . y - bounds . y ) * 360 / bounds . height ;
if ( hue < = 0.0f ) hue = 0.0f ;
if ( hue > = 359.0f ) hue = 359.0f ;
}
2022-06-06 12:11:39 +03:00
else state = STATE_FOCUSED ;
2021-07-28 14:15:43 +03:00
/*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
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( state ! = STATE_DISABLED )
2021-07-28 14:15:43 +03:00
{
// Draw hue bar:color bars
2022-06-06 12:11:39 +03:00
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 ) ) ;
2021-10-27 12:25:24 +03:00
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 ) ) ;
2021-07-28 14:15:43 +03:00
}
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 ) ) ;
2021-10-27 12:25:24 +03:00
GuiDrawRectangle ( bounds , GuiGetStyle ( COLORPICKER , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( COLORPICKER , BORDER + state * 3 ) ) , guiAlpha ) , BLANK ) ;
2021-07-28 14:15:43 +03:00
// Draw hue bar: selector
GuiDrawRectangle ( selector , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( COLORPICKER , BORDER + state * 3 ) ) , guiAlpha ) ) ;
//--------------------------------------------------------------------
return hue ;
}
// 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
2022-06-06 12:11:39 +03:00
Color GuiColorPicker ( Rectangle bounds , const char * text , Color color )
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
color = GuiColorPanel ( bounds , NULL , color ) ;
2021-07-28 14:15:43 +03:00
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 } ) ;
2022-06-06 12:11:39 +03:00
hsv . x = GuiColorBarHue ( boundsHue , NULL , hsv . x ) ;
2021-07-28 14:15:43 +03:00
//color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f);
Vector3 rgb = ConvertHSVtoRGB ( hsv ) ;
2021-10-27 12:25:24 +03:00
2021-07-28 14:15:43 +03:00
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 color ;
}
// Message Box control
int GuiMessageBox ( Rectangle bounds , const char * title , const char * message , const char * buttons )
{
2022-06-06 12:11:39 +03:00
# 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
2021-07-28 14:15:43 +03:00
int clicked = - 1 ; // Returns clicked button from buttons list, 0 refers to closed window button
2021-09-02 01:39:47 +03:00
int buttonCount = 0 ;
const char * * buttonsText = GuiTextSplit ( buttons , & buttonCount , NULL ) ;
2021-07-28 14:15:43 +03:00
Rectangle buttonBounds = { 0 } ;
2022-06-06 12:11:39 +03:00
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 ;
2021-07-28 14:15:43 +03:00
Vector2 textSize = MeasureTextEx ( guiFont , message , ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) , 1 ) ;
Rectangle textBounds = { 0 } ;
textBounds . x = bounds . x + bounds . width / 2 - textSize . x / 2 ;
2022-06-06 12:11:39 +03:00
textBounds . y = bounds . y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING ;
2021-07-28 14:15:43 +03:00
textBounds . width = textSize . x ;
2022-06-06 12:11:39 +03:00
textBounds . height = bounds . height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 3 * RAYGUI_MESSAGEBOX_BUTTON_PADDING - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT ;
2021-07-28 14:15:43 +03:00
// Draw control
//--------------------------------------------------------------------
if ( GuiWindowBox ( bounds , title ) ) clicked = 0 ;
int prevTextAlignment = GuiGetStyle ( LABEL , TEXT_ALIGNMENT ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( LABEL , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
2021-07-28 14:15:43 +03:00
GuiLabel ( textBounds , message ) ;
GuiSetStyle ( LABEL , TEXT_ALIGNMENT , prevTextAlignment ) ;
prevTextAlignment = GuiGetStyle ( BUTTON , TEXT_ALIGNMENT ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
2021-07-28 14:15:43 +03:00
2021-09-02 01:39:47 +03:00
for ( int i = 0 ; i < buttonCount ; i + + )
2021-07-28 14:15:43 +03:00
{
if ( GuiButton ( buttonBounds , buttonsText [ i ] ) ) clicked = i + 1 ;
2022-06-06 12:11:39 +03:00
buttonBounds . x + = ( buttonBounds . width + RAYGUI_MESSAGEBOX_BUTTON_PADDING ) ;
2021-07-28 14:15:43 +03:00
}
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , prevTextAlignment ) ;
//--------------------------------------------------------------------
return clicked ;
}
// Text Input Box control, ask for text
2022-06-06 12:11:39 +03:00
int GuiTextInputBox ( Rectangle bounds , const char * title , const char * message , const char * buttons , char * text , int textMaxSize , int * secretViewActive )
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT)
# define RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT 28
# endif
# if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_PADDING)
# define RAYGUI_TEXTINPUTBOX_BUTTON_PADDING 12
# endif
# if !defined(RAYGUI_TEXTINPUTBOX_HEIGHT)
# define RAYGUI_TEXTINPUTBOX_HEIGHT 28
# endif
2021-07-28 14:15:43 +03:00
// Used to enable text edit mode
// WARNING: No more than one GuiTextInputBox() should be open at the same time
static bool textEditMode = false ;
int btnIndex = - 1 ;
2021-09-02 01:39:47 +03:00
int buttonCount = 0 ;
const char * * buttonsText = GuiTextSplit ( buttons , & buttonCount , NULL ) ;
2021-07-28 14:15:43 +03:00
Rectangle buttonBounds = { 0 } ;
2022-06-06 12:11:39 +03:00
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 ;
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
int messageInputHeight = ( int ) bounds . height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - GuiGetStyle ( STATUSBAR , BORDER_WIDTH ) - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - 2 * RAYGUI_TEXTINPUTBOX_BUTTON_PADDING ;
2021-07-28 14:15:43 +03:00
Rectangle textBounds = { 0 } ;
if ( message ! = NULL )
{
Vector2 textSize = MeasureTextEx ( guiFont , message , ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) , 1 ) ;
textBounds . x = bounds . x + bounds . width / 2 - textSize . x / 2 ;
2022-06-06 12:11:39 +03:00
textBounds . y = bounds . y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight / 4 - textSize . y / 2 ;
2021-07-28 14:15:43 +03:00
textBounds . width = textSize . x ;
textBounds . height = textSize . y ;
}
Rectangle textBoxBounds = { 0 } ;
2022-06-06 12:11:39 +03:00
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 ;
2021-07-28 14:15:43 +03:00
else textBoxBounds . y + = ( messageInputHeight / 2 + messageInputHeight / 4 ) ;
2022-06-06 12:11:39 +03:00
textBoxBounds . width = bounds . width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING * 2 ;
textBoxBounds . height = RAYGUI_TEXTINPUTBOX_HEIGHT ;
2021-07-28 14:15:43 +03:00
// Draw control
//--------------------------------------------------------------------
if ( GuiWindowBox ( bounds , title ) ) btnIndex = 0 ;
// Draw message if available
if ( message ! = NULL )
{
int prevTextAlignment = GuiGetStyle ( LABEL , TEXT_ALIGNMENT ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( LABEL , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
2021-07-28 14:15:43 +03:00
GuiLabel ( textBounds , message ) ;
GuiSetStyle ( LABEL , TEXT_ALIGNMENT , prevTextAlignment ) ;
}
2022-06-06 12:11:39 +03:00
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 ;
* secretViewActive = 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 ;
}
2021-07-28 14:15:43 +03:00
int prevBtnTextAlignment = GuiGetStyle ( BUTTON , TEXT_ALIGNMENT ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ;
2021-07-28 14:15:43 +03:00
2021-09-02 01:39:47 +03:00
for ( int i = 0 ; i < buttonCount ; i + + )
2021-07-28 14:15:43 +03:00
{
if ( GuiButton ( buttonBounds , buttonsText [ i ] ) ) btnIndex = i + 1 ;
2022-06-06 12:11:39 +03:00
buttonBounds . x + = ( buttonBounds . width + RAYGUI_MESSAGEBOX_BUTTON_PADDING ) ;
2021-07-28 14:15:43 +03:00
}
GuiSetStyle ( BUTTON , TEXT_ALIGNMENT , prevBtnTextAlignment ) ;
//--------------------------------------------------------------------
return btnIndex ;
}
// 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
2022-06-06 12:11:39 +03:00
Vector2 GuiGrid ( Rectangle bounds , const char * text , float spacing , int subdivs )
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
// Grid lines alpha amount
# if !defined(RAYGUI_GRID_ALPHA)
# define RAYGUI_GRID_ALPHA 0.15f
2021-07-28 14:15:43 +03:00
# endif
2022-06-06 12:11:39 +03:00
GuiState state = guiState ;
2021-07-28 14:15:43 +03:00
Vector2 mousePoint = GetMousePosition ( ) ;
Vector2 currentCell = { - 1 , - 1 } ;
int linesV = ( ( int ) ( bounds . width / spacing ) ) * subdivs + 1 ;
int linesH = ( ( int ) ( bounds . height / spacing ) ) * subdivs + 1 ;
// Update control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
2021-07-28 14:15:43 +03:00
{
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
2022-06-06 12:11:39 +03:00
// NOTE: Cell values must be rounded to int
currentCell . x = ( int ) ( ( mousePoint . x - bounds . x ) / spacing ) ;
currentCell . y = ( int ) ( ( mousePoint . y - bounds . y ) / spacing ) ;
2021-07-28 14:15:43 +03:00
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
// TODO: Draw background panel?
2021-07-28 14:15:43 +03:00
switch ( state )
{
2022-06-06 12:11:39 +03:00
case STATE_NORMAL :
2021-07-28 14:15:43 +03:00
{
if ( subdivs > 0 )
{
// Draw vertical grid lines
for ( int i = 0 ; i < linesV ; i + + )
{
2021-10-27 12:25:24 +03:00
Rectangle lineV = { bounds . x + spacing * i / subdivs , bounds . y , 1 , bounds . height } ;
2022-06-06 12:11:39 +03:00
GuiDrawRectangle ( lineV , 0 , BLANK , ( ( i % subdivs ) = = 0 ) ? Fade ( GetColor ( GuiGetStyle ( DEFAULT , LINE_COLOR ) ) , RAYGUI_GRID_ALPHA * 4 ) : Fade ( GetColor ( GuiGetStyle ( DEFAULT , LINE_COLOR ) ) , RAYGUI_GRID_ALPHA ) ) ;
2021-07-28 14:15:43 +03:00
}
// Draw horizontal grid lines
for ( int i = 0 ; i < linesH ; i + + )
{
2021-10-27 12:25:24 +03:00
Rectangle lineH = { bounds . x , bounds . y + spacing * i / subdivs , bounds . width , 1 } ;
2022-06-06 12:11:39 +03:00
GuiDrawRectangle ( lineH , 0 , BLANK , ( ( i % subdivs ) = = 0 ) ? Fade ( GetColor ( GuiGetStyle ( DEFAULT , LINE_COLOR ) ) , RAYGUI_GRID_ALPHA * 4 ) : Fade ( GetColor ( GuiGetStyle ( DEFAULT , LINE_COLOR ) ) , RAYGUI_GRID_ALPHA ) ) ;
2021-07-28 14:15:43 +03:00
}
}
} break ;
default : break ;
}
return currentCell ;
}
//----------------------------------------------------------------------------------
// Styles loading functions
//----------------------------------------------------------------------------------
// Load raygui style file (.rgs)
2022-06-06 12:11:39 +03:00
// 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)
2021-07-28 14:15:43 +03:00
void GuiLoadStyle ( const char * fileName )
{
2022-06-06 12:11:39 +03:00
# define MAX_LINE_BUFFER_SIZE 256
2021-07-28 14:15:43 +03:00
bool tryBinary = false ;
// Try reading the files as text file first
FILE * rgsFile = fopen ( fileName , " rt " ) ;
if ( rgsFile ! = NULL )
{
2022-06-06 12:11:39 +03:00
char buffer [ MAX_LINE_BUFFER_SIZE ] = { 0 } ;
fgets ( buffer , MAX_LINE_BUFFER_SIZE , rgsFile ) ;
2021-07-28 14:15:43 +03:00
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 } ;
if ( charmapFileName [ 0 ] ! = ' 0 ' )
{
// Load characters from charmap file,
// expected '\n' separated list of integer values
char * charValues = LoadFileText ( charmapFileName ) ;
if ( charValues ! = NULL )
{
2021-09-02 01:39:47 +03:00
int glyphCount = 0 ;
const char * * chars = TextSplit ( charValues , ' \n ' , & glyphCount ) ;
2021-07-28 14:15:43 +03:00
2021-09-02 01:39:47 +03:00
int * values = ( int * ) RAYGUI_MALLOC ( glyphCount * sizeof ( int ) ) ;
for ( int i = 0 ; i < glyphCount ; i + + ) values [ i ] = TextToInteger ( chars [ i ] ) ;
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
if ( font . texture . id ! = GetFontDefault ( ) . texture . id ) UnloadTexture ( font . texture ) ;
2021-09-02 01:39:47 +03:00
font = LoadFontEx ( TextFormat ( " %s/%s " , GetDirectoryPath ( fileName ) , fontFileName ) , fontSize , values , glyphCount ) ;
2022-06-06 12:11:39 +03:00
if ( font . texture . id = = 0 ) font = GetFontDefault ( ) ;
2021-07-28 14:15:43 +03:00
RAYGUI_FREE ( values ) ;
}
}
2022-06-06 12:11:39 +03:00
else
{
if ( font . texture . id ! = GetFontDefault ( ) . texture . id ) UnloadTexture ( font . texture ) ;
font = LoadFontEx ( TextFormat ( " %s/%s " , GetDirectoryPath ( fileName ) , fontFileName ) , fontSize , NULL , 0 ) ;
if ( font . texture . id = = 0 ) font = GetFontDefault ( ) ;
}
2021-07-28 14:15:43 +03:00
2021-09-02 01:39:47 +03:00
if ( ( font . texture . id > 0 ) & & ( font . glyphCount > 0 ) ) GuiSetFont ( font ) ;
2021-07-28 14:15:43 +03:00
} break ;
default : break ;
}
2022-06-06 12:11:39 +03:00
fgets ( buffer , MAX_LINE_BUFFER_SIZE , rgsFile ) ;
2021-07-28 14:15:43 +03:00
}
}
else tryBinary = true ;
fclose ( rgsFile ) ;
}
if ( tryBinary )
{
rgsFile = fopen ( fileName , " rb " ) ;
if ( rgsFile = = NULL ) return ;
2022-06-06 12:11:39 +03:00
char signature [ 5 ] = { 0 } ;
2021-07-28 14:15:43 +03:00
short version = 0 ;
short reserved = 0 ;
2021-09-02 01:39:47 +03:00
int propertyCount = 0 ;
2021-07-28 14:15:43 +03:00
fread ( signature , 1 , 4 , rgsFile ) ;
fread ( & version , 1 , sizeof ( short ) , rgsFile ) ;
fread ( & reserved , 1 , sizeof ( short ) , rgsFile ) ;
2021-09-02 01:39:47 +03:00
fread ( & propertyCount , 1 , sizeof ( int ) , rgsFile ) ;
2021-07-28 14:15:43 +03:00
if ( ( signature [ 0 ] = = ' r ' ) & &
( signature [ 1 ] = = ' G ' ) & &
( signature [ 2 ] = = ' S ' ) & &
( signature [ 3 ] = = ' ' ) )
{
short controlId = 0 ;
short propertyId = 0 ;
2022-06-06 12:11:39 +03:00
unsigned int propertyValue = 0 ;
2021-07-28 14:15:43 +03:00
2021-09-02 01:39:47 +03:00
for ( int i = 0 ; i < propertyCount ; i + + )
2021-07-28 14:15:43 +03:00
{
fread ( & controlId , 1 , sizeof ( short ) , rgsFile ) ;
fread ( & propertyId , 1 , sizeof ( short ) , rgsFile ) ;
2022-06-06 12:11:39 +03:00
fread ( & propertyValue , 1 , sizeof ( unsigned int ) , rgsFile ) ;
2021-07-28 14:15:43 +03:00
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 ) ;
2021-10-27 12:25:24 +03:00
if ( propertyId < RAYGUI_MAX_PROPS_BASE ) for ( int i = 1 ; i < RAYGUI_MAX_CONTROLS ; i + + ) GuiSetStyle ( i , ( int ) propertyId , propertyValue ) ;
2021-07-28 14:15:43 +03:00
}
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 ;
fread ( & fontDataSize , 1 , sizeof ( int ) , rgsFile ) ;
if ( fontDataSize > 0 )
{
Font font = { 0 } ;
int fontType = 0 ; // 0-Normal, 1-SDF
Rectangle whiteRec = { 0 } ;
fread ( & font . baseSize , 1 , sizeof ( int ) , rgsFile ) ;
2021-09-02 01:39:47 +03:00
fread ( & font . glyphCount , 1 , sizeof ( int ) , rgsFile ) ;
2021-07-28 14:15:43 +03:00
fread ( & fontType , 1 , sizeof ( int ) , rgsFile ) ;
// Load font white rectangle
fread ( & whiteRec , 1 , sizeof ( Rectangle ) , rgsFile ) ;
// Load font image parameters
2022-06-06 12:11:39 +03:00
int fontImageUncompSize = 0 ;
int fontImageCompSize = 0 ;
fread ( & fontImageUncompSize , 1 , sizeof ( int ) , rgsFile ) ;
fread ( & fontImageCompSize , 1 , sizeof ( int ) , rgsFile ) ;
Image imFont = { 0 } ;
imFont . mipmaps = 1 ;
fread ( & imFont . width , 1 , sizeof ( int ) , rgsFile ) ;
fread ( & imFont . height , 1 , sizeof ( int ) , rgsFile ) ;
fread ( & imFont . format , 1 , sizeof ( int ) , rgsFile ) ;
if ( fontImageCompSize < fontImageUncompSize )
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
// Compressed font atlas image data (DEFLATE), it requires DecompressData()
int dataUncompSize = 0 ;
unsigned char * compData = ( unsigned char * ) RAYGUI_MALLOC ( fontImageCompSize ) ;
fread ( compData , 1 , fontImageCompSize , rgsFile ) ;
imFont . data = DecompressData ( compData , fontImageCompSize , & dataUncompSize ) ;
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
// Security check, dataUncompSize must match the provided fontImageUncompSize
if ( dataUncompSize ! = fontImageUncompSize ) RAYGUI_LOG ( " WARNING: Uncompressed font atlas image data could be corrupted " ) ;
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
RAYGUI_FREE ( compData ) ;
}
else
{
// Font atlas image data is not compressed
imFont . data = ( unsigned char * ) RAYGUI_MALLOC ( fontImageUncompSize ) ;
fread ( imFont . data , 1 , fontImageUncompSize , rgsFile ) ;
2021-07-28 14:15:43 +03:00
}
2022-06-06 12:11:39 +03:00
if ( font . texture . id ! = GetFontDefault ( ) . texture . id ) UnloadTexture ( font . texture ) ;
font . texture = LoadTextureFromImage ( imFont ) ;
if ( font . texture . id = = 0 ) font = GetFontDefault ( ) ;
RAYGUI_FREE ( imFont . data ) ;
2021-07-28 14:15:43 +03:00
// Load font recs data
2021-09-02 01:39:47 +03:00
font . recs = ( Rectangle * ) RAYGUI_CALLOC ( font . glyphCount , sizeof ( Rectangle ) ) ;
for ( int i = 0 ; i < font . glyphCount ; i + + ) fread ( & font . recs [ i ] , 1 , sizeof ( Rectangle ) , rgsFile ) ;
2021-07-28 14:15:43 +03:00
// Load font chars info data
2021-09-02 01:39:47 +03:00
font . glyphs = ( GlyphInfo * ) RAYGUI_CALLOC ( font . glyphCount , sizeof ( GlyphInfo ) ) ;
for ( int i = 0 ; i < font . glyphCount ; i + + )
2021-07-28 14:15:43 +03:00
{
2021-09-02 01:39:47 +03:00
fread ( & font . glyphs [ i ] . value , 1 , sizeof ( int ) , rgsFile ) ;
fread ( & font . glyphs [ i ] . offsetX , 1 , sizeof ( int ) , rgsFile ) ;
fread ( & font . glyphs [ i ] . offsetY , 1 , sizeof ( int ) , rgsFile ) ;
fread ( & font . glyphs [ i ] . advanceX , 1 , sizeof ( int ) , rgsFile ) ;
2021-07-28 14:15:43 +03:00
}
GuiSetFont ( font ) ;
// Set font texture source rectangle to be used as white texture to draw shapes
// NOTE: This way, all gui can be draw using a single draw call
if ( ( whiteRec . width ! = 0 ) & & ( whiteRec . height ! = 0 ) ) SetShapesTexture ( font . texture , whiteRec ) ;
}
# endif
}
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
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 ) ; // WARNING: Some controls use other values
GuiSetStyle ( DEFAULT , TEXT_PADDING , 0 ) ; // WARNING: Some controls use other values
2022-06-06 12:11:39 +03:00
GuiSetStyle ( DEFAULT , TEXT_ALIGNMENT , TEXT_ALIGN_CENTER ) ; // WARNING: Some controls use other values
2021-07-28 14:15:43 +03:00
// Initialize control-specific property values
// NOTE: Those properties are in default list but require specific values by control type
2022-06-06 12:11:39 +03:00
GuiSetStyle ( LABEL , TEXT_ALIGNMENT , TEXT_ALIGN_LEFT ) ;
2021-07-28 14:15:43 +03:00
GuiSetStyle ( BUTTON , BORDER_WIDTH , 2 ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( SLIDER , TEXT_PADDING , 4 ) ;
GuiSetStyle ( CHECKBOX , TEXT_PADDING , 4 ) ;
GuiSetStyle ( CHECKBOX , TEXT_ALIGNMENT , TEXT_ALIGN_RIGHT ) ;
GuiSetStyle ( TEXTBOX , TEXT_PADDING , 4 ) ;
GuiSetStyle ( TEXTBOX , TEXT_ALIGNMENT , TEXT_ALIGN_LEFT ) ;
2021-07-28 14:15:43 +03:00
GuiSetStyle ( VALUEBOX , TEXT_PADDING , 4 ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( VALUEBOX , TEXT_ALIGNMENT , TEXT_ALIGN_LEFT ) ;
2021-07-28 14:15:43 +03:00
GuiSetStyle ( SPINNER , TEXT_PADDING , 4 ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( SPINNER , TEXT_ALIGNMENT , TEXT_ALIGN_LEFT ) ;
GuiSetStyle ( STATUSBAR , TEXT_PADDING , 8 ) ;
GuiSetStyle ( STATUSBAR , TEXT_ALIGNMENT , TEXT_ALIGN_LEFT ) ;
2021-07-28 14:15:43 +03:00
// Initialize extended property values
// NOTE: By default, extended property values are initialized to 0
GuiSetStyle ( DEFAULT , TEXT_SIZE , 10 ) ; // DEFAULT, shared by all controls
GuiSetStyle ( DEFAULT , TEXT_SPACING , 1 ) ; // DEFAULT, shared by all controls
GuiSetStyle ( DEFAULT , LINE_COLOR , 0x90abb5ff ) ; // DEFAULT specific property
GuiSetStyle ( DEFAULT , BACKGROUND_COLOR , 0xf5f5f5ff ) ; // DEFAULT specific property
GuiSetStyle ( TOGGLE , GROUP_PADDING , 2 ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( SLIDER , SLIDER_WIDTH , 16 ) ;
2021-07-28 14:15:43 +03:00
GuiSetStyle ( SLIDER , SLIDER_PADDING , 1 ) ;
GuiSetStyle ( PROGRESSBAR , PROGRESS_PADDING , 1 ) ;
GuiSetStyle ( CHECKBOX , CHECK_PADDING , 1 ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( COMBOBOX , COMBO_BUTTON_WIDTH , 32 ) ;
GuiSetStyle ( COMBOBOX , COMBO_BUTTON_SPACING , 2 ) ;
2021-07-28 14:15:43 +03:00
GuiSetStyle ( DROPDOWNBOX , ARROW_PADDING , 16 ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( DROPDOWNBOX , DROPDOWN_ITEMS_SPACING , 2 ) ;
GuiSetStyle ( TEXTBOX , TEXT_LINES_SPACING , 4 ) ;
2021-07-28 14:15:43 +03:00
GuiSetStyle ( TEXTBOX , TEXT_INNER_PADDING , 4 ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( SPINNER , SPIN_BUTTON_WIDTH , 24 ) ;
GuiSetStyle ( SPINNER , SPIN_BUTTON_SPACING , 2 ) ;
2021-07-28 14:15:43 +03:00
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 ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( SCROLLBAR , SCROLL_SPEED , 12 ) ;
GuiSetStyle ( LISTVIEW , LIST_ITEMS_HEIGHT , 24 ) ;
GuiSetStyle ( LISTVIEW , LIST_ITEMS_SPACING , 2 ) ;
GuiSetStyle ( LISTVIEW , SCROLLBAR_WIDTH , 12 ) ;
2021-07-28 14:15:43 +03:00
GuiSetStyle ( LISTVIEW , SCROLLBAR_SIDE , SCROLLBAR_RIGHT_SIDE ) ;
2022-06-06 12:11:39 +03:00
GuiSetStyle ( COLORPICKER , COLOR_SELECTOR_SIZE , 8 ) ;
GuiSetStyle ( COLORPICKER , HUEBAR_WIDTH , 16 ) ;
GuiSetStyle ( COLORPICKER , HUEBAR_PADDING , 8 ) ;
GuiSetStyle ( COLORPICKER , HUEBAR_SELECTOR_HEIGHT , 8 ) ;
2021-07-28 14:15:43 +03:00
GuiSetStyle ( COLORPICKER , HUEBAR_SELECTOR_OVERFLOW , 2 ) ;
guiFont = GetFontDefault ( ) ; // Initialize default font
}
// 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 )
{
2022-06-06 12:11:39 +03:00
# if defined(RAYGUI_NO_ICONS)
2021-10-27 12:25:24 +03:00
return NULL ;
# else
2021-07-28 14:15:43 +03:00
static char buffer [ 1024 ] = { 0 } ;
2022-06-06 12:11:39 +03:00
static char iconBuffer [ 6 ] = { 0 } ;
2021-07-28 14:15:43 +03:00
if ( text ! = NULL )
{
2022-06-06 12:11:39 +03:00
memset ( buffer , 0 , 1024 ) ;
sprintf ( buffer , " #%03i# " , iconId ) ;
2021-07-28 14:15:43 +03:00
for ( int i = 5 ; i < 1024 ; i + + )
{
buffer [ i ] = text [ i - 5 ] ;
if ( text [ i - 5 ] = = ' \0 ' ) break ;
}
2022-06-06 12:11:39 +03:00
return buffer ;
}
else
{
sprintf ( iconBuffer , " #%03i# " , iconId & 0x1ff ) ;
return iconBuffer ;
2021-07-28 14:15:43 +03:00
}
# endif
}
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_NO_ICONS)
2021-07-28 14:15:43 +03:00
// Get full icons data pointer
unsigned int * GuiGetIcons ( void ) { return guiIcons ; }
// Load raygui icons file (.rgi)
// NOTE: In case nameIds are required, they can be requested with loadIconsName,
2022-06-06 12:11:39 +03:00
// they are returned as a guiIconsName[iconCount][RAYGUI_ICON_MAX_NAME_LENGTH],
2021-10-27 12:25:24 +03:00
// WARNING: guiIconsName[]][] memory should be manually freed!
2021-07-28 14:15:43 +03:00
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 )
{
2022-06-06 12:11:39 +03:00
char signature [ 5 ] = { 0 } ;
2021-07-28 14:15:43 +03:00
short version = 0 ;
short reserved = 0 ;
2021-09-02 01:39:47 +03:00
short iconCount = 0 ;
short iconSize = 0 ;
2021-07-28 14:15:43 +03:00
fread ( signature , 1 , 4 , rgiFile ) ;
fread ( & version , 1 , sizeof ( short ) , rgiFile ) ;
fread ( & reserved , 1 , sizeof ( short ) , rgiFile ) ;
2021-09-02 01:39:47 +03:00
fread ( & iconCount , 1 , sizeof ( short ) , rgiFile ) ;
fread ( & iconSize , 1 , sizeof ( short ) , rgiFile ) ;
2021-07-28 14:15:43 +03:00
if ( ( signature [ 0 ] = = ' r ' ) & &
( signature [ 1 ] = = ' G ' ) & &
( signature [ 2 ] = = ' I ' ) & &
( signature [ 3 ] = = ' ' ) )
{
if ( loadIconsName )
{
2021-09-02 01:39:47 +03:00
guiIconsName = ( char * * ) RAYGUI_MALLOC ( iconCount * sizeof ( char * * ) ) ;
for ( int i = 0 ; i < iconCount ; i + + )
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
guiIconsName [ i ] = ( char * ) RAYGUI_MALLOC ( RAYGUI_ICON_MAX_NAME_LENGTH ) ;
fread ( guiIconsName [ i ] , RAYGUI_ICON_MAX_NAME_LENGTH , 1 , rgiFile ) ;
2021-07-28 14:15:43 +03:00
}
}
2022-06-06 12:11:39 +03:00
else fseek ( rgiFile , iconCount * RAYGUI_ICON_MAX_NAME_LENGTH , SEEK_CUR ) ;
2021-07-28 14:15:43 +03:00
// Read icons data directly over guiIcons data array
2021-09-02 01:39:47 +03:00
fread ( guiIcons , iconCount * ( iconSize * iconSize / 32 ) , sizeof ( unsigned int ) , rgiFile ) ;
2021-07-28 14:15:43 +03:00
}
fclose ( rgiFile ) ;
}
return guiIconsName ;
}
// Draw selected icon using rectangles pixel-by-pixel
2021-10-27 12:25:24 +03:00
void GuiDrawIcon ( int iconId , int posX , int posY , int pixelSize , Color color )
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
# define BIT_CHECK(a,b) ((a) & (1u<<(b)))
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
for ( int i = 0 , y = 0 ; i < RAYGUI_ICON_SIZE * RAYGUI_ICON_SIZE / 32 ; i + + )
2021-07-28 14:15:43 +03:00
{
for ( int k = 0 ; k < 32 ; k + + )
{
2022-06-06 12:11:39 +03:00
if ( BIT_CHECK ( guiIcons [ iconId * RAYGUI_ICON_DATA_ELEMENTS + i ] , k ) )
2021-07-28 14:15:43 +03:00
{
# if !defined(RAYGUI_STANDALONE)
2022-06-06 12:11:39 +03:00
DrawRectangle ( posX + ( k % RAYGUI_ICON_SIZE ) * pixelSize , posY + y * pixelSize , pixelSize , pixelSize , color ) ;
2021-07-28 14:15:43 +03:00
# endif
}
if ( ( k = = 15 ) | | ( k = = 31 ) ) y + + ;
}
}
}
// Get icon bit data
2022-06-06 12:11:39 +03:00
// NOTE: Bit data array grouped as unsigned int (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32 elements)
2021-07-28 14:15:43 +03:00
unsigned int * GuiGetIconData ( int iconId )
{
2022-06-06 12:11:39 +03:00
static unsigned int iconData [ RAYGUI_ICON_DATA_ELEMENTS ] = { 0 } ;
memset ( iconData , 0 , RAYGUI_ICON_DATA_ELEMENTS * sizeof ( unsigned int ) ) ;
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
if ( iconId < RAYGUI_ICON_MAX_ICONS ) memcpy ( iconData , & guiIcons [ iconId * RAYGUI_ICON_DATA_ELEMENTS ] , RAYGUI_ICON_DATA_ELEMENTS * sizeof ( unsigned int ) ) ;
2021-07-28 14:15:43 +03:00
return iconData ;
}
// Set icon bit data
2022-06-06 12:11:39 +03:00
// NOTE: Data must be provided as unsigned int array (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32 elements)
2021-07-28 14:15:43 +03:00
void GuiSetIconData ( int iconId , unsigned int * data )
{
2022-06-06 12:11:39 +03:00
if ( iconId < RAYGUI_ICON_MAX_ICONS ) memcpy ( & guiIcons [ iconId * RAYGUI_ICON_DATA_ELEMENTS ] , data , RAYGUI_ICON_DATA_ELEMENTS * sizeof ( unsigned int ) ) ;
}
// Set icon scale (1 by default)
void GuiSetIconScale ( unsigned int scale )
{
guiIconScale = ( scale < 1 ) ? 1 : scale ;
2021-07-28 14:15:43 +03:00
}
// Set icon pixel value
void GuiSetIconPixel ( int iconId , int x , int y )
{
2022-06-06 12:11:39 +03:00
# define BIT_SET(a,b) ((a) |= (1u<<(b)))
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
// This logic works for any RAYGUI_ICON_SIZE pixels icons,
2021-07-28 14:15:43 +03:00
// For example, in case of 16x16 pixels, every 2 lines fit in one unsigned int data element
2022-06-06 12:11:39 +03:00
BIT_SET ( guiIcons [ iconId * RAYGUI_ICON_DATA_ELEMENTS + y / ( sizeof ( unsigned int ) * 8 / RAYGUI_ICON_SIZE ) ] , x + ( y % ( sizeof ( unsigned int ) * 8 / RAYGUI_ICON_SIZE ) * RAYGUI_ICON_SIZE ) ) ;
2021-07-28 14:15:43 +03:00
}
// Clear icon pixel value
void GuiClearIconPixel ( int iconId , int x , int y )
{
2022-06-06 12:11:39 +03:00
# define BIT_CLEAR(a,b) ((a) &= ~((1u)<<(b)))
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
// This logic works for any RAYGUI_ICON_SIZE pixels icons,
2021-07-28 14:15:43 +03:00
// For example, in case of 16x16 pixels, every 2 lines fit in one unsigned int data element
2022-06-06 12:11:39 +03:00
BIT_CLEAR ( guiIcons [ iconId * RAYGUI_ICON_DATA_ELEMENTS + y / ( sizeof ( unsigned int ) * 8 / RAYGUI_ICON_SIZE ) ] , x + ( y % ( sizeof ( unsigned int ) * 8 / RAYGUI_ICON_SIZE ) * RAYGUI_ICON_SIZE ) ) ;
2021-07-28 14:15:43 +03:00
}
// Check icon pixel value
bool GuiCheckIconPixel ( int iconId , int x , int y )
{
2022-06-06 12:11:39 +03:00
# define BIT_CHECK(a,b) ((a) & (1u<<(b)))
2021-07-28 14:15:43 +03:00
return ( BIT_CHECK ( guiIcons [ iconId * 8 + y / 2 ] , x + ( y % 2 * 16 ) ) ) ;
}
2022-06-06 12:11:39 +03:00
# endif // !RAYGUI_NO_ICONS
2021-07-28 14:15:43 +03:00
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
// Gui get text width considering icon
2021-07-28 14:15:43 +03:00
static int GetTextWidth ( const char * text )
{
2022-06-06 12:11:39 +03:00
# if !defined(ICON_TEXT_PADDING)
# define ICON_TEXT_PADDING 4
# endif
2021-07-28 14:15:43 +03:00
Vector2 size = { 0 } ;
2022-06-06 12:11:39 +03:00
int textIconOffset = 0 ;
2021-07-28 14:15:43 +03:00
2021-10-27 12:25:24 +03:00
if ( ( text ! = NULL ) & & ( text [ 0 ] ! = ' \0 ' ) )
{
2022-06-06 12:11:39 +03:00
if ( text [ 0 ] = = ' # ' )
{
for ( int i = 1 ; ( text [ i ] ! = ' \0 ' ) & & ( i < 5 ) ; i + + )
{
if ( text [ i ] = = ' # ' )
{
textIconOffset = i ;
break ;
}
}
}
// Make sure guiFont is set, GuiGetStyle() initializes it lazynessly
float fontSize = ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) ;
size = MeasureTextEx ( guiFont , text + textIconOffset , fontSize , ( float ) GuiGetStyle ( DEFAULT , TEXT_SPACING ) ) ;
if ( textIconOffset > 0 ) size . x + = ( RAYGUI_ICON_SIZE - ICON_TEXT_PADDING ) ;
2021-10-27 12:25:24 +03:00
}
2021-07-28 14:15:43 +03:00
return ( int ) size . 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 ) ;
textBounds . width = bounds . width - 2 * GuiGetStyle ( control , BORDER_WIDTH ) ;
textBounds . height = bounds . height - 2 * GuiGetStyle ( control , BORDER_WIDTH ) ;
// Consider TEXT_PADDING properly, depends on control type and TEXT_ALIGNMENT
switch ( control )
{
2022-06-06 12:11:39 +03:00
case COMBOBOX : bounds . width - = ( GuiGetStyle ( control , COMBO_BUTTON_WIDTH ) + GuiGetStyle ( control , COMBO_BUTTON_SPACING ) ) ; break ;
2021-07-28 14:15:43 +03:00
case VALUEBOX : break ; // NOTE: ValueBox text value always centered, text padding applies to label
default :
{
2022-06-06 12:11:39 +03:00
if ( GuiGetStyle ( control , TEXT_ALIGNMENT ) = = TEXT_ALIGN_RIGHT ) textBounds . x - = GuiGetStyle ( control , TEXT_PADDING ) ;
2021-07-28 14:15:43 +03:00
else textBounds . x + = GuiGetStyle ( control , TEXT_PADDING ) ;
} break ;
}
// TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW (scrollbar?)
2021-10-27 12:25:24 +03:00
// More special cases (label on side): CHECKBOX, SLIDER, VALUEBOX, SPINNER
2021-07-28 14:15:43 +03:00
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 )
{
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_NO_ICONS)
2021-07-28 14:15:43 +03:00
* 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
2021-10-27 12:25:24 +03:00
// WARNING: If only icon provided, it could point to EOL character: '\0'
2021-07-28 14:15:43 +03:00
if ( * iconId > = 0 ) text + = ( pos + 1 ) ;
}
}
# endif
return text ;
}
// Gui draw text using default font
static void GuiDrawText ( const char * text , Rectangle bounds , int alignment , Color tint )
{
# define TEXT_VALIGN_PIXEL_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect
2022-06-06 12:11:39 +03:00
# if !defined(ICON_TEXT_PADDING)
# define ICON_TEXT_PADDING 4
# endif
2021-07-28 14:15:43 +03:00
if ( ( text ! = NULL ) & & ( text [ 0 ] ! = ' \0 ' ) )
{
int iconId = 0 ;
2021-10-27 12:25:24 +03:00
text = GetTextIcon ( text , & iconId ) ; // Check text for icon and move cursor
2021-07-28 14:15:43 +03:00
// Get text position depending on alignment and iconId
//---------------------------------------------------------------------------------
Vector2 position = { bounds . x , bounds . y } ;
2021-10-27 12:25:24 +03:00
// NOTE: We get text size after icon has been processed
2022-06-06 12:11:39 +03:00
// TODO: REVIEW: We consider text size in case of line breaks! -> MeasureTextEx() depends on raylib!
Vector2 textSize = MeasureTextEx ( GuiGetFont ( ) , text , GuiGetStyle ( DEFAULT , TEXT_SIZE ) , GuiGetStyle ( DEFAULT , TEXT_SPACING ) ) ;
//int textWidth = GetTextWidth(text);
//int textHeight = GuiGetStyle(DEFAULT, TEXT_SIZE);
2021-07-28 14:15:43 +03:00
2021-08-25 01:51:37 +03:00
// If text requires an icon, add size to measure
2021-07-28 14:15:43 +03:00
if ( iconId > = 0 )
{
2022-06-06 12:11:39 +03:00
textSize . x + = RAYGUI_ICON_SIZE * guiIconScale ;
2021-07-28 14:15:43 +03:00
2021-10-27 12:25:24 +03:00
// WARNING: If only icon provided, text could be pointing to EOF character: '\0'
2022-06-06 12:11:39 +03:00
if ( ( text ! = NULL ) & & ( text [ 0 ] ! = ' \0 ' ) ) textSize . x + = ICON_TEXT_PADDING ;
2021-07-28 14:15:43 +03:00
}
2021-10-27 12:25:24 +03:00
2021-07-28 14:15:43 +03:00
// Check guiTextAlign global variables
switch ( alignment )
{
2022-06-06 12:11:39 +03:00
case TEXT_ALIGN_LEFT :
2021-07-28 14:15:43 +03:00
{
position . x = bounds . x ;
2022-06-06 12:11:39 +03:00
position . y = bounds . y + bounds . height / 2 - textSize . y / 2 + TEXT_VALIGN_PIXEL_OFFSET ( bounds . height ) ;
2021-07-28 14:15:43 +03:00
} break ;
2022-06-06 12:11:39 +03:00
case TEXT_ALIGN_CENTER :
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
position . x = bounds . x + bounds . width / 2 - textSize . x / 2 ;
position . y = bounds . y + bounds . height / 2 - textSize . y / 2 + TEXT_VALIGN_PIXEL_OFFSET ( bounds . height ) ;
2021-07-28 14:15:43 +03:00
} break ;
2022-06-06 12:11:39 +03:00
case TEXT_ALIGN_RIGHT :
2021-07-28 14:15:43 +03:00
{
2022-06-06 12:11:39 +03:00
position . x = bounds . x + bounds . width - textSize . x ;
position . y = bounds . y + bounds . height / 2 - textSize . y / 2 + TEXT_VALIGN_PIXEL_OFFSET ( bounds . height ) ;
2021-07-28 14:15:43 +03:00
} break ;
default : break ;
}
// NOTE: Make sure we get pixel-perfect coordinates,
// In case of decimals we got weird text positioning
position . x = ( float ) ( ( int ) position . x ) ;
position . y = ( float ) ( ( int ) position . y ) ;
//---------------------------------------------------------------------------------
// Draw text (with icon if available)
//---------------------------------------------------------------------------------
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_NO_ICONS)
2021-07-28 14:15:43 +03:00
if ( iconId > = 0 )
{
// NOTE: We consider icon height, probably different than text size
2022-06-06 12:11:39 +03:00
GuiDrawIcon ( iconId , ( int ) position . x , ( int ) ( bounds . y + bounds . height / 2 - RAYGUI_ICON_SIZE * guiIconScale / 2 + TEXT_VALIGN_PIXEL_OFFSET ( bounds . height ) ) , guiIconScale , tint ) ;
position . x + = ( RAYGUI_ICON_SIZE * guiIconScale + ICON_TEXT_PADDING ) ;
2021-07-28 14:15:43 +03:00
}
# endif
DrawTextEx ( guiFont , text , position , ( float ) GuiGetStyle ( DEFAULT , TEXT_SIZE ) , ( float ) GuiGetStyle ( DEFAULT , TEXT_SPACING ) , tint ) ;
//---------------------------------------------------------------------------------
}
}
// 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 , color ) ;
}
if ( borderWidth > 0 )
{
// Draw rectangle border lines with color
DrawRectangle ( ( int ) rec . x , ( int ) rec . y , ( int ) rec . width , borderWidth , borderColor ) ;
DrawRectangle ( ( int ) rec . x , ( int ) rec . y + borderWidth , borderWidth , ( int ) rec . height - 2 * borderWidth , borderColor ) ;
DrawRectangle ( ( int ) rec . x + ( int ) rec . width - borderWidth , ( int ) rec . y + borderWidth , borderWidth , ( int ) rec . height - 2 * borderWidth , borderColor ) ;
DrawRectangle ( ( int ) rec . x , ( int ) rec . y + ( int ) rec . height - borderWidth , ( int ) rec . width , borderWidth , borderColor ) ;
}
}
// Split controls text into multiple strings
// Also check for multiple columns (required by GuiToggleGroup())
static const char * * GuiTextSplit ( const char * text , 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:
2022-06-06 12:11:39 +03:00
// 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
2021-07-28 14:15:43 +03:00
// NOTE: Those definitions could be externally provided if required
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS)
# define RAYGUI_TEXTSPLIT_MAX_ITEMS 128
2021-07-28 14:15:43 +03:00
# endif
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE)
# define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024
2021-07-28 14:15:43 +03:00
# endif
2022-06-06 12:11:39 +03:00
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 ) ;
2021-07-28 14:15:43 +03:00
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
2022-06-06 12:11:39 +03:00
for ( int i = 0 ; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE ; i + + )
2021-07-28 14:15:43 +03:00
{
buffer [ i ] = text [ i ] ;
if ( buffer [ i ] = = ' \0 ' ) break ;
else if ( ( buffer [ i ] = = ' ; ' ) | | ( 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 + + ;
2022-06-06 12:11:39 +03:00
if ( counter = = RAYGUI_TEXTSPLIT_MAX_ITEMS ) break ;
2021-07-28 14:15:43 +03:00
}
}
* 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 ;
2021-10-27 12:25:24 +03:00
hsv . x = 0.0f ; // Undefined, maybe NAN?
2021-07-28 14:15:43 +03:00
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 ;
2021-10-27 12:25:24 +03:00
hsv . x = 0.0f ; // Undefined, maybe NAN?
2021-07-28 14:15:43 +03:00
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 ;
}
2022-06-06 12:11:39 +03:00
// 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 range = 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 ) } ;
sliderSize = ( sliderSize > = scrollbar . height ) ? ( ( int ) scrollbar . height - 2 ) : sliderSize ; // Make sure the slider won't get outside of the scrollbar
slider = RAYGUI_CLITERAL ( Rectangle ) { ( float ) bounds . x + GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_SLIDER_PADDING ) , ( float ) scrollbar . y + ( int ) ( ( ( float ) ( value - minValue ) / range ) * ( scrollbar . height - sliderSize ) ) , ( float ) bounds . width - 2 * ( GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_SLIDER_PADDING ) ) , ( float ) sliderSize } ;
}
else
{
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 ) ) } ;
sliderSize = ( sliderSize > = scrollbar . width ) ? ( ( int ) scrollbar . width - 2 ) : sliderSize ; // Make sure the slider won't get outside of the scrollbar
slider = RAYGUI_CLITERAL ( Rectangle ) { ( float ) scrollbar . x + ( int ) ( ( ( float ) ( value - minValue ) / range ) * ( scrollbar . width - sliderSize ) ) , ( float ) bounds . y + GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_SLIDER_PADDING ) , ( float ) sliderSize , ( float ) bounds . height - 2 * ( GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) + GuiGetStyle ( SCROLLBAR , SCROLL_SLIDER_PADDING ) ) } ;
}
// Update control
//--------------------------------------------------------------------
if ( ( state ! = STATE_DISABLED ) & & ! guiLocked )
{
Vector2 mousePoint = GetMousePosition ( ) ;
if ( CheckCollisionPointRec ( mousePoint , bounds ) )
{
state = STATE_FOCUSED ;
// Handle mouse wheel
int wheel = ( int ) GetMouseWheelMove ( ) ;
if ( wheel ! = 0 ) value + = wheel ;
if ( IsMouseButtonPressed ( MOUSE_LEFT_BUTTON ) )
{
if ( CheckCollisionPointRec ( mousePoint , arrowUpLeft ) ) value - = range / GuiGetStyle ( SCROLLBAR , SCROLL_SPEED ) ;
else if ( CheckCollisionPointRec ( mousePoint , arrowDownRight ) ) value + = range / GuiGetStyle ( SCROLLBAR , SCROLL_SPEED ) ;
state = STATE_PRESSED ;
}
else if ( IsMouseButtonDown ( MOUSE_LEFT_BUTTON ) )
{
if ( ! isVertical )
{
Rectangle scrollArea = { arrowUpLeft . x + arrowUpLeft . width , arrowUpLeft . y , scrollbar . width , bounds . height - 2 * GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) } ;
if ( CheckCollisionPointRec ( mousePoint , scrollArea ) ) value = ( int ) ( ( ( float ) ( mousePoint . x - scrollArea . x - slider . width / 2 ) * range ) / ( scrollArea . width - slider . width ) + minValue ) ;
}
else
{
Rectangle scrollArea = { arrowUpLeft . x , arrowUpLeft . y + arrowUpLeft . height , bounds . width - 2 * GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) , scrollbar . height } ;
if ( CheckCollisionPointRec ( mousePoint , scrollArea ) ) value = ( int ) ( ( ( float ) ( mousePoint . y - scrollArea . y - slider . height / 2 ) * range ) / ( scrollArea . height - slider . height ) + minValue ) ;
}
}
}
// Normalize value
if ( value > maxValue ) value = maxValue ;
if ( value < minValue ) value = minValue ;
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
GuiDrawRectangle ( bounds , GuiGetStyle ( SCROLLBAR , BORDER_WIDTH ) , Fade ( GetColor ( GuiGetStyle ( LISTVIEW , BORDER + state * 3 ) ) , guiAlpha ) , Fade ( GetColor ( GuiGetStyle ( DEFAULT , BORDER_COLOR_DISABLED ) ) , guiAlpha ) ) ; // Draw the background
GuiDrawRectangle ( scrollbar , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( BUTTON , BASE_COLOR_NORMAL ) ) , guiAlpha ) ) ; // Draw the scrollbar active area background
GuiDrawRectangle ( slider , 0 , BLANK , Fade ( GetColor ( GuiGetStyle ( SLIDER , BORDER + state * 3 ) ) , guiAlpha ) ) ; // Draw the slider bar
// 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 , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
GuiDrawText ( isVertical ? " v " : " > " , RAYGUI_CLITERAL ( Rectangle ) { arrowDownRight . x , arrowDownRight . y , isVertical ? bounds . width : bounds . height , isVertical ? bounds . width : bounds . height } ,
TEXT_ALIGN_CENTER , Fade ( GetColor ( GuiGetStyle ( DROPDOWNBOX , TEXT + ( state * 3 ) ) ) , guiAlpha ) ) ;
# else
GuiDrawText ( isVertical ? " #121# " : " #118# " , RAYGUI_CLITERAL ( Rectangle ) { arrowUpLeft . x , arrowUpLeft . y , isVertical ? bounds . width : bounds . height , isVertical ? bounds . width : bounds . height } ,
TEXT_ALIGN_CENTER , Fade ( GetColor ( GuiGetStyle ( SCROLLBAR , TEXT + state * 3 ) ) , guiAlpha ) ) ; // ICON_ARROW_UP_FILL / ICON_ARROW_LEFT_FILL
GuiDrawText ( isVertical ? " #120# " : " #119# " , RAYGUI_CLITERAL ( Rectangle ) { arrowDownRight . x , arrowDownRight . y , isVertical ? bounds . width : bounds . height , isVertical ? bounds . width : bounds . height } ,
TEXT_ALIGN_CENTER , Fade ( GetColor ( GuiGetStyle ( SCROLLBAR , TEXT + state * 3 ) ) , guiAlpha ) ) ; // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL
# endif
}
//--------------------------------------------------------------------
return value ;
}
2021-07-28 14:15:43 +03:00
# if defined(RAYGUI_STANDALONE)
// Returns a Color struct from hexadecimal value
2021-09-02 01:39:47 +03:00
static Color GetColor ( int hexValue )
2021-07-28 14:15:43 +03:00
{
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 ;
}
// Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
static Color Fade ( Color color , float alpha )
{
if ( alpha < 0.0f ) alpha = 0.0f ;
else if ( alpha > 1.0f ) alpha = 1.0f ;
Color result = { color . r , color . g , color . b , ( unsigned char ) ( 255.0f * alpha ) } ;
return result ;
}
// Formatting of text with variables to 'embed'
static const char * TextFormat ( const char * text , . . . )
{
2022-06-06 12:11:39 +03:00
# if !defined(RAYGUI_TEXTFORMAT_MAX_SIZE)
# define RAYGUI_TEXTFORMAT_MAX_SIZE 256
# endif
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
static char buffer [ RAYGUI_TEXTFORMAT_MAX_SIZE ] ;
2021-07-28 14:15:43 +03:00
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:
2022-06-06 12:11:39 +03:00
// 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
2021-07-28 14:15:43 +03:00
2022-06-06 12:11:39 +03:00
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 ) ;
2021-07-28 14:15:43 +03:00
result [ 0 ] = buffer ;
int counter = 0 ;
if ( text ! = NULL )
{
counter = 1 ;
// Count how many substrings we have on text and point to every one
2022-06-06 12:11:39 +03:00
for ( int i = 0 ; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE ; i + + )
2021-07-28 14:15:43 +03:00
{
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 + + ;
2022-06-06 12:11:39 +03:00
if ( counter = = RAYGUI_TEXTSPLIT_MAX_ITEMS ) break ;
2021-07-28 14:15:43 +03:00
}
}
}
* 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 ;
}
2021-09-02 01:39:47 +03:00
// Encode codepoint into UTF-8 text (char array size returned as parameter)
static const char * CodepointToUTF8 ( int codepoint , int * byteSize )
2021-07-28 14:15:43 +03:00
{
static char utf8 [ 6 ] = { 0 } ;
2021-09-02 01:39:47 +03:00
int size = 0 ;
2021-07-28 14:15:43 +03:00
if ( codepoint < = 0x7f )
{
utf8 [ 0 ] = ( char ) codepoint ;
2021-09-02 01:39:47 +03:00
size = 1 ;
2021-07-28 14:15:43 +03:00
}
else if ( codepoint < = 0x7ff )
{
utf8 [ 0 ] = ( char ) ( ( ( codepoint > > 6 ) & 0x1f ) | 0xc0 ) ;
utf8 [ 1 ] = ( char ) ( ( codepoint & 0x3f ) | 0x80 ) ;
2021-09-02 01:39:47 +03:00
size = 2 ;
2021-07-28 14:15:43 +03:00
}
else if ( codepoint < = 0xffff )
{
utf8 [ 0 ] = ( char ) ( ( ( codepoint > > 12 ) & 0x0f ) | 0xe0 ) ;
utf8 [ 1 ] = ( char ) ( ( ( codepoint > > 6 ) & 0x3f ) | 0x80 ) ;
utf8 [ 2 ] = ( char ) ( ( codepoint & 0x3f ) | 0x80 ) ;
2021-09-02 01:39:47 +03:00
size = 3 ;
2021-07-28 14:15:43 +03:00
}
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 ) ;
2021-09-02 01:39:47 +03:00
size = 4 ;
2021-07-28 14:15:43 +03:00
}
2021-09-02 01:39:47 +03:00
* byteSize = size ;
2021-07-28 14:15:43 +03:00
return utf8 ;
}
2021-10-27 12:25:24 +03:00
// 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 GetCodepoint ( const char * text , int * bytesProcessed )
{
/*
UTF - 8 specs from https : //www.ietf.org/rfc/rfc3629.txt
Char . number range | UTF - 8 octet sequence
( hexadecimal ) | ( binary )
- - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0000 0000 - 0000 007F | 0 xxxxxxx
0000 00 80 - 0000 07FF | 110 xxxxx 10 xxxxxx
0000 0800 - 0000 FFFF | 1110 xxxx 10 xxxxxx 10 xxxxxx
0001 0000 - 0010 FFFF | 11110 xxx 10 xxxxxx 10 xxxxxx 10 xxxxxx
*/
// NOTE: on decode errors we return as soon as possible
int code = 0x3f ; // Codepoint (defaults to '?')
int octet = ( unsigned char ) ( text [ 0 ] ) ; // The first UTF8 octet
* bytesProcessed = 1 ;
if ( octet < = 0x7f )
{
// Only one octet (ASCII range x00-7F)
code = text [ 0 ] ;
}
else if ( ( octet & 0xe0 ) = = 0xc0 )
{
// Two octets
// [0]xC2-DF [1]UTF8-tail(x80-BF)
unsigned char octet1 = text [ 1 ] ;
if ( ( octet1 = = ' \0 ' ) | | ( ( octet1 > > 6 ) ! = 2 ) ) { * bytesProcessed = 2 ; return code ; } // Unexpected sequence
if ( ( octet > = 0xc2 ) & & ( octet < = 0xdf ) )
{
code = ( ( octet & 0x1f ) < < 6 ) | ( octet1 & 0x3f ) ;
* bytesProcessed = 2 ;
}
}
else if ( ( octet & 0xf0 ) = = 0xe0 )
{
// Three octets
unsigned char octet1 = text [ 1 ] ;
unsigned char octet2 = ' \0 ' ;
if ( ( octet1 = = ' \0 ' ) | | ( ( octet1 > > 6 ) ! = 2 ) ) { * bytesProcessed = 2 ; return code ; } // Unexpected sequence
octet2 = text [ 2 ] ;
if ( ( octet2 = = ' \0 ' ) | | ( ( octet2 > > 6 ) ! = 2 ) ) { * bytesProcessed = 3 ; return code ; } // Unexpected sequence
// [0]xE0 [1]xA0-BF [2]UTF8-tail(x80-BF)
// [0]xE1-EC [1]UTF8-tail [2]UTF8-tail(x80-BF)
// [0]xED [1]x80-9F [2]UTF8-tail(x80-BF)
// [0]xEE-EF [1]UTF8-tail [2]UTF8-tail(x80-BF)
if ( ( ( octet = = 0xe0 ) & & ! ( ( octet1 > = 0xa0 ) & & ( octet1 < = 0xbf ) ) ) | |
( ( octet = = 0xed ) & & ! ( ( octet1 > = 0x80 ) & & ( octet1 < = 0x9f ) ) ) ) { * bytesProcessed = 2 ; return code ; }
if ( ( octet > = 0xe0 ) & & ( 0 < = 0xef ) )
{
code = ( ( octet & 0xf ) < < 12 ) | ( ( octet1 & 0x3f ) < < 6 ) | ( octet2 & 0x3f ) ;
* bytesProcessed = 3 ;
}
}
else if ( ( octet & 0xf8 ) = = 0xf0 )
{
// Four octets
if ( octet > 0xf4 ) return code ;
unsigned char octet1 = text [ 1 ] ;
unsigned char octet2 = ' \0 ' ;
unsigned char octet3 = ' \0 ' ;
if ( ( octet1 = = ' \0 ' ) | | ( ( octet1 > > 6 ) ! = 2 ) ) { * bytesProcessed = 2 ; return code ; } // Unexpected sequence
octet2 = text [ 2 ] ;
if ( ( octet2 = = ' \0 ' ) | | ( ( octet2 > > 6 ) ! = 2 ) ) { * bytesProcessed = 3 ; return code ; } // Unexpected sequence
octet3 = text [ 3 ] ;
if ( ( octet3 = = ' \0 ' ) | | ( ( octet3 > > 6 ) ! = 2 ) ) { * bytesProcessed = 4 ; return code ; } // Unexpected sequence
// [0]xF0 [1]x90-BF [2]UTF8-tail [3]UTF8-tail
// [0]xF1-F3 [1]UTF8-tail [2]UTF8-tail [3]UTF8-tail
// [0]xF4 [1]x80-8F [2]UTF8-tail [3]UTF8-tail
if ( ( ( octet = = 0xf0 ) & & ! ( ( octet1 > = 0x90 ) & & ( octet1 < = 0xbf ) ) ) | |
( ( octet = = 0xf4 ) & & ! ( ( octet1 > = 0x80 ) & & ( octet1 < = 0x8f ) ) ) ) { * bytesProcessed = 2 ; return code ; } // Unexpected sequence
if ( octet > = 0xf0 )
{
code = ( ( octet & 0x7 ) < < 18 ) | ( ( octet1 & 0x3f ) < < 12 ) | ( ( octet2 & 0x3f ) < < 6 ) | ( octet3 & 0x3f ) ;
* bytesProcessed = 4 ;
}
}
if ( code > 0x10ffff ) code = 0x3f ; // Codepoints after U+10ffff are invalid
return code ;
}
2021-07-28 14:15:43 +03:00
# endif // RAYGUI_STANDALONE
# endif // RAYGUI_IMPLEMENTATION