github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/raygui.h (about)

     1  /*******************************************************************************************
     2  *
     3  *   raygui v3.5-dev - A simple and easy-to-use immediate-mode gui library
     4  *
     5  *   DESCRIPTION:
     6  *
     7  *   raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also
     8  *   available as a standalone library, as long as input and drawing functions are provided.
     9  *
    10  *   Controls provided:
    11  *
    12  *   # Container/separators Controls
    13  *       - WindowBox     --> StatusBar, Panel
    14  *       - GroupBox      --> Line
    15  *       - Line
    16  *       - Panel         --> StatusBar
    17  *       - ScrollPanel   --> StatusBar
    18  *
    19  *   # Basic Controls
    20  *       - Label
    21  *       - Button
    22  *       - LabelButton   --> Label
    23  *       - Toggle
    24  *       - ToggleGroup   --> Toggle
    25  *       - CheckBox
    26  *       - ComboBox
    27  *       - DropdownBox
    28  *       - TextBox
    29  *       - TextBoxMulti
    30  *       - ValueBox      --> TextBox
    31  *       - Spinner       --> Button, ValueBox
    32  *       - Slider
    33  *       - SliderBar     --> Slider
    34  *       - ProgressBar
    35  *       - StatusBar
    36  *       - DummyRec
    37  *       - Grid
    38  *
    39  *   # Advance Controls
    40  *       - ListView
    41  *       - ColorPicker   --> ColorPanel, ColorBarHue
    42  *       - MessageBox    --> Window, Label, Button
    43  *       - TextInputBox  --> Window, Label, TextBox, Button
    44  *
    45  *   It also provides a set of functions for styling the controls based on its properties (size, color).
    46  *
    47  *
    48  *   RAYGUI STYLE (guiStyle):
    49  *
    50  *   raygui uses a global data array for all gui style properties (allocated on data segment by default),
    51  *   when a new style is loaded, it is loaded over the global style... but a default gui style could always be
    52  *   recovered with GuiLoadStyleDefault() function, that overwrites the current style to the default one
    53  *
    54  *   The global style array size is fixed and depends on the number of controls and properties:
    55  *
    56  *       static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)];
    57  *
    58  *   guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB
    59  *
    60  *   Note that the first set of BASE properties (by default guiStyle[0..15]) belong to the generic style
    61  *   used for all controls, when any of those base values is set, it is automatically populated to all
    62  *   controls, so, specific control values overwriting generic style should be set after base values.
    63  *
    64  *   After the first BASE set we have the EXTENDED properties (by default guiStyle[16..23]), those
    65  *   properties are actually common to all controls and can not be overwritten individually (like BASE ones)
    66  *   Some of those properties are: TEXT_SIZE, TEXT_SPACING, LINE_COLOR, BACKGROUND_COLOR
    67  *
    68  *   Custom control properties can be defined using the EXTENDED properties for each independent control.
    69  *
    70  *   TOOL: rGuiStyler is a visual tool to customize raygui style.
    71  *
    72  *
    73  *   RAYGUI ICONS (guiIcons):
    74  *
    75  *   raygui could use a global array containing icons data (allocated on data segment by default),
    76  *   a custom icons set could be loaded over this array using GuiLoadIcons(), but loaded icons set
    77  *   must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS will be loaded
    78  *
    79  *   Every icon is codified in binary form, using 1 bit per pixel, so, every 16x16 icon
    80  *   requires 8 integers (16*16/32) to be stored in memory.
    81  *
    82  *   When the icon is draw, actually one quad per pixel is drawn if the bit for that pixel is set.
    83  *
    84  *   The global icons array size is fixed and depends on the number of icons and size:
    85  *
    86  *       static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS];
    87  *
    88  *   guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB
    89  *
    90  *   TOOL: rGuiIcons is a visual tool to customize raygui icons and create new ones.
    91  *
    92  *
    93  *   CONFIGURATION:
    94  *
    95  *   #define RAYGUI_IMPLEMENTATION
    96  *       Generates the implementation of the library into the included file.
    97  *       If not defined, the library is in header only mode and can be included in other headers
    98  *       or source files without problems. But only ONE file should hold the implementation.
    99  *
   100  *   #define RAYGUI_STANDALONE
   101  *       Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined
   102  *       internally in the library and input management and drawing functions must be provided by
   103  *       the user (check library implementation for further details).
   104  *
   105  *   #define RAYGUI_NO_ICONS
   106  *       Avoid including embedded ricons data (256 icons, 16x16 pixels, 1-bit per pixel, 2KB)
   107  *
   108  *   #define RAYGUI_CUSTOM_ICONS
   109  *       Includes custom ricons.h header defining a set of custom icons,
   110  *       this file can be generated using rGuiIcons tool
   111  *
   112  *
   113  *   VERSIONS HISTORY:
   114  *       3.5 (xx-xxx-2022) ADDED: Multiple new icons, useful for code editing tools
   115  *                         ADDED: GuiTabBar(), based on GuiToggle()
   116  *                         REMOVED: Unneeded icon editing functions 
   117  *                         REDESIGNED: GuiDrawText() to divide drawing by lines
   118  *                         REMOVED: MeasureTextEx() dependency, logic directly implemented
   119  *                         REMOVED: DrawTextEx() dependency, logic directly implemented
   120  *                         ADDED: Helper functions to split text in separate lines
   121  *       3.2 (22-May-2022) RENAMED: Some enum values, for unification, avoiding prefixes
   122  *                         REMOVED: GuiScrollBar(), only internal
   123  *                         REDESIGNED: GuiPanel() to support text parameter
   124  *                         REDESIGNED: GuiScrollPanel() to support text parameter
   125  *                         REDESIGNED: GuiColorPicker() to support text parameter
   126  *                         REDESIGNED: GuiColorPanel() to support text parameter
   127  *                         REDESIGNED: GuiColorBarAlpha() to support text parameter
   128  *                         REDESIGNED: GuiColorBarHue() to support text parameter
   129  *                         REDESIGNED: GuiTextInputBox() to support password
   130  *       3.1 (12-Jan-2022) REVIEWED: Default style for consistency (aligned with rGuiLayout v2.5 tool)
   131  *                         REVIEWED: GuiLoadStyle() to support compressed font atlas image data and unload previous textures
   132  *                         REVIEWED: External icons usage logic
   133  *                         REVIEWED: GuiLine() for centered alignment when including text
   134  *                         RENAMED: Multiple controls properties definitions to prepend RAYGUI_
   135  *                         RENAMED: RICON_ references to RAYGUI_ICON_ for library consistency
   136  *                         Projects updated and multiple tweaks
   137  *       3.0 (04-Nov-2021) Integrated ricons data to avoid external file
   138  *                         REDESIGNED: GuiTextBoxMulti()
   139  *                         REMOVED: GuiImageButton*()
   140  *                         Multiple minor tweaks and bugs corrected
   141  *       2.9 (17-Mar-2021) REMOVED: Tooltip API
   142  *       2.8 (03-May-2020) Centralized rectangles drawing to GuiDrawRectangle()
   143  *       2.7 (20-Feb-2020) ADDED: Possible tooltips API
   144  *       2.6 (09-Sep-2019) ADDED: GuiTextInputBox()
   145  *                         REDESIGNED: GuiListView*(), GuiDropdownBox(), GuiSlider*(), GuiProgressBar(), GuiMessageBox()
   146  *                         REVIEWED: GuiTextBox(), GuiSpinner(), GuiValueBox(), GuiLoadStyle()
   147  *                         Replaced property INNER_PADDING by TEXT_PADDING, renamed some properties
   148  *                         ADDED: 8 new custom styles ready to use
   149  *                         Multiple minor tweaks and bugs corrected
   150  *       2.5 (28-May-2019) Implemented extended GuiTextBox(), GuiValueBox(), GuiSpinner()
   151  *       2.3 (29-Apr-2019) ADDED: rIcons auxiliar library and support for it, multiple controls reviewed
   152  *                         Refactor all controls drawing mechanism to use control state
   153  *       2.2 (05-Feb-2019) ADDED: GuiScrollBar(), GuiScrollPanel(), reviewed GuiListView(), removed Gui*Ex() controls
   154  *       2.1 (26-Dec-2018) REDESIGNED: GuiCheckBox(), GuiComboBox(), GuiDropdownBox(), GuiToggleGroup() > Use combined text string
   155  *                         REDESIGNED: Style system (breaking change)
   156  *       2.0 (08-Nov-2018) ADDED: Support controls guiLock and custom fonts
   157  *                         REVIEWED: GuiComboBox(), GuiListView()...
   158  *       1.9 (09-Oct-2018) REVIEWED: GuiGrid(), GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()...
   159  *       1.8 (01-May-2018) Lot of rework and redesign to align with rGuiStyler and rGuiLayout
   160  *       1.5 (21-Jun-2017) Working in an improved styles system
   161  *       1.4 (15-Jun-2017) Rewritten all GUI functions (removed useless ones)
   162  *       1.3 (12-Jun-2017) Complete redesign of style system
   163  *       1.1 (01-Jun-2017) Complete review of the library
   164  *       1.0 (07-Jun-2016) Converted to header-only by Ramon Santamaria.
   165  *       0.9 (07-Mar-2016) Reviewed and tested by Albert Martos, Ian Eito, Sergio Martinez and Ramon Santamaria.
   166  *       0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria.
   167  *
   168  *
   169  *   CONTRIBUTORS:
   170  *
   171  *       Ramon Santamaria:   Supervision, review, redesign, update and maintenance
   172  *       Vlad Adrian:        Complete rewrite of GuiTextBox() to support extended features (2019)
   173  *       Sergio Martinez:    Review, testing (2015) and redesign of multiple controls (2018)
   174  *       Adria Arranz:       Testing and Implementation of additional controls (2018)
   175  *       Jordi Jorba:        Testing and Implementation of additional controls (2018)
   176  *       Albert Martos:      Review and testing of the library (2015)
   177  *       Ian Eito:           Review and testing of the library (2015)
   178  *       Kevin Gato:         Initial implementation of basic components (2014)
   179  *       Daniel Nicolas:     Initial implementation of basic components (2014)
   180  *
   181  *
   182  *   LICENSE: zlib/libpng
   183  *
   184  *   Copyright (c) 2014-2022 Ramon Santamaria (@raysan5)
   185  *
   186  *   This software is provided "as-is", without any express or implied warranty. In no event
   187  *   will the authors be held liable for any damages arising from the use of this software.
   188  *
   189  *   Permission is granted to anyone to use this software for any purpose, including commercial
   190  *   applications, and to alter it and redistribute it freely, subject to the following restrictions:
   191  *
   192  *     1. The origin of this software must not be misrepresented; you must not claim that you
   193  *     wrote the original software. If you use this software in a product, an acknowledgment
   194  *     in the product documentation would be appreciated but is not required.
   195  *
   196  *     2. Altered source versions must be plainly marked as such, and must not be misrepresented
   197  *     as being the original software.
   198  *
   199  *     3. This notice may not be removed or altered from any source distribution.
   200  *
   201  **********************************************************************************************/
   202  
   203  #ifndef RAYGUI_H
   204  #define RAYGUI_H
   205  
   206  #define RAYGUI_VERSION  "3.2"
   207  
   208  #if !defined(RAYGUI_STANDALONE)
   209      #include "raylib.h"
   210  #endif
   211  
   212  // Function specifiers in case library is build/used as a shared library (Windows)
   213  // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
   214  #if defined(_WIN32)
   215      #if defined(BUILD_LIBTYPE_SHARED)
   216          #define RAYGUIAPI __declspec(dllexport)     // We are building the library as a Win32 shared library (.dll)
   217      #elif defined(USE_LIBTYPE_SHARED)
   218          #define RAYGUIAPI __declspec(dllimport)     // We are using the library as a Win32 shared library (.dll)
   219      #endif
   220  #endif
   221  
   222  // Function specifiers definition
   223  #ifndef RAYGUIAPI
   224      #define RAYGUIAPI       // Functions defined as 'extern' by default (implicit specifiers)
   225  #endif
   226  
   227  //----------------------------------------------------------------------------------
   228  // Defines and Macros
   229  //----------------------------------------------------------------------------------
   230  // Allow custom memory allocators
   231  #ifndef RAYGUI_MALLOC
   232      #define RAYGUI_MALLOC(sz)       malloc(sz)
   233  #endif
   234  #ifndef RAYGUI_CALLOC
   235      #define RAYGUI_CALLOC(n,sz)     calloc(n,sz)
   236  #endif
   237  #ifndef RAYGUI_FREE
   238      #define RAYGUI_FREE(p)          free(p)
   239  #endif
   240  
   241  // Simple log system to avoid printf() calls if required
   242  // NOTE: Avoiding those calls, also avoids const strings memory usage
   243  #define RAYGUI_SUPPORT_LOG_INFO
   244  #if defined(RAYGUI_SUPPORT_LOG_INFO)
   245    #define RAYGUI_LOG(...)           printf(__VA_ARGS__)
   246  #else
   247    #define RAYGUI_LOG(...)
   248  #endif
   249  
   250  //----------------------------------------------------------------------------------
   251  // Types and Structures Definition
   252  // NOTE: Some types are required for RAYGUI_STANDALONE usage
   253  //----------------------------------------------------------------------------------
   254  #if defined(RAYGUI_STANDALONE)
   255      #ifndef __cplusplus
   256      // Boolean type
   257          #ifndef true
   258              typedef enum { false, true } bool;
   259          #endif
   260      #endif
   261  
   262      // Vector2 type
   263      typedef struct Vector2 {
   264          float x;
   265          float y;
   266      } Vector2;
   267  
   268      // Vector3 type                 // -- ConvertHSVtoRGB(), ConvertRGBtoHSV()
   269      typedef struct Vector3 {
   270          float x;
   271          float y;
   272          float z;
   273      } Vector3;
   274  
   275      // Color type, RGBA (32bit)
   276      typedef struct Color {
   277          unsigned char r;
   278          unsigned char g;
   279          unsigned char b;
   280          unsigned char a;
   281      } Color;
   282  
   283      // Rectangle type
   284      typedef struct Rectangle {
   285          float x;
   286          float y;
   287          float width;
   288          float height;
   289      } Rectangle;
   290  
   291      // TODO: Texture2D type is very coupled to raylib, required by Font type
   292      // It should be redesigned to be provided by user
   293      typedef struct Texture2D {
   294          unsigned int id;        // OpenGL texture id
   295          int width;              // Texture base width
   296          int height;             // Texture base height
   297          int mipmaps;            // Mipmap levels, 1 by default
   298          int format;             // Data format (PixelFormat type)
   299      } Texture2D;
   300  
   301      // Image, pixel data stored in CPU memory (RAM)
   302      typedef struct Image {
   303          void *data;             // Image raw data
   304          int width;              // Image base width
   305          int height;             // Image base height
   306          int mipmaps;            // Mipmap levels, 1 by default
   307          int format;             // Data format (PixelFormat type)
   308      } Image;
   309  
   310      // GlyphInfo, font characters glyphs info
   311      typedef struct GlyphInfo {
   312          int value;              // Character value (Unicode)
   313          int offsetX;            // Character offset X when drawing
   314          int offsetY;            // Character offset Y when drawing
   315          int advanceX;           // Character advance position X
   316          Image image;            // Character image data
   317      } GlyphInfo;
   318  
   319      // TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle()
   320      // It should be redesigned to be provided by user
   321      typedef struct Font {
   322          int baseSize;           // Base size (default chars height)
   323          int glyphCount;         // Number of glyph characters
   324          int glyphPadding;       // Padding around the glyph characters
   325          Texture2D texture;      // Texture atlas containing the glyphs
   326          Rectangle *recs;        // Rectangles in texture for the glyphs
   327          GlyphInfo *glyphs;      // Glyphs info data
   328      } Font;
   329  #endif
   330  
   331  // Style property
   332  typedef struct GuiStyleProp {
   333      unsigned short controlId;
   334      unsigned short propertyId;
   335      unsigned int propertyValue;
   336  } GuiStyleProp;
   337  
   338  // Gui control state
   339  typedef enum {
   340      STATE_NORMAL = 0,
   341      STATE_FOCUSED,
   342      STATE_PRESSED,
   343      STATE_DISABLED,
   344  } GuiState;
   345  
   346  // Gui control text alignment
   347  typedef enum {
   348      TEXT_ALIGN_LEFT = 0,
   349      TEXT_ALIGN_CENTER,
   350      TEXT_ALIGN_RIGHT,
   351  } GuiTextAlignment;
   352  
   353  // Gui controls
   354  typedef enum {
   355      // Default -> populates to all controls when set
   356      DEFAULT = 0,
   357      // Basic controls
   358      LABEL,          // Used also for: LABELBUTTON
   359      BUTTON,
   360      TOGGLE,         // Used also for: TOGGLEGROUP
   361      SLIDER,         // Used also for: SLIDERBAR
   362      PROGRESSBAR,
   363      CHECKBOX,
   364      COMBOBOX,
   365      DROPDOWNBOX,
   366      TEXTBOX,        // Used also for: TEXTBOXMULTI
   367      VALUEBOX,
   368      SPINNER,        // Uses: BUTTON, VALUEBOX
   369      LISTVIEW,
   370      COLORPICKER,
   371      SCROLLBAR,
   372      STATUSBAR
   373  } GuiControl;
   374  
   375  // Gui base properties for every control
   376  // NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties)
   377  typedef enum {
   378      BORDER_COLOR_NORMAL = 0,
   379      BASE_COLOR_NORMAL,
   380      TEXT_COLOR_NORMAL,
   381      BORDER_COLOR_FOCUSED,
   382      BASE_COLOR_FOCUSED,
   383      TEXT_COLOR_FOCUSED,
   384      BORDER_COLOR_PRESSED,
   385      BASE_COLOR_PRESSED,
   386      TEXT_COLOR_PRESSED,
   387      BORDER_COLOR_DISABLED,
   388      BASE_COLOR_DISABLED,
   389      TEXT_COLOR_DISABLED,
   390      BORDER_WIDTH,
   391      TEXT_PADDING,
   392      TEXT_ALIGNMENT,
   393      RESERVED
   394  } GuiControlProperty;
   395  
   396  // Gui extended properties depend on control
   397  // NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default 8 properties)
   398  //----------------------------------------------------------------------------------
   399  
   400  // DEFAULT extended properties
   401  // NOTE: Those properties are common to all controls or global
   402  typedef enum {
   403      TEXT_SIZE = 16,             // Text size (glyphs max height)
   404      TEXT_SPACING,               // Text spacing between glyphs
   405      LINE_COLOR,                 // Line control color
   406      BACKGROUND_COLOR,           // Background color
   407  } GuiDefaultProperty;
   408  
   409  // Label
   410  //typedef enum { } GuiLabelProperty;
   411  
   412  // Button/Spinner
   413  //typedef enum { } GuiButtonProperty;
   414  
   415  // Toggle/ToggleGroup
   416  typedef enum {
   417      GROUP_PADDING = 16,         // ToggleGroup separation between toggles
   418  } GuiToggleProperty;
   419  
   420  // Slider/SliderBar
   421  typedef enum {
   422      SLIDER_WIDTH = 16,          // Slider size of internal bar
   423      SLIDER_PADDING              // Slider/SliderBar internal bar padding
   424  } GuiSliderProperty;
   425  
   426  // ProgressBar
   427  typedef enum {
   428      PROGRESS_PADDING = 16,      // ProgressBar internal padding
   429  } GuiProgressBarProperty;
   430  
   431  // ScrollBar
   432  typedef enum {
   433      ARROWS_SIZE = 16,
   434      ARROWS_VISIBLE,
   435      SCROLL_SLIDER_PADDING,      // (SLIDERBAR, SLIDER_PADDING)
   436      SCROLL_SLIDER_SIZE,
   437      SCROLL_PADDING,
   438      SCROLL_SPEED,
   439  } GuiScrollBarProperty;
   440  
   441  // CheckBox
   442  typedef enum {
   443      CHECK_PADDING = 16          // CheckBox internal check padding
   444  } GuiCheckBoxProperty;
   445  
   446  // ComboBox
   447  typedef enum {
   448      COMBO_BUTTON_WIDTH = 16,    // ComboBox right button width
   449      COMBO_BUTTON_SPACING        // ComboBox button separation
   450  } GuiComboBoxProperty;
   451  
   452  // DropdownBox
   453  typedef enum {
   454      ARROW_PADDING = 16,         // DropdownBox arrow separation from border and items
   455      DROPDOWN_ITEMS_SPACING      // DropdownBox items separation
   456  } GuiDropdownBoxProperty;
   457  
   458  // TextBox/TextBoxMulti/ValueBox/Spinner
   459  typedef enum {
   460      TEXT_INNER_PADDING = 16,    // TextBox/TextBoxMulti/ValueBox/Spinner inner text padding
   461      TEXT_LINES_SPACING,         // TextBoxMulti lines separation
   462  } GuiTextBoxProperty;
   463  
   464  // Spinner
   465  typedef enum {
   466      SPIN_BUTTON_WIDTH = 16,     // Spinner left/right buttons width
   467      SPIN_BUTTON_SPACING,        // Spinner buttons separation
   468  } GuiSpinnerProperty;
   469  
   470  // ListView
   471  typedef enum {
   472      LIST_ITEMS_HEIGHT = 16,     // ListView items height
   473      LIST_ITEMS_SPACING,         // ListView items separation
   474      SCROLLBAR_WIDTH,            // ListView scrollbar size (usually width)
   475      SCROLLBAR_SIDE,             // ListView scrollbar side (0-left, 1-right)
   476  } GuiListViewProperty;
   477  
   478  // ColorPicker
   479  typedef enum {
   480      COLOR_SELECTOR_SIZE = 16,
   481      HUEBAR_WIDTH,               // ColorPicker right hue bar width
   482      HUEBAR_PADDING,             // ColorPicker right hue bar separation from panel
   483      HUEBAR_SELECTOR_HEIGHT,     // ColorPicker right hue bar selector height
   484      HUEBAR_SELECTOR_OVERFLOW    // ColorPicker right hue bar selector overflow
   485  } GuiColorPickerProperty;
   486  
   487  #define SCROLLBAR_LEFT_SIDE     0
   488  #define SCROLLBAR_RIGHT_SIDE    1
   489  
   490  //----------------------------------------------------------------------------------
   491  // Global Variables Definition
   492  //----------------------------------------------------------------------------------
   493  // ...
   494  
   495  //----------------------------------------------------------------------------------
   496  // Module Functions Declaration
   497  //----------------------------------------------------------------------------------
   498  
   499  #if defined(__cplusplus)
   500  extern "C" {            // Prevents name mangling of functions
   501  #endif
   502  
   503  // Global gui state control functions
   504  RAYGUIAPI void GuiEnable(void);                                         // Enable gui controls (global state)
   505  RAYGUIAPI void GuiDisable(void);                                        // Disable gui controls (global state)
   506  RAYGUIAPI void GuiLock(void);                                           // Lock gui controls (global state)
   507  RAYGUIAPI void GuiUnlock(void);                                         // Unlock gui controls (global state)
   508  RAYGUIAPI bool GuiIsLocked(void);                                       // Check if gui is locked (global state)
   509  RAYGUIAPI void GuiFade(float alpha);                                    // Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f
   510  RAYGUIAPI void GuiSetState(int state);                                  // Set gui state (global state)
   511  RAYGUIAPI int GuiGetState(void);                                        // Get gui state (global state)
   512  
   513  // Font set/get functions
   514  RAYGUIAPI void GuiSetFont(Font font);                                   // Set gui custom font (global state)
   515  RAYGUIAPI Font GuiGetFont(void);                                        // Get gui custom font (global state)
   516  
   517  // Style set/get functions
   518  RAYGUIAPI void GuiSetStyle(int control, int property, int value);       // Set one style property
   519  RAYGUIAPI int GuiGetStyle(int control, int property);                   // Get one style property
   520  
   521  // Container/separator controls, useful for controls organization
   522  RAYGUIAPI bool GuiWindowBox(Rectangle bounds, const char *title);                                       // Window Box control, shows a window that can be closed
   523  RAYGUIAPI void GuiGroupBox(Rectangle bounds, const char *text);                                         // Group Box control with text name
   524  RAYGUIAPI void GuiLine(Rectangle bounds, const char *text);                                             // Line separator control, could contain text
   525  RAYGUIAPI void GuiPanel(Rectangle bounds, const char *text);                                            // Panel control, useful to group controls
   526  RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *active);                   // Tab Bar control, returns TAB to be closed or -1
   527  RAYGUIAPI Rectangle GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll); // Scroll Panel control
   528  
   529  // Basic controls set
   530  RAYGUIAPI void GuiLabel(Rectangle bounds, const char *text);                                            // Label control, shows text
   531  RAYGUIAPI bool GuiButton(Rectangle bounds, const char *text);                                           // Button control, returns true when clicked
   532  RAYGUIAPI bool GuiLabelButton(Rectangle bounds, const char *text);                                      // Label button control, show true when clicked
   533  RAYGUIAPI bool GuiToggle(Rectangle bounds, const char *text, bool active);                              // Toggle Button control, returns true when active
   534  RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int active);                           // Toggle Group control, returns active toggle index
   535  RAYGUIAPI bool GuiCheckBox(Rectangle bounds, const char *text, bool checked);                           // Check Box control, returns true when active
   536  RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int active);                              // Combo Box control, returns selected item index
   537  RAYGUIAPI bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode);          // Dropdown Box control, returns selected item
   538  RAYGUIAPI bool GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode);     // Spinner control, returns selected value
   539  RAYGUIAPI bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode);    // Value Box control, updates input text with numbers
   540  RAYGUIAPI bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode);                   // Text Box control, updates input text
   541  RAYGUIAPI bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode);              // Text Box control with multiple lines
   542  RAYGUIAPI float GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue);       // Slider control, returns selected value
   543  RAYGUIAPI float GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue);    // Slider Bar control, returns selected value
   544  RAYGUIAPI float GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue);  // Progress Bar control, shows current progress value
   545  RAYGUIAPI void GuiStatusBar(Rectangle bounds, const char *text);                                        // Status Bar control, shows info text
   546  RAYGUIAPI void GuiDummyRec(Rectangle bounds, const char *text);                                         // Dummy control for placeholders
   547  RAYGUIAPI Vector2 GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs);              // Grid control, returns mouse cell position
   548  
   549  // Advance controls set
   550  RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int active);            // List View control, returns selected list item index
   551  RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *focus, int *scrollIndex, int active);      // List View with extended parameters
   552  RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons);                 // Message Box control, displays a message
   553  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
   554  RAYGUIAPI Color GuiColorPicker(Rectangle bounds, const char *text, Color color);                        // Color Picker control (multiple color controls)
   555  RAYGUIAPI Color GuiColorPanel(Rectangle bounds, const char *text, Color color);                         // Color Panel control
   556  RAYGUIAPI float GuiColorBarAlpha(Rectangle bounds, const char *text, float alpha);                      // Color Bar Alpha control
   557  RAYGUIAPI float GuiColorBarHue(Rectangle bounds, const char *text, float value);                        // Color Bar Hue control
   558  
   559  // Styles loading functions
   560  RAYGUIAPI void GuiLoadStyle(const char *fileName);              // Load style file over global style variable (.rgs)
   561  RAYGUIAPI void GuiLoadStyleDefault(void);                       // Load style default over global style
   562  
   563  // Icons functionality
   564  RAYGUIAPI const char *GuiIconText(int iconId, const char *text); // Get text with icon id prepended (if supported)
   565  
   566  #if !defined(RAYGUI_NO_ICONS)
   567  RAYGUIAPI unsigned int *GuiGetIcons(void);                      // Get raygui icons data pointer
   568  RAYGUIAPI char **GuiLoadIcons(const char *fileName, bool loadIconsName);  // Load raygui icons file (.rgi) into internal icons data
   569  RAYGUIAPI void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color);
   570  
   571  #if !defined(RAYGUI_CUSTOM_ICONS)
   572  //----------------------------------------------------------------------------------
   573  // Icons enumeration
   574  //----------------------------------------------------------------------------------
   575  typedef enum {
   576      ICON_NONE                     = 0,
   577      ICON_FOLDER_FILE_OPEN         = 1,
   578      ICON_FILE_SAVE_CLASSIC        = 2,
   579      ICON_FOLDER_OPEN              = 3,
   580      ICON_FOLDER_SAVE              = 4,
   581      ICON_FILE_OPEN                = 5,
   582      ICON_FILE_SAVE                = 6,
   583      ICON_FILE_EXPORT              = 7,
   584      ICON_FILE_ADD                 = 8,
   585      ICON_FILE_DELETE              = 9,
   586      ICON_FILETYPE_TEXT            = 10,
   587      ICON_FILETYPE_AUDIO           = 11,
   588      ICON_FILETYPE_IMAGE           = 12,
   589      ICON_FILETYPE_PLAY            = 13,
   590      ICON_FILETYPE_VIDEO           = 14,
   591      ICON_FILETYPE_INFO            = 15,
   592      ICON_FILE_COPY                = 16,
   593      ICON_FILE_CUT                 = 17,
   594      ICON_FILE_PASTE               = 18,
   595      ICON_CURSOR_HAND              = 19,
   596      ICON_CURSOR_POINTER           = 20,
   597      ICON_CURSOR_CLASSIC           = 21,
   598      ICON_PENCIL                   = 22,
   599      ICON_PENCIL_BIG               = 23,
   600      ICON_BRUSH_CLASSIC            = 24,
   601      ICON_BRUSH_PAINTER            = 25,
   602      ICON_WATER_DROP               = 26,
   603      ICON_COLOR_PICKER             = 27,
   604      ICON_RUBBER                   = 28,
   605      ICON_COLOR_BUCKET             = 29,
   606      ICON_TEXT_T                   = 30,
   607      ICON_TEXT_A                   = 31,
   608      ICON_SCALE                    = 32,
   609      ICON_RESIZE                   = 33,
   610      ICON_FILTER_POINT             = 34,
   611      ICON_FILTER_BILINEAR          = 35,
   612      ICON_CROP                     = 36,
   613      ICON_CROP_ALPHA               = 37,
   614      ICON_SQUARE_TOGGLE            = 38,
   615      ICON_SYMMETRY                 = 39,
   616      ICON_SYMMETRY_HORIZONTAL      = 40,
   617      ICON_SYMMETRY_VERTICAL        = 41,
   618      ICON_LENS                     = 42,
   619      ICON_LENS_BIG                 = 43,
   620      ICON_EYE_ON                   = 44,
   621      ICON_EYE_OFF                  = 45,
   622      ICON_FILTER_TOP               = 46,
   623      ICON_FILTER                   = 47,
   624      ICON_TARGET_POINT             = 48,
   625      ICON_TARGET_SMALL             = 49,
   626      ICON_TARGET_BIG               = 50,
   627      ICON_TARGET_MOVE              = 51,
   628      ICON_CURSOR_MOVE              = 52,
   629      ICON_CURSOR_SCALE             = 53,
   630      ICON_CURSOR_SCALE_RIGHT       = 54,
   631      ICON_CURSOR_SCALE_LEFT        = 55,
   632      ICON_UNDO                     = 56,
   633      ICON_REDO                     = 57,
   634      ICON_REREDO                   = 58,
   635      ICON_MUTATE                   = 59,
   636      ICON_ROTATE                   = 60,
   637      ICON_REPEAT                   = 61,
   638      ICON_SHUFFLE                  = 62,
   639      ICON_EMPTYBOX                 = 63,
   640      ICON_TARGET                   = 64,
   641      ICON_TARGET_SMALL_FILL        = 65,
   642      ICON_TARGET_BIG_FILL          = 66,
   643      ICON_TARGET_MOVE_FILL         = 67,
   644      ICON_CURSOR_MOVE_FILL         = 68,
   645      ICON_CURSOR_SCALE_FILL        = 69,
   646      ICON_CURSOR_SCALE_RIGHT_FILL  = 70,
   647      ICON_CURSOR_SCALE_LEFT_FILL   = 71,
   648      ICON_UNDO_FILL                = 72,
   649      ICON_REDO_FILL                = 73,
   650      ICON_REREDO_FILL              = 74,
   651      ICON_MUTATE_FILL              = 75,
   652      ICON_ROTATE_FILL              = 76,
   653      ICON_REPEAT_FILL              = 77,
   654      ICON_SHUFFLE_FILL             = 78,
   655      ICON_EMPTYBOX_SMALL           = 79,
   656      ICON_BOX                      = 80,
   657      ICON_BOX_TOP                  = 81,
   658      ICON_BOX_TOP_RIGHT            = 82,
   659      ICON_BOX_RIGHT                = 83,
   660      ICON_BOX_BOTTOM_RIGHT         = 84,
   661      ICON_BOX_BOTTOM               = 85,
   662      ICON_BOX_BOTTOM_LEFT          = 86,
   663      ICON_BOX_LEFT                 = 87,
   664      ICON_BOX_TOP_LEFT             = 88,
   665      ICON_BOX_CENTER               = 89,
   666      ICON_BOX_CIRCLE_MASK          = 90,
   667      ICON_POT                      = 91,
   668      ICON_ALPHA_MULTIPLY           = 92,
   669      ICON_ALPHA_CLEAR              = 93,
   670      ICON_DITHERING                = 94,
   671      ICON_MIPMAPS                  = 95,
   672      ICON_BOX_GRID                 = 96,
   673      ICON_GRID                     = 97,
   674      ICON_BOX_CORNERS_SMALL        = 98,
   675      ICON_BOX_CORNERS_BIG          = 99,
   676      ICON_FOUR_BOXES               = 100,
   677      ICON_GRID_FILL                = 101,
   678      ICON_BOX_MULTISIZE            = 102,
   679      ICON_ZOOM_SMALL               = 103,
   680      ICON_ZOOM_MEDIUM              = 104,
   681      ICON_ZOOM_BIG                 = 105,
   682      ICON_ZOOM_ALL                 = 106,
   683      ICON_ZOOM_CENTER              = 107,
   684      ICON_BOX_DOTS_SMALL           = 108,
   685      ICON_BOX_DOTS_BIG             = 109,
   686      ICON_BOX_CONCENTRIC           = 110,
   687      ICON_BOX_GRID_BIG             = 111,
   688      ICON_OK_TICK                  = 112,
   689      ICON_CROSS                    = 113,
   690      ICON_ARROW_LEFT               = 114,
   691      ICON_ARROW_RIGHT              = 115,
   692      ICON_ARROW_DOWN               = 116,
   693      ICON_ARROW_UP                 = 117,
   694      ICON_ARROW_LEFT_FILL          = 118,
   695      ICON_ARROW_RIGHT_FILL         = 119,
   696      ICON_ARROW_DOWN_FILL          = 120,
   697      ICON_ARROW_UP_FILL            = 121,
   698      ICON_AUDIO                    = 122,
   699      ICON_FX                       = 123,
   700      ICON_WAVE                     = 124,
   701      ICON_WAVE_SINUS               = 125,
   702      ICON_WAVE_SQUARE              = 126,
   703      ICON_WAVE_TRIANGULAR          = 127,
   704      ICON_CROSS_SMALL              = 128,
   705      ICON_PLAYER_PREVIOUS          = 129,
   706      ICON_PLAYER_PLAY_BACK         = 130,
   707      ICON_PLAYER_PLAY              = 131,
   708      ICON_PLAYER_PAUSE             = 132,
   709      ICON_PLAYER_STOP              = 133,
   710      ICON_PLAYER_NEXT              = 134,
   711      ICON_PLAYER_RECORD            = 135,
   712      ICON_MAGNET                   = 136,
   713      ICON_LOCK_CLOSE               = 137,
   714      ICON_LOCK_OPEN                = 138,
   715      ICON_CLOCK                    = 139,
   716      ICON_TOOLS                    = 140,
   717      ICON_GEAR                     = 141,
   718      ICON_GEAR_BIG                 = 142,
   719      ICON_BIN                      = 143,
   720      ICON_HAND_POINTER             = 144,
   721      ICON_LASER                    = 145,
   722      ICON_COIN                     = 146,
   723      ICON_EXPLOSION                = 147,
   724      ICON_1UP                      = 148,
   725      ICON_PLAYER                   = 149,
   726      ICON_PLAYER_JUMP              = 150,
   727      ICON_KEY                      = 151,
   728      ICON_DEMON                    = 152,
   729      ICON_TEXT_POPUP               = 153,
   730      ICON_GEAR_EX                  = 154,
   731      ICON_CRACK                    = 155,
   732      ICON_CRACK_POINTS             = 156,
   733      ICON_STAR                     = 157,
   734      ICON_DOOR                     = 158,
   735      ICON_EXIT                     = 159,
   736      ICON_MODE_2D                  = 160,
   737      ICON_MODE_3D                  = 161,
   738      ICON_CUBE                     = 162,
   739      ICON_CUBE_FACE_TOP            = 163,
   740      ICON_CUBE_FACE_LEFT           = 164,
   741      ICON_CUBE_FACE_FRONT          = 165,
   742      ICON_CUBE_FACE_BOTTOM         = 166,
   743      ICON_CUBE_FACE_RIGHT          = 167,
   744      ICON_CUBE_FACE_BACK           = 168,
   745      ICON_CAMERA                   = 169,
   746      ICON_SPECIAL                  = 170,
   747      ICON_LINK_NET                 = 171,
   748      ICON_LINK_BOXES               = 172,
   749      ICON_LINK_MULTI               = 173,
   750      ICON_LINK                     = 174,
   751      ICON_LINK_BROKE               = 175,
   752      ICON_TEXT_NOTES               = 176,
   753      ICON_NOTEBOOK                 = 177,
   754      ICON_SUITCASE                 = 178,
   755      ICON_SUITCASE_ZIP             = 179,
   756      ICON_MAILBOX                  = 180,
   757      ICON_MONITOR                  = 181,
   758      ICON_PRINTER                  = 182,
   759      ICON_PHOTO_CAMERA             = 183,
   760      ICON_PHOTO_CAMERA_FLASH       = 184,
   761      ICON_HOUSE                    = 185,
   762      ICON_HEART                    = 186,
   763      ICON_CORNER                   = 187,
   764      ICON_VERTICAL_BARS            = 188,
   765      ICON_VERTICAL_BARS_FILL       = 189,
   766      ICON_LIFE_BARS                = 190,
   767      ICON_INFO                     = 191,
   768      ICON_CROSSLINE                = 192,
   769      ICON_HELP                     = 193,
   770      ICON_FILETYPE_ALPHA           = 194,
   771      ICON_FILETYPE_HOME            = 195,
   772      ICON_LAYERS_VISIBLE           = 196,
   773      ICON_LAYERS                   = 197,
   774      ICON_WINDOW                   = 198,
   775      ICON_HIDPI                    = 199,
   776      ICON_FILETYPE_BINARY          = 200,
   777      ICON_HEX                      = 201,
   778      ICON_SHIELD                   = 202,
   779      ICON_FILE_NEW                 = 203,
   780      ICON_FOLDER_ADD               = 204,
   781      ICON_ALARM                    = 205,
   782      ICON_CPU                      = 206,
   783      ICON_ROM                      = 207,
   784      ICON_STEP_OVER                = 208,
   785      ICON_STEP_INTO                = 209,
   786      ICON_STEP_OUT                 = 210,
   787      ICON_RESTART                  = 211,
   788      ICON_BREAKPOINT_ON            = 212,
   789      ICON_BREAKPOINT_OFF           = 213,
   790      ICON_BURGER_MENU              = 214,
   791      ICON_CASE_SENSITIVE           = 215,
   792      ICON_REG_EXP                  = 216,
   793      ICON_FOLDER                   = 217,
   794      ICON_FILE                     = 218,
   795      ICON_219                      = 219,
   796      ICON_220                      = 220,
   797      ICON_221                      = 221,
   798      ICON_222                      = 222,
   799      ICON_223                      = 223,
   800      ICON_224                      = 224,
   801      ICON_225                      = 225,
   802      ICON_226                      = 226,
   803      ICON_227                      = 227,
   804      ICON_228                      = 228,
   805      ICON_229                      = 229,
   806      ICON_230                      = 230,
   807      ICON_231                      = 231,
   808      ICON_232                      = 232,
   809      ICON_233                      = 233,
   810      ICON_234                      = 234,
   811      ICON_235                      = 235,
   812      ICON_236                      = 236,
   813      ICON_237                      = 237,
   814      ICON_238                      = 238,
   815      ICON_239                      = 239,
   816      ICON_240                      = 240,
   817      ICON_241                      = 241,
   818      ICON_242                      = 242,
   819      ICON_243                      = 243,
   820      ICON_244                      = 244,
   821      ICON_245                      = 245,
   822      ICON_246                      = 246,
   823      ICON_247                      = 247,
   824      ICON_248                      = 248,
   825      ICON_249                      = 249,
   826      ICON_250                      = 250,
   827      ICON_251                      = 251,
   828      ICON_252                      = 252,
   829      ICON_253                      = 253,
   830      ICON_254                      = 254,
   831      ICON_255                      = 255,
   832  } GuiIconName;
   833  #endif
   834  
   835  #endif
   836  
   837  #if defined(__cplusplus)
   838  }            // Prevents name mangling of functions
   839  #endif
   840  
   841  #endif // RAYGUI_H
   842  
   843  /***********************************************************************************
   844  *
   845  *   RAYGUI IMPLEMENTATION
   846  *
   847  ************************************************************************************/
   848  
   849  #if defined(RAYGUI_IMPLEMENTATION)
   850  
   851  #include <stdio.h>              // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()]
   852  #include <stdlib.h>             // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()]
   853  #include <string.h>             // Required for: strlen() [GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()], memset(), memcpy()
   854  #include <stdarg.h>             // Required for: va_list, va_start(), vfprintf(), va_end() [TextFormat()]
   855  #include <math.h>               // Required for: roundf() [GuiColorPicker()]
   856  
   857  #ifdef __cplusplus
   858      #define RAYGUI_CLITERAL(name) name
   859  #else
   860      #define RAYGUI_CLITERAL(name) (name)
   861  #endif
   862  
   863  #if !defined(RAYGUI_NO_ICONS) && !defined(RAYGUI_CUSTOM_ICONS)
   864  
   865  // Embedded icons, no external file provided
   866  #define RAYGUI_ICON_SIZE               16          // Size of icons in pixels (squared)
   867  #define RAYGUI_ICON_MAX_ICONS         256          // Maximum number of icons
   868  #define RAYGUI_ICON_MAX_NAME_LENGTH    32          // Maximum length of icon name id
   869  
   870  // Icons data is defined by bit array (every bit represents one pixel)
   871  // Those arrays are stored as unsigned int data arrays, so,
   872  // every array element defines 32 pixels (bits) of information
   873  // One icon is defined by 8 int, (8 int * 32 bit = 256 bit = 16*16 pixels)
   874  // NOTE: Number of elemens depend on RAYGUI_ICON_SIZE (by default 16x16 pixels)
   875  #define RAYGUI_ICON_DATA_ELEMENTS   (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32)
   876  
   877  //----------------------------------------------------------------------------------
   878  // Icons data for all gui possible icons (allocated on data segment by default)
   879  //
   880  // NOTE 1: Every icon is codified in binary form, using 1 bit per pixel, so,
   881  // every 16x16 icon requires 8 integers (16*16/32) to be stored
   882  //
   883  // NOTE 2: A different icon set could be loaded over this array using GuiLoadIcons(),
   884  // but loaded icons set must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS
   885  //
   886  // guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB
   887  //----------------------------------------------------------------------------------
   888  static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = {
   889      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_NONE
   890      0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe,      // ICON_FOLDER_FILE_OPEN
   891      0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe,      // ICON_FILE_SAVE_CLASSIC
   892      0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024002, 0x44424282, 0x793e4102, 0x00000100,      // ICON_FOLDER_OPEN
   893      0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024102, 0x44424102, 0x793e4282, 0x00000000,      // ICON_FOLDER_SAVE
   894      0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x24442284, 0x21042104, 0x20042104, 0x00003ffc,      // ICON_FILE_OPEN
   895      0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x21042104, 0x22842444, 0x20042104, 0x00003ffc,      // ICON_FILE_SAVE
   896      0x3ff00000, 0x201c2010, 0x00042004, 0x20041004, 0x20844784, 0x00841384, 0x20042784, 0x00003ffc,      // ICON_FILE_EXPORT
   897      0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x22042204, 0x22042f84, 0x20042204, 0x00003ffc,      // ICON_FILE_ADD
   898      0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x25042884, 0x25042204, 0x20042884, 0x00003ffc,      // ICON_FILE_DELETE
   899      0x3ff00000, 0x201c2010, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc,      // ICON_FILETYPE_TEXT
   900      0x3ff00000, 0x201c2010, 0x27042004, 0x244424c4, 0x26442444, 0x20642664, 0x20042004, 0x00003ffc,      // ICON_FILETYPE_AUDIO
   901      0x3ff00000, 0x201c2010, 0x26042604, 0x20042004, 0x35442884, 0x2414222c, 0x20042004, 0x00003ffc,      // ICON_FILETYPE_IMAGE
   902      0x3ff00000, 0x201c2010, 0x20c42004, 0x22442144, 0x22442444, 0x20c42144, 0x20042004, 0x00003ffc,      // ICON_FILETYPE_PLAY
   903      0x3ff00000, 0x3ffc2ff0, 0x3f3c2ff4, 0x3dbc2eb4, 0x3dbc2bb4, 0x3f3c2eb4, 0x3ffc2ff4, 0x00002ff4,      // ICON_FILETYPE_VIDEO
   904      0x3ff00000, 0x201c2010, 0x21842184, 0x21842004, 0x21842184, 0x21842184, 0x20042184, 0x00003ffc,      // ICON_FILETYPE_INFO
   905      0x0ff00000, 0x381c0810, 0x28042804, 0x28042804, 0x28042804, 0x28042804, 0x20102ffc, 0x00003ff0,      // ICON_FILE_COPY
   906      0x00000000, 0x701c0000, 0x079c1e14, 0x55a000f0, 0x079c00f0, 0x701c1e14, 0x00000000, 0x00000000,      // ICON_FILE_CUT
   907      0x01c00000, 0x13e41bec, 0x3f841004, 0x204420c4, 0x20442044, 0x20442044, 0x207c2044, 0x00003fc0,      // ICON_FILE_PASTE
   908      0x00000000, 0x3aa00fe0, 0x2abc2aa0, 0x2aa42aa4, 0x20042aa4, 0x20042004, 0x3ffc2004, 0x00000000,      // ICON_CURSOR_HAND
   909      0x00000000, 0x003c000c, 0x030800c8, 0x30100c10, 0x10202020, 0x04400840, 0x01800280, 0x00000000,      // ICON_CURSOR_POINTER
   910      0x00000000, 0x00180000, 0x01f00078, 0x03e007f0, 0x07c003e0, 0x04000e40, 0x00000000, 0x00000000,      // ICON_CURSOR_CLASSIC
   911      0x00000000, 0x04000000, 0x11000a00, 0x04400a80, 0x01100220, 0x00580088, 0x00000038, 0x00000000,      // ICON_PENCIL
   912      0x04000000, 0x15000a00, 0x50402880, 0x14102820, 0x05040a08, 0x015c028c, 0x007c00bc, 0x00000000,      // ICON_PENCIL_BIG
   913      0x01c00000, 0x01400140, 0x01400140, 0x0ff80140, 0x0ff80808, 0x0aa80808, 0x0aa80aa8, 0x00000ff8,      // ICON_BRUSH_CLASSIC
   914      0x1ffc0000, 0x5ffc7ffe, 0x40004000, 0x00807f80, 0x01c001c0, 0x01c001c0, 0x01c001c0, 0x00000080,      // ICON_BRUSH_PAINTER
   915      0x00000000, 0x00800000, 0x01c00080, 0x03e001c0, 0x07f003e0, 0x036006f0, 0x000001c0, 0x00000000,      // ICON_WATER_DROP
   916      0x00000000, 0x3e003800, 0x1f803f80, 0x0c201e40, 0x02080c10, 0x00840104, 0x00380044, 0x00000000,      // ICON_COLOR_PICKER
   917      0x00000000, 0x07800300, 0x1fe00fc0, 0x3f883fd0, 0x0e021f04, 0x02040402, 0x00f00108, 0x00000000,      // ICON_RUBBER
   918      0x00c00000, 0x02800140, 0x08200440, 0x20081010, 0x2ffe3004, 0x03f807fc, 0x00e001f0, 0x00000040,      // ICON_COLOR_BUCKET
   919      0x00000000, 0x21843ffc, 0x01800180, 0x01800180, 0x01800180, 0x01800180, 0x03c00180, 0x00000000,      // ICON_TEXT_T
   920      0x00800000, 0x01400180, 0x06200340, 0x0c100620, 0x1ff80c10, 0x380c1808, 0x70067004, 0x0000f80f,      // ICON_TEXT_A
   921      0x78000000, 0x50004000, 0x00004800, 0x03c003c0, 0x03c003c0, 0x00100000, 0x0002000a, 0x0000000e,      // ICON_SCALE
   922      0x75560000, 0x5e004002, 0x54001002, 0x41001202, 0x408200fe, 0x40820082, 0x40820082, 0x00006afe,      // ICON_RESIZE
   923      0x00000000, 0x3f003f00, 0x3f003f00, 0x3f003f00, 0x00400080, 0x001c0020, 0x001c001c, 0x00000000,      // ICON_FILTER_POINT
   924      0x6d800000, 0x00004080, 0x40804080, 0x40800000, 0x00406d80, 0x001c0020, 0x001c001c, 0x00000000,      // ICON_FILTER_BILINEAR
   925      0x40080000, 0x1ffe2008, 0x14081008, 0x11081208, 0x10481088, 0x10081028, 0x10047ff8, 0x00001002,      // ICON_CROP
   926      0x00100000, 0x3ffc0010, 0x2ab03550, 0x22b02550, 0x20b02150, 0x20302050, 0x2000fff0, 0x00002000,      // ICON_CROP_ALPHA
   927      0x40000000, 0x1ff82000, 0x04082808, 0x01082208, 0x00482088, 0x00182028, 0x35542008, 0x00000002,      // ICON_SQUARE_TOGGLE
   928      0x00000000, 0x02800280, 0x06c006c0, 0x0ea00ee0, 0x1e901eb0, 0x3e883e98, 0x7efc7e8c, 0x00000000,      // ICON_SYMMETRY
   929      0x01000000, 0x05600100, 0x1d480d50, 0x7d423d44, 0x3d447d42, 0x0d501d48, 0x01000560, 0x00000100,      // ICON_SYMMETRY_HORIZONTAL
   930      0x01800000, 0x04200240, 0x10080810, 0x00001ff8, 0x00007ffe, 0x0ff01ff8, 0x03c007e0, 0x00000180,      // ICON_SYMMETRY_VERTICAL
   931      0x00000000, 0x010800f0, 0x02040204, 0x02040204, 0x07f00308, 0x1c000e00, 0x30003800, 0x00000000,      // ICON_LENS
   932      0x00000000, 0x061803f0, 0x08240c0c, 0x08040814, 0x0c0c0804, 0x23f01618, 0x18002400, 0x00000000,      // ICON_LENS_BIG
   933      0x00000000, 0x00000000, 0x1c7007c0, 0x638e3398, 0x1c703398, 0x000007c0, 0x00000000, 0x00000000,      // ICON_EYE_ON
   934      0x00000000, 0x10002000, 0x04700fc0, 0x610e3218, 0x1c703098, 0x001007a0, 0x00000008, 0x00000000,      // ICON_EYE_OFF
   935      0x00000000, 0x00007ffc, 0x40047ffc, 0x10102008, 0x04400820, 0x02800280, 0x02800280, 0x00000100,      // ICON_FILTER_TOP
   936      0x00000000, 0x40027ffe, 0x10082004, 0x04200810, 0x02400240, 0x02400240, 0x01400240, 0x000000c0,      // ICON_FILTER
   937      0x00800000, 0x00800080, 0x00000080, 0x3c9e0000, 0x00000000, 0x00800080, 0x00800080, 0x00000000,      // ICON_TARGET_POINT
   938      0x00800000, 0x00800080, 0x00800080, 0x3f7e01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000,      // ICON_TARGET_SMALL
   939      0x00800000, 0x00800080, 0x03e00080, 0x3e3e0220, 0x03e00220, 0x00800080, 0x00800080, 0x00000000,      // ICON_TARGET_BIG
   940      0x01000000, 0x04400280, 0x01000100, 0x43842008, 0x43849ab2, 0x01002008, 0x04400100, 0x01000280,      // ICON_TARGET_MOVE
   941      0x01000000, 0x04400280, 0x01000100, 0x41042108, 0x41049ff2, 0x01002108, 0x04400100, 0x01000280,      // ICON_CURSOR_MOVE
   942      0x781e0000, 0x500a4002, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x4002500a, 0x0000781e,      // ICON_CURSOR_SCALE
   943      0x00000000, 0x20003c00, 0x24002800, 0x01000200, 0x00400080, 0x00140024, 0x003c0004, 0x00000000,      // ICON_CURSOR_SCALE_RIGHT
   944      0x00000000, 0x0004003c, 0x00240014, 0x00800040, 0x02000100, 0x28002400, 0x3c002000, 0x00000000,      // ICON_CURSOR_SCALE_LEFT
   945      0x00000000, 0x00100020, 0x10101fc8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000,      // ICON_UNDO
   946      0x00000000, 0x08000400, 0x080813f8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000,      // ICON_REDO
   947      0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3f902020, 0x00400020, 0x00000000,      // ICON_REREDO
   948      0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3fc82010, 0x00200010, 0x00000000,      // ICON_MUTATE
   949      0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18101020, 0x00100fc8, 0x00000020,      // ICON_ROTATE
   950      0x00000000, 0x04000200, 0x240429fc, 0x20042204, 0x20442004, 0x3f942024, 0x00400020, 0x00000000,      // ICON_REPEAT
   951      0x00000000, 0x20001000, 0x22104c0e, 0x00801120, 0x11200040, 0x4c0e2210, 0x10002000, 0x00000000,      // ICON_SHUFFLE
   952      0x7ffe0000, 0x50024002, 0x44024802, 0x41024202, 0x40424082, 0x40124022, 0x4002400a, 0x00007ffe,      // ICON_EMPTYBOX
   953      0x00800000, 0x03e00080, 0x08080490, 0x3c9e0808, 0x08080808, 0x03e00490, 0x00800080, 0x00000000,      // ICON_TARGET
   954      0x00800000, 0x00800080, 0x00800080, 0x3ffe01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000,      // ICON_TARGET_SMALL_FILL
   955      0x00800000, 0x00800080, 0x03e00080, 0x3ffe03e0, 0x03e003e0, 0x00800080, 0x00800080, 0x00000000,      // ICON_TARGET_BIG_FILL
   956      0x01000000, 0x07c00380, 0x01000100, 0x638c2008, 0x638cfbbe, 0x01002008, 0x07c00100, 0x01000380,      // ICON_TARGET_MOVE_FILL
   957      0x01000000, 0x07c00380, 0x01000100, 0x610c2108, 0x610cfffe, 0x01002108, 0x07c00100, 0x01000380,      // ICON_CURSOR_MOVE_FILL
   958      0x781e0000, 0x6006700e, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x700e6006, 0x0000781e,      // ICON_CURSOR_SCALE_FILL
   959      0x00000000, 0x38003c00, 0x24003000, 0x01000200, 0x00400080, 0x000c0024, 0x003c001c, 0x00000000,      // ICON_CURSOR_SCALE_RIGHT_FILL
   960      0x00000000, 0x001c003c, 0x0024000c, 0x00800040, 0x02000100, 0x30002400, 0x3c003800, 0x00000000,      // ICON_CURSOR_SCALE_LEFT_FILL
   961      0x00000000, 0x00300020, 0x10301ff8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000,      // ICON_UNDO_FILL
   962      0x00000000, 0x0c000400, 0x0c081ff8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000,      // ICON_REDO_FILL
   963      0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3ff02060, 0x00400060, 0x00000000,      // ICON_REREDO_FILL
   964      0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3ff82030, 0x00200030, 0x00000000,      // ICON_MUTATE_FILL
   965      0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18301020, 0x00300ff8, 0x00000020,      // ICON_ROTATE_FILL
   966      0x00000000, 0x06000200, 0x26042ffc, 0x20042204, 0x20442004, 0x3ff42064, 0x00400060, 0x00000000,      // ICON_REPEAT_FILL
   967      0x00000000, 0x30001000, 0x32107c0e, 0x00801120, 0x11200040, 0x7c0e3210, 0x10003000, 0x00000000,      // ICON_SHUFFLE_FILL
   968      0x00000000, 0x30043ffc, 0x24042804, 0x21042204, 0x20442084, 0x20142024, 0x3ffc200c, 0x00000000,      // ICON_EMPTYBOX_SMALL
   969      0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000,      // ICON_BOX
   970      0x00000000, 0x23c43ffc, 0x23c423c4, 0x200423c4, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000,      // ICON_BOX_TOP
   971      0x00000000, 0x3e043ffc, 0x3e043e04, 0x20043e04, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000,      // ICON_BOX_TOP_RIGHT
   972      0x00000000, 0x20043ffc, 0x20042004, 0x3e043e04, 0x3e043e04, 0x20042004, 0x3ffc2004, 0x00000000,      // ICON_BOX_RIGHT
   973      0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x3e042004, 0x3e043e04, 0x3ffc3e04, 0x00000000,      // ICON_BOX_BOTTOM_RIGHT
   974      0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x23c42004, 0x23c423c4, 0x3ffc23c4, 0x00000000,      // ICON_BOX_BOTTOM
   975      0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x207c2004, 0x207c207c, 0x3ffc207c, 0x00000000,      // ICON_BOX_BOTTOM_LEFT
   976      0x00000000, 0x20043ffc, 0x20042004, 0x207c207c, 0x207c207c, 0x20042004, 0x3ffc2004, 0x00000000,      // ICON_BOX_LEFT
   977      0x00000000, 0x207c3ffc, 0x207c207c, 0x2004207c, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000,      // ICON_BOX_TOP_LEFT
   978      0x00000000, 0x20043ffc, 0x20042004, 0x23c423c4, 0x23c423c4, 0x20042004, 0x3ffc2004, 0x00000000,      // ICON_BOX_CENTER
   979      0x7ffe0000, 0x40024002, 0x47e24182, 0x4ff247e2, 0x47e24ff2, 0x418247e2, 0x40024002, 0x00007ffe,      // ICON_BOX_CIRCLE_MASK
   980      0x7fff0000, 0x40014001, 0x40014001, 0x49555ddd, 0x4945495d, 0x400149c5, 0x40014001, 0x00007fff,      // ICON_POT
   981      0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x404e40ce, 0x48125432, 0x4006540e, 0x00007ffe,      // ICON_ALPHA_MULTIPLY
   982      0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x5c4e40ce, 0x44124432, 0x40065c0e, 0x00007ffe,      // ICON_ALPHA_CLEAR
   983      0x7ffe0000, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x00007ffe,      // ICON_DITHERING
   984      0x07fe0000, 0x1ffa0002, 0x7fea000a, 0x402a402a, 0x5b2a512a, 0x5128552a, 0x40205128, 0x00007fe0,      // ICON_MIPMAPS
   985      0x00000000, 0x1ff80000, 0x12481248, 0x12481ff8, 0x1ff81248, 0x12481248, 0x00001ff8, 0x00000000,      // ICON_BOX_GRID
   986      0x12480000, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x00001248,      // ICON_GRID
   987      0x00000000, 0x1c380000, 0x1c3817e8, 0x08100810, 0x08100810, 0x17e81c38, 0x00001c38, 0x00000000,      // ICON_BOX_CORNERS_SMALL
   988      0x700e0000, 0x700e5ffa, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x5ffa700e, 0x0000700e,      // ICON_BOX_CORNERS_BIG
   989      0x3f7e0000, 0x21422142, 0x21422142, 0x00003f7e, 0x21423f7e, 0x21422142, 0x3f7e2142, 0x00000000,      // ICON_FOUR_BOXES
   990      0x00000000, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x00000000,      // ICON_GRID_FILL
   991      0x7ffe0000, 0x7ffe7ffe, 0x77fe7000, 0x77fe77fe, 0x777e7700, 0x777e777e, 0x777e777e, 0x0000777e,      // ICON_BOX_MULTISIZE
   992      0x781e0000, 0x40024002, 0x00004002, 0x01800000, 0x00000180, 0x40020000, 0x40024002, 0x0000781e,      // ICON_ZOOM_SMALL
   993      0x781e0000, 0x40024002, 0x00004002, 0x03c003c0, 0x03c003c0, 0x40020000, 0x40024002, 0x0000781e,      // ICON_ZOOM_MEDIUM
   994      0x781e0000, 0x40024002, 0x07e04002, 0x07e007e0, 0x07e007e0, 0x400207e0, 0x40024002, 0x0000781e,      // ICON_ZOOM_BIG
   995      0x781e0000, 0x5ffa4002, 0x1ff85ffa, 0x1ff81ff8, 0x1ff81ff8, 0x5ffa1ff8, 0x40025ffa, 0x0000781e,      // ICON_ZOOM_ALL
   996      0x00000000, 0x2004381c, 0x00002004, 0x00000000, 0x00000000, 0x20040000, 0x381c2004, 0x00000000,      // ICON_ZOOM_CENTER
   997      0x00000000, 0x1db80000, 0x10081008, 0x10080000, 0x00001008, 0x10081008, 0x00001db8, 0x00000000,      // ICON_BOX_DOTS_SMALL
   998      0x35560000, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x35562002, 0x00000000,      // ICON_BOX_DOTS_BIG
   999      0x7ffe0000, 0x40024002, 0x48124ff2, 0x49924812, 0x48124992, 0x4ff24812, 0x40024002, 0x00007ffe,      // ICON_BOX_CONCENTRIC
  1000      0x00000000, 0x10841ffc, 0x10841084, 0x1ffc1084, 0x10841084, 0x10841084, 0x00001ffc, 0x00000000,      // ICON_BOX_GRID_BIG
  1001      0x00000000, 0x00000000, 0x10000000, 0x04000800, 0x01040200, 0x00500088, 0x00000020, 0x00000000,      // ICON_OK_TICK
  1002      0x00000000, 0x10080000, 0x04200810, 0x01800240, 0x02400180, 0x08100420, 0x00001008, 0x00000000,      // ICON_CROSS
  1003      0x00000000, 0x02000000, 0x00800100, 0x00200040, 0x00200010, 0x00800040, 0x02000100, 0x00000000,      // ICON_ARROW_LEFT
  1004      0x00000000, 0x00400000, 0x01000080, 0x04000200, 0x04000800, 0x01000200, 0x00400080, 0x00000000,      // ICON_ARROW_RIGHT
  1005      0x00000000, 0x00000000, 0x00000000, 0x08081004, 0x02200410, 0x00800140, 0x00000000, 0x00000000,      // ICON_ARROW_DOWN
  1006      0x00000000, 0x00000000, 0x01400080, 0x04100220, 0x10040808, 0x00000000, 0x00000000, 0x00000000,      // ICON_ARROW_UP
  1007      0x00000000, 0x02000000, 0x03800300, 0x03e003c0, 0x03e003f0, 0x038003c0, 0x02000300, 0x00000000,      // ICON_ARROW_LEFT_FILL
  1008      0x00000000, 0x00400000, 0x01c000c0, 0x07c003c0, 0x07c00fc0, 0x01c003c0, 0x004000c0, 0x00000000,      // ICON_ARROW_RIGHT_FILL
  1009      0x00000000, 0x00000000, 0x00000000, 0x0ff81ffc, 0x03e007f0, 0x008001c0, 0x00000000, 0x00000000,      // ICON_ARROW_DOWN_FILL
  1010      0x00000000, 0x00000000, 0x01c00080, 0x07f003e0, 0x1ffc0ff8, 0x00000000, 0x00000000, 0x00000000,      // ICON_ARROW_UP_FILL
  1011      0x00000000, 0x18a008c0, 0x32881290, 0x24822686, 0x26862482, 0x12903288, 0x08c018a0, 0x00000000,      // ICON_AUDIO
  1012      0x00000000, 0x04800780, 0x004000c0, 0x662000f0, 0x08103c30, 0x130a0e18, 0x0000318e, 0x00000000,      // ICON_FX
  1013      0x00000000, 0x00800000, 0x08880888, 0x2aaa0a8a, 0x0a8a2aaa, 0x08880888, 0x00000080, 0x00000000,      // ICON_WAVE
  1014      0x00000000, 0x00600000, 0x01080090, 0x02040108, 0x42044204, 0x24022402, 0x00001800, 0x00000000,      // ICON_WAVE_SINUS
  1015      0x00000000, 0x07f80000, 0x04080408, 0x04080408, 0x04080408, 0x7c0e0408, 0x00000000, 0x00000000,      // ICON_WAVE_SQUARE
  1016      0x00000000, 0x00000000, 0x00a00040, 0x22084110, 0x08021404, 0x00000000, 0x00000000, 0x00000000,      // ICON_WAVE_TRIANGULAR
  1017      0x00000000, 0x00000000, 0x04200000, 0x01800240, 0x02400180, 0x00000420, 0x00000000, 0x00000000,      // ICON_CROSS_SMALL
  1018      0x00000000, 0x18380000, 0x12281428, 0x10a81128, 0x112810a8, 0x14281228, 0x00001838, 0x00000000,      // ICON_PLAYER_PREVIOUS
  1019      0x00000000, 0x18000000, 0x11801600, 0x10181060, 0x10601018, 0x16001180, 0x00001800, 0x00000000,      // ICON_PLAYER_PLAY_BACK
  1020      0x00000000, 0x00180000, 0x01880068, 0x18080608, 0x06081808, 0x00680188, 0x00000018, 0x00000000,      // ICON_PLAYER_PLAY
  1021      0x00000000, 0x1e780000, 0x12481248, 0x12481248, 0x12481248, 0x12481248, 0x00001e78, 0x00000000,      // ICON_PLAYER_PAUSE
  1022      0x00000000, 0x1ff80000, 0x10081008, 0x10081008, 0x10081008, 0x10081008, 0x00001ff8, 0x00000000,      // ICON_PLAYER_STOP
  1023      0x00000000, 0x1c180000, 0x14481428, 0x15081488, 0x14881508, 0x14281448, 0x00001c18, 0x00000000,      // ICON_PLAYER_NEXT
  1024      0x00000000, 0x03c00000, 0x08100420, 0x10081008, 0x10081008, 0x04200810, 0x000003c0, 0x00000000,      // ICON_PLAYER_RECORD
  1025      0x00000000, 0x0c3007e0, 0x13c81818, 0x14281668, 0x14281428, 0x1c381c38, 0x08102244, 0x00000000,      // ICON_MAGNET
  1026      0x07c00000, 0x08200820, 0x3ff80820, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000,      // ICON_LOCK_CLOSE
  1027      0x07c00000, 0x08000800, 0x3ff80800, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000,      // ICON_LOCK_OPEN
  1028      0x01c00000, 0x0c180770, 0x3086188c, 0x60832082, 0x60034781, 0x30062002, 0x0c18180c, 0x01c00770,      // ICON_CLOCK
  1029      0x0a200000, 0x1b201b20, 0x04200e20, 0x04200420, 0x04700420, 0x0e700e70, 0x0e700e70, 0x04200e70,      // ICON_TOOLS
  1030      0x01800000, 0x3bdc318c, 0x0ff01ff8, 0x7c3e1e78, 0x1e787c3e, 0x1ff80ff0, 0x318c3bdc, 0x00000180,      // ICON_GEAR
  1031      0x01800000, 0x3ffc318c, 0x1c381ff8, 0x781e1818, 0x1818781e, 0x1ff81c38, 0x318c3ffc, 0x00000180,      // ICON_GEAR_BIG
  1032      0x00000000, 0x08080ff8, 0x08081ffc, 0x0aa80aa8, 0x0aa80aa8, 0x0aa80aa8, 0x08080aa8, 0x00000ff8,      // ICON_BIN
  1033      0x00000000, 0x00000000, 0x20043ffc, 0x08043f84, 0x04040f84, 0x04040784, 0x000007fc, 0x00000000,      // ICON_HAND_POINTER
  1034      0x00000000, 0x24400400, 0x00001480, 0x6efe0e00, 0x00000e00, 0x24401480, 0x00000400, 0x00000000,      // ICON_LASER
  1035      0x00000000, 0x03c00000, 0x08300460, 0x11181118, 0x11181118, 0x04600830, 0x000003c0, 0x00000000,      // ICON_COIN
  1036      0x00000000, 0x10880080, 0x06c00810, 0x366c07e0, 0x07e00240, 0x00001768, 0x04200240, 0x00000000,      // ICON_EXPLOSION
  1037      0x00000000, 0x3d280000, 0x2528252c, 0x3d282528, 0x05280528, 0x05e80528, 0x00000000, 0x00000000,      // ICON_1UP
  1038      0x01800000, 0x03c003c0, 0x018003c0, 0x0ff007e0, 0x0bd00bd0, 0x0a500bd0, 0x02400240, 0x02400240,      // ICON_PLAYER
  1039      0x01800000, 0x03c003c0, 0x118013c0, 0x03c81ff8, 0x07c003c8, 0x04400440, 0x0c080478, 0x00000000,      // ICON_PLAYER_JUMP
  1040      0x3ff80000, 0x30183ff8, 0x30183018, 0x3ff83ff8, 0x03000300, 0x03c003c0, 0x03e00300, 0x000003e0,      // ICON_KEY
  1041      0x3ff80000, 0x3ff83ff8, 0x33983ff8, 0x3ff83398, 0x3ff83ff8, 0x00000540, 0x0fe00aa0, 0x00000fe0,      // ICON_DEMON
  1042      0x00000000, 0x0ff00000, 0x20041008, 0x25442004, 0x10082004, 0x06000bf0, 0x00000300, 0x00000000,      // ICON_TEXT_POPUP
  1043      0x00000000, 0x11440000, 0x07f00be8, 0x1c1c0e38, 0x1c1c0c18, 0x07f00e38, 0x11440be8, 0x00000000,      // ICON_GEAR_EX
  1044      0x00000000, 0x20080000, 0x0c601010, 0x07c00fe0, 0x07c007c0, 0x0c600fe0, 0x20081010, 0x00000000,      // ICON_CRACK
  1045      0x00000000, 0x20080000, 0x0c601010, 0x04400fe0, 0x04405554, 0x0c600fe0, 0x20081010, 0x00000000,      // ICON_CRACK_POINTS
  1046      0x00000000, 0x00800080, 0x01c001c0, 0x1ffc3ffe, 0x03e007f0, 0x07f003e0, 0x0c180770, 0x00000808,      // ICON_STAR
  1047      0x0ff00000, 0x08180810, 0x08100818, 0x0a100810, 0x08180810, 0x08100818, 0x08100810, 0x00001ff8,      // ICON_DOOR
  1048      0x0ff00000, 0x08100810, 0x08100810, 0x10100010, 0x4f902010, 0x10102010, 0x08100010, 0x00000ff0,      // ICON_EXIT
  1049      0x00040000, 0x001f000e, 0x0ef40004, 0x12f41284, 0x0ef41214, 0x10040004, 0x7ffc3004, 0x10003000,      // ICON_MODE_2D
  1050      0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000,      // ICON_MODE_3D
  1051      0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe,      // ICON_CUBE
  1052      0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe,      // ICON_CUBE_FACE_TOP
  1053      0x7fe00000, 0x50386030, 0x47fe483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe,      // ICON_CUBE_FACE_LEFT
  1054      0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe,      // ICON_CUBE_FACE_FRONT
  1055      0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3ff27fe2, 0x0ffe1ffa, 0x000007fe,      // ICON_CUBE_FACE_BOTTOM
  1056      0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe,      // ICON_CUBE_FACE_RIGHT
  1057      0x7fe00000, 0x7fe87ff0, 0x7ffe7fe4, 0x7fe27fe2, 0x7fe27fe2, 0x24127fe2, 0x0c06140a, 0x000007fe,      // ICON_CUBE_FACE_BACK
  1058      0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000,      // ICON_CAMERA
  1059      0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000,      // ICON_SPECIAL
  1060      0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800,      // ICON_LINK_NET
  1061      0x00000000, 0x44007c00, 0x45004600, 0x00627cbe, 0x00620022, 0x45007cbe, 0x44004600, 0x00007c00,      // ICON_LINK_BOXES
  1062      0x00000000, 0x0044007c, 0x0010007c, 0x3f100010, 0x3f1021f0, 0x3f100010, 0x3f0021f0, 0x00000000,      // ICON_LINK_MULTI
  1063      0x00000000, 0x0044007c, 0x00440044, 0x0010007c, 0x00100010, 0x44107c10, 0x440047f0, 0x00007c00,      // ICON_LINK
  1064      0x00000000, 0x0044007c, 0x00440044, 0x0000007c, 0x00000010, 0x44007c10, 0x44004550, 0x00007c00,      // ICON_LINK_BROKE
  1065      0x02a00000, 0x22a43ffc, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc,      // ICON_TEXT_NOTES
  1066      0x3ffc0000, 0x20042004, 0x245e27c4, 0x27c42444, 0x2004201e, 0x201e2004, 0x20042004, 0x00003ffc,      // ICON_NOTEBOOK
  1067      0x00000000, 0x07e00000, 0x04200420, 0x24243ffc, 0x24242424, 0x24242424, 0x3ffc2424, 0x00000000,      // ICON_SUITCASE
  1068      0x00000000, 0x0fe00000, 0x08200820, 0x40047ffc, 0x7ffc5554, 0x40045554, 0x7ffc4004, 0x00000000,      // ICON_SUITCASE_ZIP
  1069      0x00000000, 0x20043ffc, 0x3ffc2004, 0x13c81008, 0x100813c8, 0x10081008, 0x1ff81008, 0x00000000,      // ICON_MAILBOX
  1070      0x00000000, 0x40027ffe, 0x5ffa5ffa, 0x5ffa5ffa, 0x40025ffa, 0x03c07ffe, 0x1ff81ff8, 0x00000000,      // ICON_MONITOR
  1071      0x0ff00000, 0x6bfe7ffe, 0x7ffe7ffe, 0x68167ffe, 0x08106816, 0x08100810, 0x0ff00810, 0x00000000,      // ICON_PRINTER
  1072      0x3ff80000, 0xfffe2008, 0x870a8002, 0x904a888a, 0x904a904a, 0x870a888a, 0xfffe8002, 0x00000000,      // ICON_PHOTO_CAMERA
  1073      0x0fc00000, 0xfcfe0cd8, 0x8002fffe, 0x84428382, 0x84428442, 0x80028382, 0xfffe8002, 0x00000000,      // ICON_PHOTO_CAMERA_FLASH
  1074      0x00000000, 0x02400180, 0x08100420, 0x20041008, 0x23c42004, 0x22442244, 0x3ffc2244, 0x00000000,      // ICON_HOUSE
  1075      0x00000000, 0x1c700000, 0x3ff83ef8, 0x3ff83ff8, 0x0fe01ff0, 0x038007c0, 0x00000100, 0x00000000,      // ICON_HEART
  1076      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe000c000,      // ICON_CORNER
  1077      0x00000000, 0x14001c00, 0x15c01400, 0x15401540, 0x155c1540, 0x15541554, 0x1ddc1554, 0x00000000,      // ICON_VERTICAL_BARS
  1078      0x00000000, 0x03000300, 0x1b001b00, 0x1b601b60, 0x1b6c1b60, 0x1b6c1b6c, 0x1b6c1b6c, 0x00000000,      // ICON_VERTICAL_BARS_FILL
  1079      0x00000000, 0x00000000, 0x403e7ffe, 0x7ffe403e, 0x7ffe0000, 0x43fe43fe, 0x00007ffe, 0x00000000,      // ICON_LIFE_BARS
  1080      0x7ffc0000, 0x43844004, 0x43844284, 0x43844004, 0x42844284, 0x42844284, 0x40044384, 0x00007ffc,      // ICON_INFO
  1081      0x40008000, 0x10002000, 0x04000800, 0x01000200, 0x00400080, 0x00100020, 0x00040008, 0x00010002,      // ICON_CROSSLINE
  1082      0x00000000, 0x1ff01ff0, 0x18301830, 0x1f001830, 0x03001f00, 0x00000300, 0x03000300, 0x00000000,      // ICON_HELP
  1083      0x3ff00000, 0x2abc3550, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x00003ffc,      // ICON_FILETYPE_ALPHA
  1084      0x3ff00000, 0x201c2010, 0x22442184, 0x28142424, 0x29942814, 0x2ff42994, 0x20042004, 0x00003ffc,      // ICON_FILETYPE_HOME
  1085      0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0,      // ICON_LAYERS_VISIBLE
  1086      0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0,      // ICON_LAYERS
  1087      0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000,      // ICON_WINDOW
  1088      0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000,      // ICON_HIDPI
  1089      0x3ff00000, 0x201c2010, 0x2a842e84, 0x2e842a84, 0x2ba42004, 0x2aa42aa4, 0x20042ba4, 0x00003ffc,      // ICON_FILETYPE_BINARY
  1090      0x00000000, 0x00000000, 0x00120012, 0x4a5e4bd2, 0x485233d2, 0x00004bd2, 0x00000000, 0x00000000,      // ICON_HEX
  1091      0x01800000, 0x381c0660, 0x23c42004, 0x23c42044, 0x13c82204, 0x08101008, 0x02400420, 0x00000180,      // ICON_SHIELD
  1092      0x007e0000, 0x20023fc2, 0x40227fe2, 0x400a403a, 0x400a400a, 0x400a400a, 0x4008400e, 0x00007ff8,      // ICON_FILE_NEW
  1093      0x00000000, 0x0042007e, 0x40027fc2, 0x44024002, 0x5f024402, 0x44024402, 0x7ffe4002, 0x00000000,      // ICON_FOLDER_ADD
  1094      0x44220000, 0x12482244, 0xf3cf0000, 0x14280420, 0x48122424, 0x08100810, 0x1ff81008, 0x03c00420,      // ICON_ALARM
  1095      0x0aa00000, 0x1ff80aa0, 0x1068700e, 0x1008706e, 0x1008700e, 0x1008700e, 0x0aa01ff8, 0x00000aa0,      // ICON_CPU
  1096      0x07e00000, 0x04201db8, 0x04a01c38, 0x04a01d38, 0x04a01d38, 0x04a01d38, 0x04201d38, 0x000007e0,      // ICON_ROM
  1097      0x00000000, 0x03c00000, 0x3c382ff0, 0x3c04380c, 0x01800000, 0x03c003c0, 0x00000180, 0x00000000,      // ICON_STEP_OVER
  1098      0x01800000, 0x01800180, 0x01800180, 0x03c007e0, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180,      // ICON_STEP_INTO
  1099      0x01800000, 0x07e003c0, 0x01800180, 0x01800180, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180,      // ICON_STEP_OUT
  1100      0x00000000, 0x0ff003c0, 0x181c1c34, 0x303c301c, 0x30003000, 0x1c301800, 0x03c00ff0, 0x00000000,      // ICON_RESTART
  1101      0x00000000, 0x00000000, 0x07e003c0, 0x0ff00ff0, 0x0ff00ff0, 0x03c007e0, 0x00000000, 0x00000000,      // ICON_BREAKPOINT_ON
  1102      0x00000000, 0x00000000, 0x042003c0, 0x08100810, 0x08100810, 0x03c00420, 0x00000000, 0x00000000,      // ICON_BREAKPOINT_OFF
  1103      0x00000000, 0x00000000, 0x1ff81ff8, 0x1ff80000, 0x00001ff8, 0x1ff81ff8, 0x00000000, 0x00000000,      // ICON_BURGER_MENU
  1104      0x00000000, 0x00000000, 0x00880070, 0x0c880088, 0x1e8810f8, 0x3e881288, 0x00000000, 0x00000000,      // ICON_CASE_SENSITIVE
  1105      0x00000000, 0x02000000, 0x07000a80, 0x07001fc0, 0x02000a80, 0x00300030, 0x00000000, 0x00000000,      // ICON_REG_EXP
  1106      0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000,      // ICON_FOLDER
  1107      0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x00003ffc,      // ICON_FILE
  1108      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_219
  1109      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_220
  1110      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_221
  1111      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_222
  1112      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_223
  1113      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_224
  1114      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_225
  1115      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_226
  1116      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_227
  1117      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_228
  1118      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_229
  1119      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_230
  1120      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_231
  1121      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_232
  1122      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_233
  1123      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_234
  1124      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_235
  1125      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_236
  1126      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_237
  1127      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_238
  1128      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_239
  1129      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_240
  1130      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_241
  1131      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_242
  1132      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_243
  1133      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_244
  1134      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_245
  1135      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_246
  1136      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_247
  1137      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_248
  1138      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_249
  1139      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_250
  1140      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_251
  1141      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_252
  1142      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_253
  1143      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_254
  1144      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,      // ICON_255
  1145  };
  1146  
  1147  // NOTE: We keep a pointer to the icons array, useful to point to other sets if required
  1148  static unsigned int *guiIconsPtr = guiIcons;
  1149  
  1150  #endif      // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS
  1151  
  1152  #ifndef RAYGUI_ICON_SIZE
  1153      #define RAYGUI_ICON_SIZE             0
  1154  #endif
  1155  
  1156  #define RAYGUI_MAX_CONTROLS             16      // Maximum number of standard controls
  1157  #define RAYGUI_MAX_PROPS_BASE           16      // Maximum number of standard properties
  1158  #define RAYGUI_MAX_PROPS_EXTENDED        8      // Maximum number of extended properties
  1159  
  1160  //----------------------------------------------------------------------------------
  1161  // Types and Structures Definition
  1162  //----------------------------------------------------------------------------------
  1163  // Gui control property style color element
  1164  typedef enum { BORDER = 0, BASE, TEXT, OTHER } GuiPropertyElement;
  1165  
  1166  //----------------------------------------------------------------------------------
  1167  // Global Variables Definition
  1168  //----------------------------------------------------------------------------------
  1169  static GuiState guiState = STATE_NORMAL;    // Gui global state, if !STATE_NORMAL, forces defined state
  1170  
  1171  static Font guiFont = { 0 };                // Gui current font (WARNING: highly coupled to raylib)
  1172  static bool guiLocked = false;              // Gui lock state (no inputs processed)
  1173  static float guiAlpha = 1.0f;               // Gui element transpacency on drawing
  1174  
  1175  static unsigned int guiIconScale = 1;       // Gui icon default scale (if icons enabled)
  1176  
  1177  //----------------------------------------------------------------------------------
  1178  // Style data array for all gui style properties (allocated on data segment by default)
  1179  //
  1180  // NOTE 1: First set of BASE properties are generic to all controls but could be individually
  1181  // overwritten per control, first set of EXTENDED properties are generic to all controls and
  1182  // can not be overwritten individually but custom EXTENDED properties can be used by control
  1183  //
  1184  // NOTE 2: A new style set could be loaded over this array using GuiLoadStyle(),
  1185  // but default gui style could always be recovered with GuiLoadStyleDefault()
  1186  //
  1187  // guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB
  1188  //----------------------------------------------------------------------------------
  1189  static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)] = { 0 };
  1190  
  1191  static bool guiStyleLoaded = false;         // Style loaded flag for lazy style initialization
  1192  
  1193  //----------------------------------------------------------------------------------
  1194  // Standalone Mode Functions Declaration
  1195  //
  1196  // NOTE: raygui depend on some raylib input and drawing functions
  1197  // To use raygui as standalone library, below functions must be defined by the user
  1198  //----------------------------------------------------------------------------------
  1199  #if defined(RAYGUI_STANDALONE)
  1200  
  1201  #define KEY_RIGHT           262
  1202  #define KEY_LEFT            263
  1203  #define KEY_DOWN            264
  1204  #define KEY_UP              265
  1205  #define KEY_BACKSPACE       259
  1206  #define KEY_ENTER           257
  1207  
  1208  #define MOUSE_LEFT_BUTTON     0
  1209  
  1210  // Input required functions
  1211  //-------------------------------------------------------------------------------
  1212  static Vector2 GetMousePosition(void);
  1213  static float GetMouseWheelMove(void);
  1214  static bool IsMouseButtonDown(int button);
  1215  static bool IsMouseButtonPressed(int button);
  1216  static bool IsMouseButtonReleased(int button);
  1217  
  1218  static bool IsKeyDown(int key);
  1219  static bool IsKeyPressed(int key);
  1220  static int GetCharPressed(void);         // -- GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()
  1221  //-------------------------------------------------------------------------------
  1222  
  1223  // Drawing required functions
  1224  //-------------------------------------------------------------------------------
  1225  static void DrawRectangle(int x, int y, int width, int height, Color color);        // -- GuiDrawRectangle(), GuiDrawIcon()
  1226  
  1227  static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker()
  1228  //-------------------------------------------------------------------------------
  1229  
  1230  // Text required functions
  1231  //-------------------------------------------------------------------------------
  1232  static Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount); // -- GuiLoadStyle()
  1233  static Font GetFontDefault(void);                           // -- GuiLoadStyleDefault()
  1234  static Texture2D LoadTextureFromImage(Image image);         // -- GuiLoadStyle()
  1235  static void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle()
  1236  static char *LoadFileText(const char *fileName);            // -- GuiLoadStyle()
  1237  static const char *GetDirectoryPath(const char *filePath);  // -- GuiLoadStyle()
  1238  //-------------------------------------------------------------------------------
  1239  
  1240  // raylib functions already implemented in raygui
  1241  //-------------------------------------------------------------------------------
  1242  static Color GetColor(int hexValue);                // Returns a Color struct from hexadecimal value
  1243  static int ColorToInt(Color color);                 // Returns hexadecimal value for a Color
  1244  static Color Fade(Color color, float alpha);        // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
  1245  static bool CheckCollisionPointRec(Vector2 point, Rectangle rec);   // Check if point is inside rectangle
  1246  static const char *TextFormat(const char *text, ...);               // Formatting of text with variables to 'embed'
  1247  static const char **TextSplit(const char *text, char delimiter, int *count);    // Split text into multiple strings
  1248  static int TextToInteger(const char *text);         // Get integer value from text
  1249  
  1250  static int GetCodepointNext(const char *text, int *codepointSize);  // Get next codepoint in a UTF-8 encoded text
  1251  static const char *CodepointToUTF8(int codepoint, int *byteSize);   // Encode codepoint into UTF-8 text (char array size returned as parameter)
  1252  
  1253  static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2);  // Draw rectangle vertical gradient
  1254  //-------------------------------------------------------------------------------
  1255  
  1256  #endif      // RAYGUI_STANDALONE
  1257  
  1258  //----------------------------------------------------------------------------------
  1259  // Module specific Functions Declaration
  1260  //----------------------------------------------------------------------------------
  1261  static int GetTextWidth(const char *text);                      // Gui get text width using gui font and style
  1262  static Rectangle GetTextBounds(int control, Rectangle bounds);  // Get text bounds considering control bounds
  1263  static const char *GetTextIcon(const char *text, int *iconId);  // Get text icon if provided and move text cursor
  1264  
  1265  static void GuiDrawText(const char *text, Rectangle bounds, int alignment, Color tint);         // Gui draw text using default font
  1266  static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color);   // Gui draw rectangle using default raygui style
  1267  
  1268  static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow);   // Split controls text into multiple strings
  1269  static Vector3 ConvertHSVtoRGB(Vector3 hsv);                    // Convert color data from HSV to RGB
  1270  static Vector3 ConvertRGBtoHSV(Vector3 rgb);                    // Convert color data from RGB to HSV
  1271  
  1272  static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue);   // Scroll bar control, used by GuiScrollPanel()
  1273  
  1274  //----------------------------------------------------------------------------------
  1275  // Gui Setup Functions Definition
  1276  //----------------------------------------------------------------------------------
  1277  // Enable gui global state
  1278  // NOTE: We check for STATE_DISABLED to avoid messing custom global state setups
  1279  void GuiEnable(void) { if (guiState == STATE_DISABLED) guiState = STATE_NORMAL; }
  1280  
  1281  // Disable gui global state
  1282  // NOTE: We check for STATE_NORMAL to avoid messing custom global state setups
  1283  void GuiDisable(void) { if (guiState == STATE_NORMAL) guiState = STATE_DISABLED; }
  1284  
  1285  // Lock gui global state
  1286  void GuiLock(void) { guiLocked = true; }
  1287  
  1288  // Unlock gui global state
  1289  void GuiUnlock(void) { guiLocked = false; }
  1290  
  1291  // Check if gui is locked (global state)
  1292  bool GuiIsLocked(void) { return guiLocked; }
  1293  
  1294  // Set gui controls alpha global state
  1295  void GuiFade(float alpha)
  1296  {
  1297      if (alpha < 0.0f) alpha = 0.0f;
  1298      else if (alpha > 1.0f) alpha = 1.0f;
  1299  
  1300      guiAlpha = alpha;
  1301  }
  1302  
  1303  // Set gui state (global state)
  1304  void GuiSetState(int state) { guiState = (GuiState)state; }
  1305  
  1306  // Get gui state (global state)
  1307  int GuiGetState(void) { return guiState; }
  1308  
  1309  // Set custom gui font
  1310  // NOTE: Font loading/unloading is external to raygui
  1311  void GuiSetFont(Font font)
  1312  {
  1313      if (font.texture.id > 0)
  1314      {
  1315          // NOTE: If we try to setup a font but default style has not been
  1316          // lazily loaded before, it will be overwritten, so we need to force
  1317          // default style loading first
  1318          if (!guiStyleLoaded) GuiLoadStyleDefault();
  1319  
  1320          guiFont = font;
  1321          GuiSetStyle(DEFAULT, TEXT_SIZE, font.baseSize);
  1322      }
  1323  }
  1324  
  1325  // Get custom gui font
  1326  Font GuiGetFont(void)
  1327  {
  1328      return guiFont;
  1329  }
  1330  
  1331  // Set control style property value
  1332  void GuiSetStyle(int control, int property, int value)
  1333  {
  1334      if (!guiStyleLoaded) GuiLoadStyleDefault();
  1335      guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value;
  1336  
  1337      // Default properties are propagated to all controls
  1338      if ((control == 0) && (property < RAYGUI_MAX_PROPS_BASE))
  1339      {
  1340          for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) guiStyle[i*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value;
  1341      }
  1342  }
  1343  
  1344  // Get control style property value
  1345  int GuiGetStyle(int control, int property)
  1346  {
  1347      if (!guiStyleLoaded) GuiLoadStyleDefault();
  1348      return guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property];
  1349  }
  1350  
  1351  //----------------------------------------------------------------------------------
  1352  // Gui Controls Functions Definition
  1353  //----------------------------------------------------------------------------------
  1354  
  1355  // Window Box control
  1356  bool GuiWindowBox(Rectangle bounds, const char *title)
  1357  {
  1358      // Window title bar height (including borders)
  1359      // NOTE: This define is also used by GuiMessageBox() and GuiTextInputBox()
  1360      #if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT)
  1361          #define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT        24
  1362      #endif
  1363  
  1364      //GuiState state = guiState;
  1365      bool clicked = false;
  1366  
  1367      int statusBarHeight = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT;
  1368  
  1369      Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)statusBarHeight };
  1370      if (bounds.height < statusBarHeight*2.0f) bounds.height = statusBarHeight*2.0f;
  1371  
  1372      Rectangle windowPanel = { bounds.x, bounds.y + (float)statusBarHeight - 1, bounds.width, bounds.height - (float)statusBarHeight + 1 };
  1373      Rectangle closeButtonRec = { statusBar.x + statusBar.width - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - 20,
  1374                                   statusBar.y + statusBarHeight/2.0f - 18.0f/2.0f, 18, 18 };
  1375  
  1376      // Update control
  1377      //--------------------------------------------------------------------
  1378      // NOTE: Logic is directly managed by button
  1379      //--------------------------------------------------------------------
  1380  
  1381      // Draw control
  1382      //--------------------------------------------------------------------
  1383      GuiStatusBar(statusBar, title); // Draw window header as status bar
  1384      GuiPanel(windowPanel, NULL);    // Draw window base
  1385  
  1386      // Draw window close button
  1387      int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
  1388      int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  1389      GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
  1390      GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  1391  #if defined(RAYGUI_NO_ICONS)
  1392      clicked = GuiButton(closeButtonRec, "x");
  1393  #else
  1394      clicked = GuiButton(closeButtonRec, GuiIconText(ICON_CROSS_SMALL, NULL));
  1395  #endif
  1396      GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
  1397      GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment);
  1398      //--------------------------------------------------------------------
  1399  
  1400      return clicked;
  1401  }
  1402  
  1403  // Group Box control with text name
  1404  void GuiGroupBox(Rectangle bounds, const char *text)
  1405  {
  1406      #if !defined(RAYGUI_GROUPBOX_LINE_THICK)
  1407          #define RAYGUI_GROUPBOX_LINE_THICK     1
  1408      #endif
  1409  
  1410      GuiState state = guiState;
  1411  
  1412      // Draw control
  1413      //--------------------------------------------------------------------
  1414      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));
  1415      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));
  1416      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));
  1417  
  1418      GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text);
  1419      //--------------------------------------------------------------------
  1420  }
  1421  
  1422  // Line control
  1423  void GuiLine(Rectangle bounds, const char *text)
  1424  {
  1425      #if !defined(RAYGUI_LINE_ORIGIN_SIZE)
  1426          #define RAYGUI_LINE_MARGIN_TEXT  12
  1427      #endif
  1428      #if !defined(RAYGUI_LINE_TEXT_PADDING)
  1429          #define RAYGUI_LINE_TEXT_PADDING  4
  1430      #endif
  1431  
  1432      GuiState state = guiState;
  1433  
  1434      Color color = Fade(GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)), guiAlpha);
  1435  
  1436      // Draw control
  1437      //--------------------------------------------------------------------
  1438      if (text == NULL) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, bounds.width, 1 }, 0, BLANK, color);
  1439      else
  1440      {
  1441          Rectangle textBounds = { 0 };
  1442          textBounds.width = (float)GetTextWidth(text);
  1443          textBounds.height = bounds.height;
  1444          textBounds.x = bounds.x + RAYGUI_LINE_MARGIN_TEXT;
  1445          textBounds.y = bounds.y;
  1446  
  1447          // Draw line with embedded text label: "--- text --------------"
  1448          GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color);
  1449          GuiDrawText(text, textBounds, TEXT_ALIGN_LEFT, color);
  1450          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);
  1451      }
  1452      //--------------------------------------------------------------------
  1453  }
  1454  
  1455  // Panel control
  1456  void GuiPanel(Rectangle bounds, const char *text)
  1457  {
  1458      #if !defined(RAYGUI_PANEL_BORDER_WIDTH)
  1459          #define RAYGUI_PANEL_BORDER_WIDTH   1
  1460      #endif
  1461  
  1462      GuiState state = guiState;
  1463  
  1464      // Text will be drawn as a header bar (if provided)
  1465      Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT };
  1466      if ((text != NULL) && (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f)) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f;
  1467  
  1468      if (text != NULL)
  1469      {
  1470          // Move panel bounds after the header bar
  1471          bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1;
  1472          bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + 1;
  1473      }
  1474  
  1475      // Draw control
  1476      //--------------------------------------------------------------------
  1477      if (text != NULL) GuiStatusBar(statusBar, text);  // Draw panel header as status bar
  1478  
  1479      GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, Fade(GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED: LINE_COLOR)), guiAlpha),
  1480                       Fade(GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BASE_COLOR_DISABLED : BACKGROUND_COLOR)), guiAlpha));
  1481      //--------------------------------------------------------------------
  1482  }
  1483  
  1484  // Tab Bar control
  1485  // NOTE: Using GuiToggle() for the TABS
  1486  int GuiTabBar(Rectangle bounds, const char **text, int count, int *active)
  1487  {
  1488      #define RAYGUI_TABBAR_ITEM_WIDTH    160
  1489  
  1490      GuiState state = guiState;
  1491  
  1492      int closing = -1;
  1493      Rectangle tabBounds = { bounds.x, bounds.y, RAYGUI_TABBAR_ITEM_WIDTH, bounds.height };
  1494  
  1495      if (*active < 0) *active = 0;
  1496      else if (*active > count - 1) *active = count - 1;
  1497  
  1498      // Draw control
  1499      //--------------------------------------------------------------------
  1500      for (int i = 0; i < count; i++)
  1501      {
  1502          tabBounds.x = bounds.x + (RAYGUI_TABBAR_ITEM_WIDTH + 4)*i;
  1503  
  1504          int textAlignment = GuiGetStyle(TOGGLE, TEXT_ALIGNMENT);
  1505          int textPadding = GuiGetStyle(TOGGLE, TEXT_PADDING);
  1506          GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  1507          GuiSetStyle(TOGGLE, TEXT_PADDING, 8);
  1508          if (i == *active) GuiToggle(tabBounds, GuiIconText(12, text[i]), true);
  1509          else if (GuiToggle(tabBounds, GuiIconText(12, text[i]), false) == true) *active = i;
  1510          GuiSetStyle(TOGGLE, TEXT_PADDING, textPadding);
  1511          GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment);
  1512  
  1513          // Draw tab close button
  1514          // NOTE: Only draw close button for curren tab: if (CheckCollisionPointRec(mousePoint, tabBounds))
  1515          int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
  1516          int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  1517          GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
  1518          GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  1519  #if defined(RAYGUI_NO_ICONS)
  1520          if (GuiButton(closeButtonRec, "x")) closing = i;
  1521  #else
  1522          if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, GuiIconText(ICON_CROSS_SMALL, NULL))) closing = i;
  1523  #endif
  1524          GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
  1525          GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment);
  1526      }
  1527  
  1528      GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, 1 }, 0, BLANK, GetColor(GuiGetStyle(TOGGLE, BORDER_COLOR_NORMAL)));
  1529      //GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, 1 }, NULL);
  1530      //--------------------------------------------------------------------
  1531  
  1532      return closing;     // Return closing tab requested
  1533  }
  1534  
  1535  // Scroll Panel control
  1536  Rectangle GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll)
  1537  {
  1538      GuiState state = guiState;
  1539  
  1540      Vector2 scrollPos = { 0.0f, 0.0f };
  1541      if (scroll != NULL) scrollPos = *scroll;
  1542  
  1543      // Text will be drawn as a header bar (if provided)
  1544      Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT };
  1545      if (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f;
  1546  
  1547      if (text != NULL)
  1548      {
  1549          // Move panel bounds after the header bar
  1550          bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1;
  1551          bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + 1;
  1552      }
  1553  
  1554      bool hasHorizontalScrollBar = (content.width > bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false;
  1555      bool hasVerticalScrollBar = (content.height > bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false;
  1556  
  1557      // Recheck to account for the other scrollbar being visible
  1558      if (!hasHorizontalScrollBar) hasHorizontalScrollBar = (hasVerticalScrollBar && (content.width > (bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false;
  1559      if (!hasVerticalScrollBar) hasVerticalScrollBar = (hasHorizontalScrollBar && (content.height > (bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false;
  1560  
  1561      int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0;
  1562      int verticalScrollBarWidth =  hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0;
  1563      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 };
  1564      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) };
  1565  
  1566      // Calculate view area (area without the scrollbars)
  1567      Rectangle view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)?
  1568                  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 } :
  1569                  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 };
  1570  
  1571      // Clip view area to the actual content size
  1572      if (view.width > content.width) view.width = content.width;
  1573      if (view.height > content.height) view.height = content.height;
  1574  
  1575      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);
  1576      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);
  1577      float verticalMin = hasVerticalScrollBar? 0.0f : -1.0f;
  1578      float verticalMax = hasVerticalScrollBar? content.height - bounds.height + (float)horizontalScrollBarWidth + (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH);
  1579  
  1580      // Update control
  1581      //--------------------------------------------------------------------
  1582      if ((state != STATE_DISABLED) && !guiLocked)
  1583      {
  1584          Vector2 mousePoint = GetMousePosition();
  1585  
  1586          // Check button state
  1587          if (CheckCollisionPointRec(mousePoint, bounds))
  1588          {
  1589              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  1590              else state = STATE_FOCUSED;
  1591  
  1592  #if defined(SUPPORT_SCROLLBAR_KEY_INPUT)
  1593              if (hasHorizontalScrollBar)
  1594              {
  1595                  if (IsKeyDown(KEY_RIGHT)) scrollPos.x -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  1596                  if (IsKeyDown(KEY_LEFT)) scrollPos.x += GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  1597              }
  1598  
  1599              if (hasVerticalScrollBar)
  1600              {
  1601                  if (IsKeyDown(KEY_DOWN)) scrollPos.y -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  1602                  if (IsKeyDown(KEY_UP)) scrollPos.y += GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  1603              }
  1604  #endif
  1605              float wheelMove = GetMouseWheelMove();
  1606  
  1607              // Horizontal scroll (Shift + Mouse wheel)
  1608              if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_SHIFT))) scrollPos.x += wheelMove*20;
  1609              else scrollPos.y += wheelMove*20; // Vertical scroll
  1610          }
  1611      }
  1612  
  1613      // Normalize scroll values
  1614      if (scrollPos.x > -horizontalMin) scrollPos.x = -horizontalMin;
  1615      if (scrollPos.x < -horizontalMax) scrollPos.x = -horizontalMax;
  1616      if (scrollPos.y > -verticalMin) scrollPos.y = -verticalMin;
  1617      if (scrollPos.y < -verticalMax) scrollPos.y = -verticalMax;
  1618      //--------------------------------------------------------------------
  1619  
  1620      // Draw control
  1621      //--------------------------------------------------------------------
  1622      if (text != NULL) GuiStatusBar(statusBar, text);  // Draw panel header as status bar
  1623  
  1624      GuiDrawRectangle(bounds, 0, BLANK, Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), guiAlpha));        // Draw background
  1625  
  1626      // Save size of the scrollbar slider
  1627      const int slider = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
  1628  
  1629      // Draw horizontal scrollbar if visible
  1630      if (hasHorizontalScrollBar)
  1631      {
  1632          // Change scrollbar slider size to show the diff in size between the content width and the widget width
  1633          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)));
  1634          scrollPos.x = (float)-GuiScrollBar(horizontalScrollBar, (int)-scrollPos.x, (int)horizontalMin, (int)horizontalMax);
  1635      }
  1636      else scrollPos.x = 0.0f;
  1637  
  1638      // Draw vertical scrollbar if visible
  1639      if (hasVerticalScrollBar)
  1640      {
  1641          // Change scrollbar slider size to show the diff in size between the content height and the widget height
  1642          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)));
  1643          scrollPos.y = (float)-GuiScrollBar(verticalScrollBar, (int)-scrollPos.y, (int)verticalMin, (int)verticalMax);
  1644      }
  1645      else scrollPos.y = 0.0f;
  1646  
  1647      // Draw detail corner rectangle if both scroll bars are visible
  1648      if (hasHorizontalScrollBar && hasVerticalScrollBar)
  1649      {
  1650          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 };
  1651          GuiDrawRectangle(corner, 0, BLANK, Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3))), guiAlpha));
  1652      }
  1653  
  1654      // Draw scrollbar lines depending on current state
  1655      GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), guiAlpha), BLANK);
  1656  
  1657      // Set scrollbar slider size back to the way it was before
  1658      GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, slider);
  1659      //--------------------------------------------------------------------
  1660  
  1661      if (scroll != NULL) *scroll = scrollPos;
  1662  
  1663      return view;
  1664  }
  1665  
  1666  // Label control
  1667  void GuiLabel(Rectangle bounds, const char *text)
  1668  {
  1669      GuiState state = guiState;
  1670  
  1671      // Update control
  1672      //--------------------------------------------------------------------
  1673      //...
  1674      //--------------------------------------------------------------------
  1675  
  1676      // Draw control
  1677      //--------------------------------------------------------------------
  1678      GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
  1679      //--------------------------------------------------------------------
  1680  }
  1681  
  1682  // Button control, returns true when clicked
  1683  bool GuiButton(Rectangle bounds, const char *text)
  1684  {
  1685      GuiState state = guiState;
  1686      bool pressed = false;
  1687  
  1688      // Update control
  1689      //--------------------------------------------------------------------
  1690      if ((state != STATE_DISABLED) && !guiLocked)
  1691      {
  1692          Vector2 mousePoint = GetMousePosition();
  1693  
  1694          // Check button state
  1695          if (CheckCollisionPointRec(mousePoint, bounds))
  1696          {
  1697              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  1698              else state = STATE_FOCUSED;
  1699  
  1700              if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true;
  1701          }
  1702      }
  1703      //--------------------------------------------------------------------
  1704  
  1705      // Draw control
  1706      //--------------------------------------------------------------------
  1707      GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(BUTTON, BASE + (state*3))), guiAlpha));
  1708      GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha));
  1709      //------------------------------------------------------------------
  1710  
  1711      return pressed;
  1712  }
  1713  
  1714  // Label button control
  1715  bool GuiLabelButton(Rectangle bounds, const char *text)
  1716  {
  1717      GuiState state = guiState;
  1718      bool pressed = false;
  1719  
  1720      // NOTE: We force bounds.width to be all text
  1721      float textWidth = (float)GetTextWidth(text);
  1722      if (bounds.width < textWidth) bounds.width = textWidth;
  1723  
  1724      // Update control
  1725      //--------------------------------------------------------------------
  1726      if ((state != STATE_DISABLED) && !guiLocked)
  1727      {
  1728          Vector2 mousePoint = GetMousePosition();
  1729  
  1730          // Check checkbox state
  1731          if (CheckCollisionPointRec(mousePoint, bounds))
  1732          {
  1733              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  1734              else state = STATE_FOCUSED;
  1735  
  1736              if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true;
  1737          }
  1738      }
  1739      //--------------------------------------------------------------------
  1740  
  1741      // Draw control
  1742      //--------------------------------------------------------------------
  1743      GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
  1744      //--------------------------------------------------------------------
  1745  
  1746      return pressed;
  1747  }
  1748  
  1749  // Toggle Button control, returns true when active
  1750  bool GuiToggle(Rectangle bounds, const char *text, bool active)
  1751  {
  1752      GuiState state = guiState;
  1753  
  1754      // Update control
  1755      //--------------------------------------------------------------------
  1756      if ((state != STATE_DISABLED) && !guiLocked)
  1757      {
  1758          Vector2 mousePoint = GetMousePosition();
  1759  
  1760          // Check toggle button state
  1761          if (CheckCollisionPointRec(mousePoint, bounds))
  1762          {
  1763              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  1764              else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
  1765              {
  1766                  state = STATE_NORMAL;
  1767                  active = !active;
  1768              }
  1769              else state = STATE_FOCUSED;
  1770          }
  1771      }
  1772      //--------------------------------------------------------------------
  1773  
  1774      // Draw control
  1775      //--------------------------------------------------------------------
  1776      if (state == STATE_NORMAL)
  1777      {
  1778          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));
  1779          GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, (active? TEXT_COLOR_PRESSED : (TEXT + state*3)))), guiAlpha));
  1780      }
  1781      else
  1782      {
  1783          GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TOGGLE, BORDER + state*3)), guiAlpha), Fade(GetColor(GuiGetStyle(TOGGLE, BASE + state*3)), guiAlpha));
  1784          GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, TEXT + state*3)), guiAlpha));
  1785      }
  1786      //--------------------------------------------------------------------
  1787  
  1788      return active;
  1789  }
  1790  
  1791  // Toggle Group control, returns toggled button codepointIndex
  1792  int GuiToggleGroup(Rectangle bounds, const char *text, int active)
  1793  {
  1794      #if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS)
  1795          #define RAYGUI_TOGGLEGROUP_MAX_ITEMS    32
  1796      #endif
  1797  
  1798      float initBoundsX = bounds.x;
  1799  
  1800      // Get substrings items from text (items pointers)
  1801      int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 };
  1802      int itemCount = 0;
  1803      const char **items = GuiTextSplit(text, ';', &itemCount, rows);
  1804  
  1805      int prevRow = rows[0];
  1806  
  1807      for (int i = 0; i < itemCount; i++)
  1808      {
  1809          if (prevRow != rows[i])
  1810          {
  1811              bounds.x = initBoundsX;
  1812              bounds.y += (bounds.height + GuiGetStyle(TOGGLE, GROUP_PADDING));
  1813              prevRow = rows[i];
  1814          }
  1815  
  1816          if (i == active) GuiToggle(bounds, items[i], true);
  1817          else if (GuiToggle(bounds, items[i], false) == true) active = i;
  1818  
  1819          bounds.x += (bounds.width + GuiGetStyle(TOGGLE, GROUP_PADDING));
  1820      }
  1821  
  1822      return active;
  1823  }
  1824  
  1825  // Check Box control, returns true when active
  1826  bool GuiCheckBox(Rectangle bounds, const char *text, bool checked)
  1827  {
  1828      GuiState state = guiState;
  1829  
  1830      Rectangle textBounds = { 0 };
  1831  
  1832      if (text != NULL)
  1833      {
  1834          textBounds.width = (float)GetTextWidth(text);
  1835          textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  1836          textBounds.x = bounds.x + bounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING);
  1837          textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  1838          if (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(CHECKBOX, TEXT_PADDING);
  1839      }
  1840  
  1841      // Update control
  1842      //--------------------------------------------------------------------
  1843      if ((state != STATE_DISABLED) && !guiLocked)
  1844      {
  1845          Vector2 mousePoint = GetMousePosition();
  1846  
  1847          Rectangle totalBounds = {
  1848              (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT)? textBounds.x : bounds.x,
  1849              bounds.y,
  1850              bounds.width + textBounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING),
  1851              bounds.height,
  1852          };
  1853  
  1854          // Check checkbox state
  1855          if (CheckCollisionPointRec(mousePoint, totalBounds))
  1856          {
  1857              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  1858              else state = STATE_FOCUSED;
  1859  
  1860              if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) checked = !checked;
  1861          }
  1862      }
  1863      //--------------------------------------------------------------------
  1864  
  1865      // Draw control
  1866      //--------------------------------------------------------------------
  1867      GuiDrawRectangle(bounds, GuiGetStyle(CHECKBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(CHECKBOX, BORDER + (state*3))), guiAlpha), BLANK);
  1868  
  1869      if (checked)
  1870      {
  1871          Rectangle check = { bounds.x + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING),
  1872                              bounds.y + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING),
  1873                              bounds.width - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)),
  1874                              bounds.height - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)) };
  1875          GuiDrawRectangle(check, 0, BLANK, Fade(GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3)), guiAlpha));
  1876      }
  1877  
  1878      GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
  1879      //--------------------------------------------------------------------
  1880  
  1881      return checked;
  1882  }
  1883  
  1884  // Combo Box control, returns selected item codepointIndex
  1885  int GuiComboBox(Rectangle bounds, const char *text, int active)
  1886  {
  1887      GuiState state = guiState;
  1888  
  1889      bounds.width -= (GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH) + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING));
  1890  
  1891      Rectangle selector = { (float)bounds.x + bounds.width + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING),
  1892                             (float)bounds.y, (float)GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH), (float)bounds.height };
  1893  
  1894      // Get substrings items from text (items pointers, lengths and count)
  1895      int itemCount = 0;
  1896      const char **items = GuiTextSplit(text, ';', &itemCount, NULL);
  1897  
  1898      if (active < 0) active = 0;
  1899      else if (active > itemCount - 1) active = itemCount - 1;
  1900  
  1901      // Update control
  1902      //--------------------------------------------------------------------
  1903      if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1))
  1904      {
  1905          Vector2 mousePoint = GetMousePosition();
  1906  
  1907          if (CheckCollisionPointRec(mousePoint, bounds) ||
  1908              CheckCollisionPointRec(mousePoint, selector))
  1909          {
  1910              if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
  1911              {
  1912                  active += 1;
  1913                  if (active >= itemCount) active = 0;
  1914              }
  1915  
  1916              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  1917              else state = STATE_FOCUSED;
  1918          }
  1919      }
  1920      //--------------------------------------------------------------------
  1921  
  1922      // Draw control
  1923      //--------------------------------------------------------------------
  1924      // Draw combo box main
  1925      GuiDrawRectangle(bounds, GuiGetStyle(COMBOBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(COMBOBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(COMBOBOX, BASE + (state*3))), guiAlpha));
  1926      GuiDrawText(items[active], GetTextBounds(COMBOBOX, bounds), GuiGetStyle(COMBOBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(COMBOBOX, TEXT + (state*3))), guiAlpha));
  1927  
  1928      // Draw selector using a custom button
  1929      // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
  1930      int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
  1931      int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  1932      GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
  1933      GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  1934  
  1935      GuiButton(selector, TextFormat("%i/%i", active + 1, itemCount));
  1936  
  1937      GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
  1938      GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
  1939      //--------------------------------------------------------------------
  1940  
  1941      return active;
  1942  }
  1943  
  1944  // Dropdown Box control
  1945  // NOTE: Returns mouse click
  1946  bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode)
  1947  {
  1948      GuiState state = guiState;
  1949      int itemSelected = *active;
  1950      int itemFocused = -1;
  1951  
  1952      // Get substrings items from text (items pointers, lengths and count)
  1953      int itemCount = 0;
  1954      const char **items = GuiTextSplit(text, ';', &itemCount, NULL);
  1955  
  1956      Rectangle boundsOpen = bounds;
  1957      boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
  1958  
  1959      Rectangle itemBounds = bounds;
  1960  
  1961      bool pressed = false;       // Check mouse button pressed
  1962  
  1963      // Update control
  1964      //--------------------------------------------------------------------
  1965      if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1))
  1966      {
  1967          Vector2 mousePoint = GetMousePosition();
  1968  
  1969          if (editMode)
  1970          {
  1971              state = STATE_PRESSED;
  1972  
  1973              // Check if mouse has been pressed or released outside limits
  1974              if (!CheckCollisionPointRec(mousePoint, boundsOpen))
  1975              {
  1976                  if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true;
  1977              }
  1978  
  1979              // Check if already selected item has been pressed again
  1980              if (CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
  1981  
  1982              // Check focused and selected item
  1983              for (int i = 0; i < itemCount; i++)
  1984              {
  1985                  // Update item rectangle y position for next item
  1986                  itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
  1987  
  1988                  if (CheckCollisionPointRec(mousePoint, itemBounds))
  1989                  {
  1990                      itemFocused = i;
  1991                      if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
  1992                      {
  1993                          itemSelected = i;
  1994                          pressed = true;     // Item selected, change to editMode = false
  1995                      }
  1996                      break;
  1997                  }
  1998              }
  1999  
  2000              itemBounds = bounds;
  2001          }
  2002          else
  2003          {
  2004              if (CheckCollisionPointRec(mousePoint, bounds))
  2005              {
  2006                  if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
  2007                  {
  2008                      pressed = true;
  2009                      state = STATE_PRESSED;
  2010                  }
  2011                  else state = STATE_FOCUSED;
  2012              }
  2013          }
  2014      }
  2015      //--------------------------------------------------------------------
  2016  
  2017      // Draw control
  2018      //--------------------------------------------------------------------
  2019      if (editMode) GuiPanel(boundsOpen, NULL);
  2020  
  2021      GuiDrawRectangle(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), guiAlpha), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3)), guiAlpha));
  2022      GuiDrawText(items[itemSelected], GetTextBounds(DEFAULT, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3)), guiAlpha));
  2023  
  2024      if (editMode)
  2025      {
  2026          // Draw visible items
  2027          for (int i = 0; i < itemCount; i++)
  2028          {
  2029              // Update item rectangle y position for next item
  2030              itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
  2031  
  2032              if (i == itemSelected)
  2033              {
  2034                  GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), guiAlpha), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED)), guiAlpha));
  2035                  GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED)), guiAlpha));
  2036              }
  2037              else if (i == itemFocused)
  2038              {
  2039                  GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), guiAlpha), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED)), guiAlpha));
  2040                  GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED)), guiAlpha));
  2041              }
  2042              else GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL)), guiAlpha));
  2043          }
  2044      }
  2045  
  2046      // Draw arrows (using icon if available)
  2047  #if defined(RAYGUI_NO_ICONS)
  2048      GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },
  2049                  TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha));
  2050  #else
  2051      GuiDrawText("#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },
  2052                  TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha));   // ICON_ARROW_DOWN_FILL
  2053  #endif
  2054      //--------------------------------------------------------------------
  2055  
  2056      *active = itemSelected;
  2057      return pressed;
  2058  }
  2059  
  2060  // Text Box control, updates input text
  2061  // NOTE 2: Returns if KEY_ENTER pressed (useful for data validation)
  2062  bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
  2063  {
  2064      GuiState state = guiState;
  2065      Rectangle textBounds = GetTextBounds(TEXTBOX, bounds);
  2066  
  2067      bool pressed = false;
  2068      int textWidth = GetTextWidth(text);
  2069  
  2070      Rectangle cursor = {
  2071          bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + textWidth + 2,
  2072          bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE),
  2073          4,
  2074          (float)GuiGetStyle(DEFAULT, TEXT_SIZE)*2
  2075      };
  2076  
  2077      if (cursor.height >= bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2;
  2078      if (cursor.y < (bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH))) cursor.y = bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH);
  2079  
  2080      // Update control
  2081      //--------------------------------------------------------------------
  2082      if ((state != STATE_DISABLED) && !guiLocked)
  2083      {
  2084          Vector2 mousePoint = GetMousePosition();
  2085  
  2086          if (editMode)
  2087          {
  2088              state = STATE_PRESSED;
  2089  
  2090              int key = GetCharPressed();      // Returns codepoint as Unicode
  2091              int keyCount = (int)strlen(text);
  2092              int byteSize = 0;
  2093              const char *textUTF8 = CodepointToUTF8(key, &byteSize);
  2094  
  2095              // Only allow keys in range [32..125]
  2096              if ((keyCount + byteSize) < textSize)
  2097              {
  2098                  //float maxWidth = (bounds.width - (GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING)*2));
  2099  
  2100                  if (key >= 32)
  2101                  {
  2102                      for (int i = 0; i < byteSize; i++)
  2103                      {
  2104                          text[keyCount] = textUTF8[i];
  2105                          keyCount++;
  2106                      }
  2107  
  2108                      text[keyCount] = '\0';
  2109                  }
  2110              }
  2111  
  2112              // Delete text
  2113              if (keyCount > 0)
  2114              {
  2115                  if (IsKeyPressed(KEY_BACKSPACE))
  2116                  {
  2117                      while ((keyCount > 0) && ((text[--keyCount] & 0xc0) == 0x80));
  2118                      text[keyCount] = '\0';
  2119                  }
  2120              }
  2121  
  2122              if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) pressed = true;
  2123          }
  2124          else
  2125          {
  2126              if (CheckCollisionPointRec(mousePoint, bounds))
  2127              {
  2128                  state = STATE_FOCUSED;
  2129                  if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
  2130              }
  2131          }
  2132      }
  2133      //--------------------------------------------------------------------
  2134  
  2135      // Draw control
  2136      //--------------------------------------------------------------------
  2137      if (state == STATE_PRESSED)
  2138      {
  2139          GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha));
  2140      }
  2141      else if (state == STATE_DISABLED)
  2142      {
  2143          GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)), guiAlpha));
  2144      }
  2145      else GuiDrawRectangle(bounds, 1, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), BLANK);
  2146  
  2147      if (editMode)
  2148      {
  2149          // In case we edit and text does not fit in the textbox,
  2150          // we move text pointer to a position it fits inside the text box
  2151          while ((textWidth >= textBounds.width) && (text[0] != '\0'))
  2152          {
  2153              int codepointSize = 0;
  2154              GetCodepointNext(text, &codepointSize);
  2155              text += codepointSize;
  2156              textWidth = GetTextWidth(text);
  2157              cursor.x = textBounds.x + textWidth + 2;
  2158          }
  2159      }
  2160  
  2161      GuiDrawText(text, textBounds, GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha));
  2162  
  2163      // Draw cursor
  2164      if (editMode) GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha));
  2165      //--------------------------------------------------------------------
  2166  
  2167      return pressed;
  2168  }
  2169  
  2170  // Spinner control, returns selected value
  2171  bool GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
  2172  {
  2173      GuiState state = guiState;
  2174  
  2175      bool pressed = false;
  2176      int tempValue = *value;
  2177  
  2178      Rectangle spinner = { bounds.x + GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_SPACING), bounds.y,
  2179                            bounds.width - 2*(GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_SPACING)), bounds.height };
  2180      Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height };
  2181      Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height };
  2182  
  2183      Rectangle textBounds = { 0 };
  2184      if (text != NULL)
  2185      {
  2186          textBounds.width = (float)GetTextWidth(text);
  2187          textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2188          textBounds.x = bounds.x + bounds.width + GuiGetStyle(SPINNER, TEXT_PADDING);
  2189          textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2190          if (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SPINNER, TEXT_PADDING);
  2191      }
  2192  
  2193      // Update control
  2194      //--------------------------------------------------------------------
  2195      if ((state != STATE_DISABLED) && !guiLocked)
  2196      {
  2197          Vector2 mousePoint = GetMousePosition();
  2198  
  2199          // Check spinner state
  2200          if (CheckCollisionPointRec(mousePoint, bounds))
  2201          {
  2202              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  2203              else state = STATE_FOCUSED;
  2204          }
  2205      }
  2206  
  2207  #if defined(RAYGUI_NO_ICONS)
  2208      if (GuiButton(leftButtonBound, "<")) tempValue--;
  2209      if (GuiButton(rightButtonBound, ">")) tempValue++;
  2210  #else
  2211      if (GuiButton(leftButtonBound, GuiIconText(ICON_ARROW_LEFT_FILL, NULL))) tempValue--;
  2212      if (GuiButton(rightButtonBound, GuiIconText(ICON_ARROW_RIGHT_FILL, NULL))) tempValue++;
  2213  #endif
  2214  
  2215      if (!editMode)
  2216      {
  2217          if (tempValue < minValue) tempValue = minValue;
  2218          if (tempValue > maxValue) tempValue = maxValue;
  2219      }
  2220      //--------------------------------------------------------------------
  2221  
  2222      // Draw control
  2223      //--------------------------------------------------------------------
  2224      // TODO: Set Spinner properties for ValueBox
  2225      pressed = GuiValueBox(spinner, NULL, &tempValue, minValue, maxValue, editMode);
  2226  
  2227      // Draw value selector custom buttons
  2228      // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
  2229      int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
  2230      int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  2231      GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(SPINNER, BORDER_WIDTH));
  2232      GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  2233  
  2234      GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
  2235      GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
  2236  
  2237      // Draw text label if provided
  2238      GuiDrawText(text, textBounds, (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
  2239      //--------------------------------------------------------------------
  2240  
  2241      *value = tempValue;
  2242      return pressed;
  2243  }
  2244  
  2245  // Value Box control, updates input text with numbers
  2246  // NOTE: Requires static variables: frameCounter
  2247  bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
  2248  {
  2249      #if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
  2250          #define RAYGUI_VALUEBOX_MAX_CHARS  32
  2251      #endif
  2252  
  2253      GuiState state = guiState;
  2254      bool pressed = false;
  2255  
  2256      char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";
  2257      sprintf(textValue, "%i", *value);
  2258  
  2259      Rectangle textBounds = { 0 };
  2260      if (text != NULL)
  2261      {
  2262          textBounds.width = (float)GetTextWidth(text);
  2263          textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2264          textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
  2265          textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2266          if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
  2267      }
  2268  
  2269      // Update control
  2270      //--------------------------------------------------------------------
  2271      if ((state != STATE_DISABLED) && !guiLocked)
  2272      {
  2273          Vector2 mousePoint = GetMousePosition();
  2274  
  2275          bool valueHasChanged = false;
  2276  
  2277          if (editMode)
  2278          {
  2279              state = STATE_PRESSED;
  2280  
  2281              int keyCount = (int)strlen(textValue);
  2282  
  2283              // Only allow keys in range [48..57]
  2284              if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)
  2285              {
  2286                  if (GetTextWidth(textValue) < bounds.width)
  2287                  {
  2288                      int key = GetCharPressed();
  2289                      if ((key >= 48) && (key <= 57))
  2290                      {
  2291                          textValue[keyCount] = (char)key;
  2292                          keyCount++;
  2293                          valueHasChanged = true;
  2294                      }
  2295                  }
  2296              }
  2297  
  2298              // Delete text
  2299              if (keyCount > 0)
  2300              {
  2301                  if (IsKeyPressed(KEY_BACKSPACE))
  2302                  {
  2303                      keyCount--;
  2304                      textValue[keyCount] = '\0';
  2305                      valueHasChanged = true;
  2306                  }
  2307              }
  2308  
  2309              if (valueHasChanged) *value = TextToInteger(textValue);
  2310  
  2311              // NOTE: We are not clamp values until user input finishes
  2312              //if (*value > maxValue) *value = maxValue;
  2313              //else if (*value < minValue) *value = minValue;
  2314  
  2315              if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) pressed = true;
  2316          }
  2317          else
  2318          {
  2319              if (*value > maxValue) *value = maxValue;
  2320              else if (*value < minValue) *value = minValue;
  2321  
  2322              if (CheckCollisionPointRec(mousePoint, bounds))
  2323              {
  2324                  state = STATE_FOCUSED;
  2325                  if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
  2326              }
  2327          }
  2328      }
  2329      //--------------------------------------------------------------------
  2330  
  2331      // Draw control
  2332      //--------------------------------------------------------------------
  2333      Color baseColor = BLANK;
  2334      if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));
  2335      else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));
  2336  
  2337      // WARNING: BLANK color does not work properly with Fade()
  2338      GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), guiAlpha), baseColor);
  2339      GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))), guiAlpha));
  2340  
  2341      // Draw cursor
  2342      if (editMode)
  2343      {
  2344          // NOTE: ValueBox internal text is always centered
  2345          Rectangle cursor = { bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 1, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH) };
  2346          GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
  2347      }
  2348  
  2349      // Draw text label if provided
  2350      GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
  2351      //--------------------------------------------------------------------
  2352  
  2353      return pressed;
  2354  }
  2355  
  2356  // Text Box control with multiple lines
  2357  bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
  2358  {
  2359      GuiState state = guiState;
  2360      bool pressed = false;
  2361  
  2362      Rectangle textAreaBounds = {
  2363          bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING),
  2364          bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING),
  2365          bounds.width - 2*(GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING)),
  2366          bounds.height - 2*(GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING))
  2367      };
  2368  
  2369      // Cursor position, [x, y] values should be updated
  2370      Rectangle cursor = { 0, -1, 4, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) + 2 };
  2371  
  2372      float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/(float)guiFont.baseSize;     // Character rectangle scaling factor
  2373  
  2374      // Update control
  2375      //--------------------------------------------------------------------
  2376      if ((state != STATE_DISABLED) && !guiLocked)
  2377      {
  2378          Vector2 mousePoint = GetMousePosition();
  2379  
  2380          if (editMode)
  2381          {
  2382              state = STATE_PRESSED;
  2383  
  2384              // We get an Unicode codepoint
  2385              int codepoint = GetCharPressed();
  2386              int textLength = (int)strlen(text);     // Length in bytes (UTF-8 string)
  2387              int byteSize = 0;
  2388              const char *textUTF8 = CodepointToUTF8(codepoint, &byteSize);
  2389  
  2390              // Introduce characters
  2391              if ((textLength + byteSize) < textSize)
  2392              {
  2393                  if (IsKeyPressed(KEY_ENTER))
  2394                  {
  2395                      text[textLength] = '\n';
  2396                      textLength++;
  2397                  }
  2398                  else if (codepoint >= 32)
  2399                  {
  2400                      // Supports Unicode inputs -> Encoded to UTF-8
  2401                      int charUTF8Length = 0;
  2402                      const char *charEncoded = CodepointToUTF8(codepoint, &charUTF8Length);
  2403                      memcpy(text + textLength, charEncoded, charUTF8Length);
  2404                      textLength += charUTF8Length;
  2405                  }
  2406              }
  2407  
  2408              // Delete characters
  2409              if (textLength > 0)
  2410              {
  2411                  if (IsKeyPressed(KEY_BACKSPACE))
  2412                  {
  2413                      if ((unsigned char)text[textLength - 1] < 127)
  2414                      {
  2415                          // Remove ASCII equivalent character (1 byte)
  2416                          textLength--;
  2417                          text[textLength] = '\0';
  2418                      }
  2419                      else
  2420                      {
  2421                          // Remove latest UTF-8 unicode character introduced (n bytes)
  2422                          int charUTF8Length = 0;
  2423                          while ((charUTF8Length < textLength) && ((unsigned char)text[textLength - 1 - charUTF8Length] & 0b01000000) == 0) charUTF8Length++;
  2424  
  2425                          textLength -= (charUTF8Length + 1);
  2426                          text[textLength] = '\0';
  2427                      }
  2428                  }
  2429              }
  2430  
  2431              // Exit edit mode
  2432              if (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
  2433          }
  2434          else
  2435          {
  2436              if (CheckCollisionPointRec(mousePoint, bounds))
  2437              {
  2438                  state = STATE_FOCUSED;
  2439                  if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
  2440              }
  2441          }
  2442      }
  2443      //--------------------------------------------------------------------
  2444  
  2445      // Draw control
  2446      //--------------------------------------------------------------------
  2447      if (state == STATE_PRESSED)
  2448      {
  2449          GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha));
  2450      }
  2451      else if (state == STATE_DISABLED)
  2452      {
  2453          GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)), guiAlpha));
  2454      }
  2455      else GuiDrawRectangle(bounds, 1, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), BLANK);
  2456  
  2457      int wrapMode = 1;      // 0-No wrap, 1-Char wrap, 2-Word wrap
  2458      Vector2 cursorPos = { textAreaBounds.x, textAreaBounds.y };
  2459  
  2460      //int lastSpacePos = 0;
  2461      //int lastSpaceWidth = 0;
  2462      //int lastSpaceCursorPos = 0;
  2463  
  2464      for (int i = 0, codepointSize = 0; text[i] != '\0'; i += codepointSize)
  2465      {
  2466          int codepoint = GetCodepointNext(text + i, &codepointSize);
  2467          int index = GetGlyphIndex(guiFont, codepoint);      // If requested codepoint is not found, we get '?' (0x3f)
  2468          Rectangle atlasRec = guiFont.recs[index];
  2469          GlyphInfo glyphInfo = guiFont.glyphs[index];        // Glyph measures
  2470  
  2471          if ((codepointSize == 1) && (codepoint == '\n'))
  2472          {
  2473              cursorPos.y += (guiFont.baseSize*scaleFactor + GuiGetStyle(TEXTBOX, TEXT_LINES_SPACING));   // Line feed
  2474              cursorPos.x = textAreaBounds.x;                 // Carriage return
  2475          }
  2476          else
  2477          {
  2478              if (wrapMode == 1)
  2479              {
  2480                  int glyphWidth = 0;
  2481                  if (glyphInfo.advanceX != 0) glyphWidth += glyphInfo.advanceX;
  2482                  else glyphWidth += (int)(atlasRec.width + glyphInfo.offsetX);
  2483  
  2484                  // Jump line if the end of the text box area has been reached
  2485                  if ((cursorPos.x + (glyphWidth*scaleFactor)) > (textAreaBounds.x + textAreaBounds.width))
  2486                  {
  2487                      cursorPos.y += (guiFont.baseSize*scaleFactor + GuiGetStyle(TEXTBOX, TEXT_LINES_SPACING));   // Line feed
  2488                      cursorPos.x = textAreaBounds.x;     // Carriage return
  2489                  }
  2490              }
  2491              else if (wrapMode == 2)
  2492              {
  2493                  /*
  2494                  if ((codepointSize == 1) && (codepoint == ' '))
  2495                  {
  2496                      lastSpacePos = i;
  2497                      lastSpaceWidth = 0;
  2498                      lastSpaceCursorPos = cursorPos.x;
  2499                  }
  2500  
  2501                  // Jump line if last word reaches end of text box area
  2502                  if ((lastSpaceCursorPos + lastSpaceWidth) > (textAreaBounds.x + textAreaBounds.width))
  2503                  {
  2504                      cursorPos.y += 12;               // Line feed
  2505                      cursorPos.x = textAreaBounds.x;  // Carriage return
  2506                  }
  2507                  */
  2508              }
  2509  
  2510              // Draw current character glyph
  2511              DrawTextCodepoint(guiFont, codepoint, cursorPos, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha));
  2512  
  2513              int glyphWidth = 0;
  2514              if (glyphInfo.advanceX != 0) glyphWidth += glyphInfo.advanceX;
  2515              else glyphWidth += (int)(atlasRec.width + glyphInfo.offsetX);
  2516  
  2517              cursorPos.x += (glyphWidth*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
  2518              //if (i > lastSpacePos) lastSpaceWidth += (atlasRec.width + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
  2519          }
  2520      }
  2521  
  2522      cursor.x = cursorPos.x;
  2523      cursor.y = cursorPos.y;
  2524  
  2525      // Draw cursor position considering text glyphs
  2526      if (editMode) GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha));
  2527      //--------------------------------------------------------------------
  2528  
  2529      return pressed;
  2530  }
  2531  
  2532  // Slider control with pro parameters
  2533  // NOTE: Other GuiSlider*() controls use this one
  2534  float GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue, int sliderWidth)
  2535  {
  2536      GuiState state = guiState;
  2537  
  2538      int sliderValue = (int)(((value - minValue)/(maxValue - minValue))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH)));
  2539  
  2540      Rectangle slider = { bounds.x, bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),
  2541                           0, bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) };
  2542  
  2543      if (sliderWidth > 0)        // Slider
  2544      {
  2545          slider.x += (sliderValue - sliderWidth/2);
  2546          slider.width = (float)sliderWidth;
  2547      }
  2548      else if (sliderWidth == 0)  // SliderBar
  2549      {
  2550          slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH);
  2551          slider.width = (float)sliderValue;
  2552      }
  2553  
  2554      // Update control
  2555      //--------------------------------------------------------------------
  2556      if ((state != STATE_DISABLED) && !guiLocked)
  2557      {
  2558          Vector2 mousePoint = GetMousePosition();
  2559  
  2560          if (CheckCollisionPointRec(mousePoint, bounds))
  2561          {
  2562              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  2563              {
  2564                  state = STATE_PRESSED;
  2565  
  2566                  // Get equivalent value and slider position from mousePoint.x
  2567                  value = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue;
  2568  
  2569                  if (sliderWidth > 0) slider.x = mousePoint.x - slider.width/2;  // Slider
  2570                  else if (sliderWidth == 0) slider.width = (float)sliderValue;          // SliderBar
  2571              }
  2572              else state = STATE_FOCUSED;
  2573          }
  2574  
  2575          if (value > maxValue) value = maxValue;
  2576          else if (value < minValue) value = minValue;
  2577      }
  2578  
  2579      // Bar limits check
  2580      if (sliderWidth > 0)        // Slider
  2581      {
  2582          if (slider.x <= (bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH);
  2583          else if ((slider.x + slider.width) >= (bounds.x + bounds.width)) slider.x = bounds.x + bounds.width - slider.width - GuiGetStyle(SLIDER, BORDER_WIDTH);
  2584      }
  2585      else if (sliderWidth == 0)  // SliderBar
  2586      {
  2587          if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH);
  2588      }
  2589      //--------------------------------------------------------------------
  2590  
  2591      // Draw control
  2592      //--------------------------------------------------------------------
  2593      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));
  2594  
  2595      // Draw slider internal bar (depends on state)
  2596      if ((state == STATE_NORMAL) || (state == STATE_PRESSED)) GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)), guiAlpha));
  2597      else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED)), guiAlpha));
  2598  
  2599      // Draw left/right text if provided
  2600      if (textLeft != NULL)
  2601      {
  2602          Rectangle textBounds = { 0 };
  2603          textBounds.width = (float)GetTextWidth(textLeft);
  2604          textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2605          textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SLIDER, TEXT_PADDING);
  2606          textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2607  
  2608          GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
  2609      }
  2610  
  2611      if (textRight != NULL)
  2612      {
  2613          Rectangle textBounds = { 0 };
  2614          textBounds.width = (float)GetTextWidth(textRight);
  2615          textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2616          textBounds.x = bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING);
  2617          textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2618  
  2619          GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha));
  2620      }
  2621      //--------------------------------------------------------------------
  2622  
  2623      return value;
  2624  }
  2625  
  2626  // Slider control extended, returns selected value and has text
  2627  float GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue)
  2628  {
  2629      return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, GuiGetStyle(SLIDER, SLIDER_WIDTH));
  2630  }
  2631  
  2632  // Slider Bar control extended, returns selected value
  2633  float GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue)
  2634  {
  2635      return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, 0);
  2636  }
  2637  
  2638  // Progress Bar control extended, shows current progress value
  2639  float GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float value, float minValue, float maxValue)
  2640  {
  2641      GuiState state = guiState;
  2642  
  2643      Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH),
  2644                             bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING), 0,
  2645                             bounds.height - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) };
  2646  
  2647      // Update control
  2648      //--------------------------------------------------------------------
  2649      if (value > maxValue) value = maxValue;
  2650  
  2651      if (state != STATE_DISABLED) progress.width = ((float)(value/(maxValue - minValue))*(float)(bounds.width - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)));
  2652      //--------------------------------------------------------------------
  2653  
  2654      // Draw control
  2655      //--------------------------------------------------------------------
  2656      GuiDrawRectangle(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), guiAlpha), BLANK);
  2657  
  2658      // Draw slider internal progress bar (depends on state)
  2659      if ((state == STATE_NORMAL) || (state == STATE_PRESSED)) GuiDrawRectangle(progress, 0, BLANK, Fade(GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED)), guiAlpha));
  2660      else if (state == STATE_FOCUSED) GuiDrawRectangle(progress, 0, BLANK, Fade(GetColor(GuiGetStyle(PROGRESSBAR, TEXT_COLOR_FOCUSED)), guiAlpha));
  2661  
  2662      // Draw left/right text if provided
  2663      if (textLeft != NULL)
  2664      {
  2665          Rectangle textBounds = { 0 };
  2666          textBounds.width = (float)GetTextWidth(textLeft);
  2667          textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2668          textBounds.x = bounds.x - textBounds.width - GuiGetStyle(PROGRESSBAR, TEXT_PADDING);
  2669          textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2670  
  2671          GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))), guiAlpha));
  2672      }
  2673  
  2674      if (textRight != NULL)
  2675      {
  2676          Rectangle textBounds = { 0 };
  2677          textBounds.width = (float)GetTextWidth(textRight);
  2678          textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  2679          textBounds.x = bounds.x + bounds.width + GuiGetStyle(PROGRESSBAR, TEXT_PADDING);
  2680          textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  2681  
  2682          GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, Fade(GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3))), guiAlpha));
  2683      }
  2684      //--------------------------------------------------------------------
  2685  
  2686      return value;
  2687  }
  2688  
  2689  // Status Bar control
  2690  void GuiStatusBar(Rectangle bounds, const char *text)
  2691  {
  2692      GuiState state = guiState;
  2693  
  2694      // Draw control
  2695      //--------------------------------------------------------------------
  2696      GuiDrawRectangle(bounds, GuiGetStyle(STATUSBAR, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(STATUSBAR, (state != STATE_DISABLED)? BORDER_COLOR_NORMAL : BORDER_COLOR_DISABLED)), guiAlpha),
  2697                       Fade(GetColor(GuiGetStyle(STATUSBAR, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha));
  2698      GuiDrawText(text, GetTextBounds(STATUSBAR, bounds), GuiGetStyle(STATUSBAR, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(STATUSBAR, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED)), guiAlpha));
  2699      //--------------------------------------------------------------------
  2700  }
  2701  
  2702  // Dummy rectangle control, intended for placeholding
  2703  void GuiDummyRec(Rectangle bounds, const char *text)
  2704  {
  2705      GuiState state = guiState;
  2706  
  2707      // Update control
  2708      //--------------------------------------------------------------------
  2709      if ((state != STATE_DISABLED) && !guiLocked)
  2710      {
  2711          Vector2 mousePoint = GetMousePosition();
  2712  
  2713          // Check button state
  2714          if (CheckCollisionPointRec(mousePoint, bounds))
  2715          {
  2716              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
  2717              else state = STATE_FOCUSED;
  2718          }
  2719      }
  2720      //--------------------------------------------------------------------
  2721  
  2722      // Draw control
  2723      //--------------------------------------------------------------------
  2724      GuiDrawRectangle(bounds, 0, BLANK, Fade(GetColor(GuiGetStyle(DEFAULT, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha));
  2725      GuiDrawText(text, GetTextBounds(DEFAULT, bounds), TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(BUTTON, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED)), guiAlpha));
  2726      //------------------------------------------------------------------
  2727  }
  2728  
  2729  // List View control
  2730  int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int active)
  2731  {
  2732      int itemCount = 0;
  2733      const char **items = NULL;
  2734  
  2735      if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
  2736  
  2737      return GuiListViewEx(bounds, items, itemCount, NULL, scrollIndex, active);
  2738  }
  2739  
  2740  // List View control with extended parameters
  2741  int GuiListViewEx(Rectangle bounds, const char **text, int count, int *focus, int *scrollIndex, int active)
  2742  {
  2743      GuiState state = guiState;
  2744      int itemFocused = (focus == NULL)? -1 : *focus;
  2745      int itemSelected = active;
  2746  
  2747      // Check if we need a scroll bar
  2748      bool useScrollBar = false;
  2749      if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING))*count > bounds.height) useScrollBar = true;
  2750  
  2751      // Define base item rectangle [0]
  2752      Rectangle itemBounds = { 0 };
  2753      itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING);
  2754      itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
  2755      itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) - GuiGetStyle(DEFAULT, BORDER_WIDTH);
  2756      itemBounds.height = (float)GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
  2757      if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
  2758  
  2759      // Get items on the list
  2760      int visibleItems = (int)bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING));
  2761      if (visibleItems > count) visibleItems = count;
  2762  
  2763      int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex;
  2764      if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0;
  2765      int endIndex = startIndex + visibleItems;
  2766  
  2767      // Update control
  2768      //--------------------------------------------------------------------
  2769      if ((state != STATE_DISABLED) && !guiLocked)
  2770      {
  2771          Vector2 mousePoint = GetMousePosition();
  2772  
  2773          // Check mouse inside list view
  2774          if (CheckCollisionPointRec(mousePoint, bounds))
  2775          {
  2776              state = STATE_FOCUSED;
  2777  
  2778              // Check focused and selected item
  2779              for (int i = 0; i < visibleItems; i++)
  2780              {
  2781                  if (CheckCollisionPointRec(mousePoint, itemBounds))
  2782                  {
  2783                      itemFocused = startIndex + i;
  2784                      if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
  2785                      {
  2786                          if (itemSelected == (startIndex + i)) itemSelected = -1;
  2787                          else itemSelected = startIndex + i;
  2788                      }
  2789                      break;
  2790                  }
  2791  
  2792                  // Update item rectangle y position for next item
  2793                  itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING));
  2794              }
  2795  
  2796              if (useScrollBar)
  2797              {
  2798                  int wheelMove = (int)GetMouseWheelMove();
  2799                  startIndex -= wheelMove;
  2800  
  2801                  if (startIndex < 0) startIndex = 0;
  2802                  else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems;
  2803  
  2804                  endIndex = startIndex + visibleItems;
  2805                  if (endIndex > count) endIndex = count;
  2806              }
  2807          }
  2808          else itemFocused = -1;
  2809  
  2810          // Reset item rectangle y to [0]
  2811          itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
  2812      }
  2813      //--------------------------------------------------------------------
  2814  
  2815      // Draw control
  2816      //--------------------------------------------------------------------
  2817      GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));     // Draw background
  2818  
  2819      // Draw visible items
  2820      for (int i = 0; ((i < visibleItems) && (text != NULL)); i++)
  2821      {
  2822          if (state == STATE_DISABLED)
  2823          {
  2824              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));
  2825  
  2826              GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha));
  2827          }
  2828          else
  2829          {
  2830              if ((startIndex + i) == itemSelected)
  2831              {
  2832                  // Draw item selected
  2833                  GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), guiAlpha), Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha));
  2834                  GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)), guiAlpha));
  2835              }
  2836              else if ((startIndex + i) == itemFocused)
  2837              {
  2838                  // Draw item focused
  2839                  GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), guiAlpha), Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha));
  2840                  GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)), guiAlpha));
  2841              }
  2842              else
  2843              {
  2844                  // Draw item normal
  2845                  GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)), guiAlpha));
  2846              }
  2847          }
  2848  
  2849          // Update item rectangle y position for next item
  2850          itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING));
  2851      }
  2852  
  2853      if (useScrollBar)
  2854      {
  2855          Rectangle scrollBarBounds = {
  2856              bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
  2857              bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
  2858              bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)
  2859          };
  2860  
  2861          // Calculate percentage of visible items and apply same percentage to scrollbar
  2862          float percentVisible = (float)(endIndex - startIndex)/count;
  2863          float sliderSize = bounds.height*percentVisible;
  2864  
  2865          int prevSliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);   // Save default slider size
  2866          int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed
  2867          GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)sliderSize);            // Change slider size
  2868          GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed
  2869  
  2870          startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems);
  2871  
  2872          GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default
  2873          GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, prevSliderSize); // Reset slider size to default
  2874      }
  2875      //--------------------------------------------------------------------
  2876  
  2877      if (focus != NULL) *focus = itemFocused;
  2878      if (scrollIndex != NULL) *scrollIndex = startIndex;
  2879  
  2880      return itemSelected;
  2881  }
  2882  
  2883  // Color Panel control
  2884  Color GuiColorPanel(Rectangle bounds, const char *text, Color color)
  2885  {
  2886      const Color colWhite = { 255, 255, 255, 255 };
  2887      const Color colBlack = { 0, 0, 0, 255 };
  2888  
  2889      GuiState state = guiState;
  2890      Vector2 pickerSelector = { 0 };
  2891  
  2892      Vector3 vcolor = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
  2893      Vector3 hsv = ConvertRGBtoHSV(vcolor);
  2894  
  2895      pickerSelector.x = bounds.x + (float)hsv.y*bounds.width;            // HSV: Saturation
  2896      pickerSelector.y = bounds.y + (1.0f - (float)hsv.z)*bounds.height;  // HSV: Value
  2897  
  2898      float hue = -1.0f;
  2899      Vector3 maxHue = { hue >= 0.0f ? hue : hsv.x, 1.0f, 1.0f };
  2900      Vector3 rgbHue = ConvertHSVtoRGB(maxHue);
  2901      Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x),
  2902                        (unsigned char)(255.0f*rgbHue.y),
  2903                        (unsigned char)(255.0f*rgbHue.z), 255 };
  2904  
  2905      // Update control
  2906      //--------------------------------------------------------------------
  2907      if ((state != STATE_DISABLED) && !guiLocked)
  2908      {
  2909          Vector2 mousePoint = GetMousePosition();
  2910  
  2911          if (CheckCollisionPointRec(mousePoint, bounds))
  2912          {
  2913              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  2914              {
  2915                  state = STATE_PRESSED;
  2916                  pickerSelector = mousePoint;
  2917  
  2918                  // Calculate color from picker
  2919                  Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y };
  2920  
  2921                  colorPick.x /= (float)bounds.width;     // Get normalized value on x
  2922                  colorPick.y /= (float)bounds.height;    // Get normalized value on y
  2923  
  2924                  hsv.y = colorPick.x;
  2925                  hsv.z = 1.0f - colorPick.y;
  2926  
  2927                  Vector3 rgb = ConvertHSVtoRGB(hsv);
  2928  
  2929                  // NOTE: Vector3ToColor() only available on raylib 1.8.1
  2930                  color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x),
  2931                                   (unsigned char)(255.0f*rgb.y),
  2932                                   (unsigned char)(255.0f*rgb.z),
  2933                                   (unsigned char)(255.0f*(float)color.a/255.0f) };
  2934  
  2935              }
  2936              else state = STATE_FOCUSED;
  2937          }
  2938      }
  2939      //--------------------------------------------------------------------
  2940  
  2941      // Draw control
  2942      //--------------------------------------------------------------------
  2943      if (state != STATE_DISABLED)
  2944      {
  2945          DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha));
  2946          DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0));
  2947  
  2948          // Draw color picker: selector
  2949          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) };
  2950          GuiDrawRectangle(selector, 0, BLANK, Fade(colWhite, guiAlpha));
  2951      }
  2952      else
  2953      {
  2954          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));
  2955      }
  2956  
  2957      GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha), BLANK);
  2958      //--------------------------------------------------------------------
  2959  
  2960      return color;
  2961  }
  2962  
  2963  // Color Bar Alpha control
  2964  // NOTE: Returns alpha value normalized [0..1]
  2965  float GuiColorBarAlpha(Rectangle bounds, const char *text, float alpha)
  2966  {
  2967      #if !defined(RAYGUI_COLORBARALPHA_CHECKED_SIZE)
  2968          #define RAYGUI_COLORBARALPHA_CHECKED_SIZE   10
  2969      #endif
  2970  
  2971      GuiState state = guiState;
  2972      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 };
  2973  
  2974      // Update control
  2975      //--------------------------------------------------------------------
  2976      if ((state != STATE_DISABLED) && !guiLocked)
  2977      {
  2978          Vector2 mousePoint = GetMousePosition();
  2979  
  2980          if (CheckCollisionPointRec(mousePoint, bounds) ||
  2981              CheckCollisionPointRec(mousePoint, selector))
  2982          {
  2983              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  2984              {
  2985                  state = STATE_PRESSED;
  2986  
  2987                  alpha = (mousePoint.x - bounds.x)/bounds.width;
  2988                  if (alpha <= 0.0f) alpha = 0.0f;
  2989                  if (alpha >= 1.0f) alpha = 1.0f;
  2990                  //selector.x = bounds.x + (int)(((alpha - 0)/(100 - 0))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))) - selector.width/2;
  2991              }
  2992              else state = STATE_FOCUSED;
  2993          }
  2994      }
  2995      //--------------------------------------------------------------------
  2996  
  2997      // Draw control
  2998      //--------------------------------------------------------------------
  2999  
  3000      // Draw alpha bar: checked background
  3001      if (state != STATE_DISABLED)
  3002      {
  3003          int checksX = (int)bounds.width/RAYGUI_COLORBARALPHA_CHECKED_SIZE;
  3004          int checksY = (int)bounds.height/RAYGUI_COLORBARALPHA_CHECKED_SIZE;
  3005  
  3006          for (int x = 0; x < checksX; x++)
  3007          {
  3008              for (int y = 0; y < checksY; y++)
  3009              {
  3010                  Rectangle check = { bounds.x + x*RAYGUI_COLORBARALPHA_CHECKED_SIZE, bounds.y + y*RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE };
  3011                  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));
  3012              }
  3013          }
  3014  
  3015          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));
  3016      }
  3017      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));
  3018  
  3019      GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha), BLANK);
  3020  
  3021      // Draw alpha bar: selector
  3022      GuiDrawRectangle(selector, 0, BLANK, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha));
  3023      //--------------------------------------------------------------------
  3024  
  3025      return alpha;
  3026  }
  3027  
  3028  // Color Bar Hue control
  3029  // Returns hue value normalized [0..1]
  3030  // NOTE: Other similar bars (for reference):
  3031  //      Color GuiColorBarSat() [WHITE->color]
  3032  //      Color GuiColorBarValue() [BLACK->color], HSV/HSL
  3033  //      float GuiColorBarLuminance() [BLACK->WHITE]
  3034  float GuiColorBarHue(Rectangle bounds, const char *text, float hue)
  3035  {
  3036      GuiState state = guiState;
  3037      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) };
  3038  
  3039      // Update control
  3040      //--------------------------------------------------------------------
  3041      if ((state != STATE_DISABLED) && !guiLocked)
  3042      {
  3043          Vector2 mousePoint = GetMousePosition();
  3044  
  3045          if (CheckCollisionPointRec(mousePoint, bounds) ||
  3046              CheckCollisionPointRec(mousePoint, selector))
  3047          {
  3048              if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  3049              {
  3050                  state = STATE_PRESSED;
  3051  
  3052                  hue = (mousePoint.y - bounds.y)*360/bounds.height;
  3053                  if (hue <= 0.0f) hue = 0.0f;
  3054                  if (hue >= 359.0f) hue = 359.0f;
  3055  
  3056              }
  3057              else state = STATE_FOCUSED;
  3058  
  3059              /*if (IsKeyDown(KEY_UP))
  3060              {
  3061                  hue -= 2.0f;
  3062                  if (hue <= 0.0f) hue = 0.0f;
  3063              }
  3064              else if (IsKeyDown(KEY_DOWN))
  3065              {
  3066                  hue += 2.0f;
  3067                  if (hue >= 360.0f) hue = 360.0f;
  3068              }*/
  3069          }
  3070      }
  3071      //--------------------------------------------------------------------
  3072  
  3073      // Draw control
  3074      //--------------------------------------------------------------------
  3075      if (state != STATE_DISABLED)
  3076      {
  3077          // Draw hue bar:color bars
  3078          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));
  3079          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));
  3080          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));
  3081          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));
  3082          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));
  3083          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));
  3084      }
  3085      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));
  3086  
  3087      GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha), BLANK);
  3088  
  3089      // Draw hue bar: selector
  3090      GuiDrawRectangle(selector, 0, BLANK, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha));
  3091      //--------------------------------------------------------------------
  3092  
  3093      return hue;
  3094  }
  3095  
  3096  // Color Picker control
  3097  // NOTE: It's divided in multiple controls:
  3098  //      Color GuiColorPanel(Rectangle bounds, Color color)
  3099  //      float GuiColorBarAlpha(Rectangle bounds, float alpha)
  3100  //      float GuiColorBarHue(Rectangle bounds, float value)
  3101  // NOTE: bounds define GuiColorPanel() size
  3102  Color GuiColorPicker(Rectangle bounds, const char *text, Color color)
  3103  {
  3104      color = GuiColorPanel(bounds, NULL, color);
  3105  
  3106      Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height };
  3107      //Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) };
  3108  
  3109      Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ color.r/255.0f, color.g/255.0f, color.b/255.0f });
  3110      hsv.x = GuiColorBarHue(boundsHue, NULL, hsv.x);
  3111      //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f);
  3112      Vector3 rgb = ConvertHSVtoRGB(hsv);
  3113  
  3114      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 };
  3115  
  3116      return color;
  3117  }
  3118  
  3119  // Message Box control
  3120  int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons)
  3121  {
  3122      #if !defined(RAYGUI_MESSAGEBOX_BUTTON_HEIGHT)
  3123          #define RAYGUI_MESSAGEBOX_BUTTON_HEIGHT    24
  3124      #endif
  3125      #if !defined(RAYGUI_MESSAGEBOX_BUTTON_PADDING)
  3126          #define RAYGUI_MESSAGEBOX_BUTTON_PADDING   12
  3127      #endif
  3128  
  3129      int clicked = -1;    // Returns clicked button from buttons list, 0 refers to closed window button
  3130  
  3131      int buttonCount = 0;
  3132      const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
  3133      Rectangle buttonBounds = { 0 };
  3134      buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
  3135      buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING;
  3136      buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount;
  3137      buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT;
  3138  
  3139      int textWidth = GetTextWidth(message);
  3140  
  3141      Rectangle textBounds = { 0 };
  3142      textBounds.x = bounds.x + bounds.width/2 - textWidth/2;
  3143      textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
  3144      textBounds.width = (float)textWidth;
  3145      textBounds.height = bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 3*RAYGUI_MESSAGEBOX_BUTTON_PADDING - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT;
  3146  
  3147      // Draw control
  3148      //--------------------------------------------------------------------
  3149      if (GuiWindowBox(bounds, title)) clicked = 0;
  3150  
  3151      int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT);
  3152      GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  3153      GuiLabel(textBounds, message);
  3154      GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment);
  3155  
  3156      prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  3157      GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  3158  
  3159      for (int i = 0; i < buttonCount; i++)
  3160      {
  3161          if (GuiButton(buttonBounds, buttonsText[i])) clicked = i + 1;
  3162          buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING);
  3163      }
  3164  
  3165      GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevTextAlignment);
  3166      //--------------------------------------------------------------------
  3167  
  3168      return clicked;
  3169  }
  3170  
  3171  // Text Input Box control, ask for text
  3172  int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, int *secretViewActive)
  3173  {
  3174      #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT)
  3175          #define RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT      24
  3176      #endif
  3177      #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_PADDING)
  3178          #define RAYGUI_TEXTINPUTBOX_BUTTON_PADDING     12
  3179      #endif
  3180      #if !defined(RAYGUI_TEXTINPUTBOX_HEIGHT)
  3181          #define RAYGUI_TEXTINPUTBOX_HEIGHT             26
  3182      #endif
  3183  
  3184      // Used to enable text edit mode
  3185      // WARNING: No more than one GuiTextInputBox() should be open at the same time
  3186      static bool textEditMode = false;
  3187  
  3188      int btnIndex = -1;
  3189  
  3190      int buttonCount = 0;
  3191      const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
  3192      Rectangle buttonBounds = { 0 };
  3193      buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
  3194      buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
  3195      buttonBounds.width = (bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount;
  3196      buttonBounds.height = RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT;
  3197  
  3198      int messageInputHeight = (int)bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - 2*RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
  3199  
  3200      Rectangle textBounds = { 0 };
  3201      if (message != NULL)
  3202      {
  3203          int textSize = GetTextWidth(message);
  3204  
  3205          textBounds.x = bounds.x + bounds.width/2 - textSize/2;
  3206          textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight/4 - (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
  3207          textBounds.width = (float)textSize;
  3208          textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  3209      }
  3210  
  3211      Rectangle textBoxBounds = { 0 };
  3212      textBoxBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
  3213      textBoxBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_TEXTINPUTBOX_HEIGHT/2;
  3214      if (message == NULL) textBoxBounds.y = bounds.y + 24 + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
  3215      else textBoxBounds.y += (messageInputHeight/2 + messageInputHeight/4);
  3216      textBoxBounds.width = bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*2;
  3217      textBoxBounds.height = RAYGUI_TEXTINPUTBOX_HEIGHT;
  3218  
  3219      // Draw control
  3220      //--------------------------------------------------------------------
  3221      if (GuiWindowBox(bounds, title)) btnIndex = 0;
  3222  
  3223      // Draw message if available
  3224      if (message != NULL)
  3225      {
  3226          int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT);
  3227          GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  3228          GuiLabel(textBounds, message);
  3229          GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment);
  3230      }
  3231  
  3232      if (secretViewActive != NULL)
  3233      {
  3234          static char stars[] = "****************";
  3235          if (GuiTextBox(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x, textBoxBounds.y, textBoxBounds.width - 4 - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.height },
  3236              ((*secretViewActive == 1) || textEditMode)? text : stars, textMaxSize, textEditMode)) textEditMode = !textEditMode;
  3237  
  3238          *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);
  3239      }
  3240      else
  3241      {
  3242          if (GuiTextBox(textBoxBounds, text, textMaxSize, textEditMode)) textEditMode = !textEditMode;
  3243      }
  3244  
  3245      int prevBtnTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
  3246      GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
  3247  
  3248      for (int i = 0; i < buttonCount; i++)
  3249      {
  3250          if (GuiButton(buttonBounds, buttonsText[i])) btnIndex = i + 1;
  3251          buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING);
  3252      }
  3253  
  3254      GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevBtnTextAlignment);
  3255      //--------------------------------------------------------------------
  3256  
  3257      return btnIndex;
  3258  }
  3259  
  3260  // Grid control
  3261  // NOTE: Returns grid mouse-hover selected cell
  3262  // About drawing lines at subpixel spacing, simple put, not easy solution:
  3263  // https://stackoverflow.com/questions/4435450/2d-opengl-drawing-lines-that-dont-exactly-fit-pixel-raster
  3264  Vector2 GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs)
  3265  {
  3266      // Grid lines alpha amount
  3267      #if !defined(RAYGUI_GRID_ALPHA)
  3268          #define RAYGUI_GRID_ALPHA    0.15f
  3269      #endif
  3270  
  3271      GuiState state = guiState;
  3272      Vector2 mousePoint = GetMousePosition();
  3273      Vector2 currentCell = { -1, -1 };
  3274  
  3275      int linesV = ((int)(bounds.width/spacing))*subdivs + 1;
  3276      int linesH = ((int)(bounds.height/spacing))*subdivs + 1;
  3277  
  3278      // Update control
  3279      //--------------------------------------------------------------------
  3280      if ((state != STATE_DISABLED) && !guiLocked)
  3281      {
  3282          if (CheckCollisionPointRec(mousePoint, bounds))
  3283          {
  3284              // NOTE: Cell values must be the upper left of the cell the mouse is in
  3285              currentCell.x = floorf((mousePoint.x - bounds.x)/spacing);
  3286              currentCell.y = floorf((mousePoint.y - bounds.y)/spacing);
  3287          }
  3288      }
  3289      //--------------------------------------------------------------------
  3290  
  3291      // Draw control
  3292      //--------------------------------------------------------------------
  3293  
  3294      // TODO: Draw background panel?
  3295  
  3296      switch (state)
  3297      {
  3298          case STATE_NORMAL:
  3299          {
  3300              if (subdivs > 0)
  3301              {
  3302                  // Draw vertical grid lines
  3303                  for (int i = 0; i < linesV; i++)
  3304                  {
  3305                      Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height };
  3306                      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));
  3307                  }
  3308  
  3309                  // Draw horizontal grid lines
  3310                  for (int i = 0; i < linesH; i++)
  3311                  {
  3312                      Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width, 1 };
  3313                      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));
  3314                  }
  3315              }
  3316          } break;
  3317          default: break;
  3318      }
  3319  
  3320      return currentCell;
  3321  }
  3322  
  3323  //----------------------------------------------------------------------------------
  3324  // Styles loading functions
  3325  //----------------------------------------------------------------------------------
  3326  
  3327  // Load raygui style file (.rgs)
  3328  // NOTE: By default a binary file is expected, that file could contain a custom font,
  3329  // in that case, custom font image atlas is GRAY+ALPHA and pixel data can be compressed (DEFLATE)
  3330  void GuiLoadStyle(const char *fileName)
  3331  {
  3332      #define MAX_LINE_BUFFER_SIZE    256
  3333  
  3334      bool tryBinary = false;
  3335  
  3336      // Try reading the files as text file first
  3337      FILE *rgsFile = fopen(fileName, "rt");
  3338  
  3339      if (rgsFile != NULL)
  3340      {
  3341          char buffer[MAX_LINE_BUFFER_SIZE] = { 0 };
  3342          fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile);
  3343  
  3344          if (buffer[0] == '#')
  3345          {
  3346              int controlId = 0;
  3347              int propertyId = 0;
  3348              unsigned int propertyValue = 0;
  3349  
  3350              while (!feof(rgsFile))
  3351              {
  3352                  switch (buffer[0])
  3353                  {
  3354                      case 'p':
  3355                      {
  3356                          // Style property: p <control_id> <property_id> <property_value> <property_name>
  3357  
  3358                          sscanf(buffer, "p %d %d 0x%x", &controlId, &propertyId, &propertyValue);
  3359                          GuiSetStyle(controlId, propertyId, (int)propertyValue);
  3360  
  3361                      } break;
  3362                      case 'f':
  3363                      {
  3364                          // Style font: f <gen_font_size> <charmap_file> <font_file>
  3365  
  3366                          int fontSize = 0;
  3367                          char charmapFileName[256] = { 0 };
  3368                          char fontFileName[256] = { 0 };
  3369                          sscanf(buffer, "f %d %s %[^\r\n]s", &fontSize, charmapFileName, fontFileName);
  3370  
  3371                          Font font = { 0 };
  3372  
  3373                          if (charmapFileName[0] != '0')
  3374                          {
  3375                              // Load characters from charmap file,
  3376                              // expected '\n' separated list of integer values
  3377                              char *charValues = LoadFileText(charmapFileName);
  3378                              if (charValues != NULL)
  3379                              {
  3380                                  int glyphCount = 0;
  3381                                  const char **chars = TextSplit(charValues, '\n', &glyphCount);
  3382  
  3383                                  int *values = (int *)RAYGUI_MALLOC(glyphCount*sizeof(int));
  3384                                  for (int i = 0; i < glyphCount; i++) values[i] = TextToInteger(chars[i]);
  3385  
  3386                                  if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
  3387                                  font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, values, glyphCount);
  3388                                  if (font.texture.id == 0) font = GetFontDefault();
  3389  
  3390                                  RAYGUI_FREE(values);
  3391                              }
  3392                          }
  3393                          else
  3394                          {
  3395                              if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
  3396                              font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0);
  3397                              if (font.texture.id == 0) font = GetFontDefault();
  3398                          }
  3399  
  3400                          if ((font.texture.id > 0) && (font.glyphCount > 0)) GuiSetFont(font);
  3401  
  3402                      } break;
  3403                      default: break;
  3404                  }
  3405  
  3406                  fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile);
  3407              }
  3408          }
  3409          else tryBinary = true;
  3410  
  3411          fclose(rgsFile);
  3412      }
  3413  
  3414      if (tryBinary)
  3415      {
  3416          rgsFile = fopen(fileName, "rb");
  3417  
  3418          if (rgsFile == NULL) return;
  3419  
  3420          char signature[5] = { 0 };
  3421          short version = 0;
  3422          short reserved = 0;
  3423          int propertyCount = 0;
  3424  
  3425          fread(signature, 1, 4, rgsFile);
  3426          fread(&version, 1, sizeof(short), rgsFile);
  3427          fread(&reserved, 1, sizeof(short), rgsFile);
  3428          fread(&propertyCount, 1, sizeof(int), rgsFile);
  3429  
  3430          if ((signature[0] == 'r') &&
  3431              (signature[1] == 'G') &&
  3432              (signature[2] == 'S') &&
  3433              (signature[3] == ' '))
  3434          {
  3435              short controlId = 0;
  3436              short propertyId = 0;
  3437              unsigned int propertyValue = 0;
  3438  
  3439              for (int i = 0; i < propertyCount; i++)
  3440              {
  3441                  fread(&controlId, 1, sizeof(short), rgsFile);
  3442                  fread(&propertyId, 1, sizeof(short), rgsFile);
  3443                  fread(&propertyValue, 1, sizeof(unsigned int), rgsFile);
  3444  
  3445                  if (controlId == 0) // DEFAULT control
  3446                  {
  3447                      // If a DEFAULT property is loaded, it is propagated to all controls
  3448                      // NOTE: All DEFAULT properties should be defined first in the file
  3449                      GuiSetStyle(0, (int)propertyId, propertyValue);
  3450  
  3451                      if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) GuiSetStyle(i, (int)propertyId, propertyValue);
  3452                  }
  3453                  else GuiSetStyle((int)controlId, (int)propertyId, propertyValue);
  3454              }
  3455  
  3456              // Font loading is highly dependant on raylib API to load font data and image
  3457  #if !defined(RAYGUI_STANDALONE)
  3458              // Load custom font if available
  3459              int fontDataSize = 0;
  3460              fread(&fontDataSize, 1, sizeof(int), rgsFile);
  3461  
  3462              if (fontDataSize > 0)
  3463              {
  3464                  Font font = { 0 };
  3465                  int fontType = 0;   // 0-Normal, 1-SDF
  3466                  Rectangle whiteRec = { 0 };
  3467  
  3468                  fread(&font.baseSize, 1, sizeof(int), rgsFile);
  3469                  fread(&font.glyphCount, 1, sizeof(int), rgsFile);
  3470                  fread(&fontType, 1, sizeof(int), rgsFile);
  3471  
  3472                  // Load font white rectangle
  3473                  fread(&whiteRec, 1, sizeof(Rectangle), rgsFile);
  3474  
  3475                  // Load font image parameters
  3476                  int fontImageUncompSize = 0;
  3477                  int fontImageCompSize = 0;
  3478                  fread(&fontImageUncompSize, 1, sizeof(int), rgsFile);
  3479                  fread(&fontImageCompSize, 1, sizeof(int), rgsFile);
  3480  
  3481                  Image imFont = { 0 };
  3482                  imFont.mipmaps = 1;
  3483                  fread(&imFont.width, 1, sizeof(int), rgsFile);
  3484                  fread(&imFont.height, 1, sizeof(int), rgsFile);
  3485                  fread(&imFont.format, 1, sizeof(int), rgsFile);
  3486  
  3487                  if (fontImageCompSize < fontImageUncompSize)
  3488                  {
  3489                      // Compressed font atlas image data (DEFLATE), it requires DecompressData()
  3490                      int dataUncompSize = 0;
  3491                      unsigned char *compData = (unsigned char *)RAYGUI_MALLOC(fontImageCompSize);
  3492                      fread(compData, 1, fontImageCompSize, rgsFile);
  3493                      imFont.data = DecompressData(compData, fontImageCompSize, &dataUncompSize);
  3494  
  3495                      // Security check, dataUncompSize must match the provided fontImageUncompSize
  3496                      if (dataUncompSize != fontImageUncompSize) RAYGUI_LOG("WARNING: Uncompressed font atlas image data could be corrupted");
  3497  
  3498                      RAYGUI_FREE(compData);
  3499                  }
  3500                  else
  3501                  {
  3502                      // Font atlas image data is not compressed
  3503                      imFont.data = (unsigned char *)RAYGUI_MALLOC(fontImageUncompSize);
  3504                      fread(imFont.data, 1, fontImageUncompSize, rgsFile);
  3505                  }
  3506  
  3507                  if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
  3508                  font.texture = LoadTextureFromImage(imFont);
  3509                  if (font.texture.id == 0) font = GetFontDefault();
  3510  
  3511                  RAYGUI_FREE(imFont.data);
  3512  
  3513                  // Load font recs data
  3514                  font.recs = (Rectangle *)RAYGUI_CALLOC(font.glyphCount, sizeof(Rectangle));
  3515                  for (int i = 0; i < font.glyphCount; i++) fread(&font.recs[i], 1, sizeof(Rectangle), rgsFile);
  3516  
  3517                  // Load font chars info data
  3518                  font.glyphs = (GlyphInfo *)RAYGUI_CALLOC(font.glyphCount, sizeof(GlyphInfo));
  3519                  for (int i = 0; i < font.glyphCount; i++)
  3520                  {
  3521                      fread(&font.glyphs[i].value, 1, sizeof(int), rgsFile);
  3522                      fread(&font.glyphs[i].offsetX, 1, sizeof(int), rgsFile);
  3523                      fread(&font.glyphs[i].offsetY, 1, sizeof(int), rgsFile);
  3524                      fread(&font.glyphs[i].advanceX, 1, sizeof(int), rgsFile);
  3525                  }
  3526  
  3527                  GuiSetFont(font);
  3528  
  3529                  // Set font texture source rectangle to be used as white texture to draw shapes
  3530                  // NOTE: This way, all gui can be draw using a single draw call
  3531                  if ((whiteRec.width != 0) && (whiteRec.height != 0)) SetShapesTexture(font.texture, whiteRec);
  3532              }
  3533  #endif
  3534          }
  3535  
  3536          fclose(rgsFile);
  3537      }
  3538  }
  3539  
  3540  // Load style default over global style
  3541  void GuiLoadStyleDefault(void)
  3542  {
  3543      // We set this variable first to avoid cyclic function calls
  3544      // when calling GuiSetStyle() and GuiGetStyle()
  3545      guiStyleLoaded = true;
  3546  
  3547      // Initialize default LIGHT style property values
  3548      GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x838383ff);
  3549      GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0xc9c9c9ff);
  3550      GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0x686868ff);
  3551      GuiSetStyle(DEFAULT, BORDER_COLOR_FOCUSED, 0x5bb2d9ff);
  3552      GuiSetStyle(DEFAULT, BASE_COLOR_FOCUSED, 0xc9effeff);
  3553      GuiSetStyle(DEFAULT, TEXT_COLOR_FOCUSED, 0x6c9bbcff);
  3554      GuiSetStyle(DEFAULT, BORDER_COLOR_PRESSED, 0x0492c7ff);
  3555      GuiSetStyle(DEFAULT, BASE_COLOR_PRESSED, 0x97e8ffff);
  3556      GuiSetStyle(DEFAULT, TEXT_COLOR_PRESSED, 0x368bafff);
  3557      GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, 0xb5c1c2ff);
  3558      GuiSetStyle(DEFAULT, BASE_COLOR_DISABLED, 0xe6e9e9ff);
  3559      GuiSetStyle(DEFAULT, TEXT_COLOR_DISABLED, 0xaeb7b8ff);
  3560      GuiSetStyle(DEFAULT, BORDER_WIDTH, 1);                       // WARNING: Some controls use other values
  3561      GuiSetStyle(DEFAULT, TEXT_PADDING, 0);                       // WARNING: Some controls use other values
  3562      GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); // WARNING: Some controls use other values
  3563  
  3564      // Initialize control-specific property values
  3565      // NOTE: Those properties are in default list but require specific values by control type
  3566      GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  3567      GuiSetStyle(BUTTON, BORDER_WIDTH, 2);
  3568      GuiSetStyle(SLIDER, TEXT_PADDING, 4);
  3569      GuiSetStyle(CHECKBOX, TEXT_PADDING, 4);
  3570      GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, TEXT_ALIGN_RIGHT);
  3571      GuiSetStyle(TEXTBOX, TEXT_PADDING, 4);
  3572      GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  3573      GuiSetStyle(VALUEBOX, TEXT_PADDING, 0);
  3574      GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  3575      GuiSetStyle(SPINNER, TEXT_PADDING, 0);
  3576      GuiSetStyle(SPINNER, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  3577      GuiSetStyle(STATUSBAR, TEXT_PADDING, 8);
  3578      GuiSetStyle(STATUSBAR, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
  3579  
  3580      // Initialize extended property values
  3581      // NOTE: By default, extended property values are initialized to 0
  3582      GuiSetStyle(DEFAULT, TEXT_SIZE, 10);                // DEFAULT, shared by all controls
  3583      GuiSetStyle(DEFAULT, TEXT_SPACING, 1);              // DEFAULT, shared by all controls
  3584      GuiSetStyle(DEFAULT, LINE_COLOR, 0x90abb5ff);       // DEFAULT specific property
  3585      GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xf5f5f5ff); // DEFAULT specific property
  3586      GuiSetStyle(TOGGLE, GROUP_PADDING, 2);
  3587      GuiSetStyle(SLIDER, SLIDER_WIDTH, 16);
  3588      GuiSetStyle(SLIDER, SLIDER_PADDING, 1);
  3589      GuiSetStyle(PROGRESSBAR, PROGRESS_PADDING, 1);
  3590      GuiSetStyle(CHECKBOX, CHECK_PADDING, 1);
  3591      GuiSetStyle(COMBOBOX, COMBO_BUTTON_WIDTH, 32);
  3592      GuiSetStyle(COMBOBOX, COMBO_BUTTON_SPACING, 2);
  3593      GuiSetStyle(DROPDOWNBOX, ARROW_PADDING, 16);
  3594      GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 2);
  3595      GuiSetStyle(TEXTBOX, TEXT_LINES_SPACING, 4);
  3596      GuiSetStyle(TEXTBOX, TEXT_INNER_PADDING, 4);
  3597      GuiSetStyle(SPINNER, SPIN_BUTTON_WIDTH, 24);
  3598      GuiSetStyle(SPINNER, SPIN_BUTTON_SPACING, 2);
  3599      GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0);
  3600      GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0);
  3601      GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6);
  3602      GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, 0);
  3603      GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, 16);
  3604      GuiSetStyle(SCROLLBAR, SCROLL_PADDING, 0);
  3605      GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 12);
  3606      GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 28);
  3607      GuiSetStyle(LISTVIEW, LIST_ITEMS_SPACING, 2);
  3608      GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 12);
  3609      GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE);
  3610      GuiSetStyle(COLORPICKER, COLOR_SELECTOR_SIZE, 8);
  3611      GuiSetStyle(COLORPICKER, HUEBAR_WIDTH, 16);
  3612      GuiSetStyle(COLORPICKER, HUEBAR_PADDING, 8);
  3613      GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT, 8);
  3614      GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW, 2);
  3615  
  3616      if (guiFont.texture.id != GetFontDefault().texture.id)
  3617      {
  3618          // Unload previous font texture
  3619          UnloadTexture(guiFont.texture);
  3620  
  3621          // Setup default raylib font
  3622          guiFont = GetFontDefault();
  3623  
  3624          // Setup default raylib font rectangle
  3625          Rectangle whiteChar = { 41, 46, 2, 8 };
  3626          SetShapesTexture(guiFont.texture, whiteChar);
  3627      }
  3628  }
  3629  
  3630  // Get text with icon id prepended
  3631  // NOTE: Useful to add icons by name id (enum) instead of
  3632  // a number that can change between ricon versions
  3633  const char *GuiIconText(int iconId, const char *text)
  3634  {
  3635  #if defined(RAYGUI_NO_ICONS)
  3636      return NULL;
  3637  #else
  3638      static char buffer[1024] = { 0 };
  3639      static char iconBuffer[6] = { 0 };
  3640  
  3641      if (text != NULL)
  3642      {
  3643          memset(buffer, 0, 1024);
  3644          sprintf(buffer, "#%03i#", iconId);
  3645  
  3646          for (int i = 5; i < 1024; i++)
  3647          {
  3648              buffer[i] = text[i - 5];
  3649              if (text[i - 5] == '\0') break;
  3650          }
  3651  
  3652          return buffer;
  3653      }
  3654      else
  3655      {
  3656          sprintf(iconBuffer, "#%03i#", iconId & 0x1ff);
  3657  
  3658          return iconBuffer;
  3659      }
  3660  #endif
  3661  }
  3662  
  3663  #if !defined(RAYGUI_NO_ICONS)
  3664  // Get full icons data pointer
  3665  unsigned int *GuiGetIcons(void) { return guiIconsPtr; }
  3666  
  3667  // Load raygui icons file (.rgi)
  3668  // NOTE: In case nameIds are required, they can be requested with loadIconsName,
  3669  // they are returned as a guiIconsName[iconCount][RAYGUI_ICON_MAX_NAME_LENGTH],
  3670  // WARNING: guiIconsName[]][] memory should be manually freed!
  3671  char **GuiLoadIcons(const char *fileName, bool loadIconsName)
  3672  {
  3673      // Style File Structure (.rgi)
  3674      // ------------------------------------------------------
  3675      // Offset  | Size    | Type       | Description
  3676      // ------------------------------------------------------
  3677      // 0       | 4       | char       | Signature: "rGI "
  3678      // 4       | 2       | short      | Version: 100
  3679      // 6       | 2       | short      | reserved
  3680  
  3681      // 8       | 2       | short      | Num icons (N)
  3682      // 10      | 2       | short      | Icons size (Options: 16, 32, 64) (S)
  3683  
  3684      // Icons name id (32 bytes per name id)
  3685      // foreach (icon)
  3686      // {
  3687      //   12+32*i  | 32   | char       | Icon NameId
  3688      // }
  3689  
  3690      // Icons data: One bit per pixel, stored as unsigned int array (depends on icon size)
  3691      // S*S pixels/32bit per unsigned int = K unsigned int per icon
  3692      // foreach (icon)
  3693      // {
  3694      //   ...   | K       | unsigned int | Icon Data
  3695      // }
  3696  
  3697      FILE *rgiFile = fopen(fileName, "rb");
  3698  
  3699      char **guiIconsName = NULL;
  3700  
  3701      if (rgiFile != NULL)
  3702      {
  3703          char signature[5] = { 0 };
  3704          short version = 0;
  3705          short reserved = 0;
  3706          short iconCount = 0;
  3707          short iconSize = 0;
  3708  
  3709          fread(signature, 1, 4, rgiFile);
  3710          fread(&version, 1, sizeof(short), rgiFile);
  3711          fread(&reserved, 1, sizeof(short), rgiFile);
  3712          fread(&iconCount, 1, sizeof(short), rgiFile);
  3713          fread(&iconSize, 1, sizeof(short), rgiFile);
  3714  
  3715          if ((signature[0] == 'r') &&
  3716              (signature[1] == 'G') &&
  3717              (signature[2] == 'I') &&
  3718              (signature[3] == ' '))
  3719          {
  3720              if (loadIconsName)
  3721              {
  3722                  guiIconsName = (char **)RAYGUI_MALLOC(iconCount*sizeof(char **));
  3723                  for (int i = 0; i < iconCount; i++)
  3724                  {
  3725                      guiIconsName[i] = (char *)RAYGUI_MALLOC(RAYGUI_ICON_MAX_NAME_LENGTH);
  3726                      fread(guiIconsName[i], RAYGUI_ICON_MAX_NAME_LENGTH, 1, rgiFile);
  3727                  }
  3728              }
  3729              else fseek(rgiFile, iconCount*RAYGUI_ICON_MAX_NAME_LENGTH, SEEK_CUR);
  3730  
  3731              // Read icons data directly over internal icons array
  3732              fread(guiIconsPtr, iconCount*(iconSize*iconSize/32), sizeof(unsigned int), rgiFile);
  3733          }
  3734  
  3735          fclose(rgiFile);
  3736      }
  3737  
  3738      return guiIconsName;
  3739  }
  3740  
  3741  // Draw selected icon using rectangles pixel-by-pixel
  3742  void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color)
  3743  {
  3744      #define BIT_CHECK(a,b) ((a) & (1u<<(b)))
  3745  
  3746      for (int i = 0, y = 0; i < RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32; i++)
  3747      {
  3748          for (int k = 0; k < 32; k++)
  3749          {
  3750              if (BIT_CHECK(guiIconsPtr[iconId*RAYGUI_ICON_DATA_ELEMENTS + i], k))
  3751              {
  3752              #if !defined(RAYGUI_STANDALONE)
  3753                  DrawRectangle(posX + (k%RAYGUI_ICON_SIZE)*pixelSize, posY + y*pixelSize, pixelSize, pixelSize, color);
  3754              #endif
  3755              }
  3756  
  3757              if ((k == 15) || (k == 31)) y++;
  3758          }
  3759      }
  3760  }
  3761  #endif      // !RAYGUI_NO_ICONS
  3762  
  3763  //----------------------------------------------------------------------------------
  3764  // Module specific Functions Definition
  3765  //----------------------------------------------------------------------------------
  3766  // Gui get text width considering icon
  3767  static int GetTextWidth(const char *text)
  3768  {
  3769      #if !defined(ICON_TEXT_PADDING)
  3770          #define ICON_TEXT_PADDING   4
  3771      #endif
  3772  
  3773      Vector2 textSize = { 0 };
  3774      int textIconOffset = 0;
  3775  
  3776      if ((text != NULL) && (text[0] != '\0'))
  3777      {
  3778          if (text[0] == '#')
  3779          {
  3780              for (int i = 1; (text[i] != '\0') && (i < 5); i++)
  3781              {
  3782                  if (text[i] == '#')
  3783                  {
  3784                      textIconOffset = i;
  3785                      break;
  3786                  }
  3787              }
  3788          }
  3789  
  3790          text += textIconOffset;
  3791  
  3792          // Make sure guiFont is set, GuiGetStyle() initializes it lazynessly
  3793          float fontSize = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  3794  
  3795          // Custom MeasureText() implementation
  3796          if ((guiFont.texture.id > 0) && (text != NULL))
  3797          {
  3798              // Get size in bytes of text, considering end of line and line break
  3799              int size = 0;
  3800              for (int i = 0; i < MAX_LINE_BUFFER_SIZE; i++)
  3801              {
  3802                  if ((text[i] != '\0') && (text[i] != '\n')) size++;
  3803                  else break;
  3804              }
  3805  
  3806              float scaleFactor = fontSize/(float)guiFont.baseSize;
  3807              textSize.y = (float)guiFont.baseSize*scaleFactor;
  3808              float glyphWidth = 0.0f;
  3809  
  3810              for (int i = 0, codepointSize = 0; i < size; i += codepointSize)
  3811              {
  3812                  int codepoint = GetCodepointNext(&text[i], &codepointSize);
  3813                  int codepointIndex = GetGlyphIndex(guiFont, codepoint);
  3814  
  3815                  if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
  3816                  else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor + GuiGetStyle(DEFAULT, TEXT_SPACING));
  3817  
  3818                  textSize.x += glyphWidth;
  3819              }
  3820          }
  3821  
  3822          if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE - ICON_TEXT_PADDING);
  3823      }
  3824  
  3825      return (int)textSize.x;
  3826  }
  3827  
  3828  // Get text bounds considering control bounds
  3829  static Rectangle GetTextBounds(int control, Rectangle bounds)
  3830  {
  3831      Rectangle textBounds = bounds;
  3832  
  3833      textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH);
  3834      textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH);
  3835      textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING);
  3836      textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH);
  3837  
  3838      // Consider TEXT_PADDING properly, depends on control type and TEXT_ALIGNMENT
  3839      switch (control)
  3840      {
  3841          case COMBOBOX: bounds.width -= (GuiGetStyle(control, COMBO_BUTTON_WIDTH) + GuiGetStyle(control, COMBO_BUTTON_SPACING)); break;
  3842          //case VALUEBOX: break;   // NOTE: ValueBox text value always centered, text padding applies to label
  3843          default:
  3844          {
  3845              if (GuiGetStyle(control, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) textBounds.x -= GuiGetStyle(control, TEXT_PADDING);
  3846              else textBounds.x += GuiGetStyle(control, TEXT_PADDING);
  3847              textBounds.width -= 2 * GuiGetStyle(control, TEXT_PADDING);
  3848          }
  3849          break;
  3850      }
  3851  
  3852      // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW (scrollbar?)
  3853      // More special cases (label on side): CHECKBOX, SLIDER, VALUEBOX, SPINNER
  3854  
  3855      return textBounds;
  3856  }
  3857  
  3858  // Get text icon if provided and move text cursor
  3859  // NOTE: We support up to 999 values for iconId
  3860  static const char *GetTextIcon(const char *text, int *iconId)
  3861  {
  3862  #if !defined(RAYGUI_NO_ICONS)
  3863      *iconId = -1;
  3864      if (text[0] == '#')     // Maybe we have an icon!
  3865      {
  3866          char iconValue[4] = { 0 };  // Maximum length for icon value: 3 digits + '\0'
  3867  
  3868          int pos = 1;
  3869          while ((pos < 4) && (text[pos] >= '0') && (text[pos] <= '9'))
  3870          {
  3871              iconValue[pos - 1] = text[pos];
  3872              pos++;
  3873          }
  3874  
  3875          if (text[pos] == '#')
  3876          {
  3877              *iconId = TextToInteger(iconValue);
  3878  
  3879              // Move text pointer after icon
  3880              // WARNING: If only icon provided, it could point to EOL character: '\0'
  3881              if (*iconId >= 0) text += (pos + 1);
  3882          }
  3883      }
  3884  #endif
  3885  
  3886      return text;
  3887  }
  3888  
  3889  // Get text divided into lines (by line-breaks '\n')
  3890  const char **GetTextLines(const char *text, int *count)
  3891  {
  3892      #define RAYGUI_MAX_TEXT_LINES   128
  3893  
  3894      static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 };
  3895      for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL;    // Init NULL pointers to substrings
  3896  
  3897      int textSize = (int)strlen(text);
  3898  
  3899      lines[0] = text;
  3900      int len = 0;
  3901      *count = 1;
  3902      int lineSize = 0;   // Stores current line size, not returned
  3903  
  3904      for (int i = 0, k = 0; (i < textSize) && (*count < RAYGUI_MAX_TEXT_LINES); i++)
  3905      {
  3906          if (text[i] == '\n')
  3907          {
  3908              lineSize = len;
  3909              k++;
  3910              lines[k] = &text[i + 1];     // WARNING: next value is valid?
  3911              len = 0;
  3912              *count += 1;
  3913          }
  3914          else len++;
  3915      }
  3916  
  3917      //lines[*count - 1].size = len;
  3918  
  3919      return lines;
  3920  }
  3921  
  3922  // Gui draw text using default font
  3923  static void GuiDrawText(const char *text, Rectangle bounds, int alignment, Color tint)
  3924  {
  3925      #define TEXT_VALIGN_PIXEL_OFFSET(h)  ((int)h%2)     // Vertical alignment for pixel perfect
  3926  
  3927      #if !defined(ICON_TEXT_PADDING)
  3928          #define ICON_TEXT_PADDING   4
  3929      #endif
  3930  
  3931      // We process the text lines one by one
  3932      if ((text != NULL) && (text[0] != '\0'))
  3933      {
  3934          // Get text lines ('\n' delimiter) to process lines individually
  3935          // NOTE: We can't use GuiTextSplit() because it can be already use before calling
  3936          // GuiDrawText() and static buffer would be overriden :(
  3937          int lineCount = 0;
  3938          const char **lines = GetTextLines(text, &lineCount);
  3939  
  3940          //Rectangle textBounds = GetTextBounds(LABEL, bounds);
  3941          float totalHeight = (float)(lineCount*GuiGetStyle(DEFAULT, TEXT_SIZE) + (lineCount - 1)*GuiGetStyle(DEFAULT, TEXT_SIZE)/2);
  3942          float posOffsetY = 0;
  3943  
  3944          for (int i = 0; i < lineCount; i++)
  3945          {
  3946              int iconId = 0;
  3947              lines[i] = GetTextIcon(lines[i], &iconId);      // Check text for icon and move cursor
  3948  
  3949              // Get text position depending on alignment and iconId
  3950              //---------------------------------------------------------------------------------
  3951              Vector2 position = { bounds.x, bounds.y };
  3952  
  3953              // TODO: We get text size after icon has been processed
  3954              // WARNING: GetTextWidth() also processes text icon to get width! -> Really needed?
  3955              int textSizeX = GetTextWidth(lines[i]);
  3956  
  3957              // If text requires an icon, add size to measure
  3958              if (iconId >= 0)
  3959              {
  3960                  textSizeX += RAYGUI_ICON_SIZE*guiIconScale;
  3961  
  3962                  // WARNING: If only icon provided, text could be pointing to EOF character: '\0'
  3963                  if ((lines[i] != NULL) && (lines[i][0] != '\0')) textSizeX += ICON_TEXT_PADDING;
  3964              }
  3965  
  3966              // Check guiTextAlign global variables
  3967              switch (alignment)
  3968              {
  3969                  case TEXT_ALIGN_LEFT:
  3970                  {
  3971                      position.x = bounds.x;
  3972                      position.y = bounds.y + posOffsetY + bounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(bounds.height);
  3973                  } break;
  3974                  case TEXT_ALIGN_CENTER:
  3975                  {
  3976                      position.x = bounds.x +  bounds.width/2 - textSizeX/2;
  3977                      position.y = bounds.y + posOffsetY + bounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(bounds.height);
  3978                  } break;
  3979                  case TEXT_ALIGN_RIGHT:
  3980                  {
  3981                      position.x = bounds.x + bounds.width - textSizeX;
  3982                      position.y = bounds.y + posOffsetY + bounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(bounds.height);
  3983                  } break;
  3984                  default: break;
  3985              }
  3986  
  3987              // NOTE: Make sure we get pixel-perfect coordinates,
  3988              // In case of decimals we got weird text positioning
  3989              position.x = (float)((int)position.x);
  3990              position.y = (float)((int)position.y);
  3991              //---------------------------------------------------------------------------------
  3992  
  3993              // Draw text (with icon if available)
  3994              //---------------------------------------------------------------------------------
  3995  #if !defined(RAYGUI_NO_ICONS)
  3996              if (iconId >= 0)
  3997              {
  3998                  // NOTE: We consider icon height, probably different than text size
  3999                  GuiDrawIcon(iconId, (int)position.x, (int)(bounds.y + bounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(bounds.height)), guiIconScale, tint);
  4000                  position.x += (RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);
  4001              }
  4002  #endif
  4003              //DrawTextEx(guiFont, text, position, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING), tint);
  4004  
  4005              // Get size in bytes of text, 
  4006              // considering end of line and line break
  4007              int size = 0;
  4008              for (int c = 0; (lines[i][c] != '\0') && (lines[i][c] != '\n'); c++, size++){ }
  4009              float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize;
  4010  
  4011              int textOffsetY = 0;
  4012              float textOffsetX = 0.0f;
  4013              for (int c = 0, codepointSize = 0; c < size; c += codepointSize)
  4014              {
  4015                  int codepoint = GetCodepointNext(&lines[i][c], &codepointSize);
  4016                  int index = GetGlyphIndex(guiFont, codepoint);
  4017  
  4018                  // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
  4019                  // but we need to draw all of the bad bytes using the '?' symbol moving one byte
  4020                  if (codepoint == 0x3f) codepointSize = 1;
  4021  
  4022                  if (codepoint == '\n') break;   // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint
  4023                  else
  4024                  {
  4025                      if ((codepoint != ' ') && (codepoint != '\t'))
  4026                      {
  4027                          // TODO: Draw only required text glyphs fitting the bounds.width, '...' can be appended at the end of the text
  4028                          if (textOffsetX < bounds.width)
  4029                          {
  4030                              DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ position.x + textOffsetX, position.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), tint);
  4031                          }
  4032                      }
  4033  
  4034                      if (guiFont.glyphs[index].advanceX == 0) textOffsetX += ((float)guiFont.recs[index].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
  4035                      else textOffsetX += ((float)guiFont.glyphs[index].advanceX*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
  4036                  }
  4037              }
  4038  
  4039              posOffsetY += (float)GuiGetStyle(DEFAULT, TEXT_SIZE)*1.5f;    // TODO: GuiGetStyle(DEFAULT, TEXT_LINE_SPACING)?
  4040              //---------------------------------------------------------------------------------
  4041          }
  4042      }
  4043  }
  4044  
  4045  // Gui draw rectangle using default raygui plain style with borders
  4046  static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color)
  4047  {
  4048      if (color.a > 0)
  4049      {
  4050          // Draw rectangle filled with color
  4051          DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, color);
  4052      }
  4053  
  4054      if (borderWidth > 0)
  4055      {
  4056          // Draw rectangle border lines with color
  4057          DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, borderWidth, borderColor);
  4058          DrawRectangle((int)rec.x, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, borderColor);
  4059          DrawRectangle((int)rec.x + (int)rec.width - borderWidth, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, borderColor);
  4060          DrawRectangle((int)rec.x, (int)rec.y + (int)rec.height - borderWidth, (int)rec.width, borderWidth, borderColor);
  4061      }
  4062  }
  4063  
  4064  // Split controls text into multiple strings
  4065  // Also check for multiple columns (required by GuiToggleGroup())
  4066  static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow)
  4067  {
  4068      // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
  4069      // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
  4070      // all used memory is static... it has some limitations:
  4071      //      1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS
  4072      //      2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE
  4073      // NOTE: Those definitions could be externally provided if required
  4074  
  4075      // WARNING: HACK: TODO: Review!
  4076      // textRow is an externally provided array of integers that stores row number for every splitted string
  4077  
  4078      #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS)
  4079          #define RAYGUI_TEXTSPLIT_MAX_ITEMS          128
  4080      #endif
  4081      #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE)
  4082          #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE     1024
  4083      #endif
  4084  
  4085      static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL };   // String pointers array (points to buffer data)
  4086      static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 };         // Buffer data (text input copy with '\0' added)
  4087      memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE);
  4088  
  4089      result[0] = buffer;
  4090      int counter = 1;
  4091  
  4092      if (textRow != NULL) textRow[0] = 0;
  4093  
  4094      // Count how many substrings we have on text and point to every one
  4095      for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++)
  4096      {
  4097          buffer[i] = text[i];
  4098          if (buffer[i] == '\0') break;
  4099          else if ((buffer[i] == delimiter) || (buffer[i] == '\n'))
  4100          {
  4101              result[counter] = buffer + i + 1;
  4102  
  4103              if (textRow != NULL)
  4104              {
  4105                  if (buffer[i] == '\n') textRow[counter] = textRow[counter - 1] + 1;
  4106                  else textRow[counter] = textRow[counter - 1];
  4107              }
  4108  
  4109              buffer[i] = '\0';   // Set an end of string at this point
  4110  
  4111              counter++;
  4112              if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
  4113          }
  4114      }
  4115  
  4116      *count = counter;
  4117  
  4118      return result;
  4119  }
  4120  
  4121  // Convert color data from RGB to HSV
  4122  // NOTE: Color data should be passed normalized
  4123  static Vector3 ConvertRGBtoHSV(Vector3 rgb)
  4124  {
  4125      Vector3 hsv = { 0 };
  4126      float min = 0.0f;
  4127      float max = 0.0f;
  4128      float delta = 0.0f;
  4129  
  4130      min = (rgb.x < rgb.y)? rgb.x : rgb.y;
  4131      min = (min < rgb.z)? min  : rgb.z;
  4132  
  4133      max = (rgb.x > rgb.y)? rgb.x : rgb.y;
  4134      max = (max > rgb.z)? max  : rgb.z;
  4135  
  4136      hsv.z = max;            // Value
  4137      delta = max - min;
  4138  
  4139      if (delta < 0.00001f)
  4140      {
  4141          hsv.y = 0.0f;
  4142          hsv.x = 0.0f;           // Undefined, maybe NAN?
  4143          return hsv;
  4144      }
  4145  
  4146      if (max > 0.0f)
  4147      {
  4148          // NOTE: If max is 0, this divide would cause a crash
  4149          hsv.y = (delta/max);    // Saturation
  4150      }
  4151      else
  4152      {
  4153          // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
  4154          hsv.y = 0.0f;
  4155          hsv.x = 0.0f;           // Undefined, maybe NAN?
  4156          return hsv;
  4157      }
  4158  
  4159      // NOTE: Comparing float values could not work properly
  4160      if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta;    // Between yellow & magenta
  4161      else
  4162      {
  4163          if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta;  // Between cyan & yellow
  4164          else hsv.x = 4.0f + (rgb.x - rgb.y)/delta;      // Between magenta & cyan
  4165      }
  4166  
  4167      hsv.x *= 60.0f;     // Convert to degrees
  4168  
  4169      if (hsv.x < 0.0f) hsv.x += 360.0f;
  4170  
  4171      return hsv;
  4172  }
  4173  
  4174  // Convert color data from HSV to RGB
  4175  // NOTE: Color data should be passed normalized
  4176  static Vector3 ConvertHSVtoRGB(Vector3 hsv)
  4177  {
  4178      Vector3 rgb = { 0 };
  4179      float hh = 0.0f, p = 0.0f, q = 0.0f, t = 0.0f, ff = 0.0f;
  4180      long i = 0;
  4181  
  4182      // NOTE: Comparing float values could not work properly
  4183      if (hsv.y <= 0.0f)
  4184      {
  4185          rgb.x = hsv.z;
  4186          rgb.y = hsv.z;
  4187          rgb.z = hsv.z;
  4188          return rgb;
  4189      }
  4190  
  4191      hh = hsv.x;
  4192      if (hh >= 360.0f) hh = 0.0f;
  4193      hh /= 60.0f;
  4194  
  4195      i = (long)hh;
  4196      ff = hh - i;
  4197      p = hsv.z*(1.0f - hsv.y);
  4198      q = hsv.z*(1.0f - (hsv.y*ff));
  4199      t = hsv.z*(1.0f - (hsv.y*(1.0f - ff)));
  4200  
  4201      switch (i)
  4202      {
  4203          case 0:
  4204          {
  4205              rgb.x = hsv.z;
  4206              rgb.y = t;
  4207              rgb.z = p;
  4208          } break;
  4209          case 1:
  4210          {
  4211              rgb.x = q;
  4212              rgb.y = hsv.z;
  4213              rgb.z = p;
  4214          } break;
  4215          case 2:
  4216          {
  4217              rgb.x = p;
  4218              rgb.y = hsv.z;
  4219              rgb.z = t;
  4220          } break;
  4221          case 3:
  4222          {
  4223              rgb.x = p;
  4224              rgb.y = q;
  4225              rgb.z = hsv.z;
  4226          } break;
  4227          case 4:
  4228          {
  4229              rgb.x = t;
  4230              rgb.y = p;
  4231              rgb.z = hsv.z;
  4232          } break;
  4233          case 5:
  4234          default:
  4235          {
  4236              rgb.x = hsv.z;
  4237              rgb.y = p;
  4238              rgb.z = q;
  4239          } break;
  4240      }
  4241  
  4242      return rgb;
  4243  }
  4244  
  4245  // Scroll bar control (used by GuiScrollPanel())
  4246  static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
  4247  {
  4248      GuiState state = guiState;
  4249  
  4250      // Is the scrollbar horizontal or vertical?
  4251      bool isVertical = (bounds.width > bounds.height)? false : true;
  4252  
  4253      // The size (width or height depending on scrollbar type) of the spinner buttons
  4254      const int spinnerSize = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)? 
  4255          (isVertical? (int)bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) : 
  4256          (int)bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)) : 0;
  4257  
  4258      // Arrow buttons [<] [>] [∧] [∨]
  4259      Rectangle arrowUpLeft = { 0 };
  4260      Rectangle arrowDownRight = { 0 };
  4261  
  4262      // Actual area of the scrollbar excluding the arrow buttons
  4263      Rectangle scrollbar = { 0 };
  4264  
  4265      // Slider bar that moves     --[///]-----
  4266      Rectangle slider = { 0 };
  4267  
  4268      // Normalize value
  4269      if (value > maxValue) value = maxValue;
  4270      if (value < minValue) value = minValue;
  4271  
  4272      const int range = maxValue - minValue;
  4273      int sliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
  4274  
  4275      // Calculate rectangles for all of the components
  4276      arrowUpLeft = RAYGUI_CLITERAL(Rectangle){ 
  4277          (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), 
  4278          (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), 
  4279          (float)spinnerSize, (float)spinnerSize };
  4280  
  4281      if (isVertical)
  4282      {
  4283          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 };
  4284          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) };
  4285          sliderSize = (sliderSize >= scrollbar.height)? ((int)scrollbar.height - 2) : sliderSize;     // Make sure the slider won't get outside of the scrollbar
  4286          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 };
  4287      }
  4288      else    // horizontal
  4289      {
  4290          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 };
  4291          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)) };
  4292          sliderSize = (sliderSize >= scrollbar.width)? ((int)scrollbar.width - 2) : sliderSize;       // Make sure the slider won't get outside of the scrollbar
  4293          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)) };
  4294      }
  4295  
  4296      // Update control
  4297      //--------------------------------------------------------------------
  4298      if ((state != STATE_DISABLED) && !guiLocked)
  4299      {
  4300          Vector2 mousePoint = GetMousePosition();
  4301  
  4302          if (CheckCollisionPointRec(mousePoint, bounds))
  4303          {
  4304              state = STATE_FOCUSED;
  4305  
  4306              // Handle mouse wheel
  4307              int wheel = (int)GetMouseWheelMove();
  4308              if (wheel != 0) value += wheel;
  4309  
  4310              if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
  4311              {
  4312                  if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= range/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  4313                  else if (CheckCollisionPointRec(mousePoint, arrowDownRight)) value += range/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
  4314  
  4315                  state = STATE_PRESSED;
  4316              }
  4317              else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  4318              {
  4319                  if (!isVertical)
  4320                  {
  4321                      Rectangle scrollArea = { arrowUpLeft.x + arrowUpLeft.width, arrowUpLeft.y, scrollbar.width, bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) };
  4322                      if (CheckCollisionPointRec(mousePoint, scrollArea)) value = (int)(((float)(mousePoint.x - scrollArea.x - slider.width/2)*range)/(scrollArea.width - slider.width) + minValue);
  4323                  }
  4324                  else
  4325                  {
  4326                      Rectangle scrollArea = { arrowUpLeft.x, arrowUpLeft.y+arrowUpLeft.height, bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH),  scrollbar.height };
  4327                      if (CheckCollisionPointRec(mousePoint, scrollArea)) value = (int)(((float)(mousePoint.y - scrollArea.y - slider.height/2)*range)/(scrollArea.height - slider.height) + minValue);
  4328                  }
  4329              }
  4330          }
  4331  
  4332          // Normalize value
  4333          if (value > maxValue) value = maxValue;
  4334          if (value < minValue) value = minValue;
  4335      }
  4336      //--------------------------------------------------------------------
  4337  
  4338      // Draw control
  4339      //--------------------------------------------------------------------
  4340      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
  4341  
  4342      GuiDrawRectangle(scrollbar, 0, BLANK, Fade(GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL)), guiAlpha));     // Draw the scrollbar active area background
  4343      GuiDrawRectangle(slider, 0, BLANK, Fade(GetColor(GuiGetStyle(SLIDER, BORDER + state*3)), guiAlpha));         // Draw the slider bar
  4344  
  4345      // Draw arrows (using icon if available)
  4346      if (GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE))
  4347      {
  4348  #if defined(RAYGUI_NO_ICONS)
  4349          GuiDrawText(isVertical? "^" : "<", 
  4350              RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
  4351              TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha));
  4352          GuiDrawText(isVertical? "v" : ">", 
  4353              RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
  4354              TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha));
  4355  #else
  4356          GuiDrawText(isVertical? "#121#" : "#118#", 
  4357              RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
  4358              TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3)), guiAlpha));   // ICON_ARROW_UP_FILL / ICON_ARROW_LEFT_FILL
  4359          GuiDrawText(isVertical? "#120#" : "#119#", 
  4360              RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
  4361              TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3)), guiAlpha));   // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL
  4362  #endif
  4363      }
  4364      //--------------------------------------------------------------------
  4365  
  4366      return value;
  4367  }
  4368  
  4369  #if defined(RAYGUI_STANDALONE)
  4370  // Returns a Color struct from hexadecimal value
  4371  static Color GetColor(int hexValue)
  4372  {
  4373      Color color;
  4374  
  4375      color.r = (unsigned char)(hexValue >> 24) & 0xFF;
  4376      color.g = (unsigned char)(hexValue >> 16) & 0xFF;
  4377      color.b = (unsigned char)(hexValue >> 8) & 0xFF;
  4378      color.a = (unsigned char)hexValue & 0xFF;
  4379  
  4380      return color;
  4381  }
  4382  
  4383  // Returns hexadecimal value for a Color
  4384  static int ColorToInt(Color color)
  4385  {
  4386      return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
  4387  }
  4388  
  4389  // Check if point is inside rectangle
  4390  static bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
  4391  {
  4392      bool collision = false;
  4393  
  4394      if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) &&
  4395          (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
  4396  
  4397      return collision;
  4398  }
  4399  
  4400  // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
  4401  static Color Fade(Color color, float alpha)
  4402  {
  4403      if (alpha < 0.0f) alpha = 0.0f;
  4404      else if (alpha > 1.0f) alpha = 1.0f;
  4405  
  4406      Color result = { color.r, color.g, color.b, (unsigned char)(255.0f*alpha) };
  4407  
  4408      return result;
  4409  }
  4410  
  4411  // Formatting of text with variables to 'embed'
  4412  static const char *TextFormat(const char *text, ...)
  4413  {
  4414      #if !defined(RAYGUI_TEXTFORMAT_MAX_SIZE)
  4415          #define RAYGUI_TEXTFORMAT_MAX_SIZE   256
  4416      #endif
  4417  
  4418      static char buffer[RAYGUI_TEXTFORMAT_MAX_SIZE];
  4419  
  4420      va_list args;
  4421      va_start(args, text);
  4422      vsprintf(buffer, text, args);
  4423      va_end(args);
  4424  
  4425      return buffer;
  4426  }
  4427  
  4428  // Draw rectangle with vertical gradient fill color
  4429  // NOTE: This function is only used by GuiColorPicker()
  4430  static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
  4431  {
  4432      Rectangle bounds = { (float)posX, (float)posY, (float)width, (float)height };
  4433      DrawRectangleGradientEx(bounds, color1, color2, color2, color1);
  4434  }
  4435  
  4436  // Split string into multiple strings
  4437  const char **TextSplit(const char *text, char delimiter, int *count)
  4438  {
  4439      // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
  4440      // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
  4441      // all used memory is static... it has some limitations:
  4442      //      1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS
  4443      //      2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE
  4444  
  4445      #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS)
  4446          #define RAYGUI_TEXTSPLIT_MAX_ITEMS        128
  4447      #endif
  4448      #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE)
  4449          #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE      1024
  4450      #endif
  4451  
  4452      static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL };
  4453      static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 };
  4454      memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE);
  4455  
  4456      result[0] = buffer;
  4457      int counter = 0;
  4458  
  4459      if (text != NULL)
  4460      {
  4461          counter = 1;
  4462  
  4463          // Count how many substrings we have on text and point to every one
  4464          for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++)
  4465          {
  4466              buffer[i] = text[i];
  4467              if (buffer[i] == '\0') break;
  4468              else if (buffer[i] == delimiter)
  4469              {
  4470                  buffer[i] = '\0';   // Set an end of string at this point
  4471                  result[counter] = buffer + i + 1;
  4472                  counter++;
  4473  
  4474                  if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
  4475              }
  4476          }
  4477      }
  4478  
  4479      *count = counter;
  4480      return result;
  4481  }
  4482  
  4483  // Get integer value from text
  4484  // NOTE: This function replaces atoi() [stdlib.h]
  4485  static int TextToInteger(const char *text)
  4486  {
  4487      int value = 0;
  4488      int sign = 1;
  4489  
  4490      if ((text[0] == '+') || (text[0] == '-'))
  4491      {
  4492          if (text[0] == '-') sign = -1;
  4493          text++;
  4494      }
  4495  
  4496      for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); ++i) value = value*10 + (int)(text[i] - '0');
  4497  
  4498      return value*sign;
  4499  }
  4500  
  4501  // Encode codepoint into UTF-8 text (char array size returned as parameter)
  4502  static const char *CodepointToUTF8(int codepoint, int *byteSize)
  4503  {
  4504      static char utf8[6] = { 0 };
  4505      int size = 0;
  4506  
  4507      if (codepoint <= 0x7f)
  4508      {
  4509          utf8[0] = (char)codepoint;
  4510          size = 1;
  4511      }
  4512      else if (codepoint <= 0x7ff)
  4513      {
  4514          utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0);
  4515          utf8[1] = (char)((codepoint & 0x3f) | 0x80);
  4516          size = 2;
  4517      }
  4518      else if (codepoint <= 0xffff)
  4519      {
  4520          utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0);
  4521          utf8[1] = (char)(((codepoint >>  6) & 0x3f) | 0x80);
  4522          utf8[2] = (char)((codepoint & 0x3f) | 0x80);
  4523          size = 3;
  4524      }
  4525      else if (codepoint <= 0x10ffff)
  4526      {
  4527          utf8[0] = (char)(((codepoint >> 18) & 0x07) | 0xf0);
  4528          utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80);
  4529          utf8[2] = (char)(((codepoint >>  6) & 0x3f) | 0x80);
  4530          utf8[3] = (char)((codepoint & 0x3f) | 0x80);
  4531          size = 4;
  4532      }
  4533  
  4534      *byteSize = size;
  4535  
  4536      return utf8;
  4537  }
  4538  
  4539  // Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found
  4540  // When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned
  4541  // Total number of bytes processed are returned as a parameter
  4542  // NOTE: the standard says U+FFFD should be returned in case of errors
  4543  // but that character is not supported by the default font in raylib
  4544  static int GetCodepointNext(const char *text, int *codepointSize)
  4545  {
  4546      const char *ptr = text;
  4547      int codepoint = 0x3f;       // Codepoint (defaults to '?')
  4548      *codepointSize = 0;
  4549  
  4550      // Get current codepoint and bytes processed
  4551      if (0xf0 == (0xf8 & ptr[0]))
  4552      {
  4553          // 4 byte UTF-8 codepoint
  4554          codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
  4555          *codepointSize = 4;
  4556      }
  4557      else if (0xe0 == (0xf0 & ptr[0]))
  4558      {
  4559          // 3 byte UTF-8 codepoint */
  4560          codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
  4561          *codepointSize = 3;
  4562      }
  4563      else if (0xc0 == (0xe0 & ptr[0]))
  4564      {
  4565          // 2 byte UTF-8 codepoint
  4566          codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
  4567          *codepointSize = 2;
  4568      }
  4569      else
  4570      {
  4571          // 1 byte UTF-8 codepoint
  4572          codepoint = ptr[0];
  4573          *codepointSize = 1;
  4574      }
  4575  
  4576      return codepoint;
  4577  }
  4578  #endif      // RAYGUI_STANDALONE
  4579  
  4580  #endif      // RAYGUI_IMPLEMENTATION